]> git.proxmox.com Git - libgit2.git/blame - tests/index/tests.c
Merge pull request #2261 from jacquesg/format-patch
[libgit2.git] / tests / index / tests.c
CommitLineData
6c106eec
BS
1#include "clar_libgit2.h"
2#include "index.h"
3
a8122b5d
RB
4static const size_t index_entry_count = 109;
5static const size_t index_entry_count_2 = 1437;
6c106eec
BS
6#define TEST_INDEX_PATH cl_fixture("testrepo.git/index")
7#define TEST_INDEX2_PATH cl_fixture("gitgit.index")
8#define TEST_INDEXBIG_PATH cl_fixture("big.index")
3d523345 9#define TEST_INDEXBAD_PATH cl_fixture("bad.index")
6c106eec
BS
10
11
8e5a8ef8 12/* Suite data */
6c106eec 13struct test_entry {
11d9f6b3 14 size_t index;
6c106eec
BS
15 char path[128];
16 git_off_t file_size;
17 git_time_t mtime;
18};
19
b482c420 20static struct test_entry test_entries[] = {
6c106eec
BS
21 {4, "Makefile", 5064, 0x4C3F7F33},
22 {62, "tests/Makefile", 2631, 0x4C3F7F33},
23 {36, "src/index.c", 10014, 0x4C43368D},
24 {6, "git.git-authors", 2709, 0x4C3F7F33},
25 {48, "src/revobject.h", 1448, 0x4C3F7FE2}
26};
27
8e5a8ef8 28/* Helpers */
270303ca 29static void copy_file(const char *src, const char *dst)
6c106eec
BS
30{
31 git_buf source_buf = GIT_BUF_INIT;
32 git_file dst_fd;
6c106eec 33
270303ca 34 cl_git_pass(git_futils_readbuffer(&source_buf, src));
6c106eec 35
8e5a8ef8 36 dst_fd = git_futils_creat_withpath(dst, 0777, 0666); /* -V536 */
6c106eec
BS
37 if (dst_fd < 0)
38 goto cleanup;
39
270303ca 40 cl_git_pass(p_write(dst_fd, source_buf.ptr, source_buf.size));
6c106eec
BS
41
42cleanup:
43 git_buf_free(&source_buf);
44 p_close(dst_fd);
6c106eec
BS
45}
46
270303ca 47static void files_are_equal(const char *a, const char *b)
6c106eec
BS
48{
49 git_buf buf_a = GIT_BUF_INIT;
50 git_buf buf_b = GIT_BUF_INIT;
270303ca 51 int pass;
6c106eec 52
e172cf08 53 if (git_futils_readbuffer(&buf_a, a) < 0)
270303ca 54 cl_assert(0);
6c106eec 55
e172cf08 56 if (git_futils_readbuffer(&buf_b, b) < 0) {
6c106eec 57 git_buf_free(&buf_a);
270303ca 58 cl_assert(0);
6c106eec
BS
59 }
60
270303ca 61 pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size));
6c106eec
BS
62
63 git_buf_free(&buf_a);
64 git_buf_free(&buf_b);
13ed2966
MS
65
66 cl_assert(pass);
6c106eec
BS
67}
68
69
8e5a8ef8 70/* Fixture setup and teardown */
6c106eec
BS
71void test_index_tests__initialize(void)
72{
73}
74
6c106eec
BS
75void test_index_tests__empty_index(void)
76{
77 git_index *index;
78
79 cl_git_pass(git_index_open(&index, "in-memory-index"));
80 cl_assert(index->on_disk == 0);
81
82 cl_assert(git_index_entrycount(index) == 0);
882c7742 83 cl_assert(git_vector_is_sorted(&index->entries));
6c106eec
BS
84
85 git_index_free(index);
86}
87
88void test_index_tests__default_test_index(void)
89{
90 git_index *index;
91 unsigned int i;
92 git_index_entry **entries;
93
94 cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
95 cl_assert(index->on_disk);
96
a8122b5d 97 cl_assert(git_index_entrycount(index) == index_entry_count);
882c7742 98 cl_assert(git_vector_is_sorted(&index->entries));
6c106eec
BS
99
100 entries = (git_index_entry **)index->entries.contents;
101
b482c420 102 for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
34b8eafc 103 git_index_entry *e = entries[test_entries[i].index];
6c106eec 104
34b8eafc 105 cl_assert_equal_s(e->path, test_entries[i].path);
106 cl_assert(e->mtime.seconds == test_entries[i].mtime);
107 cl_assert(e->file_size == test_entries[i].file_size);
6c106eec
BS
108 }
109
110 git_index_free(index);
111}
112
113void test_index_tests__gitgit_index(void)
114{
115 git_index *index;
116
117 cl_git_pass(git_index_open(&index, TEST_INDEX2_PATH));
118 cl_assert(index->on_disk);
119
a8122b5d 120 cl_assert(git_index_entrycount(index) == index_entry_count_2);
882c7742 121 cl_assert(git_vector_is_sorted(&index->entries));
6c106eec
BS
122 cl_assert(index->tree != NULL);
123
124 git_index_free(index);
125}
126
127void test_index_tests__find_in_existing(void)
128{
129 git_index *index;
130 unsigned int i;
131
132 cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
133
b482c420 134 for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
34b8eafc 135 size_t idx;
11d9f6b3 136
34b8eafc 137 cl_assert(!git_index_find(&idx, index, test_entries[i].path));
138 cl_assert(idx == test_entries[i].index);
6c106eec
BS
139 }
140
141 git_index_free(index);
142}
143
144void test_index_tests__find_in_empty(void)
145{
146 git_index *index;
147 unsigned int i;
148
149 cl_git_pass(git_index_open(&index, "fake-index"));
150
b482c420 151 for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
34b8eafc 152 cl_assert(GIT_ENOTFOUND == git_index_find(NULL, index, test_entries[i].path));
6c106eec
BS
153 }
154
155 git_index_free(index);
156}
157
158void test_index_tests__write(void)
159{
160 git_index *index;
161
270303ca 162 copy_file(TEST_INDEXBIG_PATH, "index_rewrite");
6c106eec
BS
163
164 cl_git_pass(git_index_open(&index, "index_rewrite"));
165 cl_assert(index->on_disk);
166
167 cl_git_pass(git_index_write(index));
270303ca 168 files_are_equal(TEST_INDEXBIG_PATH, "index_rewrite");
6c106eec
BS
169
170 git_index_free(index);
171
172 p_unlink("index_rewrite");
173}
174
175void test_index_tests__sort0(void)
176{
8e5a8ef8
RB
177 /* sort the entires in an index */
178
6c106eec
BS
179 /*
180 * TODO: This no longer applies:
181 * index sorting in Git uses some specific changes to the way
182 * directories are sorted.
183 *
184 * We need to specificially check for this by creating a new
185 * index, adding entries in random order and then
186 * checking for consistency
187 */
188}
189
190void test_index_tests__sort1(void)
191{
8e5a8ef8 192 /* sort the entires in an empty index */
6c106eec
BS
193 git_index *index;
194
195 cl_git_pass(git_index_open(&index, "fake-index"));
196
197 /* FIXME: this test is slightly dumb */
882c7742 198 cl_assert(git_vector_is_sorted(&index->entries));
6c106eec
BS
199
200 git_index_free(index);
201}
202
f6fded8f
VM
203static void cleanup_myrepo(void *opaque)
204{
205 GIT_UNUSED(opaque);
206 cl_fixture_cleanup("myrepo");
207}
208
6c106eec
BS
209void test_index_tests__add(void)
210{
f6fded8f
VM
211 git_index *index;
212 git_filebuf file = GIT_FILEBUF_INIT;
213 git_repository *repo;
214 const git_index_entry *entry;
215 git_oid id1;
6c106eec 216
f6fded8f 217 cl_set_cleanup(&cleanup_myrepo, NULL);
6c106eec 218
f6fded8f
VM
219 /* Intialize a new repository */
220 cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
6c106eec 221
f6fded8f
VM
222 /* Ensure we're the only guy in the room */
223 cl_git_pass(git_repository_index(&index, repo));
224 cl_assert(git_index_entrycount(index) == 0);
6c106eec 225
f6fded8f
VM
226 /* Create a new file in the working directory */
227 cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
1d3a8aeb 228 cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666));
f6fded8f 229 cl_git_pass(git_filebuf_write(&file, "hey there\n", 10));
1d3a8aeb 230 cl_git_pass(git_filebuf_commit(&file));
6c106eec 231
f6fded8f
VM
232 /* Store the expected hash of the file/blob
233 * This has been generated by executing the following
234 * $ echo "hey there" | git hash-object --stdin
235 */
236 cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));
6c106eec 237
f6fded8f 238 /* Add the new file to the index */
25743bd7 239 cl_git_pass(git_index_add_bypath(index, "test.txt"));
6c106eec 240
f6fded8f
VM
241 /* Wow... it worked! */
242 cl_assert(git_index_entrycount(index) == 1);
243 entry = git_index_get_byindex(index, 0);
6c106eec 244
f6fded8f 245 /* And the built-in hashing mechanism worked as expected */
d541170c 246 cl_assert(git_oid_cmp(&id1, &entry->id) == 0);
f45ec1a0 247
f6fded8f
VM
248 /* Test access by path instead of index */
249 cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
d541170c 250 cl_assert(git_oid_cmp(&id1, &entry->id) == 0);
f6fded8f
VM
251
252 git_index_free(index);
253 git_repository_free(repo);
6c106eec
BS
254}
255
1098cfae
RB
256static void cleanup_1397(void *opaque)
257{
258 GIT_UNUSED(opaque);
259 cl_git_sandbox_cleanup();
260}
261
b8acb775
SS
262void test_index_tests__add_issue_1397(void)
263{
264 git_index *index;
b8acb775
SS
265 git_repository *repo;
266 const git_index_entry *entry;
267 git_oid id1;
268
1098cfae 269 cl_set_cleanup(&cleanup_1397, NULL);
b8acb775
SS
270
271 repo = cl_git_sandbox_init("issue_1397");
272
1098cfae 273 cl_repo_set_bool(repo, "core.autocrlf", true);
b8acb775
SS
274
275 /* Ensure we're the only guy in the room */
276 cl_git_pass(git_repository_index(&index, repo));
277
278 /* Store the expected hash of the file/blob
279 * This has been generated by executing the following
280 * $ git hash-object crlf_file.txt
281 */
282 cl_git_pass(git_oid_fromstr(&id1, "8312e0889a9cbab77c732b6bc39b51a683e3a318"));
283
284 /* Make sure the initial SHA-1 is correct */
285 cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL);
d541170c 286 cl_assert_(git_oid_cmp(&id1, &entry->id) == 0, "first oid check");
b8acb775
SS
287
288 /* Update the index */
289 cl_git_pass(git_index_add_bypath(index, "crlf_file.txt"));
290
291 /* Check the new SHA-1 */
292 cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL);
d541170c 293 cl_assert_(git_oid_cmp(&id1, &entry->id) == 0, "second oid check");
b8acb775
SS
294
295 git_index_free(index);
b8acb775
SS
296}
297
25743bd7 298void test_index_tests__add_bypath_to_a_bare_repository_returns_EBAREPO(void)
33f95a9b 299{
300 git_repository *bare_repo;
301 git_index *index;
302
303 cl_git_pass(git_repository_open(&bare_repo, cl_fixture("testrepo.git")));
304 cl_git_pass(git_repository_index(&index, bare_repo));
305
25743bd7 306 cl_assert_equal_i(GIT_EBAREREPO, git_index_add_bypath(index, "test.txt"));
33f95a9b 307
308 git_index_free(index);
309 git_repository_free(bare_repo);
310}
1876360f
SG
311
312/* Test that writing an invalid filename fails */
313void test_index_tests__write_invalid_filename(void)
314{
315 git_repository *repo;
316 git_index *index;
317 git_oid expected;
318
319 p_mkdir("read_tree", 0700);
320
321 cl_git_pass(git_repository_init(&repo, "./read_tree", 0));
322 cl_git_pass(git_repository_index(&index, repo));
323
324 cl_assert(git_index_entrycount(index) == 0);
325
326 cl_git_mkfile("./read_tree/.git/hello", NULL);
327
25743bd7 328 cl_git_pass(git_index_add_bypath(index, ".git/hello"));
1876360f
SG
329
330 /* write-tree */
331 cl_git_fail(git_index_write_tree(&expected, index));
332
333 git_index_free(index);
334 git_repository_free(repo);
335
336 cl_fixture_cleanup("read_tree");
337}
7fc00435
RB
338
339void test_index_tests__remove_entry(void)
340{
341 git_repository *repo;
342 git_index *index;
343
344 p_mkdir("index_test", 0770);
345
346 cl_git_pass(git_repository_init(&repo, "index_test", 0));
347 cl_git_pass(git_repository_index(&index, repo));
348 cl_assert(git_index_entrycount(index) == 0);
349
350 cl_git_mkfile("index_test/hello", NULL);
25743bd7 351 cl_git_pass(git_index_add_bypath(index, "hello"));
7fc00435
RB
352 cl_git_pass(git_index_write(index));
353
8e5a8ef8 354 cl_git_pass(git_index_read(index, true)); /* reload */
7fc00435
RB
355 cl_assert(git_index_entrycount(index) == 1);
356 cl_assert(git_index_get_bypath(index, "hello", 0) != NULL);
357
358 cl_git_pass(git_index_remove(index, "hello", 0));
359 cl_git_pass(git_index_write(index));
360
8e5a8ef8 361 cl_git_pass(git_index_read(index, true)); /* reload */
7fc00435
RB
362 cl_assert(git_index_entrycount(index) == 0);
363 cl_assert(git_index_get_bypath(index, "hello", 0) == NULL);
364
365 git_index_free(index);
366 git_repository_free(repo);
367 cl_fixture_cleanup("index_test");
368}
369
370void test_index_tests__remove_directory(void)
371{
372 git_repository *repo;
373 git_index *index;
374
375 p_mkdir("index_test", 0770);
376
377 cl_git_pass(git_repository_init(&repo, "index_test", 0));
378 cl_git_pass(git_repository_index(&index, repo));
379 cl_assert_equal_i(0, (int)git_index_entrycount(index));
380
381 p_mkdir("index_test/a", 0770);
382 cl_git_mkfile("index_test/a/1.txt", NULL);
383 cl_git_mkfile("index_test/a/2.txt", NULL);
384 cl_git_mkfile("index_test/a/3.txt", NULL);
385 cl_git_mkfile("index_test/b.txt", NULL);
386
25743bd7
ET
387 cl_git_pass(git_index_add_bypath(index, "a/1.txt"));
388 cl_git_pass(git_index_add_bypath(index, "a/2.txt"));
389 cl_git_pass(git_index_add_bypath(index, "a/3.txt"));
390 cl_git_pass(git_index_add_bypath(index, "b.txt"));
7fc00435
RB
391 cl_git_pass(git_index_write(index));
392
8e5a8ef8 393 cl_git_pass(git_index_read(index, true)); /* reload */
7fc00435
RB
394 cl_assert_equal_i(4, (int)git_index_entrycount(index));
395 cl_assert(git_index_get_bypath(index, "a/1.txt", 0) != NULL);
396 cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL);
397 cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL);
398
399 cl_git_pass(git_index_remove(index, "a/1.txt", 0));
400 cl_git_pass(git_index_write(index));
401
8e5a8ef8 402 cl_git_pass(git_index_read(index, true)); /* reload */
7fc00435
RB
403 cl_assert_equal_i(3, (int)git_index_entrycount(index));
404 cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL);
405 cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL);
406 cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL);
407
408 cl_git_pass(git_index_remove_directory(index, "a", 0));
409 cl_git_pass(git_index_write(index));
410
8e5a8ef8 411 cl_git_pass(git_index_read(index, true)); /* reload */
7fc00435
RB
412 cl_assert_equal_i(1, (int)git_index_entrycount(index));
413 cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL);
414 cl_assert(git_index_get_bypath(index, "a/2.txt", 0) == NULL);
415 cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL);
416
417 git_index_free(index);
418 git_repository_free(repo);
419 cl_fixture_cleanup("index_test");
420}
1540b199
ET
421
422void test_index_tests__preserves_case(void)
423{
424 git_repository *repo;
425 git_index *index;
426 const git_index_entry *entry;
fb03a223 427 int index_caps;
1540b199
ET
428
429 cl_set_cleanup(&cleanup_myrepo, NULL);
430
431 cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
432 cl_git_pass(git_repository_index(&index, repo));
433
fb03a223
RB
434 index_caps = git_index_caps(index);
435
1540b199
ET
436 cl_git_rewritefile("myrepo/test.txt", "hey there\n");
437 cl_git_pass(git_index_add_bypath(index, "test.txt"));
438
439 cl_git_pass(p_rename("myrepo/test.txt", "myrepo/TEST.txt"));
440 cl_git_rewritefile("myrepo/TEST.txt", "hello again\n");
441 cl_git_pass(git_index_add_bypath(index, "TEST.txt"));
442
fb03a223
RB
443 if (index_caps & GIT_INDEXCAP_IGNORE_CASE)
444 cl_assert_equal_i(1, (int)git_index_entrycount(index));
445 else
446 cl_assert_equal_i(2, (int)git_index_entrycount(index));
1540b199
ET
447
448 /* Test access by path instead of index */
449 cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
1540b199
ET
450 /* The path should *not* have changed without an explicit remove */
451 cl_assert(git__strcmp(entry->path, "test.txt") == 0);
452
fb03a223
RB
453 cl_assert((entry = git_index_get_bypath(index, "TEST.txt", 0)) != NULL);
454 if (index_caps & GIT_INDEXCAP_IGNORE_CASE)
455 /* The path should *not* have changed without an explicit remove */
456 cl_assert(git__strcmp(entry->path, "test.txt") == 0);
457 else
458 cl_assert(git__strcmp(entry->path, "TEST.txt") == 0);
459
1540b199
ET
460 git_index_free(index);
461 git_repository_free(repo);
462}
463
3d276874
CMN
464void test_index_tests__elocked(void)
465{
466 git_repository *repo;
467 git_index *index;
468 git_filebuf file = GIT_FILEBUF_INIT;
469 const git_error *err;
470 int error;
471
472 cl_set_cleanup(&cleanup_myrepo, NULL);
473
474 cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
475 cl_git_pass(git_repository_index(&index, repo));
476
477 /* Lock the index file so we fail to lock it */
1d3a8aeb 478 cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0, 0666));
3d276874
CMN
479 error = git_index_write(index);
480 cl_assert_equal_i(GIT_ELOCKED, error);
481
482 err = giterr_last();
483 cl_assert_equal_i(err->klass, GITERR_INDEX);
484
485 git_filebuf_cleanup(&file);
486 git_index_free(index);
487 git_repository_free(repo);
488}
da7b78fa 489
490void test_index_tests__reload_from_disk(void)
491{
492 git_repository *repo;
493 git_index *read_index;
494 git_index *write_index;
495
496 cl_set_cleanup(&cleanup_myrepo, NULL);
497
498 cl_git_pass(git_futils_mkdir("./myrepo", NULL, 0777, GIT_MKDIR_PATH));
499 cl_git_mkfile("./myrepo/a.txt", "a\n");
500 cl_git_mkfile("./myrepo/b.txt", "b\n");
501
502 cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
503 cl_git_pass(git_repository_index(&write_index, repo));
504 cl_assert_equal_i(false, write_index->on_disk);
505
506 cl_git_pass(git_index_open(&read_index, write_index->index_file_path));
507 cl_assert_equal_i(false, read_index->on_disk);
508
509 /* Stage two new files agaisnt the write_index */
510 cl_git_pass(git_index_add_bypath(write_index, "a.txt"));
511 cl_git_pass(git_index_add_bypath(write_index, "b.txt"));
512
513 cl_assert_equal_sz(2, git_index_entrycount(write_index));
514
515 /* Persist the index changes to disk */
516 cl_git_pass(git_index_write(write_index));
517 cl_assert_equal_i(true, write_index->on_disk);
518
519 /* Sync the changes back into the read_index */
520 cl_assert_equal_sz(0, git_index_entrycount(read_index));
521
8e5a8ef8 522 cl_git_pass(git_index_read(read_index, true));
da7b78fa 523 cl_assert_equal_i(true, read_index->on_disk);
524
525 cl_assert_equal_sz(2, git_index_entrycount(read_index));
526
527 /* Remove the index file from the filesystem */
528 cl_git_pass(p_unlink(write_index->index_file_path));
529
530 /* Sync the changes back into the read_index */
8e5a8ef8 531 cl_git_pass(git_index_read(read_index, true));
da7b78fa 532 cl_assert_equal_i(false, read_index->on_disk);
533 cl_assert_equal_sz(0, git_index_entrycount(read_index));
534
535 git_index_free(read_index);
536 git_index_free(write_index);
537 git_repository_free(repo);
538}
3d523345 539
540void test_index_tests__corrupted_extension(void)
541{
3d523345 542 git_index *index;
543
544 cl_git_fail_with(git_index_open(&index, TEST_INDEXBAD_PATH), GIT_ERROR);
545}
43709ca8
RB
546
547static void assert_index_is_sorted(git_index *index)
548{
549 git_vector *entries = &index->entries;
550 size_t i;
551
552 cl_assert(git_vector_is_sorted(entries));
553
554 for (i = 1; i < git_vector_length(entries); ++i) {
555 git_index_entry *prev = git_vector_get(entries, i - 1);
556 git_index_entry *curr = git_vector_get(entries, i);
557 cl_assert(index->entries._cmp(prev, curr) <= 0);
558 }
559}
560
561void test_index_tests__reload_while_ignoring_case(void)
562{
563 git_index *index;
564 unsigned int caps;
565
566 cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
567 assert_index_is_sorted(index);
568
569 caps = git_index_caps(index);
570 cl_git_pass(git_index_set_caps(index, caps &= ~GIT_INDEXCAP_IGNORE_CASE));
571 cl_git_pass(git_index_read(index, true));
572 assert_index_is_sorted(index);
573
574 cl_git_pass(git_index_set_caps(index, caps | GIT_INDEXCAP_IGNORE_CASE));
575 cl_git_pass(git_index_read(index, true));
576 assert_index_is_sorted(index);
577
578 git_index_free(index);
579}