github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/corpus/corpus_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 corpus 5 6 import ( 7 "context" 8 "math/rand" 9 "testing" 10 11 "github.com/google/syzkaller/pkg/signal" 12 "github.com/google/syzkaller/prog" 13 "github.com/google/syzkaller/sys/targets" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func TestCorpusOperation(t *testing.T) { 18 // Basic corpus functionality. 19 target := getTarget(t, targets.TestOS, targets.TestArch64) 20 ch := make(chan NewItemEvent) 21 corpus := NewMonitoredCorpus(context.Background(), ch) 22 23 // First program is saved. 24 rs := rand.NewSource(0) 25 inp1 := generateInput(target, rs, 5, 5) 26 go corpus.Save(inp1) 27 event := <-ch 28 progData := inp1.Prog.Serialize() 29 assert.Equal(t, progData, event.ProgData) 30 assert.Equal(t, false, event.Exists) 31 32 // Second program is saved for every its call. 33 inp2 := generateInput(target, rs, 5, 5) 34 progData = inp2.Prog.Serialize() 35 for i := 0; i < 5; i++ { 36 inp2.Call = i 37 go corpus.Save(inp2) 38 event := <-ch 39 assert.Equal(t, progData, event.ProgData) 40 assert.Equal(t, i != 0, event.Exists) 41 } 42 43 // Verify that we can query corpus items. 44 items := corpus.Items() 45 assert.Len(t, items, 2) 46 for _, item := range items { 47 assert.Equal(t, item, corpus.Item(item.Sig)) 48 } 49 50 // Verify the total signal. 51 assert.Equal(t, corpus.StatSignal.Val(), 5) 52 assert.Equal(t, corpus.StatCover.Val(), 0) 53 assert.Equal(t, corpus.StatProgs.Val(), 2) 54 55 corpus.Minimize(true) 56 } 57 58 func TestCorpusCoverage(t *testing.T) { 59 target := getTarget(t, targets.TestOS, targets.TestArch64) 60 ch := make(chan NewItemEvent) 61 corpus := NewMonitoredCorpus(context.Background(), ch) 62 rs := rand.NewSource(0) 63 64 inp := generateInput(target, rs, 5, 5) 65 inp.Cover = []uint32{10, 11} 66 go corpus.Save(inp) 67 event := <-ch 68 assert.Equal(t, []uint32{10, 11}, event.NewCover) 69 70 inp.Call = 1 71 inp.Cover = []uint32{11, 12} 72 go corpus.Save(inp) 73 event = <-ch 74 assert.Equal(t, []uint32{12}, event.NewCover) 75 76 // Check the total corpus size. 77 assert.Equal(t, corpus.StatCover.Val(), 3) 78 } 79 80 func TestCorpusSaveConcurrency(t *testing.T) { 81 target := getTarget(t, targets.TestOS, targets.TestArch64) 82 corpus := NewCorpus(context.Background()) 83 84 const ( 85 routines = 10 86 iters = 100 87 ) 88 89 for i := 0; i < routines; i++ { 90 go func() { 91 rs := rand.NewSource(0) 92 r := rand.New(rs) 93 for it := 0; it < iters; it++ { 94 inp := generateInput(target, rs, 10, it) 95 corpus.Save(inp) 96 corpus.ChooseProgram(r).Clone() 97 } 98 }() 99 } 100 } 101 102 func generateInput(target *prog.Target, rs rand.Source, ncalls, sizeSig int) NewInput { 103 p := target.Generate(rs, ncalls, target.DefaultChoiceTable()) 104 var raw []uint32 105 for i := 1; i <= sizeSig; i++ { 106 raw = append(raw, uint32(i)) 107 } 108 return NewInput{ 109 Prog: p, 110 Call: int(rs.Int63() % int64(len(p.Calls))), 111 Signal: signal.FromRaw(raw, 0), 112 } 113 } 114 115 func getTarget(t *testing.T, os, arch string) *prog.Target { 116 t.Parallel() 117 target, err := prog.GetTarget(os, arch) 118 if err != nil { 119 t.Fatal(err) 120 } 121 return target 122 }