Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(295)

Side by Side Diff: logdog/client/annotee/annotation/annotation_test.go

Issue 2328023003: Fix Annotee stream name generation. (Closed)
Patch Set: Remove debugging junk. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package annotation 5 package annotation
6 6
7 import ( 7 import (
8 "bufio" 8 "bufio"
9 "flag" 9 "flag"
10 "fmt" 10 "fmt"
(...skipping 21 matching lines...) Expand all
32 32
33 var generate = flag.Bool("annotee.generate", false, "If true, regenerate expecta tions from source.") 33 var generate = flag.Bool("annotee.generate", false, "If true, regenerate expecta tions from source.")
34 34
35 type testCase struct { 35 type testCase struct {
36 name string 36 name string
37 exe *Execution 37 exe *Execution
38 } 38 }
39 39
40 func (tc *testCase) state(startTime time.Time) *State { 40 func (tc *testCase) state(startTime time.Time) *State {
41 cb := testCallbacks{ 41 cb := testCallbacks{
42 » » closed: map[string]struct{}{}, 42 » » closed: map[*Step]struct{}{},
43 logs: map[types.StreamName][]string{}, 43 logs: map[types.StreamName][]string{},
44 logsOpen: map[types.StreamName]struct{}{}, 44 logsOpen: map[types.StreamName]struct{}{},
45 } 45 }
46 return &State{ 46 return &State{
47 LogNameBase: types.StreamName("base"), 47 LogNameBase: types.StreamName("base"),
48 Callbacks: &cb, 48 Callbacks: &cb,
49 Clock: testclock.New(startTime), 49 Clock: testclock.New(startTime),
50 Execution: tc.exe, 50 Execution: tc.exe,
51 } 51 }
52 } 52 }
53 53
54 func (tc *testCase) generate(t *testing.T, startTime time.Time, touched stringse t.Set) error { 54 func (tc *testCase) generate(t *testing.T, startTime time.Time, touched stringse t.Set) error {
55 st := tc.state(startTime) 55 st := tc.state(startTime)
56 p, err := playAnnotationScript(t, tc.name, st) 56 p, err := playAnnotationScript(t, tc.name, st)
57 if err != nil { 57 if err != nil {
58 return err 58 return err
59 } 59 }
60 touched.Add(p) 60 touched.Add(p)
61 st.Finish() 61 st.Finish()
62 62
63 // Write out generated protos. 63 // Write out generated protos.
64 merr := errors.MultiError(nil) 64 merr := errors.MultiError(nil)
65 65
66 step := st.RootStep() 66 step := st.RootStep()
67 » p, err = writeStepProto(tc.name, step.CanonicalName(), step.Proto()) 67 » p, err = writeStepProto(tc.name, step)
68 if err != nil { 68 if err != nil {
69 » » merr = append(merr, fmt.Errorf("Failed to write step proto for % q::%q: %v", tc.name, step.CanonicalName(), err)) 69 » » merr = append(merr, fmt.Errorf("Failed to write step proto for % q::%q: %v", tc.name, step.LogNameBase, err))
70 } 70 }
71 touched.Add(p) 71 touched.Add(p)
72 72
73 // Write out generated logs. 73 // Write out generated logs.
74 cb := st.Callbacks.(*testCallbacks) 74 cb := st.Callbacks.(*testCallbacks)
75 for logName, lines := range cb.logs { 75 for logName, lines := range cb.logs {
76 p, err := writeLogText(tc.name, string(logName), lines) 76 p, err := writeLogText(tc.name, string(logName), lines)
77 if err != nil { 77 if err != nil {
78 merr = append(merr, fmt.Errorf("Failed to write log text for %q::%q: %v", tc.name, logName, err)) 78 merr = append(merr, fmt.Errorf("Failed to write log text for %q::%q: %v", tc.name, logName, err))
79 } 79 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } 164 }
165 } else if err != nil { 165 } else if err != nil {
166 return "", err 166 return "", err
167 } 167 }
168 } 168 }
169 } 169 }
170 170
171 return path, nil 171 return path, nil
172 } 172 }
173 173
174 func loadStepProto(t *testing.T, test, name string) *milo.Step { 174 func loadStepProto(t *testing.T, test string, s *Step) *milo.Step {
175 » path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.proto.txt", normali ze(test), normalize(name))) 175 » path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.proto.txt", normali ze(test), normalize(string(s.LogNameBase))))
176 data, err := ioutil.ReadFile(path) 176 data, err := ioutil.ReadFile(path)
177 if err != nil { 177 if err != nil {
178 t.Errorf("Failed to read milo.Step proto [%s]: %v", path, err) 178 t.Errorf("Failed to read milo.Step proto [%s]: %v", path, err)
179 return nil 179 return nil
180 } 180 }
181 181
182 st := milo.Step{} 182 st := milo.Step{}
183 if err := proto.UnmarshalText(string(data), &st); err != nil { 183 if err := proto.UnmarshalText(string(data), &st); err != nil {
184 t.Errorf("Failed to Unmarshal milo.Step proto [%s]: %v", path, e rr) 184 t.Errorf("Failed to Unmarshal milo.Step proto [%s]: %v", path, e rr)
185 return nil 185 return nil
186 } 186 }
187 return &st 187 return &st
188 } 188 }
189 189
190 func writeStepProto(test, name string, step *milo.Step) (string, error) { 190 func writeStepProto(test string, s *Step) (string, error) {
191 » path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.proto.txt", normali ze(test), normalize(name))) 191 » path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.proto.txt", normali ze(test), normalize(string(s.LogNameBase))))
192 » return path, ioutil.WriteFile(path, []byte(proto.MarshalTextString(step) ), 0644) 192 » return path, ioutil.WriteFile(path, []byte(proto.MarshalTextString(s.Pro to())), 0644)
193 } 193 }
194 194
195 func loadLogText(t *testing.T, test, name string) []string { 195 func loadLogText(t *testing.T, test, name string) []string {
196 path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.txt", normalize(tes t), normalize(name))) 196 path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.txt", normalize(tes t), normalize(name)))
197 f, err := os.Open(path) 197 f, err := os.Open(path)
198 if err != nil { 198 if err != nil {
199 t.Errorf("Failed to open log lines [%s]: %v", path, err) 199 t.Errorf("Failed to open log lines [%s]: %v", path, err)
200 return nil 200 return nil
201 } 201 }
202 defer f.Close() 202 defer f.Close()
203 203
204 lines := []string(nil) 204 lines := []string(nil)
205 scanner := bufio.NewScanner(f) 205 scanner := bufio.NewScanner(f)
206 for scanner.Scan() { 206 for scanner.Scan() {
207 lines = append(lines, scanner.Text()) 207 lines = append(lines, scanner.Text())
208 } 208 }
209 return lines 209 return lines
210 } 210 }
211 211
212 func writeLogText(test, name string, text []string) (string, error) { 212 func writeLogText(test, name string, text []string) (string, error) {
213 path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.txt", normalize(tes t), normalize(name))) 213 path := filepath.Join(testExpDir, fmt.Sprintf("%s_%s.txt", normalize(tes t), normalize(name)))
214 return path, ioutil.WriteFile(path, []byte(strings.Join(text, "\n")), 06 44) 214 return path, ioutil.WriteFile(path, []byte(strings.Join(text, "\n")), 06 44)
215 } 215 }
216 216
217 // testCallbacks implements the Callbacks interface, retaining all callback 217 // testCallbacks implements the Callbacks interface, retaining all callback
218 // data in memory. 218 // data in memory.
219 type testCallbacks struct { 219 type testCallbacks struct {
220 » // closed is the set of steps that have been closed, keyed on step 220 » // closed is the set of steps that have been closed.
221 » // CanonicalName. 221 » closed map[*Step]struct{}
222 » closed map[string]struct{}
223 222
224 // logs is the content of emitted annotation logs, keyed on stream name. 223 // logs is the content of emitted annotation logs, keyed on stream name.
225 logs map[types.StreamName][]string 224 logs map[types.StreamName][]string
226 // logsOpen tracks whether a given annotation log is open. 225 // logsOpen tracks whether a given annotation log is open.
227 logsOpen map[types.StreamName]struct{} 226 logsOpen map[types.StreamName]struct{}
228 } 227 }
229 228
230 func (tc *testCallbacks) StepClosed(s *Step) { 229 func (tc *testCallbacks) StepClosed(s *Step) {
231 » tc.closed[s.CanonicalName()] = struct{}{} 230 » tc.closed[s] = struct{}{}
232 } 231 }
233 232
234 func (tc *testCallbacks) StepLogLine(s *Step, n types.StreamName, label, line st ring) { 233 func (tc *testCallbacks) StepLogLine(s *Step, n types.StreamName, label, line st ring) {
235 if _, ok := tc.logs[n]; ok { 234 if _, ok := tc.logs[n]; ok {
236 // The log exists. Assert that it is open. 235 // The log exists. Assert that it is open.
237 if _, ok := tc.logsOpen[n]; !ok { 236 if _, ok := tc.logsOpen[n]; !ok {
238 panic(fmt.Errorf("write to closed log stream: %q", n)) 237 panic(fmt.Errorf("write to closed log stream: %q", n))
239 } 238 }
240 } 239 }
241 240
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 // All log streams should be closed. 309 // All log streams should be closed.
311 cb := st.Callbacks.(*testCallbacks) 310 cb := st.Callbacks.(*testCallbacks)
312 So(cb.logsOpen, ShouldResemble, map[types.Stream Name]struct{}{}) 311 So(cb.logsOpen, ShouldResemble, map[types.Stream Name]struct{}{})
313 312
314 // Iterate over each generated stream and assert that it matches its 313 // Iterate over each generated stream and assert that it matches its
315 // expectation. Do it deterministically so failu res aren't frustrating 314 // expectation. Do it deterministically so failu res aren't frustrating
316 // to reproduce. 315 // to reproduce.
317 Convey(`Has correct Step value`, func() { 316 Convey(`Has correct Step value`, func() {
318 rootStep := st.RootStep() 317 rootStep := st.RootStep()
319 318
320 » » » » » exp := loadStepProto(t, testCase.name, r ootStep.CanonicalName()) 319 » » » » » exp := loadStepProto(t, testCase.name, r ootStep)
321 So(rootStep.Proto(), ShouldResemble, exp ) 320 So(rootStep.Proto(), ShouldResemble, exp )
322 }) 321 })
323 322
324 // Iterate over each generated log and assert th at it matches its 323 // Iterate over each generated log and assert th at it matches its
325 // expectations. 324 // expectations.
326 logs := make([]string, 0, len(cb.logs)) 325 logs := make([]string, 0, len(cb.logs))
327 for k := range cb.logs { 326 for k := range cb.logs {
328 logs = append(logs, string(k)) 327 logs = append(logs, string(k))
329 } 328 }
330 sort.Strings(logs) 329 sort.Strings(logs)
331 for _, logName := range logs { 330 for _, logName := range logs {
332 log := cb.logs[types.StreamName(logName) ] 331 log := cb.logs[types.StreamName(logName) ]
333 exp := loadLogText(t, testCase.name, log Name) 332 exp := loadLogText(t, testCase.name, log Name)
334 So(log, ShouldResemble, exp) 333 So(log, ShouldResemble, exp)
335 } 334 }
336 }) 335 })
337 } 336 }
338 337
339 Convey(`Append to a closed State is a no-op.`, func() { 338 Convey(`Append to a closed State is a no-op.`, func() {
340 st := testCases[0].state(startTime) 339 st := testCases[0].state(startTime)
341 st.Finish() 340 st.Finish()
342 sclone := st 341 sclone := st
343 So(st.Append("asdf"), ShouldBeNil) 342 So(st.Append("asdf"), ShouldBeNil)
344 So(st, ShouldResemble, sclone) 343 So(st, ShouldResemble, sclone)
345 }) 344 })
346 }) 345 })
347 } 346 }
OLDNEW
« no previous file with comments | « logdog/client/annotee/annotation/annotation.go ('k') | logdog/client/annotee/annotation/test_data/coverage.annotations.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698