|
22 | 22 | from git.objects.util import ( |
23 | 23 | altz_to_utctz_str, |
24 | 24 | from_timestamp, |
| 25 | + parse_actor_and_date, |
25 | 26 | parse_date, |
26 | 27 | tzoffset, |
27 | 28 | utctz_to_altz, |
@@ -571,6 +572,54 @@ def test_actor_from_string(self): |
571 | 572 | Actor("name last another", "some-very-long-email@example.com"), |
572 | 573 | ) |
573 | 574 |
|
| 575 | + @ddt.data( |
| 576 | + ("", Actor("", None), 0, 0), |
| 577 | + ("author", Actor("author", None), 0, 0), |
| 578 | + ("author Name <email> 42 -0700", Actor("Name", "email"), 42, 25200), |
| 579 | + ("committer Name <email> 42 +0530\n", Actor("Name", "email"), 42, -19800), |
| 580 | + ("tagger Name <email> 42 +0000\r\n", Actor("Name", "email"), 42, 0), |
| 581 | + ("author Name <email> 42 -0700 trailing", Actor("Name", "email"), 42, 25200), |
| 582 | + ("author Name <email> 1 +0 42 -0700", Actor("Name", "email"), 42, 25200), |
| 583 | + ("author Name <email> invalid -0700", Actor("Name", "email"), 0, 0), |
| 584 | + ("author Name <email> 42 invalid", Actor("Name", "email"), 0, 0), |
| 585 | + ("author 42 -0700", Actor("42 -0700", None), 0, 0), |
| 586 | + ("author 42 -0700", Actor("", None), 42, 25200), |
| 587 | + (" author Name <email> 42 -0700", Actor("Name", "email"), 42, 25200), |
| 588 | + ("author Näme <email> ١ +٠١٣٠", Actor("Näme", "email"), 1, -5400), |
| 589 | + ("author\nName <email> 42 -0700", Actor("author\nName <email> 42 -0700", None), 0, 0), |
| 590 | + ("author Name <email> 42 -0700\nextra", Actor("author Name", "email"), 0, 0), |
| 591 | + ) |
| 592 | + @ddt.unpack |
| 593 | + def test_parse_actor_and_date(self, line, actor, epoch, offset): |
| 594 | + self.assertEqual(parse_actor_and_date(line), (actor, epoch, offset)) |
| 595 | + |
| 596 | + def test_parse_actor_and_date_long_malformed_lines(self): |
| 597 | + padding = " " * 64_000 |
| 598 | + for field in ("author", "committer", "tagger"): |
| 599 | + for tail in ("", "<unterminated", "invalid -0700", "42", "-0700", "42 invalid", "42 +"): |
| 600 | + actor_text = padding + tail |
| 601 | + start = time.process_time() |
| 602 | + result = parse_actor_and_date(f"{field} {actor_text}") |
| 603 | + elapsed = time.process_time() - start |
| 604 | + # Leave ample CPU time for slow runners, but catch excessive backtracking. |
| 605 | + self.assertLess(elapsed, 1.0, (field, tail)) |
| 606 | + self.assertEqual(result, (Actor(actor_text, None), 0, 0)) |
| 607 | + |
| 608 | + name = "Long name " * 6_400 |
| 609 | + self.assertEqual( |
| 610 | + parse_actor_and_date(f"{field} {name}<email> 42 -0700"), |
| 611 | + (Actor(name.rstrip(), "email"), 42, 25200), |
| 612 | + ) |
| 613 | + |
| 614 | + def test_parse_actor_and_date_long_multiline_input(self): |
| 615 | + for field in ("author", "committer", "tagger"): |
| 616 | + line = f"{field} Name <email> 42 +" + "0" * 64_000 + "\nextra" |
| 617 | + start = time.process_time() |
| 618 | + result = parse_actor_and_date(line) |
| 619 | + elapsed = time.process_time() - start |
| 620 | + self.assertLess(elapsed, 1.0, field) |
| 621 | + self.assertEqual(result, (Actor(f"{field} Name", "email"), 0, 0)) |
| 622 | + |
574 | 623 | @ddt.data( |
575 | 624 | ("name", ""), |
576 | 625 | ("name", "prefix_"), |
|
0 commit comments