github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/runtest/run_test.go (about) 1 // Copyright 2018 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 runtest 5 6 import ( 7 "bytes" 8 "context" 9 "encoding/binary" 10 "encoding/hex" 11 "flag" 12 "fmt" 13 "os" 14 "path/filepath" 15 "runtime" 16 "testing" 17 "time" 18 19 "github.com/google/syzkaller/pkg/csource" 20 "github.com/google/syzkaller/pkg/flatrpc" 21 "github.com/google/syzkaller/pkg/fuzzer/queue" 22 "github.com/google/syzkaller/pkg/osutil" 23 "github.com/google/syzkaller/pkg/rpcserver" 24 "github.com/google/syzkaller/pkg/testutil" 25 "github.com/google/syzkaller/pkg/vminfo" 26 "github.com/google/syzkaller/prog" 27 _ "github.com/google/syzkaller/sys" 28 "github.com/google/syzkaller/sys/targets" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 var ( 33 // Can be used as: 34 // go test -v -run=Test/64_fork ./pkg/runtest -filter=nonfailing 35 // to select a subset of tests to run. 36 flagFilter = flag.String("filter", "", "prefix to match test file names") 37 flagDebug = flag.Bool("debug", false, "include debug output from the executor") 38 flagGDB = flag.Bool("gdb", false, "run executor under gdb") 39 ) 40 41 func TestUnit(t *testing.T) { 42 switch runtime.GOOS { 43 case targets.OpenBSD: 44 t.Skipf("broken on %v", runtime.GOOS) 45 } 46 // Test only one target in short mode (each takes 5+ seconds to run). 47 shortTarget := targets.Get(targets.TestOS, targets.TestArch64Fork) 48 for _, sysTarget := range targets.List[targets.TestOS] { 49 if testing.Short() && sysTarget != shortTarget { 50 continue 51 } 52 sysTarget1 := targets.Get(sysTarget.OS, sysTarget.Arch) 53 t.Run(sysTarget1.Arch, func(t *testing.T) { 54 t.Parallel() 55 test(t, sysTarget1) 56 }) 57 } 58 } 59 60 func test(t *testing.T, sysTarget *targets.Target) { 61 target, err := prog.GetTarget(sysTarget.OS, sysTarget.Arch) 62 if err != nil { 63 t.Fatal(err) 64 } 65 executor := csource.BuildExecutor(t, target, "../../", "-fsanitize-coverage=trace-pc") 66 calls := make(map[*prog.Syscall]bool) 67 for _, call := range target.Syscalls { 68 calls[call] = true 69 } 70 enabledCalls := map[string]map[*prog.Syscall]bool{ 71 "": calls, 72 "none": calls, 73 } 74 ctx := &Context{ 75 Dir: filepath.Join("..", "..", "sys", target.OS, targets.TestOS), 76 Target: target, 77 Tests: *flagFilter, 78 Features: 0, 79 EnabledCalls: enabledCalls, 80 LogFunc: func(text string) { 81 t.Helper() 82 t.Log(text) 83 }, 84 Retries: 7, // empirical number that seem to reduce flakes to zero 85 Verbose: true, 86 Debug: *flagDebug, 87 } 88 ctx.Init() 89 waitCtx := startRPCServer(t, target, executor, ctx, rpcParams{ 90 manyProcs: true, 91 machineChecked: func(features flatrpc.Feature) { 92 // Features we expect to be enabled on the test OS. 93 // All sandboxes except for none are not implemented, coverage is not returned, 94 // and setup for few features is failing specifically to test feature detection. 95 want := flatrpc.FeatureCoverage | 96 flatrpc.FeatureExtraCoverage | 97 flatrpc.FeatureDelayKcovMmap | 98 flatrpc.FeatureKcovResetIoctl | 99 flatrpc.FeatureSandboxNone | 100 flatrpc.FeatureFault | 101 flatrpc.FeatureNetDevices | 102 flatrpc.FeatureKCSAN | 103 flatrpc.FeatureNicVF | 104 flatrpc.FeatureUSBEmulation | 105 flatrpc.FeatureVhciInjection | 106 flatrpc.FeatureWifiEmulation | 107 flatrpc.FeatureLRWPANEmulation | 108 flatrpc.FeatureBinFmtMisc | 109 flatrpc.FeatureSwap 110 for feat, name := range flatrpc.EnumNamesFeature { 111 if features&feat != want&feat { 112 t.Errorf("expect feature %v to be %v, but it is %v", 113 name, want&feat != 0, features&feat != 0) 114 } 115 } 116 }, 117 }) 118 if t.Failed() { 119 return 120 } 121 if err := ctx.Run(waitCtx); err != nil { 122 t.Fatal(err) 123 } 124 } 125 126 func TestCover(t *testing.T) { 127 // End-to-end test for coverage/signal/comparisons collection. 128 // We inject given blobs into KCOV buffer using syz_inject_cover, 129 // and then test what we get back. 130 t.Parallel() 131 for _, arch := range []string{targets.TestArch32, targets.TestArch64, targets.TestArch64Fork} { 132 sysTarget := targets.Get(targets.TestOS, arch) 133 t.Run(arch, func(t *testing.T) { 134 if sysTarget.BrokenCompiler != "" { 135 t.Skipf("skipping due to broken compiler:\n%v", sysTarget.BrokenCompiler) 136 } 137 target, err := prog.GetTarget(targets.TestOS, arch) 138 if err != nil { 139 t.Fatal(err) 140 } 141 t.Parallel() 142 testCover(t, target) 143 }) 144 } 145 } 146 147 type CoverTest struct { 148 Is64Bit bool 149 ExtraCoverage bool 150 Input []byte 151 MaxSignal []uint64 152 CoverFilter []uint64 153 ReturnAllSignal bool 154 Flags flatrpc.ExecFlag 155 Cover []uint64 156 Signal []uint64 157 Comps []*flatrpc.Comparison 158 } 159 160 type Comparison struct { 161 Type uint64 162 Arg1 uint64 163 Arg2 uint64 164 PC uint64 165 } 166 167 const ( 168 CmpConst = 1 169 CmpSize1 = 0 170 CmpSize2 = 2 171 CmpSize4 = 4 172 CmpSize8 = 6 173 ) 174 175 func testCover(t *testing.T, target *prog.Target) { 176 tests := []CoverTest{ 177 // Empty coverage. 178 { 179 Is64Bit: true, 180 Input: makeCover64(), 181 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 182 }, 183 { 184 Is64Bit: false, 185 Input: makeCover32(), 186 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 187 }, 188 // Single 64-bit PC. 189 { 190 Is64Bit: true, 191 Input: makeCover64(0xc0dec0dec0112233), 192 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 193 Cover: []uint64{0xc0dec0dec0112233}, 194 Signal: []uint64{0xc0dec0dec0112233}, 195 }, 196 // Single 32-bit PC. 197 { 198 Is64Bit: false, 199 Input: makeCover32(0xc0112233), 200 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 201 Cover: []uint64{0xc0112233}, 202 Signal: []uint64{0xc0112233}, 203 }, 204 // Ensure we don't sent cover/signal when not requested. 205 { 206 Is64Bit: true, 207 Input: makeCover64(0xc0dec0dec0112233), 208 Flags: flatrpc.ExecFlagCollectCover, 209 Cover: []uint64{0xc0dec0dec0112233}, 210 }, 211 { 212 Is64Bit: true, 213 Input: makeCover64(0xc0dec0dec0112233), 214 Flags: flatrpc.ExecFlagCollectSignal, 215 Signal: []uint64{0xc0dec0dec0112233}, 216 }, 217 // Coverage deduplication. 218 { 219 Is64Bit: true, 220 Input: makeCover64(0xc0dec0dec0000033, 0xc0dec0dec0000022, 0xc0dec0dec0000011, 221 0xc0dec0dec0000011, 0xc0dec0dec0000022, 0xc0dec0dec0000033, 0xc0dec0dec0000011), 222 Flags: flatrpc.ExecFlagCollectCover, 223 Cover: []uint64{0xc0dec0dec0000033, 0xc0dec0dec0000022, 0xc0dec0dec0000011, 224 0xc0dec0dec0000011, 0xc0dec0dec0000022, 0xc0dec0dec0000033, 0xc0dec0dec0000011}, 225 }, 226 { 227 Is64Bit: true, 228 Input: makeCover64(0xc0dec0dec0000033, 0xc0dec0dec0000022, 0xc0dec0dec0000011, 229 0xc0dec0dec0000011, 0xc0dec0dec0000022, 0xc0dec0dec0000033, 0xc0dec0dec0000011), 230 Flags: flatrpc.ExecFlagCollectCover | flatrpc.ExecFlagDedupCover, 231 Cover: []uint64{0xc0dec0dec0000011, 0xc0dec0dec0000022, 0xc0dec0dec0000033}, 232 }, 233 // Signal hashing. 234 { 235 Is64Bit: true, 236 Input: makeCover64(0xc0dec0dec0011001, 0xc0dec0dec0022002, 0xc0dec0dec00330f0, 237 0xc0dec0dec0044b00, 0xc0dec0dec0011001, 0xc0dec0dec0022002), 238 Flags: flatrpc.ExecFlagCollectSignal, 239 Signal: []uint64{0xc0dec0dec0011b01, 0xc0dec0dec0044bf0, 0xc0dec0dec00330f2, 240 0xc0dec0dec0022003, 0xc0dec0dec0011001}, 241 }, 242 // Invalid non-kernel PCs must fail test execution. 243 { 244 Is64Bit: true, 245 Input: makeCover64(0xc0dec0dec0000022, 0xc000000000000033), 246 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 247 }, 248 { 249 Is64Bit: false, 250 Input: makeCover32(0x33), 251 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 252 }, 253 // 64-bit comparisons. 254 { 255 Is64Bit: true, 256 Input: makeComps( 257 // A normal 8-byte comparison must be returned in the output as is. 258 Comparison{CmpSize8 | CmpConst, 0x1111111111111111, 0x2222222222222222, 1}, 259 // Duplicate must be removed. 260 Comparison{CmpSize8 | CmpConst, 0x1111111111111111, 0x2222222222222222, 1}, 261 // Non-const comparisons must be duplicated both ways. 262 Comparison{CmpSize8, 0x30, 0x31, 1}, 263 // Test sign-extension for smaller argument types. 264 Comparison{CmpSize1 | CmpConst, 0xa3, 0x77, 1}, 265 Comparison{CmpSize1 | CmpConst, 0xff10, 0xffe1, 1}, 266 Comparison{CmpSize2 | CmpConst, 0xabcd, 0x4321, 1}, 267 Comparison{CmpSize4 | CmpConst, 0xabcd1234, 0x4321, 1}, 268 // Comparison with const 0 must be removed. 269 Comparison{CmpSize8 | CmpConst, 0, 0x2222222222222222, 1}, 270 Comparison{CmpSize8, 0, 0x3333, 1}, 271 // Comparison of equal values must be removed. 272 Comparison{CmpSize8, 0, 0, 1}, 273 Comparison{CmpSize8, 0x1111, 0x1111, 1}, 274 // Comparisons of kernel addresses must be removed. 275 Comparison{CmpSize8 | CmpConst, 0xda1a0000, 0xda1a1000, 1}, 276 Comparison{CmpSize8, 0xda1a0000, 0, 1}, 277 Comparison{CmpSize8, 0, 0xda1a0010, 1}, 278 Comparison{CmpSize8 | CmpConst, 0xc0dec0dec0de0000, 0xc0dec0dec0de1000, 1}, 279 // But not with something that's not a kernel address. 280 Comparison{CmpSize8 | CmpConst, 0xda1a0010, 0xabcd, 1}, 281 ), 282 Flags: flatrpc.ExecFlagCollectComps, 283 Comps: []*flatrpc.Comparison{ 284 {Pc: 1, Op1: 0x2222222222222222, Op2: 0x1111111111111111, IsConst: true}, 285 {Pc: 1, Op1: 0x31, Op2: 0x30, IsConst: false}, 286 {Pc: 1, Op1: 0x77, Op2: 0xffffffffffffffa3, IsConst: true}, 287 {Pc: 1, Op1: 0xffffffffffffffe1, Op2: 0x10, IsConst: true}, 288 {Pc: 1, Op1: 0x4321, Op2: 0xffffffffffffabcd, IsConst: true}, 289 {Pc: 1, Op1: 0x4321, Op2: 0xffffffffabcd1234, IsConst: true}, 290 {Pc: 1, Op1: 0x3333, Op2: 0, IsConst: false}, 291 {Pc: 1, Op1: 0xabcd, Op2: 0xda1a0010, IsConst: true}, 292 }, 293 }, 294 // 32-bit comparisons must be the same, so test only a subset. 295 { 296 Is64Bit: false, 297 Input: makeComps( 298 Comparison{CmpSize8 | CmpConst, 0x1111111111111111, 0x2222222222222222, 1}, 299 Comparison{CmpSize2 | CmpConst, 0xabcd, 0x4321, 2}, 300 Comparison{CmpSize4 | CmpConst, 0xda1a0000, 0xda1a1000, 1}, 301 Comparison{CmpSize8 | CmpConst, 0xc0dec0dec0de0000, 0xc0dec0dec0de1000, 3}, 302 Comparison{CmpSize4 | CmpConst, 0xc0de0000, 0xc0de1000, 1}, 303 Comparison{CmpSize4 | CmpConst, 0xc0de0011, 0xc0de1022, 1}, 304 ), 305 Flags: flatrpc.ExecFlagCollectComps, 306 Comps: []*flatrpc.Comparison{ 307 {Pc: 1, Op1: 0x2222222222222222, Op2: 0x1111111111111111, IsConst: true}, 308 {Pc: 2, Op1: 0x4321, Op2: 0xffffffffffffabcd, IsConst: true}, 309 {Pc: 3, Op1: 0xc0dec0dec0de1000, Op2: 0xc0dec0dec0de0000, IsConst: true}, 310 }, 311 }, 312 // Test max signal. 313 { 314 Is64Bit: true, 315 Input: makeCover64(0xc0dec0dec0000001, 0xc0dec0dec0000010, 0xc0dec0dec0000002, 316 0xc0dec0dec0000100, 0xc0dec0dec0001000), 317 MaxSignal: []uint64{0xc0dec0dec0000001, 0xc0dec0dec0000013, 0xc0dec0dec0000abc}, 318 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 319 Cover: []uint64{0xc0dec0dec0000001, 0xc0dec0dec0000010, 0xc0dec0dec0000002, 320 0xc0dec0dec0000100, 0xc0dec0dec0001000}, 321 Signal: []uint64{0xc0dec0dec0001100, 0xc0dec0dec0000102}, 322 }, 323 { 324 Is64Bit: false, 325 Input: makeCover32(0xc0000001, 0xc0000010, 0xc0000002, 0xc0000100, 0xc0001000), 326 MaxSignal: []uint64{0xc0000001, 0xc0000013, 0xc0000abc}, 327 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 328 Cover: []uint64{0xc0000001, 0xc0000010, 0xc0000002, 0xc0000100, 0xc0001000}, 329 Signal: []uint64{0xc0001100, 0xc0000102}, 330 }, 331 { 332 Is64Bit: true, 333 Input: makeCover64(0xc0dec0dec0000001, 0xc0dec0dec0000010, 0xc0dec0dec0000002, 334 0xc0dec0dec0000100, 0xc0dec0dec0001000), 335 MaxSignal: []uint64{0xc0dec0dec0000001, 0xc0dec0dec0000013, 0xc0dec0dec0000abc}, 336 ReturnAllSignal: true, 337 Flags: flatrpc.ExecFlagCollectSignal, 338 Signal: []uint64{0xc0dec0dec0001100, 0xc0dec0dec0000102, 0xc0dec0dec0000012, 339 0xc0dec0dec0000011, 0xc0dec0dec0000001}, 340 }, 341 // Test cover filter. 342 { 343 Is64Bit: true, 344 Input: makeCover64(0xc0dec0dec0000001, 0xc0dec0dec0000010, 0xc0dec0dec0000020, 345 0xc0dec0dec0000040, 0xc0dec0dec0000100, 0xc0dec0dec0001000, 0xc0dec0dec0002000), 346 CoverFilter: []uint64{0xc0dec0dec0000002, 0xc0dec0dec0000100}, 347 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 348 Cover: []uint64{0xc0dec0dec0000001, 0xc0dec0dec0000010, 0xc0dec0dec0000020, 0xc0dec0dec0000040, 349 0xc0dec0dec0000100, 0xc0dec0dec0001000, 0xc0dec0dec0002000}, 350 Signal: []uint64{0xc0dec0dec0001100, 0xc0dec0dec0000140, 0xc0dec0dec0000011, 0xc0dec0dec0000001}, 351 }, 352 { 353 Is64Bit: false, 354 Input: makeCover32(0xc0000001, 0xc0000010, 0xc0000020, 0xc0000040, 355 0xc0000100, 0xc0001000, 0xc0002000), 356 CoverFilter: []uint64{0xc0000002, 0xc0000100}, 357 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 358 Cover: []uint64{0xc0000001, 0xc0000010, 0xc0000020, 0xc0000040, 359 0xc0000100, 0xc0001000, 0xc0002000}, 360 Signal: []uint64{0xc0001100, 0xc0000140, 0xc0000011, 0xc0000001}, 361 }, 362 // Extra coverage. 363 { 364 Is64Bit: true, 365 ExtraCoverage: true, 366 Input: makeCover64(0xc0dec0dec0000001, 0xc0dec0dec0000010), 367 Flags: flatrpc.ExecFlagCollectSignal | flatrpc.ExecFlagCollectCover, 368 Cover: []uint64{0xc0dec0dec0000001, 0xc0dec0dec0000010}, 369 Signal: []uint64{0xc0dec0dec0000011, 0xc0dec0dec0000001}, 370 }, 371 } 372 executor := csource.BuildExecutor(t, target, "../../") 373 for i, test := range tests { 374 t.Run(fmt.Sprint(i), func(t *testing.T) { 375 t.Parallel() 376 source := queue.Plain() 377 vmArch := targets.TestArch32 378 if test.Is64Bit { 379 vmArch = targets.TestArch64 380 } 381 sysTarget := targets.Get(targets.TestOS, vmArch) 382 if sysTarget.BrokenCompiler != "" { 383 t.Skipf("skipping due to broken compiler:\n%v", sysTarget.BrokenCompiler) 384 } 385 ctx := startRPCServer(t, target, executor, source, rpcParams{ 386 vmArch: vmArch, 387 maxSignal: test.MaxSignal, 388 coverFilter: test.CoverFilter, 389 }) 390 testCover1(t, ctx, target, test, source) 391 }) 392 } 393 } 394 395 func testCover1(t *testing.T, ctx context.Context, target *prog.Target, test CoverTest, source *queue.PlainQueue) { 396 callName := "syz_inject_cover" 397 if test.ExtraCoverage { 398 callName = "syz_inject_remote_cover" 399 } 400 text := fmt.Sprintf(`%s(&AUTO="%s", AUTO)`, callName, hex.EncodeToString(test.Input)) 401 p, err := target.Deserialize([]byte(text), prog.Strict) 402 if err != nil { 403 t.Fatal(err) 404 } 405 req := &queue.Request{ 406 Prog: p, 407 ExecOpts: flatrpc.ExecOpts{ 408 EnvFlags: flatrpc.ExecEnvSignal | flatrpc.ExecEnvExtraCover | flatrpc.ExecEnvSandboxNone, 409 ExecFlags: test.Flags, 410 }, 411 } 412 if test.ReturnAllSignal { 413 req.ReturnAllSignal = []int{0} 414 } 415 source.Submit(req) 416 res := req.Wait(ctx) 417 if res.Err != nil || res.Info == nil || len(res.Info.Calls) != 1 || res.Info.Calls[0] == nil { 418 t.Fatalf("program execution failed: status=%v err=%v\n%s", res.Status, res.Err, res.Output) 419 } 420 call := res.Info.Calls[0] 421 if test.ExtraCoverage { 422 call = res.Info.Extra 423 if call == nil { 424 t.Fatalf("got no extra coverage info") 425 } 426 } 427 if test.Cover == nil { 428 test.Cover = []uint64{} 429 } 430 if test.Signal == nil { 431 test.Signal = []uint64{} 432 } 433 assert.Equal(t, test.Cover, call.Cover) 434 assert.Equal(t, test.Signal, call.Signal) 435 // Comparisons are reordered and order does not matter, so compare without order. 436 assert.ElementsMatch(t, test.Comps, call.Comps) 437 } 438 439 func makeCover64(pcs ...uint64) []byte { 440 w := new(bytes.Buffer) 441 binary.Write(w, binary.NativeEndian, uint64(len(pcs))) 442 for _, pc := range pcs { 443 binary.Write(w, binary.NativeEndian, pc) 444 } 445 return w.Bytes() 446 } 447 448 func makeCover32(pcs ...uint32) []byte { 449 w := new(bytes.Buffer) 450 binary.Write(w, binary.NativeEndian, uint32(len(pcs))) 451 for _, pc := range pcs { 452 binary.Write(w, binary.NativeEndian, pc) 453 } 454 return w.Bytes() 455 } 456 457 func makeComps(comps ...Comparison) []byte { 458 w := new(bytes.Buffer) 459 binary.Write(w, binary.NativeEndian, uint64(len(comps))) 460 for _, cmp := range comps { 461 binary.Write(w, binary.NativeEndian, cmp) 462 } 463 return w.Bytes() 464 } 465 466 type rpcParams struct { 467 manyProcs bool 468 vmArch string 469 vmType string 470 maxSignal []uint64 471 coverFilter []uint64 472 machineChecked func(features flatrpc.Feature) 473 } 474 475 func startRPCServer(t *testing.T, target *prog.Target, executor string, 476 source queue.Source, extra rpcParams) context.Context { 477 dir, err := os.MkdirTemp("", "syz-runtest") 478 if err != nil { 479 t.Fatal(err) 480 } 481 ctx, done := context.WithCancel(context.Background()) 482 483 procs := runtime.GOMAXPROCS(0) 484 if !extra.manyProcs { 485 // We don't need many procs for this test. 486 procs = min(procs, 4) 487 } 488 var output bytes.Buffer 489 cfg := &rpcserver.LocalConfig{ 490 Config: rpcserver.Config{ 491 Config: vminfo.Config{ 492 Target: target, 493 VMType: extra.vmType, 494 Cover: true, 495 Debug: *flagDebug, 496 Features: flatrpc.AllFeatures, 497 Sandbox: flatrpc.ExecEnvSandboxNone, 498 }, 499 VMArch: extra.vmArch, 500 Procs: procs, 501 Slowdown: 10, // to deflake slower tests 502 DebugTimeouts: true, 503 }, 504 Executor: executor, 505 Dir: dir, 506 GDB: *flagGDB, 507 MaxSignal: extra.maxSignal, 508 CoverFilter: extra.coverFilter, 509 // Note that when *flagGDB is set, the option is ignored. 510 OutputWriter: &output, 511 } 512 cfg.MachineChecked = func(features flatrpc.Feature, syscalls map[*prog.Syscall]bool) queue.Source { 513 if extra.machineChecked != nil { 514 extra.machineChecked(features) 515 } 516 return source 517 } 518 errc := make(chan error) 519 go func() { 520 err := rpcserver.RunLocal(ctx, cfg) 521 done() 522 errc <- err 523 }() 524 t.Cleanup(func() { 525 done() 526 if err := <-errc; err != nil { 527 t.Logf("executor output:\n%s", output.String()) 528 t.Fatal(err) 529 } 530 // We need to retry b/c we don't wait for all executor subprocesses (only set PR_SET_PDEATHSIG), 531 // so t.TempDir() leads to episodic "directory not empty" failures. 532 for i := 0; ; i++ { 533 if err := os.RemoveAll(dir); err == nil { 534 break 535 } 536 if i < 100 { 537 time.Sleep(100 * time.Millisecond) 538 continue 539 } 540 t.Logf("executor output:\n%s", output.String()) 541 t.Fatalf("failed to remove temp dir %v: %v", dir, err) 542 } 543 }) 544 return ctx 545 } 546 547 func TestParsing(t *testing.T) { 548 t.Parallel() 549 // Test only one target in race mode (we have gazillion of auto-generated Linux test). 550 raceTarget := targets.Get(targets.TestOS, targets.TestArch64) 551 for OS, arches := range targets.List { 552 if testutil.RaceEnabled && OS != raceTarget.OS { 553 continue 554 } 555 dir := filepath.Join("..", "..", "sys", OS, "test") 556 if !osutil.IsExist(dir) { 557 continue 558 } 559 files, err := progFileList(dir, "") 560 if err != nil { 561 t.Fatal(err) 562 } 563 for arch := range arches { 564 if testutil.RaceEnabled && arch != raceTarget.Arch { 565 continue 566 } 567 target, err := prog.GetTarget(OS, arch) 568 if err != nil { 569 t.Fatal(err) 570 } 571 sysTarget := targets.Get(target.OS, target.Arch) 572 t.Run(fmt.Sprintf("%v/%v", target.OS, target.Arch), func(t *testing.T) { 573 t.Parallel() 574 for _, file := range files { 575 // syz_mount_image tests are very large and this test takes too long. 576 // syz-imagegen that generates does some of this testing (Deserialize/SerializeForExec). 577 requires := map[string]bool{"manual": false} 578 p, _, _, err := parseProg(target, dir, file, requires) 579 if err != nil { 580 t.Errorf("failed to parse %v: %v", file, err) 581 } 582 if p == nil { 583 continue 584 } 585 if runtime.GOOS != sysTarget.BuildOS { 586 continue // we need at least preprocessor binary to generate sources 587 } 588 if _, err = csource.Write(p, csource.ExecutorOpts); err != nil { 589 t.Errorf("failed to generate C source for %v: %v", file, err) 590 } 591 } 592 }) 593 } 594 } 595 }