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  }