fork of go-gitdiff with jj support
at v0.2.1 9.0 kB view raw
1package gitdiff 2 3import ( 4 "io" 5 "reflect" 6 "testing" 7) 8 9func TestParseTextFragmentHeader(t *testing.T) { 10 tests := map[string]struct { 11 Input string 12 Output *TextFragment 13 Err bool 14 }{ 15 "shortest": { 16 Input: "@@ -1 +1 @@\n", 17 Output: &TextFragment{ 18 OldPosition: 1, 19 OldLines: 1, 20 NewPosition: 1, 21 NewLines: 1, 22 }, 23 }, 24 "standard": { 25 Input: "@@ -21,5 +28,9 @@\n", 26 Output: &TextFragment{ 27 OldPosition: 21, 28 OldLines: 5, 29 NewPosition: 28, 30 NewLines: 9, 31 }, 32 }, 33 "trailingComment": { 34 Input: "@@ -21,5 +28,9 @@ func test(n int) {\n", 35 Output: &TextFragment{ 36 Comment: "func test(n int) {", 37 OldPosition: 21, 38 OldLines: 5, 39 NewPosition: 28, 40 NewLines: 9, 41 }, 42 }, 43 "incomplete": { 44 Input: "@@ -12,3 +2\n", 45 Err: true, 46 }, 47 "badNumbers": { 48 Input: "@@ -1a,2b +3c,4d @@\n", 49 Err: true, 50 }, 51 } 52 53 for name, test := range tests { 54 t.Run(name, func(t *testing.T) { 55 p := newTestParser(test.Input, true) 56 57 frag, err := p.ParseTextFragmentHeader() 58 if test.Err { 59 if err == nil || err == io.EOF { 60 t.Fatalf("expected error parsing header, but got %v", err) 61 } 62 return 63 } 64 if err != nil { 65 t.Fatalf("error parsing header: %v", err) 66 } 67 68 if !reflect.DeepEqual(test.Output, frag) { 69 t.Errorf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, frag) 70 } 71 }) 72 } 73} 74 75func TestParseTextChunk(t *testing.T) { 76 tests := map[string]struct { 77 Input string 78 Fragment TextFragment 79 80 Output *TextFragment 81 Err bool 82 }{ 83 "addWithContext": { 84 Input: ` context line 85+new line 1 86+new line 2 87 context line 88`, 89 Fragment: TextFragment{ 90 OldLines: 2, 91 NewLines: 4, 92 }, 93 Output: &TextFragment{ 94 OldLines: 2, 95 NewLines: 4, 96 Lines: []Line{ 97 {OpContext, "context line\n"}, 98 {OpAdd, "new line 1\n"}, 99 {OpAdd, "new line 2\n"}, 100 {OpContext, "context line\n"}, 101 }, 102 LinesAdded: 2, 103 LeadingContext: 1, 104 TrailingContext: 1, 105 }, 106 }, 107 "deleteWithContext": { 108 Input: ` context line 109-old line 1 110-old line 2 111 context line 112`, 113 Fragment: TextFragment{ 114 OldLines: 4, 115 NewLines: 2, 116 }, 117 Output: &TextFragment{ 118 OldLines: 4, 119 NewLines: 2, 120 Lines: []Line{ 121 {OpContext, "context line\n"}, 122 {OpDelete, "old line 1\n"}, 123 {OpDelete, "old line 2\n"}, 124 {OpContext, "context line\n"}, 125 }, 126 LinesDeleted: 2, 127 LeadingContext: 1, 128 TrailingContext: 1, 129 }, 130 }, 131 "replaceWithContext": { 132 Input: ` context line 133-old line 1 134+new line 1 135 context line 136`, 137 Fragment: TextFragment{ 138 OldLines: 3, 139 NewLines: 3, 140 }, 141 Output: &TextFragment{ 142 OldLines: 3, 143 NewLines: 3, 144 Lines: []Line{ 145 {OpContext, "context line\n"}, 146 {OpDelete, "old line 1\n"}, 147 {OpAdd, "new line 1\n"}, 148 {OpContext, "context line\n"}, 149 }, 150 LinesDeleted: 1, 151 LinesAdded: 1, 152 LeadingContext: 1, 153 TrailingContext: 1, 154 }, 155 }, 156 "middleContext": { 157 Input: ` context line 158-old line 1 159 context line 160+new line 1 161 context line 162`, 163 Fragment: TextFragment{ 164 OldLines: 4, 165 NewLines: 4, 166 }, 167 Output: &TextFragment{ 168 OldLines: 4, 169 NewLines: 4, 170 Lines: []Line{ 171 {OpContext, "context line\n"}, 172 {OpDelete, "old line 1\n"}, 173 {OpContext, "context line\n"}, 174 {OpAdd, "new line 1\n"}, 175 {OpContext, "context line\n"}, 176 }, 177 LinesDeleted: 1, 178 LinesAdded: 1, 179 LeadingContext: 1, 180 TrailingContext: 1, 181 }, 182 }, 183 "deleteFinalNewline": { 184 Input: ` context line 185-old line 1 186+new line 1 187\ No newline at end of file 188`, 189 Fragment: TextFragment{ 190 OldLines: 2, 191 NewLines: 2, 192 }, 193 Output: &TextFragment{ 194 OldLines: 2, 195 NewLines: 2, 196 Lines: []Line{ 197 {OpContext, "context line\n"}, 198 {OpDelete, "old line 1\n"}, 199 {OpAdd, "new line 1"}, 200 }, 201 LinesDeleted: 1, 202 LinesAdded: 1, 203 LeadingContext: 1, 204 }, 205 }, 206 "addFinalNewline": { 207 Input: ` context line 208-old line 1 209\ No newline at end of file 210+new line 1 211`, 212 Fragment: TextFragment{ 213 OldLines: 2, 214 NewLines: 2, 215 }, 216 Output: &TextFragment{ 217 OldLines: 2, 218 NewLines: 2, 219 Lines: []Line{ 220 {OpContext, "context line\n"}, 221 {OpDelete, "old line 1"}, 222 {OpAdd, "new line 1\n"}, 223 }, 224 LinesDeleted: 1, 225 LinesAdded: 1, 226 LeadingContext: 1, 227 }, 228 }, 229 "addAll": { 230 Input: `+new line 1 231+new line 2 232+new line 3 233`, 234 Fragment: TextFragment{ 235 OldLines: 0, 236 NewLines: 3, 237 }, 238 Output: &TextFragment{ 239 OldLines: 0, 240 NewLines: 3, 241 Lines: []Line{ 242 {OpAdd, "new line 1\n"}, 243 {OpAdd, "new line 2\n"}, 244 {OpAdd, "new line 3\n"}, 245 }, 246 LinesAdded: 3, 247 }, 248 }, 249 "deleteAll": { 250 Input: `-old line 1 251-old line 2 252-old line 3 253`, 254 Fragment: TextFragment{ 255 OldLines: 3, 256 NewLines: 0, 257 }, 258 Output: &TextFragment{ 259 OldLines: 3, 260 NewLines: 0, 261 Lines: []Line{ 262 {OpDelete, "old line 1\n"}, 263 {OpDelete, "old line 2\n"}, 264 {OpDelete, "old line 3\n"}, 265 }, 266 LinesDeleted: 3, 267 }, 268 }, 269 "emptyContextLine": { 270 Input: ` context line 271 272+new line 273 context line 274`, 275 Fragment: TextFragment{ 276 OldLines: 3, 277 NewLines: 4, 278 }, 279 Output: &TextFragment{ 280 OldLines: 3, 281 NewLines: 4, 282 Lines: []Line{ 283 {OpContext, "context line\n"}, 284 {OpContext, "\n"}, 285 {OpAdd, "new line\n"}, 286 {OpContext, "context line\n"}, 287 }, 288 LinesAdded: 1, 289 LeadingContext: 2, 290 TrailingContext: 1, 291 }, 292 }, 293 "emptyChunk": { 294 Input: "", 295 Err: true, 296 }, 297 "invalidOperation": { 298 Input: ` context line 299?wat line 300 context line 301`, 302 Fragment: TextFragment{ 303 OldLines: 3, 304 NewLines: 3, 305 }, 306 Err: true, 307 }, 308 "unbalancedHeader": { 309 Input: ` context line 310-old line 1 311+new line 1 312 context line 313`, 314 Fragment: TextFragment{ 315 OldLines: 2, 316 NewLines: 5, 317 }, 318 Err: true, 319 }, 320 } 321 322 for name, test := range tests { 323 t.Run(name, func(t *testing.T) { 324 p := newTestParser(test.Input, true) 325 326 frag := test.Fragment 327 err := p.ParseTextChunk(&frag) 328 if test.Err { 329 if err == nil || err == io.EOF { 330 t.Fatalf("expected error parsing text chunk, but got %v", err) 331 } 332 return 333 } 334 if err != nil { 335 t.Fatalf("error parsing text chunk: %v", err) 336 } 337 338 if !reflect.DeepEqual(test.Output, &frag) { 339 t.Errorf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, &frag) 340 } 341 }) 342 } 343} 344 345func TestParseTextFragments(t *testing.T) { 346 tests := map[string]struct { 347 Input string 348 File File 349 350 Fragments []*TextFragment 351 Err bool 352 }{ 353 "multipleChanges": { 354 Input: `@@ -1,3 +1,2 @@ 355 context line 356-old line 1 357 context line 358@@ -8,3 +7,3 @@ 359 context line 360-old line 2 361+new line 1 362 context line 363@@ -15,3 +14,4 @@ 364 context line 365-old line 3 366+new line 2 367+new line 3 368 context line 369`, 370 Fragments: []*TextFragment{ 371 { 372 OldPosition: 1, 373 OldLines: 3, 374 NewPosition: 1, 375 NewLines: 2, 376 Lines: []Line{ 377 {OpContext, "context line\n"}, 378 {OpDelete, "old line 1\n"}, 379 {OpContext, "context line\n"}, 380 }, 381 LinesDeleted: 1, 382 LeadingContext: 1, 383 TrailingContext: 1, 384 }, 385 { 386 OldPosition: 8, 387 OldLines: 3, 388 NewPosition: 7, 389 NewLines: 3, 390 Lines: []Line{ 391 {OpContext, "context line\n"}, 392 {OpDelete, "old line 2\n"}, 393 {OpAdd, "new line 1\n"}, 394 {OpContext, "context line\n"}, 395 }, 396 LinesDeleted: 1, 397 LinesAdded: 1, 398 LeadingContext: 1, 399 TrailingContext: 1, 400 }, 401 { 402 OldPosition: 15, 403 OldLines: 3, 404 NewPosition: 14, 405 NewLines: 4, 406 Lines: []Line{ 407 {OpContext, "context line\n"}, 408 {OpDelete, "old line 3\n"}, 409 {OpAdd, "new line 2\n"}, 410 {OpAdd, "new line 3\n"}, 411 {OpContext, "context line\n"}, 412 }, 413 LinesDeleted: 1, 414 LinesAdded: 2, 415 LeadingContext: 1, 416 TrailingContext: 1, 417 }, 418 }, 419 }, 420 "badNewFile": { 421 Input: `@@ -1 +1,2 @@ 422-old line 1 423+new line 1 424+new line 2 425`, 426 File: File{ 427 IsNew: true, 428 }, 429 Err: true, 430 }, 431 "badDeletedFile": { 432 Input: `@@ -1,2 +1 @@ 433-old line 1 434 context line 435`, 436 File: File{ 437 IsDelete: true, 438 }, 439 Err: true, 440 }, 441 } 442 443 for name, test := range tests { 444 t.Run(name, func(t *testing.T) { 445 p := newTestParser(test.Input, true) 446 447 file := test.File 448 n, err := p.ParseTextFragments(&file) 449 if test.Err { 450 if err == nil || err == io.EOF { 451 t.Fatalf("expected error parsing text fragments, but got %v", err) 452 } 453 return 454 } 455 if err != nil { 456 t.Fatalf("error parsing text fragments: %v", err) 457 } 458 459 if len(test.Fragments) != n { 460 t.Fatalf("incorrect number of added fragments: expected %d, actual %d", len(test.Fragments), n) 461 } 462 463 for i, frag := range test.Fragments { 464 if !reflect.DeepEqual(frag, file.TextFragments[i]) { 465 t.Errorf("incorrect fragment at position %d\nexpected: %+v\nactual: %+v", i, frag, file.TextFragments[i]) 466 } 467 } 468 }) 469 } 470}