529 lines
17 KiB
Go
529 lines
17 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 (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"gitea.psichedelico.com/go/bson/internal/assert"
|
|
"gitea.psichedelico.com/go/bson/x/bsonx/bsoncore"
|
|
)
|
|
|
|
func TestCopier(t *testing.T) {
|
|
t.Run("CopyDocument", func(t *testing.T) {
|
|
t.Run("ReadDocument Error", func(t *testing.T) {
|
|
want := errors.New("ReadDocumentError")
|
|
src := &TestValueReaderWriter{t: t, err: want, errAfter: llvrwReadDocument}
|
|
got := copyDocument(nil, src)
|
|
if !assert.CompareErrors(got, want) {
|
|
t.Errorf("Did not receive correct error. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("WriteDocument Error", func(t *testing.T) {
|
|
want := errors.New("WriteDocumentError")
|
|
src := &TestValueReaderWriter{}
|
|
dst := &TestValueReaderWriter{t: t, err: want, errAfter: llvrwWriteDocument}
|
|
got := copyDocument(dst, src)
|
|
if !assert.CompareErrors(got, want) {
|
|
t.Errorf("Did not receive correct error. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("success", func(t *testing.T) {
|
|
idx, doc := bsoncore.AppendDocumentStart(nil)
|
|
doc = bsoncore.AppendStringElement(doc, "Hello", "world")
|
|
doc, err := bsoncore.AppendDocumentEnd(doc, idx)
|
|
noerr(t, err)
|
|
src := newDocumentReader(bytes.NewReader(doc))
|
|
dst := newValueWriterFromSlice(make([]byte, 0))
|
|
want := doc
|
|
err = copyDocument(dst, src)
|
|
noerr(t, err)
|
|
got := dst.buf
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("Bytes are not equal. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
})
|
|
t.Run("copyArray", func(t *testing.T) {
|
|
t.Run("ReadArray Error", func(t *testing.T) {
|
|
want := errors.New("ReadArrayError")
|
|
src := &TestValueReaderWriter{t: t, err: want, errAfter: llvrwReadArray}
|
|
got := copyArray(nil, src)
|
|
if !assert.CompareErrors(got, want) {
|
|
t.Errorf("Did not receive correct error. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("WriteArray Error", func(t *testing.T) {
|
|
want := errors.New("WriteArrayError")
|
|
src := &TestValueReaderWriter{}
|
|
dst := &TestValueReaderWriter{t: t, err: want, errAfter: llvrwWriteArray}
|
|
got := copyArray(dst, src)
|
|
if !assert.CompareErrors(got, want) {
|
|
t.Errorf("Did not receive correct error. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("success", func(t *testing.T) {
|
|
idx, doc := bsoncore.AppendDocumentStart(nil)
|
|
aidx, doc := bsoncore.AppendArrayElementStart(doc, "foo")
|
|
doc = bsoncore.AppendStringElement(doc, "0", "Hello, world!")
|
|
doc, err := bsoncore.AppendArrayEnd(doc, aidx)
|
|
noerr(t, err)
|
|
doc, err = bsoncore.AppendDocumentEnd(doc, idx)
|
|
noerr(t, err)
|
|
src := newDocumentReader(bytes.NewReader(doc))
|
|
|
|
_, err = src.ReadDocument()
|
|
noerr(t, err)
|
|
_, _, err = src.ReadElement()
|
|
noerr(t, err)
|
|
|
|
dst := newValueWriterFromSlice(make([]byte, 0))
|
|
_, err = dst.WriteDocument()
|
|
noerr(t, err)
|
|
_, err = dst.WriteDocumentElement("foo")
|
|
noerr(t, err)
|
|
want := doc
|
|
|
|
err = copyArray(dst, src)
|
|
noerr(t, err)
|
|
|
|
err = dst.WriteDocumentEnd()
|
|
noerr(t, err)
|
|
|
|
got := dst.buf
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("Bytes are not equal. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
})
|
|
t.Run("CopyValue", func(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
dst *TestValueReaderWriter
|
|
src *TestValueReaderWriter
|
|
err error
|
|
}{
|
|
{
|
|
"Double/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeDouble, err: errors.New("1"), errAfter: llvrwReadDouble},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Double/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeDouble, err: errors.New("2"), errAfter: llvrwWriteDouble},
|
|
&TestValueReaderWriter{bsontype: TypeDouble, readval: float64(3.14159)},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"String/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeString, err: errors.New("1"), errAfter: llvrwReadString},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"String/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeString, err: errors.New("2"), errAfter: llvrwWriteString},
|
|
&TestValueReaderWriter{bsontype: TypeString, readval: "hello, world"},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Document/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeEmbeddedDocument, err: errors.New("1"), errAfter: llvrwReadDocument},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Array/dst/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeArray, err: errors.New("2"), errAfter: llvrwReadArray},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Binary/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeBinary, err: errors.New("1"), errAfter: llvrwReadBinary},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Binary/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeBinary, err: errors.New("2"), errAfter: llvrwWriteBinaryWithSubtype},
|
|
&TestValueReaderWriter{
|
|
bsontype: TypeBinary,
|
|
readval: bsoncore.Value{
|
|
Type: bsoncore.TypeBinary,
|
|
Data: []byte{0x03, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x02, 0x03},
|
|
},
|
|
},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Undefined/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeUndefined, err: errors.New("1"), errAfter: llvrwReadUndefined},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Undefined/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeUndefined, err: errors.New("2"), errAfter: llvrwWriteUndefined},
|
|
&TestValueReaderWriter{bsontype: TypeUndefined},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"ObjectID/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeObjectID, err: errors.New("1"), errAfter: llvrwReadObjectID},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"ObjectID/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeObjectID, err: errors.New("2"), errAfter: llvrwWriteObjectID},
|
|
&TestValueReaderWriter{bsontype: TypeObjectID, readval: ObjectID{0x01, 0x02, 0x03}},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Boolean/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeBoolean, err: errors.New("1"), errAfter: llvrwReadBoolean},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Boolean/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeBoolean, err: errors.New("2"), errAfter: llvrwWriteBoolean},
|
|
&TestValueReaderWriter{bsontype: TypeBoolean, readval: bool(true)},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"DateTime/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeDateTime, err: errors.New("1"), errAfter: llvrwReadDateTime},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"DateTime/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeDateTime, err: errors.New("2"), errAfter: llvrwWriteDateTime},
|
|
&TestValueReaderWriter{bsontype: TypeDateTime, readval: int64(1234567890)},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Null/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeNull, err: errors.New("1"), errAfter: llvrwReadNull},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Null/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeNull, err: errors.New("2"), errAfter: llvrwWriteNull},
|
|
&TestValueReaderWriter{bsontype: TypeNull},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Regex/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeRegex, err: errors.New("1"), errAfter: llvrwReadRegex},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Regex/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeRegex, err: errors.New("2"), errAfter: llvrwWriteRegex},
|
|
&TestValueReaderWriter{
|
|
bsontype: TypeRegex,
|
|
readval: bsoncore.Value{
|
|
Type: bsoncore.TypeRegex,
|
|
Data: bsoncore.AppendRegex(nil, "hello", "world"),
|
|
},
|
|
},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"DBPointer/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeDBPointer, err: errors.New("1"), errAfter: llvrwReadDBPointer},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"DBPointer/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeDBPointer, err: errors.New("2"), errAfter: llvrwWriteDBPointer},
|
|
&TestValueReaderWriter{
|
|
bsontype: TypeDBPointer,
|
|
readval: bsoncore.Value{
|
|
Type: bsoncore.TypeDBPointer,
|
|
Data: bsoncore.AppendDBPointer(nil, "foo", ObjectID{0x01, 0x02, 0x03}),
|
|
},
|
|
},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Javascript/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeJavaScript, err: errors.New("1"), errAfter: llvrwReadJavascript},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Javascript/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeJavaScript, err: errors.New("2"), errAfter: llvrwWriteJavascript},
|
|
&TestValueReaderWriter{bsontype: TypeJavaScript, readval: "hello, world"},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Symbol/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeSymbol, err: errors.New("1"), errAfter: llvrwReadSymbol},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Symbol/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeSymbol, err: errors.New("2"), errAfter: llvrwWriteSymbol},
|
|
&TestValueReaderWriter{
|
|
bsontype: TypeSymbol,
|
|
readval: bsoncore.Value{
|
|
Type: bsoncore.TypeSymbol,
|
|
Data: bsoncore.AppendSymbol(nil, "hello, world"),
|
|
},
|
|
},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"CodeWithScope/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeCodeWithScope, err: errors.New("1"), errAfter: llvrwReadCodeWithScope},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"CodeWithScope/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeCodeWithScope, err: errors.New("2"), errAfter: llvrwWriteCodeWithScope},
|
|
&TestValueReaderWriter{bsontype: TypeCodeWithScope},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"CodeWithScope/dst/copyDocumentCore error",
|
|
&TestValueReaderWriter{err: errors.New("3"), errAfter: llvrwWriteDocumentElement},
|
|
&TestValueReaderWriter{bsontype: TypeCodeWithScope},
|
|
errors.New("3"),
|
|
},
|
|
{
|
|
"Int32/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeInt32, err: errors.New("1"), errAfter: llvrwReadInt32},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Int32/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeInt32, err: errors.New("2"), errAfter: llvrwWriteInt32},
|
|
&TestValueReaderWriter{bsontype: TypeInt32, readval: int32(12345)},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Timestamp/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeTimestamp, err: errors.New("1"), errAfter: llvrwReadTimestamp},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Timestamp/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeTimestamp, err: errors.New("2"), errAfter: llvrwWriteTimestamp},
|
|
&TestValueReaderWriter{
|
|
bsontype: TypeTimestamp,
|
|
readval: bsoncore.Value{
|
|
Type: bsoncore.TypeTimestamp,
|
|
Data: bsoncore.AppendTimestamp(nil, 12345, 67890),
|
|
},
|
|
},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Int64/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeInt64, err: errors.New("1"), errAfter: llvrwReadInt64},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Int64/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeInt64, err: errors.New("2"), errAfter: llvrwWriteInt64},
|
|
&TestValueReaderWriter{bsontype: TypeInt64, readval: int64(1234567890)},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Decimal128/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeDecimal128, err: errors.New("1"), errAfter: llvrwReadDecimal128},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"Decimal128/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeDecimal128, err: errors.New("2"), errAfter: llvrwWriteDecimal128},
|
|
&TestValueReaderWriter{bsontype: TypeDecimal128, readval: NewDecimal128(12345, 67890)},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"MinKey/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeMinKey, err: errors.New("1"), errAfter: llvrwReadMinKey},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"MinKey/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeMinKey, err: errors.New("2"), errAfter: llvrwWriteMinKey},
|
|
&TestValueReaderWriter{bsontype: TypeMinKey},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"MaxKey/src/error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{bsontype: TypeMaxKey, err: errors.New("1"), errAfter: llvrwReadMaxKey},
|
|
errors.New("1"),
|
|
},
|
|
{
|
|
"MaxKey/dst/error",
|
|
&TestValueReaderWriter{bsontype: TypeMaxKey, err: errors.New("2"), errAfter: llvrwWriteMaxKey},
|
|
&TestValueReaderWriter{bsontype: TypeMaxKey},
|
|
errors.New("2"),
|
|
},
|
|
{
|
|
"Unknown BSON type error",
|
|
&TestValueReaderWriter{},
|
|
&TestValueReaderWriter{},
|
|
fmt.Errorf("cannot copy unknown BSON type %s", Type(0)),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
tc.dst.t, tc.src.t = t, t
|
|
err := copyValue(tc.dst, tc.src)
|
|
if !assert.CompareErrors(err, tc.err) {
|
|
t.Errorf("Did not receive expected error. got %v; want %v", err, tc.err)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
t.Run("CopyValueFromBytes", func(t *testing.T) {
|
|
t.Run("BytesWriter", func(t *testing.T) {
|
|
vw := newValueWriterFromSlice(make([]byte, 0))
|
|
_, err := vw.WriteDocument()
|
|
noerr(t, err)
|
|
_, err = vw.WriteDocumentElement("foo")
|
|
noerr(t, err)
|
|
err = copyValueFromBytes(vw, TypeString, bsoncore.AppendString(nil, "bar"))
|
|
noerr(t, err)
|
|
err = vw.WriteDocumentEnd()
|
|
noerr(t, err)
|
|
var idx int32
|
|
want, err := bsoncore.AppendDocumentEnd(
|
|
bsoncore.AppendStringElement(
|
|
bsoncore.AppendDocumentStartInline(nil, &idx),
|
|
"foo", "bar",
|
|
),
|
|
idx,
|
|
)
|
|
noerr(t, err)
|
|
got := vw.buf
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("Bytes are not equal. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("Non BytesWriter", func(t *testing.T) {
|
|
llvrw := &TestValueReaderWriter{t: t}
|
|
err := copyValueFromBytes(llvrw, TypeString, bsoncore.AppendString(nil, "bar"))
|
|
noerr(t, err)
|
|
got, want := llvrw.invoked, llvrwWriteString
|
|
if got != want {
|
|
t.Errorf("Incorrect method invoked on llvrw. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
})
|
|
t.Run("CopyValueToBytes", func(t *testing.T) {
|
|
t.Run("BytesReader", func(t *testing.T) {
|
|
var idx int32
|
|
b, err := bsoncore.AppendDocumentEnd(
|
|
bsoncore.AppendStringElement(
|
|
bsoncore.AppendDocumentStartInline(nil, &idx),
|
|
"hello", "world",
|
|
),
|
|
idx,
|
|
)
|
|
noerr(t, err)
|
|
vr := newDocumentReader(bytes.NewReader(b))
|
|
_, err = vr.ReadDocument()
|
|
noerr(t, err)
|
|
_, _, err = vr.ReadElement()
|
|
noerr(t, err)
|
|
btype, got, err := copyValueToBytes(vr)
|
|
noerr(t, err)
|
|
want := bsoncore.AppendString(nil, "world")
|
|
if btype != TypeString {
|
|
t.Errorf("Incorrect type returned. got %v; want %v", btype, TypeString)
|
|
}
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("Bytes do not match. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("Non BytesReader", func(t *testing.T) {
|
|
llvrw := &TestValueReaderWriter{t: t, bsontype: TypeString, readval: "Hello, world!"}
|
|
btype, got, err := copyValueToBytes(llvrw)
|
|
noerr(t, err)
|
|
want := bsoncore.AppendString(nil, "Hello, world!")
|
|
if btype != TypeString {
|
|
t.Errorf("Incorrect type returned. got %v; want %v", btype, TypeString)
|
|
}
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("Bytes do not match. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
})
|
|
t.Run("AppendValueBytes", func(t *testing.T) {
|
|
t.Run("BytesReader", func(t *testing.T) {
|
|
var idx int32
|
|
b, err := bsoncore.AppendDocumentEnd(
|
|
bsoncore.AppendStringElement(
|
|
bsoncore.AppendDocumentStartInline(nil, &idx),
|
|
"hello", "world",
|
|
),
|
|
idx,
|
|
)
|
|
noerr(t, err)
|
|
vr := newDocumentReader(bytes.NewReader(b))
|
|
_, err = vr.ReadDocument()
|
|
noerr(t, err)
|
|
_, _, err = vr.ReadElement()
|
|
noerr(t, err)
|
|
btype, got, err := copyValueToBytes(vr)
|
|
noerr(t, err)
|
|
want := bsoncore.AppendString(nil, "world")
|
|
if btype != TypeString {
|
|
t.Errorf("Incorrect type returned. got %v; want %v", btype, TypeString)
|
|
}
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("Bytes do not match. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("Non BytesReader", func(t *testing.T) {
|
|
llvrw := &TestValueReaderWriter{t: t, bsontype: TypeString, readval: "Hello, world!"}
|
|
btype, got, err := copyValueToBytes(llvrw)
|
|
noerr(t, err)
|
|
want := bsoncore.AppendString(nil, "Hello, world!")
|
|
if btype != TypeString {
|
|
t.Errorf("Incorrect type returned. got %v; want %v", btype, TypeString)
|
|
}
|
|
if !bytes.Equal(got, want) {
|
|
t.Errorf("Bytes do not match. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
t.Run("CopyValue error", func(t *testing.T) {
|
|
want := errors.New("CopyValue error")
|
|
llvrw := &TestValueReaderWriter{t: t, bsontype: TypeString, err: want, errAfter: llvrwReadString}
|
|
_, _, got := copyValueToBytes(llvrw)
|
|
if !assert.CompareErrors(got, want) {
|
|
t.Errorf("Errors do not match. got %v; want %v", got, want)
|
|
}
|
|
})
|
|
})
|
|
}
|