1
2
3
4
5 package main
6
7 import (
8 "os"
9 "os/exec"
10 "path/filepath"
11 "strings"
12 "sync"
13 "testing"
14
15 "golang.org/x/tools/internal/testenv"
16 )
17
18 func TestMain(m *testing.M) {
19 if os.Getenv("GO_FILE2FUZZ_TEST_IS_FILE2FUZZ") != "" {
20 main()
21 os.Exit(0)
22 }
23
24 os.Exit(m.Run())
25 }
26
27 var f2f struct {
28 once sync.Once
29 path string
30 err error
31 }
32
33 func file2fuzz(t *testing.T, dir string, args []string, stdin string) (string, bool) {
34 testenv.NeedsExec(t)
35
36 f2f.once.Do(func() {
37 f2f.path, f2f.err = os.Executable()
38 })
39 if f2f.err != nil {
40 t.Fatal(f2f.err)
41 }
42
43 cmd := exec.Command(f2f.path, args...)
44 cmd.Dir = dir
45 cmd.Env = append(os.Environ(), "PWD="+dir, "GO_FILE2FUZZ_TEST_IS_FILE2FUZZ=1")
46 if stdin != "" {
47 cmd.Stdin = strings.NewReader(stdin)
48 }
49 out, err := cmd.CombinedOutput()
50 if err != nil {
51 return string(out), true
52 }
53 return string(out), false
54 }
55
56 func TestFile2Fuzz(t *testing.T) {
57 type file struct {
58 name string
59 dir bool
60 content string
61 }
62 tests := []struct {
63 name string
64 args []string
65 stdin string
66 inputFiles []file
67 expectedStdout string
68 expectedFiles []file
69 expectedError string
70 }{
71 {
72 name: "stdin, stdout",
73 stdin: "hello",
74 expectedStdout: "go test fuzz v1\n[]byte(\"hello\")",
75 },
76 {
77 name: "stdin, output file",
78 stdin: "hello",
79 args: []string{"-o", "output"},
80 expectedFiles: []file{{name: "output", content: "go test fuzz v1\n[]byte(\"hello\")"}},
81 },
82 {
83 name: "stdin, output directory",
84 stdin: "hello",
85 args: []string{"-o", "output"},
86 inputFiles: []file{{name: "output", dir: true}},
87 expectedFiles: []file{{name: "output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b", content: "go test fuzz v1\n[]byte(\"hello\")"}},
88 },
89 {
90 name: "input file, output file",
91 args: []string{"-o", "output", "input"},
92 inputFiles: []file{{name: "input", content: "hello"}},
93 expectedFiles: []file{{name: "output", content: "go test fuzz v1\n[]byte(\"hello\")"}},
94 },
95 {
96 name: "input file, output directory",
97 args: []string{"-o", "output", "input"},
98 inputFiles: []file{{name: "output", dir: true}, {name: "input", content: "hello"}},
99 expectedFiles: []file{{name: "output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b", content: "go test fuzz v1\n[]byte(\"hello\")"}},
100 },
101 {
102 name: "input files, output directory",
103 args: []string{"-o", "output", "input", "input-2"},
104 inputFiles: []file{{name: "output", dir: true}, {name: "input", content: "hello"}, {name: "input-2", content: "hello :)"}},
105 expectedFiles: []file{
106 {name: "output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b", content: "go test fuzz v1\n[]byte(\"hello\")"},
107 {name: "output/28059db30ce420ff65b2c29b749804c69c601aeca21b3cbf0644244ff080d7a5", content: "go test fuzz v1\n[]byte(\"hello :)\")"},
108 },
109 },
110 {
111 name: "input files, no output",
112 args: []string{"input", "input-2"},
113 inputFiles: []file{{name: "output", dir: true}, {name: "input", content: "hello"}, {name: "input-2", content: "hello :)"}},
114 expectedError: "file2fuzz: -o required with multiple input files\n",
115 },
116 }
117
118 for _, tc := range tests {
119 t.Run(tc.name, func(t *testing.T) {
120 tmp, err := os.MkdirTemp(os.TempDir(), "file2fuzz")
121 if err != nil {
122 t.Fatalf("os.MkdirTemp failed: %s", err)
123 }
124 defer os.RemoveAll(tmp)
125 for _, f := range tc.inputFiles {
126 if f.dir {
127 if err := os.Mkdir(filepath.Join(tmp, f.name), 0777); err != nil {
128 t.Fatalf("failed to create test directory: %s", err)
129 }
130 } else {
131 if err := os.WriteFile(filepath.Join(tmp, f.name), []byte(f.content), 0666); err != nil {
132 t.Fatalf("failed to create test input file: %s", err)
133 }
134 }
135 }
136
137 out, failed := file2fuzz(t, tmp, tc.args, tc.stdin)
138 if failed && tc.expectedError == "" {
139 t.Fatalf("file2fuzz failed unexpectedly: %s", out)
140 } else if failed && out != tc.expectedError {
141 t.Fatalf("file2fuzz returned unexpected error: got %q, want %q", out, tc.expectedError)
142 }
143 if !failed && out != tc.expectedStdout {
144 t.Fatalf("file2fuzz unexpected stdout: got %q, want %q", out, tc.expectedStdout)
145 }
146
147 for _, f := range tc.expectedFiles {
148 c, err := os.ReadFile(filepath.Join(tmp, f.name))
149 if err != nil {
150 t.Fatalf("failed to read expected output file %q: %s", f.name, err)
151 }
152 if string(c) != f.content {
153 t.Fatalf("expected output file %q contains unexpected content: got %s, want %s", f.name, string(c), f.content)
154 }
155 }
156 })
157 }
158 }
159
View as plain text