changeset 296:02f2963c70fa

Issue 13: Tests for mixed-cased filenames in case-insensitive FS
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 16 Sep 2011 21:00:29 +0200
parents 981f9f50bb6c
children e7ca6f16d074
files src/org/tmatesoft/hg/repo/HgInternals.java test/org/tmatesoft/hg/test/TestDirstate.java
diffstat 2 files changed, 107 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgInternals.java	Fri Sep 16 05:35:32 2011 +0200
+++ b/src/org/tmatesoft/hg/repo/HgInternals.java	Fri Sep 16 21:00:29 2011 +0200
@@ -55,7 +55,33 @@
 	}
 
 	public void dumpDirstate() {
-		repo.loadDirstate(new PathPool(new PathRewrite.Empty())).dump();
+		getDirstate().dump();
+	}
+	
+	public HgDirstate getDirstate() {
+		return repo.loadDirstate(new PathPool(new PathRewrite.Empty()));
+	}
+	
+	// tests
+	public HgDirstate createDirstate(boolean caseSensitiveFileSystem) {
+		PathRewrite canonicalPath = null;
+		if (!caseSensitiveFileSystem) {
+			canonicalPath = new PathRewrite() {
+
+				public CharSequence rewrite(CharSequence path) {
+					return path.toString().toLowerCase();
+				}
+			};
+		}
+		return new HgDirstate(repo, new File(repo.getRepositoryRoot(), "dirstate"), new PathPool(new PathRewrite.Empty()), canonicalPath);
+	}
+	
+	public Path[] checkKnown(HgDirstate dirstate, Path[] toCheck) {
+		Path[] rv = new Path[toCheck.length];
+		for (int i = 0; i < toCheck.length; i++) {
+			rv[i] = dirstate.known(toCheck[i]);
+		}
+		return rv;
 	}
 
 	public boolean[] checkIgnored(String... toCheck) {
--- a/test/org/tmatesoft/hg/test/TestDirstate.java	Fri Sep 16 05:35:32 2011 +0200
+++ b/test/org/tmatesoft/hg/test/TestDirstate.java	Fri Sep 16 21:00:29 2011 +0200
@@ -16,12 +16,23 @@
  */
 package org.tmatesoft.hg.test;
 
+import static java.lang.Character.*;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.TreeSet;
+
 import org.junit.Assert;
 import org.junit.Test;
 import org.tmatesoft.hg.core.Nodeid;
+import org.tmatesoft.hg.repo.HgDirstate;
+import org.tmatesoft.hg.repo.HgDirstate.EntryKind;
+import org.tmatesoft.hg.repo.HgDirstate.Record;
+import org.tmatesoft.hg.repo.HgInternals;
 import org.tmatesoft.hg.repo.HgLookup;
 import org.tmatesoft.hg.repo.HgRepository;
 import org.tmatesoft.hg.util.Pair;
+import org.tmatesoft.hg.util.Path;
 
 /**
  *
@@ -58,9 +69,77 @@
 		Assert.assertEquals("default", repo.getWorkingCopyBranchName());
 	}
 
-	public void testMixedNameCaseHandling() {
+	@Test
+	public void testMixedNameCaseHandling() throws Exception {
+		// General idea: to check cases like
 		// 1. dirstate: /a/b/c, FileIterator: /a/B/C
 		// 2. dirstate: /a/B/C, FileIterator: /a/b/c
 		// 2. dirstate: /a/B/C, FileIterator: /A/b/C
+		repo = Configuration.get().find("mixed-case");
+		// Windows, case-insensitive file system
+		final HgInternals testAccess = new HgInternals(repo);
+		HgDirstate dirstate = testAccess.createDirstate(false);
+		final TreeSet<Path> entries = new TreeSet<Path>();
+		dirstate.walk(new HgDirstate.Inspector() {
+			
+			public boolean next(EntryKind kind, Record entry) {
+				entries.add(entry.name());
+				return true;
+			}
+		});
+		Path[] expected = new Path[] {
+			Path.create("a/low/low"),
+			Path.create("a/low/UP"),
+			Path.create("a/UP/low"),
+			Path.create("a/UP/UP"),
+		};
+		Path[] allLower = new Path[expected.length];
+		Path[] allUpper = new Path[expected.length];
+		Path[] mixedNonMatching = new Path[expected.length];
+		for (int i = 0; i < expected.length; i++) {
+			assertTrue("prereq", entries.contains(expected[i]));
+			final String s = expected[i].toString();
+			allLower[i] = Path.create(s.toLowerCase());
+			allUpper[i] = Path.create(s.toUpperCase());
+			char[] ss = s.toCharArray();
+			for (int j = 0; j < ss.length; j++) {
+				if (isLetter(ss[j])) {
+					ss[j] = isLowerCase(ss[j]) ? toUpperCase(ss[j]) : toLowerCase(ss[j]);
+				}
+			}
+			Path mixed = Path.create(new String(ss));
+			mixedNonMatching[i] = mixed;
+		}
+		// prereq
+		checkKnownInDirstate(testAccess, dirstate, expected, expected);
+		// all upper
+		checkKnownInDirstate(testAccess, dirstate, allUpper, expected);
+		// all lower
+		checkKnownInDirstate(testAccess, dirstate, allLower, expected);
+		// mixed
+		checkKnownInDirstate(testAccess, dirstate, mixedNonMatching, expected);
+		//
+		// check that in case-sensitive file system mangled names do not match 
+		dirstate = testAccess.createDirstate(true);
+		// ensure read
+		dirstate.walk(new HgDirstate.Inspector() {
+			public boolean next(EntryKind kind, Record entry) {
+				return false;
+			}
+		});
+		Path[] known = testAccess.checkKnown(dirstate, mixedNonMatching);
+		for (int i = 0; i < known.length; i++) {
+			if (known[i] != null) {
+				fail(expected[i] + " in case-sensitive dirstate matched " + known[i]);
+			}
+		}
+		
+	}
+
+	private static void checkKnownInDirstate(HgInternals testAccess, HgDirstate dirstate, Path[] toCheck, Path[] expected) {
+		Path[] known = testAccess.checkKnown(dirstate, toCheck);
+		for (int i = 0; i < expected.length; i++) {
+			assertTrue(expected[i].equals(known[i]));
+		}
 	}
 }