| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:build ignore |
| |
| package main |
| |
| import ( |
| "bytes" |
| "fmt" |
| "internal/trace/v2/raw" |
| "internal/trace/v2/version" |
| "internal/txtar" |
| "io" |
| "log" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "regexp" |
| ) |
| |
| func main() { |
| log.SetFlags(0) |
| ctx, err := newContext() |
| if err != nil { |
| log.Fatal(err) |
| } |
| if err := ctx.runGenerators(); err != nil { |
| log.Fatal(err) |
| } |
| if err := ctx.runTestProg("./testprog/annotations.go"); err != nil { |
| log.Fatal(err) |
| } |
| if err := ctx.runTestProg("./testprog/annotations-stress.go"); err != nil { |
| log.Fatal(err) |
| } |
| } |
| |
| type context struct { |
| testNames map[string]struct{} |
| filter *regexp.Regexp |
| } |
| |
| func newContext() (*context, error) { |
| var filter *regexp.Regexp |
| var err error |
| if pattern := os.Getenv("GOTRACETEST"); pattern != "" { |
| filter, err = regexp.Compile(pattern) |
| if err != nil { |
| return nil, fmt.Errorf("compiling regexp %q for GOTRACETEST: %v", pattern, err) |
| } |
| } |
| return &context{ |
| testNames: make(map[string]struct{}), |
| filter: filter, |
| }, nil |
| } |
| |
| func (ctx *context) register(testName string) (skip bool, err error) { |
| if _, ok := ctx.testNames[testName]; ok { |
| return true, fmt.Errorf("duplicate test %s found", testName) |
| } |
| if ctx.filter != nil { |
| return !ctx.filter.MatchString(testName), nil |
| } |
| return false, nil |
| } |
| |
| func (ctx *context) runGenerators() error { |
| generators, err := filepath.Glob("./generators/*.go") |
| if err != nil { |
| return fmt.Errorf("reading generators: %v", err) |
| } |
| genroot := "./tests" |
| |
| if err := os.MkdirAll(genroot, 0777); err != nil { |
| return fmt.Errorf("creating generated root: %v", err) |
| } |
| for _, path := range generators { |
| name := filepath.Base(path) |
| name = name[:len(name)-len(filepath.Ext(name))] |
| |
| // Skip if we have a pattern and this test doesn't match. |
| skip, err := ctx.register(name) |
| if err != nil { |
| return err |
| } |
| if skip { |
| continue |
| } |
| |
| fmt.Fprintf(os.Stderr, "generating %s... ", name) |
| |
| // Get the test path. |
| testPath := filepath.Join(genroot, fmt.Sprintf("%s.test", name)) |
| |
| // Run generator. |
| cmd := exec.Command("go", "run", path, testPath) |
| if out, err := cmd.CombinedOutput(); err != nil { |
| return fmt.Errorf("running generator %s: %v:\n%s", name, err, out) |
| } |
| fmt.Fprintln(os.Stderr) |
| } |
| return nil |
| } |
| |
| func (ctx *context) runTestProg(progPath string) error { |
| name := filepath.Base(progPath) |
| name = name[:len(name)-len(filepath.Ext(name))] |
| name = fmt.Sprintf("go1%d-%s", version.Current, name) |
| |
| // Skip if we have a pattern and this test doesn't match. |
| skip, err := ctx.register(name) |
| if err != nil { |
| return err |
| } |
| if skip { |
| return nil |
| } |
| |
| // Create command. |
| var trace, stderr bytes.Buffer |
| cmd := exec.Command("go", "run", progPath) |
| cmd.Stdout = &trace |
| cmd.Stderr = &stderr |
| |
| // Run trace program; the trace will appear in stdout. |
| fmt.Fprintf(os.Stderr, "running trace program %s...\n", name) |
| if err := cmd.Run(); err != nil { |
| log.Fatalf("running trace program: %v:\n%s", err, stderr.String()) |
| } |
| |
| // Write out the trace. |
| var textTrace bytes.Buffer |
| r, err := raw.NewReader(&trace) |
| if err != nil { |
| log.Fatalf("reading trace: %v", err) |
| } |
| w, err := raw.NewTextWriter(&textTrace, version.Current) |
| for { |
| ev, err := r.ReadEvent() |
| if err == io.EOF { |
| break |
| } |
| if err != nil { |
| log.Fatalf("reading trace: %v", err) |
| } |
| if err := w.WriteEvent(ev); err != nil { |
| log.Fatalf("writing trace: %v", err) |
| } |
| } |
| testData := txtar.Format(&txtar.Archive{ |
| Files: []txtar.File{ |
| {Name: "expect", Data: []byte("SUCCESS")}, |
| {Name: "trace", Data: textTrace.Bytes()}, |
| }, |
| }) |
| return os.WriteFile(fmt.Sprintf("./tests/%s.test", name), testData, 0o664) |
| } |