View Javadoc
1   /*
2    * Copyright (C) 2008-2009, Google Inc.
3    * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com> and others
4    *
5    * This program and the accompanying materials are made available under the
6    * terms of the Eclipse Distribution License v. 1.0 which is available at
7    * https://www.eclipse.org/org/documents/edl-v10.php.
8    *
9    * SPDX-License-Identifier: BSD-3-Clause
10   */
11  
12  package org.eclipse.jgit.dircache;
13  
14  import static org.junit.Assert.assertEquals;
15  import static org.junit.Assert.assertFalse;
16  import static org.junit.Assert.assertNotNull;
17  import static org.junit.Assert.assertNotSame;
18  import static org.junit.Assert.assertSame;
19  import static org.junit.Assert.assertTrue;
20  import static org.junit.Assert.fail;
21  
22  import java.io.File;
23  import java.time.Instant;
24  
25  import org.eclipse.jgit.events.IndexChangedEvent;
26  import org.eclipse.jgit.events.IndexChangedListener;
27  import org.eclipse.jgit.events.ListenerList;
28  import org.eclipse.jgit.junit.RepositoryTestCase;
29  import org.eclipse.jgit.lib.FileMode;
30  import org.eclipse.jgit.lib.ObjectId;
31  import org.junit.Test;
32  
33  public class DirCacheBuilderTest extends RepositoryTestCase {
34  	@Test
35  	public void testBuildEmpty() throws Exception {
36  		{
37  			final DirCache dc = db.lockDirCache();
38  			final DirCacheBuilder b = dc.builder();
39  			assertNotNull(b);
40  			b.finish();
41  			dc.write();
42  			assertTrue(dc.commit());
43  		}
44  		{
45  			final DirCache dc = db.readDirCache();
46  			assertEquals(0, dc.getEntryCount());
47  		}
48  	}
49  
50  	@Test
51  	public void testBuildRejectsUnsetFileMode() throws Exception {
52  		final DirCache dc = DirCache.newInCore();
53  		final DirCacheBuilder b = dc.builder();
54  		assertNotNull(b);
55  
56  		final DirCacheEntry e = new DirCacheEntry("a");
57  		assertEquals(0, e.getRawMode());
58  		try {
59  			b.add(e);
60  			fail("did not reject unset file mode");
61  		} catch (IllegalArgumentException err) {
62  			assertEquals("FileMode not set for path a", err.getMessage());
63  		}
64  	}
65  
66  	@Test
67  	public void testBuildOneFile_FinishWriteCommit() throws Exception {
68  		final String path = "a-file-path";
69  		final FileMode mode = FileMode.REGULAR_FILE;
70  		final Instant lastModified = Instant.ofEpochMilli(1218123387057L);
71  		final int length = 1342;
72  		final DirCacheEntry entOrig;
73  		{
74  			final DirCache dc = db.lockDirCache();
75  			final DirCacheBuilder b = dc.builder();
76  			assertNotNull(b);
77  
78  			entOrig = new DirCacheEntry(path);
79  			entOrig.setFileMode(mode);
80  			entOrig.setLastModified(lastModified);
81  			entOrig.setLength(length);
82  
83  			assertNotSame(path, entOrig.getPathString());
84  			assertEquals(path, entOrig.getPathString());
85  			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
86  			assertEquals(mode.getBits(), entOrig.getRawMode());
87  			assertEquals(0, entOrig.getStage());
88  			assertEquals(lastModified, entOrig.getLastModifiedInstant());
89  			assertEquals(length, entOrig.getLength());
90  			assertFalse(entOrig.isAssumeValid());
91  			b.add(entOrig);
92  
93  			b.finish();
94  			assertEquals(1, dc.getEntryCount());
95  			assertSame(entOrig, dc.getEntry(0));
96  
97  			dc.write();
98  			assertTrue(dc.commit());
99  		}
100 		{
101 			final DirCache dc = db.readDirCache();
102 			assertEquals(1, dc.getEntryCount());
103 
104 			final DirCacheEntry entRead = dc.getEntry(0);
105 			assertNotSame(entOrig, entRead);
106 			assertEquals(path, entRead.getPathString());
107 			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
108 			assertEquals(mode.getBits(), entOrig.getRawMode());
109 			assertEquals(0, entOrig.getStage());
110 			assertEquals(lastModified, entOrig.getLastModifiedInstant());
111 			assertEquals(length, entOrig.getLength());
112 			assertFalse(entOrig.isAssumeValid());
113 		}
114 	}
115 
116 	@Test
117 	public void testBuildOneFile_Commit() throws Exception {
118 		final String path = "a-file-path";
119 		final FileMode mode = FileMode.REGULAR_FILE;
120 		final Instant lastModified = Instant.ofEpochMilli(1218123387057L);
121 		final int length = 1342;
122 		final DirCacheEntry entOrig;
123 		{
124 			final DirCache dc = db.lockDirCache();
125 			final DirCacheBuilder b = dc.builder();
126 			assertNotNull(b);
127 
128 			entOrig = new DirCacheEntry(path);
129 			entOrig.setFileMode(mode);
130 			entOrig.setLastModified(lastModified);
131 			entOrig.setLength(length);
132 
133 			assertNotSame(path, entOrig.getPathString());
134 			assertEquals(path, entOrig.getPathString());
135 			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
136 			assertEquals(mode.getBits(), entOrig.getRawMode());
137 			assertEquals(0, entOrig.getStage());
138 			assertEquals(lastModified, entOrig.getLastModifiedInstant());
139 			assertEquals(length, entOrig.getLength());
140 			assertFalse(entOrig.isAssumeValid());
141 			b.add(entOrig);
142 
143 			assertTrue(b.commit());
144 			assertEquals(1, dc.getEntryCount());
145 			assertSame(entOrig, dc.getEntry(0));
146 			assertFalse(new File(db.getDirectory(), "index.lock").exists());
147 		}
148 		{
149 			final DirCache dc = db.readDirCache();
150 			assertEquals(1, dc.getEntryCount());
151 
152 			final DirCacheEntry entRead = dc.getEntry(0);
153 			assertNotSame(entOrig, entRead);
154 			assertEquals(path, entRead.getPathString());
155 			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
156 			assertEquals(mode.getBits(), entOrig.getRawMode());
157 			assertEquals(0, entOrig.getStage());
158 			assertEquals(lastModified, entOrig.getLastModifiedInstant());
159 			assertEquals(length, entOrig.getLength());
160 			assertFalse(entOrig.isAssumeValid());
161 		}
162 	}
163 
164 	@Test
165 	public void testBuildOneFile_Commit_IndexChangedEvent()
166 			throws Exception {
167 		final class ReceivedEventMarkerException extends RuntimeException {
168 			private static final long serialVersionUID = 1L;
169 			// empty
170 		}
171 
172 		final String path = "a-file-path";
173 		final FileMode mode = FileMode.REGULAR_FILE;
174 		// "old" date in 2008
175 		final Instant lastModified = Instant.ofEpochMilli(1218123387057L);
176 		final int length = 1342;
177 		DirCacheEntry entOrig;
178 		boolean receivedEvent = false;
179 
180 		DirCache dc = db.lockDirCache();
181 		IndexChangedListener listener = (IndexChangedEvent event) -> {
182 			throw new ReceivedEventMarkerException();
183 		};
184 
185 		ListenerList l = db.getListenerList();
186 		l.addIndexChangedListener(listener);
187 		DirCacheBuilder b = dc.builder();
188 
189 		entOrig = new DirCacheEntry(path);
190 		entOrig.setFileMode(mode);
191 		entOrig.setLastModified(lastModified);
192 		entOrig.setLength(length);
193 		b.add(entOrig);
194 		try {
195 			b.commit();
196 		} catch (ReceivedEventMarkerException e) {
197 			receivedEvent = true;
198 		}
199 		if (!receivedEvent)
200 			fail("did not receive IndexChangedEvent");
201 
202 		// do the same again, as this doesn't change index compared to first
203 		// round we should get no event this time
204 		dc = db.lockDirCache();
205 		listener = (IndexChangedEvent event) -> {
206 			throw new ReceivedEventMarkerException();
207 		};
208 
209 		l = db.getListenerList();
210 		l.addIndexChangedListener(listener);
211 		b = dc.builder();
212 
213 		entOrig = new DirCacheEntry(path);
214 		entOrig.setFileMode(mode);
215 		entOrig.setLastModified(lastModified);
216 		entOrig.setLength(length);
217 		b.add(entOrig);
218 		try {
219 			b.commit();
220 		} catch (ReceivedEventMarkerException e) {
221 			fail("unexpected IndexChangedEvent");
222 		}
223 	}
224 
225 	@Test
226 	public void testFindSingleFile() throws Exception {
227 		final String path = "a-file-path";
228 		final DirCache dc = db.readDirCache();
229 		final DirCacheBuilder b = dc.builder();
230 		assertNotNull(b);
231 
232 		final DirCacheEntry entOrig = new DirCacheEntry(path);
233 		entOrig.setFileMode(FileMode.REGULAR_FILE);
234 		assertNotSame(path, entOrig.getPathString());
235 		assertEquals(path, entOrig.getPathString());
236 		b.add(entOrig);
237 		b.finish();
238 
239 		assertEquals(1, dc.getEntryCount());
240 		assertSame(entOrig, dc.getEntry(0));
241 		assertEquals(0, dc.findEntry(path));
242 
243 		assertEquals(-1, dc.findEntry("@@-before"));
244 		assertEquals(0, real(dc.findEntry("@@-before")));
245 
246 		assertEquals(-2, dc.findEntry("a-zoo"));
247 		assertEquals(1, real(dc.findEntry("a-zoo")));
248 
249 		assertSame(entOrig, dc.getEntry(path));
250 	}
251 
252 	@Test
253 	public void testAdd_InGitSortOrder() throws Exception {
254 		final DirCache dc = db.readDirCache();
255 
256 		final String[] paths = { "a-", "a.b", "a/b", "a0b" };
257 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
258 		for (int i = 0; i < paths.length; i++) {
259 			ents[i] = new DirCacheEntry(paths[i]);
260 			ents[i].setFileMode(FileMode.REGULAR_FILE);
261 		}
262 
263 		final DirCacheBuilder b = dc.builder();
264 		for (DirCacheEntry ent : ents) {
265 			b.add(ent);
266 		}
267 		b.finish();
268 
269 		assertEquals(paths.length, dc.getEntryCount());
270 		for (int i = 0; i < paths.length; i++) {
271 			assertSame(ents[i], dc.getEntry(i));
272 			assertEquals(paths[i], dc.getEntry(i).getPathString());
273 			assertEquals(i, dc.findEntry(paths[i]));
274 			assertSame(ents[i], dc.getEntry(paths[i]));
275 		}
276 	}
277 
278 	@Test
279 	public void testAdd_ReverseGitSortOrder() throws Exception {
280 		final DirCache dc = db.readDirCache();
281 
282 		final String[] paths = { "a-", "a.b", "a/b", "a0b" };
283 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
284 		for (int i = 0; i < paths.length; i++) {
285 			ents[i] = new DirCacheEntry(paths[i]);
286 			ents[i].setFileMode(FileMode.REGULAR_FILE);
287 		}
288 
289 		final DirCacheBuilder b = dc.builder();
290 		for (int i = ents.length - 1; i >= 0; i--)
291 			b.add(ents[i]);
292 		b.finish();
293 
294 		assertEquals(paths.length, dc.getEntryCount());
295 		for (int i = 0; i < paths.length; i++) {
296 			assertSame(ents[i], dc.getEntry(i));
297 			assertEquals(paths[i], dc.getEntry(i).getPathString());
298 			assertEquals(i, dc.findEntry(paths[i]));
299 			assertSame(ents[i], dc.getEntry(paths[i]));
300 		}
301 	}
302 
303 	@Test
304 	public void testBuilderClear() throws Exception {
305 		final DirCache dc = db.readDirCache();
306 
307 		final String[] paths = { "a-", "a.b", "a/b", "a0b" };
308 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
309 		for (int i = 0; i < paths.length; i++) {
310 			ents[i] = new DirCacheEntry(paths[i]);
311 			ents[i].setFileMode(FileMode.REGULAR_FILE);
312 		}
313 		{
314 			final DirCacheBuilder b = dc.builder();
315 			for (DirCacheEntry ent : ents) {
316 				b.add(ent);
317 			}
318 			b.finish();
319 		}
320 		assertEquals(paths.length, dc.getEntryCount());
321 		{
322 			final DirCacheBuilder b = dc.builder();
323 			b.finish();
324 		}
325 		assertEquals(0, dc.getEntryCount());
326 	}
327 
328 	private static int real(int eIdx) {
329 		if (eIdx < 0)
330 			eIdx = -(eIdx + 1);
331 		return eIdx;
332 	}
333 }