Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java134
1 files changed, 40 insertions, 94 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
index 8d9ccab1bd..6bc8ff78bd 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RacyGitTests.java
@@ -42,93 +42,25 @@
*/
package org.eclipse.jgit.lib;
-import static java.lang.Long.valueOf;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.TreeSet;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.treewalk.FileTreeIterator;
-import org.eclipse.jgit.treewalk.FileTreeIteratorWithTimeControl;
-import org.eclipse.jgit.treewalk.NameConflictTreeWalk;
-import org.eclipse.jgit.util.FileUtils;
+import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import org.junit.Test;
public class RacyGitTests extends RepositoryTestCase {
- @Test
- public void testIterator() throws IllegalStateException, IOException,
- InterruptedException {
- TreeSet<Long> modTimes = new TreeSet<>();
- File lastFile = null;
- for (int i = 0; i < 10; i++) {
- lastFile = new File(db.getWorkTree(), "0." + i);
- FileUtils.createNewFile(lastFile);
- if (i == 5)
- fsTick(lastFile);
- }
- modTimes.add(valueOf(fsTick(lastFile)));
- for (int i = 0; i < 10; i++) {
- lastFile = new File(db.getWorkTree(), "1." + i);
- FileUtils.createNewFile(lastFile);
- }
- modTimes.add(valueOf(fsTick(lastFile)));
- for (int i = 0; i < 10; i++) {
- lastFile = new File(db.getWorkTree(), "2." + i);
- FileUtils.createNewFile(lastFile);
- if (i % 4 == 0)
- fsTick(lastFile);
- }
- FileTreeIteratorWithTimeControl fileIt = new FileTreeIteratorWithTimeControl(
- db, modTimes);
- try (NameConflictTreeWalk tw = new NameConflictTreeWalk(db)) {
- tw.addTree(fileIt);
- tw.setRecursive(true);
- FileTreeIterator t;
- long t0 = 0;
- for (int i = 0; i < 10; i++) {
- assertTrue(tw.next());
- t = tw.getTree(0, FileTreeIterator.class);
- if (i == 0) {
- t0 = t.getEntryLastModified();
- } else {
- assertEquals(t0, t.getEntryLastModified());
- }
- }
- long t1 = 0;
- for (int i = 0; i < 10; i++) {
- assertTrue(tw.next());
- t = tw.getTree(0, FileTreeIterator.class);
- if (i == 0) {
- t1 = t.getEntryLastModified();
- assertTrue(t1 > t0);
- } else {
- assertEquals(t1, t.getEntryLastModified());
- }
- }
- long t2 = 0;
- for (int i = 0; i < 10; i++) {
- assertTrue(tw.next());
- t = tw.getTree(0, FileTreeIterator.class);
- if (i == 0) {
- t2 = t.getEntryLastModified();
- assertTrue(t2 > t1);
- } else {
- assertEquals(t2, t.getEntryLastModified());
- }
- }
- }
- }
@Test
public void testRacyGitDetection() throws Exception {
- TreeSet<Long> modTimes = new TreeSet<>();
- File lastFile;
-
// Reset to force creation of index file
try (Git git = new Git(db)) {
git.reset().call();
@@ -136,45 +68,59 @@ public class RacyGitTests extends RepositoryTestCase {
// wait to ensure that modtimes of the file doesn't match last index
// file modtime
- modTimes.add(valueOf(fsTick(db.getIndexFile())));
+ fsTick(db.getIndexFile());
// create two files
- addToWorkDir("a", "a");
- lastFile = addToWorkDir("b", "b");
+ File a = writeToWorkDir("a", "a");
+ File b = writeToWorkDir("b", "b");
+ assertTrue(a.setLastModified(b.lastModified()));
+ assertTrue(b.setLastModified(b.lastModified()));
// wait to ensure that file-modTimes and therefore index entry modTime
// doesn't match the modtime of index-file after next persistance
- modTimes.add(valueOf(fsTick(lastFile)));
+ fsTick(b);
// now add both files to the index. No racy git expected
- resetIndex(new FileTreeIteratorWithTimeControl(db, modTimes));
+ resetIndex(new FileTreeIterator(db));
assertEquals(
- "[a, mode:100644, time:t0, length:1, content:a]" +
- "[b, mode:100644, time:t0, length:1, content:b]",
+ "[a, mode:100644, time:t0, length:1, content:a]"
+ + "[b, mode:100644, time:t0, length:1, content:b]",
indexState(SMUDGE | MOD_TIME | LENGTH | CONTENT));
- // Remember the last modTime of index file. All modifications times of
- // further modification are translated to this value so it looks that
- // files have been modified in the same time slot as the index file
- modTimes.add(Long.valueOf(db.getIndexFile().lastModified()));
+ // wait to ensure the file 'a' is updated at t1.
+ fsTick(db.getIndexFile());
- // modify one file
- addToWorkDir("a", "a2");
- // now update the index the index. 'a' has to be racily clean -- because
- // it's modification time is exactly the same as the previous index file
- // mod time.
- resetIndex(new FileTreeIteratorWithTimeControl(db, modTimes));
+ // Create a racy git situation. This is a situation that the index is
+ // updated and then a file is modified within the same tick of the
+ // filesystem timestamp resolution. By changing the index file
+ // artificially, we create a fake racy situation.
+ File updatedA = writeToWorkDir("a", "a2");
+ long newLastModified = updatedA.lastModified() + 100;
+ assertTrue(updatedA.setLastModified(newLastModified));
+ resetIndex(new FileTreeIterator(db));
+ assertTrue(db.getIndexFile().setLastModified(newLastModified));
- db.readDirCache();
- // although racily clean a should not be reported as being dirty
+ DirCache dc = db.readDirCache();
+ // check index state: although racily clean a should not be reported as
+ // being dirty since we forcefully reset the index to match the working
+ // tree
assertEquals(
- "[a, mode:100644, time:t1, smudged, length:0, content:a2]" +
- "[b, mode:100644, time:t0, length:1, content:b]",
- indexState(SMUDGE|MOD_TIME|LENGTH|CONTENT));
+ "[a, mode:100644, time:t1, smudged, length:0, content:a2]"
+ + "[b, mode:100644, time:t0, length:1, content:b]",
+ indexState(SMUDGE | MOD_TIME | LENGTH | CONTENT));
+
+ // compare state of files in working tree with index to check that
+ // FileTreeIterator.isModified() works as expected
+ FileTreeIterator f = new FileTreeIterator(db.getWorkTree(), db.getFS(),
+ db.getConfig().get(WorkingTreeOptions.KEY));
+ assertTrue(f.findFile("a"));
+ try (ObjectReader reader = db.newObjectReader()) {
+ assertFalse(f.isModified(dc.getEntry("a"), false, reader));
+ }
}
- private File addToWorkDir(String path, String content) throws IOException {
+ private File writeToWorkDir(String path, String content) throws IOException {
File f = new File(db.getWorkTree(), path);
try (FileOutputStream fos = new FileOutputStream(f)) {
fos.write(content.getBytes(Constants.CHARACTER_ENCODING));

Back to the top