git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[JGIT PATCH 6/8] Cleanup after each test.

From
Robin Rosenberg <robin.rosenberg@dewire.com>
Date
Nov 30, 2008, 23:40 UTC
Message-ID
<1228088435-23722-7-git-send-email-robin.rosenberg@dewire.com>
In-Reply-To
<1228088435-23722-6-git-send-email-robin.rosenberg@dewire.com>

Automatically clean up any repositories created by the test cases. Cleanup is attempted at the end of each test, but if that fails Shutdown hooks attempt to clean up when the JVM exits. If memmory mapping is enabled (disabled by default in unit tests), gc is invoked to make it more likely that cleanup will occur successfully. The drawback is that this is much slower, which is the reason we disble memory mapping by default in unit tests.

Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 .../org/spearce/jgit/lib/RepositoryTestCase.java   |   62 ++++++++++++++++----
 1 files changed, 50 insertions(+), 12 deletions(-)
diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java
index 8e23bc1..aaa3592 100644
--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java
+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/RepositoryTestCase.java
@@ -45,6 +45,8 @@
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
 
 import junit.framework.TestCase;
 import org.spearce.jgit.util.JGitTestUtil;
@@ -95,8 +97,8 @@ protected void configure() {
 	 *
 	 * @param dir
 	 */
-	protected static void recursiveDelete(final File dir) {
-		recursiveDelete(dir, false, null);
+	protected void recursiveDelete(final File dir) {
+		recursiveDelete(dir, false, getClass().getName() + "." + getName());
 	}
 
 	protected static boolean recursiveDelete(final File dir, boolean silent,
@@ -170,9 +172,12 @@ protected static void checkFile(File f, final String checkData)
 	}
 
 	protected Repository db;
-
+	private static Thread shutdownhook;
+	private static List<Runnable> shutDownCleanups = new ArrayList<Runnable>();
 	private static int testcount;
 
+	private ArrayList<Repository> repositoriesToClose = new ArrayList<Repository>();
+
 	public void setUp() throws Exception {
 		super.setUp();
 		configure();
@@ -180,14 +185,23 @@ public void setUp() throws Exception {
 		recursiveDelete(trashParent, true, name);
 		trash = new File(trashParent,"trash"+System.currentTimeMillis()+"."+(testcount++));
 		trash_git = new File(trash, ".git");
-
-		Runtime.getRuntime().addShutdownHook(new Thread() {
-			@Override
-			public void run() {
-				recursiveDelete(trashParent, false, name);
-			}
-		});
-
+		if (shutdownhook == null) {
+			shutdownhook = new Thread() {
+				@Override
+				public void run() {
+					// This may look superfluous, but is an extra attempt
+					// to clean up. First GC to release as many resources
+					// as possible and then try to clean up one test repo
+					// at a time (to record problems) and finally to drop
+					// the directory containing all test repositories.
+					System.gc();
+					for (Runnable r : shutDownCleanups)
+						r.run();
+					recursiveDelete(trashParent, false, null);
+				}
+			};
+			Runtime.getRuntime().addShutdownHook(shutdownhook);
+		}
 		db = new Repository(trash_git);
 		db.create();
 
@@ -213,6 +227,22 @@ copyFile(JGitTestUtil.getTestResourceFile(packs[k] + ".idx"), new File(packDir,
 
 	protected void tearDown() throws Exception {
 		db.close();
+		for (Repository r : repositoriesToClose)
+			r.close();
+
+		// Since memory mapping is controlled by the GC we need to
+		// tell it this is a good time to clean up and unlock
+		// memory mapped files.
+		if (packedGitMMAP)
+			System.gc();
+
+		final String name = getClass().getName() + "." + getName();
+		recursiveDelete(trash, false, name);
+		for (Repository r : repositoriesToClose)
+			recursiveDelete(r.getWorkDir(), false, name);
+
+		repositoriesToClose.clear();
+
 		super.tearDown();
 	}
 
@@ -224,10 +254,18 @@ protected void tearDown() throws Exception {
 	 * @throws IOException
 	 */
 	protected Repository createNewEmptyRepo() throws IOException {
-		File newTestRepo = new File(trashParent, "new"+System.currentTimeMillis()+"."+(testcount++)+"/.git");
+		final File newTestRepo = new File(trashParent, "new"
+				+ System.currentTimeMillis() + "." + (testcount++) + "/.git");
 		assertFalse(newTestRepo.exists());
 		final Repository newRepo = new Repository(newTestRepo);
 		newRepo.create();
+		final String name = getClass().getName() + "." + getName();
+		shutDownCleanups.add(new Runnable() {
+			public void run() {
+				recursiveDelete(newTestRepo, false, name);
+			}
+		});
+		repositoriesToClose.add(newRepo);
 		return newRepo;
 	}
 
-- 
1.6.0.3.640.g6331a
Previous: Robin RosenbergNext: Robin Rosenberg
Message 12 of 15 in “RepositoryTestCase cleanups”
  1. 0/4 RepositoryTestCase cleanupsRobin Rosenberg, Nov 27, 2008
  2. Shawn O. PearceNov 27, 2008
  3. Robin RosenbergNov 29, 2008
  4. Johannes SchindelinDec 1, 2008
  5. Robin RosenbergNov 30, 2008
  6. 0/8 Unit test cleanupsRobin Rosenberg, Nov 30, 2008
  7. 1/8 Drop unneeded code in unit testsRobin Rosenberg, Nov 30, 2008
  8. 2/8 Cleanup malformed test casesRobin Rosenberg, Nov 30, 2008
  9. 3/8 Turn off memory mapping in JGit unit tests by defaultRobin Rosenberg, Nov 30, 2008
  10. 4/8 Add a counter to make sure the test repo name is uniqueRobin Rosenberg, Nov 30, 2008
  11. 5/8 Make the cleanup less verbose when it fails to delete temporary stuff.Robin Rosenberg, Nov 30, 2008
  12. 6/8 Cleanup after each test.Robin Rosenberg, Nov 30, 2008
  13. 7/8 Close files opened by unit testing frameworkRobin Rosenberg, Nov 30, 2008
  14. 8/8 Hard failure on unit test cleanups if they fail.Robin Rosenberg, Nov 30, 2008
  15. Shawn O. PearceDec 2, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.