From 9fc14fddb0177442728a7154b8ba10aa125ac2bc Mon Sep 17 00:00:00 2001 From: Billy Keyes Date: Mon, 27 Jan 2020 22:35:13 -0800 Subject: [PATCH] Add tests for file-level application Also refactor the apply tests to use a common type now that there are three variants that do almost the same thing for each test. --- gitdiff/apply_test.go | 136 ++++++------ gitdiff/testdata/apply/bin_file_modify.out | Bin 0 -> 1084 bytes gitdiff/testdata/apply/bin_file_modify.patch | 13 ++ gitdiff/testdata/apply/bin_file_modify.src | Bin 0 -> 1024 bytes gitdiff/testdata/apply/file_mode_change.out | 2 + gitdiff/testdata/apply/file_mode_change.patch | 3 + gitdiff/testdata/apply/file_mode_change.src | 2 + gitdiff/testdata/apply/text_file_modify.out | 195 +++++++++++++++++ gitdiff/testdata/apply/text_file_modify.patch | 62 ++++++ gitdiff/testdata/apply/text_file_modify.src | 200 ++++++++++++++++++ 10 files changed, 547 insertions(+), 66 deletions(-) create mode 100644 gitdiff/testdata/apply/bin_file_modify.out create mode 100644 gitdiff/testdata/apply/bin_file_modify.patch create mode 100644 gitdiff/testdata/apply/bin_file_modify.src create mode 100644 gitdiff/testdata/apply/file_mode_change.out create mode 100644 gitdiff/testdata/apply/file_mode_change.patch create mode 100644 gitdiff/testdata/apply/file_mode_change.src create mode 100644 gitdiff/testdata/apply/text_file_modify.out create mode 100644 gitdiff/testdata/apply/text_file_modify.patch create mode 100644 gitdiff/testdata/apply/text_file_modify.src diff --git a/gitdiff/apply_test.go b/gitdiff/apply_test.go index b58ce00..f35acc6 100644 --- a/gitdiff/apply_test.go +++ b/gitdiff/apply_test.go @@ -73,11 +73,8 @@ func TestApplierInvariants(t *testing.T) { }) } -func TestTextFragmentApplyStrict(t *testing.T) { - tests := map[string]struct { - Files applyFiles - Err error - }{ +func TestApplyTextFragment(t *testing.T) { + tests := map[string]applyTest{ "createFile": {Files: getApplyFiles("text_fragment_new")}, "deleteFile": {Files: getApplyFiles("text_fragment_delete_all")}, @@ -131,43 +128,18 @@ func TestTextFragmentApplyStrict(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - src, patch, out := test.Files.Load(t) - - files, _, err := Parse(bytes.NewReader(patch)) - if err != nil { - t.Fatalf("failed to parse patch file: %v", err) - } - if len(files) != 1 { - t.Fatalf("patch should contain exactly one file, but it has %d", len(files)) - } - if len(files[0].TextFragments) != 1 { - t.Fatalf("patch should contain exactly one fragment, but it has %d", len(files[0].TextFragments)) - } - - applier := NewApplier(bytes.NewReader(src)) - - var dst bytes.Buffer - err = applier.ApplyTextFragment(&dst, files[0].TextFragments[0]) - if test.Err != nil { - checkApplyError(t, test.Err, err) - return - } - if err != nil { - t.Fatalf("unexpected error applying fragment: %v", err) - } - - if !bytes.Equal(out, dst.Bytes()) { - t.Errorf("incorrect result after apply\nexpected:\n%s\nactual:\n%s", out, dst.Bytes()) - } + test.run(t, func(w io.Writer, applier *Applier, file *File) error { + if len(file.TextFragments) != 1 { + t.Fatalf("patch should contain exactly one fragment, but it has %d", len(file.TextFragments)) + } + return applier.ApplyTextFragment(w, file.TextFragments[0]) + }) }) } } -func TestBinaryFragmentApply(t *testing.T) { - tests := map[string]struct { - Files applyFiles - Err interface{} - }{ +func TestApplyBinaryFragment(t *testing.T) { + tests := map[string]applyTest{ "literalCreate": {Files: getApplyFiles("bin_fragment_literal_create")}, "literalModify": {Files: getApplyFiles("bin_fragment_literal_modify")}, "deltaModify": {Files: getApplyFiles("bin_fragment_delta_modify")}, @@ -205,41 +177,73 @@ func TestBinaryFragmentApply(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - src, patch, out := test.Files.Load(t) - - files, _, err := Parse(bytes.NewReader(patch)) - if err != nil { - t.Fatalf("failed to parse patch file: %v", err) - } - if len(files) != 1 { - t.Fatalf("patch should contain exactly one file, but it has %d", len(files)) - } - - applier := NewApplier(bytes.NewReader(src)) - - var dst bytes.Buffer - err = applier.ApplyBinaryFragment(&dst, files[0].BinaryFragment) - if test.Err != nil { - checkApplyError(t, test.Err, err) - return - } - if err != nil { - t.Fatalf("unexpected error applying fragment: %v", err) - } - - if !bytes.Equal(out, dst.Bytes()) { - t.Errorf("incorrect result after apply\nexpected:\n%x\nactual:\n%x", out, dst.Bytes()) - } + test.run(t, func(w io.Writer, applier *Applier, file *File) error { + return applier.ApplyBinaryFragment(w, file.BinaryFragment) + }) }) } } -func checkApplyError(t *testing.T, terr interface{}, err error) { +func TestApplyFile(t *testing.T) { + tests := map[string]applyTest{ + "textModify": {Files: getApplyFiles("text_file_modify")}, + "binaryModify": {Files: getApplyFiles("bin_file_modify")}, + "modeChange": {Files: getApplyFiles("file_mode_change")}, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + test.run(t, func(w io.Writer, applier *Applier, file *File) error { + return applier.ApplyFile(w, file) + }) + }) + } +} + +type applyTest struct { + Files applyFiles + Err interface{} +} + +func (at applyTest) run(t *testing.T, apply func(io.Writer, *Applier, *File) error) { + src, patch, out := at.Files.Load(t) + + files, _, err := Parse(bytes.NewReader(patch)) + if err != nil { + t.Fatalf("failed to parse patch file: %v", err) + } + if len(files) != 1 { + t.Fatalf("patch should contain exactly one file, but it has %d", len(files)) + } + + applier := NewApplier(bytes.NewReader(src)) + + var dst bytes.Buffer + err = apply(&dst, applier, files[0]) + if at.Err != nil { + at.assertError(t, err) + return + } + if err != nil { + var aerr *ApplyError + if errors.As(err, &aerr) { + t.Fatalf("unexpected error applying: at %d: fragment %d at %d: %v", aerr.Line, aerr.Fragment, aerr.FragmentLine, err) + } else { + t.Fatalf("unexpected error applying: %v", err) + } + } + + if !bytes.Equal(out, dst.Bytes()) { + t.Errorf("incorrect result after apply\nexpected:\n%x\nactual:\n%x", out, dst.Bytes()) + } +} + +func (at applyTest) assertError(t *testing.T, err error) { if err == nil { t.Fatalf("expected error applying fragment, but got nil") } - switch terr := terr.(type) { + switch terr := at.Err.(type) { case string: if !strings.Contains(err.Error(), terr) { t.Fatalf("incorrect apply error: %q does not contain %q", err.Error(), terr) @@ -249,7 +253,7 @@ func checkApplyError(t *testing.T, terr interface{}, err error) { t.Fatalf("incorrect apply error: expected: %T (%v), actual: %T (%v)", terr, terr, err, err) } default: - t.Fatalf("unsupported error type: %T", terr) + t.Fatalf("unsupported expected error type: %T", terr) } } diff --git a/gitdiff/testdata/apply/bin_file_modify.out b/gitdiff/testdata/apply/bin_file_modify.out new file mode 100644 index 0000000000000000000000000000000000000000..f3386d1e1783c7787fd4f4da915181af11ec11d8 GIT binary patch literal 1084 zcmV-C1jG9P09pNE#3WFH&TwN$dg8wM!`BfQJQ+NUo0}w+BiI9I6=84y)2him_%;Q# zqZG?mF{7OrSxFE*$eDv1G`Yi&L)<%eIjm1U&9T!pU}n7Y`z#fxdodlKsB{fbNO}*v|5%C!bA=5zW4K`GA2JbeVJf!)NKv z$Pc7*$Qb7o%<|j_lP|a#SCt^XrxR4pfgnznhRCVnp&Nj4&TN zOwbpi3BxBcjKFXA9ya-^EGn7s(!!6{%mW`X*X?qZ2LeAJxqJ~ovT1MVq7LLjQ>1Xo ziFJzSD-Y*q(320bN#yK!mA3Wl6IAC(u+$25#oEN{P(typ=S1N*WDhLU>$`B^Ht`f{ zZx#e}J?%?-WMMdQ?87TF#bw~HPDR;7Pp7_+JOkRF1UG{_(zeQaGB(3F1t#qy13}vW z00000Kl{JH)lGa=l#3#2J{N|7sUd?b!wjX~)=^!%v^*GtS2cHrr^Uh`x(AyUA`CTb z)FV6q(!G(4oMVA8*OoiNMq#erMXh!rsV@tC9o%PUY@%ZRd=H{m#%pRwN{f_(?}hY zH@*?~Kv?`8wia>c#fPPPenu_zBaT}=4`e9K9qD~8vAg}B!|CdQzv~Q{jy&IQn{Rk| z@(}=1|AS+>#eyHB;-DM81@LES-_@z;iPQf^7h6@oPuv|@W0@>v1*Q#E!*(hi%xc9PgBlAP}qo61kTT| z-9F*=G3)9h7ZH?Sv^C=b&&Rqt8WXGH7MyGIU);QC2KKQRd%o(!Esh8rfU8AwJpU)# zU_7DWRRGl#r_`#*+j^eJ`9F?^rlv~F2QNw4IWihFjiho_7j&TxHQHrsKFm$`We>j* z!nhHX_7P^)^_>xah9<*4>@O7_&Ex1KD-g?znDA?8BGC8mbWB!7N&YGaE$qGB>_vuj zxSv!ALI#5fBvRQ0salG)DA))EjMz7#j&@0bJ{~Z~0@X${&1Kk# z98tb3==a{J7A;`O`v&J`s>wb0HU+h#6w8q?tUO~cHmDjZi2<8yZ9XmKhhMdo +zWu(4bg|8QwzZ|1e*rL4P#)`FenXTQ5=J2y;^BfB}4 +zWkisH791|vOVl5e-@^VLX0s~Ky_UyN!3;CgPr>Edj0j+0gOSwSsFsr$0q6zUJph{7OrR$Oxg9NfM>tEXFE4ck0ZM|mSsecffgJt*h|zOli$Mr z9%i#D&%Kt%P{9l{(@(+W+KdQbV1tp=+^CiW*v|5%C!bA=5zW4K`GA2JbeVJf!)NKv z$Pc7*$Qb7o%<|j_lP|a#SCt^XrxR4pfgnznhRCVnp&Nj4&TN zOwbpi3BxBcjKFXA9ya-^EGn7s(!!6{%mW`X*X?qZ2LeAJxqJ~ovT1MVq7LLjQ>1Xo ziFJzSD-Y*q(320bN#yK!mA3Wl6IAC(u+$25#oEN{P(typ=S1N*WDhLU>$`B^Ht`f{ zZx#e}J?%?-WMMdQ?87TF#bw~HPDR;7Pp7_+JOkRF1UG{_(zeQaGB(3F1t#qy13}x_ zJphH{m#%pRwN{f_(?}hY zH@*?~Kv?`8wia>c#fPPPenu_zBaT}=4`e9K9qD~8vAg}B!|CdQzv~Q{jy&IQn{Rk| z@(}=1|AS+>#eyHB;-DM81@LES-_@z;iPQf^7h6@oPuv|@W0@>v1*Q#E!*(hi%xc9PgBlAP}qo61kTT| z-9F*=G3)9h7ZH?Sv^C=b&&Rqt8WXGH7MyGIU);QC2KKQRd%o(!Esh8rfU8AwJpU)# zU_7DWRRGl#r_`#*+j^eJ`9F?^rlv~F2QNw4IWihFjiho_7j&TxHQHrsKFm$`We>j* z!nhHX_7P^)^_>xah9<*4>@O7_&Ex1KD-g?znDA?8BGC8mbWB!7N&YGaE$qGB>_vuj uxSv!ALI#5fBvRQ0salG)DA))EjMz7#j&?~*_7UBMefQ!3 literal 0 HcmV?d00001 diff --git a/gitdiff/testdata/apply/file_mode_change.out b/gitdiff/testdata/apply/file_mode_change.out new file mode 100644 index 0000000..ec3b7fd --- /dev/null +++ b/gitdiff/testdata/apply/file_mode_change.out @@ -0,0 +1,2 @@ +#!/bin/bash +echo "this file is executable" diff --git a/gitdiff/testdata/apply/file_mode_change.patch b/gitdiff/testdata/apply/file_mode_change.patch new file mode 100644 index 0000000..b1f6859 --- /dev/null +++ b/gitdiff/testdata/apply/file_mode_change.patch @@ -0,0 +1,3 @@ +diff --git a/gitdiff/testdata/apply/file_mode_change.src b/gitdiff/testdata/apply/file_mode_change.src +old mode 100644 +new mode 100755 diff --git a/gitdiff/testdata/apply/file_mode_change.src b/gitdiff/testdata/apply/file_mode_change.src new file mode 100644 index 0000000..ec3b7fd --- /dev/null +++ b/gitdiff/testdata/apply/file_mode_change.src @@ -0,0 +1,2 @@ +#!/bin/bash +echo "this file is executable" diff --git a/gitdiff/testdata/apply/text_file_modify.out b/gitdiff/testdata/apply/text_file_modify.out new file mode 100644 index 0000000..dc20c07 --- /dev/null +++ b/gitdiff/testdata/apply/text_file_modify.out @@ -0,0 +1,195 @@ +the first line is different +this is line 2 +this is line 3 +this is line 4 +this is line 5 +this is line 6 +this is line 7 +this is line 8 +this is line 9 +this is line 10 +this is line 11 +this is line 12 +this is line 13 +this is line 14 +this is line 15 +this is line 16 +this is line 17 +this is line 18 +this is line 19 +this line offsets all the line numbers! +this is line 20 +this is line 21 +until here, now we're back on track! +this is line 24 +this is line 25 +this is line 26 +this is line 27 +this is line 28 +this is line 29 +this is line 30 +this is line 31 +this is line 32 +this is line 33 +this is line 34 +this is line 35 +this is line 36 +this is line 37 +this is line 38 +this is line 39 +this is line 40 +this is line 41 +this is line 42 +this is line 43 +this is line 44 +this is line 45 +this is line 46 +this is line 47 +this is line 48 +this is line 49 +this is line 50 +this is line 51 +this is line 52 +this is line 53 +this is line 54 +this is line 55 +once upon a time, a line + in a text + file + changed +this is line 60 +this is line 61 +this is line 62 +this is line 63 +this is line 64 +this is line 65 +this is line 66 +this is line 67 +this is line 68 +this is line 69 +this is line 70 +this is line 71 +this is line 72 +this is line 73 +this is line 74 +this is line 75 +this is line 76 +this is line 77 +this is line 78 +this is line 79 +this is line 80 +this is line 81 +this is line 82 +this is line 83 +this is line 84 +this is line 85 +this is line 86 +this is line 87 +this is line 88 +this is line 89 +this is line 90 +this is line 91 +this is line 92 +this is line 93 +this is line 94 +this is line 95 +this is line 96 +this is line 97 +this is line 98 +this is line 99 +this is line 100 +this is line 101 +this is line 102 +this is line 103 +this is line 104 +this is line 105 +this is line 106 +this is line 107 +this is line 108 +this is line 109 +this is line 110 +this is line 111 +this is line 112 +this is line 113 +this is line 114 +this is line 115 +this is line 116 +this is line 117 +this is line 118 +this is line 119 +this is line 120 +this is line 121 +this is line 122 +this is line 123 +this is line 124 +this is line 125 +this is line 126 +this is line 127 +this is line 128 +this is line 129 +this is line 130 +this is line 131 +this is line 132 +this line was bad and has been removed +this line was REDACTED and has been REDACTED +this is line 135 +this is line 136 +this is line 137 +this is line 138 +this is line 139 +this is line 140 +this is line 141 +this is line 142 +this is line 143 +this is line 144 +this is line 145 +this is line 146 +this is line 147 +this is line 148 +this is line 149 +this is line 150 +this is line 151 +this is line 152 +this is line 153 +this is line 154 +this is line 155 +this is line 156 +this is line 157 +this is line 158 +this is line 159 +this is line 160 +this is line 161 +this is line 162 +this is line 163 +the number on the remaining lines is 5 ahead of their actual position in the file +this is line 170 +this is line 171 +this is line 172 +this is line 173 +this is line 174 +this is line 175 +this is line 176 +this is line 177 +this is line 178 +this is line 179 +this is line 180 +this is line 181 +this is line 182 +this is line 183 +this is line 184 +this is line 185 +this is line 186 +this is line 187 +this is line 188 +this is line 189 +this is line 190 +this is line 191 +this is line 192 +this is line 193 +this is line 194 +this is line 195 +this is line 196 +this is line 197 +this is line 198 +this is line 199 +this is line 200 diff --git a/gitdiff/testdata/apply/text_file_modify.patch b/gitdiff/testdata/apply/text_file_modify.patch new file mode 100644 index 0000000..8d4c766 --- /dev/null +++ b/gitdiff/testdata/apply/text_file_modify.patch @@ -0,0 +1,62 @@ +diff --git a/gitdiff/testdata/apply/text_file_modify.src b/gitdiff/testdata/apply/text_file_modify.src +--- a/gitdiff/testdata/apply/text_file_modify.src ++++ b/gitdiff/testdata/apply/text_file_modify.src +@@ -1,4 +1,4 @@ +-this is line 1 ++the first line is different + this is line 2 + this is line 3 + this is line 4 +@@ -17,10 +17,10 @@ this is line 16 + this is line 17 + this is line 18 + this is line 19 ++this line offsets all the line numbers! + this is line 20 + this is line 21 +-this is line 22 +-this is line 23 ++until here, now we're back on track! + this is line 24 + this is line 25 + this is line 26 +@@ -53,10 +53,10 @@ this is line 52 + this is line 53 + this is line 54 + this is line 55 +-this is line 56 +-this is line 57 +-this is line 58 +-this is line 59 ++once upon a time, a line ++ in a text ++ file ++ changed + this is line 60 + this is line 61 + this is line 62 +@@ -130,8 +130,8 @@ this is line 129 + this is line 130 + this is line 131 + this is line 132 +-this is line 133 +-this is line 134 ++this line was bad and has been removed ++this line was REDACTED and has been REDACTED + this is line 135 + this is line 136 + this is line 137 +@@ -161,12 +161,7 @@ this is line 160 + this is line 161 + this is line 162 + this is line 163 +-this is line 164 +-this is line 165 +-this is line 166 +-this is line 167 +-this is line 168 +-this is line 169 ++the number on the remaining lines is 5 ahead of their actual position in the file + this is line 170 + this is line 171 + this is line 172 diff --git a/gitdiff/testdata/apply/text_file_modify.src b/gitdiff/testdata/apply/text_file_modify.src new file mode 100644 index 0000000..3805ad4 --- /dev/null +++ b/gitdiff/testdata/apply/text_file_modify.src @@ -0,0 +1,200 @@ +this is line 1 +this is line 2 +this is line 3 +this is line 4 +this is line 5 +this is line 6 +this is line 7 +this is line 8 +this is line 9 +this is line 10 +this is line 11 +this is line 12 +this is line 13 +this is line 14 +this is line 15 +this is line 16 +this is line 17 +this is line 18 +this is line 19 +this is line 20 +this is line 21 +this is line 22 +this is line 23 +this is line 24 +this is line 25 +this is line 26 +this is line 27 +this is line 28 +this is line 29 +this is line 30 +this is line 31 +this is line 32 +this is line 33 +this is line 34 +this is line 35 +this is line 36 +this is line 37 +this is line 38 +this is line 39 +this is line 40 +this is line 41 +this is line 42 +this is line 43 +this is line 44 +this is line 45 +this is line 46 +this is line 47 +this is line 48 +this is line 49 +this is line 50 +this is line 51 +this is line 52 +this is line 53 +this is line 54 +this is line 55 +this is line 56 +this is line 57 +this is line 58 +this is line 59 +this is line 60 +this is line 61 +this is line 62 +this is line 63 +this is line 64 +this is line 65 +this is line 66 +this is line 67 +this is line 68 +this is line 69 +this is line 70 +this is line 71 +this is line 72 +this is line 73 +this is line 74 +this is line 75 +this is line 76 +this is line 77 +this is line 78 +this is line 79 +this is line 80 +this is line 81 +this is line 82 +this is line 83 +this is line 84 +this is line 85 +this is line 86 +this is line 87 +this is line 88 +this is line 89 +this is line 90 +this is line 91 +this is line 92 +this is line 93 +this is line 94 +this is line 95 +this is line 96 +this is line 97 +this is line 98 +this is line 99 +this is line 100 +this is line 101 +this is line 102 +this is line 103 +this is line 104 +this is line 105 +this is line 106 +this is line 107 +this is line 108 +this is line 109 +this is line 110 +this is line 111 +this is line 112 +this is line 113 +this is line 114 +this is line 115 +this is line 116 +this is line 117 +this is line 118 +this is line 119 +this is line 120 +this is line 121 +this is line 122 +this is line 123 +this is line 124 +this is line 125 +this is line 126 +this is line 127 +this is line 128 +this is line 129 +this is line 130 +this is line 131 +this is line 132 +this is line 133 +this is line 134 +this is line 135 +this is line 136 +this is line 137 +this is line 138 +this is line 139 +this is line 140 +this is line 141 +this is line 142 +this is line 143 +this is line 144 +this is line 145 +this is line 146 +this is line 147 +this is line 148 +this is line 149 +this is line 150 +this is line 151 +this is line 152 +this is line 153 +this is line 154 +this is line 155 +this is line 156 +this is line 157 +this is line 158 +this is line 159 +this is line 160 +this is line 161 +this is line 162 +this is line 163 +this is line 164 +this is line 165 +this is line 166 +this is line 167 +this is line 168 +this is line 169 +this is line 170 +this is line 171 +this is line 172 +this is line 173 +this is line 174 +this is line 175 +this is line 176 +this is line 177 +this is line 178 +this is line 179 +this is line 180 +this is line 181 +this is line 182 +this is line 183 +this is line 184 +this is line 185 +this is line 186 +this is line 187 +this is line 188 +this is line 189 +this is line 190 +this is line 191 +this is line 192 +this is line 193 +this is line 194 +this is line 195 +this is line 196 +this is line 197 +this is line 198 +this is line 199 +this is line 200