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 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