summaryrefslogtreecommitdiff
path: root/tests/libgit2/patch
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-11-16 23:29:22 -0500
committerEdward Thomson <ethomson@edwardthomson.com>2022-02-22 22:07:45 -0500
commit3344fddc97bbdea9c1b6ebb6f7fb6dbd70b41dfb (patch)
treefd6368a72944571c51627b40c592e7d58e0036e1 /tests/libgit2/patch
parent91ba089663f5efc3bd4ba14a5099372cf5ce57a6 (diff)
downloadlibgit2-3344fddc97bbdea9c1b6ebb6f7fb6dbd70b41dfb.tar.gz
refactor: `tests` is now `tests/libgit2`
Like we want to separate libgit2 and utility source code, we want to separate libgit2 and utility tests. Start by moving all the tests into libgit2.
Diffstat (limited to 'tests/libgit2/patch')
-rw-r--r--tests/libgit2/patch/parse.c221
-rw-r--r--tests/libgit2/patch/patch_common.h1005
-rw-r--r--tests/libgit2/patch/print.c186
3 files changed, 1412 insertions, 0 deletions
diff --git a/tests/libgit2/patch/parse.c b/tests/libgit2/patch/parse.c
new file mode 100644
index 000000000..a3c4c6730
--- /dev/null
+++ b/tests/libgit2/patch/parse.c
@@ -0,0 +1,221 @@
+#include "clar_libgit2.h"
+#include "patch.h"
+#include "patch_parse.h"
+
+#include "patch_common.h"
+
+static void ensure_patch_validity(git_patch *patch)
+{
+ 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);
+
+ cl_assert_equal_s(delta->old_file.path, "file.txt");
+ 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);
+
+ cl_assert_equal_s(delta->new_file.path, "file.txt");
+ 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);
+}
+
+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(buf.ptr, content, strlen(content));
+
+ git_patch_free(patch);
+ git_buf_dispose(&buf);
+}
+
+void test_patch_parse__original_to_change_middle(void)
+{
+ git_patch *patch;
+
+ cl_git_pass(git_patch_from_buffer(
+ &patch, PATCH_ORIGINAL_TO_CHANGE_MIDDLE,
+ strlen(PATCH_ORIGINAL_TO_CHANGE_MIDDLE), NULL));
+ ensure_patch_validity(patch);
+ git_patch_free(patch);
+}
+
+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));
+}
+
+void test_patch_parse__no_newline_at_end_of_new_file(void)
+{
+ ensure_identical_patch_inout(PATCH_APPEND_NO_NL);
+}
+
+void test_patch_parse__no_newline_at_end_of_old_file(void)
+{
+ ensure_identical_patch_inout(PATCH_APPEND_NO_NL_IN_OLD_FILE);
+}
+
+void test_patch_parse__files_with_whitespaces_succeeds(void)
+{
+ ensure_identical_patch_inout(PATCH_NAME_WHITESPACE);
+}
+
+void test_patch_parse__lifetime_of_patch_does_not_depend_on_buffer(void)
+{
+ git_str diff = GIT_STR_INIT;
+ git_buf rendered = GIT_BUF_INIT;
+ git_patch *patch;
+
+ cl_git_pass(git_str_sets(&diff, PATCH_ORIGINAL_TO_CHANGE_MIDDLE));
+ cl_git_pass(git_patch_from_buffer(&patch, diff.ptr, diff.size, NULL));
+ git_str_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);
+}
+
+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));
+}
+
+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));
+}
+
+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));
+}
+
+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");
+}
+
+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));
+}
+
+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);
+}
+
+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);
+}
diff --git a/tests/libgit2/patch/patch_common.h b/tests/libgit2/patch/patch_common.h
new file mode 100644
index 000000000..1e03889fc
--- /dev/null
+++ b/tests/libgit2/patch/patch_common.h
@@ -0,0 +1,1005 @@
+/* The original file contents */
+
+#define FILE_ORIGINAL \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+/* A change in the middle of the file (and the resultant patch) */
+
+#define FILE_CHANGE_MIDDLE \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(THIS line is changed!)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_CHANGE_MIDDLE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -3,7 +3,7 @@ this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define PATCH_ORIGINAL_TO_CHANGE_MIDDLE_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -6 +6 @@ yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n"
+
+/* A change of the first line (and the resultant patch) */
+
+#define FILE_CHANGE_FIRSTLINE \
+ "hey, change in head!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..c81df1d 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,4 +1,4 @@\n" \
+ "-hey!\n" \
+ "+hey, change in head!\n" \
+ " this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n"
+
+/* A change of the last line (and the resultant patch) */
+
+#define FILE_CHANGE_LASTLINE \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "change to the last line.\n"
+
+#define PATCH_ORIGINAL_TO_CHANGE_LASTLINE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..f70db1c 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -6,4 +6,4 @@ yes it is!\n" \
+ " (this line is changed)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ "-below it!\n" \
+ "+change to the last line.\n"
+
+/* A change of the middle where we remove many lines */
+
+#define FILE_CHANGE_MIDDLE_SHRINK \
+ "hey!\n" \
+ "i've changed a lot, but left the line\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_CHANGE_MIDDLE_SHRINK \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..629cd35 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,9 +1,3 @@\n" \
+ " hey!\n" \
+ "-this is some context!\n" \
+ "-around some lines\n" \
+ "-that will change\n" \
+ "-yes it is!\n" \
+ "-(this line is changed)\n" \
+ "-and this\n" \
+ "-is additional context\n" \
+ "+i've changed a lot, but left the line\n" \
+ " below it!\n"
+
+#define PATCH_ORIGINAL_TO_MIDDLE_SHRINK_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..629cd35 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -2,7 +2 @@ hey!\n" \
+ "-this is some context!\n" \
+ "-around some lines\n" \
+ "-that will change\n" \
+ "-yes it is!\n" \
+ "-(this line is changed)\n" \
+ "-and this\n" \
+ "-is additional context\n" \
+ "+i've changed a lot, but left the line\n"
+
+/* A change to the middle where we grow many lines */
+
+#define FILE_CHANGE_MIDDLE_GROW \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "this line is changed\n" \
+ "and this line is added\n" \
+ "so is this\n" \
+ "(this too)\n" \
+ "whee...\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_CHANGE_MIDDLE_GROW \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..207ebca 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -3,7 +3,11 @@ this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+this line is changed\n" \
+ "+and this line is added\n" \
+ "+so is this\n" \
+ "+(this too)\n" \
+ "+whee...\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+
+#define PATCH_ORIGINAL_TO_MIDDLE_GROW_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..207ebca 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -6 +6,5 @@ yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+this line is changed\n" \
+ "+and this line is added\n" \
+ "+so is this\n" \
+ "+(this too)\n" \
+ "+whee...\n"
+
+/* An insertion at the beginning of the file (and the resultant patch) */
+
+#define FILE_PREPEND \
+ "insert at front\n" \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_PREPEND \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..0f39b9a 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,3 +1,4 @@\n" \
+ "+insert at front\n" \
+ " hey!\n" \
+ " this is some context!\n" \
+ " around some lines\n"
+
+#define PATCH_ORIGINAL_TO_PREPEND_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..0f39b9a 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -0,0 +1 @@\n" \
+ "+insert at front\n"
+
+/* An insertion at the beginning of the file and change in the middle */
+
+#define FILE_PREPEND_AND_CHANGE \
+ "insert at front\n" \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(THIS line is changed!)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..f73c8bb 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,9 +1,10 @@\n" \
+ "+insert at front\n" \
+ " hey!\n" \
+ " this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..f73c8bb 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -0,0 +1 @@\n" \
+ "+insert at front\n" \
+ "@@ -6 +7 @@ yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n"
+
+/* A change in the middle and a deletion of the newline at the end of the file */
+
+#define FILE_CHANGE_MIDDLE_AND_LASTLINE \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(THIS line is changed!)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "BELOW it! - (THIS line is changed!)"
+
+#define PATCH_ORIGINAL_TO_CHANGE_MIDDLE_AND_LASTLINE_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..e05d36c 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -6 +6 @@ yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ "@@ -9 +9 @@ is additional context\n" \
+ "-below it!\n" \
+ "+BELOW it! - (THIS line is changed!)\n" \
+ "\\ No newline at end of file\n"
+
+/* A deletion at the beginning of the file and a change in the middle */
+
+#define FILE_DELETE_AND_CHANGE \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(THIS line is changed!)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_DELETE_AND_CHANGE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..1e2dfa6 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,9 +1,8 @@\n" \
+ "-hey!\n" \
+ " this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define PATCH_ORIGINAL_TO_DELETE_AND_CHANGE_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..1e2dfa6 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1 +0,0 @@\n" \
+ "-hey!\n" \
+ "@@ -6 +5 @@ yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n"
+
+/* A deletion at the beginning of the file */
+
+#define FILE_DELETE_FIRSTLINE \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n"
+
+#define PATCH_ORIGINAL_TO_DELETE_FIRSTLINE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..f31fa13 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,4 +1,3 @@\n" \
+ "-hey!\n" \
+ " this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n"
+
+/* An insertion at the end of the file (and the resultant patch) */
+
+#define FILE_APPEND \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n" \
+ "insert at end\n"
+
+#define PATCH_ORIGINAL_TO_APPEND \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..72788bb 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -7,3 +7,4 @@ yes it is!\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n" \
+ "+insert at end\n"
+
+#define PATCH_ORIGINAL_TO_APPEND_NOCONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..72788bb 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -9,0 +10 @@ below it!\n" \
+ "+insert at end\n"
+
+#define PATCH_DELETED_FILE_2_HUNKS \
+ "diff --git a/a b/a\n" \
+ "index 7f129fd..af431f2 100644\n" \
+ "--- a/a\n" \
+ "+++ b/a\n" \
+ "@@ -1 +1 @@\n" \
+ "-a contents 2\n" \
+ "+a contents\n" \
+ "diff --git a/c/d b/c/d\n" \
+ "deleted file mode 100644\n" \
+ "index 297efb8..0000000\n" \
+ "--- a/c/d\n" \
+ "+++ /dev/null\n" \
+ "@@ -1 +0,0 @@\n" \
+ "-c/d contents\n"
+
+#define PATCH_DELETED_FILE_2_HUNKS_SHUFFLED \
+ "diff --git a/c/d b/c/d\n" \
+ "deleted file mode 100644\n" \
+ "index 297efb8..0000000\n" \
+ "--- a/c/d\n" \
+ "+++ /dev/null\n" \
+ "@@ -1 +0,0 @@\n" \
+ "-c/d contents\n" \
+ "diff --git a/a b/a\n" \
+ "index 7f129fd..af431f2 100644\n" \
+ "--- a/a\n" \
+ "+++ b/a\n" \
+ "@@ -1 +1 @@\n" \
+ "-a contents 2\n" \
+ "+a contents\n"
+
+#define PATCH_SIMPLE_COMMIT \
+ "commit 15e119375018fba121cf58e02a9f17fe22df0df8\n" \
+ "Author: Edward Thomson <ethomson@edwardthomson.com>\n" \
+ "Date: Wed Jun 14 13:31:20 2017 +0200\n" \
+ "\n" \
+ " CHANGELOG: document git_filter_init and GIT_FILTER_INIT\n" \
+ "\n" \
+ "diff --git a/CHANGELOG.md b/CHANGELOG.md\n" \
+ "index 1b9e0c90a..24ecba426 100644\n" \
+ "--- a/CHANGELOG.md\n" \
+ "+++ b/CHANGELOG.md\n" \
+ "@@ -96,6 +96,9 @@ v0.26\n" \
+ " * `git_transport_smart_proxy_options()' enables you to get the proxy options for\n" \
+ " smart transports.\n" \
+ "\n" \
+ "+* The `GIT_FILTER_INIT` macro and the `git_filter_init` function are provided\n" \
+ "+ to initialize a `git_filter` structure.\n" \
+ "+\n" \
+ " ### Breaking API changes\n" \
+ "\n" \
+ " * `clone_checkout_strategy` has been removed from\n"
+
+#define PATCH_MULTIPLE_HUNKS \
+ "diff --git a/x b/x\n" \
+ "index 0719398..fa0350c 100644\n" \
+ "--- a/x\n" \
+ "+++ b/x\n" \
+ "@@ -1,5 +1,4 @@\n" \
+ " 1\n" \
+ "-2\n" \
+ " 3\n" \
+ " 4\n" \
+ " 5\n" \
+ "@@ -7,3 +6,4 @@\n" \
+ " 7\n" \
+ " 8\n" \
+ " 9\n" \
+ "+10\n"
+
+#define PATCH_MULTIPLE_FILES \
+ "diff --git a/x b/x\n" \
+ "index 8a1218a..7059ba5 100644\n" \
+ "--- a/x\n" \
+ "+++ b/x\n" \
+ "@@ -1,5 +1,4 @@\n" \
+ " 1\n" \
+ " 2\n" \
+ "-3\n" \
+ " 4\n" \
+ " 5\n" \
+ "diff --git a/y b/y\n" \
+ "index e006065..9405325 100644\n" \
+ "--- a/y\n" \
+ "+++ b/y\n" \
+ "@@ -1,4 +1,5 @@\n" \
+ " a\n" \
+ " b\n" \
+ "+c\n" \
+ " d\n" \
+ " e\n"
+
+#define FILE_PREPEND_AND_APPEND \
+ "first and\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "last lines\n"
+
+#define PATCH_ORIGINAL_TO_PREPEND_AND_APPEND \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..f282430 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,4 +1,4 @@\n" \
+ "-hey!\n" \
+ "+first and\n" \
+ " this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ "@@ -6,4 +6,4 @@ yes it is!\n" \
+ " (this line is changed)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ "-below it!\n" \
+ "+last lines\n"
+
+#define PATCH_ORIGINAL_TO_EMPTY_FILE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..e69de29 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,9 +0,0 @@\n" \
+ "-hey!\n" \
+ "-this is some context!\n" \
+ "-around some lines\n" \
+ "-that will change\n" \
+ "-yes it is!\n" \
+ "-(this line is changed)\n" \
+ "-and this\n" \
+ "-is additional context\n" \
+ "-below it!\n"
+
+#define PATCH_EMPTY_FILE_TO_ORIGINAL \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index e69de29..9432026 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -0,0 +1,9 @@\n" \
+ "+hey!\n" \
+ "+this is some context!\n" \
+ "+around some lines\n" \
+ "+that will change\n" \
+ "+yes it is!\n" \
+ "+(this line is changed)\n" \
+ "+and this\n" \
+ "+is additional context\n" \
+ "+below it!\n"
+
+#define PATCH_ADD_ORIGINAL \
+ "diff --git a/file.txt b/file.txt\n" \
+ "new file mode 100644\n" \
+ "index 0000000..9432026\n" \
+ "--- /dev/null\n" \
+ "+++ b/file.txt\n" \
+ "@@ -0,0 +1,9 @@\n" \
+ "+hey!\n" \
+ "+this is some context!\n" \
+ "+around some lines\n" \
+ "+that will change\n" \
+ "+yes it is!\n" \
+ "+(this line is changed)\n" \
+ "+and this\n" \
+ "+is additional context\n" \
+ "+below it!\n"
+
+#define PATCH_DELETE_ORIGINAL \
+ "diff --git a/file.txt b/file.txt\n" \
+ "deleted file mode 100644\n" \
+ "index 9432026..0000000\n" \
+ "--- a/file.txt\n" \
+ "+++ /dev/null\n" \
+ "@@ -1,9 +0,0 @@\n" \
+ "-hey!\n" \
+ "-this is some context!\n" \
+ "-around some lines\n" \
+ "-that will change\n" \
+ "-yes it is!\n" \
+ "-(this line is changed)\n" \
+ "-and this\n" \
+ "-is additional context\n" \
+ "-below it!\n"
+
+#define PATCH_RENAME_EXACT \
+ "diff --git a/file.txt b/newfile.txt\n" \
+ "similarity index 100%\n" \
+ "rename from file.txt\n" \
+ "rename to newfile.txt\n"
+
+#define PATCH_RENAME_EXACT_WITH_MODE \
+ "diff --git a/RENAMED.md b/README.md\n" \
+ "old mode 100644\n" \
+ "new mode 100755\n" \
+ "similarity index 100%\n" \
+ "rename from RENAMED.md\n" \
+ "rename to README.md\n"
+
+#define PATCH_RENAME_SIMILAR \
+ "diff --git a/file.txt b/newfile.txt\n" \
+ "similarity index 77%\n" \
+ "rename from file.txt\n" \
+ "rename to newfile.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/newfile.txt\n" \
+ "@@ -3,7 +3,7 @@ this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define PATCH_RENAME_EXACT_QUOTEDNAME \
+ "diff --git a/file.txt \"b/foo\\\"bar.txt\"\n" \
+ "similarity index 100%\n" \
+ "rename from file.txt\n" \
+ "rename to \"foo\\\"bar.txt\"\n"
+
+#define PATCH_RENAME_SIMILAR_QUOTEDNAME \
+ "diff --git a/file.txt \"b/foo\\\"bar.txt\"\n" \
+ "similarity index 77%\n" \
+ "rename from file.txt\n" \
+ "rename to \"foo\\\"bar.txt\"\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ \"b/foo\\\"bar.txt\"\n" \
+ "@@ -3,7 +3,7 @@ this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define PATCH_MODECHANGE_UNCHANGED \
+ "diff --git a/file.txt b/file.txt\n" \
+ "old mode 100644\n" \
+ "new mode 100755\n"
+
+#define PATCH_MODECHANGE_MODIFIED \
+ "diff --git a/file.txt b/file.txt\n" \
+ "old mode 100644\n" \
+ "new mode 100755\n" \
+ "index 9432026..cd8fd12\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -3,7 +3,7 @@ this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define PATCH_NOISY \
+ "This is some\nleading noise\n@@ - that\nlooks like a hunk header\n" \
+ "but actually isn't and should parse ok\n" \
+ PATCH_ORIGINAL_TO_CHANGE_MIDDLE \
+ "plus some trailing garbage for good measure\n"
+
+#define PATCH_NOISY_NOCONTEXT \
+ "This is some\nleading noise\n@@ - that\nlooks like a hunk header\n" \
+ "but actually isn't and should parse ok\n" \
+ PATCH_ORIGINAL_TO_CHANGE_MIDDLE_NOCONTEXT \
+ "plus some trailing garbage for good measure\n"
+
+#define PATCH_TRUNCATED_1 \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -3,7 +3,7 @@ this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n"
+
+#define PATCH_TRUNCATED_2 \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -3,7 +3,7 @@ this is some context!\n" \
+ " around some lines\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define PATCH_TRUNCATED_3 \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -3,7 +3,7 @@ this is some context!\n" \
+ " around some lines\n" \
+ " that will change\n" \
+ " yes it is!\n" \
+ "+(THIS line is changed!)\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n"
+
+#define FILE_EMPTY_CONTEXT_ORIGINAL \
+ "this\nhas\nan\n\nempty\ncontext\nline\n"
+
+#define FILE_EMPTY_CONTEXT_MODIFIED \
+ "this\nhas\nan\n\nempty...\ncontext\nline\n"
+
+#define PATCH_EMPTY_CONTEXT \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 398d2df..bb15234 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -2,6 +2,6 @@ this\n" \
+ " has\n" \
+ " an\n" \
+ "\n" \
+ "-empty\n" \
+ "+empty...\n" \
+ " context\n" \
+ " line\n"
+
+#define FILE_APPEND_NO_NL \
+ "hey!\n" \
+ "this is some context!\n" \
+ "around some lines\n" \
+ "that will change\n" \
+ "yes it is!\n" \
+ "(this line is changed)\n" \
+ "and this\n" \
+ "is additional context\n" \
+ "below it!\n" \
+ "added line with no nl"
+
+#define PATCH_APPEND_NO_NL \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..83759c0 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -7,3 +7,4 @@ yes it is!\n" \
+ " and this\n" \
+ " is additional context\n" \
+ " below it!\n" \
+ "+added line with no nl\n" \
+ "\\ No newline at end of file\n"
+
+#define PATCH_APPEND_NO_NL_IN_OLD_FILE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..83759c0 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -1,1 +1,1 @@\n" \
+ "-foo\n" \
+ "\\ No newline at end of file\n" \
+ "+foo\n"
+
+#define PATCH_NAME_WHITESPACE \
+ "diff --git a/file with spaces.txt b/file with spaces.txt\n" \
+ "index 9432026..83759c0 100644\n" \
+ "--- a/file with spaces.txt\n" \
+ "+++ b/file with spaces.txt\n" \
+ "@@ -0,3 +0,2 @@\n" \
+ " and this\n" \
+ "-is additional context\n" \
+ " below it!\n" \
+
+#define PATCH_CORRUPT_GIT_HEADER \
+ "diff --git a/file.txt\n" \
+ "index 9432026..0f39b9a 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -0,0 +1 @@\n" \
+ "+insert at front\n"
+
+#define PATCH_CORRUPT_MISSING_NEW_FILE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "@@ -6 +6 @@ yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n"
+
+#define PATCH_CORRUPT_MISSING_OLD_FILE \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "+++ b/file.txt\n" \
+ "@@ -6 +6 @@ yes it is!\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n"
+
+#define PATCH_CORRUPT_NO_CHANGES \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "@@ -0,0 +0,0 @@ yes it is!\n"
+
+#define PATCH_CORRUPT_MISSING_HUNK_HEADER \
+ "diff --git a/file.txt b/file.txt\n" \
+ "index 9432026..cd8fd12 100644\n" \
+ "--- a/file.txt\n" \
+ "+++ b/file.txt\n" \
+ "-(this line is changed)\n" \
+ "+(THIS line is changed!)\n"
+
+#define PATCH_NOT_A_PATCH \
+ "+++this is not\n" \
+ "--actually even\n" \
+ " a legitimate \n" \
+ "+patch file\n" \
+ "-it's something else\n" \
+ " entirely!"
+
+/* binary contents */
+
+#define FILE_BINARY_LITERAL_ORIGINAL "\x00\x00\x0a"
+#define FILE_BINARY_LITERAL_ORIGINAL_LEN 3
+
+#define FILE_BINARY_LITERAL_MODIFIED "\x00\x00\x01\x02\x0a"
+#define FILE_BINARY_LITERAL_MODIFIED_LEN 5
+
+#define PATCH_BINARY_LITERAL \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "index bd474b2519cc15eab801ff851cc7d50f0dee49a1..9ac35ff15cd8864aeafd889e4826a3150f0b06c4 100644\n" \
+ "GIT binary patch\n" \
+ "literal 5\n" \
+ "Mc${NkU}WL~000&M4gdfE\n" \
+ "\n" \
+ "literal 3\n" \
+ "Kc${Nk-~s>u4FC%O\n\n"
+
+#define FILE_BINARY_DELTA_ORIGINAL \
+ "\x00\x00\x01\x02\x00\x00\x01\x02\x00\x00\x01\x02\x0a\x54\x68\x69" \
+ "\x73\x20\x69\x73\x20\x61\x20\x62\x69\x6e\x61\x72\x79\x20\x66\x69" \
+ "\x6c\x65\x2c\x20\x62\x79\x20\x76\x69\x72\x74\x75\x65\x20\x6f\x66" \
+ "\x20\x68\x61\x76\x69\x6e\x67\x20\x73\x6f\x6d\x65\x20\x6e\x75\x6c" \
+ "\x6c\x73\x2e\x0a\x00\x00\x01\x02\x00\x00\x01\x02\x00\x00\x01\x02" \
+ "\x0a\x57\x65\x27\x72\x65\x20\x67\x6f\x69\x6e\x67\x20\x74\x6f\x20" \
+ "\x63\x68\x61\x6e\x67\x65\x20\x70\x6f\x72\x74\x69\x6f\x6e\x73\x20" \
+ "\x6f\x66\x20\x69\x74\x2e\x0a\x00\x00\x01\x02\x00\x00\x01\x02\x00" \
+ "\x00\x01\x02\x0a\x53\x6f\x20\x74\x68\x61\x74\x20\x77\x65\x20\x67" \
+ "\x69\x74\x20\x61\x20\x62\x69\x6e\x61\x72\x79\x20\x64\x65\x6c\x74" \
+ "\x61\x20\x69\x6e\x73\x74\x65\x61\x64\x20\x6f\x66\x20\x74\x68\x65" \
+ "\x20\x64\x65\x66\x6c\x61\x74\x65\x64\x20\x63\x6f\x6e\x74\x65\x6e" \
+ "\x74\x73\x2e\x0a\x00\x00\x01\x02\x00\x00\x01\x02\x00\x00\x01\x02" \
+ "\x0a"
+#define FILE_BINARY_DELTA_ORIGINAL_LEN 209
+
+#define FILE_BINARY_DELTA_MODIFIED \
+ "\x00\x00\x01\x02\x00\x00\x01\x02\x00\x00\x01\x02\x0a\x5a\x5a\x5a" \
+ "\x5a\x20\x69\x73\x20\x61\x20\x62\x69\x6e\x61\x72\x79\x20\x66\x69" \
+ "\x6c\x65\x2c\x20\x62\x79\x20\x76\x69\x72\x74\x75\x65\x20\x6f\x66" \
+ "\x20\x68\x61\x76\x69\x6e\x67\x20\x73\x6f\x6d\x65\x20\x6e\x75\x6c" \
+ "\x6c\x73\x2e\x0a\x00\x00\x01\x02\x00\x00\x01\x02\x00\x00\x01\x02" \
+ "\x0a\x57\x65\x27\x72\x65\x20\x67\x6f\x69\x6e\x67\x20\x74\x6f\x20" \
+ "\x63\x68\x61\x6e\x67\x65\x20\x70\x6f\x72\x74\x69\x6f\x6e\x73\x20" \
+ "\x6f\x66\x20\x49\x54\x2e\x0a\x00\x00\x01\x02\x00\x00\x01\x02\x00" \
+ "\x00\x01\x02\x0a\x53\x4f\x20\x74\x68\x61\x74\x20\x77\x65\x20\x67" \
+ "\x69\x74\x20\x61\x20\x62\x69\x6e\x61\x72\x79\x20\x64\x65\x6c\x74" \
+ "\x61\x20\x69\x6e\x73\x74\x65\x61\x64\x20\x6f\x66\x20\x74\x68\x65" \
+ "\x20\x64\x65\x66\x6c\x61\x74\x65\x64\x20\x63\x6f\x6e\x74\x65\x6e" \
+ "\x74\x73\x2e\x0a\x00\x00\x01\x02\x00\x00\x01\x02\x00\x00\x01\x02" \
+ "\x0a"
+#define FILE_BINARY_DELTA_MODIFIED_LEN 209
+
+#define PATCH_BINARY_DELTA \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "index 27184d9883b12c4c9c54b4a31137603586169f51..7c94f9e60bf366033d98e0d551ae37d30faef74a 100644\n" \
+ "GIT binary patch\n" \
+ "delta 48\n" \
+ "kc$~Y)c#%<%fq{_;hPk4EV4`4>uxE%K7m7r%|HL+L0In7XGynhq\n" \
+ "\n" \
+ "delta 48\n" \
+ "mc$~Y)c#%<%fq{_;hPgsAGK(h)CJASj=y9P)1m{m|^9BI99|yz$\n\n"
+
+#define PATCH_BINARY_ADD \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "new file mode 100644\n" \
+ "index 0000000000000000000000000000000000000000..7c94f9e60bf366033d98e0d551ae37d30faef74a\n" \
+ "GIT binary patch\n" \
+ "literal 209\n" \
+ "zc${60u?oUK5JXSQe8qG&;(u6KC<u0&+$Ohh?#kUJlD{_rLCL^0!@QXgcKh&k^H>C_\n" \
+ "zAhe=XX7rNzh<3&##YcwqNHmEKsP<&&m~%Zf;eX@Khr$?aExDmfqyyt+#l^I)3+LMg\n" \
+ "kxnAIj9Pfn_|Gh`fP7tlm6j#y{FJYg_IifRlR^R@A08f862mk;8\n" \
+ "\n" \
+ "literal 0\n" \
+ "Hc$@<O00001\n\n"
+
+#define PATCH_BINARY_DELETE \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "deleted file mode 100644\n" \
+ "index 7c94f9e60bf366033d98e0d551ae37d30faef74a..0000000000000000000000000000000000000000\n" \
+ "GIT binary patch\n" \
+ "literal 0\n" \
+ "Hc$@<O00001\n" \
+ "\n" \
+ "literal 209\n" \
+ "zc${60u?oUK5JXSQe8qG&;(u6KC<u0&+$Ohh?#kUJlD{_rLCL^0!@QXgcKh&k^H>C_\n" \
+ "zAhe=XX7rNzh<3&##YcwqNHmEKsP<&&m~%Zf;eX@Khr$?aExDmfqyyt+#l^I)3+LMg\n" \
+ "kxnAIj9Pfn_|Gh`fP7tlm6j#y{FJYg_IifRlR^R@A08f862mk;8\n\n"
+
+/* contains an old side that does not match the expected source */
+#define PATCH_BINARY_NOT_REVERSIBLE \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "index 27184d9883b12c4c9c54b4a31137603586169f51..7c94f9e60bf366033d98e0d551ae37d30faef74a 100644\n" \
+ "GIT binary patch\n" \
+ "literal 5\n" \
+ "Mc${NkU}WL~000&M4gdfE\n" \
+ "\n" \
+ "delta 48\n" \
+ "mc$~Y)c#%<%fq{_;hPgsAGK(h)CJASj=y9P)1m{m|^9BI99|yz$\n\n"
+
+#define PATCH_BINARY_NOT_PRINTED \
+ "diff --git a/binary.bin b/binary.bin\n" \
+ "index 27184d9..7c94f9e 100644\n" \
+ "Binary files a/binary.bin and b/binary.bin differ\n"
+
+#define PATCH_ADD_BINARY_NOT_PRINTED \
+ "diff --git a/test.bin b/test.bin\n" \
+ "new file mode 100644\n" \
+ "index 0000000..9e0f96a\n" \
+ "Binary files /dev/null and b/test.bin differ\n"
+
+#define PATCH_ORIGINAL_NEW_FILE_WITH_SPACE \
+ "diff --git a/sp ace.txt b/sp ace.txt\n" \
+ "new file mode 100644\n" \
+ "index 000000000..789819226\n" \
+ "--- /dev/null\n" \
+ "+++ b/sp ace.txt\n" \
+ "@@ -0,0 +1 @@\n" \
+ "+a\n"
+
+#define PATCH_CRLF \
+ "diff --git a/test-file b/test-file\r\n" \
+ "new file mode 100644\r\n" \
+ "index 0000000..af431f2 100644\r\n" \
+ "--- /dev/null\r\n" \
+ "+++ b/test-file\r\n" \
+ "@@ -0,0 +1 @@\r\n" \
+ "+a contents\r\n"
+
+#define PATCH_NO_EXTENDED_HEADERS \
+ "diff --git a/file b/file\n" \
+ "--- a/file\n" \
+ "+++ b/file\n" \
+ "@@ -1,3 +1,3 @@\n" \
+ " a\n" \
+ "-b\n" \
+ "+bb\n" \
+ " c\n"
+
+#define PATCH_BINARY_FILE_WITH_MISSING_PATHS \
+ "diff --git \n" \
+ "--- \n" \
+ "+++ \n" \
+ "Binary files "
+
+#define PATCH_BINARY_FILE_WITH_WHITESPACE_PATHS \
+ "diff --git a/file b/file\n" \
+ "--- \n" \
+ "+++ \n" \
+ "Binary files "
+
+#define PATCH_BINARY_FILE_WITH_QUOTED_EMPTY_PATHS \
+ "diff --git a/file b/file\n" \
+ "--- \"\"\n" \
+ "+++ \"\"\n" \
+ "Binary files "
+
+#define PATCH_BINARY_FILE_PATH_WITH_SPACES \
+ "diff --git a b c d e f\n" \
+ "--- a b c\n" \
+ "+++ d e f\n" \
+ "Binary files a b c and d e f differ"
+
+#define PATCH_BINARY_FILE_PATH_WITHOUT_BODY_PATHS \
+ "diff --git a b c d e f\n" \
+ "--- \n" \
+ "+++ \n" \
+ "Binary files a b c and d e f differ"
+
+#define PATCH_BINARY_FILE_WITH_TRUNCATED_DELTA \
+ "diff --git a/file b/file\n" \
+ "index 1420..b71f\n" \
+ "GIT binary patch\n" \
+ "delta 7\n" \
+ "d"
+
+#define PATCH_MULTIPLE_OLD_PATHS \
+ "diff --git \n" \
+ "--- \n" \
+ "+++ \n" \
+ "index 0000..7DDb\n" \
+ "--- \n"
+
+#define PATCH_INTMAX_NEW_LINES \
+ "diff --git a/file b/file\n" \
+ "--- a/file\n" \
+ "+++ b/file\n" \
+ "@@ -0 +2147483647 @@\n" \
+ "\n" \
+ " "
diff --git a/tests/libgit2/patch/print.c b/tests/libgit2/patch/print.c
new file mode 100644
index 000000000..33cf27ddb
--- /dev/null
+++ b/tests/libgit2/patch/print.c
@@ -0,0 +1,186 @@
+#include "clar_libgit2.h"
+#include "patch.h"
+#include "patch_parse.h"
+
+#include "patch_common.h"
+
+
+/* sanity check the round-trip of patch parsing: ensure that we can parse
+ * and then print a variety of patch files.
+ */
+
+static void patch_print_from_patchfile(const char *data, size_t len)
+{
+ git_patch *patch;
+ git_buf buf = GIT_BUF_INIT;
+
+ cl_git_pass(git_patch_from_buffer(&patch, data, len, NULL));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+
+ cl_assert_equal_s(data, buf.ptr);
+
+ git_patch_free(patch);
+ git_buf_dispose(&buf);
+}
+
+void test_patch_print__change_middle(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_CHANGE_MIDDLE,
+ strlen(PATCH_ORIGINAL_TO_CHANGE_MIDDLE));
+}
+
+void test_patch_print__change_middle_nocontext(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_CHANGE_MIDDLE_NOCONTEXT,
+ strlen(PATCH_ORIGINAL_TO_CHANGE_MIDDLE_NOCONTEXT));
+}
+
+void test_patch_print__change_firstline(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE,
+ strlen(PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE));
+}
+
+void test_patch_print__change_lastline(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_CHANGE_LASTLINE,
+ strlen(PATCH_ORIGINAL_TO_CHANGE_LASTLINE));
+}
+
+void test_patch_print__prepend(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_PREPEND,
+ strlen(PATCH_ORIGINAL_TO_PREPEND));
+}
+
+void test_patch_print__prepend_nocontext(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_PREPEND_NOCONTEXT,
+ strlen(PATCH_ORIGINAL_TO_PREPEND_NOCONTEXT));
+}
+
+void test_patch_print__append(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_APPEND,
+ strlen(PATCH_ORIGINAL_TO_APPEND));
+}
+
+void test_patch_print__append_nocontext(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_APPEND_NOCONTEXT,
+ strlen(PATCH_ORIGINAL_TO_APPEND_NOCONTEXT));
+}
+
+void test_patch_print__prepend_and_append(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_PREPEND_AND_APPEND,
+ strlen(PATCH_ORIGINAL_TO_PREPEND_AND_APPEND));
+}
+
+void test_patch_print__to_empty_file(void)
+{
+ patch_print_from_patchfile(PATCH_ORIGINAL_TO_EMPTY_FILE,
+ strlen(PATCH_ORIGINAL_TO_EMPTY_FILE));
+}
+
+void test_patch_print__from_empty_file(void)
+{
+ patch_print_from_patchfile(PATCH_EMPTY_FILE_TO_ORIGINAL,
+ strlen(PATCH_EMPTY_FILE_TO_ORIGINAL));
+}
+
+void test_patch_print__add(void)
+{
+ patch_print_from_patchfile(PATCH_ADD_ORIGINAL,
+ strlen(PATCH_ADD_ORIGINAL));
+}
+
+void test_patch_print__delete(void)
+{
+ patch_print_from_patchfile(PATCH_DELETE_ORIGINAL,
+ strlen(PATCH_DELETE_ORIGINAL));
+}
+
+void test_patch_print__rename_exact(void)
+{
+ patch_print_from_patchfile(PATCH_RENAME_EXACT,
+ strlen(PATCH_RENAME_EXACT));
+}
+
+void test_patch_print__rename_exact_with_mode(void)
+{
+ patch_print_from_patchfile(PATCH_RENAME_EXACT_WITH_MODE,
+ strlen(PATCH_RENAME_EXACT_WITH_MODE));
+}
+
+void test_patch_print__rename_similar(void)
+{
+ patch_print_from_patchfile(PATCH_RENAME_SIMILAR,
+ strlen(PATCH_RENAME_SIMILAR));
+}
+
+void test_patch_print__rename_exact_quotedname(void)
+{
+ patch_print_from_patchfile(PATCH_RENAME_EXACT_QUOTEDNAME,
+ strlen(PATCH_RENAME_EXACT_QUOTEDNAME));
+}
+
+void test_patch_print__rename_similar_quotedname(void)
+{
+ patch_print_from_patchfile(PATCH_RENAME_SIMILAR_QUOTEDNAME,
+ strlen(PATCH_RENAME_SIMILAR_QUOTEDNAME));
+}
+
+void test_patch_print__modechange_unchanged(void)
+{
+ patch_print_from_patchfile(PATCH_MODECHANGE_UNCHANGED,
+ strlen(PATCH_MODECHANGE_UNCHANGED));
+}
+
+void test_patch_print__modechange_modified(void)
+{
+ patch_print_from_patchfile(PATCH_MODECHANGE_MODIFIED,
+ strlen(PATCH_MODECHANGE_MODIFIED));
+}
+
+void test_patch_print__binary_literal(void)
+{
+ patch_print_from_patchfile(PATCH_BINARY_LITERAL,
+ strlen(PATCH_BINARY_LITERAL));
+}
+
+void test_patch_print__binary_delta(void)
+{
+ patch_print_from_patchfile(PATCH_BINARY_DELTA,
+ strlen(PATCH_BINARY_DELTA));
+}
+
+void test_patch_print__binary_add(void)
+{
+ patch_print_from_patchfile(PATCH_BINARY_ADD,
+ strlen(PATCH_BINARY_ADD));
+}
+
+void test_patch_print__binary_delete(void)
+{
+ patch_print_from_patchfile(PATCH_BINARY_DELETE,
+ strlen(PATCH_BINARY_DELETE));
+}
+
+void test_patch_print__not_reversible(void)
+{
+ patch_print_from_patchfile(PATCH_BINARY_NOT_REVERSIBLE,
+ strlen(PATCH_BINARY_NOT_REVERSIBLE));
+}
+
+void test_patch_print__binary_not_shown(void)
+{
+ patch_print_from_patchfile(PATCH_BINARY_NOT_PRINTED,
+ strlen(PATCH_BINARY_NOT_PRINTED));
+}
+
+void test_patch_print__binary_add_not_shown(void)
+{
+ patch_print_from_patchfile(PATCH_ADD_BINARY_NOT_PRINTED,
+ strlen(PATCH_ADD_BINARY_NOT_PRINTED));
+}