1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.dircache;
12
13 import static java.time.Instant.EPOCH;
14 import static org.junit.Assert.assertArrayEquals;
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertFalse;
17 import static org.junit.Assert.assertSame;
18 import static org.junit.Assert.assertTrue;
19 import static org.junit.Assert.fail;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.security.MessageDigest;
25 import java.time.Instant;
26 import java.util.concurrent.TimeUnit;
27
28 import org.eclipse.jgit.dircache.DirCache.DirCacheVersion;
29 import org.eclipse.jgit.lib.Constants;
30 import org.eclipse.jgit.lib.FileMode;
31 import org.eclipse.jgit.lib.ObjectId;
32 import org.eclipse.jgit.util.MutableInteger;
33 import org.junit.Test;
34
35 public class DirCacheEntryTest {
36 @Test
37 public void testIsValidPath() {
38 assertTrue(isValidPath("a"));
39 assertTrue(isValidPath("a/b"));
40 assertTrue(isValidPath("ab/cd/ef"));
41
42 assertFalse(isValidPath(""));
43 assertFalse(isValidPath("/a"));
44 assertFalse(isValidPath("a//b"));
45 assertFalse(isValidPath("ab/cd//ef"));
46 assertFalse(isValidPath("a/"));
47 assertFalse(isValidPath("ab/cd/ef/"));
48 assertFalse(isValidPath("a\u0000b"));
49 }
50
51 @SuppressWarnings("unused")
52 private static boolean isValidPath(String path) {
53 try {
54 new DirCacheEntry(path);
55 return true;
56 } catch (InvalidPathException e) {
57 return false;
58 }
59 }
60
61 private static void checkPath(DirCacheVersion indexVersion,
62 DirCacheEntry previous, String name) throws IOException {
63 DirCacheEntry dce = new DirCacheEntry(name);
64 long now = System.currentTimeMillis();
65 long anHourAgo = now - TimeUnit.HOURS.toMillis(1);
66 dce.setLastModified(Instant.ofEpochMilli(anHourAgo));
67 ByteArrayOutputStream out = new ByteArrayOutputStream();
68 dce.write(out, indexVersion, previous);
69 byte[] raw = out.toByteArray();
70 MessageDigest md0 = Constants.newMessageDigest();
71 md0.update(raw);
72 ByteArrayInputStream in = new ByteArrayInputStream(raw);
73 MutableInteger infoAt = new MutableInteger();
74 byte[] sharedInfo = new byte[raw.length];
75 MessageDigest md = Constants.newMessageDigest();
76 DirCacheEntry read = new DirCacheEntry(sharedInfo, infoAt, in, md,
77 Instant.ofEpochMilli(now), indexVersion, previous);
78 assertEquals("Paths of length " + name.length() + " should match", name,
79 read.getPathString());
80 assertEquals("Should have been fully read", -1, in.read());
81 assertArrayEquals("Digests should match", md0.digest(),
82 md.digest());
83 }
84
85 @Test
86 public void testLongPath() throws Exception {
87 StringBuilder name = new StringBuilder(4094 + 16);
88 for (int i = 0; i < 4094; i++) {
89 name.append('a');
90 }
91 for (int j = 0; j < 16; j++) {
92 checkPath(DirCacheVersion.DIRC_VERSION_EXTENDED, null,
93 name.toString());
94 name.append('b');
95 }
96 }
97
98 @Test
99 public void testLongPathV4() throws Exception {
100 StringBuilder name = new StringBuilder(4094 + 16);
101 for (int i = 0; i < 4094; i++) {
102 name.append('a');
103 }
104 DirCacheEntry previous = new DirCacheEntry(name.toString());
105 for (int j = 0; j < 16; j++) {
106 checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous,
107 name.toString());
108 name.append('b');
109 }
110 }
111
112 @Test
113 public void testShortPath() throws Exception {
114 StringBuilder name = new StringBuilder(1 + 16);
115 name.append('a');
116 for (int j = 0; j < 16; j++) {
117 checkPath(DirCacheVersion.DIRC_VERSION_EXTENDED, null,
118 name.toString());
119 name.append('b');
120 }
121 }
122
123 @Test
124 public void testShortPathV4() throws Exception {
125 StringBuilder name = new StringBuilder(1 + 16);
126 name.append('a');
127 DirCacheEntry previous = new DirCacheEntry(name.toString());
128 for (int j = 0; j < 16; j++) {
129 checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous,
130 name.toString());
131 name.append('b');
132 }
133 }
134
135 @Test
136 public void testPathV4() throws Exception {
137 StringBuilder name = new StringBuilder();
138 for (int i = 0; i < 20; i++) {
139 name.append('a');
140 }
141 DirCacheEntry previous = new DirCacheEntry(name.toString());
142 for (int j = 0; j < 20; j++) {
143 name.setLength(name.length() - 1);
144 String newName = name.toString() + "bbb";
145 checkPath(DirCacheVersion.DIRC_VERSION_PATHCOMPRESS, previous,
146 newName);
147 }
148 }
149
150 @SuppressWarnings("unused")
151 @Test
152 public void testCreate_ByStringPath() {
153 assertEquals("a", new DirCacheEntry("a").getPathString());
154 assertEquals("a/b", new DirCacheEntry("a/b").getPathString());
155
156 try {
157 new DirCacheEntry("/a");
158 fail("Incorrectly created DirCacheEntry");
159 } catch (IllegalArgumentException err) {
160 assertEquals("Invalid path: /a", err.getMessage());
161 }
162 }
163
164 @SuppressWarnings("unused")
165 @Test
166 public void testCreate_ByStringPathAndStage() {
167 DirCacheEntry e;
168
169 e = new DirCacheEntry("a", 0);
170 assertEquals("a", e.getPathString());
171 assertEquals(0, e.getStage());
172
173 e = new DirCacheEntry("a/b", 1);
174 assertEquals("a/b", e.getPathString());
175 assertEquals(1, e.getStage());
176
177 e = new DirCacheEntry("a/c", 2);
178 assertEquals("a/c", e.getPathString());
179 assertEquals(2, e.getStage());
180
181 e = new DirCacheEntry("a/d", 3);
182 assertEquals("a/d", e.getPathString());
183 assertEquals(3, e.getStage());
184
185 try {
186 new DirCacheEntry("/a", 1);
187 fail("Incorrectly created DirCacheEntry");
188 } catch (IllegalArgumentException err) {
189 assertEquals("Invalid path: /a", err.getMessage());
190 }
191
192 try {
193 new DirCacheEntry("a", -11);
194 fail("Incorrectly created DirCacheEntry");
195 } catch (IllegalArgumentException err) {
196 assertEquals("Invalid stage -11 for path a", err.getMessage());
197 }
198
199 try {
200 new DirCacheEntry("a", 4);
201 fail("Incorrectly created DirCacheEntry");
202 } catch (IllegalArgumentException err) {
203 assertEquals("Invalid stage 4 for path a", err.getMessage());
204 }
205 }
206
207 @Test
208 public void testSetFileMode() {
209 final DirCacheEntry e = new DirCacheEntry("a");
210
211 assertEquals(0, e.getRawMode());
212
213 e.setFileMode(FileMode.REGULAR_FILE);
214 assertSame(FileMode.REGULAR_FILE, e.getFileMode());
215 assertEquals(FileMode.REGULAR_FILE.getBits(), e.getRawMode());
216
217 e.setFileMode(FileMode.EXECUTABLE_FILE);
218 assertSame(FileMode.EXECUTABLE_FILE, e.getFileMode());
219 assertEquals(FileMode.EXECUTABLE_FILE.getBits(), e.getRawMode());
220
221 e.setFileMode(FileMode.SYMLINK);
222 assertSame(FileMode.SYMLINK, e.getFileMode());
223 assertEquals(FileMode.SYMLINK.getBits(), e.getRawMode());
224
225 e.setFileMode(FileMode.GITLINK);
226 assertSame(FileMode.GITLINK, e.getFileMode());
227 assertEquals(FileMode.GITLINK.getBits(), e.getRawMode());
228
229 try {
230 e.setFileMode(FileMode.MISSING);
231 fail("incorrectly accepted FileMode.MISSING");
232 } catch (IllegalArgumentException err) {
233 assertEquals("Invalid mode 0 for path a", err.getMessage());
234 }
235
236 try {
237 e.setFileMode(FileMode.TREE);
238 fail("incorrectly accepted FileMode.TREE");
239 } catch (IllegalArgumentException err) {
240 assertEquals("Invalid mode 40000 for path a", err.getMessage());
241 }
242 }
243
244 @Test
245 public void testSetStage() {
246 DirCacheEntry e = new DirCacheEntry("some/path", DirCacheEntry.STAGE_1);
247 e.setAssumeValid(true);
248 e.setCreationTime(2L);
249 e.setFileMode(FileMode.EXECUTABLE_FILE);
250 e.setLastModified(EPOCH.plusMillis(3L));
251 e.setLength(100L);
252 e.setObjectId(ObjectId
253 .fromString("0123456789012345678901234567890123456789"));
254 e.setUpdateNeeded(true);
255 e.setStage(DirCacheEntry.STAGE_2);
256
257 assertTrue(e.isAssumeValid());
258 assertEquals(2L, e.getCreationTime());
259 assertEquals(
260 ObjectId.fromString("0123456789012345678901234567890123456789"),
261 e.getObjectId());
262 assertEquals(FileMode.EXECUTABLE_FILE, e.getFileMode());
263 assertEquals(EPOCH.plusMillis(3L), e.getLastModifiedInstant());
264 assertEquals(100L, e.getLength());
265 assertEquals(DirCacheEntry.STAGE_2, e.getStage());
266 assertTrue(e.isUpdateNeeded());
267 assertEquals("some/path", e.getPathString());
268
269 e.setStage(DirCacheEntry.STAGE_0);
270
271 assertTrue(e.isAssumeValid());
272 assertEquals(2L, e.getCreationTime());
273 assertEquals(
274 ObjectId.fromString("0123456789012345678901234567890123456789"),
275 e.getObjectId());
276 assertEquals(FileMode.EXECUTABLE_FILE, e.getFileMode());
277 assertEquals(EPOCH.plusMillis(3L), e.getLastModifiedInstant());
278 assertEquals(100L, e.getLength());
279 assertEquals(DirCacheEntry.STAGE_0, e.getStage());
280 assertTrue(e.isUpdateNeeded());
281 assertEquals("some/path", e.getPathString());
282 }
283
284 @Test
285 public void testCopyMetaDataWithStage() {
286 copyMetaDataHelper(false);
287 }
288
289 @Test
290 public void testCopyMetaDataWithoutStage() {
291 copyMetaDataHelper(true);
292 }
293
294 private static void copyMetaDataHelper(boolean keepStage) {
295 DirCacheEntry e = new DirCacheEntry("some/path", DirCacheEntry.STAGE_2);
296 e.setAssumeValid(false);
297 e.setCreationTime(2L);
298 e.setFileMode(FileMode.EXECUTABLE_FILE);
299 e.setLastModified(EPOCH.plusMillis(3L));
300 e.setLength(100L);
301 e.setObjectId(ObjectId
302 .fromString("0123456789012345678901234567890123456789"));
303 e.setUpdateNeeded(true);
304
305 DirCacheEntry f = new DirCacheEntry("someother/path",
306 DirCacheEntry.STAGE_1);
307 f.setAssumeValid(true);
308 f.setCreationTime(10L);
309 f.setFileMode(FileMode.SYMLINK);
310 f.setLastModified(EPOCH.plusMillis(20L));
311 f.setLength(100000000L);
312 f.setObjectId(ObjectId
313 .fromString("1234567890123456789012345678901234567890"));
314 f.setUpdateNeeded(true);
315
316 e.copyMetaData(f, keepStage);
317 assertTrue(e.isAssumeValid());
318 assertEquals(10L, e.getCreationTime());
319 assertEquals(
320 ObjectId.fromString("1234567890123456789012345678901234567890"),
321 e.getObjectId());
322 assertEquals(FileMode.SYMLINK, e.getFileMode());
323 assertEquals(EPOCH.plusMillis(20L), e.getLastModifiedInstant());
324 assertEquals(100000000L, e.getLength());
325 if (keepStage)
326 assertEquals(DirCacheEntry.STAGE_2, e.getStage());
327 else
328 assertEquals(DirCacheEntry.STAGE_1, e.getStage());
329 assertTrue(e.isUpdateNeeded());
330 assertEquals("some/path", e.getPathString());
331 }
332 }