...

Source file src/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_documentbuilder_test.go

Documentation: go.mongodb.org/mongo-driver/x/bsonx/bsoncore

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package bsoncore
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/binary"
    12  	"math"
    13  	"reflect"
    14  	"testing"
    15  
    16  	"go.mongodb.org/mongo-driver/bson/primitive"
    17  )
    18  
    19  func TestDocumentBuilder(t *testing.T) {
    20  	bits := math.Float64bits(3.14159)
    21  	pi := make([]byte, 8)
    22  	binary.LittleEndian.PutUint64(pi, bits)
    23  
    24  	testCases := []struct {
    25  		name     string
    26  		fn       interface{}
    27  		params   []interface{}
    28  		expected []byte
    29  	}{
    30  		{
    31  			"AppendInt32",
    32  			NewDocumentBuilder().AppendInt32,
    33  			[]interface{}{"foobar", int32(256)},
    34  			BuildDocumentFromElements(nil, AppendInt32Element(nil, "foobar", 256)),
    35  		},
    36  		{
    37  			"AppendDouble",
    38  			NewDocumentBuilder().AppendDouble,
    39  			[]interface{}{"foobar", float64(3.14159)},
    40  			BuildDocumentFromElements(nil, AppendDoubleElement(nil, "foobar", float64(3.14159))),
    41  		},
    42  		{
    43  			"AppendString",
    44  			NewDocumentBuilder().AppendString,
    45  			[]interface{}{"foobar", "x"},
    46  			BuildDocumentFromElements(nil, AppendStringElement(nil, "foobar", "x")),
    47  		},
    48  		{
    49  			"AppendDocument",
    50  			NewDocumentBuilder().AppendDocument,
    51  			[]interface{}{"foobar", []byte{0x05, 0x00, 0x00, 0x00, 0x00}},
    52  			BuildDocumentFromElements(nil, AppendDocumentElement(nil, "foobar", []byte{0x05, 0x00, 0x00, 0x00, 0x00})),
    53  		},
    54  		{
    55  			"AppendArray",
    56  			NewDocumentBuilder().AppendArray,
    57  			[]interface{}{"foobar", []byte{0x05, 0x00, 0x00, 0x00, 0x00}},
    58  			BuildDocumentFromElements(nil, AppendArrayElement(nil, "foobar", []byte{0x05, 0x00, 0x00, 0x00, 0x00})),
    59  		},
    60  		{
    61  			"AppendBinary",
    62  			NewDocumentBuilder().AppendBinary,
    63  			[]interface{}{"foobar", byte(0x02), []byte{0x01, 0x02, 0x03}},
    64  			BuildDocumentFromElements(nil, AppendBinaryElement(nil, "foobar", byte(0x02), []byte{0x01, 0x02, 0x03})),
    65  		},
    66  		{
    67  			"AppendObjectID",
    68  			NewDocumentBuilder().AppendObjectID,
    69  			[]interface{}{
    70  				"foobar",
    71  				primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C},
    72  			},
    73  			BuildDocumentFromElements(nil, AppendObjectIDElement(nil, "foobar",
    74  				primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C})),
    75  		},
    76  		{
    77  			"AppendBoolean",
    78  			NewDocumentBuilder().AppendBoolean,
    79  			[]interface{}{"foobar", true},
    80  			BuildDocumentFromElements(nil, AppendBooleanElement(nil, "foobar", true)),
    81  		},
    82  		{
    83  			"AppendDateTime",
    84  			NewDocumentBuilder().AppendDateTime,
    85  			[]interface{}{"foobar", int64(256)},
    86  			BuildDocumentFromElements(nil, AppendDateTimeElement(nil, "foobar", int64(256))),
    87  		},
    88  		{
    89  			"AppendNull",
    90  			NewDocumentBuilder().AppendNull,
    91  			[]interface{}{"foobar"},
    92  			BuildDocumentFromElements(nil, AppendNullElement(nil, "foobar")),
    93  		},
    94  		{
    95  			"AppendRegex",
    96  			NewDocumentBuilder().AppendRegex,
    97  			[]interface{}{"foobar", "bar", "baz"},
    98  			BuildDocumentFromElements(nil, AppendRegexElement(nil, "foobar", "bar", "baz")),
    99  		},
   100  		{
   101  			"AppendJavaScript",
   102  			NewDocumentBuilder().AppendJavaScript,
   103  			[]interface{}{"foobar", "barbaz"},
   104  			BuildDocumentFromElements(nil, AppendJavaScriptElement(nil, "foobar", "barbaz")),
   105  		},
   106  		{
   107  			"AppendCodeWithScope",
   108  			NewDocumentBuilder().AppendCodeWithScope,
   109  			[]interface{}{"foobar", "barbaz", Document([]byte{0x05, 0x00, 0x00, 0x00, 0x00})},
   110  			BuildDocumentFromElements(nil, AppendCodeWithScopeElement(nil, "foobar", "barbaz", Document([]byte{0x05, 0x00, 0x00, 0x00, 0x00}))),
   111  		},
   112  		{
   113  			"AppendTimestamp",
   114  			NewDocumentBuilder().AppendTimestamp,
   115  			[]interface{}{"foobar", uint32(65536), uint32(256)},
   116  			BuildDocumentFromElements(nil, AppendTimestampElement(nil, "foobar", uint32(65536), uint32(256))),
   117  		},
   118  		{
   119  			"AppendInt64",
   120  			NewDocumentBuilder().AppendInt64,
   121  			[]interface{}{"foobar", int64(4294967296)},
   122  			BuildDocumentFromElements(nil, AppendInt64Element(nil, "foobar", int64(4294967296))),
   123  		},
   124  		{
   125  			"AppendDecimal128",
   126  			NewDocumentBuilder().AppendDecimal128,
   127  			[]interface{}{"foobar", primitive.NewDecimal128(4294967296, 65536)},
   128  			BuildDocumentFromElements(nil, AppendDecimal128Element(nil, "foobar", primitive.NewDecimal128(4294967296, 65536))),
   129  		},
   130  		{
   131  			"AppendMaxKey",
   132  			NewDocumentBuilder().AppendMaxKey,
   133  			[]interface{}{"foobar"},
   134  			BuildDocumentFromElements(nil, AppendMaxKeyElement(nil, "foobar")),
   135  		},
   136  		{
   137  			"AppendMinKey",
   138  			NewDocumentBuilder().AppendMinKey,
   139  			[]interface{}{"foobar"},
   140  			BuildDocumentFromElements(nil, AppendMinKeyElement(nil, "foobar")),
   141  		},
   142  		{
   143  			"AppendSymbol",
   144  			NewDocumentBuilder().AppendSymbol,
   145  			[]interface{}{"foobar", "barbaz"},
   146  			BuildDocumentFromElements(nil, AppendSymbolElement(nil, "foobar", "barbaz")),
   147  		},
   148  		{
   149  			"AppendDBPointer",
   150  			NewDocumentBuilder().AppendDBPointer,
   151  			[]interface{}{"foobar", "barbaz",
   152  				primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C}},
   153  			BuildDocumentFromElements(nil, AppendDBPointerElement(nil, "foobar", "barbaz",
   154  				primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C})),
   155  		},
   156  		{
   157  			"AppendUndefined",
   158  			NewDocumentBuilder().AppendUndefined,
   159  			[]interface{}{"foobar"},
   160  			BuildDocumentFromElements(nil, AppendUndefinedElement(nil, "foobar")),
   161  		},
   162  	}
   163  	for _, tc := range testCases {
   164  		t.Run(tc.name, func(t *testing.T) {
   165  
   166  			fn := reflect.ValueOf(tc.fn)
   167  			if fn.Kind() != reflect.Func {
   168  				t.Fatalf("fn must be of kind Func but is a %v", fn.Kind())
   169  			}
   170  			if fn.Type().NumIn() != len(tc.params) {
   171  				t.Fatalf("tc.params must match the number of params in tc.fn. params %d; fn %d", fn.Type().NumIn(), len(tc.params))
   172  			}
   173  			if fn.Type().NumOut() != 1 || fn.Type().Out(0) != reflect.TypeOf(&DocumentBuilder{}) {
   174  				t.Fatalf("fn must have one return parameter and it must be a DocumentBuilder.")
   175  			}
   176  			params := make([]reflect.Value, 0, len(tc.params))
   177  			for _, param := range tc.params {
   178  				params = append(params, reflect.ValueOf(param))
   179  			}
   180  			results := fn.Call(params)
   181  			got := results[0].Interface().(*DocumentBuilder)
   182  			doc := got.Build()
   183  			want := tc.expected
   184  			if !bytes.Equal(doc, want) {
   185  				t.Errorf("Did not receive expected bytes. got %v; want %v", got, want)
   186  			}
   187  		})
   188  	}
   189  	t.Run("TestBuildTwoElements", func(t *testing.T) {
   190  		intArr := BuildDocumentFromElements(nil, AppendInt32Element(nil, "0", int32(1)))
   191  		expected := BuildDocumentFromElements(nil, AppendArrayElement(AppendInt32Element(nil, "x", int32(3)), "y", intArr))
   192  		elem := NewArrayBuilder().AppendInt32(int32(1)).Build()
   193  		result := NewDocumentBuilder().AppendInt32("x", int32(3)).AppendArray("y", elem).Build()
   194  		if !bytes.Equal(result, expected) {
   195  			t.Errorf("Documents do not match. got %v; want %v", result, expected)
   196  		}
   197  	})
   198  	t.Run("TestBuildInlineDocument", func(t *testing.T) {
   199  		docElement := BuildDocumentFromElements(nil, AppendInt32Element(nil, "x", int32(256)))
   200  		expected := Document(BuildDocumentFromElements(nil, AppendDocumentElement(nil, "y", docElement)))
   201  		result := NewDocumentBuilder().StartDocument("y").AppendInt32("x", int32(256)).FinishDocument().Build()
   202  		if !bytes.Equal(result, expected) {
   203  			t.Errorf("Documents do not match. got %v; want %v", result, expected)
   204  		}
   205  	})
   206  	t.Run("TestBuildNestedInlineDocument", func(t *testing.T) {
   207  		docElement := BuildDocumentFromElements(nil, AppendDoubleElement(nil, "x", 3.14))
   208  		docInline := BuildDocumentFromElements(nil, AppendDocumentElement(nil, "y", docElement))
   209  		expected := Document(BuildDocumentFromElements(nil, AppendDocumentElement(nil, "z", docInline)))
   210  		result := NewDocumentBuilder().StartDocument("z").StartDocument("y").AppendDouble("x", 3.14).FinishDocument().FinishDocument().Build()
   211  		if !bytes.Equal(result, expected) {
   212  			t.Errorf("Documents do not match. got %v; want %v", result, expected)
   213  		}
   214  	})
   215  }
   216  

View as plain text