parse.c 6.54 KB
Newer Older
1
#include "clar_libgit2.h"
2
#include "patch.h"
3
#include "patch_parse.h"
4 5 6

#include "patch_common.h"

7
static void ensure_patch_validity(git_patch *patch)
8 9 10 11 12 13 14
{
	const git_diff_delta *delta;
	char idstr[GIT_OID_HEXSZ+1] = {0};

	cl_assert((delta = git_patch_get_delta(patch)) != NULL);
	cl_assert_equal_i(2, delta->nfiles);

15
	cl_assert_equal_s(delta->old_file.path, "file.txt");
16 17 18 19 20 21
	cl_assert(delta->old_file.mode == GIT_FILEMODE_BLOB);
	cl_assert_equal_i(7, delta->old_file.id_abbrev);
	git_oid_nfmt(idstr, delta->old_file.id_abbrev, &delta->old_file.id);
	cl_assert_equal_s(idstr, "9432026");
	cl_assert_equal_i(0, delta->old_file.size);

22
	cl_assert_equal_s(delta->new_file.path, "file.txt");
23 24 25 26 27
	cl_assert(delta->new_file.mode == GIT_FILEMODE_BLOB);
	cl_assert_equal_i(7, delta->new_file.id_abbrev);
	git_oid_nfmt(idstr, delta->new_file.id_abbrev, &delta->new_file.id);
	cl_assert_equal_s(idstr, "cd8fd12");
	cl_assert_equal_i(0, delta->new_file.size);
28 29
}

30 31 32 33 34 35 36 37 38 39 40 41
static void ensure_identical_patch_inout(const char *content) {
	git_buf buf = GIT_BUF_INIT;
	git_patch *patch;

	cl_git_pass(git_patch_from_buffer(&patch, content, strlen(content), NULL));
	cl_git_pass(git_patch_to_buf(&buf, patch));
	cl_assert_equal_strn(git_buf_cstr(&buf), content, strlen(content));

	git_patch_free(patch);
	git_buf_dispose(&buf);
}

42 43 44
void test_patch_parse__original_to_change_middle(void)
{
	git_patch *patch;
45

46 47 48 49
	cl_git_pass(git_patch_from_buffer(
		&patch, PATCH_ORIGINAL_TO_CHANGE_MIDDLE,
		strlen(PATCH_ORIGINAL_TO_CHANGE_MIDDLE), NULL));
	ensure_patch_validity(patch);
50 51
	git_patch_free(patch);
}
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

void test_patch_parse__leading_and_trailing_garbage(void)
{
	git_patch *patch;
	const char *leading = "This is some leading garbage.\n"
		"Maybe it's email headers?\n"
		"\n"
		PATCH_ORIGINAL_TO_CHANGE_MIDDLE;
	const char *trailing = PATCH_ORIGINAL_TO_CHANGE_MIDDLE
		"\n"
		"This is some trailing garbage.\n"
		"Maybe it's an email signature?\n";
	const char *both = "Here's some leading garbage\n"
		PATCH_ORIGINAL_TO_CHANGE_MIDDLE
		"And here's some trailing.\n";

	cl_git_pass(git_patch_from_buffer(&patch, leading, strlen(leading),
		NULL));
	ensure_patch_validity(patch);
	git_patch_free(patch);

	cl_git_pass(git_patch_from_buffer(&patch, trailing, strlen(trailing),
		NULL));
	ensure_patch_validity(patch);
	git_patch_free(patch);

	cl_git_pass(git_patch_from_buffer(&patch, both, strlen(both),
		NULL));
	ensure_patch_validity(patch);
	git_patch_free(patch);
}

void test_patch_parse__nonpatches_fail_with_notfound(void)
{
	git_patch *patch;

	cl_git_fail_with(GIT_ENOTFOUND,
		git_patch_from_buffer(&patch, PATCH_NOT_A_PATCH,
		strlen(PATCH_NOT_A_PATCH), NULL));
}

void test_patch_parse__invalid_patches_fails(void)
{
	git_patch *patch;

	cl_git_fail_with(GIT_ERROR,
		git_patch_from_buffer(&patch, PATCH_CORRUPT_GIT_HEADER,
		strlen(PATCH_CORRUPT_GIT_HEADER), NULL));
	cl_git_fail_with(GIT_ERROR,
		git_patch_from_buffer(&patch,
		PATCH_CORRUPT_MISSING_NEW_FILE,
		strlen(PATCH_CORRUPT_MISSING_NEW_FILE), NULL));
	cl_git_fail_with(GIT_ERROR,
		git_patch_from_buffer(&patch,
		PATCH_CORRUPT_MISSING_OLD_FILE,
		strlen(PATCH_CORRUPT_MISSING_OLD_FILE), NULL));
	cl_git_fail_with(GIT_ERROR,
		git_patch_from_buffer(&patch, PATCH_CORRUPT_NO_CHANGES,
		strlen(PATCH_CORRUPT_NO_CHANGES), NULL));
	cl_git_fail_with(GIT_ERROR,
		git_patch_from_buffer(&patch,
		PATCH_CORRUPT_MISSING_HUNK_HEADER,
		strlen(PATCH_CORRUPT_MISSING_HUNK_HEADER), NULL));
}

117 118
void test_patch_parse__no_newline_at_end_of_new_file(void)
{
119
	ensure_identical_patch_inout(PATCH_APPEND_NO_NL);
120 121 122 123
}

void test_patch_parse__no_newline_at_end_of_old_file(void)
{
124
	ensure_identical_patch_inout(PATCH_APPEND_NO_NL_IN_OLD_FILE);
125 126
}

127 128
void test_patch_parse__files_with_whitespaces_succeeds(void)
{
129
	ensure_identical_patch_inout(PATCH_NAME_WHITESPACE);
130
}
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

void test_patch_parse__lifetime_of_patch_does_not_depend_on_buffer(void)
{
	git_buf diff = GIT_BUF_INIT, rendered = GIT_BUF_INIT;
	git_patch *patch;

	cl_git_pass(git_buf_sets(&diff, PATCH_ORIGINAL_TO_CHANGE_MIDDLE));
	cl_git_pass(git_patch_from_buffer(&patch, diff.ptr, diff.size, NULL));
	git_buf_dispose(&diff);

	cl_git_pass(git_patch_to_buf(&rendered, patch));
	cl_assert_equal_s(PATCH_ORIGINAL_TO_CHANGE_MIDDLE, rendered.ptr);
	git_buf_dispose(&rendered);

	cl_git_pass(git_patch_to_buf(&rendered, patch));
	cl_assert_equal_s(PATCH_ORIGINAL_TO_CHANGE_MIDDLE, rendered.ptr);
	git_buf_dispose(&rendered);

	git_patch_free(patch);
}
151

152 153 154 155 156 157 158
void test_patch_parse__binary_file_with_missing_paths(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_WITH_MISSING_PATHS,
					  strlen(PATCH_BINARY_FILE_WITH_MISSING_PATHS), NULL));
}

159 160 161 162 163 164 165 166 167 168 169 170 171 172
void test_patch_parse__binary_file_with_whitespace_paths(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_WITH_WHITESPACE_PATHS,
					  strlen(PATCH_BINARY_FILE_WITH_WHITESPACE_PATHS), NULL));
}

void test_patch_parse__binary_file_with_empty_quoted_paths(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_WITH_QUOTED_EMPTY_PATHS,
					  strlen(PATCH_BINARY_FILE_WITH_QUOTED_EMPTY_PATHS), NULL));
}

173 174 175 176 177 178 179 180 181 182 183 184 185 186
void test_patch_parse__binary_file_path_with_spaces(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_PATH_WITH_SPACES,
					  strlen(PATCH_BINARY_FILE_PATH_WITH_SPACES), NULL));
}

void test_patch_parse__binary_file_path_without_body_paths(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_PATH_WITHOUT_BODY_PATHS,
					  strlen(PATCH_BINARY_FILE_PATH_WITHOUT_BODY_PATHS), NULL));
}

187 188 189 190 191 192 193 194
void test_patch_parse__binary_file_with_truncated_delta(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_WITH_TRUNCATED_DELTA,
					  strlen(PATCH_BINARY_FILE_WITH_TRUNCATED_DELTA), NULL));
	cl_assert_equal_s(git_error_last()->message, "truncated binary data at line 5");
}

195 196 197 198 199
void test_patch_parse__memory_leak_on_multiple_paths(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_MULTIPLE_OLD_PATHS, strlen(PATCH_MULTIPLE_OLD_PATHS), NULL));
}
200 201 202 203 204 205 206 207 208 209 210 211 212

void test_patch_parse__truncated_no_newline_at_end_of_file(void)
{
	size_t len = strlen(PATCH_APPEND_NO_NL) - strlen("at end of file\n");
	const git_diff_line *line;
	git_patch *patch;

	cl_git_pass(git_patch_from_buffer(&patch, PATCH_APPEND_NO_NL, len, NULL));
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 4));
	cl_assert_equal_s(line->content, "\\ No newline ");

	git_patch_free(patch);
}
213 214 215 216 217 218 219

void test_patch_parse__line_number_overflow(void)
{
	git_patch *patch;
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_INTMAX_NEW_LINES, strlen(PATCH_INTMAX_NEW_LINES), NULL));
	git_patch_free(patch);
}