diff options
Diffstat (limited to 'model/utils.go')
-rw-r--r-- | model/utils.go | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/model/utils.go b/model/utils.go index 72369852b..2d61b49f6 100644 --- a/model/utils.go +++ b/model/utils.go @@ -15,9 +15,11 @@ import ( "net/http" "net/mail" "net/url" + "reflect" "regexp" "strconv" "strings" + "testing" "time" "unicode" @@ -469,3 +471,60 @@ func IsValidId(value string) bool { return true } + +// checkNowhereNil checks that the given interface value is not nil, and if a struct, that all of +// its public fields are also nowhere nil +func checkNowhereNil(t *testing.T, name string, value interface{}) bool { + if value == nil { + return false + } + + v := reflect.ValueOf(value) + switch v.Type().Kind() { + case reflect.Ptr: + if v.IsNil() { + t.Logf("%s was nil", name) + return false + } + + return checkNowhereNil(t, fmt.Sprintf("(*%s)", name), v.Elem().Interface()) + + case reflect.Map: + if v.IsNil() { + t.Logf("%s was nil", name) + return false + } + + // Don't check map values + return true + + case reflect.Struct: + nowhereNil := true + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + // Ignore unexported fields + if v.Type().Field(i).PkgPath != "" { + continue + } + + nowhereNil = nowhereNil && checkNowhereNil(t, fmt.Sprintf("%s.%s", name, v.Type().Field(i).Name), f.Interface()) + } + + return nowhereNil + + case reflect.Array: + fallthrough + case reflect.Chan: + fallthrough + case reflect.Func: + fallthrough + case reflect.Interface: + fallthrough + case reflect.UnsafePointer: + t.Logf("unhandled field %s, type: %s", name, v.Type().Kind()) + return false + + default: + return true + } +} |