| // Copyright 2021 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package main | |
| import ( | |
| "os" | |
| "os/exec" | |
| "path/filepath" | |
| "strings" | |
| "sync" | |
| "testing" | |
| "golang.org/x/tools/internal/testenv" | |
| ) | |
| func TestMain(m *testing.M) { | |
| if os.Getenv("GO_FILE2FUZZ_TEST_IS_FILE2FUZZ") != "" { | |
| main() | |
| os.Exit(0) | |
| } | |
| os.Exit(m.Run()) | |
| } | |
| var f2f struct { | |
| once sync.Once | |
| path string | |
| err error | |
| } | |
| func file2fuzz(t *testing.T, dir string, args []string, stdin string) (string, bool) { | |
| testenv.NeedsExec(t) | |
| f2f.once.Do(func() { | |
| f2f.path, f2f.err = os.Executable() | |
| }) | |
| if f2f.err != nil { | |
| t.Fatal(f2f.err) | |
| } | |
| cmd := exec.Command(f2f.path, args...) | |
| cmd.Dir = dir | |
| cmd.Env = append(os.Environ(), "PWD="+dir, "GO_FILE2FUZZ_TEST_IS_FILE2FUZZ=1") | |
| if stdin != "" { | |
| cmd.Stdin = strings.NewReader(stdin) | |
| } | |
| out, err := cmd.CombinedOutput() | |
| if err != nil { | |
| return string(out), true | |
| } | |
| return string(out), false | |
| } | |
| func TestFile2Fuzz(t *testing.T) { | |
| type file struct { | |
| name string | |
| dir bool | |
| content string | |
| } | |
| tests := []struct { | |
| name string | |
| args []string | |
| stdin string | |
| inputFiles []file | |
| expectedStdout string | |
| expectedFiles []file | |
| expectedError string | |
| }{ | |
| { | |
| name: "stdin, stdout", | |
| stdin: "hello", | |
| expectedStdout: "go test fuzz v1\n[]byte(\"hello\")", | |
| }, | |
| { | |
| name: "stdin, output file", | |
| stdin: "hello", | |
| args: []string{"-o", "output"}, | |
| expectedFiles: []file{{name: "output", content: "go test fuzz v1\n[]byte(\"hello\")"}}, | |
| }, | |
| { | |
| name: "stdin, output directory", | |
| stdin: "hello", | |
| args: []string{"-o", "output"}, | |
| inputFiles: []file{{name: "output", dir: true}}, | |
| expectedFiles: []file{{name: "output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b", content: "go test fuzz v1\n[]byte(\"hello\")"}}, | |
| }, | |
| { | |
| name: "input file, output file", | |
| args: []string{"-o", "output", "input"}, | |
| inputFiles: []file{{name: "input", content: "hello"}}, | |
| expectedFiles: []file{{name: "output", content: "go test fuzz v1\n[]byte(\"hello\")"}}, | |
| }, | |
| { | |
| name: "input file, output directory", | |
| args: []string{"-o", "output", "input"}, | |
| inputFiles: []file{{name: "output", dir: true}, {name: "input", content: "hello"}}, | |
| expectedFiles: []file{{name: "output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b", content: "go test fuzz v1\n[]byte(\"hello\")"}}, | |
| }, | |
| { | |
| name: "input files, output directory", | |
| args: []string{"-o", "output", "input", "input-2"}, | |
| inputFiles: []file{{name: "output", dir: true}, {name: "input", content: "hello"}, {name: "input-2", content: "hello :)"}}, | |
| expectedFiles: []file{ | |
| {name: "output/ffc7b87a0377262d4f77926bd235551d78e6037bbe970d81ec39ac1d95542f7b", content: "go test fuzz v1\n[]byte(\"hello\")"}, | |
| {name: "output/28059db30ce420ff65b2c29b749804c69c601aeca21b3cbf0644244ff080d7a5", content: "go test fuzz v1\n[]byte(\"hello :)\")"}, | |
| }, | |
| }, | |
| { | |
| name: "input files, no output", | |
| args: []string{"input", "input-2"}, | |
| inputFiles: []file{{name: "output", dir: true}, {name: "input", content: "hello"}, {name: "input-2", content: "hello :)"}}, | |
| expectedError: "file2fuzz: -o required with multiple input files\n", | |
| }, | |
| } | |
| for _, tc := range tests { | |
| t.Run(tc.name, func(t *testing.T) { | |
| tmp, err := os.MkdirTemp(os.TempDir(), "file2fuzz") | |
| if err != nil { | |
| t.Fatalf("os.MkdirTemp failed: %s", err) | |
| } | |
| defer os.RemoveAll(tmp) | |
| for _, f := range tc.inputFiles { | |
| if f.dir { | |
| if err := os.Mkdir(filepath.Join(tmp, f.name), 0777); err != nil { | |
| t.Fatalf("failed to create test directory: %s", err) | |
| } | |
| } else { | |
| if err := os.WriteFile(filepath.Join(tmp, f.name), []byte(f.content), 0666); err != nil { | |
| t.Fatalf("failed to create test input file: %s", err) | |
| } | |
| } | |
| } | |
| out, failed := file2fuzz(t, tmp, tc.args, tc.stdin) | |
| if failed && tc.expectedError == "" { | |
| t.Fatalf("file2fuzz failed unexpectedly: %s", out) | |
| } else if failed && out != tc.expectedError { | |
| t.Fatalf("file2fuzz returned unexpected error: got %q, want %q", out, tc.expectedError) | |
| } | |
| if !failed && out != tc.expectedStdout { | |
| t.Fatalf("file2fuzz unexpected stdout: got %q, want %q", out, tc.expectedStdout) | |
| } | |
| for _, f := range tc.expectedFiles { | |
| c, err := os.ReadFile(filepath.Join(tmp, f.name)) | |
| if err != nil { | |
| t.Fatalf("failed to read expected output file %q: %s", f.name, err) | |
| } | |
| if string(c) != f.content { | |
| t.Fatalf("expected output file %q contains unexpected content: got %s, want %s", f.name, string(c), f.content) | |
| } | |
| } | |
| }) | |
| } | |
| } |