fork of go-gitdiff with jj support
at v0.8.1 16 kB view raw
1package gitdiff 2 3import ( 4 "testing" 5 "time" 6) 7 8func TestParsePatchDate(t *testing.T) { 9 expected := time.Date(2020, 4, 9, 8, 7, 6, 0, time.UTC) 10 11 tests := map[string]struct { 12 Input string 13 Output time.Time 14 Err interface{} 15 }{ 16 "default": { 17 Input: "Thu Apr 9 01:07:06 2020 -0700", 18 Output: expected, 19 }, 20 "defaultLocal": { 21 Input: "Thu Apr 9 01:07:06 2020", 22 Output: time.Date(2020, 4, 9, 1, 7, 6, 0, time.Local), 23 }, 24 "iso": { 25 Input: "2020-04-09 01:07:06 -0700", 26 Output: expected, 27 }, 28 "isoStrict": { 29 Input: "2020-04-09T01:07:06-07:00", 30 Output: expected, 31 }, 32 "rfc": { 33 Input: "Thu, 9 Apr 2020 01:07:06 -0700", 34 Output: expected, 35 }, 36 "short": { 37 Input: "2020-04-09", 38 Output: time.Date(2020, 4, 9, 0, 0, 0, 0, time.Local), 39 }, 40 "raw": { 41 Input: "1586419626 -0700", 42 Output: expected, 43 }, 44 "unix": { 45 Input: "1586419626", 46 Output: expected, 47 }, 48 "unknownFormat": { 49 Input: "4/9/2020 01:07:06 PDT", 50 Err: "unknown date format", 51 }, 52 "empty": { 53 Input: "", 54 }, 55 } 56 57 for name, test := range tests { 58 t.Run(name, func(t *testing.T) { 59 d, err := ParsePatchDate(test.Input) 60 if test.Err != nil { 61 assertError(t, test.Err, err, "parsing date") 62 return 63 } 64 if err != nil { 65 t.Fatalf("unexpected error parsing date: %v", err) 66 } 67 if !test.Output.Equal(d) { 68 t.Errorf("incorrect parsed date: expected %v, actual %v", test.Output, d) 69 } 70 }) 71 } 72} 73 74func TestParsePatchHeader(t *testing.T) { 75 expectedSHA := "61f5cd90bed4d204ee3feb3aa41ee91d4734855b" 76 expectedIdentity := &PatchIdentity{ 77 Name: "Morton Haypenny", 78 Email: "mhaypenny@example.com", 79 } 80 expectedDate := time.Date(2020, 04, 11, 15, 21, 23, 0, time.FixedZone("PDT", -7*60*60)) 81 expectedTitle := "A sample commit to test header parsing" 82 expectedEmojiOneLineTitle := "🤖 Enabling auto-merging" 83 expectedEmojiMultiLineTitle := "[IA64] Put ia64 config files on the Uwe Kleine-König diet" 84 expectedBody := "The medium format shows the body, which\nmay wrap on to multiple lines.\n\nAnother body line." 85 expectedBodyAppendix := "CC: Joe Smith <joe.smith@company.com>" 86 87 tests := map[string]struct { 88 Input string 89 Options []PatchHeaderOption 90 Header PatchHeader 91 Err interface{} 92 }{ 93 "prettyShort": { 94 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 95Author: Morton Haypenny <mhaypenny@example.com> 96 97 A sample commit to test header parsing 98`, 99 Header: PatchHeader{ 100 SHA: expectedSHA, 101 Author: expectedIdentity, 102 Title: expectedTitle, 103 }, 104 }, 105 "prettyMedium": { 106 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 107Author: Morton Haypenny <mhaypenny@example.com> 108Date: Sat Apr 11 15:21:23 2020 -0700 109 110 A sample commit to test header parsing 111 112 The medium format shows the body, which 113 may wrap on to multiple lines. 114 115 Another body line. 116`, 117 Header: PatchHeader{ 118 SHA: expectedSHA, 119 Author: expectedIdentity, 120 AuthorDate: expectedDate, 121 Title: expectedTitle, 122 Body: expectedBody, 123 }, 124 }, 125 "prettyFull": { 126 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 127Author: Morton Haypenny <mhaypenny@example.com> 128Commit: Morton Haypenny <mhaypenny@example.com> 129 130 A sample commit to test header parsing 131 132 The medium format shows the body, which 133 may wrap on to multiple lines. 134 135 Another body line. 136`, 137 Header: PatchHeader{ 138 SHA: expectedSHA, 139 Author: expectedIdentity, 140 Committer: expectedIdentity, 141 Title: expectedTitle, 142 Body: expectedBody, 143 }, 144 }, 145 "prettyFuller": { 146 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 147Author: Morton Haypenny <mhaypenny@example.com> 148AuthorDate: Sat Apr 11 15:21:23 2020 -0700 149Commit: Morton Haypenny <mhaypenny@example.com> 150CommitDate: Sat Apr 11 15:21:23 2020 -0700 151 152 A sample commit to test header parsing 153 154 The medium format shows the body, which 155 may wrap on to multiple lines. 156 157 Another body line. 158`, 159 Header: PatchHeader{ 160 SHA: expectedSHA, 161 Author: expectedIdentity, 162 AuthorDate: expectedDate, 163 Committer: expectedIdentity, 164 CommitterDate: expectedDate, 165 Title: expectedTitle, 166 Body: expectedBody, 167 }, 168 }, 169 "prettyAppendix": { 170 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 171Author: Morton Haypenny <mhaypenny@example.com> 172AuthorDate: Sat Apr 11 15:21:23 2020 -0700 173Commit: Morton Haypenny <mhaypenny@example.com> 174CommitDate: Sat Apr 11 15:21:23 2020 -0700 175 176 A sample commit to test header parsing 177 178 The medium format shows the body, which 179 may wrap on to multiple lines. 180 181 Another body line. 182 --- 183 CC: Joe Smith <joe.smith@company.com> 184`, 185 Header: PatchHeader{ 186 SHA: expectedSHA, 187 Author: expectedIdentity, 188 AuthorDate: expectedDate, 189 Committer: expectedIdentity, 190 CommitterDate: expectedDate, 191 Title: expectedTitle, 192 Body: expectedBody + "\n---\n" + expectedBodyAppendix, 193 }, 194 }, 195 "mailbox": { 196 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 197From: Morton Haypenny <mhaypenny@example.com> 198Date: Sat, 11 Apr 2020 15:21:23 -0700 199Subject: [PATCH] A sample commit to test header parsing 200 201The medium format shows the body, which 202may wrap on to multiple lines. 203 204Another body line. 205`, 206 Header: PatchHeader{ 207 SHA: expectedSHA, 208 Author: expectedIdentity, 209 AuthorDate: expectedDate, 210 Title: expectedTitle, 211 Body: expectedBody, 212 }, 213 }, 214 "mailboxPatchOnly": { 215 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 216From: Morton Haypenny <mhaypenny@example.com> 217Date: Sat, 11 Apr 2020 15:21:23 -0700 218Subject: [PATCH] [BUG-123] A sample commit to test header parsing 219 220The medium format shows the body, which 221may wrap on to multiple lines. 222 223Another body line. 224`, 225 Options: []PatchHeaderOption{ 226 WithSubjectCleanMode(SubjectCleanPatchOnly), 227 }, 228 Header: PatchHeader{ 229 SHA: expectedSHA, 230 Author: expectedIdentity, 231 AuthorDate: expectedDate, 232 Title: "[BUG-123] " + expectedTitle, 233 Body: expectedBody, 234 }, 235 }, 236 "mailboxEmojiOneLine": { 237 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 238From: Morton Haypenny <mhaypenny@example.com> 239Date: Sat, 11 Apr 2020 15:21:23 -0700 240Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Enabling=20auto-merging?= 241 242The medium format shows the body, which 243may wrap on to multiple lines. 244 245Another body line. 246`, 247 Header: PatchHeader{ 248 SHA: expectedSHA, 249 Author: expectedIdentity, 250 AuthorDate: expectedDate, 251 Title: expectedEmojiOneLineTitle, 252 Body: expectedBody, 253 }, 254 }, 255 "mailboxEmojiMultiLine": { 256 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 257From: Morton Haypenny <mhaypenny@example.com> 258Date: Sat, 11 Apr 2020 15:21:23 -0700 259Subject: [PATCH] =?UTF-8?q?[IA64]=20Put=20ia64=20config=20files=20on=20the=20?= 260 =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20diet?= 261 262The medium format shows the body, which 263may wrap on to multiple lines. 264 265Another body line. 266`, 267 Header: PatchHeader{ 268 SHA: expectedSHA, 269 Author: expectedIdentity, 270 AuthorDate: expectedDate, 271 Title: expectedEmojiMultiLineTitle, 272 Body: expectedBody, 273 }, 274 }, 275 "mailboxRFC5322SpecialCharacters": { 276 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 277From: "dependabot[bot]" <12345+dependabot[bot]@users.noreply.github.com> 278Date: Sat, 11 Apr 2020 15:21:23 -0700 279Subject: [PATCH] A sample commit to test header parsing 280 281The medium format shows the body, which 282may wrap on to multiple lines. 283 284Another body line. 285`, 286 Header: PatchHeader{ 287 SHA: expectedSHA, 288 Author: &PatchIdentity{ 289 Name: "dependabot[bot]", 290 Email: "12345+dependabot[bot]@users.noreply.github.com", 291 }, 292 AuthorDate: expectedDate, 293 Title: expectedTitle, 294 Body: expectedBody, 295 }, 296 }, 297 "mailboxAppendix": { 298 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 299From: Morton Haypenny <mhaypenny@example.com> 300Date: Sat, 11 Apr 2020 15:21:23 -0700 301Subject: [PATCH] A sample commit to test header parsing 302 303The medium format shows the body, which 304may wrap on to multiple lines. 305 306Another body line. 307--- 308CC: Joe Smith <joe.smith@company.com> 309`, 310 Header: PatchHeader{ 311 SHA: expectedSHA, 312 Author: expectedIdentity, 313 AuthorDate: expectedDate, 314 Title: expectedTitle, 315 Body: expectedBody, 316 BodyAppendix: expectedBodyAppendix, 317 }, 318 }, 319 "mailboxMinimalNoName": { 320 Input: `From: <mhaypenny@example.com> 321Subject: [PATCH] A sample commit to test header parsing 322 323The medium format shows the body, which 324may wrap on to multiple lines. 325 326Another body line. 327`, 328 Header: PatchHeader{ 329 Author: &PatchIdentity{expectedIdentity.Email, expectedIdentity.Email}, 330 Title: expectedTitle, 331 Body: expectedBody, 332 }, 333 }, 334 "mailboxMinimal": { 335 Input: `From: Morton Haypenny <mhaypenny@example.com> 336Subject: [PATCH] A sample commit to test header parsing 337 338The medium format shows the body, which 339may wrap on to multiple lines. 340 341Another body line. 342`, 343 Header: PatchHeader{ 344 Author: expectedIdentity, 345 Title: expectedTitle, 346 Body: expectedBody, 347 }, 348 }, 349 "unwrapTitle": { 350 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 351Author: Morton Haypenny <mhaypenny@example.com> 352Date: Sat Apr 11 15:21:23 2020 -0700 353 354 A sample commit to test header parsing with a long 355 title that is wrapped. 356`, 357 Header: PatchHeader{ 358 SHA: expectedSHA, 359 Author: expectedIdentity, 360 AuthorDate: expectedDate, 361 Title: expectedTitle + " with a long title that is wrapped.", 362 }, 363 }, 364 "normalizeBodySpace": { 365 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 366Author: Morton Haypenny <mhaypenny@example.com> 367Date: Sat Apr 11 15:21:23 2020 -0700 368 369 A sample commit to test header parsing 370 371 372 The medium format shows the body, which 373 may wrap on to multiple lines. 374 375 376 Another body line. 377 378 379`, 380 Header: PatchHeader{ 381 SHA: expectedSHA, 382 Author: expectedIdentity, 383 AuthorDate: expectedDate, 384 Title: expectedTitle, 385 Body: expectedBody, 386 }, 387 }, 388 "ignoreLeadingBlankLines": { 389 Input: ` 390 391` + " " + ` 392commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 393Author: Morton Haypenny <mhaypenny@example.com> 394 395 A sample commit to test header parsing 396`, 397 Header: PatchHeader{ 398 SHA: expectedSHA, 399 Author: expectedIdentity, 400 Title: expectedTitle, 401 }, 402 }, 403 "emptyHeader": { 404 Input: "", 405 Header: PatchHeader{}, 406 }, 407 } 408 409 for name, test := range tests { 410 t.Run(name, func(t *testing.T) { 411 h, err := ParsePatchHeader(test.Input, test.Options...) 412 if test.Err != nil { 413 assertError(t, test.Err, err, "parsing patch header") 414 return 415 } 416 if err != nil { 417 t.Fatalf("unexpected error parsing patch header: %v", err) 418 } 419 if h == nil { 420 t.Fatalf("expected non-nil header, but got nil") 421 } 422 423 exp := test.Header 424 act := *h 425 426 if exp.SHA != act.SHA { 427 t.Errorf("incorrect parsed SHA: expected %q, actual %q", exp.SHA, act.SHA) 428 } 429 430 assertPatchIdentity(t, "author", exp.Author, act.Author) 431 if !exp.AuthorDate.Equal(act.AuthorDate) { 432 t.Errorf("incorrect parsed author date: expected %v, but got %v", exp.AuthorDate, act.AuthorDate) 433 } 434 435 assertPatchIdentity(t, "committer", exp.Committer, act.Committer) 436 if !exp.CommitterDate.Equal(act.CommitterDate) { 437 t.Errorf("incorrect parsed committer date: expected %v, but got %v", exp.CommitterDate, act.CommitterDate) 438 } 439 440 if exp.Title != act.Title { 441 t.Errorf("incorrect parsed title:\n expected: %q\n actual: %q", exp.Title, act.Title) 442 } 443 if exp.Body != act.Body { 444 t.Errorf("incorrect parsed body:\n expected: %q\n actual: %q", exp.Body, act.Body) 445 } 446 if exp.BodyAppendix != act.BodyAppendix { 447 t.Errorf("incorrect parsed body appendix:\n expected: %q\n actual: %q", 448 exp.BodyAppendix, act.BodyAppendix) 449 } 450 }) 451 } 452} 453 454func assertPatchIdentity(t *testing.T, kind string, exp, act *PatchIdentity) { 455 switch { 456 case exp == nil && act == nil: 457 case exp == nil && act != nil: 458 t.Errorf("incorrect parsed %s: expected nil, but got %+v", kind, act) 459 case exp != nil && act == nil: 460 t.Errorf("incorrect parsed %s: expected %+v, but got nil", kind, exp) 461 case exp.Name != act.Name || exp.Email != act.Email: 462 t.Errorf("incorrect parsed %s, expected %+v, bot got %+v", kind, exp, act) 463 } 464} 465 466func TestCleanSubject(t *testing.T) { 467 expectedSubject := "A sample commit to test header parsing" 468 469 tests := map[string]struct { 470 Input string 471 Mode SubjectCleanMode 472 Prefix string 473 Subject string 474 }{ 475 "CleanAll/noPrefix": { 476 Input: expectedSubject, 477 Mode: SubjectCleanAll, 478 Subject: expectedSubject, 479 }, 480 "CleanAll/patchPrefix": { 481 Input: "[PATCH] " + expectedSubject, 482 Mode: SubjectCleanAll, 483 Prefix: "[PATCH] ", 484 Subject: expectedSubject, 485 }, 486 "CleanAll/patchPrefixNoSpace": { 487 Input: "[PATCH]" + expectedSubject, 488 Mode: SubjectCleanAll, 489 Prefix: "[PATCH]", 490 Subject: expectedSubject, 491 }, 492 "CleanAll/patchPrefixContent": { 493 Input: "[PATCH 3/7] " + expectedSubject, 494 Mode: SubjectCleanAll, 495 Prefix: "[PATCH 3/7] ", 496 Subject: expectedSubject, 497 }, 498 "CleanAll/spacePrefix": { 499 Input: " " + expectedSubject, 500 Mode: SubjectCleanAll, 501 Subject: expectedSubject, 502 }, 503 "CleanAll/replyLowerPrefix": { 504 Input: "re: " + expectedSubject, 505 Mode: SubjectCleanAll, 506 Prefix: "re: ", 507 Subject: expectedSubject, 508 }, 509 "CleanAll/replyMixedPrefix": { 510 Input: "Re: " + expectedSubject, 511 Mode: SubjectCleanAll, 512 Prefix: "Re: ", 513 Subject: expectedSubject, 514 }, 515 "CleanAll/replyCapsPrefix": { 516 Input: "RE: " + expectedSubject, 517 Mode: SubjectCleanAll, 518 Prefix: "RE: ", 519 Subject: expectedSubject, 520 }, 521 "CleanAll/replyDoublePrefix": { 522 Input: "Re: re: " + expectedSubject, 523 Mode: SubjectCleanAll, 524 Prefix: "Re: re: ", 525 Subject: expectedSubject, 526 }, 527 "CleanAll/noPrefixSubjectHasRe": { 528 Input: "Reimplement parsing", 529 Mode: SubjectCleanAll, 530 Subject: "Reimplement parsing", 531 }, 532 "CleanAll/patchPrefixSubjectHasRe": { 533 Input: "[PATCH 1/2] Reimplement parsing", 534 Mode: SubjectCleanAll, 535 Prefix: "[PATCH 1/2] ", 536 Subject: "Reimplement parsing", 537 }, 538 "CleanAll/unclosedPrefix": { 539 Input: "[Just to annoy people", 540 Mode: SubjectCleanAll, 541 Subject: "[Just to annoy people", 542 }, 543 "CleanAll/multiplePrefix": { 544 Input: " Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject + " ", 545 Mode: SubjectCleanAll, 546 Prefix: "Re:Re: [PATCH 1/2][DRAFT] ", 547 Subject: expectedSubject, 548 }, 549 "CleanPatchOnly/patchPrefix": { 550 Input: "[PATCH] " + expectedSubject, 551 Mode: SubjectCleanPatchOnly, 552 Prefix: "[PATCH] ", 553 Subject: expectedSubject, 554 }, 555 "CleanPatchOnly/mixedPrefix": { 556 Input: "[PATCH] [TICKET-123] " + expectedSubject, 557 Mode: SubjectCleanPatchOnly, 558 Prefix: "[PATCH] ", 559 Subject: "[TICKET-123] " + expectedSubject, 560 }, 561 "CleanPatchOnly/multiplePrefix": { 562 Input: "Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject, 563 Mode: SubjectCleanPatchOnly, 564 Prefix: "Re:Re: [PATCH 1/2]", 565 Subject: "[DRAFT] " + expectedSubject, 566 }, 567 "CleanWhitespace/leadingSpace": { 568 Input: " [PATCH] " + expectedSubject, 569 Mode: SubjectCleanWhitespace, 570 Subject: "[PATCH] " + expectedSubject, 571 }, 572 "CleanWhitespace/trailingSpace": { 573 Input: "[PATCH] " + expectedSubject + " ", 574 Mode: SubjectCleanWhitespace, 575 Subject: "[PATCH] " + expectedSubject, 576 }, 577 } 578 579 for name, test := range tests { 580 t.Run(name, func(t *testing.T) { 581 prefix, subject := cleanSubject(test.Input, test.Mode) 582 if prefix != test.Prefix { 583 t.Errorf("incorrect prefix: expected %q, actual %q", test.Prefix, prefix) 584 } 585 if subject != test.Subject { 586 t.Errorf("incorrect subject: expected %q, actual %q", test.Subject, subject) 587 } 588 }) 589 } 590}