280 lines
5.3 KiB
Go
280 lines
5.3 KiB
Go
|
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)
|
||
|
}
|
||
|
}
|