github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/prog/prio_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 prog 5 6 import ( 7 "math/rand" 8 "reflect" 9 "testing" 10 11 "github.com/google/syzkaller/pkg/testutil" 12 ) 13 14 func TestNormalizePrios(t *testing.T) { 15 prios := [][]int32{ 16 {2, 2, 2}, 17 {1, 2, 4}, 18 {1, 2, 0}, 19 } 20 want := [][]int32{ 21 {10, 10, 10}, 22 {4, 8, 17}, 23 {10, 20, 0}, 24 } 25 t.Logf("had: %+v", prios) 26 normalizePrios(prios) 27 if !reflect.DeepEqual(prios, want) { 28 t.Logf("got: %+v", prios) 29 t.Errorf("want: %+v", want) 30 } 31 } 32 33 // Test static priorities assigned based on argument direction. 34 func TestStaticPriorities(t *testing.T) { 35 target := initTargetTest(t, "linux", "amd64") 36 rs := rand.NewSource(0) 37 // The test is probabilistic and needs some sensible number of iterations to succeed. 38 // If it fails try to increase the number a bit. 39 const iters = 2e5 40 // The first call is the one that creates a resource and the rest are calls that can use that resource. 41 tests := [][]string{ 42 {"open", "read", "write", "mmap"}, 43 {"socket", "listen", "setsockopt"}, 44 } 45 ct := target.DefaultChoiceTable() 46 r := rand.New(rs) 47 for _, syscalls := range tests { 48 // Counts the number of times a call is chosen after a call that creates a resource (referenceCall). 49 counter := make(map[string]int) 50 referenceCall := syscalls[0] 51 for _, call := range syscalls { 52 count := 0 53 for it := 0; it < iters; it++ { 54 chosenCall := target.Syscalls[ct.choose(r, target.SyscallMap[call].ID)].Name 55 if call == referenceCall { 56 counter[chosenCall]++ 57 } else if chosenCall == referenceCall { 58 count++ 59 } 60 } 61 if call == referenceCall { 62 continue 63 } 64 // Checks that prio[callCreatesRes][callUsesRes] > prio[callUsesRes][callCreatesRes] 65 if count >= counter[call] { 66 t.Fatalf("too high priority for %s -> %s: %d vs %s -> %s: %d", 67 call, referenceCall, count, referenceCall, call, counter[call]) 68 } 69 } 70 } 71 } 72 73 func TestPrioDeterminism(t *testing.T) { 74 if testutil.RaceEnabled { 75 t.Skip("skipping in race mode, too slow") 76 } 77 target, rs, iters := initTest(t) 78 ct := target.DefaultChoiceTable() 79 var corpus []*Prog 80 for i := 0; i < 100; i++ { 81 corpus = append(corpus, target.Generate(rs, 10, ct)) 82 } 83 ct0 := target.BuildChoiceTable(corpus, nil) 84 ct1 := target.BuildChoiceTable(corpus, nil) 85 if !reflect.DeepEqual(ct0.runs, ct1.runs) { 86 t.Fatal("non-deterministic ChoiceTable") 87 } 88 for i := 0; i < iters; i++ { 89 seed := rs.Int63() 90 call0 := ct0.choose(rand.New(rand.NewSource(seed)), -1) 91 call1 := ct1.choose(rand.New(rand.NewSource(seed)), -1) 92 if call0 != call1 { 93 t.Fatalf("seed=%v iter=%v call=%v/%v", seed, i, call0, call1) 94 } 95 } 96 }