blob.c 15.6 KB
Newer Older
1 2 3 4
#include "clar_libgit2.h"
#include "diff_helpers.h"

static git_repository *g_repo = NULL;
nulltoken committed
5
static diff_expects expected;
6
static git_diff_options opts;
7
static git_blob *d, *alien;
8 9 10

void test_diff_blob__initialize(void)
{
11
	git_oid oid;
12

13
	g_repo = cl_git_sandbox_init("attr");
14

Ben Straub committed
15
	GIT_INIT_STRUCTURE(&opts, GIT_DIFF_OPTIONS_VERSION);
16
	opts.context_lines = 1;
17
	opts.interhunk_lines = 0;
18

nulltoken committed
19
	memset(&expected, 0, sizeof(expected));
20 21

	/* tests/resources/attr/root_test4.txt */
22 23
	cl_git_pass(git_oid_fromstrn(&oid, "a0f7217a", 8));
	cl_git_pass(git_blob_lookup_prefix(&d, g_repo, &oid, 4));
24 25 26 27

	/* alien.png */
	cl_git_pass(git_oid_fromstrn(&oid, "edf3dcee", 8));
	cl_git_pass(git_blob_lookup_prefix(&alien, g_repo, &oid, 4));
28 29 30 31
}

void test_diff_blob__cleanup(void)
{
32
	git_blob_free(d);
33 34
	d = NULL;

35
	git_blob_free(alien);
36
	alien = NULL;
37

38
	cl_git_sandbox_cleanup();
39 40
}

41
void test_diff_blob__can_compare_text_blobs(void)
42
{
43 44
	git_blob *a, *b, *c;
	git_oid a_oid, b_oid, c_oid;
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

	/* tests/resources/attr/root_test1 */
	cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8));
	cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4));

	/* tests/resources/attr/root_test2 */
	cl_git_pass(git_oid_fromstrn(&b_oid, "4d713dc4", 8));
	cl_git_pass(git_blob_lookup_prefix(&b, g_repo, &b_oid, 4));

	/* tests/resources/attr/root_test3 */
	cl_git_pass(git_oid_fromstrn(&c_oid, "c96bbb2c2557a832", 16));
	cl_git_pass(git_blob_lookup_prefix(&c, g_repo, &c_oid, 8));

	/* Doing the equivalent of a `git diff -U1` on these files */

60
	/* diff on tests/resources/attr/root_test1 */
61
	cl_git_pass(git_diff_blobs(
62
		a, b, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
63

Russell Belfer committed
64
	cl_assert_equal_i(1, expected.files);
65 66
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]);
	cl_assert_equal_i(0, expected.files_binary);
67

Russell Belfer committed
68 69 70 71 72
	cl_assert_equal_i(1, expected.hunks);
	cl_assert_equal_i(6, expected.lines);
	cl_assert_equal_i(1, expected.line_ctxt);
	cl_assert_equal_i(5, expected.line_adds);
	cl_assert_equal_i(0, expected.line_dels);
73

74
	/* diff on tests/resources/attr/root_test2 */
nulltoken committed
75
	memset(&expected, 0, sizeof(expected));
76
	cl_git_pass(git_diff_blobs(
77
		b, c, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
78

Russell Belfer committed
79
	cl_assert_equal_i(1, expected.files);
80 81
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]);
	cl_assert_equal_i(0, expected.files_binary);
82

Russell Belfer committed
83 84 85 86 87
	cl_assert_equal_i(1, expected.hunks);
	cl_assert_equal_i(15, expected.lines);
	cl_assert_equal_i(3, expected.line_ctxt);
	cl_assert_equal_i(9, expected.line_adds);
	cl_assert_equal_i(3, expected.line_dels);
88

89
	/* diff on tests/resources/attr/root_test3 */
nulltoken committed
90
	memset(&expected, 0, sizeof(expected));
91
	cl_git_pass(git_diff_blobs(
92
		a, c, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
93

Russell Belfer committed
94
	cl_assert_equal_i(1, expected.files);
95 96
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]);
	cl_assert_equal_i(0, expected.files_binary);
97

Russell Belfer committed
98 99 100 101 102
	cl_assert_equal_i(1, expected.hunks);
	cl_assert_equal_i(13, expected.lines);
	cl_assert_equal_i(0, expected.line_ctxt);
	cl_assert_equal_i(12, expected.line_adds);
	cl_assert_equal_i(1, expected.line_dels);
103

nulltoken committed
104
	memset(&expected, 0, sizeof(expected));
105
	cl_git_pass(git_diff_blobs(
106
		c, d, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
107

Russell Belfer committed
108
	cl_assert_equal_i(1, expected.files);
109 110
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]);
	cl_assert_equal_i(0, expected.files_binary);
111

Russell Belfer committed
112 113 114 115 116
	cl_assert_equal_i(2, expected.hunks);
	cl_assert_equal_i(14, expected.lines);
	cl_assert_equal_i(4, expected.line_ctxt);
	cl_assert_equal_i(6, expected.line_adds);
	cl_assert_equal_i(4, expected.line_dels);
117 118 119 120 121 122

	git_blob_free(a);
	git_blob_free(b);
	git_blob_free(c);
}

123 124 125 126 127
void test_diff_blob__can_compare_against_null_blobs(void)
{
	git_blob *e = NULL;

	cl_git_pass(git_diff_blobs(
128
		d, e, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
129

Russell Belfer committed
130
	cl_assert_equal_i(1, expected.files);
131 132
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]);
	cl_assert_equal_i(0, expected.files_binary);
133

Russell Belfer committed
134 135 136 137
	cl_assert_equal_i(1, expected.hunks);
	cl_assert_equal_i(14, expected.hunk_old_lines);
	cl_assert_equal_i(14, expected.lines);
	cl_assert_equal_i(14, expected.line_dels);
138 139

	opts.flags |= GIT_DIFF_REVERSE;
nulltoken committed
140
	memset(&expected, 0, sizeof(expected));
141 142

	cl_git_pass(git_diff_blobs(
143
		d, e, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
144

Russell Belfer committed
145
	cl_assert_equal_i(1, expected.files);
146 147
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]);
	cl_assert_equal_i(0, expected.files_binary);
148

Russell Belfer committed
149 150 151 152
	cl_assert_equal_i(1, expected.hunks);
	cl_assert_equal_i(14, expected.hunk_new_lines);
	cl_assert_equal_i(14, expected.lines);
	cl_assert_equal_i(14, expected.line_adds);
153 154

	opts.flags ^= GIT_DIFF_REVERSE;
nulltoken committed
155
	memset(&expected, 0, sizeof(expected));
156 157

	cl_git_pass(git_diff_blobs(
158
		alien, NULL, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
159

Russell Belfer committed
160
	cl_assert_equal_i(1, expected.files);
161 162
	cl_assert_equal_i(1, expected.files_binary);
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]);
Russell Belfer committed
163 164
	cl_assert_equal_i(0, expected.hunks);
	cl_assert_equal_i(0, expected.lines);
165

nulltoken committed
166
	memset(&expected, 0, sizeof(expected));
167 168

	cl_git_pass(git_diff_blobs(
169
		NULL, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
170

Russell Belfer committed
171
	cl_assert_equal_i(1, expected.files);
172 173
	cl_assert_equal_i(1, expected.files_binary);
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]);
Russell Belfer committed
174 175
	cl_assert_equal_i(0, expected.hunks);
	cl_assert_equal_i(0, expected.lines);
176 177
}

178
static void assert_identical_blobs_comparison(diff_expects *expected)
179
{
180 181 182 183
	cl_assert_equal_i(1, expected->files);
	cl_assert_equal_i(1, expected->file_status[GIT_DELTA_UNMODIFIED]);
	cl_assert_equal_i(0, expected->hunks);
	cl_assert_equal_i(0, expected->lines);
184 185 186 187 188
}

void test_diff_blob__can_compare_identical_blobs(void)
{
	cl_git_pass(git_diff_blobs(
189
		d, d, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
190

191 192
	cl_assert_equal_i(0, expected.files_binary);
	assert_identical_blobs_comparison(&expected);
193

nulltoken committed
194
	memset(&expected, 0, sizeof(expected));
195
	cl_git_pass(git_diff_blobs(
196
		NULL, NULL, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
197

198
	cl_assert_equal_i(0, expected.files_binary);
199
	cl_assert_equal_i(0, expected.files); /* NULLs mean no callbacks, period */
200

nulltoken committed
201
	memset(&expected, 0, sizeof(expected));
202
	cl_git_pass(git_diff_blobs(
203
		alien, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
204

205 206
	cl_assert(expected.files_binary > 0);
	assert_identical_blobs_comparison(&expected);
207 208
}

209
static void assert_binary_blobs_comparison(diff_expects *expected)
210
{
211
	cl_assert(expected->files_binary > 0);
212

213 214 215 216
	cl_assert_equal_i(1, expected->files);
	cl_assert_equal_i(1, expected->file_status[GIT_DELTA_MODIFIED]);
	cl_assert_equal_i(0, expected->hunks);
	cl_assert_equal_i(0, expected->lines);
217 218 219 220 221 222 223 224 225 226 227 228
}

void test_diff_blob__can_compare_two_binary_blobs(void)
{
	git_blob *heart;
	git_oid h_oid;

	/* heart.png */
	cl_git_pass(git_oid_fromstrn(&h_oid, "de863bff", 8));
	cl_git_pass(git_blob_lookup_prefix(&heart, g_repo, &h_oid, 4));

	cl_git_pass(git_diff_blobs(
229
		alien, heart, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
230

231
	assert_binary_blobs_comparison(&expected);
232

nulltoken committed
233
	memset(&expected, 0, sizeof(expected));
234 235

	cl_git_pass(git_diff_blobs(
236
		heart, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
237

238
	assert_binary_blobs_comparison(&expected);
239 240 241 242 243 244 245

	git_blob_free(heart);
}

void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void)
{
	cl_git_pass(git_diff_blobs(
246
		alien, d, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
247

248
	assert_binary_blobs_comparison(&expected);
249

nulltoken committed
250
	memset(&expected, 0, sizeof(expected));
251 252

	cl_git_pass(git_diff_blobs(
253
		d, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
254

255
	assert_binary_blobs_comparison(&expected);
256
}
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

/*
 * $ git diff fe773770 a0f7217
 * diff --git a/fe773770 b/a0f7217
 * index fe77377..a0f7217 100644
 * --- a/fe773770
 * +++ b/a0f7217
 * @@ -1,6 +1,6 @@
 *  Here is some stuff at the start
 * 
 * -This should go in one hunk
 * +This should go in one hunk (first)
 * 
 *  Some additional lines
 * 
 * @@ -8,7 +8,7 @@ Down here below the other lines
 * 
 *  With even more at the end
 * 
 * -Followed by a second hunk of stuff
 * +Followed by a second hunk of stuff (second)
 * 
 *  That happens down here
 */
void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
{
	git_blob *old_d;
	git_oid old_d_oid;

	opts.context_lines = 3;

	/* tests/resources/attr/root_test1 from commit f5b0af1 */
	cl_git_pass(git_oid_fromstrn(&old_d_oid, "fe773770", 8));
	cl_git_pass(git_blob_lookup_prefix(&old_d, g_repo, &old_d_oid, 4));

	/* Test with default inter-hunk-context (not set) => default is 0 */
	cl_git_pass(git_diff_blobs(
294
		old_d, d, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
295

Russell Belfer committed
296
	cl_assert_equal_i(2, expected.hunks);
297 298 299 300 301

	/* Test with inter-hunk-context explicitly set to 0 */
	opts.interhunk_lines = 0;
	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blobs(
302
		old_d, d, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
303

Russell Belfer committed
304
	cl_assert_equal_i(2, expected.hunks);
305 306 307 308 309

	/* Test with inter-hunk-context explicitly set to 1 */
	opts.interhunk_lines = 1;
	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blobs(
310
		old_d, d, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
311

Russell Belfer committed
312
	cl_assert_equal_i(1, expected.hunks);
313 314 315

	git_blob_free(old_d);
}
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337

void test_diff_blob__checks_options_version_too_low(void)
{
	const git_error *err;

	opts.version = 0;
	cl_git_fail(git_diff_blobs(
		d, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	err = giterr_last();
	cl_assert_equal_i(GITERR_INVALID, err->klass);
}

void test_diff_blob__checks_options_version_too_high(void)
{
	const git_error *err;

	opts.version = 1024;
	cl_git_fail(git_diff_blobs(
		d, alien, &opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	err = giterr_last();
	cl_assert_equal_i(GITERR_INVALID, err->klass);
}
338 339 340 341 342 343 344 345 346 347 348 349

void test_diff_blob__can_correctly_detect_a_binary_blob_as_binary(void)
{
	/* alien.png */
	cl_assert_equal_i(true, git_blob_is_binary(alien));
}

void test_diff_blob__can_correctly_detect_a_textual_blob_as_non_binary(void)
{
	/* tests/resources/attr/root_test4.txt */
	cl_assert_equal_i(false, git_blob_is_binary(d));
}
350 351 352 353 354

/*
 * git_diff_blob_to_buffer tests
 */

355 356 357 358 359 360 361 362 363 364 365 366 367 368
static void assert_changed_single_one_line_file(
	diff_expects *expected, git_delta_t mod)
{
	cl_assert_equal_i(1, expected->files);
	cl_assert_equal_i(1, expected->file_status[mod]);
	cl_assert_equal_i(1, expected->hunks);
	cl_assert_equal_i(1, expected->lines);

	if (mod == GIT_DELTA_ADDED)
		cl_assert_equal_i(1, expected->line_adds);
	else if (mod == GIT_DELTA_DELETED)
		cl_assert_equal_i(1, expected->line_dels);
}

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
void test_diff_blob__can_compare_blob_to_buffer(void)
{
	git_blob *a;
	git_oid a_oid;
	const char *a_content = "Hello from the root\n";
	const char *b_content = "Hello from the root\n\nSome additional lines\n\nDown here below\n\n";

	/* tests/resources/attr/root_test1 */
	cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8));
	cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 4));

	/* diff from blob a to content of b */
	cl_git_pass(git_diff_blob_to_buffer(
		a, b_content, strlen(b_content),
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));

	cl_assert_equal_i(1, expected.files);
	cl_assert_equal_i(1, expected.file_status[GIT_DELTA_MODIFIED]);
	cl_assert_equal_i(0, expected.files_binary);
	cl_assert_equal_i(1, expected.hunks);
	cl_assert_equal_i(6, expected.lines);
	cl_assert_equal_i(1, expected.line_ctxt);
	cl_assert_equal_i(5, expected.line_adds);
	cl_assert_equal_i(0, expected.line_dels);

	/* diff from blob a to content of a */
	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		a, a_content, strlen(a_content),
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));

	assert_identical_blobs_comparison(&expected);

402
	/* diff from NULL blob to content of a */
403 404 405 406 407
	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		NULL, a_content, strlen(a_content),
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));

408
	assert_changed_single_one_line_file(&expected, GIT_DELTA_ADDED);
409 410 411 412 413 414 415

	/* diff from blob a to NULL buffer */
	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		a, NULL, 0,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));

416
	assert_changed_single_one_line_file(&expected, GIT_DELTA_DELETED);
417 418 419 420 421 422 423 424 425

	/* diff with reverse */
	opts.flags ^= GIT_DIFF_REVERSE;

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		a, NULL, 0,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));

426
	assert_changed_single_one_line_file(&expected, GIT_DELTA_ADDED);
427 428 429

	git_blob_free(a);
}
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531


static void assert_one_modified_with_lines(diff_expects *expected, int lines)
{
	cl_assert_equal_i(1, expected->files);
	cl_assert_equal_i(1, expected->file_status[GIT_DELTA_MODIFIED]);
	cl_assert_equal_i(0, expected->files_binary);
	cl_assert_equal_i(lines, expected->lines);
}

void test_diff_blob__binary_data_comparisons(void)
{
	git_blob *bin, *nonbin;
	git_oid oid;
	const char *nonbin_content = "Hello from the root\n";
	size_t nonbin_len = 20;
	const char *bin_content = "0123456789\n\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00\n0123456789\n";
	size_t bin_len = 33;

	cl_git_pass(git_oid_fromstrn(&oid, "45141a79", 8));
	cl_git_pass(git_blob_lookup_prefix(&nonbin, g_repo, &oid, 4));

	cl_git_pass(git_oid_fromstrn(&oid, "b435cd56", 8));
	cl_git_pass(git_blob_lookup_prefix(&bin, g_repo, &oid, 4));

	/* non-binary to reference content */

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		nonbin, nonbin_content, nonbin_len,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_identical_blobs_comparison(&expected);
	cl_assert_equal_i(0, expected.files_binary);

	/* binary to reference content */

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		bin, bin_content, bin_len,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_identical_blobs_comparison(&expected);

	cl_assert_equal_i(1, expected.files_binary);

	/* non-binary to binary content */

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		nonbin, bin_content, bin_len,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_binary_blobs_comparison(&expected);

	/* binary to non-binary content */

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		bin, nonbin_content, nonbin_len,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_binary_blobs_comparison(&expected);

	/* non-binary to binary blob */

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blobs(
		bin, nonbin, &opts,
		diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_binary_blobs_comparison(&expected);

	/*
	 * repeat with FORCE_TEXT
	 */

	opts.flags |= GIT_DIFF_FORCE_TEXT;

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		bin, bin_content, bin_len,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_identical_blobs_comparison(&expected);

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		nonbin, bin_content, bin_len,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_one_modified_with_lines(&expected, 4);

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blob_to_buffer(
		bin, nonbin_content, nonbin_len,
		&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_one_modified_with_lines(&expected, 4);

	memset(&expected, 0, sizeof(expected));
	cl_git_pass(git_diff_blobs(
		bin, nonbin, &opts,
		diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
	assert_one_modified_with_lines(&expected, 4);

	/* cleanup */
	git_blob_free(bin);
	git_blob_free(nonbin);
}