fork of go-gitdiff with jj support
at v0.8.1 9.3 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 "onlyContext": { 321 Input: ` context line 322 context line 323`, 324 Fragment: TextFragment{ 325 OldLines: 2, 326 NewLines: 2, 327 }, 328 Err: true, 329 }, 330 "unexpectedNoNewlineMarker": { 331 Input: `\ No newline at end of file`, 332 Fragment: TextFragment{ 333 OldLines: 1, 334 NewLines: 1, 335 }, 336 Err: true, 337 }, 338 } 339 340 for name, test := range tests { 341 t.Run(name, func(t *testing.T) { 342 p := newTestParser(test.Input, true) 343 344 frag := test.Fragment 345 err := p.ParseTextChunk(&frag) 346 if test.Err { 347 if err == nil || err == io.EOF { 348 t.Fatalf("expected error parsing text chunk, but got %v", err) 349 } 350 return 351 } 352 if err != nil { 353 t.Fatalf("error parsing text chunk: %v", err) 354 } 355 356 if !reflect.DeepEqual(test.Output, &frag) { 357 t.Errorf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, &frag) 358 } 359 }) 360 } 361} 362 363func TestParseTextFragments(t *testing.T) { 364 tests := map[string]struct { 365 Input string 366 File File 367 368 Fragments []*TextFragment 369 Err bool 370 }{ 371 "multipleChanges": { 372 Input: `@@ -1,3 +1,2 @@ 373 context line 374-old line 1 375 context line 376@@ -8,3 +7,3 @@ 377 context line 378-old line 2 379+new line 1 380 context line 381@@ -15,3 +14,4 @@ 382 context line 383-old line 3 384+new line 2 385+new line 3 386 context line 387`, 388 Fragments: []*TextFragment{ 389 { 390 OldPosition: 1, 391 OldLines: 3, 392 NewPosition: 1, 393 NewLines: 2, 394 Lines: []Line{ 395 {OpContext, "context line\n"}, 396 {OpDelete, "old line 1\n"}, 397 {OpContext, "context line\n"}, 398 }, 399 LinesDeleted: 1, 400 LeadingContext: 1, 401 TrailingContext: 1, 402 }, 403 { 404 OldPosition: 8, 405 OldLines: 3, 406 NewPosition: 7, 407 NewLines: 3, 408 Lines: []Line{ 409 {OpContext, "context line\n"}, 410 {OpDelete, "old line 2\n"}, 411 {OpAdd, "new line 1\n"}, 412 {OpContext, "context line\n"}, 413 }, 414 LinesDeleted: 1, 415 LinesAdded: 1, 416 LeadingContext: 1, 417 TrailingContext: 1, 418 }, 419 { 420 OldPosition: 15, 421 OldLines: 3, 422 NewPosition: 14, 423 NewLines: 4, 424 Lines: []Line{ 425 {OpContext, "context line\n"}, 426 {OpDelete, "old line 3\n"}, 427 {OpAdd, "new line 2\n"}, 428 {OpAdd, "new line 3\n"}, 429 {OpContext, "context line\n"}, 430 }, 431 LinesDeleted: 1, 432 LinesAdded: 2, 433 LeadingContext: 1, 434 TrailingContext: 1, 435 }, 436 }, 437 }, 438 "badNewFile": { 439 Input: `@@ -1 +1,2 @@ 440-old line 1 441+new line 1 442+new line 2 443`, 444 File: File{ 445 IsNew: true, 446 }, 447 Err: true, 448 }, 449 "badDeletedFile": { 450 Input: `@@ -1,2 +1 @@ 451-old line 1 452 context line 453`, 454 File: File{ 455 IsDelete: true, 456 }, 457 Err: true, 458 }, 459 } 460 461 for name, test := range tests { 462 t.Run(name, func(t *testing.T) { 463 p := newTestParser(test.Input, true) 464 465 file := test.File 466 n, err := p.ParseTextFragments(&file) 467 if test.Err { 468 if err == nil || err == io.EOF { 469 t.Fatalf("expected error parsing text fragments, but got %v", err) 470 } 471 return 472 } 473 if err != nil { 474 t.Fatalf("error parsing text fragments: %v", err) 475 } 476 477 if len(test.Fragments) != n { 478 t.Fatalf("incorrect number of added fragments: expected %d, actual %d", len(test.Fragments), n) 479 } 480 481 for i, frag := range test.Fragments { 482 if !reflect.DeepEqual(frag, file.TextFragments[i]) { 483 t.Errorf("incorrect fragment at position %d\nexpected: %+v\nactual: %+v", i, frag, file.TextFragments[i]) 484 } 485 } 486 }) 487 } 488}