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