golang.org/x/tools@v0.21.0/cmd/bisect/main_test.go (about)

     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  package main
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/json"
    10  	"flag"
    11  	"fmt"
    12  	"go/build/constraint"
    13  	"math/rand"
    14  	"os"
    15  	"path/filepath"
    16  	"strings"
    17  	"testing"
    18  
    19  	"golang.org/x/tools/internal/bisect"
    20  	"golang.org/x/tools/internal/diffp"
    21  	"golang.org/x/tools/txtar"
    22  )
    23  
    24  var update = flag.Bool("update", false, "update testdata with new stdout/stderr")
    25  
    26  func Test(t *testing.T) {
    27  	files, err := filepath.Glob("testdata/*.txt")
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  	for _, file := range files {
    32  		t.Run(strings.TrimSuffix(filepath.Base(file), ".txt"), func(t *testing.T) {
    33  			data, err := os.ReadFile(file)
    34  			if err != nil {
    35  				t.Fatal(err)
    36  			}
    37  			a := txtar.Parse(data)
    38  			var wantStdout, wantStderr []byte
    39  			files := a.Files
    40  			if len(files) > 0 && files[0].Name == "stdout" {
    41  				wantStdout = files[0].Data
    42  				files = files[1:]
    43  			}
    44  			if len(files) > 0 && files[0].Name == "stderr" {
    45  				wantStderr = files[0].Data
    46  				files = files[1:]
    47  			}
    48  			if len(files) > 0 {
    49  				t.Fatalf("unexpected txtar entry: %s", files[0].Name)
    50  			}
    51  
    52  			var tt struct {
    53  				Fail   string
    54  				Bisect Bisect
    55  			}
    56  			if err := json.Unmarshal(a.Comment, &tt); err != nil {
    57  				t.Fatal(err)
    58  			}
    59  
    60  			expr, err := constraint.Parse("//go:build " + tt.Fail)
    61  			if err != nil {
    62  				t.Fatalf("invalid Cmd: %v", err)
    63  			}
    64  
    65  			rnd := rand.New(rand.NewSource(1))
    66  			b := &tt.Bisect
    67  			b.Cmd = "test"
    68  			b.Args = []string{"PATTERN"}
    69  			var stdout, stderr bytes.Buffer
    70  			b.Stdout = &stdout
    71  			b.Stderr = &stderr
    72  			b.TestRun = func(env []string, cmd string, args []string) (out []byte, err error) {
    73  				pattern := args[0]
    74  				m, err := bisect.New(pattern)
    75  				if err != nil {
    76  					t.Fatal(err)
    77  				}
    78  				have := make(map[string]bool)
    79  				for i, color := range colors {
    80  					if m.ShouldEnable(uint64(i)) {
    81  						have[color] = true
    82  					}
    83  					if m.ShouldReport(uint64(i)) {
    84  						out = fmt.Appendf(out, "%s %s\n", color, bisect.Marker(uint64(i)))
    85  					}
    86  				}
    87  				err = nil
    88  				if eval(rnd, expr, have) {
    89  					err = fmt.Errorf("failed")
    90  				}
    91  				return out, err
    92  			}
    93  
    94  			if !b.Search() {
    95  				stderr.WriteString("<bisect failed>\n")
    96  			}
    97  			rewrite := false
    98  			if !bytes.Equal(stdout.Bytes(), wantStdout) {
    99  				if *update {
   100  					rewrite = true
   101  				} else {
   102  					t.Errorf("incorrect stdout: %s", diffp.Diff("have", stdout.Bytes(), "want", wantStdout))
   103  				}
   104  			}
   105  			if !bytes.Equal(stderr.Bytes(), wantStderr) {
   106  				if *update {
   107  					rewrite = true
   108  				} else {
   109  					t.Errorf("incorrect stderr: %s", diffp.Diff("have", stderr.Bytes(), "want", wantStderr))
   110  				}
   111  			}
   112  			if rewrite {
   113  				a.Files = []txtar.File{{Name: "stdout", Data: stdout.Bytes()}, {Name: "stderr", Data: stderr.Bytes()}}
   114  				err := os.WriteFile(file, txtar.Format(a), 0666)
   115  				if err != nil {
   116  					t.Fatal(err)
   117  				}
   118  				t.Logf("updated %s", file)
   119  			}
   120  		})
   121  	}
   122  }
   123  
   124  func eval(rnd *rand.Rand, z constraint.Expr, have map[string]bool) bool {
   125  	switch z := z.(type) {
   126  	default:
   127  		panic(fmt.Sprintf("unexpected type %T", z))
   128  	case *constraint.NotExpr:
   129  		return !eval(rnd, z.X, have)
   130  	case *constraint.AndExpr:
   131  		return eval(rnd, z.X, have) && eval(rnd, z.Y, have)
   132  	case *constraint.OrExpr:
   133  		return eval(rnd, z.X, have) || eval(rnd, z.Y, have)
   134  	case *constraint.TagExpr:
   135  		if z.Tag == "random" {
   136  			return rnd.Intn(2) == 1
   137  		}
   138  		return have[z.Tag]
   139  	}
   140  }
   141  
   142  var colors = strings.Fields(`
   143  	aliceblue
   144  	amaranth
   145  	amber
   146  	amethyst
   147  	applegreen
   148  	applered
   149  	apricot
   150  	aquamarine
   151  	azure
   152  	babyblue
   153  	beige
   154  	brickred
   155  	black
   156  	blue
   157  	bluegreen
   158  	blueviolet
   159  	blush
   160  	bronze
   161  	brown
   162  	burgundy
   163  	byzantium
   164  	carmine
   165  	cerise
   166  	cerulean
   167  	champagne
   168  	chartreusegreen
   169  	chocolate
   170  	cobaltblue
   171  	coffee
   172  	copper
   173  	coral
   174  	crimson
   175  	cyan
   176  	desertsand
   177  	electricblue
   178  	emerald
   179  	erin
   180  	gold
   181  	gray
   182  	green
   183  	harlequin
   184  	indigo
   185  	ivory
   186  	jade
   187  	junglegreen
   188  	lavender
   189  	lemon
   190  	lilac
   191  	lime
   192  	magenta
   193  	magentarose
   194  	maroon
   195  	mauve
   196  	navyblue
   197  	ochre
   198  	olive
   199  	orange
   200  	orangered
   201  	orchid
   202  	peach
   203  	pear
   204  	periwinkle
   205  	persianblue
   206  	pink
   207  	plum
   208  	prussianblue
   209  	puce
   210  	purple
   211  	raspberry
   212  	red
   213  	redviolet
   214  	rose
   215  	ruby
   216  	salmon
   217  	sangria
   218  	sapphire
   219  	scarlet
   220  	silver
   221  	slategray
   222  	springbud
   223  	springgreen
   224  	tan
   225  	taupe
   226  	teal
   227  	turquoise
   228  	ultramarine
   229  	violet
   230  	viridian
   231  	white
   232  	yellow
   233  `)