diff options
Diffstat (limited to 'pkg/runtest/executor_test.go')
| -rw-r--r-- | pkg/runtest/executor_test.go | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/pkg/runtest/executor_test.go b/pkg/runtest/executor_test.go index bb830e885..5655f5ea4 100644 --- a/pkg/runtest/executor_test.go +++ b/pkg/runtest/executor_test.go @@ -8,6 +8,8 @@ import ( "fmt" "math/rand" "os" + "os/exec" + "path/filepath" "runtime" "strings" "testing" @@ -24,6 +26,42 @@ import ( "github.com/google/syzkaller/sys/targets" ) +// Find the corresponding QEMU binary for the target arch, if needed. +func qemuBinary(arch string) (string, error) { + qarch, ok := map[string]string{ + "386": "i386", + "amd64": "x86_64", + "arm64": "aarch64", + "arm": "arm", + "mips64le": "mips64el", + "ppc64le": "ppc64le", + "riscv64": "riscv64", + "s390x": "s390x", + }[arch] + if !ok { + return "", fmt.Errorf("unsupported architecture: %s", arch) + } + + qemuBinary := "qemu-" + qarch + path, err := exec.LookPath(qemuBinary) + if err != nil { + return "", fmt.Errorf("qemu binary not found in PATH: %s", qemuBinary) + } + + return filepath.Base(path), nil +} + +// If the tests are running on CI, or if there is an assertion failure in the executor, +// report a fatal error. Otherwise, assume cross-arch execution does not work, and skip +// the test. +func handleCrossArchError(t *testing.T, err error) { + if os.Getenv("CI") != "" || strings.Contains(err.Error(), "SYZFAIL:") { + t.Fatal(err) + } else { + t.Skipf("skipping, cross-arch execution failed: %v", err) + } +} + // TestExecutor runs all internal executor unit tests. // We do it here because we already build executor binary here. func TestExecutor(t *testing.T) { @@ -41,15 +79,20 @@ func TestExecutor(t *testing.T) { t.Fatal(err) } bin := csource.BuildExecutor(t, target, "../..") - // qemu-user may allow us to run some cross-arch binaries. - if _, err := osutil.RunCmd(time.Minute, dir, bin, "test"); err != nil { - if sysTarget.Arch == runtime.GOARCH || sysTarget.VMArch == runtime.GOARCH { + if sysTarget.Arch == runtime.GOARCH || sysTarget.VMArch == runtime.GOARCH { + // Execute the tests natively. + if _, err := osutil.RunCmd(time.Minute, dir, bin, "test"); err != nil { t.Fatal(err) } - if os.Getenv("CI") != "" || strings.Contains(err.Error(), "SYZFAIL:") { - t.Fatal(err) - } else { - t.Skipf("skipping, cross-arch binary failed: %v", err) + } else { + // Get QEMU binary for the target arch. This code might run inside Docker, so it cannot + // rely on binfmt_misc handlers provided by qemu-user. + qemu, err := qemuBinary(sysTarget.Arch) + if err != nil { + handleCrossArchError(t, err) + } + if _, err := osutil.RunCmd(time.Minute, dir, qemu, bin, "test"); err != nil { + handleCrossArchError(t, err) } } }) |
