1package commands
2
3import (
4 "fmt"
5 "io/ioutil"
6 "strings"
7 "testing"
8 "time"
9
10 "github.com/stretchr/testify/require"
11)
12
13func TestComment(t *testing.T) {
14 const golden = "testdata/comment/message-only"
15
16 env, bug := newTestEnvAndBug(t)
17
18 require.NoError(t, runComment(env.env, []string{bug}))
19
20 requireCommentsEqual(t, golden, env)
21}
22
23const gitDateFormat = "Mon Jan 2 15:04:05 2006 -0700"
24
25type parsedComment struct {
26 author string
27 id string
28 date time.Time
29 message string
30}
31
32type parseFunc func(*parsedComment, string)
33
34type commentParser struct {
35 t *testing.T
36 fn parseFunc
37 comments []parsedComment
38}
39
40func parseComments(t *testing.T, env *testEnv) []parsedComment {
41 t.Helper()
42
43 parser := &commentParser{
44 t: t,
45 comments: []parsedComment{},
46 }
47
48 comment := &parsedComment{}
49 parser.fn = parser.parseAuthor
50
51 for _, line := range strings.Split(env.out.String(), "\n") {
52 parser.fn(comment, line)
53 }
54
55 parser.comments = append(parser.comments, *comment)
56
57 return parser.comments
58}
59
60func (p *commentParser) parseAuthor(comment *parsedComment, line string) {
61 p.t.Helper()
62
63 tkns := strings.Split(line, ": ")
64 require.Len(p.t, tkns, 2)
65 require.Equal(p.t, "Author", tkns[0])
66
67 comment.author = tkns[1]
68 p.fn = p.parseID
69}
70
71func (p *commentParser) parseID(comment *parsedComment, line string) {
72 p.t.Helper()
73
74 tkns := strings.Split(line, ": ")
75 require.Len(p.t, tkns, 2)
76 require.Equal(p.t, "Id", tkns[0])
77
78 comment.id = tkns[1]
79 p.fn = p.parseDate
80}
81
82func (p *commentParser) parseDate(comment *parsedComment, line string) {
83 p.t.Helper()
84
85 tkns := strings.Split(line, ": ")
86 require.Len(p.t, tkns, 2)
87 require.Equal(p.t, "Date", tkns[0])
88
89 date, err := time.Parse(gitDateFormat, tkns[1])
90 require.NoError(p.t, err)
91
92 comment.date = date
93 p.fn = p.parseMessage
94}
95
96func (p *commentParser) parseMessage(comment *parsedComment, line string) {
97 p.t.Helper()
98
99 if strings.HasPrefix(line, "Author: ") {
100 p.comments = append(p.comments, *comment)
101 comment = &parsedComment{}
102 p.parseAuthor(comment, line)
103
104 return
105 }
106
107 require.True(p.t, line == "" || strings.HasPrefix(line, " "))
108
109 comment.message = strings.Join([]string{comment.message, line}, "\n")
110}
111
112func normalizeParsedComments(t *testing.T, comments []parsedComment) []parsedComment {
113 t.Helper()
114
115 prefix := 0x1234567
116 date, err := time.Parse(gitDateFormat, "Fri Aug 19 07:00:00 2022 +1900")
117 require.NoError(t, err)
118
119 out := []parsedComment{}
120
121 for i, comment := range comments {
122 comment.id = fmt.Sprintf("%7x", prefix+i)
123 comment.date = date.Add(time.Duration(i) * time.Minute)
124 out = append(out, comment)
125 }
126
127 return out
128}
129
130func requireCommentsEqual(t *testing.T, golden string, env *testEnv) {
131 t.Helper()
132
133 const goldenFilePatter = "%s-%d-golden.txt"
134
135 comments := parseComments(t, env)
136 comments = normalizeParsedComments(t, comments)
137
138 if *update {
139 t.Log("Got here")
140 for i, comment := range comments {
141 fileName := fmt.Sprintf(goldenFilePatter, golden, i)
142 require.NoError(t, ioutil.WriteFile(fileName, []byte(comment.message), 0644))
143 }
144 }
145
146 prefix := 0x1234567
147 date, err := time.Parse(gitDateFormat, "Fri Aug 19 07:00:00 2022 +1900")
148 require.NoError(t, err)
149
150 for i, comment := range comments {
151 require.Equal(t, "John Doe", comment.author)
152 require.Equal(t, fmt.Sprintf("%7x", prefix+i), comment.id)
153 require.Equal(t, date.Add(time.Duration(i)*time.Minute), comment.date)
154
155 fileName := fmt.Sprintf(goldenFilePatter, golden, i)
156 exp, err := ioutil.ReadFile(fileName)
157 require.NoError(t, err)
158 require.Equal(t, string(exp), comment.message)
159 }
160}