Skip to content

Commit

Permalink
Improve testing of alloc bounded slices. (algorand#2515)
Browse files Browse the repository at this point in the history
This change is needed in order to support codec types such as the following:
```golang
//msgp:allocbound typeA 16
type typeA []typeB
```
since we want the codec object randomizer to recognize that `typeA` has a allocbound defined, and use that bound.
( this would be used in the feature/txnsync branch, but the change doesn't really related to any of the other changes in the feature/txnsync branch and would be a good change regardless )
  • Loading branch information
tsachiherman authored Jul 12, 2021
1 parent da26ca7 commit 10e91da
Showing 1 changed file with 38 additions and 26 deletions.
64 changes: 38 additions & 26 deletions protocol/codec_tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,14 @@ func RandomizeObject(template interface{}) (interface{}, error) {
if tt.Kind() != reflect.Ptr {
return nil, fmt.Errorf("RandomizeObject: must be ptr")
}

v := reflect.New(tt.Elem())
err := randomizeValue(v.Elem(), tt.String(), "")
hasAllocBound := checkBoundsLimitingTag(v.Elem(), v.Elem().Type().Name(), "codec:\",\"", false)
pseudoTag := ""
if hasAllocBound {
// we emulate a pseudo tag here on an item that has a alloc bound msgp directive.
pseudoTag = "codec:\",allocbound=1\""
}
err := randomizeValue(v.Elem(), tt.String(), pseudoTag)
return v.Interface(), err
}

Expand Down Expand Up @@ -90,7 +95,31 @@ func printWarning(warnMsg string) {
var testedDatatypesForAllocBound = map[string]bool{}
var testedDatatypesForAllocBoundMu = deadlock.Mutex{}

func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string) (hasAllocBound bool) {
func checkMsgpAllocBoundDirective(dataType reflect.Type) bool {
// does any of the go files in the package directory has the msgp:allocbound defined for that datatype ?
gopath := os.Getenv("GOPATH")
packageFilesPath := path.Join(gopath, "src", dataType.PkgPath())
packageFiles := []string{}
filepath.Walk(packageFilesPath, func(path string, info os.FileInfo, err error) error {
if filepath.Ext(path) == ".go" {
packageFiles = append(packageFiles, path)
}
return nil
})
for _, packageFile := range packageFiles {
fileBytes, err := ioutil.ReadFile(packageFile)
if err != nil {
continue
}
if strings.Index(string(fileBytes), fmt.Sprintf("msgp:allocbound %s", dataType.Name())) != -1 {
// message pack alloc bound definition was found.
return true
}
}
return false
}

func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string, warnMissingAllocBound bool) (hasAllocBound bool) {
if structTag == "" {
return
}
Expand Down Expand Up @@ -132,28 +161,11 @@ func checkBoundsLimitingTag(val reflect.Value, datapath string, structTag string

if val.Type().Name() != "" {
// does any of the go files in the package directory has the msgp:allocbound defined for that datatype ?
gopath := os.Getenv("GOPATH")
packageFilesPath := path.Join(gopath, "src", val.Type().PkgPath())
packageFiles := []string{}
filepath.Walk(packageFilesPath, func(path string, info os.FileInfo, err error) error {
if filepath.Ext(path) == ".go" {
packageFiles = append(packageFiles, path)
}
return nil
})
for _, packageFile := range packageFiles {
fileBytes, err := ioutil.ReadFile(packageFile)
if err != nil {
continue
}
if strings.Index(string(fileBytes), fmt.Sprintf("msgp:allocbound %s", val.Type().Name())) != -1 {
// message pack alloc bound definition was found.
hasAllocBound = true
return
}
}
hasAllocBound = checkMsgpAllocBoundDirective(val.Type())
}
if warnMissingAllocBound {
printWarning(fmt.Sprintf("%s %s does not have an allocbound defined - %s", objType, datapath, val.Type().PkgPath()))
}
printWarning(fmt.Sprintf("%s %s does not have an allocbound defined - %s", objType, datapath, val.Type().PkgPath()))
return
}

Expand Down Expand Up @@ -201,7 +213,7 @@ func randomizeValue(v reflect.Value, datapath string, tag string) error {
}
}
case reflect.Slice:
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag)
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag, true)
l := rand.Int() % 32
if hasAllocBound {
l = 1
Expand All @@ -217,7 +229,7 @@ func randomizeValue(v reflect.Value, datapath string, tag string) error {
case reflect.Bool:
v.SetBool(rand.Uint32()%2 == 0)
case reflect.Map:
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag)
hasAllocBound := checkBoundsLimitingTag(v, datapath, tag, true)
mt := v.Type()
v.Set(reflect.MakeMap(mt))
l := rand.Int() % 32
Expand Down

0 comments on commit 10e91da

Please sign in to comment.