changeset 2012:4851a6db01a9

Stabilize integration tests for mongodb 3.2.x Backport of: http://icedtea.classpath.org/hg/thermostat/rev/1a237d1821fa Also includes: Get PID when starting storage and don't wait if process doesn't start successfully from: http://icedtea.classpath.org/hg/thermostat/rev/b36e89aa7070 PR3150 Reviewed-by: jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-August/020700.html
author Jie Kang <jkang@redhat.com>
date Fri, 26 Aug 2016 13:53:09 -0400
parents 53db26fe0673
children 189fa2a6b1f5
files integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/AllCommandsResolvableTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/CliTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/DevWebStorageTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/PluginTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageConnectionTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/SystemPluginsTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/UserPluginsTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/VmCommandsTest.java integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java storage/cli/src/main/java/com/redhat/thermostat/storage/cli/internal/MongoProcessRunner.java
diffstat 13 files changed, 226 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/AllCommandsResolvableTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/AllCommandsResolvableTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -38,7 +38,6 @@
 
 import static org.junit.Assert.assertTrue;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -46,8 +45,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.junit.After;
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import expectj.Spawn;
@@ -61,16 +59,16 @@
     
     private static final String UNKNOWN_CMD_OPTION = "--unknownOption";
     
-    @Before
-    public void setup() {
+    @BeforeClass
+    public static void setupOnce() {
+        setupIntegrationTest(AllCommandsResolvableTest.class);
+        /**
+         * If thermostat runs without setup complete it will run the setup;
+         * skip this by creating the stamp beforehand
+         */
         createFakeSetupCompleteFile();
     }
     
-    @After
-    public void tearDown() throws IOException {
-        removeSetupCompleteStampFiles();
-    }
-    
     @Test
     public void testAllCommandsOsgiResolve() throws Exception {
         List<String> allCmds = parseAvailableCommandsFromHelp();
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/CliTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/CliTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -38,14 +38,12 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.IOException;
 
-import org.junit.After;
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import expectj.Spawn;
@@ -65,15 +63,16 @@
             "                  system shell-prompt.conf file for instructions on how to write\n" +
             "                  the config file.\n";
     
-    @Before
-    public void setup() {
+    @BeforeClass
+    public static void setupOnce() {
+        setupIntegrationTest(CliTest.class);
+
+        /**
+         * If thermostat runs without setup complete it will run the setup;
+         * skip this by creating the stamp beforehand
+         */
         createFakeSetupCompleteFile();
     }
-    
-    @After
-    public void tearDown() throws IOException {
-        removeSetupCompleteStampFiles();
-    }
 
     @Test
     public void testExpectIsSane() throws Exception {
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/DevWebStorageTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/DevWebStorageTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -37,11 +37,9 @@
 package com.redhat.thermostat.itest;
 
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
 import java.util.Map;
 
 import org.junit.AfterClass;
@@ -56,31 +54,21 @@
 
     @BeforeClass
     public static void setUp() throws IOException {
-        clearStorageDataDirectory();
+        setupIntegrationTest(DevWebStorageTest.class);
         backupOriginalCredentialsFiles();
+
         try {
             runThermostatDevSetup();
         } catch (Exception e) {
             e.printStackTrace();
             restoreBackedUpCredentialsFiles();
+            fail();
         }
     }
     
     @AfterClass
     public static void tearDown() throws IOException {
         restoreBackedUpCredentialsFiles();
-        removeSetupCompleteStampFiles();
-        removeAgentAuthFile();
-        clearStorageDataDirectory();
-    }
-    
-    private static void removeAgentAuthFile() throws IOException {
-        File agentAuth = new File(getUserThermostatHome() , "etc/agent.auth");
-        try {
-            Files.delete(agentAuth.toPath());
-        } catch (NoSuchFileException e) {
-            // this is what we wanted, so ignore it.
-        }
     }
 
     /**
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/IntegrationTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -44,7 +44,6 @@
 import java.lang.reflect.Field;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -77,30 +76,12 @@
     private static final String THERMOSTAT_HOME = "THERMOSTAT_HOME";
     private static final String USER_THERMOSTAT_HOME = "USER_THERMOSTAT_HOME";
     
-    public static final Map<String, String> DEFAULT_ENVIRONMENT;
-    public static final Map<String, String> DEFAULT_ENV_WITH_LANG_C;
-    
-    /**
-     * Configure the log level to FINEST, and configure a file handler so as for
-     * log messages to go to USER_THERMOSTAT_HOME/integration-tests.log rather
-     * than stdout. This is to ensure integration tests pass without dependency
-     * on log levels. See:
-     *   http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1594
-     */
-    static {
-        createUserThermostatHomeAndEtc();
-        File loggingProperties = new File(getUserThermostatHome() + File.separator + "etc" + File.separator + "logging.properties");
-        File logFile = new File(getUserThermostatHome() + File.separator + "integration-tests.log");
-        LogConfigurator configurator = new LogConfigurator(Level.FINEST, loggingProperties, logFile);
-        configurator.writeConfiguration();
-        
-        // Set up environment maps.
-        DEFAULT_ENVIRONMENT = new HashMap<>();
-        DEFAULT_ENVIRONMENT.put(THERMOSTAT_HOME, getThermostatHome());
-        DEFAULT_ENVIRONMENT.put(USER_THERMOSTAT_HOME, getUserThermostatHome());
-        DEFAULT_ENV_WITH_LANG_C = new HashMap<>(DEFAULT_ENVIRONMENT);
-        DEFAULT_ENV_WITH_LANG_C.put("LANG", "C");
-    }
+    public static Map<String, String> DEFAULT_ENVIRONMENT;
+    public static Map<String, String> DEFAULT_ENV_WITH_LANG_C;
+
+    private static String testName;
+    private static String thermostatHome;
+    private static String userThermostatHome;
     
     public static class SpawnResult {
         final Process process;
@@ -118,6 +99,57 @@
     public static final String SHELL_CONNECT_PROMPT = "Thermostat + >";
 
     private static final String THERMOSTAT_SCRIPT = "thermostat";
+
+    public static void setupIntegrationTest(Class testClass) {
+        setupIntegrationTest(testClass.getName());
+    }
+
+    /**
+     * Call this with the name of the test e.g. Test.class.getName()
+     * to setup the testing environment. It is expected that integration
+     * tests call this in an @BeforeClass first before using other
+     * methods provided by this class. Otherwise behaviour is
+     * undefined
+     * @param testName
+     */
+    public static void setupIntegrationTest(String testName) {
+        /**
+         * Configure the log level to FINEST, and configure a file handler so as for
+         * log messages to go to USER_THERMOSTAT_HOME/integration-tests.log rather
+         * than stdout. This is to ensure integration tests pass without dependency
+         * on log levels. See:
+         *   http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1594
+         */
+        IntegrationTest.testName = testName;
+        setUserThermostatHome();
+        setThermostatHome();
+
+        /**
+         * Clean up the directory if it already exists for the new test run
+         * Older test runs may not have removed the directory or subdirectories
+         */
+        File f = new File(userThermostatHome);
+        if (f.exists()) {
+            try {
+                deleteFilesRecursivelyUnder(f);
+            } catch (IOException e) {
+            }
+        }
+
+        createUserThermostatHomeAndEtc();
+        File loggingProperties = new File(getUserThermostatHome() + File.separator + "etc" + File.separator + "logging.properties");
+        File logFile = new File(getUserThermostatHome() + File.separator + "integration-tests.log");
+        LogConfigurator configurator = new LogConfigurator(Level.FINEST, loggingProperties, logFile);
+        configurator.writeConfiguration();
+
+        // Set up environment maps.
+        DEFAULT_ENVIRONMENT = new HashMap<>();
+        DEFAULT_ENVIRONMENT.put(THERMOSTAT_HOME, getThermostatHome());
+        DEFAULT_ENVIRONMENT.put(USER_THERMOSTAT_HOME, getUserThermostatHome());
+
+        DEFAULT_ENV_WITH_LANG_C = new HashMap<>(DEFAULT_ENVIRONMENT);
+        DEFAULT_ENV_WITH_LANG_C.put("LANG", "C");
+    }
     
     private static File createUserThermostatHomeAndEtc() {
         File userThHome = new File(getUserThermostatHome());
@@ -150,52 +182,7 @@
             throw new RuntimeException(e.getMessage(), e);
         }
     }
-    
-    protected static void createFakeUserSetupDoneFile() {
-        String userHome = getUserThermostatHome();
-        File fUserHome = new File(userHome);
-        fUserHome.mkdir();
-        File dataDir = new File(fUserHome, "data");
-        dataDir.mkdir();
 
-        File mongodbUserDoneFile = new File(dataDir, "mongodb-user-done.stamp");
-        try {
-            // creates the file only if not yet existing
-            mongodbUserDoneFile.createNewFile();
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * Utility method for removing stamp files which may get created by certain
-     * integration test runs. For example a test which runs the "service"
-     * command now depends on a proper mongodb user to be set up. Setting it up
-     * may create the mongodb-user-done.stamp file. Similar with running
-     * the thermostat-setup script and setup-complete.stamp.
-     * 
-     * Be sure to call this in @After/@AfterClass as appropriate. There is no
-     * simple way for the base class to know when to erase those files.
-     * 
-     * @throws IOException
-     */
-    protected static void removeSetupCompleteStampFiles() throws IOException {
-        String mongodbUserDoneFile = getUserThermostatHome() + "/data/mongodb-user-done.stamp";
-        String setupStampFile = getUserThermostatHome() + "/data/setup-complete.stamp";
-        File mongodbFileStamp = new File(mongodbUserDoneFile);
-        File setupFileStamp = new File(setupStampFile);
-        removeFileIgnoreMissing(mongodbFileStamp);
-        removeFileIgnoreMissing(setupFileStamp);
-    }
-    
-    private static void removeFileIgnoreMissing(File file) throws IOException {
-        try {
-            Files.delete(file.toPath());
-        } catch (NoSuchFileException e) {
-            // wanted to delete that file, so that should be fine.
-        }
-    }
-    
     protected static Map<String, String> getVerboseModeProperties() {
         Map<String, String> testProperties = new HashMap<>();
         // See AgentApplication.VERBOSE_MODE_PROPERTY
@@ -213,8 +200,20 @@
                 StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
     }
 
-    protected void deleteAgentAuthFile() throws IOException {
-        Files.delete(new File(new File(getUserThermostatHome(), "etc"), "agent.auth").toPath());
+    private static void setThermostatHome() {
+        String propHome = System.getProperty(ITEST_THERMOSTAT_HOME_PROP);
+        if (propHome == null) {
+            String relPath = "../../distribution/target/image";
+            try {
+                IntegrationTest.thermostatHome = new File(relPath).getCanonicalPath();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            IntegrationTest.thermostatHome = propHome;
+        }
+
+        System.setProperty(THERMOSTAT_HOME, IntegrationTest.thermostatHome);
     }
 
     /* This is a mirror of paths from c.r.t.shared.Configuration */
@@ -245,33 +244,24 @@
         return getThermostatHome() + "/bin";
     }
 
-    public static String getUserThermostatHome() {
+    private static void setUserThermostatHome() {
         String userHomeProp = System.getProperty(ITEST_USER_HOME_PROP);
         if (userHomeProp == null) {
-        	String relPath = "../../distribution/target/user-home";
-        	try {
-                return new File(relPath).getCanonicalPath();
+            String relPath = "target/user-home-" + testName;
+            try {
+                IntegrationTest.userThermostatHome = new File(relPath).getCanonicalPath();
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         } else {
-            return userHomeProp;
+            IntegrationTest.userThermostatHome = userHomeProp;
         }
-    }
 
-    public static String getStorageDataDirectory() {
-        return getUserThermostatHome() + "/data/db";
+        System.setProperty(USER_THERMOSTAT_HOME, IntegrationTest.userThermostatHome);
     }
 
-    public static void clearStorageDataDirectory() throws IOException {
-        File storageDir = new File(getStorageDataDirectory());
-        if (storageDir.exists()) {
-            if (storageDir.isDirectory()) {
-                deleteFilesRecursivelyUnder(storageDir);
-            } else {
-                throw new IllegalStateException(storageDir + " exists but is not a directory");
-            }
-        }
+    public static String getUserThermostatHome() {
+        return IntegrationTest.userThermostatHome;
     }
 
     /** pre-conditions:
@@ -330,6 +320,7 @@
         storage.expectClose();
 
         assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents());
+
         return storage;
     }
     
@@ -338,6 +329,7 @@
         storage.expect("server shutdown complete");
         storage.expectClose();
         assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents());
+
         return storage;
     }
     
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/MongoQueriesTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -125,7 +125,8 @@
 
     @BeforeClass
     public static void setUpOnce() throws Exception {
-        clearStorageDataDirectory();
+        setupIntegrationTest(MongoQueriesTest.class);
+
         createFakeSetupCompleteFile();
         addUserToStorage(USERNAME, PASSWORD);
 
@@ -136,11 +137,7 @@
 
     @AfterClass
     public static void tearDownOnce() throws Exception {
-        deleteCpuData();
-
         stopStorage();
-        removeSetupCompleteStampFiles();
-        clearStorageDataDirectory();
     }
 
     /*
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/PluginTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/PluginTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -41,10 +41,7 @@
 import java.io.IOException;
 
 public class PluginTest extends IntegrationTest {
-
     protected static final String SYSTEM_PLUGIN_HOME = getSystemPluginHome();
-    protected static final String USER_PLUGIN_HOME = getUserThermostatHome() + File.separator + "data" + File.separator + "plugins";
-    protected static final String USER_PLUGIN_INSTALL_LOCATION = USER_PLUGIN_HOME + File.separator + "user";
     protected static final String SYSTEM_PLUGIN_INSTALL_LOCATION = SYSTEM_PLUGIN_HOME + File.separator + "new";
 
     protected abstract static class BasicPlugin {
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageConnectionTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageConnectionTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -38,8 +38,7 @@
 
 import java.io.IOException;
 
-import org.junit.After;
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -49,26 +48,16 @@
 
 public class StorageConnectionTest extends IntegrationTest {
 
-    // @BeforeClass // reinstate once we actually need storage running (see ignored tests)
+    @BeforeClass
     public static void setUpOnce() throws Exception {
-        clearStorageDataDirectory();
-        startStorage();
-    }
+        setupIntegrationTest(StorageConnectionTest.class);
 
-    // @AfterClass // reinstate once we actually need storage running
-    public static void tearDownOnce() throws Exception {
-        stopStorage();
-    }
-    
-    @Before
-    public void setup() {
+        /**
+         * If thermostat runs without setup complete it will run the setup;
+         * skip this by creating the stamp beforehand
+         */
         createFakeSetupCompleteFile();
     }
-    
-    @After
-    public void tearDown() throws IOException {
-        removeSetupCompleteStampFiles();
-    }
 
     @Ignore //FIXME when keyring/preferences improvements have been made, un-Ignore
     @Test
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/StorageTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -36,42 +36,37 @@
 
 package com.redhat.thermostat.itest;
 
-import java.io.IOException;
 import java.util.Map;
 
-import org.junit.After;
-import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 import expectj.Spawn;
 
 public class StorageTest extends IntegrationTest {
     
-    @Before
-    public void setup() {
+    @BeforeClass
+    public static void setupOnce() throws Exception {
+        setupIntegrationTest(StorageTest.class);
+
         createFakeSetupCompleteFile();
-    }
-    
-    @After
-    public void tearDown() throws IOException {
-        removeSetupCompleteStampFiles();
+
+        addUserToStorage("foo", "bar");
+        createAgentAuthFile("foo", "bar");
     }
 
     @Test
     public void startAndStopStorage() throws Exception {
-        clearStorageDataDirectory();
-
         Spawn storage;
-        storage = startStorage();
+        startStorage();
 
         storage = spawnThermostat("storage", "--status");
         storage.expect("Storage is running");
         storage.expectClose();
         
         assertNoExceptions(storage.getCurrentStandardOutContents(), storage.getCurrentStandardErrContents());
-        
-        storage = stopStorage();
-        
+
+        stopStorage();
         storage = spawnThermostat("storage", "--status");
         storage.expect("Storage is not running");
         storage.expectClose();
@@ -81,10 +76,6 @@
 
     @Test
     public void testServiceStartAndKilling() throws Exception {
-        clearStorageDataDirectory();
-        addUserToStorage("foo", "bar");
-        createAgentAuthFile("foo", "bar");
-
         Map<String, String> testProperties = getVerboseModeProperties();
         SpawnResult spawnResult = spawnThermostatWithPropertiesSetAndGetProcess(testProperties, "service");
         Spawn service = spawnResult.spawn;
@@ -105,7 +96,9 @@
         service.stop();
         service.expectClose();
 
-        deleteAgentAuthFile();
+        service = spawnThermostat("storage", "--status");
+        service.expect("Storage is not running");
+        service.expectClose();
     }
 
 }
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/SystemPluginsTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/SystemPluginsTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -38,11 +38,7 @@
 
 import static org.junit.Assert.assertTrue;
 
-import java.io.IOException;
-
-import org.junit.After;
 import org.junit.AfterClass;
-import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -58,25 +54,19 @@
             "provides foo command", SYSTEM_PLUGIN_INSTALL_LOCATION);
     
     @BeforeClass
-    public static void setUpOnce() {
+    public static void setUpOnce()
+    {
+        setupIntegrationTest(SystemPluginsTest.class);
+        createFakeSetupCompleteFile();
+
         fooPlugin.install();
     }
     
-    @Before
-    public void setup() {
-        createFakeSetupCompleteFile();
-    }
-
     @AfterClass
     public static void tearDownOnce() {
         fooPlugin.uninstall();
     }
     
-    @After
-    public void tearDown() throws IOException {
-        removeSetupCompleteStampFiles();
-    }
-
     @Test
     public void helpOutputContainsSystemPluginName() throws Exception {
         Spawn shell = spawnThermostat("help");
@@ -91,7 +81,6 @@
         assertTrue(stdOut.contains("ping"));
         assertTrue(stdOut.contains("shell"));
 
-
         assertTrue(stdOut.contains(fooPlugin.getCommandName()));
     }
 }
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/UserPluginsTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/UserPluginsTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -40,11 +40,7 @@
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
-import java.io.IOException;
 
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -56,31 +52,27 @@
  */
 public class UserPluginsTest extends PluginTest {
 
-    private static NewCommandPlugin userPlugin = new NewCommandPlugin(
-            "user",
-            "a plugin that is provided by the user", USER_PLUGIN_INSTALL_LOCATION);
-    private static UnknownExtendsPlugin unknownExtension = new UnknownExtendsPlugin(USER_PLUGIN_HOME + File.separator + "unknown");
+    private static NewCommandPlugin userPlugin;
+    private static UnknownExtendsPlugin unknownExtension;
 
     @BeforeClass
     public static void setUpOnce() {
-        userPlugin.install();
-        unknownExtension.install();
-    }
-    
-    @Before
-    public void setup() {
+        setupIntegrationTest(UserPluginsTest.class);
+
         createFakeSetupCompleteFile();
-    }
+
+        String USER_PLUGIN_HOME = getUserThermostatHome() + File.separator + "data" + File.separator + "plugins";
+        String USER_PLUGIN_INSTALL_LOCATION = USER_PLUGIN_HOME + File.separator + "user";
+
 
-    @AfterClass
-    public static void tearDownOnce() {
-        unknownExtension.uninstall();
-        userPlugin.uninstall();
-    }
-    
-    @After
-    public void tearDown() throws IOException {
-        removeSetupCompleteStampFiles();
+        userPlugin = new NewCommandPlugin(
+                "user",
+                "a plugin that is provided by the user",
+                USER_PLUGIN_INSTALL_LOCATION);
+        userPlugin.install();
+
+        unknownExtension = new UnknownExtendsPlugin(USER_PLUGIN_HOME + File.separator + "unknown");
+        unknownExtension.install();
     }
 
     @Test
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/VmCommandsTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/VmCommandsTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -56,8 +56,10 @@
 
     @BeforeClass
     public static void setUpOnce() throws Exception {
+        setupIntegrationTest(VmCommandsTest.class);
+
         createFakeSetupCompleteFile();
-        clearStorageDataDirectory();
+
         addUserToStorage(USERNAME, PASSWORD);
         createAgentAuthFile(USERNAME, PASSWORD);
 
@@ -69,7 +71,6 @@
     @AfterClass
     public static void tearDownOnce() throws Exception {
         stopStorage();
-        removeSetupCompleteStampFiles();
     }
 
     @Ignore //FIXME when keyring/preferences improvements have been made, un-Ignore
--- a/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/integration-tests/itest-run/src/test/java/com/redhat/thermostat/itest/WebAppTest.java	Fri Aug 26 13:53:09 2016 -0400
@@ -252,12 +252,11 @@
 
     @BeforeClass
     public static void setUpOnce() throws Exception {
-        clearStorageDataDirectory();
+        setupIntegrationTest(WebAppTest.class.getName());
 
         backupOriginalCredentialsFiles();
 
         createFakeSetupCompleteFile();
-        createFakeUserSetupDoneFile();
 
         addUserToStorage(getMongodbUsername(), getMongodbPassword());
 
@@ -311,10 +310,8 @@
                     e.printStackTrace();
                     throw e;
                 } finally {
-                    removeSetupCompleteStampFiles();
                     restoreBackedUpCredentialsFiles();
                     System.out.println("RESTORED backed-up files!");
-                    clearStorageDataDirectory();
                 }
             }
         }
@@ -490,7 +487,7 @@
         String version = appInfo.getMavenVersion();
         String warfile = "target/libs/thermostat-web-war-" + version + ".war";
         WebAppContext ctx = new WebAppContext(warfile, "/thermostat");
-        
+
         // We need to set this to true in order for WebStorageEndPoint to pick
         // up the descriptor registrations from WebAppTestStatementDescriptorRegistration
         // which would result in 
--- a/storage/cli/src/main/java/com/redhat/thermostat/storage/cli/internal/MongoProcessRunner.java	Fri Aug 19 10:41:56 2016 -0400
+++ b/storage/cli/src/main/java/com/redhat/thermostat/storage/cli/internal/MongoProcessRunner.java	Fri Aug 26 13:53:09 2016 -0400
@@ -82,6 +82,8 @@
         "kill", "-s", "TERM"
     };
 
+    private static final String EMPTY_STRING = "";
+
     private static final String NO_JOURNAL_ARGUMENT = "--nojournal";
     static final String NO_JOURNAL_FIRST_VERSION = "1.9.2";
     static final String LOCALHOST_EXPTN_FIRST_VERSION = "2.4.0";
@@ -168,7 +170,7 @@
             throw new StorageAlreadyRunningException(pid, message.getContents());
         }
         
-        String dbVersion;
+        final String dbVersion;
         try {
             dbVersion = getDBVersion();
         } catch (IOException e) {
@@ -177,15 +179,14 @@
             throw new ApplicationException(message.getContents(), e);
 
         }
-        List<String> commands = null;
-        commands = getStartupCommand(dbVersion);
+        List<String> commands = getStartupCommand(dbVersion);
         
         logger.log(Level.FINEST, "Executing mongo: " + StringUtils.join(" ", commands));
 
         display(translator.localize(LocaleResources.STARTING_STORAGE_SERVER));
         
         LoggedExternalProcess process = new LoggedExternalProcess(commands);
-        int status = -1;
+        int status;
         try {
             status = process.runAndReturnResult();
         } catch (ApplicationException ae) {
@@ -193,19 +194,16 @@
             throw new ApplicationException(message.getContents(), ae);
         }
 
-        Thread.sleep(500);
+        if (status == 0) {
+            waitForLogFile(getStartString(dbVersion));
+            /**
+             * This checkPid() call will also set the variable pid used in the following display(...) call
+             */
+            checkPid();
 
-        if (status == 0) {
-            if (!isStorageRunning()) {
-                status = -1;
-            }
-        }
-
-        if (status == 0) {
             display(translator.localize(LocaleResources.SERVER_LISTENING_ON, configuration.getDBConnectionString()));
             display(translator.localize(LocaleResources.LOG_FILE_AT, configuration.getLogFile().toString()));
             display(translator.localize(LocaleResources.PID_IS, String.valueOf(pid)));
-            
         } else {
             // don't display anything when throwing an exception; whatever catches the exception will do so.
             LocalizedString message = translator.localize(LocaleResources.CANNOT_START_SERVER,
@@ -231,6 +229,19 @@
 
         LoggedExternalProcess process = new LoggedExternalProcess(commands);
         int status = process.runAndReturnResult();
+
+        final String dbVersion;
+        try {
+            dbVersion = getDBVersion();
+        } catch (IOException e) {
+            LocalizedString message = translator.localize(
+                    LocaleResources.CANNOT_EXECUTE_PROCESS, MONGO_PROCESS);
+            throw new ApplicationException(message.getContents(), e);
+
+        }
+
+        waitForLogFile(getStopString(dbVersion));
+
         if (status == 0) {
             display(translator.localize(LocaleResources.SERVER_SHUTDOWN_COMPLETE, configuration.getDBPath().toString()));
             display(translator.localize(LocaleResources.LOG_FILE_AT, configuration.getLogFile().toString()));
@@ -309,6 +320,57 @@
         InputStream out = process.getInputStream();
         return doGetDBVersion(out);
     }
+
+    private void waitForLogFile(final String toWaitFor) throws InterruptedException, IOException {
+        final File logFile = configuration.getLogFile();
+        /**
+         * Initialize with empty string so first check does not NPE
+         */
+        final String[] s = new String[]{EMPTY_STRING};
+
+        /**
+         * Try for approximately 5 seconds
+         */
+        for (int i = 0; i < 50; i++) {
+            if (logFile.exists() && !s[0].contains(toWaitFor)) {
+                s[0] = new String(Files.readAllBytes(logFile.toPath()));
+                Thread.sleep(100l);
+            } else {
+                return;
+            }
+        }
+    }
+
+    private String getStartString(String dbVersion) {
+        /**
+         * Valid for mongodb >= 2.0.6
+         */
+        if (dbVersion.compareTo("2.0.6") >= 0) {
+            return "waiting for connections on port";
+        }
+        /**
+         * For other versions return empty.
+         */
+        return EMPTY_STRING;
+    }
+
+    private String getStopString(String dbVersion) {
+        /**
+         * Valid for mongodb >= 3.2.0
+         */
+        if (dbVersion.compareTo("3.2.0") >= 0) {
+            return "dbexit:  rc: 0";
+        } else if (dbVersion.compareTo("2.0.6") >= 0) {
+            /**
+             * Valid for mongodb >= 2.0.6 and < 3.2.0
+             */
+            return "dbexit: really exiting now";
+        }
+        /**
+         * For other versions return empty.
+         */
+        return EMPTY_STRING;
+    }
     
     // package private for testing
     String doGetDBVersion(InputStream in) throws IOException {