]> git.proxmox.com Git - libgit2.git/blob - tests/odb/loose.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / tests / odb / loose.c
1 #include "clar_libgit2.h"
2 #include "odb.h"
3 #include "git2/odb_backend.h"
4 #include "posix.h"
5 #include "loose_data.h"
6 #include "repository.h"
7
8 #ifdef __ANDROID_API__
9 # define S_IREAD S_IRUSR
10 # define S_IWRITE S_IWUSR
11 #endif
12
13 static void write_object_files(object_data *d)
14 {
15 int fd;
16
17 if (p_mkdir(d->dir, GIT_OBJECT_DIR_MODE) < 0)
18 cl_assert(errno == EEXIST);
19
20 cl_assert((fd = p_creat(d->file, S_IREAD | S_IWRITE)) >= 0);
21 cl_must_pass(p_write(fd, d->bytes, d->blen));
22
23 p_close(fd);
24 }
25
26 static void cmp_objects(git_rawobj *o, object_data *d)
27 {
28 cl_assert(o->type == git_object_string2type(d->type));
29 cl_assert(o->len == d->dlen);
30
31 if (o->len > 0)
32 cl_assert(memcmp(o->data, d->data, o->len) == 0);
33 }
34
35 static void test_read_object(object_data *data)
36 {
37 git_oid id;
38 git_odb_object *obj;
39 git_odb *odb;
40 git_rawobj tmp;
41
42 write_object_files(data);
43
44 cl_git_pass(git_odb_open(&odb, "test-objects"));
45 cl_git_pass(git_oid_fromstr(&id, data->id));
46 cl_git_pass(git_odb_read(&obj, odb, &id));
47
48 tmp.data = obj->buffer;
49 tmp.len = obj->cached.size;
50 tmp.type = obj->cached.type;
51
52 cmp_objects(&tmp, data);
53
54 git_odb_object_free(obj);
55 git_odb_free(odb);
56 }
57
58 static void test_read_header(object_data *data)
59 {
60 git_oid id;
61 git_odb *odb;
62 size_t len;
63 git_object_t type;
64
65 write_object_files(data);
66
67 cl_git_pass(git_odb_open(&odb, "test-objects"));
68 cl_git_pass(git_oid_fromstr(&id, data->id));
69 cl_git_pass(git_odb_read_header(&len, &type, odb, &id));
70
71 cl_assert_equal_sz(data->dlen, len);
72 cl_assert_equal_i(git_object_string2type(data->type), type);
73
74 git_odb_free(odb);
75 }
76
77 static void test_readstream_object(object_data *data, size_t blocksize)
78 {
79 git_oid id;
80 git_odb *odb;
81 git_odb_stream *stream;
82 git_rawobj tmp;
83 char buf[2048], *ptr = buf;
84 size_t remain;
85 int ret;
86
87 write_object_files(data);
88
89 cl_git_pass(git_odb_open(&odb, "test-objects"));
90 cl_git_pass(git_oid_fromstr(&id, data->id));
91 cl_git_pass(git_odb_open_rstream(&stream, &tmp.len, &tmp.type, odb, &id));
92
93 remain = tmp.len;
94
95 while (remain) {
96 cl_assert((ret = git_odb_stream_read(stream, ptr, blocksize)) >= 0);
97 if (ret == 0)
98 break;
99
100 cl_assert(remain >= (size_t)ret);
101 remain -= ret;
102 ptr += ret;
103 }
104
105 cl_assert(remain == 0);
106
107 tmp.data = buf;
108
109 cmp_objects(&tmp, data);
110
111 git_odb_stream_free(stream);
112 git_odb_free(odb);
113 }
114
115 void test_odb_loose__initialize(void)
116 {
117 p_fsync__cnt = 0;
118 cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE));
119 }
120
121 void test_odb_loose__cleanup(void)
122 {
123 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 0));
124 cl_fixture_cleanup("test-objects");
125 }
126
127 void test_odb_loose__exists(void)
128 {
129 git_oid id, id2;
130 git_odb *odb;
131
132 write_object_files(&one);
133 cl_git_pass(git_odb_open(&odb, "test-objects"));
134
135 cl_git_pass(git_oid_fromstr(&id, one.id));
136 cl_assert(git_odb_exists(odb, &id));
137
138 cl_git_pass(git_oid_fromstrp(&id, "8b137891"));
139 cl_git_pass(git_odb_exists_prefix(&id2, odb, &id, 8));
140 cl_assert_equal_i(0, git_oid_streq(&id2, one.id));
141
142 /* Test for a missing object */
143 cl_git_pass(git_oid_fromstr(&id, "8b137891791fe96927ad78e64b0aad7bded08baa"));
144 cl_assert(!git_odb_exists(odb, &id));
145
146 cl_git_pass(git_oid_fromstrp(&id, "8b13789a"));
147 cl_assert_equal_i(GIT_ENOTFOUND, git_odb_exists_prefix(&id2, odb, &id, 8));
148
149 git_odb_free(odb);
150 }
151
152 void test_odb_loose__simple_reads(void)
153 {
154 test_read_object(&commit);
155 test_read_object(&tree);
156 test_read_object(&tag);
157 test_read_object(&zero);
158 test_read_object(&one);
159 test_read_object(&two);
160 test_read_object(&some);
161 }
162
163 void test_odb_loose__streaming_reads(void)
164 {
165 size_t blocksizes[] = { 1, 2, 4, 16, 99, 1024, 123456789 };
166 size_t i;
167
168 for (i = 0; i < ARRAY_SIZE(blocksizes); i++) {
169 test_readstream_object(&commit, blocksizes[i]);
170 test_readstream_object(&tree, blocksizes[i]);
171 test_readstream_object(&tag, blocksizes[i]);
172 test_readstream_object(&zero, blocksizes[i]);
173 test_readstream_object(&one, blocksizes[i]);
174 test_readstream_object(&two, blocksizes[i]);
175 test_readstream_object(&some, blocksizes[i]);
176 }
177 }
178
179 void test_odb_loose__read_header(void)
180 {
181 test_read_header(&commit);
182 test_read_header(&tree);
183 test_read_header(&tag);
184 test_read_header(&zero);
185 test_read_header(&one);
186 test_read_header(&two);
187 test_read_header(&some);
188 }
189
190 static void test_write_object_permission(
191 mode_t dir_mode, mode_t file_mode,
192 mode_t expected_dir_mode, mode_t expected_file_mode)
193 {
194 git_odb *odb;
195 git_odb_backend *backend;
196 git_oid oid;
197 struct stat statbuf;
198 mode_t mask, os_mask;
199
200 /* Windows does not return group/user bits from stat,
201 * files are never executable.
202 */
203 #ifdef GIT_WIN32
204 os_mask = 0600;
205 #else
206 os_mask = 0777;
207 #endif
208
209 mask = p_umask(0);
210 p_umask(mask);
211
212 cl_git_pass(git_odb_new(&odb));
213 cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, 0, dir_mode, file_mode));
214 cl_git_pass(git_odb_add_backend(odb, backend, 1));
215 cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJECT_BLOB));
216
217 cl_git_pass(p_stat("test-objects/67", &statbuf));
218 cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_dir_mode & ~mask) & os_mask);
219
220 cl_git_pass(p_stat("test-objects/67/b808feb36201507a77f85e6d898f0a2836e4a5", &statbuf));
221 cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_file_mode & ~mask) & os_mask);
222
223 git_odb_free(odb);
224 }
225
226 void test_odb_loose__permissions_standard(void)
227 {
228 test_write_object_permission(0, 0, GIT_OBJECT_DIR_MODE, GIT_OBJECT_FILE_MODE);
229 }
230
231 void test_odb_loose__permissions_readonly(void)
232 {
233 test_write_object_permission(0777, 0444, 0777, 0444);
234 }
235
236 void test_odb_loose__permissions_readwrite(void)
237 {
238 test_write_object_permission(0777, 0666, 0777, 0666);
239 }
240
241 static void write_object_to_loose_odb(int fsync)
242 {
243 git_odb *odb;
244 git_odb_backend *backend;
245 git_oid oid;
246
247 cl_git_pass(git_odb_new(&odb));
248 cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, fsync, 0777, 0666));
249 cl_git_pass(git_odb_add_backend(odb, backend, 1));
250 cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJECT_BLOB));
251 git_odb_free(odb);
252 }
253
254 void test_odb_loose__does_not_fsync_by_default(void)
255 {
256 write_object_to_loose_odb(0);
257 cl_assert_equal_sz(0, p_fsync__cnt);
258 }
259
260 void test_odb_loose__fsync_obeys_odb_option(void)
261 {
262 write_object_to_loose_odb(1);
263 cl_assert(p_fsync__cnt > 0);
264 }
265
266 void test_odb_loose__fsync_obeys_global_setting(void)
267 {
268 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 1));
269 write_object_to_loose_odb(0);
270 cl_assert(p_fsync__cnt > 0);
271 }
272
273 void test_odb_loose__fsync_obeys_repo_setting(void)
274 {
275 git_repository *repo;
276 git_odb *odb;
277 git_oid oid;
278
279 cl_git_pass(git_repository_init(&repo, "test-objects", 1));
280 cl_git_pass(git_repository_odb__weakptr(&odb, repo));
281 cl_git_pass(git_odb_write(&oid, odb, "No fsync here\n", 14, GIT_OBJECT_BLOB));
282 cl_assert(p_fsync__cnt == 0);
283 git_repository_free(repo);
284
285 cl_git_pass(git_repository_open(&repo, "test-objects"));
286 cl_repo_set_bool(repo, "core.fsyncObjectFiles", true);
287 cl_git_pass(git_repository_odb__weakptr(&odb, repo));
288 cl_git_pass(git_odb_write(&oid, odb, "Now fsync\n", 10, GIT_OBJECT_BLOB));
289 cl_assert(p_fsync__cnt > 0);
290 git_repository_free(repo);
291 }