1
2
3
4
5
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 TestArrayBuilder(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 NewArrayBuilder().AppendInt32,
33 []interface{}{int32(256)},
34 BuildDocumentFromElements(nil, AppendInt32Element(nil, "0", int32(256))),
35 },
36 {
37 "AppendDouble",
38 NewArrayBuilder().AppendDouble,
39 []interface{}{float64(3.14159)},
40 BuildDocumentFromElements(nil, AppendDoubleElement(nil, "0", float64(3.14159))),
41 },
42 {
43 "AppendString",
44 NewArrayBuilder().AppendString,
45 []interface{}{"x"},
46 BuildDocumentFromElements(nil, AppendStringElement(nil, "0", "x")),
47 },
48 {
49 "AppendDocument",
50 NewArrayBuilder().AppendDocument,
51 []interface{}{[]byte{0x05, 0x00, 0x00, 0x00, 0x00}},
52 BuildDocumentFromElements(nil, AppendDocumentElement(nil, "0", []byte{0x05, 0x00, 0x00, 0x00, 0x00})),
53 },
54 {
55 "AppendArray",
56 NewArrayBuilder().AppendArray,
57 []interface{}{[]byte{0x05, 0x00, 0x00, 0x00, 0x00}},
58 BuildDocumentFromElements(nil, AppendArrayElement(nil, "0", []byte{0x05, 0x00, 0x00, 0x00, 0x00})),
59 },
60 {
61 "AppendBinary",
62 NewArrayBuilder().AppendBinary,
63 []interface{}{byte(0x02), []byte{0x01, 0x02, 0x03}},
64 BuildDocumentFromElements(nil, AppendBinaryElement(nil, "0", byte(0x02), []byte{0x01, 0x02, 0x03})),
65 },
66 {
67 "AppendObjectID",
68 NewArrayBuilder().AppendObjectID,
69 []interface{}{
70 primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C},
71 },
72 BuildDocumentFromElements(nil, AppendObjectIDElement(nil, "0",
73 primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C})),
74 },
75 {
76 "AppendBoolean",
77 NewArrayBuilder().AppendBoolean,
78 []interface{}{true},
79 BuildDocumentFromElements(nil, AppendBooleanElement(nil, "0", true)),
80 },
81 {
82 "AppendDateTime",
83 NewArrayBuilder().AppendDateTime,
84 []interface{}{int64(256)},
85 BuildDocumentFromElements(nil, AppendDateTimeElement(nil, "0", int64(256))),
86 },
87 {
88 "AppendNull",
89 NewArrayBuilder().AppendNull,
90 []interface{}{},
91 BuildDocumentFromElements(nil, AppendNullElement(nil, "0")),
92 },
93 {
94 "AppendRegex",
95 NewArrayBuilder().AppendRegex,
96 []interface{}{"bar", "baz"},
97 BuildDocumentFromElements(nil, AppendRegexElement(nil, "0", "bar", "baz")),
98 },
99 {
100 "AppendJavaScript",
101 NewArrayBuilder().AppendJavaScript,
102 []interface{}{"barbaz"},
103 BuildDocumentFromElements(nil, AppendJavaScriptElement(nil, "0", "barbaz")),
104 },
105 {
106 "AppendCodeWithScope",
107 NewArrayBuilder().AppendCodeWithScope,
108 []interface{}{"barbaz", Document([]byte{0x05, 0x00, 0x00, 0x00, 0x00})},
109 BuildDocumentFromElements(nil, AppendCodeWithScopeElement(nil, "0", "barbaz", Document([]byte{0x05, 0x00, 0x00, 0x00, 0x00}))),
110 },
111 {
112 "AppendTimestamp",
113 NewArrayBuilder().AppendTimestamp,
114 []interface{}{uint32(65536), uint32(256)},
115 BuildDocumentFromElements(nil, AppendTimestampElement(nil, "0", uint32(65536), uint32(256))),
116 },
117 {
118 "AppendInt64",
119 NewArrayBuilder().AppendInt64,
120 []interface{}{int64(4294967296)},
121 BuildDocumentFromElements(nil, AppendInt64Element(nil, "0", int64(4294967296))),
122 },
123 {
124 "AppendDecimal128",
125 NewArrayBuilder().AppendDecimal128,
126 []interface{}{primitive.NewDecimal128(4294967296, 65536)},
127 BuildDocumentFromElements(nil, AppendDecimal128Element(nil, "0", primitive.NewDecimal128(4294967296, 65536))),
128 },
129 {
130 "AppendMaxKey",
131 NewArrayBuilder().AppendMaxKey,
132 []interface{}{},
133 BuildDocumentFromElements(nil, AppendMaxKeyElement(nil, "0")),
134 },
135 {
136 "AppendMinKey",
137 NewArrayBuilder().AppendMinKey,
138 []interface{}{},
139 BuildDocumentFromElements(nil, AppendMinKeyElement(nil, "0")),
140 },
141 {
142 "AppendSymbol",
143 NewArrayBuilder().AppendSymbol,
144 []interface{}{"barbaz"},
145 BuildDocumentFromElements(nil, AppendSymbolElement(nil, "0", "barbaz")),
146 },
147 {
148 "AppendDBPointer",
149 NewArrayBuilder().AppendDBPointer,
150 []interface{}{"barbaz",
151 primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C}},
152 BuildDocumentFromElements(nil, AppendDBPointerElement(nil, "0", "barbaz",
153 primitive.ObjectID{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C})),
154 },
155 {
156 "AppendUndefined",
157 NewArrayBuilder().AppendUndefined,
158 []interface{}{},
159 BuildDocumentFromElements(nil, AppendUndefinedElement(nil, "0")),
160 },
161 }
162 for _, tc := range testCases {
163 t.Run(tc.name, func(t *testing.T) {
164
165 fn := reflect.ValueOf(tc.fn)
166 if fn.Kind() != reflect.Func {
167 t.Fatalf("fn must be of kind Func but is a %v", fn.Kind())
168 }
169 if fn.Type().NumIn() != len(tc.params) {
170 t.Fatalf("tc.params must match the number of params in tc.fn. params %d; fn %d", fn.Type().NumIn(), len(tc.params))
171 }
172 if fn.Type().NumOut() != 1 || fn.Type().Out(0) != reflect.TypeOf(&ArrayBuilder{}) {
173 t.Fatalf("fn must have one return parameter and it must be an ArrayBuilder.")
174 }
175 params := make([]reflect.Value, 0, len(tc.params))
176 for _, param := range tc.params {
177 params = append(params, reflect.ValueOf(param))
178 }
179 results := fn.Call(params)
180 got := results[0].Interface().(*ArrayBuilder).Build()
181 want := tc.expected
182 if !bytes.Equal(got, want) {
183 t.Errorf("Did not receive expected bytes. got %v; want %v", got, want)
184 }
185 })
186 }
187 t.Run("TestBuildTwoElementsArray", func(t *testing.T) {
188 intArr := BuildDocumentFromElements(nil, AppendInt32Element(nil, "0", int32(1)))
189 expected := BuildDocumentFromElements(nil, AppendArrayElement(AppendInt32Element(nil, "0", int32(3)), "1", intArr))
190 elem := NewArrayBuilder().AppendInt32(int32(1)).Build()
191 result := NewArrayBuilder().AppendInt32(int32(3)).AppendArray(elem).Build()
192 if !bytes.Equal(result, expected) {
193 t.Errorf("Arrays do not match. got %v; want %v", result, expected)
194 }
195 })
196 t.Run("TestBuildInlineArray", func(t *testing.T) {
197 docElement := BuildDocumentFromElements(nil, AppendInt32Element(nil, "0", int32(256)))
198 expected := Document(BuildDocumentFromElements(nil, AppendArrayElement(nil, "0", docElement)))
199 result := NewArrayBuilder().StartArray().AppendInt32(int32(256)).FinishArray().Build()
200 if !bytes.Equal(result, expected) {
201 t.Errorf("Documents do not match. got %v; want %v", result, expected)
202 }
203 })
204 t.Run("TestBuildNestedInlineArray", func(t *testing.T) {
205 docElement := BuildDocumentFromElements(nil, AppendDoubleElement(nil, "0", 3.14))
206 docInline := BuildDocumentFromElements(nil, AppendArrayElement(nil, "0", docElement))
207 expected := Document(BuildDocumentFromElements(nil, AppendArrayElement(nil, "0", docInline)))
208 result := NewArrayBuilder().StartArray().StartArray().AppendDouble(3.14).FinishArray().FinishArray().Build()
209 if !bytes.Equal(result, expected) {
210 t.Errorf("Documents do not match. got %v; want %v", result, expected)
211 }
212 })
213 }
214
View as plain text