mvdan.cc/goreduce@v0.0.0-20240319135341-50b0d7f2497f/reduce_test.go (about)

     1  // Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
     2  // See LICENSE for licensing information
     3  
     4  package main
     5  
     6  import (
     7  	"bytes"
     8  	"flag"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  var (
    17  	write = flag.Bool("w", false, "write test outputs")
    18  	fast  = flag.Bool("f", false, "skip work to make tests faster")
    19  )
    20  
    21  func TestMain(m *testing.M) {
    22  	flag.Parse()
    23  	fastTest = *fast
    24  	os.Exit(m.Run())
    25  }
    26  
    27  func TestReductions(t *testing.T) {
    28  	paths, err := filepath.Glob(filepath.Join("testdata", "*"))
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  	*verbose = true
    33  	for _, path := range paths {
    34  		name := filepath.Base(path)
    35  		t.Run(name, testReduction(name))
    36  	}
    37  }
    38  
    39  func readFile(t testing.TB, dir, path string) string {
    40  	bs, err := ioutil.ReadFile(filepath.Join(dir, path))
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	return string(bs)
    45  }
    46  
    47  func writeFile(t testing.TB, dir, path, cont string) {
    48  	err := ioutil.WriteFile(filepath.Join(dir, path), []byte(cont), 0644)
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  }
    53  
    54  func testReduction(name string) func(*testing.T) {
    55  	return func(t *testing.T) {
    56  		t.Parallel()
    57  		dir := filepath.Join("testdata", name)
    58  		orig := []byte(readFile(t, dir, "src.go"))
    59  		defer ioutil.WriteFile(filepath.Join(dir, "src.go"), orig, 0644)
    60  		want := readFile(t, dir, "src.go.min")
    61  		match := strings.TrimRight(readFile(t, dir, "match"), "\n")
    62  		impPath := "./testdata/" + name
    63  		var buf bytes.Buffer
    64  		if err := reduce(impPath, match, &buf, ""); err != nil {
    65  			t.Fatal(err)
    66  		}
    67  		got := readFile(t, dir, "src.go")
    68  		if want != got {
    69  			if *write {
    70  				writeFile(t, dir, "src.go.min", got)
    71  			} else {
    72  				t.Fatalf("unexpected program output\nwant:\n%sgot:\n%s",
    73  					want, got)
    74  			}
    75  		}
    76  		// remove testdata/<dir>/ bit
    77  		rawLog := buf.String()
    78  		buf.Reset()
    79  		for _, line := range strings.Split(rawLog, "\n") {
    80  			if line == "" {
    81  				break
    82  			}
    83  			line = strings.TrimPrefix(line, dir+string(filepath.Separator))
    84  			buf.WriteString(line)
    85  			buf.WriteByte('\n')
    86  		}
    87  		gotLog := buf.String()
    88  		wantLog := readFile(t, dir, "log")
    89  		if wantLog != gotLog {
    90  			if *write {
    91  				writeFile(t, dir, "log", gotLog)
    92  			} else {
    93  				t.Fatalf("unexpected log output\nwant:\n%sgot:\n%s",
    94  					wantLog, gotLog)
    95  			}
    96  		}
    97  	}
    98  }
    99  
   100  func BenchmarkReduce(b *testing.B) {
   101  	dir, err := ioutil.TempDir("", "goreduce")
   102  	if err != nil {
   103  		b.Fatal(err)
   104  	}
   105  	defer os.RemoveAll(dir)
   106  	if err := os.Chdir(dir); err != nil {
   107  		b.Fatal(err)
   108  	}
   109  	orig := []byte(`package crasher
   110  
   111  import "sync"
   112  
   113  func Crasher() {
   114  	var a []int
   115  	_ = sync.Once{}
   116  	println(a[0])
   117  }`)
   118  	for i := 0; i < b.N; i++ {
   119  		if err := ioutil.WriteFile("src.go", orig, 0644); err != nil {
   120  			b.Fatal(err)
   121  		}
   122  		err := reduce(".", "index out of range", ioutil.Discard, "")
   123  		if err != nil {
   124  			b.Fatal(err)
   125  		}
   126  	}
   127  }
   128  
   129  func TestReduceErrs(t *testing.T) {
   130  	t.Parallel()
   131  	fastTest = false
   132  	defer func() { fastTest = *fast }()
   133  	tests := [...]struct {
   134  		dir, match string
   135  		errCont    string
   136  	}{
   137  		{"missing-dir", "[", "missing closing ]"},
   138  		{"missing-dir", ".", "no such file"},
   139  		{"testdata/remove-stmt", "no-match", "does not match"},
   140  	}
   141  	for _, tc := range tests {
   142  		err := reduce(tc.dir, tc.match, ioutil.Discard, "")
   143  		if err == nil || !strings.Contains(err.Error(), tc.errCont) {
   144  			t.Fatalf("wanted error conatining %q, got: %v",
   145  				tc.errCont, err)
   146  		}
   147  	}
   148  }