fork of go-gitdiff with jj support
at v0.5.1 13 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 expectedBody := "The medium format shows the body, which\nmay wrap on to multiple lines.\n\nAnother body line." 142 expectedBodyAppendix := "CC: Joe Smith <joe.smith@company.com>" 143 144 tests := map[string]struct { 145 Input string 146 Header PatchHeader 147 Err interface{} 148 }{ 149 "prettyShort": { 150 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 151Author: Morton Haypenny <mhaypenny@example.com> 152 153 A sample commit to test header parsing 154`, 155 Header: PatchHeader{ 156 SHA: expectedSHA, 157 Author: expectedIdentity, 158 Title: expectedTitle, 159 }, 160 }, 161 "prettyMedium": { 162 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 163Author: Morton Haypenny <mhaypenny@example.com> 164Date: Sat Apr 11 15:21:23 2020 -0700 165 166 A sample commit to test header parsing 167 168 The medium format shows the body, which 169 may wrap on to multiple lines. 170 171 Another body line. 172`, 173 Header: PatchHeader{ 174 SHA: expectedSHA, 175 Author: expectedIdentity, 176 AuthorDate: expectedDate, 177 Title: expectedTitle, 178 Body: expectedBody, 179 }, 180 }, 181 "prettyFull": { 182 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 183Author: Morton Haypenny <mhaypenny@example.com> 184Commit: Morton Haypenny <mhaypenny@example.com> 185 186 A sample commit to test header parsing 187 188 The medium format shows the body, which 189 may wrap on to multiple lines. 190 191 Another body line. 192`, 193 Header: PatchHeader{ 194 SHA: expectedSHA, 195 Author: expectedIdentity, 196 Committer: expectedIdentity, 197 Title: expectedTitle, 198 Body: expectedBody, 199 }, 200 }, 201 "prettyFuller": { 202 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 203Author: Morton Haypenny <mhaypenny@example.com> 204AuthorDate: Sat Apr 11 15:21:23 2020 -0700 205Commit: Morton Haypenny <mhaypenny@example.com> 206CommitDate: Sat Apr 11 15:21:23 2020 -0700 207 208 A sample commit to test header parsing 209 210 The medium format shows the body, which 211 may wrap on to multiple lines. 212 213 Another body line. 214`, 215 Header: PatchHeader{ 216 SHA: expectedSHA, 217 Author: expectedIdentity, 218 AuthorDate: expectedDate, 219 Committer: expectedIdentity, 220 CommitterDate: expectedDate, 221 Title: expectedTitle, 222 Body: expectedBody, 223 }, 224 }, 225 "prettyAppendix": { 226 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 227Author: Morton Haypenny <mhaypenny@example.com> 228AuthorDate: Sat Apr 11 15:21:23 2020 -0700 229Commit: Morton Haypenny <mhaypenny@example.com> 230CommitDate: Sat Apr 11 15:21:23 2020 -0700 231 232 A sample commit to test header parsing 233 234 The medium format shows the body, which 235 may wrap on to multiple lines. 236 237 Another body line. 238 --- 239 CC: Joe Smith <joe.smith@company.com> 240`, 241 Header: PatchHeader{ 242 SHA: expectedSHA, 243 Author: expectedIdentity, 244 AuthorDate: expectedDate, 245 Committer: expectedIdentity, 246 CommitterDate: expectedDate, 247 Title: expectedTitle, 248 Body: expectedBody + "\n---\n" + expectedBodyAppendix, 249 }, 250 }, 251 "mailbox": { 252 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 253From: Morton Haypenny <mhaypenny@example.com> 254Date: Sat, 11 Apr 2020 15:21:23 -0700 255Subject: [PATCH] A sample commit to test header parsing 256 257The medium format shows the body, which 258may wrap on to multiple lines. 259 260Another body line. 261`, 262 Header: PatchHeader{ 263 SHA: expectedSHA, 264 Author: expectedIdentity, 265 AuthorDate: expectedDate, 266 Title: expectedTitle, 267 Body: expectedBody, 268 }, 269 }, 270 "mailboxAppendix": { 271 Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 272From: Morton Haypenny <mhaypenny@example.com> 273Date: Sat, 11 Apr 2020 15:21:23 -0700 274Subject: [PATCH] A sample commit to test header parsing 275 276The medium format shows the body, which 277may wrap on to multiple lines. 278 279Another body line. 280--- 281CC: Joe Smith <joe.smith@company.com> 282`, 283 Header: PatchHeader{ 284 SHA: expectedSHA, 285 Author: expectedIdentity, 286 AuthorDate: expectedDate, 287 Title: expectedTitle, 288 Body: expectedBody, 289 BodyAppendix: expectedBodyAppendix, 290 }, 291 }, 292 "mailboxMinimalNoName": { 293 Input: `From: <mhaypenny@example.com> 294Subject: [PATCH] A sample commit to test header parsing 295 296The medium format shows the body, which 297may wrap on to multiple lines. 298 299Another body line. 300`, 301 Header: PatchHeader{ 302 Author: &PatchIdentity{expectedIdentity.Email, expectedIdentity.Email}, 303 Title: expectedTitle, 304 Body: expectedBody, 305 }, 306 }, 307 "mailboxMinimal": { 308 Input: `From: Morton Haypenny <mhaypenny@example.com> 309Subject: [PATCH] A sample commit to test header parsing 310 311The medium format shows the body, which 312may wrap on to multiple lines. 313 314Another body line. 315`, 316 Header: PatchHeader{ 317 Author: expectedIdentity, 318 Title: expectedTitle, 319 Body: expectedBody, 320 }, 321 }, 322 "unwrapTitle": { 323 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 324Author: Morton Haypenny <mhaypenny@example.com> 325Date: Sat Apr 11 15:21:23 2020 -0700 326 327 A sample commit to test header parsing with a long 328 title that is wrapped. 329`, 330 Header: PatchHeader{ 331 SHA: expectedSHA, 332 Author: expectedIdentity, 333 AuthorDate: expectedDate, 334 Title: expectedTitle + " with a long title that is wrapped.", 335 }, 336 }, 337 "normalizeBodySpace": { 338 Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 339Author: Morton Haypenny <mhaypenny@example.com> 340Date: Sat Apr 11 15:21:23 2020 -0700 341 342 A sample commit to test header parsing 343 344 345 The medium format shows the body, which 346 may wrap on to multiple lines. 347 348 349 Another body line. 350 351 352`, 353 Header: PatchHeader{ 354 SHA: expectedSHA, 355 Author: expectedIdentity, 356 AuthorDate: expectedDate, 357 Title: expectedTitle, 358 Body: expectedBody, 359 }, 360 }, 361 "ignoreLeadingBlankLines": { 362 Input: ` 363 364` + " " + ` 365commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b 366Author: Morton Haypenny <mhaypenny@example.com> 367 368 A sample commit to test header parsing 369`, 370 Header: PatchHeader{ 371 SHA: expectedSHA, 372 Author: expectedIdentity, 373 Title: expectedTitle, 374 }, 375 }, 376 } 377 378 for name, test := range tests { 379 t.Run(name, func(t *testing.T) { 380 h, err := ParsePatchHeader(test.Input) 381 if test.Err != nil { 382 assertError(t, test.Err, err, "parsing patch header") 383 return 384 } 385 if err != nil { 386 t.Fatalf("unexpected error parsing patch header: %v", err) 387 } 388 if h == nil { 389 t.Fatalf("expected non-nil header, but got nil") 390 } 391 392 exp := test.Header 393 act := *h 394 395 if exp.SHA != act.SHA { 396 t.Errorf("incorrect parsed SHA: expected %q, actual %q", exp.SHA, act.SHA) 397 } 398 399 assertPatchIdentity(t, "author", exp.Author, act.Author) 400 if !exp.AuthorDate.Equal(act.AuthorDate) { 401 t.Errorf("incorrect parsed author date: expected %v, but got %v", exp.AuthorDate, act.AuthorDate) 402 } 403 404 assertPatchIdentity(t, "committer", exp.Committer, act.Committer) 405 if !exp.CommitterDate.Equal(act.CommitterDate) { 406 t.Errorf("incorrect parsed committer date: expected %v, but got %v", exp.CommitterDate, act.CommitterDate) 407 } 408 409 if exp.Title != act.Title { 410 t.Errorf("incorrect parsed title:\n expected: %q\n actual: %q", exp.Title, act.Title) 411 } 412 if exp.Body != act.Body { 413 t.Errorf("incorrect parsed body:\n expected: %q\n actual: %q", exp.Body, act.Body) 414 } 415 if exp.BodyAppendix != act.BodyAppendix { 416 t.Errorf("incorrect parsed body appendix:\n expected: %q\n actual: %q", 417 exp.BodyAppendix, act.BodyAppendix) 418 } 419 }) 420 } 421} 422 423func assertPatchIdentity(t *testing.T, kind string, exp, act *PatchIdentity) { 424 switch { 425 case exp == nil && act == nil: 426 case exp == nil && act != nil: 427 t.Errorf("incorrect parsed %s: expected nil, but got %+v", kind, act) 428 case exp != nil && act == nil: 429 t.Errorf("incorrect parsed %s: expected %+v, but got nil", kind, exp) 430 case exp.Name != act.Name || exp.Email != act.Email: 431 t.Errorf("incorrect parsed %s, expected %+v, bot got %+v", kind, exp, act) 432 } 433} 434 435func TestCleanupSubject(t *testing.T) { 436 exp := "A sample commit to test header parsing" 437 tests := map[string]string{ 438 "plain": "", 439 "patch": "[PATCH] ", 440 "patchv5": "[PATCH v5] ", 441 "patchrfc": "[PATCH RFC] ", 442 "patchnospace": "[PATCH]", 443 "space": " ", 444 "re": "re: ", 445 "Re": "Re: ", 446 "RE": "rE: ", 447 "rere": "re: re: ", 448 } 449 450 for name, prefix := range tests { 451 gotprefix, gottitle := parseSubject(prefix + exp) 452 if gottitle != exp { 453 t.Errorf("%s: Incorrect parsing of prefix %s: got title %s, wanted %s", 454 name, prefix, gottitle, exp) 455 } 456 if gotprefix != prefix { 457 t.Errorf("%s: Incorrect parsing of prefix %s: got prefix %s", 458 name, prefix, gotprefix) 459 } 460 } 461 462 moretests := map[string]struct { 463 in, eprefix, etitle string 464 }{ 465 "Reimplement": {"Reimplement something", "", "Reimplement something"}, 466 "patch-reimplement": {"[PATCH v5] Reimplement something", "[PATCH v5] ", "Reimplement something"}, 467 "Openbracket": {"[Just to annoy people", "", "[Just to annoy people"}, 468 } 469 470 for name, test := range moretests { 471 prefix, title := parseSubject(test.in) 472 if title != test.etitle { 473 t.Errorf("%s: Incorrect parsing of %s: got title %s, wanted %s", 474 name, test.in, title, test.etitle) 475 } 476 if prefix != test.eprefix { 477 t.Errorf("%s: Incorrect parsing of %s: got prefix %s, wanted %s", 478 name, test.in, title, test.etitle) 479 } 480 } 481}