github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/vminfo/vminfo_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 vminfo 5 6 import ( 7 "context" 8 "os" 9 "path/filepath" 10 "runtime" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/google/syzkaller/pkg/flatrpc" 16 "github.com/google/syzkaller/pkg/fuzzer/queue" 17 "github.com/google/syzkaller/prog" 18 _ "github.com/google/syzkaller/sys" 19 "github.com/google/syzkaller/sys/targets" 20 ) 21 22 func TestHostMachineInfo(t *testing.T) { 23 checker, files := hostChecker(t) 24 dups := make(map[string]bool) 25 for _, file := range files { 26 if file.Name[0] != '/' || file.Name[len(file.Name)-1] == '/' || strings.Contains(file.Name, "\\") { 27 t.Errorf("malformed file %q", file.Name) 28 } 29 // Reading duplicate files leads to duplicate work. 30 if dups[file.Name] { 31 t.Errorf("duplicate file %q", file.Name) 32 } 33 dups[file.Name] = true 34 if file.Error != "" { 35 t.Logf("failed to read %q: %s", file.Name, file.Error) 36 } 37 } 38 modules, info, err := checker.MachineInfo(files) 39 if err != nil { 40 t.Fatal(err) 41 } 42 t.Logf("machine info:\n%s", info) 43 for _, module := range modules { 44 t.Logf("module %q: addr 0x%x size %v", module.Name, module.Addr, module.Size) 45 } 46 } 47 48 func TestSyscalls(t *testing.T) { 49 t.Parallel() 50 for _, arches := range targets.List { 51 for _, target := range arches { 52 if target.OS == targets.Linux { 53 continue // linux has own TestLinuxSyscalls test 54 } 55 t.Run(target.OS+"/"+target.Arch, func(t *testing.T) { 56 t.Parallel() 57 cfg := testConfig(t, target.OS, target.Arch) 58 checker := New(cfg) 59 stop := make(chan struct{}) 60 go createSuccessfulResults(checker, stop) 61 enabled, disabled, _, err := checker.Run(context.Background(), nil, allFeatures()) 62 close(stop) 63 if err != nil { 64 t.Fatal(err) 65 } 66 for call, reason := range disabled { 67 t.Errorf("disabled call %v: %v", call.Name, reason) 68 } 69 if len(enabled) != len(cfg.Syscalls) { 70 t.Errorf("enabled only %v calls out of %v", len(enabled), len(cfg.Syscalls)) 71 } 72 }) 73 } 74 } 75 } 76 77 func allFeatures() []*flatrpc.FeatureInfo { 78 var features []*flatrpc.FeatureInfo 79 for feat := range flatrpc.EnumNamesFeature { 80 features = append(features, &flatrpc.FeatureInfo{ 81 Id: feat, 82 }) 83 } 84 return features 85 } 86 87 func createSuccessfulResults(source queue.Source, stop chan struct{}) { 88 var count int 89 for { 90 select { 91 case <-stop: 92 return 93 case <-time.After(time.Millisecond): 94 } 95 req := source.Next() 96 if req == nil { 97 continue 98 } 99 count++ 100 if count > 1000 { 101 // This is just a sanity check that we don't do something stupid accidentally. 102 // If it grows above the limit intentionally, the limit can be increased. 103 // Currently we have 641 (when we failed to properly dedup syscall tests, it was 4349). 104 panic("too many test programs") 105 } 106 res := &queue.Result{ 107 Status: queue.Success, 108 } 109 switch req.Type { 110 case flatrpc.RequestTypeProgram: 111 res.Info = &flatrpc.ProgInfo{} 112 for range req.Prog.Calls { 113 res.Info.Calls = append(res.Info.Calls, &flatrpc.CallInfo{ 114 Cover: []uint64{1}, 115 Signal: []uint64{1}, 116 Comps: []*flatrpc.Comparison{{Op1: 1, Op2: 2}}, 117 }) 118 } 119 case flatrpc.RequestTypeGlob: 120 res.Output = []byte("/some/file\n") 121 } 122 req.Done(res) 123 } 124 } 125 126 func hostChecker(t *testing.T) (*Checker, []*flatrpc.FileInfo) { 127 cfg := testConfig(t, runtime.GOOS, runtime.GOARCH) 128 checker := New(cfg) 129 files := readFiles(checker.RequiredFiles()) 130 return checker, files 131 } 132 133 func testConfig(t *testing.T, OS, arch string) *Config { 134 target, err := prog.GetTarget(OS, arch) 135 if err != nil { 136 t.Fatal(err) 137 } 138 var syscalls []int 139 for id := range target.Syscalls { 140 if !target.Syscalls[id].Attrs.Disabled { 141 syscalls = append(syscalls, id) 142 } 143 } 144 return &Config{ 145 Target: target, 146 Features: flatrpc.AllFeatures, 147 Sandbox: flatrpc.ExecEnvSandboxNone, 148 Syscalls: syscalls, 149 } 150 } 151 152 func readFiles(files []string) []*flatrpc.FileInfo { 153 var res []*flatrpc.FileInfo 154 for _, glob := range files { 155 glob = filepath.FromSlash(glob) 156 if !strings.Contains(glob, "*") { 157 res = append(res, readFile(glob)) 158 continue 159 } 160 matches, err := filepath.Glob(glob) 161 if err != nil { 162 res = append(res, &flatrpc.FileInfo{ 163 Name: glob, 164 Error: err.Error(), 165 }) 166 continue 167 } 168 for _, file := range matches { 169 res = append(res, readFile(file)) 170 } 171 } 172 return res 173 } 174 175 func readFile(file string) *flatrpc.FileInfo { 176 data, err := os.ReadFile(file) 177 exists, errStr := true, "" 178 if err != nil { 179 exists, errStr = !os.IsNotExist(err), err.Error() 180 } 181 return &flatrpc.FileInfo{ 182 Name: file, 183 Exists: exists, 184 Error: errStr, 185 Data: data, 186 } 187 }