308 lines
6.0 KiB
Go
308 lines
6.0 KiB
Go
|
// Copyright (C) MongoDB, Inc. 2017-present.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||
|
// not use this file except in compliance with the License. You may obtain
|
||
|
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
package bson
|
||
|
|
||
|
import (
|
||
|
"compress/gzip"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
"path"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
type encodetest struct {
|
||
|
Field1String string
|
||
|
Field1Int64 int64
|
||
|
Field1Float64 float64
|
||
|
Field2String string
|
||
|
Field2Int64 int64
|
||
|
Field2Float64 float64
|
||
|
Field3String string
|
||
|
Field3Int64 int64
|
||
|
Field3Float64 float64
|
||
|
Field4String string
|
||
|
Field4Int64 int64
|
||
|
Field4Float64 float64
|
||
|
}
|
||
|
|
||
|
type nestedtest1 struct {
|
||
|
Nested nestedtest2
|
||
|
}
|
||
|
|
||
|
type nestedtest2 struct {
|
||
|
Nested nestedtest3
|
||
|
}
|
||
|
|
||
|
type nestedtest3 struct {
|
||
|
Nested nestedtest4
|
||
|
}
|
||
|
|
||
|
type nestedtest4 struct {
|
||
|
Nested nestedtest5
|
||
|
}
|
||
|
|
||
|
type nestedtest5 struct {
|
||
|
Nested nestedtest6
|
||
|
}
|
||
|
|
||
|
type nestedtest6 struct {
|
||
|
Nested nestedtest7
|
||
|
}
|
||
|
|
||
|
type nestedtest7 struct {
|
||
|
Nested nestedtest8
|
||
|
}
|
||
|
|
||
|
type nestedtest8 struct {
|
||
|
Nested nestedtest9
|
||
|
}
|
||
|
|
||
|
type nestedtest9 struct {
|
||
|
Nested nestedtest10
|
||
|
}
|
||
|
|
||
|
type nestedtest10 struct {
|
||
|
Nested nestedtest11
|
||
|
}
|
||
|
|
||
|
type nestedtest11 struct {
|
||
|
Nested encodetest
|
||
|
}
|
||
|
|
||
|
var encodetestInstance = encodetest{
|
||
|
Field1String: "foo",
|
||
|
Field1Int64: 1,
|
||
|
Field1Float64: 3.0,
|
||
|
Field2String: "bar",
|
||
|
Field2Int64: 2,
|
||
|
Field2Float64: 3.1,
|
||
|
Field3String: "baz",
|
||
|
Field3Int64: 3,
|
||
|
Field3Float64: 3.14,
|
||
|
Field4String: "qux",
|
||
|
Field4Int64: 4,
|
||
|
Field4Float64: 3.141,
|
||
|
}
|
||
|
|
||
|
var nestedInstance = nestedtest1{
|
||
|
nestedtest2{
|
||
|
nestedtest3{
|
||
|
nestedtest4{
|
||
|
nestedtest5{
|
||
|
nestedtest6{
|
||
|
nestedtest7{
|
||
|
nestedtest8{
|
||
|
nestedtest9{
|
||
|
nestedtest10{
|
||
|
nestedtest11{
|
||
|
encodetest{
|
||
|
Field1String: "foo",
|
||
|
Field1Int64: 1,
|
||
|
Field1Float64: 3.0,
|
||
|
Field2String: "bar",
|
||
|
Field2Int64: 2,
|
||
|
Field2Float64: 3.1,
|
||
|
Field3String: "baz",
|
||
|
Field3Int64: 3,
|
||
|
Field3Float64: 3.14,
|
||
|
Field4String: "qux",
|
||
|
Field4Int64: 4,
|
||
|
Field4Float64: 3.141,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
const extendedBSONDir = "../testdata/extended_bson"
|
||
|
|
||
|
// readExtJSONFile reads the GZIP-compressed extended JSON document from the given filename in the
|
||
|
// "extended BSON" test data directory (../testdata/extended_bson) and returns it as a
|
||
|
// map[string]interface{}. It panics on any errors.
|
||
|
func readExtJSONFile(filename string) map[string]interface{} {
|
||
|
filePath := path.Join(extendedBSONDir, filename)
|
||
|
file, err := os.Open(filePath)
|
||
|
if err != nil {
|
||
|
panic(fmt.Sprintf("error opening file %q: %s", filePath, err))
|
||
|
}
|
||
|
defer func() {
|
||
|
_ = file.Close()
|
||
|
}()
|
||
|
|
||
|
gz, err := gzip.NewReader(file)
|
||
|
if err != nil {
|
||
|
panic(fmt.Sprintf("error creating GZIP reader: %s", err))
|
||
|
}
|
||
|
defer func() {
|
||
|
_ = gz.Close()
|
||
|
}()
|
||
|
|
||
|
data, err := ioutil.ReadAll(gz)
|
||
|
if err != nil {
|
||
|
panic(fmt.Sprintf("error reading GZIP contents of file: %s", err))
|
||
|
}
|
||
|
|
||
|
var v map[string]interface{}
|
||
|
err = UnmarshalExtJSON(data, false, &v)
|
||
|
if err != nil {
|
||
|
panic(fmt.Sprintf("error unmarshalling extended JSON: %s", err))
|
||
|
}
|
||
|
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
func BenchmarkMarshal(b *testing.B) {
|
||
|
cases := []struct {
|
||
|
desc string
|
||
|
value interface{}
|
||
|
}{
|
||
|
{
|
||
|
desc: "simple struct",
|
||
|
value: encodetestInstance,
|
||
|
},
|
||
|
{
|
||
|
desc: "nested struct",
|
||
|
value: nestedInstance,
|
||
|
},
|
||
|
{
|
||
|
desc: "deep_bson.json.gz",
|
||
|
value: readExtJSONFile("deep_bson.json.gz"),
|
||
|
},
|
||
|
{
|
||
|
desc: "flat_bson.json.gz",
|
||
|
value: readExtJSONFile("flat_bson.json.gz"),
|
||
|
},
|
||
|
{
|
||
|
desc: "full_bson.json.gz",
|
||
|
value: readExtJSONFile("full_bson.json.gz"),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, tc := range cases {
|
||
|
b.Run(tc.desc, func(b *testing.B) {
|
||
|
b.Run("BSON", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
_, err := Marshal(tc.value)
|
||
|
if err != nil {
|
||
|
b.Errorf("error marshalling BSON: %s", err)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
b.Run("extJSON", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
_, err := MarshalExtJSON(tc.value, true, false)
|
||
|
if err != nil {
|
||
|
b.Errorf("error marshalling extended JSON: %s", err)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
b.Run("JSON", func(b *testing.B) {
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
_, err := json.Marshal(tc.value)
|
||
|
if err != nil {
|
||
|
b.Errorf("error marshalling JSON: %s", err)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func BenchmarkUnmarshal(b *testing.B) {
|
||
|
cases := []struct {
|
||
|
desc string
|
||
|
value interface{}
|
||
|
}{
|
||
|
{
|
||
|
desc: "simple struct",
|
||
|
value: encodetestInstance,
|
||
|
},
|
||
|
{
|
||
|
desc: "nested struct",
|
||
|
value: nestedInstance,
|
||
|
},
|
||
|
{
|
||
|
desc: "deep_bson.json.gz",
|
||
|
value: readExtJSONFile("deep_bson.json.gz"),
|
||
|
},
|
||
|
{
|
||
|
desc: "flat_bson.json.gz",
|
||
|
value: readExtJSONFile("flat_bson.json.gz"),
|
||
|
},
|
||
|
{
|
||
|
desc: "full_bson.json.gz",
|
||
|
value: readExtJSONFile("full_bson.json.gz"),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, tc := range cases {
|
||
|
b.Run(tc.desc, func(b *testing.B) {
|
||
|
b.Run("BSON", func(b *testing.B) {
|
||
|
data, err := Marshal(tc.value)
|
||
|
if err != nil {
|
||
|
b.Errorf("error marshalling BSON: %s", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
b.ResetTimer()
|
||
|
var v2 map[string]interface{}
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
err := Unmarshal(data, &v2)
|
||
|
if err != nil {
|
||
|
b.Errorf("error unmarshalling BSON: %s", err)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
b.Run("extJSON", func(b *testing.B) {
|
||
|
data, err := MarshalExtJSON(tc.value, true, false)
|
||
|
if err != nil {
|
||
|
b.Errorf("error marshalling extended JSON: %s", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
b.ResetTimer()
|
||
|
var v2 map[string]interface{}
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
err := UnmarshalExtJSON(data, true, &v2)
|
||
|
if err != nil {
|
||
|
b.Errorf("error unmarshalling extended JSON: %s", err)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
b.Run("JSON", func(b *testing.B) {
|
||
|
data, err := json.Marshal(tc.value)
|
||
|
if err != nil {
|
||
|
b.Errorf("error marshalling JSON: %s", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
b.ResetTimer()
|
||
|
var v2 map[string]interface{}
|
||
|
for i := 0; i < b.N; i++ {
|
||
|
err := json.Unmarshal(data, &v2)
|
||
|
if err != nil {
|
||
|
b.Errorf("error unmarshalling JSON: %s", err)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
}
|