commit d0c00d882d8829097c1d9347180389c17224134c Author: stack Date: Tue Jan 20 10:49:23 2015 -0800 Add in htraced test start/stop diff --git a/htrace-htraced/src/test/java/org/apache/htrace/util/DataDir.java b/htrace-htraced/src/test/java/org/apache/htrace/util/DataDir.java new file mode 100644 index 0000000..dcc8182 --- /dev/null +++ b/htrace-htraced/src/test/java/org/apache/htrace/util/DataDir.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.htrace.util; + +import java.io.File; +import java.io.IOException; +import java.util.UUID; + +/** + * Small util for making a data directory for tests to use when running tests. We put it up at + * target/test-data/UUID. Create an instance of this class per unit test run and it will take + * care of setting up the dirs for you. Pass what is returned here as location from which to + * have daemons and tests dump data. + * TODO: Add close on exit. + */ +public class DataDir { + private File baseTestDir = null; + private File testDir = null; + + /** + * System property key to get base test directory value + */ + public static final String TEST_BASE_DIRECTORY_KEY = "test.data.base.dir"; + + /** + * Default base directory for test output. + */ + public static final String TEST_BASE_DIRECTORY_DEFAULT = "target"; + + public static final String TEST_BASE_DIRECTORY_NAME = "test-data"; + + /** + * @return Where to write test data on local filesystem; usually + * {@link #TEST_BASE_DIRECTORY_DEFAULT} + * Should not be used directly by the unit tests, hence its's private. + * Unit test will use a subdirectory of this directory. + * @see #setupDataTestDir() + */ + private synchronized File getBaseTestDir() { + if (this.baseTestDir != null) return this.baseTestDir; + String testHome = System.getProperty(TEST_BASE_DIRECTORY_KEY, TEST_BASE_DIRECTORY_DEFAULT); + this.baseTestDir = new File(testHome, TEST_BASE_DIRECTORY_NAME); + return this.baseTestDir; + } + + /** + * @return Test dir for this instance of TestDir. + * @throws IOException + */ + public synchronized File getDataDir() throws IOException { + if (this.testDir != null) return this.testDir; + this.testDir = new File(getBaseTestDir(), UUID.randomUUID().toString()); + if (!this.testDir.exists()) { + if (!this.testDir.mkdirs()) throw new IOException("Failed mkdirs for " + this.testDir); + } + return this.testDir; + } + + /** + * Fragile. Ugly. Presumes paths. Best we can do for now until htraced comes local to this module + * and is moved out of src dir. + * @param dataDir A datadir gotten from {@link #getDataDir()} + * @return Top-level of the checkout. + */ + public static File getTopLevelOfCheckout(final File dataDir) { + // Need absolute else we run out of road when dir is relative to this module. + File absolute = dataDir.getAbsoluteFile(); + // Check we are where we think we are. + File testDataDir = absolute.getParentFile(); + if (!testDataDir.getName().equals(TEST_BASE_DIRECTORY_NAME)) { + throw new IllegalArgumentException(dataDir.toString()); + } + // Do another check. + File targetDir = testDataDir.getParentFile(); + if (!targetDir.getName().equals(TEST_BASE_DIRECTORY_DEFAULT)) { + throw new IllegalArgumentException(dataDir.toString()); + } + // Back up last two dirs out of the htrace-htraced dir. + return targetDir.getParentFile().getParentFile(); + } +} \ No newline at end of file diff --git a/htrace-htraced/src/test/java/org/apache/htrace/util/HTracedProcess.java b/htrace-htraced/src/test/java/org/apache/htrace/util/HTracedProcess.java new file mode 100644 index 0000000..770e442 --- /dev/null +++ b/htrace-htraced/src/test/java/org/apache/htrace/util/HTracedProcess.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.htrace.util; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ProcessBuilder.Redirect; +import java.net.URL; + +/** + * To get instance of HTraced up and running, create an instance of this class. + * Upon successful construction, htraced is running using dataDir as directory to + * host data (leveldbs and logs). + * TODO: We expect to find the htraced in a very particular place. Fragile. Will break if stuff + * moves. + * TODO: What if a port clash? How to have it come up another port then ask the process what port + * it is running on? + */ +public class HTracedProcess extends Process { + private final Process delegate; + + public HTracedProcess(final File pathToHTracedBinary, final File dataDir, final URL url) + throws IOException { + // web.address for htraced is hostname ':' port; no 'scheme' yet. + String webAddress = url.getHost() + ":" + url.getPort(); + // Pass cmdline args to htraced to it uses our test dir for data. + ProcessBuilder pb = new ProcessBuilder(pathToHTracedBinary.toString(), + "-Dweb.address=" + webAddress, + "-Ddata.store.clear=true", + "-Ddata.store.directories=" + dataDir.toString()); + pb.redirectErrorStream(true); + // Inherit STDERR/STDOUT i/o; dumps on console for now. Can add logs later. + pb.inheritIO(); + pb.directory(dataDir); + this.delegate = pb.start(); + assert pb.redirectInput() == Redirect.PIPE; + assert pb.redirectOutput().file() == dataDir; + assert this.delegate.getInputStream().read() == -1; + } + + public int hashCode() { + return delegate.hashCode(); + } + + public OutputStream getOutputStream() { + throw new UnsupportedOperationException("Unsupported until complaint; output on STDOUT"); + } + + public InputStream getInputStream() { + throw new UnsupportedOperationException("Unsupported until complaint; output on STDOUT"); + } + + public boolean equals(Object obj) { + return delegate.equals(obj); + } + + public InputStream getErrorStream() { + throw new UnsupportedOperationException("Unsupported until complaint; output on STDOUT"); + } + + public int waitFor() throws InterruptedException { + return delegate.waitFor(); + } + + public int exitValue() { + return delegate.exitValue(); + } + + public void destroy() { + delegate.destroy(); + } + + public String toString() { + return delegate.toString(); + } + + /** + * Ugly but how else to do file-math? + * @param topLevel Presumes top-level of the htrace checkout. + * @return Path to the htraced binary. + */ + public static File getPathToHTraceBinaryFromTopLevel(final File topLevel) { + return new File(new File(new File(new File(new File(topLevel, "htrace-core"), "src"), "go"), + "build"), "htraced"); + } +} \ No newline at end of file diff --git a/htrace-htraced/src/test/java/org/apache/htrace/util/TestHTracedProcess.java b/htrace-htraced/src/test/java/org/apache/htrace/util/TestHTracedProcess.java new file mode 100644 index 0000000..cb2c577 --- /dev/null +++ b/htrace-htraced/src/test/java/org/apache/htrace/util/TestHTracedProcess.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.htrace.util; + +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; + +import org.junit.Before; +import org.junit.Test; + +/** + * Test putting up an htraced and making sure it basically works. + * Makes presumption about paths; where data is relative to the htraced binary, etc., encoded + * in methods in the below. + */ +public class TestHTracedProcess { + private DataDir testDir = null; + private final int TIMEOUT = 10000; + + @Before + public void setupTest() { + this.testDir = new DataDir(); + } + + /* + * Do a basic GET of the server info from the running htraced instance. + */ + private String doGet(final URL url) throws IOException { + URLConnection connection = url.openConnection(); + connection.setConnectTimeout(TIMEOUT); + connection.setReadTimeout(TIMEOUT); + connection.connect(); + StringBuffer sb = new StringBuffer(); + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + try { + String line = null; + while ((line = reader.readLine()) != null) { + System.out.println(line); + sb.append(line); + } + } finally { + reader.close(); + } + return sb.toString(); + } + + /** + * Put up an htraced instance and do a Get against /server/info. + * @throws IOException + * @throws InterruptedException + */ + @Test (timeout=100000) + public void testStartStopHTraced() throws IOException, InterruptedException { + // TODO: Make the test port random so no classes if concurrent test runs. Anything better + // I can do here? Pass a zero and have the daemon tell me where it is successfully listening? + String restURL = "http://localhost:9096/"; + URL restServerURL = new URL(restURL); + HTracedProcess htraced = null; + File dataDir = this.testDir.getDataDir(); + File topLevel = DataDir.getTopLevelOfCheckout(dataDir); + try { + htraced = new HTracedProcess(HTracedProcess.getPathToHTraceBinaryFromTopLevel(topLevel), + dataDir, restServerURL); + String str = doGet(new URL(restServerURL + "server/info")); + // Assert we go something back. + assertTrue(str.contains("ReleaseVersion")); + // Assert that the datadir is not empty. + } finally { + if (htraced != null) htraced.destroy(); + System.out.println("ExitValue=" + htraced.exitValue()); + } + } +} \ No newline at end of file