# HG changeset patch # User Roman Kennke # Date 1361280286 -3600 # Node ID 930ef1c74e991b47cb57707fb949ecba1c0e4e1e # Parent 92588dada473775a3a35bda97f2ab055f3675988 Integeration test for WAR. Reviewed-by: neugens, jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-February/005732.html diff -r 92588dada473 -r 930ef1c74e99 common/core/src/main/java/com/redhat/thermostat/common/ApplicationInfo.java --- a/common/core/src/main/java/com/redhat/thermostat/common/ApplicationInfo.java Fri Feb 15 17:24:29 2013 -0500 +++ b/common/core/src/main/java/com/redhat/thermostat/common/ApplicationInfo.java Tue Feb 19 14:24:46 2013 +0100 @@ -77,6 +77,10 @@ return new Version(); } + public String getMavenVersion() { + return appInfo.getProperty("APP_VERSION"); + } + public String getDescription() { return t.localize(LocaleResources.APPLICATION_INFO_DESCRIPTION); } diff -r 92588dada473 -r 930ef1c74e99 common/core/src/main/resources/com/redhat/thermostat/app-info.properties --- a/common/core/src/main/resources/com/redhat/thermostat/app-info.properties Fri Feb 15 17:24:29 2013 -0500 +++ b/common/core/src/main/resources/com/redhat/thermostat/app-info.properties Tue Feb 19 14:24:46 2013 +0100 @@ -3,4 +3,4 @@ APP_EMAIL = ${thermostat.email} APP_WEBSITE = ${thermostat.url} APP_COPYRIGHT = Copyright 2012, 2013 Red Hat, Inc. - +APP_VERSION = ${project.version} diff -r 92588dada473 -r 930ef1c74e99 distribution/pom.xml --- a/distribution/pom.xml Fri Feb 15 17:24:29 2013 -0500 +++ b/distribution/pom.xml Tue Feb 19 14:24:46 2013 +0100 @@ -309,11 +309,6 @@ junit test - - net.sourceforge.expectj - expectj - test - diff -r 92588dada473 -r 930ef1c74e99 distribution/src/test/java/com/redhat/thermostat/distribution/CliTest.java --- a/distribution/src/test/java/com/redhat/thermostat/distribution/CliTest.java Fri Feb 15 17:24:29 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -/* - * Copyright 2012, 2013 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.distribution; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.IOException; - -import org.junit.Ignore; -import org.junit.Test; - -import expectj.Spawn; -import expectj.TimeoutException; - -/** - * Integration tests to exercise the basics of the thermostat command line. - */ -public class CliTest extends IntegrationTest { - - @Test - public void testExpectIsSane() throws Exception { - Spawn shell = spawnThermostat(); - - try { - shell.expect("some-random-text-that-is-not-really-possible"); - fail("should never match"); - } catch (IOException endOfStream) { - assertTrue(endOfStream.getMessage().contains("End of stream reached, no match found")); - } - shell.expectClose(); - } - - @Test - public void testSimpleInvocationPrintsHelp() throws Exception { - Spawn shell = spawnThermostat(); - shell.expectClose(); - - String stdOut = shell.getCurrentStandardOutContents(); - - assertMatchesHelpCommandList(stdOut); - - String stdErr = shell.getCurrentStandardErrContents(); - assertEquals(stdErr, ""); - } - - @Test - public void testHelpCommandInvocation() throws Exception { - Spawn shell = spawnThermostat("help"); - shell.expectClose(); - - String stdOut = shell.getCurrentStandardOutContents(); - String stdErr = shell.getCurrentStandardErrContents(); - - assertMatchesHelpCommandList(stdOut); - assertEquals(stdErr, ""); - } - - @Test - public void testHelpOnHelp() throws Exception { - Spawn shell = spawnThermostat("help", "help"); - shell.expectClose(); - - String stdOut = shell.getCurrentStandardOutContents(); - String stdErr = shell.getCurrentStandardErrContents(); - - String[] lines = stdOut.split("\n"); - String usage = lines[0]; - assertEquals("usage: thermostat help [command-name]", usage); - - assertEquals(stdErr, ""); - } - - @Test - public void testVersionArgument() throws Exception { - Spawn shell = spawnThermostat("--version"); - shell.expectClose(); - - String stdOut = shell.getCurrentStandardOutContents(); - String stdErr = shell.getCurrentStandardErrContents(); - - assertTrue(stdOut.matches("Thermostat version \\d+\\.\\d+\\.\\d+\n")); - assertEquals(stdErr, ""); - } - - @Test - public void testShell() throws Exception { - Spawn shell = spawnThermostat("shell"); - - shell.expect(SHELL_PROMPT); - shell.send("help\n"); - - shell.expect(SHELL_PROMPT); - - assertMatchesHelpCommandList(shell.getCurrentStandardOutContents()); - - shell.send("exit\n"); - - shell.expectClose(); - } - - @Test - public void testShellHelp() throws Exception { - Spawn shell = spawnThermostat("help", "shell"); - shell.expectClose(); - - String stdOut = shell.getCurrentStandardOutContents(); - - String[] lines = stdOut.split("\n"); - String usage = lines[0]; - assertTrue(usage.matches("^usage: thermostat shell$")); - String description = lines[1]; - assertTrue(description.matches("^\\s+launches the Thermostat interactive shell$")); - assertTrue(lines[2].matches("thermostat shell")); - } - - @Test - public void testShellUnrecognizedArgument() throws Exception { - Spawn shell = spawnThermostat("shell", "--foo"); - shell.expectErr("Unrecognized option: --foo"); - shell.expectClose(); - } - - @Test - public void testUnrecognizedEventsInShell() throws IOException, TimeoutException { - // test '!' events - Spawn shell = spawnThermostat("shell"); - - shell.expect(SHELL_PROMPT); - shell.send("what!?!\n"); - shell.expect(SHELL_PROMPT); - shell.send("exit\n"); - - assertTrue(shell.getCurrentStandardErrContents().contains("!?!: event not found")); - assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); - } - - @Test - public void testInvalidCommand() throws Exception { - Spawn shell = spawnThermostat("foobar", "baz"); - - // TODO should this be stderr? - shell.expect("unknown command 'foobar'"); - shell.expectClose(); - - String stdOut = shell.getCurrentStandardOutContents(); - - assertMatchesHelpCommandList(stdOut); - } - - private static void assertMatchesHelpCommandList(String actual) { - assertTrue(actual.contains("list of commands")); - assertTrue(actual.contains("help")); - assertTrue(actual.contains("agent")); - assertTrue(actual.contains("gui")); - assertTrue(actual.contains("ping")); - assertTrue(actual.contains("shell")); - } - -} - diff -r 92588dada473 -r 930ef1c74e99 distribution/src/test/java/com/redhat/thermostat/distribution/IntegrationTest.java --- a/distribution/src/test/java/com/redhat/thermostat/distribution/IntegrationTest.java Fri Feb 15 17:24:29 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -/* - * Copyright 2012, 2013 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.distribution; - -import static org.junit.Assert.assertFalse; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import com.redhat.thermostat.common.utils.StreamUtils; - -import expectj.Executor; -import expectj.ExpectJ; -import expectj.Spawn; - -/** - * Helper methods to support writing an integration test. - */ -public class IntegrationTest { - - public static final long TIMEOUT_IN_SECONDS = 30; - - public static final String SHELL_PROMPT = "Thermostat >"; - - public static String getThermostatExecutable() { - return "target/bin/thermostat"; - } - - public static String getStorageDataDirectory() { - return "target/storage/db"; - } - - public static Spawn spawnThermostat(String... args) throws IOException { - ExpectJ expect = new ExpectJ(TIMEOUT_IN_SECONDS); - StringBuilder result = new StringBuilder(getThermostatExecutable()); - if (args != null) { - for (String arg : args) { - result.append(" ").append(arg); - } - } - String toExecute = result.toString(); - //System.out.println("executing: '" + toExecute + "'"); - return expect.spawn(toExecute); - } - - public static Spawn spawn(List args) throws IOException { - ExpectJ expect = new ExpectJ(TIMEOUT_IN_SECONDS); - StringBuilder result = new StringBuilder(); - for (String arg : args) { - result.append(arg).append(" "); - } - return expect.spawn(result.substring(0, result.length() - 1)); - } - - public static Spawn spawn(Executor executor) throws IOException { - ExpectJ expect = new ExpectJ(TIMEOUT_IN_SECONDS); - return expect.spawn(executor); - } - - /** - * Kill the process and all its children, recursively. Sends SIGTERM. - */ - public static void killRecursively(Process process) throws Exception { - killRecursively(getPid(process)); - } - - private static void killRecursively(int pid) throws Exception { - List childPids = findChildPids(pid); - for (Integer childPid : childPids) { - killRecursively(childPid); - } - killProcess(pid); - } - - private static void killProcess(int processId) throws Exception { - Runtime.getRuntime().exec("kill " + processId).waitFor(); - } - - private static List findChildPids(int processId) throws IOException { - String children = new String(StreamUtils.readAll(Runtime.getRuntime().exec("ps --ppid " + processId + " -o pid=").getInputStream())); - String[] childPids = children.split("\n"); - List result = new ArrayList<>(); - for (String childPid : childPids) { - String pidString = childPid.trim(); - if (pidString.length() == 0) { - continue; - } - try { - result.add(Integer.parseInt(pidString)); - } catch (NumberFormatException nfe) { - System.err.println(nfe); - } - } - return result; - } - - private static int getPid(Process process) throws Exception { - final String UNIX_PROCESS_CLASS = "java.lang.UNIXProcess"; - if (!process.getClass().getName().equals(UNIX_PROCESS_CLASS)) { - throw new IllegalArgumentException("can only kill " + UNIX_PROCESS_CLASS + "; input is a " + process.getClass()); - } - - Class processClass = process.getClass(); - Field pidField = processClass.getDeclaredField("pid"); - pidField.setAccessible(true); - return (int) pidField.get(process); - } - - public static void deleteFilesUnder(String path) throws IOException { - String[] filesToDelete = new File(path).list(); - for (String toDelete : filesToDelete) { - if (!new File(path, toDelete).delete()) { - throw new IOException("cant delete: '" + new File(path, toDelete).toString() + "'."); - } - } - } - - public static void assertCommandIsFound(String stdOutContents, String stdErrContents) { - assertFalse(stdOutContents.contains("unknown command")); - assertFalse(stdErrContents.contains("unknown command")); - } - - public static void assertNoExceptions(String stdOutContents, String stdErrContents) { - assertFalse(stdOutContents.contains("Exception")); - assertFalse(stdErrContents.contains("Exception")); - } - -} - diff -r 92588dada473 -r 930ef1c74e99 distribution/src/test/java/com/redhat/thermostat/distribution/StorageConnectionTest.java --- a/distribution/src/test/java/com/redhat/thermostat/distribution/StorageConnectionTest.java Fri Feb 15 17:24:29 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * Copyright 2012, 2013 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.distribution; - -import java.io.IOException; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; - -import expectj.ExpectJException; -import expectj.Spawn; -import expectj.TimeoutException; - -public class StorageConnectionTest extends IntegrationTest { - - @BeforeClass - public static void setUpOnce() throws IOException, TimeoutException, ExpectJException { - Spawn storage = spawnThermostat("storage", "--start"); - storage.expect("pid:"); - storage.expectClose(); - - assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); - } - - @AfterClass - public static void tearDownOnce() throws IOException, TimeoutException, ExpectJException { - Spawn storage = spawnThermostat("storage", "--stop"); - storage.expect("server shutdown complete"); - storage.expectClose(); - - assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); - } - - @Test - public void testConnect() throws ExpectJException, TimeoutException, IOException { - Spawn shell = spawnThermostat("shell"); - - shell.expect(SHELL_PROMPT); - shell.send("connect -d mongodb://127.0.0.1:27518\n"); - shell.expect(SHELL_PROMPT); - shell.send("exit\n"); - shell.expectClose(); - - assertCommandIsFound(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); - assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); - } - - @Test - public void testDisconnectWithoutConnecting() throws ExpectJException, TimeoutException, IOException { - Spawn shell = spawnThermostat("shell"); - - shell.expect(SHELL_PROMPT); - shell.send("disconnect\n"); - shell.expect(SHELL_PROMPT); - shell.send("exit\n"); - shell.expectClose(); - - assertCommandIsFound(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); - assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); - } - - @Test - public void testConnectAndDisconnectInShell() throws IOException, TimeoutException, ExpectJException { - Spawn shell = spawnThermostat("shell"); - - shell.expect(SHELL_PROMPT); - shell.send("connect -d mongodb://127.0.0.1:27518\n"); - shell.expect(SHELL_PROMPT); - shell.send("disconnect\n"); - shell.send("exit\n"); - shell.expectClose(); - - assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); - } - - // TODO add a test to make sure connect/disconnect is not visible outside the shell -} - diff -r 92588dada473 -r 930ef1c74e99 distribution/src/test/java/com/redhat/thermostat/distribution/StorageTest.java --- a/distribution/src/test/java/com/redhat/thermostat/distribution/StorageTest.java Fri Feb 15 17:24:29 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright 2012, 2013 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.distribution; - -import java.io.IOException; - -import org.junit.Test; - -import expectj.Executor; -import expectj.Spawn; - -public class StorageTest extends IntegrationTest { - - @Test - public void startAndStopStorage() throws Exception { - Spawn storage; - - storage = spawnThermostat("storage", "--start"); - storage.expect("pid:"); - storage.expectClose(); - - assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); - - storage = spawnThermostat("storage", "--stop"); - storage.expect("server shutdown complete"); - storage.expectClose(); - - assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); - } - - @Test - public void testServiceStartAndKilling() throws Exception { - Spawn storage; - final Process[] process = new Process[1]; - - storage = spawn(new Executor() { - @Override - public Process execute() throws IOException { - ProcessBuilder builder = new ProcessBuilder(getThermostatExecutable(), "service"); - Process service = builder.start(); - process[0] = service; - return service; - } - }); - - try { - storage.expectErr("agent started"); - } - finally { - killRecursively(process[0]); - } - } - -} - diff -r 92588dada473 -r 930ef1c74e99 distribution/src/test/java/com/redhat/thermostat/distribution/VmCommandsTest.java --- a/distribution/src/test/java/com/redhat/thermostat/distribution/VmCommandsTest.java Fri Feb 15 17:24:29 2013 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* - * Copyright 2012, 2013 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * . - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.distribution; - -import static org.junit.Assert.assertEquals; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import expectj.Spawn; - -/** Integration tests for the various vm commands */ -public class VmCommandsTest extends IntegrationTest { - - @BeforeClass - public static void setUpOnce() throws IOException, InterruptedException { - String staleDataDir = getStorageDataDirectory(); - deleteFilesUnder(staleDataDir); - - Process startStorage = new ProcessBuilder(getThermostatExecutable(), "storage", "--start").start(); - startStorage.waitFor(); - - // TODO insert actual data into the database and test that - } - - @AfterClass - public static void tearDownOnce() throws InterruptedException, IOException { - Process stopStorage = new ProcessBuilder(getThermostatExecutable(), "storage", "--stop").start(); - stopStorage.waitFor(); - } - - @Test - public void testListVms() throws Exception { - Spawn vmList = commandAgainstMongo("list-vms"); - vmList.expectClose(); - - assertEquals("HOST_ID HOST VM_ID STATUS VM_NAME\n", vmList.getCurrentStandardOutContents()); - } - - @Test - public void testVmStat() throws Exception { - Spawn vmStat = commandAgainstMongo("vm-stat"); - vmStat.expectClose(); - - System.out.println(vmStat.getCurrentStandardOutContents()); - assertCommandIsFound(vmStat.getCurrentStandardOutContents(), vmStat.getCurrentStandardErrContents()); - assertNoExceptions(vmStat.getCurrentStandardOutContents(), vmStat.getCurrentStandardErrContents()); - } - - @Test - public void testVmInfo() throws Exception { - Spawn vmInfo = commandAgainstMongo("vm-info"); - vmInfo.expectClose(); - - assertNoExceptions(vmInfo.getCurrentStandardOutContents(), vmInfo.getCurrentStandardErrContents()); - } - - @Test - public void testHeapCommands() throws Exception { - String[] commands = new String[] { - "dump-heap", - "list-heap-dumps", - "save-heap-dump-to-file", - "show-heap-histogram", - "find-objects", - "object-info", - "find-root" - }; - - for (String command : commands) { - Spawn heapCommand = commandAgainstMongo(command); - heapCommand.expectClose(); - - assertCommandIsFound( - heapCommand.getCurrentStandardOutContents(), - heapCommand.getCurrentStandardErrContents()); - assertNoExceptions( - heapCommand.getCurrentStandardOutContents(), - heapCommand.getCurrentStandardErrContents()); - } - } - - private static Spawn commandAgainstMongo(String... args) throws IOException { - if (args == null || args.length == 0) { - throw new IllegalArgumentException("args must be an array with something"); - } - List completeArgs = new ArrayList<>(); - completeArgs.addAll(Arrays.asList(args)); - completeArgs.add("-d"); - completeArgs.add("mongodb://127.0.0.1:27518"); - return spawnThermostat(completeArgs.toArray(new String[0])); - } - -} - diff -r 92588dada473 -r 930ef1c74e99 integration-tests/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/pom.xml Tue Feb 19 14:24:46 2013 +0100 @@ -0,0 +1,145 @@ + + + + 4.0.0 + + + com.redhat.thermostat + thermostat + 0.6.0-SNAPSHOT + + + thermostat-integration-tests + jar + + Thermostat Integration Tests + + + UTF-8 + ${project.basedir}/.. + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + run-integration-tests + integration-test + + test + + + false + + + + + + maven-dependency-plugin + 2.4 + + + copy-deps + package + + copy-dependencies + + + true + org.osgi,junit,org.hamcrest + ${project.build.directory}/libs + + + + + + + + + + + junit + junit + test + + + net.sourceforge.expectj + expectj + test + + + + + com.redhat.thermostat + thermostat-distribution + ${project.version} + test + + + com.redhat.thermostat + thermostat-web-war + ${project.version} + war + test + + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + test + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + test + + + + + diff -r 92588dada473 -r 930ef1c74e99 integration-tests/src/test/java/com/redhat/thermostat/itest/CliTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/CliTest.java Tue Feb 19 14:24:46 2013 +0100 @@ -0,0 +1,196 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.itest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; + +import org.junit.Ignore; +import org.junit.Test; + +import expectj.Spawn; +import expectj.TimeoutException; + +/** + * Integration tests to exercise the basics of the thermostat command line. + */ +public class CliTest extends IntegrationTest { + + @Test + public void testExpectIsSane() throws Exception { + Spawn shell = spawnThermostat(); + + try { + shell.expect("some-random-text-that-is-not-really-possible"); + fail("should never match"); + } catch (IOException endOfStream) { + assertTrue(endOfStream.getMessage().contains("End of stream reached, no match found")); + } + shell.expectClose(); + } + + @Test + public void testSimpleInvocationPrintsHelp() throws Exception { + Spawn shell = spawnThermostat(); + shell.expectClose(); + + String stdOut = shell.getCurrentStandardOutContents(); + + assertMatchesHelpCommandList(stdOut); + + String stdErr = shell.getCurrentStandardErrContents(); + assertEquals(stdErr, ""); + } + + @Test + public void testHelpCommandInvocation() throws Exception { + Spawn shell = spawnThermostat("help"); + shell.expectClose(); + + String stdOut = shell.getCurrentStandardOutContents(); + String stdErr = shell.getCurrentStandardErrContents(); + + assertMatchesHelpCommandList(stdOut); + assertEquals(stdErr, ""); + } + + @Test + public void testHelpOnHelp() throws Exception { + Spawn shell = spawnThermostat("help", "help"); + shell.expectClose(); + + String stdOut = shell.getCurrentStandardOutContents(); + String stdErr = shell.getCurrentStandardErrContents(); + + String[] lines = stdOut.split("\n"); + String usage = lines[0]; + assertEquals("usage: thermostat help [command-name]", usage); + + assertEquals(stdErr, ""); + } + + @Test + public void testVersionArgument() throws Exception { + Spawn shell = spawnThermostat("--version"); + shell.expectClose(); + + String stdOut = shell.getCurrentStandardOutContents(); + String stdErr = shell.getCurrentStandardErrContents(); + + assertTrue(stdOut.matches("Thermostat version \\d+\\.\\d+\\.\\d+\n")); + assertEquals(stdErr, ""); + } + + @Test + public void testShell() throws Exception { + Spawn shell = spawnThermostat("shell"); + + shell.expect(SHELL_PROMPT); + shell.send("help\n"); + + shell.expect(SHELL_PROMPT); + + assertMatchesHelpCommandList(shell.getCurrentStandardOutContents()); + + shell.send("exit\n"); + + shell.expectClose(); + } + + @Test + public void testShellHelp() throws Exception { + Spawn shell = spawnThermostat("help", "shell"); + shell.expectClose(); + + String stdOut = shell.getCurrentStandardOutContents(); + + String[] lines = stdOut.split("\n"); + String usage = lines[0]; + assertTrue(usage.matches("^usage: thermostat shell$")); + String description = lines[1]; + assertTrue(description.matches("^\\s+launches the Thermostat interactive shell$")); + assertTrue(lines[2].matches("thermostat shell")); + } + + @Test + public void testShellUnrecognizedArgument() throws Exception { + Spawn shell = spawnThermostat("shell", "--foo"); + shell.expectErr("Unrecognized option: --foo"); + shell.expectClose(); + } + + @Test + public void testUnrecognizedEventsInShell() throws IOException, TimeoutException { + // test '!' events + Spawn shell = spawnThermostat("shell"); + + shell.expect(SHELL_PROMPT); + shell.send("what!?!\n"); + shell.expect(SHELL_PROMPT); + shell.send("exit\n"); + + assertTrue(shell.getCurrentStandardErrContents().contains("!?!: event not found")); + assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); + } + + @Test + public void testInvalidCommand() throws Exception { + Spawn shell = spawnThermostat("foobar", "baz"); + + // TODO should this be stderr? + shell.expect("unknown command 'foobar'"); + shell.expectClose(); + + String stdOut = shell.getCurrentStandardOutContents(); + + assertMatchesHelpCommandList(stdOut); + } + + private static void assertMatchesHelpCommandList(String actual) { + assertTrue(actual.contains("list of commands")); + assertTrue(actual.contains("help")); + assertTrue(actual.contains("agent")); + assertTrue(actual.contains("gui")); + assertTrue(actual.contains("ping")); + assertTrue(actual.contains("shell")); + } + +} + diff -r 92588dada473 -r 930ef1c74e99 integration-tests/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java Tue Feb 19 14:24:46 2013 +0100 @@ -0,0 +1,166 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.itest; + +import static org.junit.Assert.assertFalse; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import com.redhat.thermostat.common.utils.StreamUtils; + +import expectj.Executor; +import expectj.ExpectJ; +import expectj.Spawn; + +/** + * Helper methods to support writing an integration test. + */ +public class IntegrationTest { + + public static final long TIMEOUT_IN_SECONDS = 30; + + public static final String SHELL_PROMPT = "Thermostat >"; + + public static String getThermostatExecutable() { + return "../distribution/target/bin/thermostat"; + } + + public static String getStorageDataDirectory() { + return "../distribution/target/storage/db"; + } + + public static Spawn spawnThermostat(String... args) throws IOException { + ExpectJ expect = new ExpectJ(TIMEOUT_IN_SECONDS); + StringBuilder result = new StringBuilder(getThermostatExecutable()); + if (args != null) { + for (String arg : args) { + result.append(" ").append(arg); + } + } + String toExecute = result.toString(); + //System.out.println("executing: '" + toExecute + "'"); + return expect.spawn(toExecute); + } + + public static Spawn spawn(List args) throws IOException { + ExpectJ expect = new ExpectJ(TIMEOUT_IN_SECONDS); + StringBuilder result = new StringBuilder(); + for (String arg : args) { + result.append(arg).append(" "); + } + return expect.spawn(result.substring(0, result.length() - 1)); + } + + public static Spawn spawn(Executor executor) throws IOException { + ExpectJ expect = new ExpectJ(TIMEOUT_IN_SECONDS); + return expect.spawn(executor); + } + + /** + * Kill the process and all its children, recursively. Sends SIGTERM. + */ + public static void killRecursively(Process process) throws Exception { + killRecursively(getPid(process)); + } + + private static void killRecursively(int pid) throws Exception { + List childPids = findChildPids(pid); + for (Integer childPid : childPids) { + killRecursively(childPid); + } + killProcess(pid); + } + + private static void killProcess(int processId) throws Exception { + Runtime.getRuntime().exec("kill " + processId).waitFor(); + } + + private static List findChildPids(int processId) throws IOException { + String children = new String(StreamUtils.readAll(Runtime.getRuntime().exec("ps --ppid " + processId + " -o pid=").getInputStream())); + String[] childPids = children.split("\n"); + List result = new ArrayList<>(); + for (String childPid : childPids) { + String pidString = childPid.trim(); + if (pidString.length() == 0) { + continue; + } + try { + result.add(Integer.parseInt(pidString)); + } catch (NumberFormatException nfe) { + System.err.println(nfe); + } + } + return result; + } + + private static int getPid(Process process) throws Exception { + final String UNIX_PROCESS_CLASS = "java.lang.UNIXProcess"; + if (!process.getClass().getName().equals(UNIX_PROCESS_CLASS)) { + throw new IllegalArgumentException("can only kill " + UNIX_PROCESS_CLASS + "; input is a " + process.getClass()); + } + + Class processClass = process.getClass(); + Field pidField = processClass.getDeclaredField("pid"); + pidField.setAccessible(true); + return (int) pidField.get(process); + } + + public static void deleteFilesUnder(String path) throws IOException { + String[] filesToDelete = new File(path).list(); + for (String toDelete : filesToDelete) { + if (!new File(path, toDelete).delete()) { + throw new IOException("cant delete: '" + new File(path, toDelete).toString() + "'."); + } + } + } + + public static void assertCommandIsFound(String stdOutContents, String stdErrContents) { + assertFalse(stdOutContents.contains("unknown command")); + assertFalse(stdErrContents.contains("unknown command")); + } + + public static void assertNoExceptions(String stdOutContents, String stdErrContents) { + assertFalse(stdOutContents.contains("Exception")); + assertFalse(stdErrContents.contains("Exception")); + } + +} + diff -r 92588dada473 -r 930ef1c74e99 integration-tests/src/test/java/com/redhat/thermostat/itest/StorageConnectionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/StorageConnectionTest.java Tue Feb 19 14:24:46 2013 +0100 @@ -0,0 +1,114 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.itest; + +import java.io.IOException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import expectj.ExpectJException; +import expectj.Spawn; +import expectj.TimeoutException; + +public class StorageConnectionTest extends IntegrationTest { + + @BeforeClass + public static void setUpOnce() throws IOException, TimeoutException, ExpectJException { + Spawn storage = spawnThermostat("storage", "--start"); + storage.expect("pid:"); + storage.expectClose(); + + assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); + } + + @AfterClass + public static void tearDownOnce() throws IOException, TimeoutException, ExpectJException { + Spawn storage = spawnThermostat("storage", "--stop"); + storage.expect("server shutdown complete"); + storage.expectClose(); + + assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); + } + + @Test + public void testConnect() throws ExpectJException, TimeoutException, IOException { + Spawn shell = spawnThermostat("shell"); + + shell.expect(SHELL_PROMPT); + shell.send("connect -d mongodb://127.0.0.1:27518\n"); + shell.expect(SHELL_PROMPT); + shell.send("exit\n"); + shell.expectClose(); + + assertCommandIsFound(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); + assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); + } + + @Test + public void testDisconnectWithoutConnecting() throws ExpectJException, TimeoutException, IOException { + Spawn shell = spawnThermostat("shell"); + + shell.expect(SHELL_PROMPT); + shell.send("disconnect\n"); + shell.expect(SHELL_PROMPT); + shell.send("exit\n"); + shell.expectClose(); + + assertCommandIsFound(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); + assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); + } + + @Test + public void testConnectAndDisconnectInShell() throws IOException, TimeoutException, ExpectJException { + Spawn shell = spawnThermostat("shell"); + + shell.expect(SHELL_PROMPT); + shell.send("connect -d mongodb://127.0.0.1:27518\n"); + shell.expect(SHELL_PROMPT); + shell.send("disconnect\n"); + shell.send("exit\n"); + shell.expectClose(); + + assertNoExceptions(shell.getCurrentStandardOutContents(), shell.getCurrentStandardErrContents()); + } + + // TODO add a test to make sure connect/disconnect is not visible outside the shell +} + diff -r 92588dada473 -r 930ef1c74e99 integration-tests/src/test/java/com/redhat/thermostat/itest/StorageTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/StorageTest.java Tue Feb 19 14:24:46 2013 +0100 @@ -0,0 +1,89 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.itest; + +import java.io.IOException; + +import org.junit.Test; + +import expectj.Executor; +import expectj.Spawn; + +public class StorageTest extends IntegrationTest { + + @Test + public void startAndStopStorage() throws Exception { + Spawn storage; + + storage = spawnThermostat("storage", "--start"); + storage.expect("pid:"); + storage.expectClose(); + + assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); + + storage = spawnThermostat("storage", "--stop"); + storage.expect("server shutdown complete"); + storage.expectClose(); + + assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); + } + + @Test + public void testServiceStartAndKilling() throws Exception { + Spawn storage; + final Process[] process = new Process[1]; + + storage = spawn(new Executor() { + @Override + public Process execute() throws IOException { + ProcessBuilder builder = new ProcessBuilder(getThermostatExecutable(), "service"); + Process service = builder.start(); + process[0] = service; + return service; + } + }); + + try { + storage.expectErr("agent started"); + } + finally { + killRecursively(process[0]); + } + } + +} + diff -r 92588dada473 -r 930ef1c74e99 integration-tests/src/test/java/com/redhat/thermostat/itest/VmCommandsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/VmCommandsTest.java Tue Feb 19 14:24:46 2013 +0100 @@ -0,0 +1,135 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.itest; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import expectj.Spawn; + +/** Integration tests for the various vm commands */ +public class VmCommandsTest extends IntegrationTest { + + @BeforeClass + public static void setUpOnce() throws IOException, InterruptedException { + String staleDataDir = getStorageDataDirectory(); + deleteFilesUnder(staleDataDir); + + Process startStorage = new ProcessBuilder(getThermostatExecutable(), "storage", "--start").start(); + startStorage.waitFor(); + + // TODO insert actual data into the database and test that + } + + @AfterClass + public static void tearDownOnce() throws InterruptedException, IOException { + Process stopStorage = new ProcessBuilder(getThermostatExecutable(), "storage", "--stop").start(); + stopStorage.waitFor(); + } + + @Test + public void testListVms() throws Exception { + Spawn vmList = commandAgainstMongo("list-vms"); + vmList.expectClose(); + + assertEquals("HOST_ID HOST VM_ID STATUS VM_NAME\n", vmList.getCurrentStandardOutContents()); + } + + @Test + public void testVmStat() throws Exception { + Spawn vmStat = commandAgainstMongo("vm-stat"); + vmStat.expectClose(); + + System.out.println(vmStat.getCurrentStandardOutContents()); + assertCommandIsFound(vmStat.getCurrentStandardOutContents(), vmStat.getCurrentStandardErrContents()); + assertNoExceptions(vmStat.getCurrentStandardOutContents(), vmStat.getCurrentStandardErrContents()); + } + + @Test + public void testVmInfo() throws Exception { + Spawn vmInfo = commandAgainstMongo("vm-info"); + vmInfo.expectClose(); + + assertNoExceptions(vmInfo.getCurrentStandardOutContents(), vmInfo.getCurrentStandardErrContents()); + } + + @Test + public void testHeapCommands() throws Exception { + String[] commands = new String[] { + "dump-heap", + "list-heap-dumps", + "save-heap-dump-to-file", + "show-heap-histogram", + "find-objects", + "object-info", + "find-root" + }; + + for (String command : commands) { + Spawn heapCommand = commandAgainstMongo(command); + heapCommand.expectClose(); + + assertCommandIsFound( + heapCommand.getCurrentStandardOutContents(), + heapCommand.getCurrentStandardErrContents()); + assertNoExceptions( + heapCommand.getCurrentStandardOutContents(), + heapCommand.getCurrentStandardErrContents()); + } + } + + private static Spawn commandAgainstMongo(String... args) throws IOException { + if (args == null || args.length == 0) { + throw new IllegalArgumentException("args must be an array with something"); + } + List completeArgs = new ArrayList<>(); + completeArgs.addAll(Arrays.asList(args)); + completeArgs.add("-d"); + completeArgs.add("mongodb://127.0.0.1:27518"); + return spawnThermostat(completeArgs.toArray(new String[0])); + } + +} + diff -r 92588dada473 -r 930ef1c74e99 integration-tests/src/test/java/com/redhat/thermostat/itest/WebAppTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/WebAppTest.java Tue Feb 19 14:24:46 2013 +0100 @@ -0,0 +1,166 @@ +/* + * Copyright 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * . + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.itest; + +import static com.redhat.thermostat.itest.IntegrationTest.assertNoExceptions; +import static com.redhat.thermostat.itest.IntegrationTest.spawnThermostat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.UUID; + +import org.eclipse.jetty.security.DefaultUserIdentity; +import org.eclipse.jetty.security.MappedLoginService; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.UserIdentity; +import org.eclipse.jetty.util.security.Password; +import org.eclipse.jetty.webapp.WebAppContext; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.redhat.thermostat.common.ApplicationInfo; +import com.redhat.thermostat.storage.config.ConnectionConfiguration; +import com.redhat.thermostat.storage.config.StartupConfiguration; +import com.redhat.thermostat.storage.core.Add; +import com.redhat.thermostat.storage.core.Cursor; +import com.redhat.thermostat.storage.core.Query; +import com.redhat.thermostat.test.FreePortFinder; +import com.redhat.thermostat.test.FreePortFinder.TryPort; +import com.redhat.thermostat.vm.classstat.common.VmClassStatDAO; +import com.redhat.thermostat.vm.classstat.common.model.VmClassStat; +import com.redhat.thermostat.web.client.internal.WebStorage; + +import expectj.Spawn; + +public class WebAppTest { + + private static WebStorage webStorage; + private static Server server; + private static int port; + + @BeforeClass + public static void setUpOnce() throws Exception { + Spawn storage = spawnThermostat("storage", "--start"); + storage.expect("pid:"); + storage.expectClose(); + + assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); + + port = FreePortFinder.findFreePort(new TryPort() { + + @Override + public void tryPort(int port) throws Exception { + startServer(port); + } + }); + registerCategory(); + } + + @AfterClass + public static void tearDownOnce() throws Exception { + server.stop(); + server.join(); + + Spawn storage = spawnThermostat("storage", "--stop"); + storage.expect("server shutdown complete"); + storage.expectClose(); + + assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents()); + } + + private static void startServer(int port) throws Exception { + server = new Server(port); + ApplicationInfo appInfo = new ApplicationInfo(); + String version = appInfo.getMavenVersion(); + String warfile = "target/libs/thermostat-web-war-" + version + ".war"; + WebAppContext ctx = new WebAppContext(warfile, "/thermostat"); + ctx.getSecurityHandler().setAuthMethod("BASIC"); + ctx.getSecurityHandler().setLoginService(new MappedLoginService() { + + @Override + protected void loadUsers() throws IOException { + putUser("testname", new Password("testpasswd"), new String[] { "thermostat-agent" }); + putUser("test-no-role", new Password("testpasswd"), new String[] { "fluff" }); + putUser("test-cmd-channel", new Password("testpasswd"), new String[] { "thermostat-cmd-channel" }); + } + + @Override + protected UserIdentity loadUser(String username) { + if (username.equals("test-cmd-channel")) { + return new DefaultUserIdentity(null, null, new String[] { "thermostat-cmd-channel" }); + } + return new DefaultUserIdentity(null, null, new String[] { "thermostat-agent" }); + } + }); + server.setHandler(ctx); + server.start(); + } + + private static void registerCategory() { + String url = "http://localhost:" + port + "/thermostat/storage"; + StartupConfiguration config = new ConnectionConfiguration(url, "testname", "testpasswd"); + webStorage = new WebStorage(config); + webStorage.setAgentId(new UUID(42, 24)); + webStorage.getConnection().connect(); + webStorage.registerCategory(VmClassStatDAO.vmClassStatsCategory); + } + + @Test + public void testPutFind() { + Add add = webStorage.createAdd(VmClassStatDAO.vmClassStatsCategory); + VmClassStat pojo = new VmClassStat(); + pojo.setAgentId("fluff"); + pojo.setLoadedClasses(12345); + pojo.setTimeStamp(42); + pojo.setVmId(987); + add.setPojo(pojo); + add.apply(); + + Query query = webStorage.createQuery(VmClassStatDAO.vmClassStatsCategory); + Cursor cursor = query.execute(); + assertTrue(cursor.hasNext()); + VmClassStat foundPojo = cursor.next(); + assertEquals("fluff", foundPojo.getAgentId()); + assertEquals(42, foundPojo.getTimeStamp()); + assertEquals(987, foundPojo.getVmId()); + assertEquals(12345, foundPojo.getLoadedClasses()); + assertFalse(cursor.hasNext()); + } +} diff -r 92588dada473 -r 930ef1c74e99 pom.xml --- a/pom.xml Fri Feb 15 17:24:29 2013 -0500 +++ b/pom.xml Tue Feb 19 14:24:46 2013 +0100 @@ -142,6 +142,7 @@ vm-heap-analysis numa + integration-tests dev diff -r 92588dada473 -r 930ef1c74e99 web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorage.java --- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorage.java Fri Feb 15 17:24:29 2013 -0500 +++ b/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorage.java Tue Feb 19 14:24:46 2013 +0100 @@ -85,6 +85,7 @@ import com.redhat.thermostat.common.ssl.SSLContextFactory; import com.redhat.thermostat.common.ssl.SslInitException; import com.redhat.thermostat.common.utils.LoggingUtils; +import com.redhat.thermostat.storage.config.AuthenticationConfiguration; import com.redhat.thermostat.storage.config.StartupConfiguration; import com.redhat.thermostat.storage.core.Add; import com.redhat.thermostat.storage.core.AuthToken; @@ -341,6 +342,11 @@ random = new SecureRandom(); conn = new WebConnection(); + setEndpoint(config.getDBConnectionString()); + if (config instanceof AuthenticationConfiguration) { + AuthenticationConfiguration authConfig = (AuthenticationConfiguration) config; + setAuthConfig(authConfig.getUsername(), authConfig.getPassword()); + } // setup SSL if necessary if (config.getDBConnectionString().startsWith(HTTPS_PREFIX)) { registerSSLScheme(connManager); diff -r 92588dada473 -r 930ef1c74e99 web/server/pom.xml --- a/web/server/pom.xml Fri Feb 15 17:24:29 2013 -0500 +++ b/web/server/pom.xml Tue Feb 19 14:24:46 2013 +0100 @@ -87,6 +87,7 @@ javax.servlet servlet-api ${javax.servlet.version} + provided