github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/pkg/fuzzer/job_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 fuzzer 5 6 import ( 7 "testing" 8 9 "github.com/google/syzkaller/pkg/fuzzer/queue" 10 "github.com/google/syzkaller/pkg/ipc" 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 TestDeflakeFail(t *testing.T) { 18 target, err := prog.GetTarget(targets.TestOS, targets.TestArch64Fuzz) 19 if err != nil { 20 t.Fatal(err) 21 } 22 prog, err := target.Deserialize([]byte(anyTestProg), prog.NonStrict) 23 assert.NoError(t, err) 24 25 testJob := &triageJob{ 26 p: prog, 27 info: ipc.CallInfo{}, 28 newSignal: signal.FromRaw([]uint32{0, 1, 2, 3, 4}, 0), 29 } 30 31 run := 0 32 ret, stop := testJob.deflake(func(_ *queue.Request, _ ProgTypes) *queue.Result { 33 run++ 34 // For first, we return 0 and 1. For second, 1 and 2. And so on. 35 return fakeResult(0, []uint32{uint32(run), uint32(run + 1)}, []uint32{10, 20}) 36 }, nil, false) 37 assert.False(t, stop) 38 assert.Equal(t, 5, run) 39 assert.Empty(t, ret.stableSignal.ToRaw()) 40 assert.Empty(t, ret.newStableSignal.ToRaw()) 41 } 42 43 func TestDeflakeSuccess(t *testing.T) { 44 target, err := prog.GetTarget(targets.TestOS, targets.TestArch64Fuzz) 45 if err != nil { 46 t.Fatal(err) 47 } 48 prog, err := target.Deserialize([]byte(anyTestProg), prog.NonStrict) 49 assert.NoError(t, err) 50 51 testJob := &triageJob{ 52 p: prog, 53 info: ipc.CallInfo{}, 54 newSignal: signal.FromRaw([]uint32{0, 1, 2}, 0), 55 } 56 run := 0 57 ret, stop := testJob.deflake(func(_ *queue.Request, _ ProgTypes) *queue.Result { 58 run++ 59 switch run { 60 case 1: 61 return fakeResult(0, []uint32{0, 2, 4, 6, 8}, []uint32{10, 20}) 62 case 2: 63 // This one should be ignored -- it has a different errno. 64 return fakeResult(1, []uint32{0, 1, 2}, []uint32{100}) 65 case 3: 66 return fakeResult(0, []uint32{0, 2, 4, 6, 8}, []uint32{20, 30}) 67 case 4: 68 return fakeResult(0, []uint32{0, 2, 6}, []uint32{30, 40}) 69 } 70 // We expect it to have finished earlier. 71 t.Fatal("only 4 runs were expected") 72 return nil 73 }, nil, false) 74 assert.False(t, stop) 75 // Cover is a union of all coverages. 76 assert.ElementsMatch(t, []uint32{10, 20, 30, 40}, ret.cover.Serialize()) 77 // 0, 2, 6 were in three resuls. 78 assert.ElementsMatch(t, []uint32{0, 2, 6}, ret.stableSignal.ToRaw()) 79 // 0, 2 were also in newSignal. 80 assert.ElementsMatch(t, []uint32{0, 2}, ret.newStableSignal.ToRaw()) 81 } 82 83 func fakeResult(errno int, signal, cover []uint32) *queue.Result { 84 return &queue.Result{ 85 Info: &ipc.ProgInfo{ 86 Calls: []ipc.CallInfo{ 87 { 88 Errno: errno, 89 Signal: signal, 90 Cover: cover, 91 }, 92 }, 93 }, 94 } 95 }