...

Source file src/internal/trace/v2/testdata/mktests.go

Documentation: internal/trace/v2/testdata

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"internal/trace/v2/raw"
    13  	"internal/trace/v2/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  		// Skip if we have a pattern and this test doesn't match.
    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  		// Get the test path.
    96  		testPath := filepath.Join(genroot, fmt.Sprintf("%s.test", name))
    97  
    98  		// Run generator.
    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  	// Skip if we have a pattern and this test doesn't match.
   114  	skip, err := ctx.register(name)
   115  	if err != nil {
   116  		return err
   117  	}
   118  	if skip {
   119  		return nil
   120  	}
   121  
   122  	// Create command.
   123  	var trace, stderr bytes.Buffer
   124  	cmd := exec.Command("go", "run", progPath)
   125  	// TODO(mknyszek): Remove if goexperiment.Exectracer2 becomes the default.
   126  	cmd.Env = append(os.Environ(), "GOEXPERIMENT=exectracer2")
   127  	cmd.Stdout = &trace
   128  	cmd.Stderr = &stderr
   129  
   130  	// Run trace program; the trace will appear in stdout.
   131  	fmt.Fprintf(os.Stderr, "running trace program %s...\n", name)
   132  	if err := cmd.Run(); err != nil {
   133  		log.Fatalf("running trace program: %v:\n%s", err, stderr.String())
   134  	}
   135  
   136  	// Write out the trace.
   137  	var textTrace bytes.Buffer
   138  	r, err := raw.NewReader(&trace)
   139  	if err != nil {
   140  		log.Fatalf("reading trace: %v", err)
   141  	}
   142  	w, err := raw.NewTextWriter(&textTrace, version.Current)
   143  	for {
   144  		ev, err := r.ReadEvent()
   145  		if err == io.EOF {
   146  			break
   147  		}
   148  		if err != nil {
   149  			log.Fatalf("reading trace: %v", err)
   150  		}
   151  		if err := w.WriteEvent(ev); err != nil {
   152  			log.Fatalf("writing trace: %v", err)
   153  		}
   154  	}
   155  	testData := txtar.Format(&txtar.Archive{
   156  		Files: []txtar.File{
   157  			{Name: "expect", Data: []byte("SUCCESS")},
   158  			{Name: "trace", Data: textTrace.Bytes()},
   159  		},
   160  	})
   161  	return os.WriteFile(fmt.Sprintf("./tests/%s.test", name), testData, 0o664)
   162  }
   163  

View as plain text