blob: a548bde6d05b381e4250749cf5166b755450d83c [file] [log] [blame] [edit]
// Copyright 2020 The Fuchsia 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 fuzz
import (
"bytes"
"reflect"
"strings"
"testing"
)
func TestAbsPath(t *testing.T) {
build, _ := newMockBuild()
f, err := build.Fuzzer("foo/bar")
if err != nil {
t.Fatalf("failed to load fuzzer: %s", err)
}
absPaths := map[string]string{
"pkg/data/relpath": "/pkgfs/packages/foo/0/data/relpath",
"/pkg/data/relpath": "/pkg/data/relpath",
"data/relpath": "/data/r/sys/fuchsia.com:foo:0#meta:bar.cmx/relpath",
"/data/relpath": "/data/relpath",
"relpath": "/relpath",
"/relpath": "/relpath",
}
for relpath, expected := range absPaths {
got := f.AbsPath(relpath)
if expected != got {
t.Fatalf("expected %q, got %q", expected, got)
}
}
}
func TestParse(t *testing.T) {
build, _ := newMockBuild()
f, err := build.Fuzzer("foo/bar")
if err != nil {
t.Fatalf("failed to load fuzzer: %s", err)
}
f.Parse([]string{"arg", "-k1=v1", "-k1=v2", "-k2=v3", "-bad", "--alsobad", "-it=has=two"})
if !reflect.DeepEqual(f.args, []string{"arg", "-bad", "--alsobad", "-it=has=two"}) {
t.Fatalf("missing arg(s): %s", strings.Join(f.args, " "))
}
if k1, found := f.options["k1"]; !found || k1 != "v2" {
t.Fatalf("expected v2, got %s", k1)
}
if k2, found := f.options["k2"]; !found || k2 != "v3" {
t.Fatalf("expected v3, got %s", k2)
}
}
const (
FuzzerNormal = iota
FuzzerSymbolizerFailure
FuzzerSyslogFailure
)
// Run fuzzer and collect its output and artifacts. Scenario should be one of
// those listed above.
func runFuzzer(t *testing.T, name string, args []string, scenario int) (string, []string, error) {
build, _ := newMockBuild()
conn := &mockConnector{}
switch scenario {
case FuzzerSymbolizerFailure:
build.(*mockBuild).brokenSymbolizer = true
case FuzzerSyslogFailure:
conn.shouldFailToGetSysLog = true
}
f, err := build.Fuzzer(name)
if err != nil {
t.Fatalf("failed to load fuzzer: %s", err)
}
f.Parse(args)
var outBuf bytes.Buffer
artifacts, err := f.Run(conn, &outBuf, "/some/artifactDir")
return outBuf.String(), artifacts, err
}
func TestRun(t *testing.T) {
out, artifacts, err := runFuzzer(t, "foo/bar", nil, FuzzerNormal)
if err != nil {
t.Fatalf("failed to run fuzzer: %s", err)
}
// Check for syslog insertion
if !strings.Contains(out, "syslog for 123") {
t.Fatalf("fuzzer output missing syslog: %q", out)
}
// Check for symbolization
if !strings.Contains(out, "wow.c:1") {
t.Fatalf("fuzzer output not properly symbolized: %q", out)
}
// Check for artifact detection
artifactAbsPath := "/data/r/sys/fuchsia.com:foo:0#meta:bar.cmx/crash-1312"
if !reflect.DeepEqual(artifacts, []string{artifactAbsPath}) {
t.Fatalf("unexpected artifact list: %s", artifacts)
}
// Check for artifact path rewriting
if !strings.Contains(out, "/some/artifactDir/crash-1312") {
t.Fatalf("artifact prefix not rewritten: %q", out)
}
}
func TestRunWithInvalidArtifactPrefix(t *testing.T) {
args := []string{"-artifact_prefix=foo/bar"}
_, _, err := runFuzzer(t, "foo/bar", args, FuzzerNormal)
if err == nil || !strings.Contains(err.Error(), "artifact_prefix not in data/") {
t.Fatalf("expected failure to run but got: %s", err)
}
}
func TestMissingPID(t *testing.T) {
output, _, err := runFuzzer(t, "fail/nopid", nil, FuzzerNormal)
if err != nil {
t.Fatalf("expected to succeed but got: %s", err)
}
if !strings.Contains(output, "missing pid") {
t.Fatalf("expected missing pid but got: %q", output)
}
}
func TestSyslogFailure(t *testing.T) {
output, _, err := runFuzzer(t, "foo/bar", nil, FuzzerSyslogFailure)
if err != nil {
t.Fatalf("expected to succeed but got: %s", err)
}
if !strings.Contains(output, "failed to fetch syslog") {
t.Fatalf("expected syslog fetch failure but got: %q", output)
}
}
func TestMissingSymbolizer(t *testing.T) {
_, _, err := runFuzzer(t, "foo/bar", nil, FuzzerSymbolizerFailure)
if err == nil || !strings.Contains(err.Error(), "failed during symbolization") {
t.Fatalf("expected failure to symbolize but got: %s", err)
}
}
func TestMissingFuzzerPackage(t *testing.T) {
_, _, err := runFuzzer(t, "fail/notfound", nil, FuzzerNormal)
if err == nil || !strings.Contains(err.Error(), "not found") {
t.Fatalf("expected failure to find package but got: %s", err)
}
}