View Javadoc
1   /*
2    * Copyright (C) 2008-2009, Google Inc.
3    * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com>
4    * and other copyright owners as documented in the project's IP log.
5    *
6    * This program and the accompanying materials are made available
7    * under the terms of the Eclipse Distribution License v1.0 which
8    * accompanies this distribution, is reproduced below, and is
9    * available at http://www.eclipse.org/org/documents/edl-v10.php
10   *
11   * All rights reserved.
12   *
13   * Redistribution and use in source and binary forms, with or
14   * without modification, are permitted provided that the following
15   * conditions are met:
16   *
17   * - Redistributions of source code must retain the above copyright
18   *   notice, this list of conditions and the following disclaimer.
19   *
20   * - Redistributions in binary form must reproduce the above
21   *   copyright notice, this list of conditions and the following
22   *   disclaimer in the documentation and/or other materials provided
23   *   with the distribution.
24   *
25   * - Neither the name of the Eclipse Foundation, Inc. nor the
26   *   names of its contributors may be used to endorse or promote
27   *   products derived from this software without specific prior
28   *   written permission.
29   *
30   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
31   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
32   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
35   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
37   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43   */
44  
45  package org.eclipse.jgit.dircache;
46  
47  import static org.junit.Assert.assertEquals;
48  import static org.junit.Assert.assertFalse;
49  import static org.junit.Assert.assertNotNull;
50  import static org.junit.Assert.assertNotSame;
51  import static org.junit.Assert.assertSame;
52  import static org.junit.Assert.assertTrue;
53  import static org.junit.Assert.fail;
54  
55  import java.io.File;
56  
57  import org.eclipse.jgit.events.IndexChangedEvent;
58  import org.eclipse.jgit.events.IndexChangedListener;
59  import org.eclipse.jgit.events.ListenerList;
60  import org.eclipse.jgit.junit.RepositoryTestCase;
61  import org.eclipse.jgit.lib.FileMode;
62  import org.eclipse.jgit.lib.ObjectId;
63  import org.junit.Test;
64  
65  public class DirCacheBuilderTest extends RepositoryTestCase {
66  	@Test
67  	public void testBuildEmpty() throws Exception {
68  		{
69  			final DirCache dc = db.lockDirCache();
70  			final DirCacheBuilder b = dc.builder();
71  			assertNotNull(b);
72  			b.finish();
73  			dc.write();
74  			assertTrue(dc.commit());
75  		}
76  		{
77  			final DirCache dc = db.readDirCache();
78  			assertEquals(0, dc.getEntryCount());
79  		}
80  	}
81  
82  	@Test
83  	public void testBuildRejectsUnsetFileMode() throws Exception {
84  		final DirCache dc = DirCache.newInCore();
85  		final DirCacheBuilder b = dc.builder();
86  		assertNotNull(b);
87  
88  		final DirCacheEntry e = new DirCacheEntry("a");
89  		assertEquals(0, e.getRawMode());
90  		try {
91  			b.add(e);
92  			fail("did not reject unset file mode");
93  		} catch (IllegalArgumentException err) {
94  			assertEquals("FileMode not set for path a", err.getMessage());
95  		}
96  	}
97  
98  	@Test
99  	public void testBuildOneFile_FinishWriteCommit() throws Exception {
100 		final String path = "a-file-path";
101 		final FileMode mode = FileMode.REGULAR_FILE;
102 		final long lastModified = 1218123387057L;
103 		final int length = 1342;
104 		final DirCacheEntry entOrig;
105 		{
106 			final DirCache dc = db.lockDirCache();
107 			final DirCacheBuilder b = dc.builder();
108 			assertNotNull(b);
109 
110 			entOrig = new DirCacheEntry(path);
111 			entOrig.setFileMode(mode);
112 			entOrig.setLastModified(lastModified);
113 			entOrig.setLength(length);
114 
115 			assertNotSame(path, entOrig.getPathString());
116 			assertEquals(path, entOrig.getPathString());
117 			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
118 			assertEquals(mode.getBits(), entOrig.getRawMode());
119 			assertEquals(0, entOrig.getStage());
120 			assertEquals(lastModified, entOrig.getLastModified());
121 			assertEquals(length, entOrig.getLength());
122 			assertFalse(entOrig.isAssumeValid());
123 			b.add(entOrig);
124 
125 			b.finish();
126 			assertEquals(1, dc.getEntryCount());
127 			assertSame(entOrig, dc.getEntry(0));
128 
129 			dc.write();
130 			assertTrue(dc.commit());
131 		}
132 		{
133 			final DirCache dc = db.readDirCache();
134 			assertEquals(1, dc.getEntryCount());
135 
136 			final DirCacheEntry entRead = dc.getEntry(0);
137 			assertNotSame(entOrig, entRead);
138 			assertEquals(path, entRead.getPathString());
139 			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
140 			assertEquals(mode.getBits(), entOrig.getRawMode());
141 			assertEquals(0, entOrig.getStage());
142 			assertEquals(lastModified, entOrig.getLastModified());
143 			assertEquals(length, entOrig.getLength());
144 			assertFalse(entOrig.isAssumeValid());
145 		}
146 	}
147 
148 	@Test
149 	public void testBuildOneFile_Commit() throws Exception {
150 		final String path = "a-file-path";
151 		final FileMode mode = FileMode.REGULAR_FILE;
152 		final long lastModified = 1218123387057L;
153 		final int length = 1342;
154 		final DirCacheEntry entOrig;
155 		{
156 			final DirCache dc = db.lockDirCache();
157 			final DirCacheBuilder b = dc.builder();
158 			assertNotNull(b);
159 
160 			entOrig = new DirCacheEntry(path);
161 			entOrig.setFileMode(mode);
162 			entOrig.setLastModified(lastModified);
163 			entOrig.setLength(length);
164 
165 			assertNotSame(path, entOrig.getPathString());
166 			assertEquals(path, entOrig.getPathString());
167 			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
168 			assertEquals(mode.getBits(), entOrig.getRawMode());
169 			assertEquals(0, entOrig.getStage());
170 			assertEquals(lastModified, entOrig.getLastModified());
171 			assertEquals(length, entOrig.getLength());
172 			assertFalse(entOrig.isAssumeValid());
173 			b.add(entOrig);
174 
175 			assertTrue(b.commit());
176 			assertEquals(1, dc.getEntryCount());
177 			assertSame(entOrig, dc.getEntry(0));
178 			assertFalse(new File(db.getDirectory(), "index.lock").exists());
179 		}
180 		{
181 			final DirCache dc = db.readDirCache();
182 			assertEquals(1, dc.getEntryCount());
183 
184 			final DirCacheEntry entRead = dc.getEntry(0);
185 			assertNotSame(entOrig, entRead);
186 			assertEquals(path, entRead.getPathString());
187 			assertEquals(ObjectId.zeroId(), entOrig.getObjectId());
188 			assertEquals(mode.getBits(), entOrig.getRawMode());
189 			assertEquals(0, entOrig.getStage());
190 			assertEquals(lastModified, entOrig.getLastModified());
191 			assertEquals(length, entOrig.getLength());
192 			assertFalse(entOrig.isAssumeValid());
193 		}
194 	}
195 
196 	@Test
197 	public void testBuildOneFile_Commit_IndexChangedEvent()
198 			throws Exception {
199 		final class ReceivedEventMarkerException extends RuntimeException {
200 			private static final long serialVersionUID = 1L;
201 			// empty
202 		}
203 
204 		final String path = "a-file-path";
205 		final FileMode mode = FileMode.REGULAR_FILE;
206 		// "old" date in 2008
207 		final long lastModified = 1218123387057L;
208 		final int length = 1342;
209 		DirCacheEntry entOrig;
210 		boolean receivedEvent = false;
211 
212 		DirCache dc = db.lockDirCache();
213 		IndexChangedListener listener = (IndexChangedEvent event) -> {
214 			throw new ReceivedEventMarkerException();
215 		};
216 
217 		ListenerList l = db.getListenerList();
218 		l.addIndexChangedListener(listener);
219 		DirCacheBuilder b = dc.builder();
220 
221 		entOrig = new DirCacheEntry(path);
222 		entOrig.setFileMode(mode);
223 		entOrig.setLastModified(lastModified);
224 		entOrig.setLength(length);
225 		b.add(entOrig);
226 		try {
227 			b.commit();
228 		} catch (ReceivedEventMarkerException e) {
229 			receivedEvent = true;
230 		}
231 		if (!receivedEvent)
232 			fail("did not receive IndexChangedEvent");
233 
234 		// do the same again, as this doesn't change index compared to first
235 		// round we should get no event this time
236 		dc = db.lockDirCache();
237 		listener = (IndexChangedEvent event) -> {
238 			throw new ReceivedEventMarkerException();
239 		};
240 
241 		l = db.getListenerList();
242 		l.addIndexChangedListener(listener);
243 		b = dc.builder();
244 
245 		entOrig = new DirCacheEntry(path);
246 		entOrig.setFileMode(mode);
247 		entOrig.setLastModified(lastModified);
248 		entOrig.setLength(length);
249 		b.add(entOrig);
250 		try {
251 			b.commit();
252 		} catch (ReceivedEventMarkerException e) {
253 			fail("unexpected IndexChangedEvent");
254 		}
255 	}
256 
257 	@Test
258 	public void testFindSingleFile() throws Exception {
259 		final String path = "a-file-path";
260 		final DirCache dc = db.readDirCache();
261 		final DirCacheBuilder b = dc.builder();
262 		assertNotNull(b);
263 
264 		final DirCacheEntry entOrig = new DirCacheEntry(path);
265 		entOrig.setFileMode(FileMode.REGULAR_FILE);
266 		assertNotSame(path, entOrig.getPathString());
267 		assertEquals(path, entOrig.getPathString());
268 		b.add(entOrig);
269 		b.finish();
270 
271 		assertEquals(1, dc.getEntryCount());
272 		assertSame(entOrig, dc.getEntry(0));
273 		assertEquals(0, dc.findEntry(path));
274 
275 		assertEquals(-1, dc.findEntry("@@-before"));
276 		assertEquals(0, real(dc.findEntry("@@-before")));
277 
278 		assertEquals(-2, dc.findEntry("a-zoo"));
279 		assertEquals(1, real(dc.findEntry("a-zoo")));
280 
281 		assertSame(entOrig, dc.getEntry(path));
282 	}
283 
284 	@Test
285 	public void testAdd_InGitSortOrder() throws Exception {
286 		final DirCache dc = db.readDirCache();
287 
288 		final String[] paths = { "a-", "a.b", "a/b", "a0b" };
289 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
290 		for (int i = 0; i < paths.length; i++) {
291 			ents[i] = new DirCacheEntry(paths[i]);
292 			ents[i].setFileMode(FileMode.REGULAR_FILE);
293 		}
294 
295 		final DirCacheBuilder b = dc.builder();
296 		for (DirCacheEntry ent : ents) {
297 			b.add(ent);
298 		}
299 		b.finish();
300 
301 		assertEquals(paths.length, dc.getEntryCount());
302 		for (int i = 0; i < paths.length; i++) {
303 			assertSame(ents[i], dc.getEntry(i));
304 			assertEquals(paths[i], dc.getEntry(i).getPathString());
305 			assertEquals(i, dc.findEntry(paths[i]));
306 			assertSame(ents[i], dc.getEntry(paths[i]));
307 		}
308 	}
309 
310 	@Test
311 	public void testAdd_ReverseGitSortOrder() throws Exception {
312 		final DirCache dc = db.readDirCache();
313 
314 		final String[] paths = { "a-", "a.b", "a/b", "a0b" };
315 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
316 		for (int i = 0; i < paths.length; i++) {
317 			ents[i] = new DirCacheEntry(paths[i]);
318 			ents[i].setFileMode(FileMode.REGULAR_FILE);
319 		}
320 
321 		final DirCacheBuilder b = dc.builder();
322 		for (int i = ents.length - 1; i >= 0; i--)
323 			b.add(ents[i]);
324 		b.finish();
325 
326 		assertEquals(paths.length, dc.getEntryCount());
327 		for (int i = 0; i < paths.length; i++) {
328 			assertSame(ents[i], dc.getEntry(i));
329 			assertEquals(paths[i], dc.getEntry(i).getPathString());
330 			assertEquals(i, dc.findEntry(paths[i]));
331 			assertSame(ents[i], dc.getEntry(paths[i]));
332 		}
333 	}
334 
335 	@Test
336 	public void testBuilderClear() throws Exception {
337 		final DirCache dc = db.readDirCache();
338 
339 		final String[] paths = { "a-", "a.b", "a/b", "a0b" };
340 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
341 		for (int i = 0; i < paths.length; i++) {
342 			ents[i] = new DirCacheEntry(paths[i]);
343 			ents[i].setFileMode(FileMode.REGULAR_FILE);
344 		}
345 		{
346 			final DirCacheBuilder b = dc.builder();
347 			for (DirCacheEntry ent : ents) {
348 				b.add(ent);
349 			}
350 			b.finish();
351 		}
352 		assertEquals(paths.length, dc.getEntryCount());
353 		{
354 			final DirCacheBuilder b = dc.builder();
355 			b.finish();
356 		}
357 		assertEquals(0, dc.getEntryCount());
358 	}
359 
360 	private static int real(int eIdx) {
361 		if (eIdx < 0)
362 			eIdx = -(eIdx + 1);
363 		return eIdx;
364 	}
365 }