1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.internal.storage.dfs;
45
46 import static org.eclipse.jgit.junit.JGitTestUtil.concat;
47 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
48 import static org.eclipse.jgit.lib.Constants.encodeASCII;
49 import static org.junit.Assert.assertEquals;
50 import static org.junit.Assert.assertNull;
51 import static org.junit.Assert.assertTrue;
52 import static org.junit.Assert.fail;
53
54 import java.io.IOException;
55
56 import org.eclipse.jgit.internal.fsck.FsckError;
57 import org.eclipse.jgit.internal.fsck.FsckError.CorruptObject;
58 import org.eclipse.jgit.junit.TestRepository;
59 import org.eclipse.jgit.lib.Constants;
60 import org.eclipse.jgit.lib.ObjectChecker.ErrorType;
61 import org.eclipse.jgit.lib.ObjectId;
62 import org.eclipse.jgit.lib.ObjectInserter;
63 import org.eclipse.jgit.revwalk.RevCommit;
64 import org.junit.Before;
65 import org.junit.Test;
66
67 public class DfsFsckTest {
68 private TestRepository<InMemoryRepository> git;
69
70 private InMemoryRepository repo;
71
72 private ObjectInserter ins;
73
74 @Before
75 public void setUp() throws IOException {
76 DfsRepositoryDescription desc = new DfsRepositoryDescription("test");
77 git = new TestRepository<>(new InMemoryRepository(desc));
78 repo = git.getRepository();
79 ins = repo.newObjectInserter();
80 }
81
82 @Test
83 public void testHealthyRepo() throws Exception {
84 RevCommit commit0 = git.commit().message("0").create();
85 RevCommit commit1 = git.commit().message("1").parent(commit0).create();
86 git.update("master", commit1);
87
88 DfsFsck fsck = new DfsFsck(repo);
89 FsckError errors = fsck.check(null);
90
91 assertEquals(errors.getCorruptObjects().size(), 0);
92 assertEquals(errors.getMissingObjects().size(), 0);
93 assertEquals(errors.getCorruptIndices().size(), 0);
94 }
95
96 @Test
97 public void testCommitWithCorruptAuthor() throws Exception {
98 StringBuilder b = new StringBuilder();
99 b.append("tree be9bfa841874ccc9f2ef7c48d0c76226f89b7189\n");
100 b.append("author b <b@c> <b@c> 0 +0000\n");
101 b.append("committer <> 0 +0000\n");
102 byte[] data = encodeASCII(b.toString());
103 ObjectId id = ins.insert(Constants.OBJ_COMMIT, data);
104 ins.flush();
105
106 DfsFsck fsck = new DfsFsck(repo);
107 FsckError errors = fsck.check(null);
108
109 assertEquals(errors.getCorruptObjects().size(), 1);
110 CorruptObject o = errors.getCorruptObjects().iterator().next();
111 assertTrue(o.getId().equals(id));
112 assertEquals(o.getErrorType(), ErrorType.BAD_DATE);
113 }
114
115 @Test
116 public void testCommitWithoutTree() throws Exception {
117 StringBuilder b = new StringBuilder();
118 b.append("parent ");
119 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
120 b.append('\n');
121 byte[] data = encodeASCII(b.toString());
122 ObjectId id = ins.insert(Constants.OBJ_COMMIT, data);
123 ins.flush();
124
125 DfsFsck fsck = new DfsFsck(repo);
126 FsckError errors = fsck.check(null);
127
128 assertEquals(errors.getCorruptObjects().size(), 1);
129 CorruptObject o = errors.getCorruptObjects().iterator().next();
130 assertTrue(o.getId().equals(id));
131 assertEquals(o.getErrorType(), ErrorType.MISSING_TREE);
132 }
133
134 @Test
135 public void testTagWithoutObject() throws Exception {
136 StringBuilder b = new StringBuilder();
137 b.append("type commit\n");
138 b.append("tag test-tag\n");
139 b.append("tagger A. U. Thor <author@localhost> 1 +0000\n");
140 byte[] data = encodeASCII(b.toString());
141 ObjectId id = ins.insert(Constants.OBJ_TAG, data);
142 ins.flush();
143
144 DfsFsck fsck = new DfsFsck(repo);
145 FsckError errors = fsck.check(null);
146
147 assertEquals(errors.getCorruptObjects().size(), 1);
148 CorruptObject o = errors.getCorruptObjects().iterator().next();
149 assertTrue(o.getId().equals(id));
150 assertEquals(o.getErrorType(), ErrorType.MISSING_OBJECT);
151 }
152
153 @Test
154 public void testTreeWithNullSha() throws Exception {
155 byte[] data = concat(encodeASCII("100644 A"), new byte[] { '\0' },
156 new byte[OBJECT_ID_LENGTH]);
157 ObjectId id = ins.insert(Constants.OBJ_TREE, data);
158 ins.flush();
159
160 DfsFsck fsck = new DfsFsck(repo);
161 FsckError errors = fsck.check(null);
162
163 assertEquals(errors.getCorruptObjects().size(), 1);
164 CorruptObject o = errors.getCorruptObjects().iterator().next();
165 assertTrue(o.getId().equals(id));
166 assertEquals(o.getErrorType(), ErrorType.NULL_SHA1);
167 }
168
169 @Test
170 public void testMultipleInvalidObjects() throws Exception {
171 StringBuilder b = new StringBuilder();
172 b.append("tree ");
173 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
174 b.append('\n');
175 b.append("parent ");
176 b.append("\n");
177 byte[] data = encodeASCII(b.toString());
178 ObjectId id1 = ins.insert(Constants.OBJ_COMMIT, data);
179
180 b = new StringBuilder();
181 b.append("100644");
182 data = encodeASCII(b.toString());
183 ObjectId id2 = ins.insert(Constants.OBJ_TREE, data);
184
185 ins.flush();
186
187 DfsFsck fsck = new DfsFsck(repo);
188 FsckError errors = fsck.check(null);
189
190 assertEquals(errors.getCorruptObjects().size(), 2);
191 for (CorruptObject o : errors.getCorruptObjects()) {
192 if (o.getId().equals(id1)) {
193 assertEquals(o.getErrorType(), ErrorType.BAD_PARENT_SHA1);
194 } else if (o.getId().equals(id2)) {
195 assertNull(o.getErrorType());
196 } else {
197 fail();
198 }
199 }
200 }
201
202 @Test
203 public void testValidConnectivity() throws Exception {
204 ObjectId blobId = ins
205 .insert(Constants.OBJ_BLOB, Constants.encode("foo"));
206
207 byte[] blobIdBytes = new byte[OBJECT_ID_LENGTH];
208 blobId.copyRawTo(blobIdBytes, 0);
209 byte[] data = concat(encodeASCII("100644 regular-file\0"), blobIdBytes);
210 ObjectId treeId = ins.insert(Constants.OBJ_TREE, data);
211 ins.flush();
212
213 RevCommit commit = git.commit().message("0").setTopLevelTree(treeId)
214 .create();
215
216 git.update("master", commit);
217
218 DfsFsck fsck = new DfsFsck(repo);
219 FsckError errors = fsck.check(null);
220 assertEquals(errors.getMissingObjects().size(), 0);
221 }
222
223 @Test
224 public void testMissingObject() throws Exception {
225 ObjectId blobId = ObjectId
226 .fromString("19102815663d23f8b75a47e7a01965dcdc96468c");
227 byte[] blobIdBytes = new byte[OBJECT_ID_LENGTH];
228 blobId.copyRawTo(blobIdBytes, 0);
229 byte[] data = concat(encodeASCII("100644 regular-file\0"), blobIdBytes);
230 ObjectId treeId = ins.insert(Constants.OBJ_TREE, data);
231 ins.flush();
232
233 RevCommit commit = git.commit().message("0").setTopLevelTree(treeId)
234 .create();
235
236 git.update("master", commit);
237
238 DfsFsck fsck = new DfsFsck(repo);
239 FsckError errors = fsck.check(null);
240 assertEquals(errors.getMissingObjects().size(), 1);
241 assertEquals(errors.getMissingObjects().iterator().next(), blobId);
242 }
243
244 @Test
245 public void testNonCommitHead() throws Exception {
246 RevCommit commit0 = git.commit().message("0").create();
247 StringBuilder b = new StringBuilder();
248 b.append("object ");
249 b.append(commit0.getName());
250 b.append('\n');
251 b.append("type commit\n");
252 b.append("tag test-tag\n");
253 b.append("tagger A. U. Thor <author@localhost> 1 +0000\n");
254
255 byte[] data = encodeASCII(b.toString());
256 ObjectId tagId = ins.insert(Constants.OBJ_TAG, data);
257 ins.flush();
258
259 git.update("master", tagId);
260
261 DfsFsck fsck = new DfsFsck(repo);
262 FsckError errors = fsck.check(null);
263 assertEquals(errors.getCorruptObjects().size(), 0);
264 assertEquals(errors.getNonCommitHeads().size(), 1);
265 assertEquals(errors.getNonCommitHeads().iterator().next(),
266 "refs/heads/master");
267 }
268
269 }