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