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