this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 18058d1e151e780b7617d574c037b8a4e948816c 226 lines 6.0 kB view raw
1package gitdiff 2 3import ( 4 "bytes" 5 "errors" 6 "io" 7 "io/ioutil" 8 "path/filepath" 9 "strings" 10 "testing" 11) 12 13func TestTextFragmentApplyStrict(t *testing.T) { 14 tests := map[string]struct { 15 Files applyFiles 16 Err error 17 }{ 18 "createFile": {Files: getApplyFiles("text_fragment_new")}, 19 "deleteFile": {Files: getApplyFiles("text_fragment_delete_all")}, 20 21 "addStart": {Files: getApplyFiles("text_fragment_add_start")}, 22 "addMiddle": {Files: getApplyFiles("text_fragment_add_middle")}, 23 "addEnd": {Files: getApplyFiles("text_fragment_add_end")}, 24 "addEndNoEOL": {Files: getApplyFiles("text_fragment_add_end_noeol")}, 25 26 "changeStart": {Files: getApplyFiles("text_fragment_change_start")}, 27 "changeMiddle": {Files: getApplyFiles("text_fragment_change_middle")}, 28 "changeEnd": {Files: getApplyFiles("text_fragment_change_end")}, 29 "changeExact": {Files: getApplyFiles("text_fragment_change_exact")}, 30 "changeSingleNoEOL": {Files: getApplyFiles("text_fragment_change_single_noeol")}, 31 32 "errorShortSrcBefore": { 33 Files: applyFiles{ 34 Src: "text_fragment_error.src", 35 Patch: "text_fragment_error_short_src_before.patch", 36 }, 37 Err: io.ErrUnexpectedEOF, 38 }, 39 "errorShortSrc": { 40 Files: applyFiles{ 41 Src: "text_fragment_error.src", 42 Patch: "text_fragment_error_short_src.patch", 43 }, 44 Err: io.ErrUnexpectedEOF, 45 }, 46 "errorContextConflict": { 47 Files: applyFiles{ 48 Src: "text_fragment_error.src", 49 Patch: "text_fragment_error_context_conflict.patch", 50 }, 51 Err: &Conflict{}, 52 }, 53 "errorDeleteConflict": { 54 Files: applyFiles{ 55 Src: "text_fragment_error.src", 56 Patch: "text_fragment_error_delete_conflict.patch", 57 }, 58 Err: &Conflict{}, 59 }, 60 "errorNewFile": { 61 Files: applyFiles{ 62 Src: "text_fragment_error.src", 63 Patch: "text_fragment_error_new_file.patch", 64 }, 65 Err: &Conflict{}, 66 }, 67 } 68 69 for name, test := range tests { 70 t.Run(name, func(t *testing.T) { 71 src, patch, out := test.Files.Load(t) 72 73 files, _, err := Parse(bytes.NewReader(patch)) 74 if err != nil { 75 t.Fatalf("failed to parse patch file: %v", err) 76 } 77 if len(files) != 1 { 78 t.Fatalf("patch should contain exactly one file, but it has %d", len(files)) 79 } 80 if len(files[0].TextFragments) != 1 { 81 t.Fatalf("patch should contain exactly one fragment, but it has %d", len(files[0].TextFragments)) 82 } 83 84 applier := NewApplier(bytes.NewReader(src)) 85 86 var dst bytes.Buffer 87 err = applier.ApplyTextFragment(&dst, files[0].TextFragments[0]) 88 if test.Err != nil { 89 checkApplyError(t, test.Err, err) 90 return 91 } 92 if err != nil { 93 t.Fatalf("unexpected error applying fragment: %v", err) 94 } 95 96 if !bytes.Equal(out, dst.Bytes()) { 97 t.Errorf("incorrect result after apply\nexpected:\n%s\nactual:\n%s", out, dst.Bytes()) 98 } 99 }) 100 } 101} 102 103func TestBinaryFragmentApply(t *testing.T) { 104 tests := map[string]struct { 105 Files applyFiles 106 Err interface{} 107 }{ 108 "literalCreate": {Files: getApplyFiles("bin_fragment_literal_create")}, 109 "literalModify": {Files: getApplyFiles("bin_fragment_literal_modify")}, 110 "deltaModify": {Files: getApplyFiles("bin_fragment_delta_modify")}, 111 "deltaModifyLarge": {Files: getApplyFiles("bin_fragment_delta_modify_large")}, 112 113 "errorIncompleteAdd": { 114 Files: applyFiles{ 115 Src: "bin_fragment_delta_error.src", 116 Patch: "bin_fragment_delta_error_incomplete_add.patch", 117 }, 118 Err: "incomplete add", 119 }, 120 "errorIncompleteCopy": { 121 Files: applyFiles{ 122 Src: "bin_fragment_delta_error.src", 123 Patch: "bin_fragment_delta_error_incomplete_copy.patch", 124 }, 125 Err: "incomplete copy", 126 }, 127 "errorSrcSize": { 128 Files: applyFiles{ 129 Src: "bin_fragment_delta_error.src", 130 Patch: "bin_fragment_delta_error_src_size.patch", 131 }, 132 Err: &Conflict{}, 133 }, 134 "errorDstSize": { 135 Files: applyFiles{ 136 Src: "bin_fragment_delta_error.src", 137 Patch: "bin_fragment_delta_error_dst_size.patch", 138 }, 139 Err: "insufficient or extra data", 140 }, 141 } 142 143 for name, test := range tests { 144 t.Run(name, func(t *testing.T) { 145 src, patch, out := test.Files.Load(t) 146 147 files, _, err := Parse(bytes.NewReader(patch)) 148 if err != nil { 149 t.Fatalf("failed to parse patch file: %v", err) 150 } 151 if len(files) != 1 { 152 t.Fatalf("patch should contain exactly one file, but it has %d", len(files)) 153 } 154 155 applier := NewApplier(bytes.NewReader(src)) 156 157 var dst bytes.Buffer 158 err = applier.ApplyBinaryFragment(&dst, files[0].BinaryFragment) 159 if test.Err != nil { 160 checkApplyError(t, test.Err, err) 161 return 162 } 163 if err != nil { 164 t.Fatalf("unexpected error applying fragment: %v", err) 165 } 166 167 if !bytes.Equal(out, dst.Bytes()) { 168 t.Errorf("incorrect result after apply\nexpected:\n%x\nactual:\n%x", out, dst.Bytes()) 169 } 170 }) 171 } 172} 173 174func checkApplyError(t *testing.T, terr interface{}, err error) { 175 if err == nil { 176 t.Fatalf("expected error applying fragment, but got nil") 177 } 178 179 switch terr := terr.(type) { 180 case string: 181 if !strings.Contains(err.Error(), terr) { 182 t.Fatalf("incorrect apply error: %q does not contain %q", err.Error(), terr) 183 } 184 case error: 185 if !errors.Is(err, terr) { 186 t.Fatalf("incorrect apply error: expected: %T (%v), actual: %T (%v)", terr, terr, err, err) 187 } 188 default: 189 t.Fatalf("unsupported error type: %T", terr) 190 } 191} 192 193type applyFiles struct { 194 Src string 195 Patch string 196 Out string 197} 198 199func getApplyFiles(name string) applyFiles { 200 return applyFiles{ 201 Src: name + ".src", 202 Patch: name + ".patch", 203 Out: name + ".out", 204 } 205} 206 207func (f applyFiles) Load(t *testing.T) (src []byte, patch []byte, out []byte) { 208 load := func(name, kind string) []byte { 209 d, err := ioutil.ReadFile(filepath.Join("testdata", "apply", name)) 210 if err != nil { 211 t.Fatalf("failed to read %s file: %v", kind, err) 212 } 213 return d 214 } 215 216 if f.Src != "" { 217 src = load(f.Src, "source") 218 } 219 if f.Patch != "" { 220 patch = load(f.Patch, "patch") 221 } 222 if f.Out != "" { 223 out = load(f.Out, "output") 224 } 225 return 226}