github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/kfuzztest/description_generation_test.go (about)

     1  // Copyright 2025 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  package kfuzztest
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"path"
     9  	"runtime"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/google/go-cmp/cmp"
    14  	"github.com/google/syzkaller/pkg/osutil"
    15  	"github.com/google/syzkaller/sys/targets"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  type testData struct {
    20  	dir  string
    21  	desc string
    22  }
    23  
    24  func TestBuildDescriptions(t *testing.T) {
    25  	testCases, err := readTestCases("./testdata")
    26  	require.NoError(t, err)
    27  
    28  	target := targets.Get(targets.Linux, targets.AMD64)
    29  	if runtime.GOOS != target.BuildOS {
    30  		t.Skip("we cannot build Linux on this target")
    31  	}
    32  	if target.BrokenCompiler != "" {
    33  		t.Skip("skipping the test due to broken cross-compiler:\n" + target.BrokenCompiler)
    34  	}
    35  	for _, tc := range testCases {
    36  		t.Run(tc.dir, func(t *testing.T) {
    37  			runTest(t, target, tc)
    38  		})
    39  	}
    40  }
    41  
    42  // Tests that the description inferred from a compiled binary matches an
    43  // expected description.
    44  func runTest(t *testing.T, target *targets.Target, tc testData) {
    45  	// Compile the C binary containing the metadata.
    46  	cmd := flags(tc.dir)
    47  	out, err := osutil.RunCmd(time.Hour, "", target.CCompiler, cmd...)
    48  	require.NoErrorf(t, err, "Failed to compile: %s", string(out))
    49  	// Cleanup the compiled binary.
    50  	defer func() {
    51  		out, err := osutil.RunCmd(time.Hour, "", "rm", path.Join(tc.dir, "bin"))
    52  		if err != nil {
    53  			require.NoErrorf(t, err, "Failed to cleanup: %s", string(out))
    54  		}
    55  	}()
    56  
    57  	binaryPath := path.Join(tc.dir, "bin")
    58  	desc, err := ExtractDescription(binaryPath)
    59  	require.NoError(t, err)
    60  
    61  	if diffDesc := cmp.Diff(tc.desc, desc); diffDesc != "" {
    62  		fmt.Print(diffDesc)
    63  		t.Fail()
    64  		return
    65  	}
    66  }
    67  
    68  func flags(testDir string) []string {
    69  	return []string{
    70  		"-g",
    71  		"-T",
    72  		path.Join(testDir, "..", "linker.ld"),
    73  		"-o",
    74  		path.Join(testDir, "bin"),
    75  		path.Join(testDir, "prog.c"),
    76  	}
    77  }
    78  
    79  func readTestCases(dir string) ([]testData, error) {
    80  	var testCases []testData
    81  	testDirs, err := os.ReadDir(dir)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	for _, subDir := range testDirs {
    87  		if !subDir.IsDir() {
    88  			continue
    89  		}
    90  		testData, err := readTestdata(path.Join(dir, subDir.Name()))
    91  		if err != nil {
    92  			return nil, err
    93  		}
    94  		testCases = append(testCases, testData)
    95  	}
    96  
    97  	return testCases, nil
    98  }
    99  
   100  func readTestdata(testDir string) (testData, error) {
   101  	content, err := os.ReadFile(path.Join(testDir, "desc.txt"))
   102  	if err != nil {
   103  		return testData{}, err
   104  	}
   105  
   106  	return testData{
   107  		dir:  testDir,
   108  		desc: string(content),
   109  	}, nil
   110  }