]> source.dussan.org Git - jgit.git/commitdiff
Fix hardcoded use of target/trash in LocalDiskRepositoryTestCase 68/12668/3
authorShawn Pearce <spearce@spearce.org>
Thu, 9 May 2013 00:34:47 +0000 (17:34 -0700)
committerShawn Pearce <spearce@spearce.org>
Thu, 9 May 2013 00:59:34 +0000 (17:59 -0700)
`pwd`/target is only valid in Maven Reactor builds where Maven
has moved into the project directory and created a target for
the build output. Most other build systems do not use "target"
and may not even perform a directory change between test suites.

Rewrite LocalDiskRepositoryTestCase's temporary directory code
to use the system specified location and create new unique names.
This prevents fixes between concurrently running tests and allows
the caller to specify the root using java.io.tmpdir.

Update the surefire command lines to use target within each project as
the system temporary directory during unit testing, preventing JGit's
own test suite from writing to /tmp or somewhere like C:\tmp.

Change-Id: I9e8431f6ddfc16fee89f677bcce67c99cfb56782

org.eclipse.jgit.ant.test/pom.xml
org.eclipse.jgit.java7.test/pom.xml
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java
org.eclipse.jgit.test/pom.xml
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RepositorySetupWorkDirTest.java

index ee51ec04320d136679aaa3da436a401bf9b084cd..f9204d90366906f66f9a707c83e1687252dcb1c7 100644 (file)
@@ -94,7 +94,7 @@
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>-Xmx256m -Dfile.encoding=UTF-8</argLine>
+          <argLine>-Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine>
         </configuration>
       </plugin>
     </plugins>
index c395669e389f9cfcd308f83f15591fe852234043..5dce6dad3f234763a68c10235fb25268ae7e01aa 100644 (file)
       <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
-         <argLine>-Xmx256m -Dfile.encoding=UTF-8</argLine>
+         <argLine>-Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine>
        </configuration>
       </plugin>
     </plugins>
index 565f934f3c962492f9985d6196b00f2dd51be446..d2b49e842768e48bd6b2bd3defc7958a2fae2678 100644 (file)
@@ -89,10 +89,6 @@ import org.junit.Before;
  * descriptors or address space for the test process.
  */
 public abstract class LocalDiskRepositoryTestCase {
-       private static Thread shutdownHook;
-
-       private static int testCount;
-
        private static final boolean useMMAP = "true".equals(System
                        .getProperty("jgit.junit.usemmap"));
 
@@ -102,36 +98,20 @@ public abstract class LocalDiskRepositoryTestCase {
        /** A fake (but stable) identity for committer fields in the test. */
        protected PersonIdent committer;
 
-       private final File trash = new File(new File("target"), "trash");
-
        private final List<Repository> toClose = new ArrayList<Repository>();
+       private File tmp;
 
        private MockSystemReader mockSystemReader;
 
        @Before
        public void setUp() throws Exception {
-
-               synchronized(this) {
-                       if (shutdownHook == null) {
-                               shutdownHook = new Thread() {
-                                       @Override
-                                       public void run() {
-                                               // On windows accidentally open files or memory
-                                               // mapped regions may prevent files from being deleted.
-                                               // Suggesting a GC increases the likelihood that our
-                                               // test repositories actually get removed after the
-                                               // tests, even in the case of failure.
-                                               System.gc();
-                                               recursiveDelete("SHUTDOWN", trash, false, false);
-                                       }
-                               };
-                               Runtime.getRuntime().addShutdownHook(shutdownHook);
-                       }
-               }
-               recursiveDelete(testId(), trash, true, false);
+               tmp = File.createTempFile("jgit_test_", "_tmp");
+               CleanupThread.deleteOnShutdown(tmp);
+               if (!tmp.delete() || !tmp.mkdir())
+                       throw new IOException("Cannot create " + tmp);
 
                mockSystemReader = new MockSystemReader();
-               mockSystemReader.userGitConfig = new FileBasedConfig(new File(trash,
+               mockSystemReader.userGitConfig = new FileBasedConfig(new File(tmp,
                                "usergitconfig"), FS.DETECTED);
                ceilTestDirectories(getCeilings());
                SystemReader.setInstance(mockSystemReader);
@@ -152,9 +132,12 @@ public abstract class LocalDiskRepositoryTestCase {
                c.install();
        }
 
+       protected File getTemporaryDirectory() {
+               return tmp.getAbsoluteFile();
+       }
 
        protected List<File> getCeilings() {
-               return Collections.singletonList(trash.getParentFile().getAbsoluteFile());
+               return Collections.singletonList(getTemporaryDirectory());
        }
 
        private void ceilTestDirectories(List<File> ceilings) {
@@ -184,8 +167,10 @@ public abstract class LocalDiskRepositoryTestCase {
                //
                if (useMMAP)
                        System.gc();
-
-               recursiveDelete(testId(), trash, false, true);
+               if (tmp != null)
+                       recursiveDelete(tmp, false, true);
+               if (tmp != null && !tmp.exists())
+                       CleanupThread.removed(tmp);
        }
 
        /** Increment the {@link #author} and {@link #committer} times. */
@@ -206,11 +191,11 @@ public abstract class LocalDiskRepositoryTestCase {
         *            the recursively directory to delete, if present.
         */
        protected void recursiveDelete(final File dir) {
-               recursiveDelete(testId(), dir, false, true);
+               recursiveDelete(dir, false, true);
        }
 
-       private static boolean recursiveDelete(final String testName,
-                       final File dir, boolean silent, boolean failOnError) {
+       private static boolean recursiveDelete(final File dir,
+                       boolean silent, boolean failOnError) {
                assert !(silent && failOnError);
                if (!dir.exists())
                        return silent;
@@ -219,31 +204,24 @@ public abstract class LocalDiskRepositoryTestCase {
                        for (int k = 0; k < ls.length; k++) {
                                final File e = ls[k];
                                if (e.isDirectory())
-                                       silent = recursiveDelete(testName, e, silent, failOnError);
+                                       silent = recursiveDelete(e, silent, failOnError);
                                else if (!e.delete()) {
                                        if (!silent)
-                                               reportDeleteFailure(testName, failOnError, e);
+                                               reportDeleteFailure(failOnError, e);
                                        silent = !failOnError;
                                }
                        }
                if (!dir.delete()) {
                        if (!silent)
-                               reportDeleteFailure(testName, failOnError, dir);
+                               reportDeleteFailure(failOnError, dir);
                        silent = !failOnError;
                }
                return silent;
        }
 
-       private static void reportDeleteFailure(final String testName,
-                       final boolean failOnError, final File e) {
-               final String severity;
-               if (failOnError)
-                       severity = "ERROR";
-               else
-                       severity = "WARNING";
-
-               final String msg = severity + ": Failed to delete " + e + " in "
-                               + testName;
+       private static void reportDeleteFailure(boolean failOnError, File e) {
+               String severity = failOnError ? "ERROR" : "WARNING";
+               String msg = severity + ": Failed to delete " + e;
                if (failOnError)
                        fail(msg);
                else
@@ -302,10 +280,6 @@ public abstract class LocalDiskRepositoryTestCase {
                toClose.add(r);
        }
 
-       private static String createUniqueTestFolderPrefix() {
-               return "test" + (System.currentTimeMillis() + "_" + (testCount++));
-       }
-
        /**
         * Creates a unique directory for a test
         *
@@ -315,9 +289,7 @@ public abstract class LocalDiskRepositoryTestCase {
         * @throws IOException
         */
        protected File createTempDirectory(String name) throws IOException {
-               String gitdirName = createUniqueTestFolderPrefix();
-               File parent = new File(trash, gitdirName);
-               File directory = new File(parent, name);
+               File directory = new File(createTempFile(), name);
                FileUtils.mkdirs(directory);
                return directory.getCanonicalFile();
        }
@@ -332,16 +304,31 @@ public abstract class LocalDiskRepositoryTestCase {
         * @throws IOException
         */
        protected File createUniqueTestGitDir(boolean bare) throws IOException {
-               String gitdirName = createUniqueTestFolderPrefix();
+               String gitdirName = createTempFile().getPath();
                if (!bare)
                        gitdirName += "/";
-               gitdirName += Constants.DOT_GIT;
-               File gitdir = new File(trash, gitdirName);
-               return gitdir.getCanonicalFile();
+               return new File(gitdirName + Constants.DOT_GIT);
        }
 
+       /**
+        * Allocates a new unique file path that does not exist.
+        * <p>
+        * Unlike the standard {@code File.createTempFile} the returned path does
+        * not exist, but may be created by another thread in a race with the
+        * caller. Good luck.
+        * <p>
+        * This method is inherently unsafe due to a race condition between creating
+        * the name and the first use that reserves it.
+        *
+        * @return a unique path that does not exist.
+        * @throws IOException
+        */
        protected File createTempFile() throws IOException {
-               return new File(trash, "tmp-" + UUID.randomUUID()).getCanonicalFile();
+               File p = File.createTempFile("tmp_", "", tmp);
+               if (!p.delete()) {
+                       throw new IOException("Cannot obtain unique path " + tmp);
+               }
+               return p;
        }
 
        /**
@@ -399,7 +386,7 @@ public abstract class LocalDiskRepositoryTestCase {
         *             the file could not be written.
         */
        protected File write(final String body) throws IOException {
-               final File f = File.createTempFile("temp", "txt", trash);
+               final File f = File.createTempFile("temp", "txt", tmp);
                try {
                        write(f, body);
                        return f;
@@ -449,8 +436,41 @@ public abstract class LocalDiskRepositoryTestCase {
                return new HashMap<String, String>(System.getenv());
        }
 
-       private String testId() {
-               return getClass().getName() + "." + testCount;
-       }
+       private static final class CleanupThread extends Thread {
+               private static final CleanupThread me;
+               static {
+                       me = new CleanupThread();
+                       Runtime.getRuntime().addShutdownHook(me);
+               }
 
+               static void deleteOnShutdown(File tmp) {
+                       synchronized (me) {
+                               me.toDelete.add(tmp);
+                       }
+               }
+
+               static void removed(File tmp) {
+                       synchronized (me) {
+                               me.toDelete.remove(tmp);
+                       }
+               }
+
+               private final List<File> toDelete = new ArrayList<File>();
+
+               @Override
+               public void run() {
+                       // On windows accidentally open files or memory
+                       // mapped regions may prevent files from being deleted.
+                       // Suggesting a GC increases the likelihood that our
+                       // test repositories actually get removed after the
+                       // tests, even in the case of failure.
+                       System.gc();
+                       synchronized (this) {
+                               boolean silent = false;
+                               boolean failOnError = false;
+                               for (File tmp : toDelete)
+                                       recursiveDelete(tmp, silent, failOnError);
+                       }
+               }
+       }
 }
index 4d9eae99b82af42b3166706d53aef46a2591aea8..c794102667d4e4dc014c556b6d17bf359f4d9426 100644 (file)
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>-Xmx256m -Dfile.encoding=UTF-8</argLine>
+          <argLine>-Xmx256m -Dfile.encoding=UTF-8 -Djava.io.tmpdir=${project.build.directory}</argLine>
         </configuration>
       </plugin>
     </plugins>
index bc47782ea01099eaf8a23c7771b174169a012364..295ef45a79b83f9819cb4f899575b5b4c6e820f3 100644 (file)
@@ -187,16 +187,15 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
                }
        }
 
-       private static File getFile(String... pathComponents) throws IOException {
-               String rootPath = new File(new File("target"), "trash").getPath();
+       private File getFile(String... pathComponents) throws IOException {
+               File dir = getTemporaryDirectory();
                for (String pathComponent : pathComponents)
-                       rootPath = rootPath + File.separatorChar + pathComponent;
-               File result = new File(rootPath);
-               FileUtils.mkdirs(result, true);
-               return result;
+                       dir = new File(dir, pathComponent);
+               FileUtils.mkdirs(dir, true);
+               return dir;
        }
 
-       private static void setBare(File gitDir, boolean bare) throws IOException,
+       private void setBare(File gitDir, boolean bare) throws IOException,
                        ConfigInvalidException {
                FileBasedConfig cfg = configFor(gitDir);
                cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
@@ -204,7 +203,7 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
                cfg.save();
        }
 
-       private static void setWorkTree(File gitDir, File workTree)
+       private void setWorkTree(File gitDir, File workTree)
                        throws IOException,
                        ConfigInvalidException {
                String path = workTree.getAbsolutePath();
@@ -214,7 +213,7 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
                cfg.save();
        }
 
-       private static FileBasedConfig configFor(File gitDir) throws IOException,
+       private FileBasedConfig configFor(File gitDir) throws IOException,
                        ConfigInvalidException {
                File configPath = new File(gitDir, Constants.CONFIG);
                FileBasedConfig cfg = new FileBasedConfig(configPath, FS.DETECTED);
@@ -222,14 +221,14 @@ public class RepositorySetupWorkDirTest extends LocalDiskRepositoryTestCase {
                return cfg;
        }
 
-       private static void assertGitdirPath(Repository repo, String... expected)
+       private void assertGitdirPath(Repository repo, String... expected)
                        throws IOException {
                File exp = getFile(expected).getCanonicalFile();
                File act = repo.getDirectory().getCanonicalFile();
                assertEquals("Wrong Git Directory", exp, act);
        }
 
-       private static void assertWorkdirPath(Repository repo, String... expected)
+       private void assertWorkdirPath(Repository repo, String... expected)
                        throws IOException {
                File exp = getFile(expected).getCanonicalFile();
                File act = repo.getWorkTree().getCanonicalFile();