Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions agreement/persistence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,19 @@ func BenchmarkAgreementPersistenceRecovery(b *testing.B) {
}
}

const randomizedEncodingMaxCollectionLen = 8 // instead of 32 used in codec_tester.go

func randomizeDiskState() (rr rootRouter, p player) {
p2, err := protocol.RandomizeObject(&player{})
opts := []protocol.RandomizeObjectOption{
protocol.RandomizeObjectWithMaxCollectionLen(randomizedEncodingMaxCollectionLen),
protocol.RandomizeObjectSilenceAllocWarnings(),
}
p2, err := protocol.RandomizeObject(&player{}, opts...)
if err != nil {
return
}

rr2, err := protocol.RandomizeObject(&rootRouter{})
rr2, err := protocol.RandomizeObject(&rootRouter{}, opts...)
if err != nil {
return
}
Expand All @@ -200,7 +206,12 @@ func randomizeDiskState() (rr rootRouter, p player) {

func TestRandomizedEncodingFullDiskState(t *testing.T) {
partitiontest.PartitionTest(t)
for i := 0; i < 5000; i++ {
iterations := 1000
if testing.Short() {
iterations = 500
}

for i := 0; i < iterations; i++ {
router, player := randomizeDiskState()
a := []action{}
clock := timers.MakeMonotonicClock[TimeoutType](time.Date(2015, 1, 2, 5, 6, 7, 8, time.UTC))
Expand Down
47 changes: 39 additions & 8 deletions protocol/codec_tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ type randomizeObjectCfg struct {
ZeroesEveryN int
// AllUintSizes will be equally likely to generate 8-bit, 16-bit, 32-bit, or 64-bit uints.
AllUintSizes bool
// MaxCollectionLen bounds randomized slice/map lengths when positive.
MaxCollectionLen int
// SilenceAllocWarnings suppresses allocbound warning prints.
SilenceAllocWarnings bool
}

// RandomizeObjectOption is an option for RandomizeObject
Expand All @@ -69,6 +73,20 @@ func RandomizeObjectWithAllUintSizes() RandomizeObjectOption {
return func(cfg *randomizeObjectCfg) { cfg.AllUintSizes = true }
}

// RandomizeObjectSilenceAllocWarnings silences allocbound warning prints.
func RandomizeObjectSilenceAllocWarnings() RandomizeObjectOption {
return func(cfg *randomizeObjectCfg) { cfg.SilenceAllocWarnings = true }
}

// RandomizeObjectWithMaxCollectionLen limits randomized slice/map lengths to n (when n>0).
func RandomizeObjectWithMaxCollectionLen(n int) RandomizeObjectOption {
return func(cfg *randomizeObjectCfg) {
if n > 0 {
cfg.MaxCollectionLen = n
}
}
}

// RandomizeObject returns a random object of the same type as template
func RandomizeObject(template interface{}, opts ...RandomizeObjectOption) (interface{}, error) {
cfg := randomizeObjectCfg{}
Expand Down Expand Up @@ -185,7 +203,7 @@ func checkMsgpAllocBoundDirective(dataType reflect.Type) bool {
return false
}

func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string) (hasAllocBound bool) {
func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string, cfg randomizeObjectCfg) (hasAllocBound bool) {
var objType string
if val.Kind() == reflect.Slice {
objType = "slice"
Expand All @@ -199,7 +217,9 @@ func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string
tagsMap := parseStructTags(structTag)

if tagsMap["allocbound"] == "-" {
printWarning(fmt.Sprintf("%s %s have an unbounded allocbound defined", objType, datapath))
if !cfg.SilenceAllocWarnings {
printWarning(fmt.Sprintf("%s %s have an unbounded allocbound defined", objType, datapath))
}
return
}

Expand Down Expand Up @@ -234,7 +254,9 @@ func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string
}

if val.Type().Kind() == reflect.Slice || val.Type().Kind() == reflect.Map || val.Type().Kind() == reflect.Array {
printWarning(fmt.Sprintf("%s %s does not have an allocbound defined for %s %s", objType, datapath, val.Type().String(), val.Type().PkgPath()))
if !cfg.SilenceAllocWarnings {
printWarning(fmt.Sprintf("%s %s does not have an allocbound defined for %s %s", objType, datapath, val.Type().String(), val.Type().PkgPath()))
}
}
return
}
Expand Down Expand Up @@ -285,7 +307,7 @@ func randomizeValue(v reflect.Value, depth int, datapath string, tag string, rem
v.SetInt(int64(rand.Uint64()))
*remainingChanges--
case reflect.String:
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag)
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag, cfg)
var buf []byte
var len int
if strings.HasSuffix(v.Type().PkgPath(), "go-algorand/agreement") && v.Type().Name() == "serializableError" {
Expand Down Expand Up @@ -359,9 +381,13 @@ func randomizeValue(v reflect.Value, depth int, datapath string, tag string, rem
case reflect.Slice:
// we don't want to allocate a slice with size of 0. This is because decoding and encoding this slice
// will result in nil and not slice of size 0
l := rand.Int()%31 + 1
maxLen := 31
if cfg.MaxCollectionLen > 0 {
maxLen = min(maxLen, cfg.MaxCollectionLen)
}
l := rand.Intn(maxLen) + 1

hasAllocBound := checkBoundsLimitingTag(v, datapath, tag)
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag, cfg)
if hasAllocBound {
l = 1
}
Expand All @@ -382,10 +408,15 @@ func randomizeValue(v reflect.Value, depth int, datapath string, tag string, rem
v.SetBool(rand.Uint32()%2 == 0)
*remainingChanges--
case reflect.Map:
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag)
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag, cfg)
mt := v.Type()
v.Set(reflect.MakeMap(mt))
l := rand.Int() % 32
maxLen := 32
if cfg.MaxCollectionLen > 0 {
// preserve possibility of zero entries while capping positive lengths
maxLen = min(maxLen, cfg.MaxCollectionLen+1)
}
l := rand.Intn(maxLen)
if hasAllocBound {
l = 1
}
Expand Down
Loading