github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/tools/syz-declextract/declextract_test.go (about)

     1  // Copyright 2024 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  
     4  package main
     5  
     6  import (
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"github.com/google/syzkaller/pkg/ast"
    12  	"github.com/google/syzkaller/pkg/clangtool"
    13  	"github.com/google/syzkaller/pkg/clangtool/tooltest"
    14  	"github.com/google/syzkaller/pkg/compiler"
    15  	"github.com/google/syzkaller/pkg/declextract"
    16  	"github.com/google/syzkaller/pkg/ifaceprobe"
    17  	"github.com/google/syzkaller/pkg/osutil"
    18  )
    19  
    20  func TestClangTool(t *testing.T) {
    21  	tooltest.TestClangTool[declextract.Output](t)
    22  }
    23  
    24  func TestDeclextract(t *testing.T) {
    25  	tooltest.ForEachTestFile(t, func(t *testing.T, cfg *clangtool.Config, file string) {
    26  		// Created cache file to avoid running the clang tool.
    27  		goldenFile := file + ".json"
    28  		cacheFile := filepath.Join(cfg.KernelObj, filepath.Base(goldenFile))
    29  		if err := os.Symlink(goldenFile, cacheFile); err != nil {
    30  			t.Fatal(err)
    31  		}
    32  		if err := os.Symlink(filepath.Join(cfg.KernelSrc, "manual.txt"),
    33  			filepath.Join(cfg.KernelObj, "manual.txt")); err != nil {
    34  			t.Fatal(err)
    35  		}
    36  		cfg.ToolBin = "this-is-not-supposed-to-run"
    37  		probeInfo := new(ifaceprobe.Info)
    38  		probeFile := filepath.Join(cfg.KernelSrc, filepath.Base(file)+".probe")
    39  		if osutil.IsExist(probeFile) {
    40  			var err error
    41  			probeInfo, err = readProbeResult(probeFile)
    42  			if err != nil {
    43  				t.Fatal(err)
    44  			}
    45  		}
    46  		coverFile := filepath.Join(cfg.KernelSrc, filepath.Base(file)+".cover")
    47  		if !osutil.IsExist(coverFile) {
    48  			coverFile = ""
    49  		}
    50  		autoFile := filepath.Join(cfg.KernelObj, filepath.Base(file)+".txt")
    51  		runcfg := &config{
    52  			autoFile:  autoFile,
    53  			coverFile: coverFile,
    54  			loadProbeInfo: func() (*ifaceprobe.Info, error) {
    55  				return probeInfo, nil
    56  			},
    57  			Config: cfg,
    58  		}
    59  		res, err := run(runcfg)
    60  		if err != nil {
    61  			if *tooltest.FlagUpdate {
    62  				osutil.CopyFile(autoFile, file+".txt")
    63  				osutil.CopyFile(autoFile+".info", file+".info")
    64  			}
    65  			t.Fatal(err)
    66  		}
    67  
    68  		// Check that descriptions compile.
    69  		eh, errors := errorHandler()
    70  		full := ast.ParseGlob(filepath.Join(cfg.KernelObj, "*.txt"), eh)
    71  		if full == nil {
    72  			t.Fatalf("failed to parse full descriptions:\n%s", errors)
    73  		}
    74  		constInfo := compiler.ExtractConsts(full, target, eh)
    75  		if constInfo == nil {
    76  			t.Fatalf("failed to compile full descriptions:\n%s", errors)
    77  		}
    78  		// Fabricate consts.
    79  		consts := make(map[string]uint64)
    80  		for _, info := range constInfo {
    81  			for i, c := range info.Consts {
    82  				consts[c.Name] = uint64(i + 1)
    83  			}
    84  		}
    85  		desc := compiler.Compile(full, consts, target, eh)
    86  		if desc == nil {
    87  			t.Fatalf("failed to compile full descriptions:\n%s", errors)
    88  		}
    89  
    90  		// Check that generated structs have the same size/align as they had in C.
    91  		// We assume size/align do not depend on const values (which we fabricated).
    92  		for _, typ := range desc.Types {
    93  			info := res.StructInfo[typ.Name()]
    94  			if info == nil {
    95  				continue
    96  			}
    97  			if typ.Size() != uint64(info.Size) || typ.Alignment() != uint64(info.Align) {
    98  				t.Errorf("incorrect generated type %v: size %v/%v align %v/%v",
    99  					typ.Name(), typ.Size(), info.Size, typ.Alignment(), info.Align)
   100  			}
   101  		}
   102  
   103  		// TODO: Ensure that none of the syscalls will be disabled by TransitivelyEnabledCalls.
   104  
   105  		tooltest.CompareGoldenFile(t, file+".txt", autoFile)
   106  		tooltest.CompareGoldenFile(t, file+".info", autoFile+".info")
   107  	})
   108  }