github.com/benma/gogen@v0.0.0-20160826115606-cf49914b915a/unmarshalmap/testunmarshalmap/test.go (about) 1 package testunmarshalmap 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "reflect" 8 "strconv" 9 "strings" 10 "testing" 11 ) 12 13 // Debug indicates we should log debugging information 14 var Debug bool 15 16 type unmarshalMapper interface { 17 UnmarshalMap(map[string]interface{}) error 18 } 19 20 // Run tests that UnmarshalMap unmarshalls all fields 21 func Run(t *testing.T, v unmarshalMapper) { 22 // make an empty variable of the same type as v 23 n := empty(t, v) 24 25 // fill the variable with data 26 fill(t, v) 27 28 // generate a map[string]interface{} 29 m := generateMap(t, v) 30 31 // unmarshal generated map into the empty variable 32 n.UnmarshalMap(m) 33 34 if !reflect.DeepEqual(v, n) { 35 t.Fatalf("UnmarshalMap() method from %T out of date. regenerate the code", v) 36 } 37 } 38 39 func empty(t *testing.T, v unmarshalMapper) unmarshalMapper { 40 n := makeNew(t, v) 41 u, ok := n.(unmarshalMapper) 42 if !ok { 43 t.Fatalf("%T should implement UnmarshalMap", n) 44 } 45 return u 46 } 47 48 func generateMap(t *testing.T, v unmarshalMapper) map[string]interface{} { 49 var buf bytes.Buffer 50 err := json.NewEncoder(&buf).Encode(v) 51 if err != nil { 52 t.Fatal(err) 53 } 54 var m map[string]interface{} 55 err = json.NewDecoder(&buf).Decode(&m) 56 if err != nil { 57 t.Fatal(err) 58 } 59 return m 60 } 61 62 func fill(t *testing.T, v interface{}) { 63 val := reflect.ValueOf(v) 64 fillReflect(t, "", val) 65 } 66 67 func makeNew(t *testing.T, v interface{}) interface{} { 68 typ := reflect.TypeOf(v).Elem() 69 val := reflect.New(typ) 70 return val.Interface() 71 } 72 73 func fillReflect(t *testing.T, scope string, val reflect.Value) { 74 if val.Kind() == reflect.Ptr { 75 val = val.Elem() 76 } 77 typ := val.Type() 78 if !val.IsValid() { 79 t.Fatalf("invalid") 80 } 81 if Debug { 82 t.Logf("%s %s", scope, typ.Kind()) 83 } 84 85 for i := 0; i < typ.NumField(); i++ { 86 f := typ.Field(i) 87 // Skip omitted fields 88 if tag := strings.Split(f.Tag.Get("json"), ","); len(tag) > 0 && tag[0] == "-" { 89 continue 90 } 91 if Debug { 92 t.Logf("%s%s %s", scope, f.Name, f.Type.Kind()) 93 } 94 v := val.Field(i) 95 fillValue(t, scope+f.Name+".", v) 96 } 97 } 98 99 func fillValue(t *testing.T, scope string, v reflect.Value) { 100 kind := v.Type().Kind() 101 if kind == reflect.Ptr { 102 v.Set(reflect.New(v.Type().Elem())) 103 v = v.Elem() 104 kind = v.Kind() 105 } 106 switch kind { 107 case reflect.Ptr: 108 t.Fatalf("%s should have been de-referenced", scope) 109 case reflect.Interface, reflect.Chan, reflect.Func, reflect.Complex64, reflect.Complex128, reflect.Uintptr: 110 t.Fatalf("%s cannot unmarshall %s", scope, kind) 111 case reflect.Bool: 112 v.SetBool(true) 113 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 114 v.SetInt(newInt()) 115 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 116 v.SetUint(newUint()) 117 case reflect.Float32, reflect.Float64: 118 v.SetFloat(newFloat()) 119 case reflect.Array: 120 l := v.Cap() 121 for i := 0; i < l; i++ { 122 fillValue(t, fmt.Sprintf("%s[%d].", scope, i), v.Index(i)) 123 } 124 case reflect.Slice: 125 l := int(newInt())/2 + 1 126 s := reflect.MakeSlice(v.Type(), l, l) 127 v.Set(s) 128 for i := 0; i < l; i++ { 129 fillValue(t, fmt.Sprintf("%s[%d].", scope, i), s.Index(i)) 130 } 131 // case reflect.Map: 132 // t.Fatalf("%s unmarshalling maps is still pending", scope) 133 case reflect.String: 134 v.SetString(newStr()) 135 case reflect.Struct: 136 fillReflect(t, scope, v) 137 default: 138 t.Fatalf("gounmarshalmap is missing support for %s unmarshalling", kind) 139 } 140 } 141 142 var i uint64 143 144 func newInt() int64 { 145 i++ 146 return int64(i) 147 } 148 149 func newFloat() float64 { 150 i++ 151 return float64(i) 152 } 153 154 func newUint() uint64 { 155 i++ 156 return i 157 } 158 159 func newStr() string { 160 i++ 161 return strconv.FormatInt(int64(i), 10) 162 }