You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by km...@apache.org on 2010/06/22 21:48:05 UTC

svn commit: r957000 - in /db/derby/code/branches/10.6: ./ java/testing/org/apache/derbyTesting/functionTests/master/ java/testing/org/apache/derbyTesting/functionTests/suites/ java/testing/org/apache/derbyTesting/functionTests/tests/store/ java/testing...

Author: kmarsden
Date: Tue Jun 22 19:48:04 2010
New Revision: 957000

URL: http://svn.apache.org/viewvc?rev=957000&view=rev
Log:
DERBY-4179 bootLock.java fails with missing exception if spawned process fails.
DERBY-4667 BootLockTest.testBootLock() sometimes fails with connection refused.

Convert bootLock.java to JUnit
contributed mostly by Dag Wanvik


Added:
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java
      - copied, changed from r942286, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java
      - copied, changed from r942286, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java
Removed:
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/master/bootLock.out
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/bootLock.java
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/bootLock1.java
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/bootLock_app.properties
Modified:
    db/derby/code/branches/10.6/   (props changed)
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/build.xml
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/DatabasePropertyTestSetup.java
    db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java

Propchange: db/derby/code/branches/10.6/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jun 22 19:48:04 2010
@@ -1,2 +1,2 @@
-/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,944152,946794,948045,948069,951346,952138,954344,954421,954544,955001,956234
+/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,942286,942476,942480,942587,944152,946794,948045,948069,951346,952138,954344,954421,954544,955001,956075,956234,956445,956659
 /db/derby/docs/trunk:954344

Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall?rev=957000&r1=956999&r2=957000&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/suites/storemore.runall Tue Jun 22 19:48:04 2010
@@ -22,7 +22,6 @@ store/rollForwardRecovery.sql
 store/readlocks.sql
 store/backupRestore.sql
 store/backupRestore1.java
-store/bootLock.java
 store/bug3498.sql
 store/Beetle6038.java
 store/TestDurabilityProperty.java

Copied: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java (from r942286, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java)
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java?p2=db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java&p1=db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java&r1=942286&r2=957000&rev=957000&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockMinion.java Tue Jun 22 19:48:04 2010
@@ -31,18 +31,14 @@ import org.apache.derby.jdbc.EmbeddedSim
  * Create and boot the supplied db argument. This auxiliary program is used by
  * {@code BootLockTest.java} to boot a db in a different jvm and subsequently
  * attempt a boot to from the original VM to detect dual boot attempt.
-* <p>
- * You can verify this subprogram by invoking it directly as:
- * </p>
- * <p>
- * {@code java org.apache.derbyTesting.functionTests.tests.store.BootLockMinion <dbname>}
- * </p>
+ * <p/>
+ * Started as:
+ * {@code java org.apache.derbyTesting.functionTests.tests.store.BootLockMinion <dbname> <port>}
  */
 
 public class BootLockMinion {
     public static void main(String[] args) {
         String dbName = args[0];
-        int portNumber = Integer.decode(args[1]).intValue();
         Connection con;
         Statement stmt;
         System.setProperty("derby.stream.error.file",
@@ -57,12 +53,6 @@ public class BootLockMinion {
             stmt = con.createStatement();
 
             stmt.execute("create table t1(i int)");
-
-            // Signal to parent that we have booted dbName, so it can try,
-            // too..
-            Socket parentS;
-            parentS = new Socket("localhost", portNumber);
-
             //infinite loop until we get killed by BootLockTest.java
             for(;;)
             {

Copied: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java (from r942286, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java)
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java?p2=db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java&p1=db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java&r1=942286&r2=957000&rev=957000&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/BootLockTest.java Tue Jun 22 19:48:04 2010
@@ -29,6 +29,7 @@ import java.sql.SQLException;
 import java.net.SocketTimeoutException;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.util.Properties;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -38,14 +39,15 @@ import org.apache.derbyTesting.junit.Bas
 import org.apache.derbyTesting.junit.SecurityManagerSetup;
 import org.apache.derbyTesting.junit.TestConfiguration;
 import org.apache.derbyTesting.junit.JDBC;
-import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.SystemPropertyTestSetup;
 
 import org.apache.derby.iapi.store.raw.data.DataFactory;
 
 /**
- * Testing for FileLocks that prevent Derby Double Boot.
+ * Testing file locks that prevent Derby "double boot" a.k.a "dual boot",
+ * i.e. two VMs booting a database concurrently, a disaster scenario.
  * <p/>
- * For Sun phoneME, test that the property {@code
+ * For phoneME, test that the property {@code
  * derby.database.forceDatabaseLock} protects us.
  * <p/>
  * FIXME: If DERBY-4646 is fixed, the special handling for phoneME
@@ -55,10 +57,16 @@ import org.apache.derby.iapi.store.raw.d
 public class BootLockTest extends BaseJDBCTestCase {
 
     private final static String dbName = "BootLockTestDB";
-
+    private final static String dbDir = DEFAULT_DB_DIR + File.separator + dbName;
+    private final static String dbLockFile = dbDir + File.separator +
+    DataFactory.DB_LOCKFILE_NAME;
+    private final static String dbExLockFile = dbDir + File.separator +
+    DataFactory.DB_EX_LOCKFILE_NAME;
+    private final static String servicePropertiesFileName = dbDir + File.separator + "service.properties";
+    
     private static String[] cmd = new String[]{
         "org.apache.derbyTesting.functionTests.tests.store.BootLockMinion",
-        DEFAULT_DB_DIR + File.separator + dbName,
+        dbDir,
         ""
     };
 
@@ -75,10 +83,9 @@ public class BootLockTest extends BaseJD
     }
 
     /**
-     * Creates a suite with two testcases, with and without some extra
-     * system properties.
+     * Creates a suite.
      *
-     * @return The test suite with both English and German locales.
+     * @return The test suite
      */
     public static Test suite() {
         TestSuite suite = new TestSuite("BootLockTest");
@@ -102,179 +109,118 @@ public class BootLockTest extends BaseJD
 
         Test test = new TestSuite(BootLockTest.class);
 
-        test = TestConfiguration.singleUseDatabaseDecorator(test, dbName);
-
-        test = SecurityManagerSetup.noSecurityManager(test);
-
-        return test;
-    }
-
-    String oldPropValue = null;
-
-    protected void setUp() throws Exception {
-
-        super.setUp();
-
-        // For phoneMe, we won't see DATA_MULTIPLE_JBMS_ON_DB, but instead we
-        // can check that we get DATA_MULTIPLE_JBMS_FORCE_LOCK if we set
-        // derby.database.forceDatabaseLock.
-
-        // FIXME: I tried to use the DatabasePropertyTestSetup.singleProperty,
-        // but for some reason it failed to do the job, no matter where in the
-        // decorator stack in decorateTest I placed it. Should be investigated
-        // so this manual set/reset code of the property can be removed.
-
         if (JDBC.vmSupportsJSR169()) {
-            oldPropValue =
-                System.getProperty("derby.database.forceDatabaseLock");
-            System.setProperty("derby.database.forceDatabaseLock", "true");
+            Properties props = new Properties();
+            props.setProperty("derby.database.forceDatabaseLock", "true");
+            test = new SystemPropertyTestSetup(test, props, true);
         }
-    }
-
-
-    protected void tearDown() throws Exception {
-
-        if (JDBC.vmSupportsJSR169()) {
-
-            if (oldPropValue != null) {
-                System.setProperty("derby.database.forceDatabaseLock",
-                                   oldPropValue);
-            } else {
-                // FIXME: Java 1.5 only: improve code when we move to that
-                // source level.
-                // System.clearProperty("derby.database.forceDatabaseLock");
-                System.setProperty("derby.database.forceDatabaseLock",
-                                   "false");
-            }
 
+        test = TestConfiguration.singleUseDatabaseDecorator(test, dbName);
 
-        }
+        test = SecurityManagerSetup.noSecurityManager(test);
 
-        super.tearDown();
+        return test;
     }
 
 
     public void testBootLock() throws Exception {
 
-        ServerSocket parentService = null;
-        Socket clientSocket = null;
-        BufferedReader minionSysErr = null;
         Process p = null;
 
-        try {
-            int port = TestConfiguration.getCurrent().getPort();
-            cmd[2] = (new Integer(port)).toString();
-
-            p = execJavaCmd(cmd);
-
-            // Attempt to catch any errors happening in minion for better test
-            // diagnosis.
-            minionSysErr = new BufferedReader(
-                new InputStreamReader(p.getErrorStream()));
-
-            // Create a socket so we know when subprogram has booted.  Since we
-            // run this test only in embedded mode, (re)use derby server port.
-            parentService = new ServerSocket(port);
-            parentService.setSoTimeout(60000); // max we wait is 60s
-
-            try {
-
-                clientSocket = parentService.accept();
-
-            } catch (SocketTimeoutException e) {
-                p.destroy();
-                p.waitFor();
-
-                StringBuffer failmsg = new StringBuffer();
-                failmsg.append(
-                    "Minion did not start or boot db in 60 seconds.\n" +
-                    "----Minion's stderr:\n");
-
-                String minionErrLine= null ;
-                do {
-                    try {
-                        minionErrLine = minionSysErr.readLine();
-                    } catch (Exception ioe) {
-                        // may not always work, so just bail out.
-                        failmsg.append("could not read minion's stderr");
-                    }
-
-                    if (minionErrLine != null) {
-                        failmsg.append(minionErrLine);
-                    }
-                } while (minionErrLine != null);
-
-                failmsg.append("\n----Minion's stderr ended");
-
-                fail(failmsg.toString());
-            }
-
-            // We now know minion has booted
+        p = execJavaCmd(cmd);
+        waitForMinionBoot(p,60000);
 
+        // We now know minion has booted
 
-            try {
-                Connection c = getConnection();
-                fail("Dual boot not detected: check BootLockMinion.log");
-            } catch (SQLException e) {
-                if (JDBC.vmSupportsJSR169()) {
-                    assertSQLState(
+        try {
+            Connection c = getConnection();
+            fail("Dual boot not detected: check BootLockMinion.log");
+        } catch (SQLException e) {
+            if (JDBC.vmSupportsJSR169()) {
+                assertSQLState(
                         "Dual boot not detected: check BootLockMinion.log",
                         DATA_MULTIPLE_JBMS_FORCE_LOCK,
                         e);
-                } else {
-                    assertSQLState(
+            } else {
+                assertSQLState(
                         "Dual boot not detected: check BootLockMinion.log",
                         DATA_MULTIPLE_JBMS_ON_DB,
                         e);
-                }
             }
+        }
+        finally {
+            if (p!= null) {
+                p.destroy();
+                p.waitFor();
+            }
+        }
+        // Since all went OK, no need to keep the minion log file.
+        File minionLog = new File("BootLockMinion.log");
+        assertTrue(minionLog.delete());
 
-            p.destroy();
-            p.waitFor();
+        if (JDBC.vmSupportsJSR169()) {
+            // Delete lock files so JUnit machinery can clean up the
+            // one-off database without further warnings on System.err
+            // (phoneMe).
+            File db_lockfile_name = new File(dbLockFile);                    
 
-            // Since all went OK, no need to keep the minion log file.
-            File minionLog = new File("BootLockMinion.log");
-            assertTrue(minionLog.delete());
+            File db_ex_lockfile_name = new File(dbExLockFile);                    
 
-        } finally {
-            // Make sure we free up any socket resources
-            if (clientSocket != null) {
-                clientSocket.close();
-            }
+            db_lockfile_name.delete();
+            db_ex_lockfile_name.delete();
+        }
+    }
 
-            if (parentService != null) {
-                parentService.close();
+    private void waitForMinionBoot(Process p, int waitmillis) throws InterruptedException {
+        StringBuffer failmsg = new StringBuffer();
+        // boolean set to true once we find the  lock file
+        File lockFile = new File(dbLockFile);
+        File servicePropertiesFile = new File(servicePropertiesFileName);
+        // Attempt to catch any errors happening in minion for better test
+        // diagnosis.
+        BufferedReader minionSysErr = new BufferedReader(
+            new InputStreamReader(p.getErrorStream()));
+        String minionErrLine= null ;
+        do {
+            if (lockFile.exists() && servicePropertiesFile.exists()) { 
+                // if the lock file is there and service.properties,
+                // the database has booted, return. If we don't check for
+                // service.properties, we may get just an error that the
+                // directory already exists. We'll give a few seconds too
+                // for service.properties to finish writing.
+                Thread.sleep(3000);
+                return;
             }
-
-            if (minionSysErr != null) {
-                minionSysErr.close();
+            // otherwise sleep for a second and try again
+            waitmillis -= 1000;
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                fail(e.getMessage());
+            }
+        } while (waitmillis > 0);
+        
+        // If we got here, the database did not boot. Try to print the error.
+        failmsg.append(
+                "Minion did not start or boot db in 60 seconds.\n" +
+                "----Minion's stderr:\n");
+        do {
+            try {
+                minionErrLine = minionSysErr.readLine();
+            } catch (Exception ioe) {
+                // may not always work, so just bail out.
+                failmsg.append("could not read minion's stderr");
             }
 
-            // Get rid of minion in case test fails, otherwise redundant.
-            if (p != null) {
-                p.destroy();
-                p.waitFor();
+            if (minionErrLine != null) {
+                failmsg.append(minionErrLine);
             }
+        } while (minionErrLine != null);
 
-
-            if (JDBC.vmSupportsJSR169()) {
-                // Delete lock files so JUnit machinery can clean up the
-                // one-off database without further warnings on System.err
-                // (phoneMe).
-                File db_lockfile_name = new File(
-                    DEFAULT_DB_DIR + File.separator +
-                    dbName + File.separator +
-                    DataFactory.DB_LOCKFILE_NAME);
-
-                File db_ex_lockfile_name = new File(
-                    DEFAULT_DB_DIR + File.separator +
-                    dbName + File.separator +
-                    DataFactory.DB_EX_LOCKFILE_NAME);
-
-                db_lockfile_name.delete();
-                db_ex_lockfile_name.delete();
-            }
-        }
+        failmsg.append("\n----Minion's stderr ended");
+        p.destroy();
+        p.waitFor();
+        fail(failmsg.toString());
     }
 
 }

Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java?rev=957000&r1=956999&r2=957000&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java Tue Jun 22 19:48:04 2010
@@ -58,6 +58,7 @@ public class _Suite extends BaseTestCase
         suite.addTest(Derby3625Test.suite());
         suite.addTest(Derby151Test.suite());
         suite.addTest(Derby4676Test.suite());
+        suite.addTest(BootLockTest.suite());
         suite.addTest(PositionedStoreStreamTest.suite());
         suite.addTest(OSReadOnlyTest.suite());
         suite.addTest(BackupRestoreTest.suite());

Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/build.xml
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/build.xml?rev=957000&r1=956999&r2=957000&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/build.xml (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/functionTests/tests/store/build.xml Tue Jun 22 19:48:04 2010
@@ -84,26 +84,6 @@
         <pathelement path="${junit}"/>
       </classpath>
       <include name="${this.dir}/*.java"/>
-      <exclude name="${this.dir}/bootLock.java"/>
-    </javac>
-    <javac
-      source="1.4"
-      target="1.4"
-      bootclasspath="${empty}"
-      nowarn="on"
-      debug="true"
-      depend="${depend}"
-      deprecation="${deprecation}"
-      optimize="${optimize}"
-      proceed="${proceed}"
-      verbose="${verbose}" 
-      srcdir="${derby.testing.src.dir}"
-      destdir="${out.dir}">
-      <classpath>
-        <!--pathelement location="${oro}"/-->
-        <pathelement path="${java14compile.classpath}"/>
-      </classpath>
-      <include name="${this.dir}/bootLock.java"/>
     </javac>
   </target>
 

Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java?rev=957000&r1=956999&r2=957000&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/BaseTestCase.java Tue Jun 22 19:48:04 2010
@@ -526,20 +526,38 @@ public abstract class BaseTestCase
 	    return pr;
 	}
 
-	/**
-         * Return the executable name for spawning java commands.
-         * This will be <path to j9>/j9  for j9 jvms.
-	 * @return full path to java executable.
-         */
-         public static final String getJavaExecutableName() {
-             String vmname = getSystemProperty("com.ibm.oti.vm.exe");
-             if (vmname == null)
-                 vmname = getSystemProperty("java.home") + File.separator + "bin" +
-                 File.separator +"java";
-             return vmname;
-         }
-          
-   
+    /**
+     * Return the executable name for spawning java commands.
+     * This will be <path to j9>/j9  for j9 jvms.
+     * @return full path to java executable.
+     */
+    public static final String getJavaExecutableName() {
+        String vmname = getSystemProperty("com.ibm.oti.vm.exe");
+
+        if (vmname == null) {
+            vmname = getSystemProperty("java.vm.name");
+
+            // Sun phoneME
+            if ("CVM".equals(vmname)) {
+                vmname = getSystemProperty("java.home") +
+                    File.separator + "bin" +
+                    File.separator + "cvm";
+            } else {
+                vmname = getSystemProperty("java.home") +
+                    File.separator + "bin" +
+                    File.separator + "java";
+            }
+        }
+        return vmname;
+    }
+
+    /**
+     * @return true if this is a j9 VM
+     */
+    public static final boolean isJ9Platform() {
+        return getSystemProperty("com.ibm.oti.vm.exe") != null;
+    }
+
    /**
     * Reads output from a process and returns it as a string.
     * This will block until the process terminates.

Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/DatabasePropertyTestSetup.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/DatabasePropertyTestSetup.java?rev=957000&r1=956999&r2=957000&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/DatabasePropertyTestSetup.java (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/DatabasePropertyTestSetup.java Tue Jun 22 19:48:04 2010
@@ -1,6 +1,6 @@
 /*
  *
- * Derby - Class org.apache.derbyTesting.functionTests.util.DatabasePropertyTestSetup
+ * Derby - Class org.apache.derbyTesting.junit.DatabasePropertyTestSetup
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with

Modified: db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java?rev=957000&r1=956999&r2=957000&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java (original)
+++ db/derby/code/branches/10.6/java/testing/org/apache/derbyTesting/junit/TestConfiguration.java Tue Jun 22 19:48:04 2010
@@ -664,6 +664,26 @@ public class TestConfiguration {
         return new DatabaseChangeSetup(new DropDatabaseSetup(test, dbName), dbName, dbName, true);
     }
 
+
+    /**
+     * Decorate a test to use a new database that is created upon the first
+     * connection request to the database and shutdown & deleted at
+     * tearDown. The configuration differs only from the current configuration
+     * by the list of used databases. The generated database name is added at
+     * the end of <code>usedDbNames</code> and assigned as a default database
+     * name.  This decorator expects the database file to be local so it can be
+     * removed.
+     * @param test Test to be decorated
+     * @param dbName We sometimes need to know outside to be able topass it on
+     *               to other VMs/processes.
+     * @return decorated test.
+     */
+    public static TestSetup singleUseDatabaseDecorator(Test test, String dbName)
+    {
+        return new DatabaseChangeSetup(
+            new DropDatabaseSetup(test, dbName), dbName, dbName, true);
+    }
+
     /**
      * Decorate a test to use a new database that is created upon the
      * first connection request to the database and deleted at