dehub/typeobj/typeobj_test.go
mediocregopher 9bfd012221 Add 'default' tag functionality to typeobj
message: |-
  Add 'default' tag functionality to typeobj

  Adding "default" to a typeobj tag now makes that field the default one to use if
  there's not a type field set in the input data. This is necessary because all
  the old commit objects in this repo don't have a type field set, but they will
  need to default to "commit".
change_hash: AP+DSWWe9K0wnnEV1wNt3u/Q89tEOf35zZGWjdES/d2t
credentials:
- type: pgp_signature
  pub_key_id: 95C46FA6A41148AC
  body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl5gOgkACgkQlcRvpqQRSKxG7hAAsWbbW+Vb7zmD3m32sQYQSY2e8OAClLGAB5tjWURp/bhFJUXf2T2aMPTPW4wNztQM2OgzcsIlAvFWRl8I/rUa9L04U/vvcA7vo03KYLLjTjqz6HEkeTg5is8gF/jJDdt7YBFpXJVaUu9b2hInpo87iyfsRYfxF832huvCrVxftd3eQcF/l33sWakwlc539M7UZ6V/kED2FQ0X8bhiOXCFrBrsb5cpedyNcdnFclOKk++y71pMoVU4r1Jm57i+f7HInxnFl7hm7Z82clgzYTPgr0Da43OB1RR/LOzTzPqHA/e9TUx/TSWd2Zu/MTdNiFRhNoMz0SdxXcXw805HGqoIK1s3pHiiaeujgFtnFWYuvnqQ5H7rOjf3lr+ig3pi9qsBR+/upOfw4iIP590OGC+JOu51PGe9NkOyRFi49j6j8BtFXxIVk49znMgqd242hOxh17u7LCHW/YS2nZVdFqoQZCNlpEJRuM18XvJ1c9bkulFNd4rkXEExEhedFEIm8fFWM04VwVbdimvRO4/YfU6MzPi/T/5hGhd1Gmauk/TwpQyoEsw/VDZU600uz0YVt2XnsoSRPcfcCX1uYjaYhrKadddCwuLpl8hvtWwd8EIaIfq6vcUVeBLxX53xb3mlo48wDOYDz7v3MJO/oKzoSLui/wAT/5fOoFVs6XT9F8AmhlM=
  account: mediocregopher
2020-03-04 16:30:24 -07:00

157 lines
3.7 KiB
Go

package typeobj
import (
"reflect"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
"gopkg.in/yaml.v2"
)
type foo struct {
A int `yaml:"a"`
}
type bar struct {
B int `yaml:"b"`
}
type outer struct {
Foo foo `type:"foo"`
Bar *bar `type:"bar"`
Other string `yaml:"other_field,omitempty"`
}
func (o outer) MarshalYAML() (interface{}, error) {
return MarshalYAML(o)
}
func (o *outer) UnmarshalYAML(unmarshal func(interface{}) error) error {
return UnmarshalYAML(o, unmarshal)
}
type outerWDefault struct {
Foo foo `type:"foo,default"`
Bar *bar `type:"bar"`
}
func (o outerWDefault) MarshalYAML() (interface{}, error) {
return MarshalYAML(o)
}
func (o *outerWDefault) UnmarshalYAML(unmarshal func(interface{}) error) error {
return UnmarshalYAML(o, unmarshal)
}
func TestTypeObj(t *testing.T) {
type test struct {
descr string
str string
expErr string
expObj interface{}
expTypeTag string
expElem interface{}
expMarshalOut string // defaults to str
}
tests := []test{
{
descr: "no type set",
str: `{}`,
expErr: "type field not set",
expObj: outer{},
},
{
descr: "no type set with nontype field",
str: `other_field: aaa`,
expErr: "type field not set",
expObj: outer{},
},
{
descr: "no type set with default",
str: `a: 1`,
expObj: outerWDefault{Foo: foo{A: 1}},
expTypeTag: "foo",
expElem: foo{A: 1},
expMarshalOut: "type: foo\na: 1",
},
{
descr: "invalid type value",
str: "type: baz",
expErr: "invalid type value",
expObj: outer{},
},
{
descr: "foo set",
str: "type: foo\na: 1",
expObj: outer{Foo: foo{A: 1}},
expTypeTag: "foo",
expElem: foo{A: 1},
},
{
descr: "bar set",
str: "type: bar\nb: 1",
expObj: outer{Bar: &bar{B: 1}},
expTypeTag: "bar",
expElem: &bar{B: 1},
},
{
descr: "foo and other_field set",
str: "type: foo\na: 1\nother_field: aaa",
expObj: outer{Foo: foo{A: 1}, Other: "aaa"},
expTypeTag: "foo",
expElem: foo{A: 1},
},
}
for _, test := range tests {
t.Run(test.descr, func(t *testing.T) {
intoV := reflect.New(reflect.TypeOf(test.expObj))
err := yaml.Unmarshal([]byte(test.str), intoV.Interface())
if test.expErr != "" {
if err == nil || !strings.HasPrefix(err.Error(), test.expErr) {
t.Fatalf("expected error %q when unmarshaling but got: %v", test.expErr, err)
}
return
} else if test.expErr == "" && err != nil {
t.Fatalf("unmarshaling %q returned unexpected error: %v", test.str, err)
}
into := intoV.Elem().Interface()
if !reflect.DeepEqual(into, test.expObj) {
t.Fatalf("test expected value:\n%s\nbut got value:\n%s", spew.Sprint(test.expObj), spew.Sprint(into))
}
elem, typeTag, err := Element(into)
if err != nil {
t.Fatalf("error when calling Element(%s): %v", spew.Sprint(into), err)
} else if !reflect.DeepEqual(elem, test.expElem) {
t.Fatalf("test expected elem value:\n%s\nbut got value:\n%s", spew.Sprint(test.expElem), spew.Sprint(elem))
} else if typeTag != test.expTypeTag {
t.Fatalf("test expected typeTag value %q but got %q", test.expTypeTag, typeTag)
}
expMarshalOut := test.expMarshalOut
if expMarshalOut == "" {
expMarshalOut = test.str
}
expMarshalOut = strings.TrimSpace(expMarshalOut)
b, err := yaml.Marshal(into)
if err != nil {
t.Fatalf("error marshaling %s: %v", spew.Sprint(into), err)
}
marshalOut := strings.TrimSpace(string(b))
if marshalOut != expMarshalOut {
t.Fatalf("test expected to marshal to %q, but instead marshaled to %q", expMarshalOut, marshalOut)
}
})
}
}