1package check 2 3import ( 4 "fmt" 5 "io" 6 "sync" 7) 8 9// ----------------------------------------------------------------------- 10// Output writer manages atomic output writing according to settings. 11 12type outputWriter struct { 13 m sync.Mutex 14 writer io.Writer 15 wroteCallProblemLast bool 16 Stream bool 17 Verbose bool 18} 19 20func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { 21 return &outputWriter{writer: writer, Stream: stream, Verbose: verbose} 22} 23 24func (ow *outputWriter) Write(content []byte) (n int, err error) { 25 ow.m.Lock() 26 n, err = ow.writer.Write(content) 27 ow.m.Unlock() 28 return 29} 30 31func (ow *outputWriter) WriteCallStarted(label string, c *C) { 32 if ow.Stream { 33 header := renderCallHeader(label, c, "", "\n") 34 ow.m.Lock() 35 ow.writer.Write([]byte(header)) 36 ow.m.Unlock() 37 } 38} 39 40func (ow *outputWriter) WriteCallProblem(label string, c *C) { 41 var prefix string 42 if !ow.Stream { 43 prefix = "\n-----------------------------------" + 44 "-----------------------------------\n" 45 } 46 header := renderCallHeader(label, c, prefix, "\n\n") 47 ow.m.Lock() 48 ow.wroteCallProblemLast = true 49 ow.writer.Write([]byte(header)) 50 if !ow.Stream { 51 c.logb.WriteTo(ow.writer) 52 } 53 ow.m.Unlock() 54} 55 56func (ow *outputWriter) WriteCallSuccess(label string, c *C) { 57 if ow.Stream || (ow.Verbose && c.kind == testKd) { 58 // TODO Use a buffer here. 59 var suffix string 60 if c.reason != "" { 61 suffix = " (" + c.reason + ")" 62 } 63 if c.status() == succeededSt { 64 suffix += "\t" + c.timerString() 65 } 66 suffix += "\n" 67 if ow.Stream { 68 suffix += "\n" 69 } 70 header := renderCallHeader(label, c, "", suffix) 71 ow.m.Lock() 72 // Resist temptation of using line as prefix above due to race. 73 if !ow.Stream && ow.wroteCallProblemLast { 74 header = "\n-----------------------------------" + 75 "-----------------------------------\n" + 76 header 77 } 78 ow.wroteCallProblemLast = false 79 ow.writer.Write([]byte(header)) 80 ow.m.Unlock() 81 } 82} 83 84func renderCallHeader(label string, c *C, prefix, suffix string) string { 85 pc := c.method.PC() 86 return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc), 87 niceFuncName(pc), suffix) 88} 89