mirror of https://github.com/golang/go.git
182 lines
5.4 KiB
Go
182 lines
5.4 KiB
Go
// 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 (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
// The setup for this test is mostly cribbed from x/exp/txtar.
|
|
|
|
var buildBin struct {
|
|
once sync.Once
|
|
name string
|
|
err error
|
|
}
|
|
|
|
func binPath(t *testing.T) string {
|
|
t.Helper()
|
|
if _, err := exec.LookPath("go"); err != nil {
|
|
t.Skipf("cannot build file2fuzz binary: %v", err)
|
|
}
|
|
|
|
buildBin.once.Do(func() {
|
|
exe, err := ioutil.TempFile("", "file2fuzz-*.exe")
|
|
if err != nil {
|
|
buildBin.err = err
|
|
return
|
|
}
|
|
exe.Close()
|
|
buildBin.name = exe.Name()
|
|
|
|
cmd := exec.Command("go", "build", "-o", buildBin.name, ".")
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
buildBin.err = fmt.Errorf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
|
}
|
|
})
|
|
|
|
if buildBin.err != nil {
|
|
if runtime.GOOS == "android" {
|
|
t.Skipf("skipping test after failing to build file2fuzz binary: go_android_exec may have failed to copy needed dependencies (see https://golang.org/issue/37088)")
|
|
}
|
|
t.Fatal(buildBin.err)
|
|
}
|
|
return buildBin.name
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
os.Exit(m.Run())
|
|
if buildBin.name != "" {
|
|
os.Remove(buildBin.name)
|
|
}
|
|
}
|
|
|
|
func file2fuzz(t *testing.T, dir string, args []string, stdin string) (string, bool) {
|
|
t.Helper()
|
|
cmd := exec.Command(binPath(t), args...)
|
|
cmd.Dir = dir
|
|
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 := ioutil.TempDir(os.TempDir(), "file2fuzz")
|
|
if err != nil {
|
|
t.Fatalf("ioutil.TempDir 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 := ioutil.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 := ioutil.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)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|