]>
git.proxmox.com Git - libgit2.git/blob - tests/t01-rawobj.c
2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
32 static int hash_object(git_oid
*oid
, git_rawobj
*obj
)
34 return git_odb_hash(oid
, obj
->data
, obj
->len
, obj
->type
);
37 BEGIN_TEST(oid0
, "validate size of oid objects")
39 must_be_true(20 == GIT_OID_RAWSZ
);
40 must_be_true(40 == GIT_OID_HEXSZ
);
41 must_be_true(sizeof(out
) == GIT_OID_RAWSZ
);
42 must_be_true(sizeof(out
.id
) == GIT_OID_RAWSZ
);
45 BEGIN_TEST(oid1
, "fail when parsing an empty string as oid")
47 must_fail(git_oid_fromstr(&out
, ""));
50 BEGIN_TEST(oid2
, "fail when parsing an invalid string as oid")
52 must_fail(git_oid_fromstr(&out
, "moo"));
55 static int from_hex(unsigned int i
)
57 if (i
>= '0' && i
<= '9')
59 if (i
>= 'a' && i
<= 'f')
60 return 10 + (i
- 'a');
61 if (i
>= 'A' && i
<= 'F')
62 return 10 + (i
- 'A');
66 BEGIN_TEST(oid3
, "find all invalid characters when parsing an oid")
68 unsigned char exp
[] = {
69 0x16, 0xa6, 0x77, 0x70, 0xb7,
70 0xd8, 0xd7, 0x23, 0x17, 0xc4,
71 0xb7, 0x75, 0x21, 0x3c, 0x23,
72 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
74 char in
[41] = "16a67770b7d8d72317c4b775213c23a8bd74f5e0";
77 for (i
= 0; i
< 256; i
++) {
80 if (from_hex(i
) >= 0) {
81 exp
[19] = (unsigned char)(from_hex(i
) << 4);
82 must_pass(git_oid_fromstr(&out
, in
));
83 must_be_true(memcmp(out
.id
, exp
, sizeof(out
.id
)) == 0);
85 must_fail(git_oid_fromstr(&out
, in
));
90 BEGIN_TEST(oid4
, "fail when parsing an invalid oid string")
92 must_fail(git_oid_fromstr(&out
, "16a67770b7d8d72317c4b775213c23a8bd74f5ez"));
95 BEGIN_TEST(oid5
, "succeed when parsing a valid oid string")
97 unsigned char exp
[] = {
98 0x16, 0xa6, 0x77, 0x70, 0xb7,
99 0xd8, 0xd7, 0x23, 0x17, 0xc4,
100 0xb7, 0x75, 0x21, 0x3c, 0x23,
101 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
104 must_pass(git_oid_fromstr(&out
, "16a67770b7d8d72317c4b775213c23a8bd74f5e0"));
105 must_pass(memcmp(out
.id
, exp
, sizeof(out
.id
)));
107 must_pass(git_oid_fromstr(&out
, "16A67770B7D8D72317C4b775213C23A8BD74F5E0"));
108 must_pass(memcmp(out
.id
, exp
, sizeof(out
.id
)));
111 BEGIN_TEST(oid6
, "build a valid oid from raw bytes")
113 unsigned char exp
[] = {
114 0x16, 0xa6, 0x77, 0x70, 0xb7,
115 0xd8, 0xd7, 0x23, 0x17, 0xc4,
116 0xb7, 0x75, 0x21, 0x3c, 0x23,
117 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
120 git_oid_fromraw(&out
, exp
);
121 must_pass(memcmp(out
.id
, exp
, sizeof(out
.id
)));
124 BEGIN_TEST(oid7
, "properly copy an oid to another")
126 unsigned char exp
[] = {
127 0x16, 0xa6, 0x77, 0x70, 0xb7,
128 0xd8, 0xd7, 0x23, 0x17, 0xc4,
129 0xb7, 0x75, 0x21, 0x3c, 0x23,
130 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
133 memset(&b
, 0, sizeof(b
));
134 git_oid_fromraw(&a
, exp
);
136 must_pass(memcmp(a
.id
, exp
, sizeof(a
.id
)));
139 BEGIN_TEST(oid8
, "compare two oids (lesser than)")
141 unsigned char a_in
[] = {
142 0x16, 0xa6, 0x77, 0x70, 0xb7,
143 0xd8, 0xd7, 0x23, 0x17, 0xc4,
144 0xb7, 0x75, 0x21, 0x3c, 0x23,
145 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
147 unsigned char b_in
[] = {
148 0x16, 0xa6, 0x77, 0x70, 0xb7,
149 0xd8, 0xd7, 0x23, 0x17, 0xc4,
150 0xb7, 0x75, 0x21, 0x3c, 0x23,
151 0xa8, 0xbd, 0x74, 0xf5, 0xf0,
154 git_oid_fromraw(&a
, a_in
);
155 git_oid_fromraw(&b
, b_in
);
156 must_be_true(git_oid_cmp(&a
, &b
) < 0);
159 BEGIN_TEST(oid9
, "compare two oids (equal)")
161 unsigned char a_in
[] = {
162 0x16, 0xa6, 0x77, 0x70, 0xb7,
163 0xd8, 0xd7, 0x23, 0x17, 0xc4,
164 0xb7, 0x75, 0x21, 0x3c, 0x23,
165 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
168 git_oid_fromraw(&a
, a_in
);
169 git_oid_fromraw(&b
, a_in
);
170 must_be_true(git_oid_cmp(&a
, &b
) == 0);
173 BEGIN_TEST(oid10
, "compare two oids (greater than)")
175 unsigned char a_in
[] = {
176 0x16, 0xa6, 0x77, 0x70, 0xb7,
177 0xd8, 0xd7, 0x23, 0x17, 0xc4,
178 0xb7, 0x75, 0x21, 0x3c, 0x23,
179 0xa8, 0xbd, 0x74, 0xf5, 0xe0,
181 unsigned char b_in
[] = {
182 0x16, 0xa6, 0x77, 0x70, 0xb7,
183 0xd8, 0xd7, 0x23, 0x17, 0xc4,
184 0xb7, 0x75, 0x21, 0x3c, 0x23,
185 0xa8, 0xbd, 0x74, 0xf5, 0xd0,
188 git_oid_fromraw(&a
, a_in
);
189 git_oid_fromraw(&b
, b_in
);
190 must_be_true(git_oid_cmp(&a
, &b
) > 0);
193 BEGIN_TEST(oid11
, "compare formated oids")
194 const char *exp
= "16a0123456789abcdef4b775213c23a8bd74f5e0";
196 char out
[GIT_OID_HEXSZ
+ 1];
198 must_pass(git_oid_fromstr(&in
, exp
));
200 /* Format doesn't touch the last byte */
201 out
[GIT_OID_HEXSZ
] = 'Z';
202 git_oid_fmt(out
, &in
);
203 must_be_true(out
[GIT_OID_HEXSZ
] == 'Z');
205 /* Format produced the right result */
206 out
[GIT_OID_HEXSZ
] = '\0';
207 must_be_true(strcmp(exp
, out
) == 0);
210 BEGIN_TEST(oid12
, "compare oids (allocate + format)")
211 const char *exp
= "16a0123456789abcdef4b775213c23a8bd74f5e0";
215 must_pass(git_oid_fromstr(&in
, exp
));
217 out
= git_oid_allocfmt(&in
);
219 must_be_true(strcmp(exp
, out
) == 0);
223 BEGIN_TEST(oid13
, "compare oids (path format)")
224 const char *exp1
= "16a0123456789abcdef4b775213c23a8bd74f5e0";
225 const char *exp2
= "16/a0123456789abcdef4b775213c23a8bd74f5e0";
227 char out
[GIT_OID_HEXSZ
+ 2];
229 must_pass(git_oid_fromstr(&in
, exp1
));
231 /* Format doesn't touch the last byte */
232 out
[GIT_OID_HEXSZ
+ 1] = 'Z';
233 git_oid_pathfmt(out
, &in
);
234 must_be_true(out
[GIT_OID_HEXSZ
+ 1] == 'Z');
236 /* Format produced the right result */
237 out
[GIT_OID_HEXSZ
+ 1] = '\0';
238 must_be_true(strcmp(exp2
, out
) == 0);
241 BEGIN_TEST(oid14
, "convert raw oid to string")
242 const char *exp
= "16a0123456789abcdef4b775213c23a8bd74f5e0";
244 char out
[GIT_OID_HEXSZ
+ 1];
248 must_pass(git_oid_fromstr(&in
, exp
));
250 /* NULL buffer pointer, returns static empty string */
251 str
= git_oid_to_string(NULL
, sizeof(out
), &in
);
252 must_be_true(str
&& *str
== '\0' && str
!= out
);
254 /* zero buffer size, returns static empty string */
255 str
= git_oid_to_string(out
, 0, &in
);
256 must_be_true(str
&& *str
== '\0' && str
!= out
);
258 /* NULL oid pointer, returns static empty string */
259 str
= git_oid_to_string(out
, sizeof(out
), NULL
);
260 must_be_true(str
&& *str
== '\0' && str
!= out
);
262 /* n == 1, returns out as an empty string */
263 str
= git_oid_to_string(out
, 1, &in
);
264 must_be_true(str
&& *str
== '\0' && str
== out
);
266 for (i
= 1; i
< GIT_OID_HEXSZ
; i
++) {
268 str
= git_oid_to_string(out
, i
+1, &in
);
269 /* returns out containing c-string */
270 must_be_true(str
&& str
== out
);
271 /* must be '\0' terminated */
272 must_be_true(*(str
+i
) == '\0');
273 /* must not touch bytes past end of string */
274 must_be_true(*(str
+(i
+1)) == 'Z');
275 /* i == n-1 charaters of string */
276 must_pass(strncmp(exp
, out
, i
));
279 /* returns out as hex formatted c-string */
280 str
= git_oid_to_string(out
, sizeof(out
), &in
);
281 must_be_true(str
&& str
== out
&& *(str
+GIT_OID_HEXSZ
) == '\0');
282 must_be_true(strcmp(exp
, out
) == 0);
285 BEGIN_TEST(oid15
, "convert raw oid to string (big)")
286 const char *exp
= "16a0123456789abcdef4b775213c23a8bd74f5e0";
288 char big
[GIT_OID_HEXSZ
+ 1 + 3]; /* note + 4 => big buffer */
291 must_pass(git_oid_fromstr(&in
, exp
));
293 /* place some tail material */
294 big
[GIT_OID_HEXSZ
+0] = 'W'; /* should be '\0' afterwards */
295 big
[GIT_OID_HEXSZ
+1] = 'X'; /* should remain untouched */
296 big
[GIT_OID_HEXSZ
+2] = 'Y'; /* ditto */
297 big
[GIT_OID_HEXSZ
+3] = 'Z'; /* ditto */
299 /* returns big as hex formatted c-string */
300 str
= git_oid_to_string(big
, sizeof(big
), &in
);
301 must_be_true(str
&& str
== big
&& *(str
+GIT_OID_HEXSZ
) == '\0');
302 must_be_true(strcmp(exp
, big
) == 0);
304 /* check tail material is untouched */
305 must_be_true(str
&& str
== big
&& *(str
+GIT_OID_HEXSZ
+1) == 'X');
306 must_be_true(str
&& str
== big
&& *(str
+GIT_OID_HEXSZ
+2) == 'Y');
307 must_be_true(str
&& str
== big
&& *(str
+GIT_OID_HEXSZ
+3) == 'Z');
311 BEGIN_TEST(oid16
, "make sure the OID shortener doesn't choke on duplicate sha1s")
316 os
= git_oid_shorten_new(0);
317 must_be_true(os
!= NULL
);
319 git_oid_shorten_add(os
, "22596363b3de40b06f981fb85d82312e8c0ed511");
320 git_oid_shorten_add(os
, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09");
321 git_oid_shorten_add(os
, "16a0123456789abcdef4b775213c23a8bd74f5e0");
322 min_len
= git_oid_shorten_add(os
, "ce08fe4884650f067bd5703b6a59a8b3b3c99a09");
324 must_be_true(min_len
== GIT_OID_HEXSZ
+ 1);
326 git_oid_shorten_free(os
);
329 BEGIN_TEST(oid17
, "stress test for the git_oid_shorten object")
331 #define MAX_OIDS 1000
334 char *oids
[MAX_OIDS
];
335 char number_buffer
[16];
339 int min_len
= 0, found_collision
;
341 os
= git_oid_shorten_new(0);
342 must_be_true(os
!= NULL
);
345 * Insert in the shortener 1000 unique SHA1 ids
347 for (i
= 0; i
< MAX_OIDS
; ++i
) {
350 sprintf(number_buffer
, "%u", (unsigned int)i
);
351 git_hash_buf(&oid
, number_buffer
, strlen(number_buffer
));
353 oid_text
= git__malloc(GIT_OID_HEXSZ
+ 1);
354 git_oid_fmt(oid_text
, &oid
);
355 oid_text
[GIT_OID_HEXSZ
] = 0;
357 min_len
= git_oid_shorten_add(os
, oid_text
);
358 must_be_true(min_len
>= 0);
364 * Compare the first `min_char - 1` characters of each
365 * SHA1 OID. If the minimizer worked, we should find at
366 * least one collision
369 for (i
= 0; i
< MAX_OIDS
; ++i
) {
370 for (j
= 0; j
< MAX_OIDS
; ++j
) {
371 if (i
!= j
&& memcmp(oids
[i
], oids
[j
], min_len
- 1) == 0)
375 must_be_true(found_collision
== 1);
378 * Compare the first `min_char` characters of each
379 * SHA1 OID. If the minimizer worked, every single preffix
383 for (i
= 0; i
< MAX_OIDS
; ++i
) {
384 for (j
= 0; j
< MAX_OIDS
; ++j
) {
385 if (i
!= j
&& memcmp(oids
[i
], oids
[j
], min_len
) == 0)
389 must_be_true(found_collision
== 0);
392 for (i
= 0; i
< MAX_OIDS
; ++i
)
395 git_oid_shorten_free(os
);
400 static char *hello_id
= "22596363b3de40b06f981fb85d82312e8c0ed511";
401 static char *hello_text
= "hello world\n";
403 static char *bye_id
= "ce08fe4884650f067bd5703b6a59a8b3b3c99a09";
404 static char *bye_text
= "bye world\n";
406 BEGIN_TEST(hash0
, "normal hash by blocks")
410 must_be_true((ctx
= git_hash_new_ctx()) != NULL
);
412 /* should already be init'd */
413 git_hash_update(ctx
, hello_text
, strlen(hello_text
));
414 git_hash_final(&id2
, ctx
);
415 must_pass(git_oid_fromstr(&id1
, hello_id
));
416 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
418 /* reinit should permit reuse */
420 git_hash_update(ctx
, bye_text
, strlen(bye_text
));
421 git_hash_final(&id2
, ctx
);
422 must_pass(git_oid_fromstr(&id1
, bye_id
));
423 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
425 git_hash_free_ctx(ctx
);
428 BEGIN_TEST(hash1
, "hash whole buffer in a single call")
431 must_pass(git_oid_fromstr(&id1
, hello_id
));
433 git_hash_buf(&id2
, hello_text
, strlen(hello_text
));
435 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
438 BEGIN_TEST(hash2
, "hash a vector")
442 must_pass(git_oid_fromstr(&id1
, hello_id
));
444 vec
[0].data
= hello_text
;
446 vec
[1].data
= hello_text
+4;
447 vec
[1].len
= strlen(hello_text
)-4;
449 git_hash_vec(&id2
, vec
, 2);
451 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
454 BEGIN_TEST(objtype0
, "convert type to string")
455 must_be_true(!strcmp(git_object_type2string(GIT_OBJ_BAD
), ""));
456 must_be_true(!strcmp(git_object_type2string(GIT_OBJ__EXT1
), ""));
457 must_be_true(!strcmp(git_object_type2string(GIT_OBJ_COMMIT
), "commit"));
458 must_be_true(!strcmp(git_object_type2string(GIT_OBJ_TREE
), "tree"));
459 must_be_true(!strcmp(git_object_type2string(GIT_OBJ_BLOB
), "blob"));
460 must_be_true(!strcmp(git_object_type2string(GIT_OBJ_TAG
), "tag"));
461 must_be_true(!strcmp(git_object_type2string(GIT_OBJ__EXT2
), ""));
462 must_be_true(!strcmp(git_object_type2string(GIT_OBJ_OFS_DELTA
), "OFS_DELTA"));
463 must_be_true(!strcmp(git_object_type2string(GIT_OBJ_REF_DELTA
), "REF_DELTA"));
465 must_be_true(!strcmp(git_object_type2string(-2), ""));
466 must_be_true(!strcmp(git_object_type2string(8), ""));
467 must_be_true(!strcmp(git_object_type2string(1234), ""));
470 BEGIN_TEST(objtype1
, "convert string to type")
471 must_be_true(git_object_string2type(NULL
) == GIT_OBJ_BAD
);
472 must_be_true(git_object_string2type("") == GIT_OBJ_BAD
);
473 must_be_true(git_object_string2type("commit") == GIT_OBJ_COMMIT
);
474 must_be_true(git_object_string2type("tree") == GIT_OBJ_TREE
);
475 must_be_true(git_object_string2type("blob") == GIT_OBJ_BLOB
);
476 must_be_true(git_object_string2type("tag") == GIT_OBJ_TAG
);
477 must_be_true(git_object_string2type("OFS_DELTA") == GIT_OBJ_OFS_DELTA
);
478 must_be_true(git_object_string2type("REF_DELTA") == GIT_OBJ_REF_DELTA
);
480 must_be_true(git_object_string2type("CoMmIt") == GIT_OBJ_BAD
);
481 must_be_true(git_object_string2type("hohoho") == GIT_OBJ_BAD
);
484 BEGIN_TEST(objtype2
, "check if an object type is loose")
485 must_be_true(git_object_typeisloose(GIT_OBJ_BAD
) == 0);
486 must_be_true(git_object_typeisloose(GIT_OBJ__EXT1
) == 0);
487 must_be_true(git_object_typeisloose(GIT_OBJ_COMMIT
) == 1);
488 must_be_true(git_object_typeisloose(GIT_OBJ_TREE
) == 1);
489 must_be_true(git_object_typeisloose(GIT_OBJ_BLOB
) == 1);
490 must_be_true(git_object_typeisloose(GIT_OBJ_TAG
) == 1);
491 must_be_true(git_object_typeisloose(GIT_OBJ__EXT2
) == 0);
492 must_be_true(git_object_typeisloose(GIT_OBJ_OFS_DELTA
) == 0);
493 must_be_true(git_object_typeisloose(GIT_OBJ_REF_DELTA
) == 0);
495 must_be_true(git_object_typeisloose(-2) == 0);
496 must_be_true(git_object_typeisloose(8) == 0);
497 must_be_true(git_object_typeisloose(1234) == 0);
500 BEGIN_TEST(objhash0
, "hash junk data")
503 must_pass(git_oid_fromstr(&id_zero
, zero_id
));
506 junk_obj
.data
= some_data
;
507 must_fail(hash_object(&id
, &junk_obj
));
509 junk_obj
.type
= GIT_OBJ__EXT1
;
510 must_fail(hash_object(&id
, &junk_obj
));
512 junk_obj
.type
= GIT_OBJ__EXT2
;
513 must_fail(hash_object(&id
, &junk_obj
));
515 junk_obj
.type
= GIT_OBJ_OFS_DELTA
;
516 must_fail(hash_object(&id
, &junk_obj
));
518 junk_obj
.type
= GIT_OBJ_REF_DELTA
;
519 must_fail(hash_object(&id
, &junk_obj
));
521 /* data can be NULL only if len is zero: */
522 junk_obj
.type
= GIT_OBJ_BLOB
;
523 junk_obj
.data
= NULL
;
524 must_pass(hash_object(&id
, &junk_obj
));
525 must_be_true(git_oid_cmp(&id
, &id_zero
) == 0);
528 must_fail(hash_object(&id
, &junk_obj
));
531 BEGIN_TEST(objhash1
, "hash a commit object")
534 must_pass(git_oid_fromstr(&id1
, commit_id
));
536 must_pass(hash_object(&id2
, &commit_obj
));
538 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
541 BEGIN_TEST(objhash2
, "hash a tree object")
544 must_pass(git_oid_fromstr(&id1
, tree_id
));
546 must_pass(hash_object(&id2
, &tree_obj
));
548 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
551 BEGIN_TEST(objhash3
, "hash a tag object")
554 must_pass(git_oid_fromstr(&id1
, tag_id
));
556 must_pass(hash_object(&id2
, &tag_obj
));
558 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
561 BEGIN_TEST(objhash4
, "hash a zero-length object")
564 must_pass(git_oid_fromstr(&id1
, zero_id
));
566 must_pass(hash_object(&id2
, &zero_obj
));
568 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
571 BEGIN_TEST(objhash5
, "hash an one-byte long object")
574 must_pass(git_oid_fromstr(&id1
, one_id
));
576 must_pass(hash_object(&id2
, &one_obj
));
578 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
581 BEGIN_TEST(objhash6
, "hash a two-byte long object")
584 must_pass(git_oid_fromstr(&id1
, two_id
));
586 must_pass(hash_object(&id2
, &two_obj
));
588 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
591 BEGIN_TEST(objhash7
, "hash an object several bytes long")
594 must_pass(git_oid_fromstr(&id1
, some_id
));
596 must_pass(hash_object(&id2
, &some_obj
));
598 must_be_true(git_oid_cmp(&id1
, &id2
) == 0);
601 BEGIN_SUITE(rawobjects
)