1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-18 05:18:24 +02:00

Add helper for finding uninitialized config (#2534)

Add helper for finding uninitialized config
This commit is contained in:
Marcus Holl 2021-01-25 12:58:43 +01:00 committed by GitHub
parent 7bdbed3d65
commit ee7279c8fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 0 deletions

View File

@ -0,0 +1,49 @@
package validation
import (
"fmt"
"reflect"
"strings"
)
// FindEmptyStringsInConfigStruct finds empty strings in a struct.
// In case the struct contains other nested structs, these struct are also checked.
func FindEmptyStringsInConfigStruct(v interface{}) ([]string, error) {
emptyStrings := []string{}
if reflect.ValueOf(v).Kind() != reflect.Struct {
return emptyStrings, fmt.Errorf("'%v' (%T) is not a struct", v, v)
}
err := findNestedEmptyStrings(v, &emptyStrings, []string{})
return emptyStrings, err
}
func findNestedEmptyStrings(v interface{}, emptyStrings *[]string, prefix []string) error {
fields := reflect.TypeOf(v)
values := reflect.ValueOf(v)
for i := 0; i < fields.NumField(); i++ {
switch values.Field(i).Kind() {
case reflect.String:
if len(values.Field(i).String()) == 0 {
*emptyStrings = append(*emptyStrings, strings.Join(append(prefix, fields.Field(i).Name), "."))
}
case reflect.Struct:
err := findNestedEmptyStrings(values.Field(i).Interface(), emptyStrings, append(prefix, fields.Field(i).Name))
if err != nil {
return err
}
case reflect.Int:
case reflect.Int32:
case reflect.Int64:
case reflect.Bool:
case reflect.Slice:
// in case someone needs more types these types can be added here
default:
return fmt.Errorf("unexpected type '%v' of field: '%v', value: '%v'",
values.Field(i).Kind(),
fields.Field(i).Name,
values.Field(i),
)
}
}
return nil
}

View File

@ -0,0 +1,64 @@
package validation
import (
"github.com/stretchr/testify/assert"
"testing"
)
type Connection struct {
Endpoint string
User string
Password string
}
type Dummy struct {
Connection Connection
Prop1 string
Prop2 string
Prop3 string
Bool1 bool
Int1 int64
List []string
}
func TestWeProvideNotAStruct(t *testing.T) {
_, err := FindEmptyStringsInConfigStruct("Hello World")
assert.EqualError(t, err, "'Hello World' (string) is not a struct")
}
func TestUnsupportedType(t *testing.T) {
type DummyWithUnsupportedType struct {
Dummy
NotExpected float32
}
_, err := FindEmptyStringsInConfigStruct(DummyWithUnsupportedType{})
assert.EqualError(t, err, "unexpected type 'float32' of field: 'NotExpected', value: '0'")
}
func TestFindEmptyStringsInConfig(t *testing.T) {
myStruct := Dummy{
Connection: Connection{
Endpoint: "<set>",
User: "",
Password: "<set>",
},
Prop1: "<set>",
Prop2: "", // this is empty
// Prop3: "this is missing intentionally"
Bool1: false,
Int1: 42,
List: []string{"1", "2"},
}
emptyStrings, err := FindEmptyStringsInConfigStruct(myStruct)
if assert.NoError(t, err) {
assert.Len(t, emptyStrings, 3)
assert.Subset(t, emptyStrings, []string{
"Connection.User", // empty value, nested
"Prop2", // empty value
"Prop3", // missing value
})
}
}