github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/testutil/testutil.go (about)

     1  // Copyright 2022 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 testutil
     5  
     6  import (
     7  	"math/rand"
     8  	"os"
     9  	"reflect"
    10  	"strconv"
    11  	"testing"
    12  	"testing/quick"
    13  	"time"
    14  )
    15  
    16  func IterCount() int {
    17  	iters := 1000
    18  	if testing.Short() {
    19  		iters /= 10
    20  	}
    21  	if RaceEnabled {
    22  		iters /= 10
    23  	}
    24  	return iters
    25  }
    26  
    27  func RandSource(t *testing.T) rand.Source {
    28  	seed := time.Now().UnixNano()
    29  	if fixed := os.Getenv("SYZ_SEED"); fixed != "" {
    30  		seed, _ = strconv.ParseInt(fixed, 0, 64)
    31  	}
    32  	if os.Getenv("CI") != "" {
    33  		seed = 0 // required for deterministic coverage reports
    34  	}
    35  	t.Logf("seed=%v", seed)
    36  	return rand.NewSource(seed)
    37  }
    38  
    39  func RandMountImage(r *rand.Rand) []byte {
    40  	const maxLen = 1 << 20 // 1 MB.
    41  	len := r.Intn(maxLen)
    42  	slice := make([]byte, len)
    43  	r.Read(slice)
    44  	return slice
    45  }
    46  
    47  // RandValue creates a random value of the same type as the argument typ.
    48  // It recursively fills structs/slices/maps similar to testing/quick.Value,
    49  // but it handles time.Time as well w/o panicing (unfortunately testing/quick panics on time.Time).
    50  func RandValue(t *testing.T, typ any) any {
    51  	return randValue(t, rand.New(RandSource(t)), reflect.TypeOf(typ)).Interface()
    52  }
    53  
    54  func randValue(t *testing.T, rnd *rand.Rand, typ reflect.Type) reflect.Value {
    55  	v := reflect.New(typ).Elem()
    56  	switch typ.Kind() {
    57  	default:
    58  		ok := false
    59  		v, ok = quick.Value(typ, rnd)
    60  		if !ok {
    61  			t.Fatalf("failed to generate random value of type %v", typ)
    62  		}
    63  	case reflect.Slice:
    64  		size := rand.Intn(4)
    65  		v.Set(reflect.MakeSlice(typ, size, size))
    66  		fallthrough
    67  	case reflect.Array:
    68  		for i := 0; i < v.Len(); i++ {
    69  			v.Index(i).Set(randValue(t, rnd, typ.Elem()))
    70  		}
    71  	case reflect.Struct:
    72  		if typ.String() == "time.Time" {
    73  			v = reflect.ValueOf(time.UnixMilli(rnd.Int63()))
    74  		} else {
    75  			for i := 0; i < v.NumField(); i++ {
    76  				v.Field(i).Set(randValue(t, rnd, typ.Field(i).Type))
    77  			}
    78  		}
    79  	case reflect.Pointer:
    80  		v.SetZero()
    81  		if rand.Intn(2) == 0 {
    82  			v.Set(reflect.New(typ.Elem()))
    83  			v.Elem().Set(randValue(t, rnd, typ.Elem()))
    84  		}
    85  	case reflect.Map:
    86  		v.Set(reflect.MakeMap(typ))
    87  		for i := rand.Intn(4); i > 0; i-- {
    88  			v.SetMapIndex(randValue(t, rnd, typ.Key()), randValue(t, rnd, typ.Elem()))
    89  		}
    90  	}
    91  	return v
    92  }
    93  
    94  type Writer struct {
    95  	testing.TB
    96  }
    97  
    98  func (w *Writer) Write(data []byte) (int, error) {
    99  	w.TB.Logf("%s", data)
   100  	return len(data), nil
   101  }