-
Notifications
You must be signed in to change notification settings - Fork 4
/
zbtest.go
136 lines (111 loc) · 2.86 KB
/
zbtest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package zbtest
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
"jrubin.io/zb/lib/buildflags"
"jrubin.io/zb/lib/project"
"jrubin.io/zb/lib/zbcontext"
)
// ZBTest provides methods for working with cached test result files
type ZBTest struct {
buildflags.TestFlagsData
Force bool
}
func (t *ZBTest) TestSetup(ctx zbcontext.Context) zbcontext.Context {
if filepath.Base(ctx.CacheDir) != "test" {
ctx.CacheDir = filepath.Join(ctx.CacheDir, "test")
}
ctx.BuildArger = &t.TestFlagsData
ctx.BuildContext = t.TestFlagsData.BuildContext()
return ctx
}
var endRE = regexp.MustCompile(`\A(\?|ok|FAIL) {0,3}\t([^ \t]+)[ \t]([0-9.]+s|\[.*\])\n\z`)
// CacheFile returns the location of the test cache file for a given package
func (t *ZBTest) CacheFile(ctx zbcontext.Context, p *project.Package) (string, error) {
testHash, err := p.TestHash(ctx, &t.TestFlagsData)
if err != nil {
return "", err
}
return filepath.Join(
ctx.CacheDir,
testHash[:3],
fmt.Sprintf("%s.test", testHash[3:]),
), nil
}
// HaveResult checks to see if a test result is available for a given package
func (t *ZBTest) HaveResult(ctx zbcontext.Context, p *project.Package) (bool, error) {
if t.Force {
return false, nil
}
file, err := t.CacheFile(ctx, p)
if err != nil {
return false, err
}
fi, err := os.Stat(file)
return err == nil && fi.Mode().IsRegular(), nil
}
// StringReader is satisfied by bufio.Reader
type StringReader interface {
io.Reader
ReadString(byte) (string, error)
}
// ReadResult from the StringReader and write it to the CacheFile for the
// given package
func (t *ZBTest) ReadResult(ctx zbcontext.Context, r StringReader, p *project.Package) error {
file, err := t.CacheFile(ctx, p)
if err != nil {
return err
}
var buf bytes.Buffer
for eof := false; !eof; {
line, err := r.ReadString('\n')
if err == io.EOF {
eof = true
} else if err != nil {
return err
}
m := endRE.FindStringSubmatch(line)
if m == nil {
if _, err := buf.WriteString(line); err != nil {
return err
}
continue
}
fmt.Fprintf(&buf, "%s (cached)\n", strings.TrimSuffix(line, "\n"))
if err := os.MkdirAll(filepath.Dir(file), 0700); err != nil {
return err
}
if err := ioutil.WriteFile(file, buf.Bytes(), 0600); err != nil {
return err
}
break
}
return nil
}
// ShowResult reads the CacheFile for the given package and writes it to the
// Writer
func (t *ZBTest) ShowResult(ctx zbcontext.Context, w io.Writer, p *project.Package) (bool, error) {
file, err := t.CacheFile(ctx, p)
if err != nil {
return false, err
}
data, err := ioutil.ReadFile(file)
if err != nil {
return false, err
}
check := bytes.TrimSpace(data)
i := bytes.LastIndex(check, []byte{'\n'})
line := check[i+1:]
if bytes.HasPrefix(line, []byte("FAIL")) {
_, err = w.Write(data)
return false, err
}
_, err = w.Write(data)
return true, err
}