vitess-gh/go/bson/custom_test.go

250 строки
11 KiB
Go

// Copyright 2012, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bson
import (
"bytes"
"fmt"
"reflect"
"testing"
"time"
"github.com/youtube/vitess/go/bytes2"
)
const (
bsonValNil = "\nVal\x00"
bsonValBytes = "\x05Val\x00\x04\x00\x00\x00\x00test"
bsonValInt64 = "\x12Val\x00\x01\x00\x00\x00\x00\x00\x00\x00"
bsonValInt32 = "\x10Val\x00\x01\x00\x00\x00"
bsonValUint64 = "\x12Val\x00\x01\x00\x00\x00\x00\x00\x00\x00"
bsonValFloat64 = "\x01Val\x00\x00\x00\x00\x00\x00\x00\xf0?"
bsonValBool = "\bVal\x00\x01"
bsonValMap = "\x03Val\x00\x13\x00\x00\x00\x12Val1\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
bsonValSlice = "\x04Val\x00\x10\x00\x00\x00\x120\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
bsonValTime = "\tVal\x00\x88\xf2\\\x8d\b\x01\x00\x00"
)
var interfaceMarshalCases = []struct {
desc string
in interface{}
out string
}{
{"nil", nil, bsonValNil},
{"string", "test", bsonValBytes},
{"[]byte", []byte("test"), bsonValBytes},
{"int64", int64(1), bsonValInt64},
{"int32", int32(1), bsonValInt32},
{"int", int(1), bsonValInt64},
{"uint64", uint64(1), bsonValUint64},
{"uint32", uint32(1), bsonValUint64},
{"uint", uint(1), bsonValUint64},
{"float64", float64(1.0), bsonValFloat64},
{"bool", true, bsonValBool},
{"nil map", map[string]interface{}(nil), bsonValNil},
{"map", map[string]interface{}{"Val1": 1}, bsonValMap},
{"nil slice", []interface{}(nil), bsonValNil},
{"slice", []interface{}{1}, bsonValSlice},
{"time", time.Unix(1136243045, 0).UTC(), bsonValTime},
}
func TestInterfaceMarshal(t *testing.T) {
for _, tcase := range interfaceMarshalCases {
buf := bytes2.NewChunkedWriter(DefaultBufferSize)
EncodeInterface(buf, "Val", tcase.in)
got := string(buf.Bytes())
if got != tcase.out {
t.Errorf("%s: got \n%q, want \n%q", tcase.desc, got, tcase.out)
}
}
}
func TestInterfaceMarshalFailure(t *testing.T) {
want := "don't know how to marshal chan int"
func() {
defer func() {
if x := recover(); x != nil {
got := x.(BsonError).Error()
if got != want {
t.Errorf("got %s, want %s", got, want)
}
return
}
}()
buf := bytes2.NewChunkedWriter(DefaultBufferSize)
EncodeInterface(buf, "Val", make(chan int))
t.Errorf("got no error, want %s", want)
}()
}
const (
bsonString = "\x05\x00\x00\x00test\x00"
bsonBinary = "\x04\x00\x00\x00\x00test"
bsonInt = "\x01\x00\x00\x00"
bsonLong = "\x01\x00\x00\x00\x00\x00\x00\x00"
bsonNumber = "\x00\x00\x00\x00\x00\x00\xf0?"
bsonDatetime = "\x88\xf2\\\x8d\b\x01\x00\x00"
bsonBoolean = "\x01"
bsonObject = "\x14\x00\x00\x00\x05Val2\x00\x04\x00\x00\x00\x00test\x00"
bsonObjectNull = "\v\x00\x00\x00\nVal2\x00\x00"
bsonArray = "\x11\x00\x00\x00\x050\x00\x04\x00\x00\x00\x00test\x00"
bsonArrayNull = "\x13\x00\x00\x00\n0\x00\x121\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
bsonStringArray = "\x1f\x00\x00\x00\x050\x00\x05\x00\x00\x00\x00test1\x051\x00\x05\x00\x00\x00\x00test2\x00"
)
func stringDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeString(buf, kind) }
func binaryDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeBinary(buf, kind) }
func int64Decoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeInt64(buf, kind) }
func int32Decoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeInt32(buf, kind) }
func intDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeInt(buf, kind) }
func uint64Decoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeUint64(buf, kind) }
func uint32Decoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeUint32(buf, kind) }
func uintDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeUint(buf, kind) }
func float64Decoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeFloat64(buf, kind) }
func boolDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeBool(buf, kind) }
func timeDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeTime(buf, kind) }
func interfaceDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeInterface(buf, kind) }
func mapDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeMap(buf, kind) }
func arrayDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeArray(buf, kind) }
func skipDecoder(buf *bytes.Buffer, kind byte) interface{} { Skip(buf, kind); return nil }
func stringArrayDecoder(buf *bytes.Buffer, kind byte) interface{} { return DecodeStringArray(buf, kind) }
var customUnmarshalCases = []struct {
desc string
in string
kind byte
decoder func(buf *bytes.Buffer, kind byte) interface{}
out interface{}
}{
{"String->string", bsonString, String, stringDecoder, "test"},
{"Binary->string", bsonBinary, Binary, stringDecoder, "test"},
{"Null->string", "", Null, stringDecoder, ""},
{"String->bytes", bsonString, String, binaryDecoder, []byte("test")},
{"Binary->bytes", bsonBinary, Binary, binaryDecoder, []byte("test")},
{"Null->bytes", "", Null, binaryDecoder, []byte(nil)},
{"Int->int64", bsonInt, Int, int64Decoder, int64(1)},
{"Long->int64", bsonLong, Long, int64Decoder, int64(1)},
{"Ulong->int64", bsonLong, Ulong, int64Decoder, int64(1)},
{"Null->int64", "", Null, int64Decoder, int64(0)},
{"Int->int32", bsonInt, Int, int32Decoder, int32(1)},
{"Null->int32", "", Null, int32Decoder, int32(0)},
{"Int->int", bsonInt, Int, intDecoder, int(1)},
{"Long->int", bsonLong, Long, intDecoder, int(1)},
{"Ulong->int", bsonLong, Ulong, intDecoder, int(1)},
{"Null->int", "", Null, intDecoder, int(0)},
{"Int->uint64", bsonInt, Int, uint64Decoder, uint64(1)},
{"Long->uint64", bsonLong, Long, uint64Decoder, uint64(1)},
{"Ulong->uint64", bsonLong, Ulong, uint64Decoder, uint64(1)},
{"Null->uint64", "", Null, uint64Decoder, uint64(0)},
{"Int->uint32", bsonInt, Int, uint32Decoder, uint32(1)},
{"Ulong->uint32", bsonLong, Ulong, uint32Decoder, uint32(1)},
{"Null->uint32", "", Null, uint32Decoder, uint32(0)},
{"Int->uint", bsonInt, Int, uintDecoder, uint(1)},
{"Long->uint", bsonLong, Long, uintDecoder, uint(1)},
{"Ulong->uint", bsonLong, Ulong, uintDecoder, uint(1)},
{"Null->uint", "", Null, uintDecoder, uint(0)},
{"Number->float64", bsonNumber, Number, float64Decoder, float64(1.0)},
{"Null->float64", "", Null, float64Decoder, float64(0.0)},
{"Boolean->bool", bsonBoolean, Boolean, boolDecoder, true},
{"Null->bool", "", Null, boolDecoder, false},
{"Datetime->time.Time", bsonDatetime, Datetime, timeDecoder, time.Unix(1136243045, 0).UTC()},
{"Null->time.Time", "", Null, timeDecoder, time.Time{}},
{"Number->interface{}", bsonNumber, Number, interfaceDecoder, float64(1.0)},
{"String->interface{}", bsonString, String, interfaceDecoder, "test"},
{"Object->interface{}", bsonObject, Object, interfaceDecoder, map[string]interface{}{"Val2": []byte("test")}},
{"Object->interface{} with null element", bsonObjectNull, Object, interfaceDecoder, map[string]interface{}{"Val2": nil}},
{"Array->interface{}", bsonArray, Array, interfaceDecoder, []interface{}{[]byte("test")}},
{"Array->interface{} with null element", bsonArrayNull, Array, interfaceDecoder, []interface{}{nil, int64(1)}},
{"Binary->interface{}", bsonBinary, Binary, interfaceDecoder, []byte("test")},
{"Boolean->interface{}", bsonBoolean, Boolean, interfaceDecoder, true},
{"Datetime->interface{}", bsonDatetime, Datetime, interfaceDecoder, time.Unix(1136243045, 0).UTC()},
{"Int->interface{}", bsonInt, Int, interfaceDecoder, int32(1)},
{"Long->interface{}", bsonLong, Long, interfaceDecoder, int64(1)},
{"Ulong->interface{}", bsonLong, Ulong, interfaceDecoder, uint64(1)},
{"Null->interface{}", "", Null, interfaceDecoder, nil},
{"Null->map[string]interface{}", "", Null, mapDecoder, map[string]interface{}(nil)},
{"Null->[]interface{}", "", Null, arrayDecoder, []interface{}(nil)},
{"Number->Skip", bsonNumber, Number, skipDecoder, nil},
{"String->Skip", bsonString, String, skipDecoder, nil},
{"Object->Skip", bsonObject, Object, skipDecoder, nil},
{"Object->Skip with null element", bsonObjectNull, Object, skipDecoder, nil},
{"Array->Skip", bsonArray, Array, skipDecoder, nil},
{"Array->Skip with null element", bsonArrayNull, Array, skipDecoder, nil},
{"Binary->Skip", bsonBinary, Binary, skipDecoder, nil},
{"Boolean->Skip", bsonBoolean, Boolean, skipDecoder, nil},
{"Datetime->Skip", bsonDatetime, Datetime, skipDecoder, nil},
{"Int->Skip", bsonInt, Int, skipDecoder, nil},
{"Long->Skip", bsonLong, Long, skipDecoder, nil},
{"Ulong->Skip", bsonLong, Ulong, skipDecoder, nil},
{"Null->Skip", "", Null, skipDecoder, nil},
{"Null->map[string]interface{}", "", Null, mapDecoder, map[string]interface{}(nil)},
{"Null->[]interface{}", "", Null, arrayDecoder, []interface{}(nil)},
{"Array->[]string", bsonStringArray, Array, stringArrayDecoder, []string{"test1", "test2"}},
{"Null->[]string", "", Null, stringArrayDecoder, []string(nil)},
}
func TestCustomUnmarshal(t *testing.T) {
for _, tcase := range customUnmarshalCases {
buf := bytes.NewBuffer([]byte(tcase.in))
got := tcase.decoder(buf, tcase.kind)
if !reflect.DeepEqual(got, tcase.out) {
t.Errorf("%s: received: %v, want %v", tcase.desc, got, tcase.out)
}
if buf.Len() != 0 {
t.Errorf("%s: %d unread bytes from %q, want 0", tcase.desc, buf.Len(), tcase.in)
}
}
}
var customUnmarshalFailureCases = []struct {
typ string
decoder func(buf *bytes.Buffer, kind byte) interface{}
valid []byte
}{
{"string", stringDecoder, []byte{String, Binary, Null}},
{"[]byte", binaryDecoder, []byte{String, Binary, Null}},
{"int64", int64Decoder, []byte{Int, Long, Ulong, Null}},
{"int32", int32Decoder, []byte{Int, Long, Null}},
{"int", intDecoder, []byte{Int, Long, Ulong, Null}},
{"uint64", uint64Decoder, []byte{Int, Long, Ulong, Null}},
{"uint32", uint32Decoder, []byte{Int, Long, Ulong, Null}},
{"uint", uintDecoder, []byte{Int, Long, Ulong, Null}},
{"float64", float64Decoder, []byte{Number, Null}},
{"bool", boolDecoder, []byte{Boolean, Int, Long, Ulong, Null}},
{"time.Time", timeDecoder, []byte{Datetime, Null}},
{"interface{}", interfaceDecoder, []byte{Number, String, Object, Array, Binary, Boolean, Datetime, Null, Int, Long, Ulong}},
{"map", mapDecoder, []byte{Object, Null}},
{"slice", arrayDecoder, []byte{Array, Null}},
{"[]string", stringArrayDecoder, []byte{Array, Null}},
{"skip", skipDecoder, []byte{Number, String, Object, Array, Binary, Boolean, Datetime, Null, Int, Long, Ulong}},
}
func TestCustomUnmarshalFailures(t *testing.T) {
allKinds := []byte{EOO, Number, String, Object, Array, Binary, Boolean, Datetime, Null, Int, Long, Ulong}
for _, tcase := range customUnmarshalFailureCases {
for _, kind := range allKinds {
want := fmt.Sprintf("unexpected kind %v for %s", kind, tcase.typ)
func() {
defer func() {
if x := recover(); x != nil {
got := x.(BsonError).Error()
if got != want {
t.Errorf("got %s, want %s", got, want)
}
return
}
}()
for _, valid := range tcase.valid {
if kind == valid {
return
}
}
tcase.decoder(nil, kind)
t.Errorf("got no error, want %s", want)
}()
}
}
}