github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/prog/rotation_test.go (about) 1 // Copyright 2019 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 "bytes" 8 "fmt" 9 "math/rand" 10 "sort" 11 "testing" 12 13 "github.com/google/go-cmp/cmp" 14 ) 15 16 func TestRotationResourceless(t *testing.T) { 17 target, rs, _ := initRandomTargetTest(t, "test", "64") 18 calls := map[*Syscall]bool{ 19 target.SyscallMap["test$int"]: true, 20 } 21 got := MakeRotator(target, calls, rand.New(rs)).Select() 22 if diff := cmp.Diff(calls, got); diff != "" { 23 t.Fatal(diff) 24 } 25 } 26 27 func TestRotationRandom(t *testing.T) { 28 target, rs, _ := initTest(t) 29 for _, ncalls := range []int{10, 100, 1000, 1e9} { 30 rnd := rand.New(rand.NewSource(rs.Int63())) 31 t.Run(fmt.Sprint(ncalls), func(t *testing.T) { 32 t.Parallel() 33 calls0 := selectCalls(target, rnd, ncalls) 34 calls := MakeRotator(target, calls0, rnd).Select() 35 for call := range calls { 36 if !calls0[call] { 37 t.Errorf("selected disabled syscall %v", call.Name) 38 } 39 } 40 buf := new(bytes.Buffer) 41 var array []*Syscall 42 for call := range calls { 43 array = append(array, call) 44 } 45 sort.Slice(array, func(i, j int) bool { 46 return array[i].Name < array[j].Name 47 }) 48 for _, call := range array { 49 fmt.Fprintf(buf, "%v\n", call.Name) 50 } 51 t.Logf("calls %v->%v:\n%s", len(calls0), len(calls), buf.Bytes()) 52 }) 53 } 54 } 55 56 func TestRotationCoverage(t *testing.T) { 57 target, rs, _ := initTest(t) 58 calls := make(map[*Syscall]bool) 59 counters := make(map[string]int) 60 for _, call := range target.Syscalls { 61 if call.Attrs.Disabled || call.Attrs.Automatic { 62 continue 63 } 64 calls[call] = true 65 counters[call.Name] = 0 66 } 67 rotator := MakeRotator(target, calls, rand.New(rs)) 68 nextIter: 69 for iter := 0; iter < 1e4; iter++ { 70 for call := range rotator.Select() { 71 counters[call.Name]++ 72 } 73 for _, count := range counters { 74 if count == 0 { 75 continue nextIter 76 } 77 } 78 break 79 } 80 type pair struct { 81 name string 82 count int 83 } 84 var pairs []pair 85 remain := len(counters) 86 for name, count := range counters { 87 pairs = append(pairs, pair{name, count}) 88 if count != 0 { 89 remain-- 90 } 91 } 92 sort.Slice(pairs, func(i, j int) bool { 93 if pairs[i].count != pairs[j].count { 94 return pairs[i].count > pairs[j].count 95 } 96 return pairs[i].name < pairs[j].name 97 }) 98 for i, pair := range pairs { 99 t.Logf("# %4d: % 4d %v", i, pair.count, pair.name) 100 } 101 if remain != 0 { 102 t.Fatalf("uncovered syscalls: %v", remain) 103 } 104 } 105 106 func selectCalls(target *Target, rnd *rand.Rand, ncalls int) map[*Syscall]bool { 107 retry: 108 calls := make(map[*Syscall]bool) 109 for _, call := range target.Syscalls { 110 calls[call] = true 111 } 112 for { 113 for { 114 remove := 0 115 switch { 116 case len(calls) > ncalls+1000: 117 remove = 100 118 case len(calls) > ncalls+50: 119 remove = 20 120 case len(calls) > ncalls: 121 remove = 1 122 default: 123 return calls 124 } 125 var array []*Syscall 126 for call := range calls { 127 array = append(array, call) 128 } 129 sort.Slice(array, func(i, j int) bool { 130 return array[i].ID < array[j].ID 131 }) 132 rnd.Shuffle(len(calls), func(i, j int) { 133 array[i], array[j] = array[j], array[i] 134 }) 135 for _, call := range array[:remove] { 136 delete(calls, call) 137 } 138 calls, _ = target.transitivelyEnabled(calls) 139 if len(calls) == 0 { 140 goto retry 141 } 142 } 143 } 144 } 145 146 func TestRotationDeterminism(t *testing.T) { 147 target, rs, _ := initTest(t) 148 calls := make(map[*Syscall]bool) 149 for _, call := range target.Syscalls { 150 calls[call] = true 151 } 152 seed := rs.Int63() 153 rnd0 := rand.New(rand.NewSource(seed)) 154 calls0 := MakeRotator(target, calls, rnd0).Select() 155 rnd1 := rand.New(rand.NewSource(seed)) 156 calls1 := MakeRotator(target, calls, rnd1).Select() 157 if diff := cmp.Diff(calls0, calls1); diff != "" { 158 t.Fatal(diff) 159 } 160 }