diff --git a/go.mod b/go.mod index f53d59d..551168b 100644 --- a/go.mod +++ b/go.mod @@ -65,6 +65,7 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/oklog/run v1.0.0 // indirect + github.com/onsi/gomega v1.30.0 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/posener/complete v1.2.3 // indirect github.com/russross/blackfriday v1.6.0 // indirect diff --git a/go.sum b/go.sum index 4721641..3bb7032 100644 --- a/go.sum +++ b/go.sum @@ -192,6 +192,8 @@ github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmt github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= diff --git a/internal/valueutil/string.go b/internal/valueutil/string.go index 324a485..e14a850 100644 --- a/internal/valueutil/string.go +++ b/internal/valueutil/string.go @@ -3,6 +3,7 @@ package valueutil import ( "fmt" "github.com/hashicorp/terraform-plugin-framework/types" + "reflect" ) func StringOrNull[T string](s T) types.String { @@ -20,8 +21,24 @@ func StringPtrOrNull[T ~string](s *T) types.String { } func StringerOrNull(s fmt.Stringer) types.String { - if s == nil { + if isReallyNil(s) { return types.StringNull() } return types.StringValue(s.String()) } + +func isReallyNil(v any) bool { + if v == nil { + return true + } + + rv := reflect.ValueOf(v) + switch rv.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return rv.IsNil() + case reflect.Array: + return rv.Len() == 0 + default: + return false + } +} diff --git a/internal/valueutil/string_test.go b/internal/valueutil/string_test.go new file mode 100644 index 0000000..03d9399 --- /dev/null +++ b/internal/valueutil/string_test.go @@ -0,0 +1,31 @@ +package valueutil + +import ( + "github.com/google/uuid" + . "github.com/onsi/gomega" + "testing" +) + +func TestStringerOrNullAcceptsStringer(t *testing.T) { + g := NewWithT(t) + u := uuid.New() + s := StringerOrNull(u) + + g.Expect(s.IsNull()).To(BeFalse()) + g.Expect(s.ValueString()).To(Equal(u.String())) +} + +func TestStringerOrNullAcceptsNil(t *testing.T) { + g := NewWithT(t) + s := StringerOrNull(nil) + + g.Expect(s.IsNull()).To(BeTrue()) +} + +func TestStringerOrNullAcceptsNilInterface(t *testing.T) { + g := NewWithT(t) + u := (*uuid.UUID)(nil) + s := StringerOrNull(u) + + g.Expect(s.IsNull()).To(BeTrue()) +}