github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/corpus/prio_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"
     9  	"math/rand"
    10  	"testing"
    11  
    12  	"github.com/google/syzkaller/prog"
    13  	"github.com/google/syzkaller/sys/targets"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestChooseProgram(t *testing.T) {
    18  	rs := rand.NewSource(0)
    19  	r := rand.New(rs)
    20  	target := getTarget(t, targets.TestOS, targets.TestArch64)
    21  	corpus := NewCorpus(context.Background())
    22  
    23  	const (
    24  		maxIters   = 1000
    25  		sizeCorpus = 1000
    26  		eps        = 0.01
    27  	)
    28  
    29  	priorities := make(map[*prog.Prog]int64)
    30  	for i := 0; i < sizeCorpus; i++ {
    31  		sizeSig := i + 1
    32  		if sizeSig%250 == 0 {
    33  			sizeSig = 0
    34  		}
    35  		inp := generateInput(target, rs, sizeSig)
    36  		corpus.Save(inp)
    37  		priorities[inp.Prog] = int64(len(inp.Signal))
    38  	}
    39  	counters := make(map[*prog.Prog]int)
    40  	for it := 0; it < maxIters; it++ {
    41  		counters[corpus.chooseProgram(r)]++
    42  	}
    43  	for p, prio := range priorities {
    44  		prob := float64(prio) / float64(corpus.sumPrios)
    45  		diff := math.Abs(prob*maxIters - float64(counters[p]))
    46  		if diff > eps*maxIters {
    47  			t.Fatalf("the difference (%f) is higher than %f%%", diff, eps*100)
    48  		}
    49  	}
    50  }
    51  
    52  func TestFocusAreas(t *testing.T) {
    53  	target := getTarget(t, targets.TestOS, targets.TestArch64)
    54  	corpus := NewFocusedCorpus(context.Background(), nil, []FocusArea{
    55  		{
    56  			CoverPCs: map[uint64]struct{}{
    57  				0: {},
    58  				1: {},
    59  				2: {},
    60  			},
    61  			Weight: 10,
    62  		},
    63  		{
    64  			CoverPCs: map[uint64]struct{}{
    65  				2: {},
    66  				3: {},
    67  			},
    68  			Weight: 30,
    69  		},
    70  		{
    71  			CoverPCs: map[uint64]struct{}{
    72  				4: {},
    73  				5: {},
    74  			},
    75  			Weight: 60,
    76  		},
    77  	})
    78  
    79  	rs := rand.NewSource(0)
    80  
    81  	fillGroup := func(from, to, count int) map[*prog.Prog]bool {
    82  		ret := map[*prog.Prog]bool{}
    83  		for i := 0; i < count; i++ {
    84  			a := from + i%(to-from+1)
    85  			b := a + i%(to-a+1)
    86  			inp := generateRangedInput(target, rs, a, b)
    87  			ret[inp.Prog] = true
    88  			corpus.Save(inp)
    89  		}
    90  		return ret
    91  	}
    92  
    93  	first := fillGroup(0, 1, 10)
    94  	second := fillGroup(2, 3, 10)
    95  	third := fillGroup(4, 5, 10)
    96  
    97  	rnd := rand.New(rs)
    98  	different := map[*prog.Prog]bool{}
    99  	firstCount, secondCount, thirdCount := 0, 0, 0
   100  	const TOTAL = 10000
   101  	for i := 0; i < TOTAL; i++ {
   102  		p := corpus.ChooseProgram(rnd)
   103  		different[p] = true
   104  
   105  		if first[p] {
   106  			firstCount++
   107  		} else if second[p] {
   108  			secondCount++
   109  		} else if third[p] {
   110  			thirdCount++
   111  		}
   112  	}
   113  
   114  	assert.Greater(t, len(different), 25)
   115  	// These must be proportional to the focus area weight distribution.
   116  	assert.InDelta(t, firstCount, TOTAL*0.1, TOTAL/25)
   117  	assert.InDelta(t, secondCount, TOTAL*0.3, TOTAL/25)
   118  	assert.InDelta(t, thirdCount, TOTAL*0.6, TOTAL/25)
   119  }