1package mapstructure 2 3import "testing" 4 5// GH-1 6func TestDecode_NilValue(t *testing.T) { 7 input := map[string]interface{}{ 8 "vfoo": nil, 9 "vother": nil, 10 } 11 12 var result Map 13 err := Decode(input, &result) 14 if err != nil { 15 t.Fatalf("should not error: %s", err) 16 } 17 18 if result.Vfoo != "" { 19 t.Fatalf("value should be default: %s", result.Vfoo) 20 } 21 22 if result.Vother != nil { 23 t.Fatalf("Vother should be nil: %s", result.Vother) 24 } 25} 26 27// GH-10 28func TestDecode_mapInterfaceInterface(t *testing.T) { 29 input := map[interface{}]interface{}{ 30 "vfoo": nil, 31 "vother": nil, 32 } 33 34 var result Map 35 err := Decode(input, &result) 36 if err != nil { 37 t.Fatalf("should not error: %s", err) 38 } 39 40 if result.Vfoo != "" { 41 t.Fatalf("value should be default: %s", result.Vfoo) 42 } 43 44 if result.Vother != nil { 45 t.Fatalf("Vother should be nil: %s", result.Vother) 46 } 47} 48 49// #48 50func TestNestedTypePointerWithDefaults(t *testing.T) { 51 t.Parallel() 52 53 input := map[string]interface{}{ 54 "vfoo": "foo", 55 "vbar": map[string]interface{}{ 56 "vstring": "foo", 57 "vint": 42, 58 "vbool": true, 59 }, 60 } 61 62 result := NestedPointer{ 63 Vbar: &Basic{ 64 Vuint: 42, 65 }, 66 } 67 err := Decode(input, &result) 68 if err != nil { 69 t.Fatalf("got an err: %s", err.Error()) 70 } 71 72 if result.Vfoo != "foo" { 73 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) 74 } 75 76 if result.Vbar.Vstring != "foo" { 77 t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring) 78 } 79 80 if result.Vbar.Vint != 42 { 81 t.Errorf("vint value should be 42: %#v", result.Vbar.Vint) 82 } 83 84 if result.Vbar.Vbool != true { 85 t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool) 86 } 87 88 if result.Vbar.Vextra != "" { 89 t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra) 90 } 91 92 // this is the error 93 if result.Vbar.Vuint != 42 { 94 t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint) 95 } 96 97} 98 99type NestedSlice struct { 100 Vfoo string 101 Vbars []Basic 102 Vempty []Basic 103} 104 105// #48 106func TestNestedTypeSliceWithDefaults(t *testing.T) { 107 t.Parallel() 108 109 input := map[string]interface{}{ 110 "vfoo": "foo", 111 "vbars": []map[string]interface{}{ 112 {"vstring": "foo", "vint": 42, "vbool": true}, 113 {"vint": 42, "vbool": true}, 114 }, 115 "vempty": []map[string]interface{}{ 116 {"vstring": "foo", "vint": 42, "vbool": true}, 117 {"vint": 42, "vbool": true}, 118 }, 119 } 120 121 result := NestedSlice{ 122 Vbars: []Basic{ 123 {Vuint: 42}, 124 {Vstring: "foo"}, 125 }, 126 } 127 err := Decode(input, &result) 128 if err != nil { 129 t.Fatalf("got an err: %s", err.Error()) 130 } 131 132 if result.Vfoo != "foo" { 133 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) 134 } 135 136 if result.Vbars[0].Vstring != "foo" { 137 t.Errorf("vstring value should be 'foo': %#v", result.Vbars[0].Vstring) 138 } 139 // this is the error 140 if result.Vbars[0].Vuint != 42 { 141 t.Errorf("vuint value should be 42: %#v", result.Vbars[0].Vuint) 142 } 143} 144 145// #48 workaround 146func TestNestedTypeWithDefaults(t *testing.T) { 147 t.Parallel() 148 149 input := map[string]interface{}{ 150 "vfoo": "foo", 151 "vbar": map[string]interface{}{ 152 "vstring": "foo", 153 "vint": 42, 154 "vbool": true, 155 }, 156 } 157 158 result := Nested{ 159 Vbar: Basic{ 160 Vuint: 42, 161 }, 162 } 163 err := Decode(input, &result) 164 if err != nil { 165 t.Fatalf("got an err: %s", err.Error()) 166 } 167 168 if result.Vfoo != "foo" { 169 t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) 170 } 171 172 if result.Vbar.Vstring != "foo" { 173 t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring) 174 } 175 176 if result.Vbar.Vint != 42 { 177 t.Errorf("vint value should be 42: %#v", result.Vbar.Vint) 178 } 179 180 if result.Vbar.Vbool != true { 181 t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool) 182 } 183 184 if result.Vbar.Vextra != "" { 185 t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra) 186 } 187 188 // this is the error 189 if result.Vbar.Vuint != 42 { 190 t.Errorf("vuint value should be 42: %#v", result.Vbar.Vuint) 191 } 192 193} 194 195// #67 panic() on extending slices (decodeSlice with disabled ZeroValues) 196func TestDecodeSliceToEmptySliceWOZeroing(t *testing.T) { 197 t.Parallel() 198 199 type TestStruct struct { 200 Vfoo []string 201 } 202 203 decode := func(m interface{}, rawVal interface{}) error { 204 config := &DecoderConfig{ 205 Metadata: nil, 206 Result: rawVal, 207 ZeroFields: false, 208 } 209 210 decoder, err := NewDecoder(config) 211 if err != nil { 212 return err 213 } 214 215 return decoder.Decode(m) 216 } 217 218 { 219 input := map[string]interface{}{ 220 "vfoo": []string{"1"}, 221 } 222 223 result := &TestStruct{} 224 225 err := decode(input, &result) 226 if err != nil { 227 t.Fatalf("got an err: %s", err.Error()) 228 } 229 } 230 231 { 232 input := map[string]interface{}{ 233 "vfoo": []string{"1"}, 234 } 235 236 result := &TestStruct{ 237 Vfoo: []string{}, 238 } 239 240 err := decode(input, &result) 241 if err != nil { 242 t.Fatalf("got an err: %s", err.Error()) 243 } 244 } 245 246 { 247 input := map[string]interface{}{ 248 "vfoo": []string{"2", "3"}, 249 } 250 251 result := &TestStruct{ 252 Vfoo: []string{"1"}, 253 } 254 255 err := decode(input, &result) 256 if err != nil { 257 t.Fatalf("got an err: %s", err.Error()) 258 } 259 } 260} 261