| package mapstructure |
| |
| import ( |
| "encoding/json" |
| "testing" |
| ) |
| |
| func Benchmark_Decode(b *testing.B) { |
| type Person struct { |
| Name string |
| Age int |
| Emails []string |
| Extra map[string]string |
| } |
| |
| input := map[string]interface{}{ |
| "name": "Mitchell", |
| "age": 91, |
| "emails": []string{"one", "two", "three"}, |
| "extra": map[string]string{ |
| "twitter": "mitchellh", |
| }, |
| } |
| |
| var result Person |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |
| |
| // decodeViaJSON takes the map data and passes it through encoding/json to convert it into the |
| // given Go native structure pointed to by v. v must be a pointer to a struct. |
| func decodeViaJSON(data interface{}, v interface{}) error { |
| // Perform the task by simply marshalling the input into JSON, |
| // then unmarshalling it into target native Go struct. |
| b, err := json.Marshal(data) |
| if err != nil { |
| return err |
| } |
| return json.Unmarshal(b, v) |
| } |
| |
| func Benchmark_DecodeViaJSON(b *testing.B) { |
| type Person struct { |
| Name string |
| Age int |
| Emails []string |
| Extra map[string]string |
| } |
| |
| input := map[string]interface{}{ |
| "name": "Mitchell", |
| "age": 91, |
| "emails": []string{"one", "two", "three"}, |
| "extra": map[string]string{ |
| "twitter": "mitchellh", |
| }, |
| } |
| |
| var result Person |
| for i := 0; i < b.N; i++ { |
| decodeViaJSON(input, &result) |
| } |
| } |
| |
| func Benchmark_DecodeBasic(b *testing.B) { |
| input := map[string]interface{}{ |
| "vstring": "foo", |
| "vint": 42, |
| "Vuint": 42, |
| "vbool": true, |
| "Vfloat": 42.42, |
| "vsilent": true, |
| "vdata": 42, |
| } |
| |
| var result Basic |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |
| |
| func Benchmark_DecodeEmbedded(b *testing.B) { |
| input := map[string]interface{}{ |
| "vstring": "foo", |
| "Basic": map[string]interface{}{ |
| "vstring": "innerfoo", |
| }, |
| "vunique": "bar", |
| } |
| |
| var result Embedded |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |
| |
| func Benchmark_DecodeTypeConversion(b *testing.B) { |
| input := map[string]interface{}{ |
| "IntToFloat": 42, |
| "IntToUint": 42, |
| "IntToBool": 1, |
| "IntToString": 42, |
| "UintToInt": 42, |
| "UintToFloat": 42, |
| "UintToBool": 42, |
| "UintToString": 42, |
| "BoolToInt": true, |
| "BoolToUint": true, |
| "BoolToFloat": true, |
| "BoolToString": true, |
| "FloatToInt": 42.42, |
| "FloatToUint": 42.42, |
| "FloatToBool": 42.42, |
| "FloatToString": 42.42, |
| "StringToInt": "42", |
| "StringToUint": "42", |
| "StringToBool": "1", |
| "StringToFloat": "42.42", |
| "SliceToMap": []interface{}{}, |
| "MapToSlice": map[string]interface{}{}, |
| } |
| |
| var resultStrict TypeConversionResult |
| for i := 0; i < b.N; i++ { |
| Decode(input, &resultStrict) |
| } |
| } |
| |
| func Benchmark_DecodeMap(b *testing.B) { |
| input := map[string]interface{}{ |
| "vfoo": "foo", |
| "vother": map[interface{}]interface{}{ |
| "foo": "foo", |
| "bar": "bar", |
| }, |
| } |
| |
| var result Map |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |
| |
| func Benchmark_DecodeMapOfStruct(b *testing.B) { |
| input := map[string]interface{}{ |
| "value": map[string]interface{}{ |
| "foo": map[string]string{"vstring": "one"}, |
| "bar": map[string]string{"vstring": "two"}, |
| }, |
| } |
| |
| var result MapOfStruct |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |
| |
| func Benchmark_DecodeSlice(b *testing.B) { |
| input := map[string]interface{}{ |
| "vfoo": "foo", |
| "vbar": []string{"foo", "bar", "baz"}, |
| } |
| |
| var result Slice |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |
| |
| func Benchmark_DecodeSliceOfStruct(b *testing.B) { |
| input := map[string]interface{}{ |
| "value": []map[string]interface{}{ |
| {"vstring": "one"}, |
| {"vstring": "two"}, |
| }, |
| } |
| |
| var result SliceOfStruct |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |
| |
| func Benchmark_DecodeWeaklyTypedInput(b *testing.B) { |
| type Person struct { |
| Name string |
| Age int |
| Emails []string |
| } |
| |
| // This input can come from anywhere, but typically comes from |
| // something like decoding JSON, generated by a weakly typed language |
| // such as PHP. |
| input := map[string]interface{}{ |
| "name": 123, // number => string |
| "age": "42", // string => number |
| "emails": map[string]interface{}{}, // empty map => empty array |
| } |
| |
| var result Person |
| config := &DecoderConfig{ |
| WeaklyTypedInput: true, |
| Result: &result, |
| } |
| |
| decoder, err := NewDecoder(config) |
| if err != nil { |
| panic(err) |
| } |
| |
| for i := 0; i < b.N; i++ { |
| decoder.Decode(input) |
| } |
| } |
| |
| func Benchmark_DecodeMetadata(b *testing.B) { |
| type Person struct { |
| Name string |
| Age int |
| } |
| |
| input := map[string]interface{}{ |
| "name": "Mitchell", |
| "age": 91, |
| "email": "foo@bar.com", |
| } |
| |
| var md Metadata |
| var result Person |
| config := &DecoderConfig{ |
| Metadata: &md, |
| Result: &result, |
| } |
| |
| decoder, err := NewDecoder(config) |
| if err != nil { |
| panic(err) |
| } |
| |
| for i := 0; i < b.N; i++ { |
| decoder.Decode(input) |
| } |
| } |
| |
| func Benchmark_DecodeMetadataEmbedded(b *testing.B) { |
| input := map[string]interface{}{ |
| "vstring": "foo", |
| "vunique": "bar", |
| } |
| |
| var md Metadata |
| var result EmbeddedSquash |
| config := &DecoderConfig{ |
| Metadata: &md, |
| Result: &result, |
| } |
| |
| decoder, err := NewDecoder(config) |
| if err != nil { |
| b.Fatalf("err: %s", err) |
| } |
| |
| for i := 0; i < b.N; i++ { |
| decoder.Decode(input) |
| } |
| } |
| |
| func Benchmark_DecodeTagged(b *testing.B) { |
| input := map[string]interface{}{ |
| "foo": "bar", |
| "bar": "value", |
| } |
| |
| var result Tagged |
| for i := 0; i < b.N; i++ { |
| Decode(input, &result) |
| } |
| } |