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 }