summaryrefslogtreecommitdiff
path: root/tests/index/version.c
blob: b6c0b7918dd8e6e7ebf9009e50f2c72ba7bd3e40 (plain)
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "clar_libgit2.h"
#include "index.h"

static git_repository *g_repo = NULL;

void test_index_version__cleanup(void)
{
        cl_git_sandbox_cleanup();
        g_repo = NULL;
}

void test_index_version__can_read_v4(void)
{
	const char *paths[] = {
	    "file.tx", "file.txt", "file.txz", "foo", "zzz",
	};
	git_index *index;
	size_t i;

	g_repo = cl_git_sandbox_init("indexv4");

	cl_git_pass(git_repository_index(&index, g_repo));
	cl_assert_equal_sz(git_index_entrycount(index), 5);

	for (i = 0; i < ARRAY_SIZE(paths); i++) {
		const git_index_entry *entry =
		    git_index_get_bypath(index, paths[i], GIT_INDEX_STAGE_NORMAL);

		cl_assert(entry != NULL);
	}

	git_index_free(index);
}

void test_index_version__can_write_v4(void)
{
	const char *paths[] = {
	    "foo",
	    "foox",
	    "foobar",
	    "foobal",
	    "x",
	    "xz",
	    "xyzzyx"
	};
	git_repository *repo;
	git_index_entry entry;
	git_index *index;
	size_t i;

	g_repo = cl_git_sandbox_init("empty_standard_repo");
	cl_git_pass(git_repository_index(&index, g_repo));
	cl_git_pass(git_index_set_version(index, 4));

	for (i = 0; i < ARRAY_SIZE(paths); i++) {
		memset(&entry, 0, sizeof(entry));
		entry.path = paths[i];
		entry.mode = GIT_FILEMODE_BLOB;
		cl_git_pass(git_index_add_from_buffer(index, &entry, paths[i],
						     strlen(paths[i]) + 1));
	}
	cl_assert_equal_sz(git_index_entrycount(index), ARRAY_SIZE(paths));

	cl_git_pass(git_index_write(index));
	git_index_free(index);

	cl_git_pass(git_repository_open(&repo, git_repository_path(g_repo)));
	cl_git_pass(git_repository_index(&index, repo));
	cl_assert(git_index_version(index) == 4);

	for (i = 0; i < ARRAY_SIZE(paths); i++) {
		const git_index_entry *e;

		cl_assert(e = git_index_get_bypath(index, paths[i], 0));
		cl_assert_equal_s(paths[i], e->path);
	}

	git_index_free(index);
	git_repository_free(repo);
}

void test_index_version__v4_uses_path_compression(void)
{
	git_index_entry entry;
	git_index *index;
	char path[250], buf[1];
	struct stat st;
	char i, j;

	memset(path, 'a', sizeof(path));
	memset(buf, 'a', sizeof(buf));

	memset(&entry, 0, sizeof(entry));
	entry.path = path;
	entry.mode = GIT_FILEMODE_BLOB;

	g_repo = cl_git_sandbox_init("indexv4");
	cl_git_pass(git_repository_index(&index, g_repo));

	/* write 676 paths of 250 bytes length */
	for (i = 'a'; i <= 'z'; i++) {
		for (j = 'a'; j < 'z'; j++) {
			path[ARRAY_SIZE(path) - 3] = i;
			path[ARRAY_SIZE(path) - 2] = j;
			path[ARRAY_SIZE(path) - 1] = '\0';
			cl_git_pass(git_index_add_from_buffer(index, &entry, buf, sizeof(buf)));
		}
	}

	cl_git_pass(git_index_write(index));
	cl_git_pass(p_stat(git_index_path(index), &st));

	/*
	 * Without path compression, the written paths would at
	 * least take
	 *
	 *    (entries * pathlen) = len
	 *    (676 * 250) = 169000
	 *
	 *  bytes. As index v4 uses suffix-compression and our
	 *  written paths only differ in the last two entries,
	 *  this number will be much smaller, e.g.
	 *
	 *    (1 * pathlen) + (675 * 2) = len
	 *    676 + 1350 = 2026
	 *
	 *    bytes.
	 *
	 *    Note that the above calculations do not include
	 *    additional metadata of the index, e.g. OIDs or
	 *    index extensions. Including those we get an index
	 *    of approx. 200kB without compression and 40kB with
	 *    compression. As this is a lot smaller than without
	 *    compression, we can verify that path compression is
	 *    used.
	 */
	cl_assert_(st.st_size < 75000, "path compression not enabled");

	git_index_free(index);
}