mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 11:08:10 +00:00
New helper methods for generating readable loggable strings (#20911)
This commit is contained in:
81
sdk/helper/testhelpers/output.go
Normal file
81
sdk/helper/testhelpers/output.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package testhelpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-testing-interface"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToMap renders an input value of any type as a map. This is intended for
|
||||||
|
// logging human-readable data dumps in test logs, so it uses the `json`
|
||||||
|
// tags on struct fields: this makes it easy to exclude `"-"` values that
|
||||||
|
// are typically not interesting, respect omitempty, etc.
|
||||||
|
//
|
||||||
|
// We also replace any []byte fields with a hash of their value.
|
||||||
|
// This is usually sufficient for test log purposes, and is a lot more readable
|
||||||
|
// than a big array of individual byte values like Go would normally stringify a
|
||||||
|
// byte slice.
|
||||||
|
func ToMap(in any) (map[string]any, error) {
|
||||||
|
temp := make(map[string]any)
|
||||||
|
cfg := &mapstructure.DecoderConfig{
|
||||||
|
TagName: "json",
|
||||||
|
IgnoreUntaggedFields: true,
|
||||||
|
Result: &temp,
|
||||||
|
}
|
||||||
|
md, err := mapstructure.NewDecoder(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = md.Decode(in)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapstructure doesn't call the DecodeHook for each field when doing
|
||||||
|
// struct->map conversions, but it does for map->map, so call it a second
|
||||||
|
// time to convert each []byte field.
|
||||||
|
out := make(map[string]any)
|
||||||
|
md2, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||||
|
Result: &out,
|
||||||
|
DecodeHook: func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
|
||||||
|
if from.Kind() != reflect.Slice || from.Elem().Kind() != reflect.Uint8 {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
b := data.([]byte)
|
||||||
|
return fmt.Sprintf("%x", sha256.Sum256(b)), nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = md2.Decode(temp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString renders its input using ToMap, and returns a string containing the
|
||||||
|
// result or an error if that fails.
|
||||||
|
func ToString(in any) string {
|
||||||
|
m, err := ToMap(in)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v", m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringOrDie renders its input using ToMap, and returns a string containing the
|
||||||
|
// result. If rendering yields an error, calls t.Fatal.
|
||||||
|
func StringOrDie(t testing.T, in any) string {
|
||||||
|
t.Helper()
|
||||||
|
m, err := ToMap(in)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v", m)
|
||||||
|
}
|
||||||
45
sdk/helper/testhelpers/output_test.go
Normal file
45
sdk/helper/testhelpers/output_test.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package testhelpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestToMap(t *testing.T) {
|
||||||
|
type s struct {
|
||||||
|
A string `json:"a"`
|
||||||
|
B []byte `json:"b"`
|
||||||
|
C map[string]string `json:"c"`
|
||||||
|
D string `json:"-"`
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
in s
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic",
|
||||||
|
args: args{s{A: "a", B: []byte("bytes"), C: map[string]string{"k": "v"}, D: "d"}},
|
||||||
|
want: "map[a:a b:277089d91c0bdf4f2e6862ba7e4a07605119431f5d13f726dd352b06f1b206a9 c:map[k:v]]",
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m, err := ToMap(&tt.args.in)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ToMap() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
got := fmt.Sprintf("%s", m)
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("ToMap() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user