package gitdiff import ( "testing" "time" ) func TestParsePatchIdentity(t *testing.T) { tests := map[string]struct { Input string Output PatchIdentity Err interface{} }{ "simple": { Input: "Morton Haypenny ", Output: PatchIdentity{ Name: "Morton Haypenny", Email: "mhaypenny@example.com", }, }, "extraWhitespace": { Input: " Morton Haypenny ", Output: PatchIdentity{ Name: "Morton Haypenny", Email: "mhaypenny@example.com", }, }, "trailingCharacters": { Input: "Morton Haypenny unrelated garbage", Output: PatchIdentity{ Name: "Morton Haypenny", Email: "mhaypenny@example.com", }, }, "missingName": { Input: "", Err: "invalid identity", }, "missingEmail": { Input: "Morton Haypenny", Err: "invalid identity", }, "unclosedEmail": { Input: "Morton Haypenny A sample commit to test header parsing `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, Title: expectedTitle, }, }, "prettyMedium": { Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Author: Morton Haypenny Date: Sat Apr 11 15:21:23 2020 -0700 A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: expectedTitle, Body: expectedBody, }, }, "prettyFull": { Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Author: Morton Haypenny Commit: Morton Haypenny A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, Committer: expectedIdentity, Title: expectedTitle, Body: expectedBody, }, }, "prettyFuller": { Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Author: Morton Haypenny AuthorDate: Sat Apr 11 15:21:23 2020 -0700 Commit: Morton Haypenny CommitDate: Sat Apr 11 15:21:23 2020 -0700 A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Committer: expectedIdentity, CommitterDate: expectedDate, Title: expectedTitle, Body: expectedBody, }, }, "prettyAppendix": { Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Author: Morton Haypenny AuthorDate: Sat Apr 11 15:21:23 2020 -0700 Commit: Morton Haypenny CommitDate: Sat Apr 11 15:21:23 2020 -0700 A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. --- CC: Joe Smith `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Committer: expectedIdentity, CommitterDate: expectedDate, Title: expectedTitle, Body: expectedBody + "\n---\n" + expectedBodyAppendix, }, }, "mailbox": { Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 From: Morton Haypenny Date: Sat, 11 Apr 2020 15:21:23 -0700 Subject: [PATCH] A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: expectedTitle, Body: expectedBody, }, }, "mailboxPatchOnly": { Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 From: Morton Haypenny Date: Sat, 11 Apr 2020 15:21:23 -0700 Subject: [PATCH] [BUG-123] A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Options: []PatchHeaderOption{ WithSubjectCleanMode(SubjectCleanPatchOnly), }, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: "[BUG-123] " + expectedTitle, Body: expectedBody, }, }, "mailboxEmojiOneLine": { Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 From: Morton Haypenny Date: Sat, 11 Apr 2020 15:21:23 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Enabling=20auto-merging?= The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: expectedEmojiOneLineTitle, Body: expectedBody, }, }, "mailboxEmojiMultiLine": { Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 From: Morton Haypenny Date: Sat, 11 Apr 2020 15:21:23 -0700 Subject: [PATCH] =?UTF-8?q?[IA64]=20Put=20ia64=20config=20files=20on=20the=20?= =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20diet?= The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: expectedEmojiMultiLineTitle, Body: expectedBody, }, }, "mailboxAppendix": { Input: `From 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Mon Sep 17 00:00:00 2001 From: Morton Haypenny Date: Sat, 11 Apr 2020 15:21:23 -0700 Subject: [PATCH] A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. --- CC: Joe Smith `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: expectedTitle, Body: expectedBody, BodyAppendix: expectedBodyAppendix, }, }, "mailboxMinimalNoName": { Input: `From: Subject: [PATCH] A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ Author: &PatchIdentity{expectedIdentity.Email, expectedIdentity.Email}, Title: expectedTitle, Body: expectedBody, }, }, "mailboxMinimal": { Input: `From: Morton Haypenny Subject: [PATCH] A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ Author: expectedIdentity, Title: expectedTitle, Body: expectedBody, }, }, "unwrapTitle": { Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Author: Morton Haypenny Date: Sat Apr 11 15:21:23 2020 -0700 A sample commit to test header parsing with a long title that is wrapped. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: expectedTitle + " with a long title that is wrapped.", }, }, "normalizeBodySpace": { Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Author: Morton Haypenny Date: Sat Apr 11 15:21:23 2020 -0700 A sample commit to test header parsing The medium format shows the body, which may wrap on to multiple lines. Another body line. `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, AuthorDate: expectedDate, Title: expectedTitle, Body: expectedBody, }, }, "ignoreLeadingBlankLines": { Input: ` ` + " " + ` commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b Author: Morton Haypenny A sample commit to test header parsing `, Header: PatchHeader{ SHA: expectedSHA, Author: expectedIdentity, Title: expectedTitle, }, }, "emptyHeader": { Input: "", Header: PatchHeader{}, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { h, err := ParsePatchHeader(test.Input, test.Options...) if test.Err != nil { assertError(t, test.Err, err, "parsing patch header") return } if err != nil { t.Fatalf("unexpected error parsing patch header: %v", err) } if h == nil { t.Fatalf("expected non-nil header, but got nil") } exp := test.Header act := *h if exp.SHA != act.SHA { t.Errorf("incorrect parsed SHA: expected %q, actual %q", exp.SHA, act.SHA) } assertPatchIdentity(t, "author", exp.Author, act.Author) if !exp.AuthorDate.Equal(act.AuthorDate) { t.Errorf("incorrect parsed author date: expected %v, but got %v", exp.AuthorDate, act.AuthorDate) } assertPatchIdentity(t, "committer", exp.Committer, act.Committer) if !exp.CommitterDate.Equal(act.CommitterDate) { t.Errorf("incorrect parsed committer date: expected %v, but got %v", exp.CommitterDate, act.CommitterDate) } if exp.Title != act.Title { t.Errorf("incorrect parsed title:\n expected: %q\n actual: %q", exp.Title, act.Title) } if exp.Body != act.Body { t.Errorf("incorrect parsed body:\n expected: %q\n actual: %q", exp.Body, act.Body) } if exp.BodyAppendix != act.BodyAppendix { t.Errorf("incorrect parsed body appendix:\n expected: %q\n actual: %q", exp.BodyAppendix, act.BodyAppendix) } }) } } func assertPatchIdentity(t *testing.T, kind string, exp, act *PatchIdentity) { switch { case exp == nil && act == nil: case exp == nil && act != nil: t.Errorf("incorrect parsed %s: expected nil, but got %+v", kind, act) case exp != nil && act == nil: t.Errorf("incorrect parsed %s: expected %+v, but got nil", kind, exp) case exp.Name != act.Name || exp.Email != act.Email: t.Errorf("incorrect parsed %s, expected %+v, bot got %+v", kind, exp, act) } } func TestCleanSubject(t *testing.T) { expectedSubject := "A sample commit to test header parsing" tests := map[string]struct { Input string Mode SubjectCleanMode Prefix string Subject string }{ "CleanAll/noPrefix": { Input: expectedSubject, Mode: SubjectCleanAll, Subject: expectedSubject, }, "CleanAll/patchPrefix": { Input: "[PATCH] " + expectedSubject, Mode: SubjectCleanAll, Prefix: "[PATCH] ", Subject: expectedSubject, }, "CleanAll/patchPrefixNoSpace": { Input: "[PATCH]" + expectedSubject, Mode: SubjectCleanAll, Prefix: "[PATCH]", Subject: expectedSubject, }, "CleanAll/patchPrefixContent": { Input: "[PATCH 3/7] " + expectedSubject, Mode: SubjectCleanAll, Prefix: "[PATCH 3/7] ", Subject: expectedSubject, }, "CleanAll/spacePrefix": { Input: " " + expectedSubject, Mode: SubjectCleanAll, Subject: expectedSubject, }, "CleanAll/replyLowerPrefix": { Input: "re: " + expectedSubject, Mode: SubjectCleanAll, Prefix: "re: ", Subject: expectedSubject, }, "CleanAll/replyMixedPrefix": { Input: "Re: " + expectedSubject, Mode: SubjectCleanAll, Prefix: "Re: ", Subject: expectedSubject, }, "CleanAll/replyCapsPrefix": { Input: "RE: " + expectedSubject, Mode: SubjectCleanAll, Prefix: "RE: ", Subject: expectedSubject, }, "CleanAll/replyDoublePrefix": { Input: "Re: re: " + expectedSubject, Mode: SubjectCleanAll, Prefix: "Re: re: ", Subject: expectedSubject, }, "CleanAll/noPrefixSubjectHasRe": { Input: "Reimplement parsing", Mode: SubjectCleanAll, Subject: "Reimplement parsing", }, "CleanAll/patchPrefixSubjectHasRe": { Input: "[PATCH 1/2] Reimplement parsing", Mode: SubjectCleanAll, Prefix: "[PATCH 1/2] ", Subject: "Reimplement parsing", }, "CleanAll/unclosedPrefix": { Input: "[Just to annoy people", Mode: SubjectCleanAll, Subject: "[Just to annoy people", }, "CleanAll/multiplePrefix": { Input: " Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject + " ", Mode: SubjectCleanAll, Prefix: "Re:Re: [PATCH 1/2][DRAFT] ", Subject: expectedSubject, }, "CleanPatchOnly/patchPrefix": { Input: "[PATCH] " + expectedSubject, Mode: SubjectCleanPatchOnly, Prefix: "[PATCH] ", Subject: expectedSubject, }, "CleanPatchOnly/mixedPrefix": { Input: "[PATCH] [TICKET-123] " + expectedSubject, Mode: SubjectCleanPatchOnly, Prefix: "[PATCH] ", Subject: "[TICKET-123] " + expectedSubject, }, "CleanPatchOnly/multiplePrefix": { Input: "Re:Re: [PATCH 1/2][DRAFT] " + expectedSubject, Mode: SubjectCleanPatchOnly, Prefix: "Re:Re: [PATCH 1/2]", Subject: "[DRAFT] " + expectedSubject, }, "CleanWhitespace/leadingSpace": { Input: " [PATCH] " + expectedSubject, Mode: SubjectCleanWhitespace, Subject: "[PATCH] " + expectedSubject, }, "CleanWhitespace/trailingSpace": { Input: "[PATCH] " + expectedSubject + " ", Mode: SubjectCleanWhitespace, Subject: "[PATCH] " + expectedSubject, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { prefix, subject := cleanSubject(test.Input, test.Mode) if prefix != test.Prefix { t.Errorf("incorrect prefix: expected %q, actual %q", test.Prefix, prefix) } if subject != test.Subject { t.Errorf("incorrect subject: expected %q, actual %q", test.Subject, subject) } }) } }