diff options
| -rw-r--r-- | pkg/clangtool/tooltest/tooltest.go | 103 | ||||
| -rw-r--r-- | tools/syz-declextract/declextract_test.go | 95 |
2 files changed, 109 insertions, 89 deletions
diff --git a/pkg/clangtool/tooltest/tooltest.go b/pkg/clangtool/tooltest/tooltest.go new file mode 100644 index 000000000..b9ad18a83 --- /dev/null +++ b/pkg/clangtool/tooltest/tooltest.go @@ -0,0 +1,103 @@ +// Copyright 2025 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package tooltest + +import ( + "encoding/json" + "flag" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/syzkaller/pkg/clangtool" + "github.com/google/syzkaller/pkg/osutil" + "github.com/google/syzkaller/pkg/testutil" +) + +var ( + FlagBin = flag.String("bin", "", "path to the clang tool binary to use") + FlagUpdate = flag.Bool("update", false, "update golden files") +) + +func TestClangTool[Output any, OutputPtr clangtool.OutputDataPtr[Output]](t *testing.T) { + if *FlagBin == "" { + t.Skipf("clang tool path is not specified, run with -bin=clangtool flag") + } + ForEachTestFile(t, func(t *testing.T, cfg *clangtool.Config, file string) { + out, err := clangtool.Run[Output, OutputPtr](cfg) + if err != nil { + t.Fatal(err) + } + got, err := json.MarshalIndent(out, "", "\t") + if err != nil { + t.Fatal(err) + } + CompareGoldenData(t, file+".json", got) + }) +} + +func ForEachTestFile(t *testing.T, fn func(t *testing.T, cfg *clangtool.Config, file string)) { + forEachTestFile(t, func(t *testing.T, file string) { + t.Run(filepath.Base(file), func(t *testing.T) { + t.Parallel() + buildDir := t.TempDir() + commands := fmt.Sprintf(`[{ + "file": "%s", + "directory": "%s", + "command": "clang -c %s -DKBUILD_BASENAME=foo" + }]`, + file, buildDir, file) + dbFile := filepath.Join(buildDir, "compile_commands.json") + if err := os.WriteFile(dbFile, []byte(commands), 0600); err != nil { + t.Fatal(err) + } + cfg := &clangtool.Config{ + ToolBin: *FlagBin, + KernelSrc: osutil.Abs("testdata"), + KernelObj: buildDir, + CacheFile: filepath.Join(buildDir, filepath.Base(file)+".json"), + DebugTrace: &testutil.Writer{TB: t}, + } + fn(t, cfg, file) + }) + }) +} + +func forEachTestFile(t *testing.T, fn func(t *testing.T, file string)) { + files, err := filepath.Glob(filepath.Join(osutil.Abs("testdata"), "*.c")) + if err != nil { + t.Fatal(err) + } + if len(files) == 0 { + t.Fatal("found no source files") + } + for _, file := range files { + fn(t, file) + } +} + +func CompareGoldenFile(t *testing.T, goldenFile, gotFile string) { + got, err := os.ReadFile(gotFile) + if err != nil { + t.Fatal(err) + } + CompareGoldenData(t, goldenFile, got) +} + +func CompareGoldenData(t *testing.T, goldenFile string, got []byte) { + if *FlagUpdate { + if err := os.WriteFile(goldenFile, got, 0644); err != nil { + t.Fatal(err) + } + } + want, err := os.ReadFile(goldenFile) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(want, got); diff != "" { + t.Fatal(diff) + } +} diff --git a/tools/syz-declextract/declextract_test.go b/tools/syz-declextract/declextract_test.go index 879e49707..bf1af7bdf 100644 --- a/tools/syz-declextract/declextract_test.go +++ b/tools/syz-declextract/declextract_test.go @@ -4,47 +4,25 @@ package main import ( - "encoding/json" - "flag" - "fmt" "os" "path/filepath" "testing" - "github.com/google/go-cmp/cmp" "github.com/google/syzkaller/pkg/ast" "github.com/google/syzkaller/pkg/clangtool" + "github.com/google/syzkaller/pkg/clangtool/tooltest" "github.com/google/syzkaller/pkg/compiler" "github.com/google/syzkaller/pkg/declextract" "github.com/google/syzkaller/pkg/ifaceprobe" "github.com/google/syzkaller/pkg/osutil" - "github.com/google/syzkaller/pkg/testutil" -) - -var ( - flagBin = flag.String("bin", "", "path to syz-declextract binary to use") - flagUpdate = flag.Bool("update", false, "update golden files") ) func TestClangTool(t *testing.T) { - if *flagBin == "" { - t.Skipf("syz-declextract path is not specified, run with -bin=syz-declextract flag") - } - testEachFile(t, func(t *testing.T, cfg *clangtool.Config, file string) { - out, err := clangtool.Run[declextract.Output](cfg) - if err != nil { - t.Fatal(err) - } - got, err := json.MarshalIndent(out, "", "\t") - if err != nil { - t.Fatal(err) - } - compareGoldenData(t, file+".json", got) - }) + tooltest.TestClangTool[declextract.Output](t) } func TestDeclextract(t *testing.T) { - testEachFile(t, func(t *testing.T, cfg *clangtool.Config, file string) { + tooltest.ForEachTestFile(t, func(t *testing.T, cfg *clangtool.Config, file string) { // Created cache file to avoid running the clang tool. goldenFile := file + ".json" cacheFile := filepath.Join(cfg.KernelObj, filepath.Base(goldenFile)) @@ -80,7 +58,7 @@ func TestDeclextract(t *testing.T) { } res, err := run(runcfg) if err != nil { - if *flagUpdate { + if *tooltest.FlagUpdate { osutil.CopyFile(autoFile, file+".txt") osutil.CopyFile(autoFile+".info", file+".info") } @@ -124,68 +102,7 @@ func TestDeclextract(t *testing.T) { // TODO: Ensure that none of the syscalls will be disabled by TransitivelyEnabledCalls. - compareGoldenFile(t, file+".txt", autoFile) - compareGoldenFile(t, file+".info", autoFile+".info") + tooltest.CompareGoldenFile(t, file+".txt", autoFile) + tooltest.CompareGoldenFile(t, file+".info", autoFile+".info") }) } - -func testEachFile(t *testing.T, fn func(t *testing.T, cfg *clangtool.Config, file string)) { - testdata, err := filepath.Abs("testdata") - if err != nil { - t.Fatal(err) - } - files, err := filepath.Glob(filepath.Join(testdata, "*.c")) - if err != nil { - t.Fatal(err) - } - if len(files) == 0 { - t.Fatal("found no source files") - } - for _, file := range files { - t.Run(filepath.Base(file), func(t *testing.T) { - t.Parallel() - buildDir := t.TempDir() - commands := fmt.Sprintf(`[{ - "file": "%s", - "directory": "%s", - "command": "clang -c %s -DKBUILD_BASENAME=foo" - }]`, - file, buildDir, file) - dbFile := filepath.Join(buildDir, "compile_commands.json") - if err := os.WriteFile(dbFile, []byte(commands), 0600); err != nil { - t.Fatal(err) - } - cfg := &clangtool.Config{ - ToolBin: *flagBin, - KernelSrc: testdata, - KernelObj: buildDir, - CacheFile: filepath.Join(buildDir, filepath.Base(file)+".json"), - DebugTrace: &testutil.Writer{TB: t}, - } - fn(t, cfg, file) - }) - } -} - -func compareGoldenFile(t *testing.T, goldenFile, gotFile string) { - got, err := os.ReadFile(gotFile) - if err != nil { - t.Fatal(err) - } - compareGoldenData(t, goldenFile, got) -} - -func compareGoldenData(t *testing.T, goldenFile string, got []byte) { - if *flagUpdate { - if err := os.WriteFile(goldenFile, got, 0644); err != nil { - t.Fatal(err) - } - } - want, err := os.ReadFile(goldenFile) - if err != nil { - t.Fatal(err) - } - if diff := cmp.Diff(got, want); diff != "" { - t.Fatal(diff) - } -} |
