1
2
3
4
5
6
7 package main
8
9 import (
10 "bytes"
11 "fmt"
12 "internal/trace/raw"
13 "internal/trace/version"
14 "internal/txtar"
15 "io"
16 "log"
17 "os"
18 "os/exec"
19 "path/filepath"
20 "regexp"
21 )
22
23 func main() {
24 log.SetFlags(0)
25 ctx, err := newContext()
26 if err != nil {
27 log.Fatal(err)
28 }
29 if err := ctx.runGenerators(); err != nil {
30 log.Fatal(err)
31 }
32 if err := ctx.runTestProg("./testprog/annotations.go"); err != nil {
33 log.Fatal(err)
34 }
35 if err := ctx.runTestProg("./testprog/annotations-stress.go"); err != nil {
36 log.Fatal(err)
37 }
38 }
39
40 type context struct {
41 testNames map[string]struct{}
42 filter *regexp.Regexp
43 }
44
45 func newContext() (*context, error) {
46 var filter *regexp.Regexp
47 var err error
48 if pattern := os.Getenv("GOTRACETEST"); pattern != "" {
49 filter, err = regexp.Compile(pattern)
50 if err != nil {
51 return nil, fmt.Errorf("compiling regexp %q for GOTRACETEST: %v", pattern, err)
52 }
53 }
54 return &context{
55 testNames: make(map[string]struct{}),
56 filter: filter,
57 }, nil
58 }
59
60 func (ctx *context) register(testName string) (skip bool, err error) {
61 if _, ok := ctx.testNames[testName]; ok {
62 return true, fmt.Errorf("duplicate test %s found", testName)
63 }
64 if ctx.filter != nil {
65 return !ctx.filter.MatchString(testName), nil
66 }
67 return false, nil
68 }
69
70 func (ctx *context) runGenerators() error {
71 generators, err := filepath.Glob("./generators/*.go")
72 if err != nil {
73 return fmt.Errorf("reading generators: %v", err)
74 }
75 genroot := "./tests"
76
77 if err := os.MkdirAll(genroot, 0777); err != nil {
78 return fmt.Errorf("creating generated root: %v", err)
79 }
80 for _, path := range generators {
81 name := filepath.Base(path)
82 name = name[:len(name)-len(filepath.Ext(name))]
83
84
85 skip, err := ctx.register(name)
86 if err != nil {
87 return err
88 }
89 if skip {
90 continue
91 }
92
93 fmt.Fprintf(os.Stderr, "generating %s... ", name)
94
95
96 testPath := filepath.Join(genroot, fmt.Sprintf("%s.test", name))
97
98
99 cmd := exec.Command("go", "run", path, testPath)
100 if out, err := cmd.CombinedOutput(); err != nil {
101 return fmt.Errorf("running generator %s: %v:\n%s", name, err, out)
102 }
103 fmt.Fprintln(os.Stderr)
104 }
105 return nil
106 }
107
108 func (ctx *context) runTestProg(progPath string) error {
109 name := filepath.Base(progPath)
110 name = name[:len(name)-len(filepath.Ext(name))]
111 name = fmt.Sprintf("go1%d-%s", version.Current, name)
112
113
114 skip, err := ctx.register(name)
115 if err != nil {
116 return err
117 }
118 if skip {
119 return nil
120 }
121
122
123 var trace, stderr bytes.Buffer
124 cmd := exec.Command("go", "run", progPath)
125 cmd.Stdout = &trace
126 cmd.Stderr = &stderr
127
128
129 fmt.Fprintf(os.Stderr, "running trace program %s...\n", name)
130 if err := cmd.Run(); err != nil {
131 log.Fatalf("running trace program: %v:\n%s", err, stderr.String())
132 }
133
134
135 var textTrace bytes.Buffer
136 r, err := raw.NewReader(&trace)
137 if err != nil {
138 log.Fatalf("reading trace: %v", err)
139 }
140 w, err := raw.NewTextWriter(&textTrace, version.Current)
141 for {
142 ev, err := r.ReadEvent()
143 if err == io.EOF {
144 break
145 }
146 if err != nil {
147 log.Fatalf("reading trace: %v", err)
148 }
149 if err := w.WriteEvent(ev); err != nil {
150 log.Fatalf("writing trace: %v", err)
151 }
152 }
153 testData := txtar.Format(&txtar.Archive{
154 Files: []txtar.File{
155 {Name: "expect", Data: []byte("SUCCESS")},
156 {Name: "trace", Data: textTrace.Bytes()},
157 },
158 })
159 return os.WriteFile(fmt.Sprintf("./tests/%s.test", name), testData, 0o664)
160 }
161
View as plain text