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