3
// Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net>
5
// All rights reserved.
7
// Redistribution and use in source and binary forms, with or without
8
// modification, are permitted provided that the following conditions are met:
10
// 1. Redistributions of source code must retain the above copyright notice, this
11
// list of conditions and the following disclaimer.
12
// 2. Redistributions in binary form must reproduce the above copyright notice,
13
// this list of conditions and the following disclaimer in the documentation
14
// and/or other materials provided with the distribution.
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
// gobson - BSON library for Go.
34
. "launchpad.net/gocheck"
35
"labix.org/v2/mgo/bson"
42
func TestAll(t *testing.T) {
50
// Wrap up the document elements contained in data, prepending the int32
51
// length of the data, and appending the '\x00' value closing the document.
52
func wrapInDoc(data string) string {
53
result := make([]byte, len(data)+5)
54
binary.LittleEndian.PutUint32(result, uint32(len(result)))
55
copy(result[4:], []byte(data))
59
func makeZeroDoc(value interface{}) (zero interface{}) {
60
v := reflect.ValueOf(value)
64
mv := reflect.MakeMap(t)
67
pv := reflect.New(v.Type().Elem())
70
zero = reflect.New(t).Interface()
72
panic("unsupported doc type")
77
func testUnmarshal(c *C, data string, obj interface{}) {
78
zero := makeZeroDoc(obj)
79
err := bson.Unmarshal([]byte(data), zero)
81
c.Assert(zero, DeepEquals, obj)
84
type testItemType struct {
89
// --------------------------------------------------------------------------
90
// Samples from bsonspec.org:
92
var sampleItems = []testItemType{
93
{bson.M{"hello": "world"},
94
"\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"},
95
{bson.M{"BSON": []interface{}{"awesome", float64(5.05), 1986}},
96
"1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" +
97
"awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"},
100
func (s *S) TestMarshalSampleItems(c *C) {
101
for i, item := range sampleItems {
102
data, err := bson.Marshal(item.obj)
104
c.Assert(string(data), Equals, item.data, Commentf("Failed on item %d", i))
108
func (s *S) TestUnmarshalSampleItems(c *C) {
109
for i, item := range sampleItems {
111
err := bson.Unmarshal([]byte(item.data), value)
113
c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d", i))
117
// --------------------------------------------------------------------------
118
// Every type, ordered by the type flag. These are not wrapped with the
119
// length and last \x00 from the document. wrapInDoc() computes them.
120
// Note that all of them should be supported as two-way conversions.
122
var allItems = []testItemType{
125
{bson.M{"_": float64(5.05)},
126
"\x01_\x00333333\x14@"},
128
"\x02_\x00\x03\x00\x00\x00yo\x00"},
129
{bson.M{"_": bson.M{"a": true}},
130
"\x03_\x00\x09\x00\x00\x00\x08a\x00\x01\x00"},
131
{bson.M{"_": []interface{}{true, false}},
132
"\x04_\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
133
{bson.M{"_": []byte("yo")},
134
"\x05_\x00\x02\x00\x00\x00\x00yo"},
135
{bson.M{"_": bson.Binary{0x80, []byte("udef")}},
136
"\x05_\x00\x04\x00\x00\x00\x80udef"},
137
{bson.M{"_": bson.Undefined}, // Obsolete, but still seen in the wild.
139
{bson.M{"_": bson.ObjectId("0123456789ab")},
140
"\x07_\x000123456789ab"},
145
{bson.M{"_": time.Unix(0, 258e6)}, // Note the NS <=> MS conversion.
146
"\x09_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
149
{bson.M{"_": bson.RegEx{"ab", "cd"}},
150
"\x0B_\x00ab\x00cd\x00"},
151
{bson.M{"_": bson.JavaScript{"code", nil}},
152
"\x0D_\x00\x05\x00\x00\x00code\x00"},
153
{bson.M{"_": bson.Symbol("sym")},
154
"\x0E_\x00\x04\x00\x00\x00sym\x00"},
155
{bson.M{"_": bson.JavaScript{"code", bson.M{"": nil}}},
156
"\x0F_\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" +
157
"\x07\x00\x00\x00\x0A\x00\x00"},
159
"\x10_\x00\x02\x01\x00\x00"},
160
{bson.M{"_": bson.MongoTimestamp(258)},
161
"\x11_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
162
{bson.M{"_": int64(258)},
163
"\x12_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
164
{bson.M{"_": int64(258 << 32)},
165
"\x12_\x00\x00\x00\x00\x00\x02\x01\x00\x00"},
166
{bson.M{"_": bson.MaxKey},
168
{bson.M{"_": bson.MinKey},
172
func (s *S) TestMarshalAllItems(c *C) {
173
for i, item := range allItems {
174
data, err := bson.Marshal(item.obj)
176
c.Assert(string(data), Equals, wrapInDoc(item.data), Commentf("Failed on item %d: %#v", i, item))
180
func (s *S) TestUnmarshalAllItems(c *C) {
181
for i, item := range allItems {
183
err := bson.Unmarshal([]byte(wrapInDoc(item.data)), value)
185
c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item))
189
func (s *S) TestUnmarshalRawAllItems(c *C) {
190
for i, item := range allItems {
191
if len(item.data) == 0 {
194
value := item.obj.(bson.M)["_"]
198
pv := reflect.New(reflect.ValueOf(value).Type())
199
raw := bson.Raw{item.data[0], []byte(item.data[3:])}
200
c.Logf("Unmarshal raw: %#v, %#v", raw, pv.Interface())
201
err := raw.Unmarshal(pv.Interface())
203
c.Assert(pv.Elem().Interface(), DeepEquals, value, Commentf("Failed on item %d: %#v", i, item))
207
func (s *S) TestUnmarshalRawIncompatible(c *C) {
208
raw := bson.Raw{0x08, []byte{0x01}} // true
209
err := raw.Unmarshal(&struct{}{})
210
c.Assert(err, ErrorMatches, "BSON kind 0x08 isn't compatible with type struct \\{\\}")
213
func (s *S) TestUnmarshalZeroesStruct(c *C) {
214
data, err := bson.Marshal(bson.M{"b": 2})
216
type T struct{ A, B int }
218
err = bson.Unmarshal(data, &v)
220
c.Assert(v.A, Equals, 0)
221
c.Assert(v.B, Equals, 2)
224
func (s *S) TestUnmarshalZeroesMap(c *C) {
225
data, err := bson.Marshal(bson.M{"b": 2})
228
err = bson.Unmarshal(data, &m)
230
c.Assert(m, DeepEquals, bson.M{"b": 2})
233
func (s *S) TestUnmarshalNonNilInterface(c *C) {
234
data, err := bson.Marshal(bson.M{"b": 2})
239
err = bson.Unmarshal(data, &i)
241
c.Assert(i, DeepEquals, bson.M{"b": 2})
242
c.Assert(m, DeepEquals, bson.M{"a": 1})
245
// --------------------------------------------------------------------------
246
// Some one way marshaling operations which would unmarshal differently.
248
var oneWayMarshalItems = []testItemType{
249
// These are being passed as pointers, and will unmarshal as values.
250
{bson.M{"": &bson.Binary{0x02, []byte("old")}},
251
"\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
252
{bson.M{"": &bson.Binary{0x80, []byte("udef")}},
253
"\x05\x00\x04\x00\x00\x00\x80udef"},
254
{bson.M{"": &bson.RegEx{"ab", "cd"}},
255
"\x0B\x00ab\x00cd\x00"},
256
{bson.M{"": &bson.JavaScript{"code", nil}},
257
"\x0D\x00\x05\x00\x00\x00code\x00"},
258
{bson.M{"": &bson.JavaScript{"code", bson.M{"": nil}}},
259
"\x0F\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" +
260
"\x07\x00\x00\x00\x0A\x00\x00"},
262
// There's no float32 type in BSON. Will encode as a float64.
263
{bson.M{"": float32(5.05)},
264
"\x01\x00\x00\x00\x00@33\x14@"},
266
// The array will be unmarshaled as a slice instead.
267
{bson.M{"": [2]bool{true, false}},
268
"\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
270
// The typed slice will be unmarshaled as []interface{}.
271
{bson.M{"": []bool{true, false}},
272
"\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"},
274
// Will unmarshal as a []byte.
275
{bson.M{"": bson.Binary{0x00, []byte("yo")}},
276
"\x05\x00\x02\x00\x00\x00\x00yo"},
277
{bson.M{"": bson.Binary{0x02, []byte("old")}},
278
"\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
280
// No way to preserve the type information here. We might encode as a zero
281
// value, but this would mean that pointer values in structs wouldn't be
282
// able to correctly distinguish between unset and set to the zero value.
283
{bson.M{"": (*byte)(nil)},
286
// No int types smaller than int32 in BSON. Could encode this as a char,
287
// but it would still be ambiguous, take more, and be awkward in Go when
288
// loaded without typing information.
289
{bson.M{"": byte(8)},
290
"\x10\x00\x08\x00\x00\x00"},
292
// There are no unsigned types in BSON. Will unmarshal as int32 or int64.
293
{bson.M{"": uint32(258)},
294
"\x10\x00\x02\x01\x00\x00"},
295
{bson.M{"": uint64(258)},
296
"\x12\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
297
{bson.M{"": uint64(258 << 32)},
298
"\x12\x00\x00\x00\x00\x00\x02\x01\x00\x00"},
300
// This will unmarshal as int.
301
{bson.M{"": int32(258)},
302
"\x10\x00\x02\x01\x00\x00"},
304
// That's a special case. The unsigned value is too large for an int32,
305
// so an int64 is used instead.
306
{bson.M{"": uint32(1<<32 - 1)},
307
"\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"},
308
{bson.M{"": uint(1<<32 - 1)},
309
"\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"},
312
func (s *S) TestOneWayMarshalItems(c *C) {
313
for i, item := range oneWayMarshalItems {
314
data, err := bson.Marshal(item.obj)
316
c.Assert(string(data), Equals, wrapInDoc(item.data),
317
Commentf("Failed on item %d", i))
321
// --------------------------------------------------------------------------
322
// Two-way tests for user-defined structures using the samples
323
// from bsonspec.org.
325
type specSample1 struct {
329
type specSample2 struct {
330
BSON []interface{} "BSON"
333
var structSampleItems = []testItemType{
334
{&specSample1{"world"},
335
"\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"},
336
{&specSample2{[]interface{}{"awesome", float64(5.05), 1986}},
337
"1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" +
338
"awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"},
341
func (s *S) TestMarshalStructSampleItems(c *C) {
342
for i, item := range structSampleItems {
343
data, err := bson.Marshal(item.obj)
345
c.Assert(string(data), Equals, item.data,
346
Commentf("Failed on item %d", i))
350
func (s *S) TestUnmarshalStructSampleItems(c *C) {
351
for _, item := range structSampleItems {
352
testUnmarshal(c, item.data, item.obj)
356
// --------------------------------------------------------------------------
357
// Generic two-way struct marshaling tests.
359
var bytevar = byte(8)
360
var byteptr = &bytevar
362
var structItems = []testItemType{
363
{&struct{ Ptr *byte }{nil},
365
{&struct{ Ptr *byte }{&bytevar},
366
"\x10ptr\x00\x08\x00\x00\x00"},
367
{&struct{ Ptr **byte }{&byteptr},
368
"\x10ptr\x00\x08\x00\x00\x00"},
369
{&struct{ Byte byte }{8},
370
"\x10byte\x00\x08\x00\x00\x00"},
371
{&struct{ Byte byte }{0},
372
"\x10byte\x00\x00\x00\x00\x00"},
376
"\x10Tag\x00\x08\x00\x00\x00"},
381
}{&struct{ Byte byte }{8}},
382
"\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"},
383
{&struct{ priv byte }{}, ""},
385
// The order of the dumped fields should be the same in the struct.
386
{&struct{ A, C, B, D, F, E *byte }{},
387
"\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x0Ae\x00"},
389
{&struct{ V bson.Raw }{bson.Raw{0x03, []byte("\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00")}},
390
"\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"},
391
{&struct{ V bson.Raw }{bson.Raw{0x10, []byte("\x00\x00\x00\x00")}},
392
"\x10v\x00" + "\x00\x00\x00\x00"},
395
{&struct{ V [2]byte }{[2]byte{'y', 'o'}},
396
"\x05v\x00\x02\x00\x00\x00\x00yo"},
399
func (s *S) TestMarshalStructItems(c *C) {
400
for i, item := range structItems {
401
data, err := bson.Marshal(item.obj)
403
c.Assert(string(data), Equals, wrapInDoc(item.data),
404
Commentf("Failed on item %d", i))
408
func (s *S) TestUnmarshalStructItems(c *C) {
409
for _, item := range structItems {
410
testUnmarshal(c, wrapInDoc(item.data), item.obj)
414
func (s *S) TestUnmarshalRawStructItems(c *C) {
415
for i, item := range structItems {
416
raw := bson.Raw{0x03, []byte(wrapInDoc(item.data))}
417
zero := makeZeroDoc(item.obj)
418
err := raw.Unmarshal(zero)
420
c.Assert(zero, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item))
424
func (s *S) TestUnmarshalRawNil(c *C) {
425
// Regression test: shouldn't try to nil out the pointer itself,
426
// as it's not settable.
427
raw := bson.Raw{0x0A, []byte{}}
428
err := raw.Unmarshal(&struct{}{})
432
// --------------------------------------------------------------------------
433
// One-way marshaling tests.
435
type dOnIface struct {
439
type ignoreField struct {
441
Ignore string `bson:"-"`
445
var marshalItems = []testItemType{
446
// Ordered document dump. Will unmarshal as a dictionary by default.
447
{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}},
448
"\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"},
449
{MyD{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}},
450
"\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"},
451
{&dOnIface{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}},
452
"\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")},
453
{&ignoreField{"before", "ignore", "after"},
454
"\x02before\x00\a\x00\x00\x00before\x00\x02after\x00\x06\x00\x00\x00after\x00"},
456
// Marshalling a Raw document does nothing.
457
{bson.Raw{0x03, []byte(wrapInDoc("anything"))},
459
{bson.Raw{Data: []byte(wrapInDoc("anything"))},
463
func (s *S) TestMarshalOneWayItems(c *C) {
464
for _, item := range marshalItems {
465
data, err := bson.Marshal(item.obj)
467
c.Assert(string(data), Equals, wrapInDoc(item.data))
471
// --------------------------------------------------------------------------
472
// One-way unmarshaling tests.
474
var unmarshalItems = []testItemType{
475
// Field is private. Should not attempt to unmarshal it.
476
{&struct{ priv byte }{},
477
"\x10priv\x00\x08\x00\x00\x00"},
479
// Wrong casing. Field names are lowercased.
480
{&struct{ Byte byte }{},
481
"\x10Byte\x00\x08\x00\x00\x00"},
483
// Ignore non-existing field.
484
{&struct{ Byte byte }{9},
485
"\x10boot\x00\x08\x00\x00\x00" + "\x10byte\x00\x09\x00\x00\x00"},
487
// Do not unmarshal on ignored field.
488
{&ignoreField{"before", "", "after"},
489
"\x02before\x00\a\x00\x00\x00before\x00" +
490
"\x02-\x00\a\x00\x00\x00ignore\x00" +
491
"\x02after\x00\x06\x00\x00\x00after\x00"},
493
// Ignore unsuitable types silently.
494
{map[string]string{"str": "s"},
495
"\x02str\x00\x02\x00\x00\x00s\x00" + "\x10int\x00\x01\x00\x00\x00"},
496
{map[string][]int{"array": []int{5, 9}},
497
"\x04array\x00" + wrapInDoc("\x100\x00\x05\x00\x00\x00"+"\x021\x00\x02\x00\x00\x00s\x00"+"\x102\x00\x09\x00\x00\x00")},
499
// Wrong type. Shouldn't init pointer.
500
{&struct{ Str *byte }{},
501
"\x02str\x00\x02\x00\x00\x00s\x00"},
502
{&struct{ Str *struct{ Str string } }{},
503
"\x02str\x00\x02\x00\x00\x00s\x00"},
506
{&struct{ bson.D }{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}},
507
"\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")},
510
{&bson.Raw{0x03, []byte(wrapInDoc("\x10byte\x00\x08\x00\x00\x00"))},
511
"\x10byte\x00\x08\x00\x00\x00"},
513
// Decode old binary.
514
{bson.M{"_": []byte("old")},
515
"\x05_\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
518
func (s *S) TestUnmarshalOneWayItems(c *C) {
519
for _, item := range unmarshalItems {
520
testUnmarshal(c, wrapInDoc(item.data), item.obj)
524
func (s *S) TestUnmarshalNilInStruct(c *C) {
525
// Nil is the default value, so we need to ensure it's indeed being set.
527
v := &struct{ Ptr *byte }{&b}
528
err := bson.Unmarshal([]byte(wrapInDoc("\x0Aptr\x00")), v)
530
c.Assert(v, DeepEquals, &struct{ Ptr *byte }{nil})
533
// --------------------------------------------------------------------------
534
// Marshalling error cases.
536
type structWithDupKeys struct {
538
Other byte "name" // Tag should precede.
541
var marshalErrorItems = []testItemType{
542
{bson.M{"": uint64(1 << 63)},
543
"BSON has no uint64 type, and value is too large to fit correctly in an int64"},
544
{bson.M{"": bson.ObjectId("tooshort")},
545
"ObjectIDs must be exactly 12 bytes long \\(got 8\\)"},
547
"Can't marshal int64 as a BSON document"},
549
"Can't marshal complex128 in a BSON document"},
550
{&structWithDupKeys{},
551
"Duplicated key 'name' in struct bson_test.structWithDupKeys"},
552
{bson.Raw{0x0A, []byte{}},
553
"Attempted to unmarshal Raw kind 10 as a document"},
554
{&inlineCantPtr{&struct{ A, B int }{1, 2}},
555
"Option ,inline needs a struct value or map field"},
556
{&inlineDupName{1, struct{ A, B int }{2, 3}},
557
"Duplicated key 'a' in struct bson_test.inlineDupName"},
559
"Multiple ,inline maps in struct bson_test.inlineDupMap"},
561
"Option ,inline needs a map with string keys in struct bson_test.inlineBadKeyMap"},
562
{&inlineMap{A: 1, M: map[string]interface{}{"a": 1}},
563
`Can't have key "a" in inlined map; conflicts with struct field`},
566
func (s *S) TestMarshalErrorItems(c *C) {
567
for _, item := range marshalErrorItems {
568
data, err := bson.Marshal(item.obj)
569
c.Assert(err, ErrorMatches, item.data)
570
c.Assert(data, IsNil)
574
// --------------------------------------------------------------------------
575
// Unmarshalling error cases.
577
type unmarshalErrorType struct {
583
var unmarshalErrorItems = []unmarshalErrorType{
584
// Tag name conflicts with existing parameter.
585
{&structWithDupKeys{},
586
"\x10name\x00\x08\x00\x00\x00",
587
"Duplicated key 'name' in struct bson_test.structWithDupKeys"},
589
// Non-string map key.
590
{map[int]interface{}{},
591
"\x10name\x00\x08\x00\x00\x00",
592
"BSON map must have string keys. Got: map\\[int\\]interface \\{\\}"},
596
"Unknown element kind \\(0xEE\\)"},
598
{struct{ Name bool }{},
599
"\x10name\x00\x08\x00\x00\x00",
600
"Unmarshal can't deal with struct values. Use a pointer."},
603
"\x10name\x00\x08\x00\x00\x00",
604
"Unmarshal needs a map or a pointer to a struct."},
607
func (s *S) TestUnmarshalErrorItems(c *C) {
608
for _, item := range unmarshalErrorItems {
609
data := []byte(wrapInDoc(item.data))
610
var value interface{}
611
switch reflect.ValueOf(item.obj).Kind() {
612
case reflect.Map, reflect.Ptr:
613
value = makeZeroDoc(item.obj)
614
case reflect.Invalid:
619
err := bson.Unmarshal(data, value)
620
c.Assert(err, ErrorMatches, item.error)
624
type unmarshalRawErrorType struct {
630
var unmarshalRawErrorItems = []unmarshalRawErrorType{
631
// Tag name conflicts with existing parameter.
632
{&structWithDupKeys{},
633
bson.Raw{0x03, []byte("\x10byte\x00\x08\x00\x00\x00")},
634
"Duplicated key 'name' in struct bson_test.structWithDupKeys"},
637
bson.Raw{0xEE, []byte{}},
638
"Unknown element kind \\(0xEE\\)"},
640
{struct{ Name bool }{},
641
bson.Raw{0x10, []byte("\x08\x00\x00\x00")},
642
"Raw Unmarshal can't deal with struct values. Use a pointer."},
645
bson.Raw{0x10, []byte("\x08\x00\x00\x00")},
646
"Raw Unmarshal needs a map or a valid pointer."},
649
func (s *S) TestUnmarshalRawErrorItems(c *C) {
650
for i, item := range unmarshalRawErrorItems {
651
err := item.raw.Unmarshal(item.obj)
652
c.Assert(err, ErrorMatches, item.error, Commentf("Failed on item %d: %#v\n", i, item))
656
var corruptedData = []string{
657
"\x04\x00\x00\x00\x00", // Shorter than minimum
658
"\x06\x00\x00\x00\x00", // Not enough data
659
"\x05\x00\x00", // Broken length
660
"\x05\x00\x00\x00\xff", // Corrupted termination
661
"\x0A\x00\x00\x00\x0Aooop\x00", // Unfinished C string
663
// Array end past end of string (s[2]=0x07 is correct)
664
wrapInDoc("\x04\x00\x09\x00\x00\x00\x0A\x00\x00"),
666
// Array end within string, but past acceptable.
667
wrapInDoc("\x04\x00\x08\x00\x00\x00\x0A\x00\x00"),
669
// Document end within string, but past acceptable.
670
wrapInDoc("\x03\x00\x08\x00\x00\x00\x0A\x00\x00"),
672
// String with corrupted end.
673
wrapInDoc("\x02\x00\x03\x00\x00\x00yo\xFF"),
676
func (s *S) TestUnmarshalMapDocumentTooShort(c *C) {
677
for _, data := range corruptedData {
678
err := bson.Unmarshal([]byte(data), bson.M{})
679
c.Assert(err, ErrorMatches, "Document is corrupted")
681
err = bson.Unmarshal([]byte(data), &struct{}{})
682
c.Assert(err, ErrorMatches, "Document is corrupted")
686
// --------------------------------------------------------------------------
687
// Setter test cases.
689
var setterResult = map[string]error{}
691
type setterType struct {
695
func (o *setterType) SetBSON(raw bson.Raw) error {
696
err := raw.Unmarshal(&o.received)
698
panic("The panic:" + err.Error())
700
if s, ok := o.received.(string); ok {
701
if result, ok := setterResult[s]; ok {
708
type ptrSetterDoc struct {
709
Field *setterType "_"
712
type valSetterDoc struct {
716
func (s *S) TestUnmarshalAllItemsWithPtrSetter(c *C) {
717
for _, item := range allItems {
718
for i := 0; i != 2; i++ {
719
var field *setterType
721
obj := &ptrSetterDoc{}
722
err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj)
726
obj := &valSetterDoc{}
727
err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj)
732
// Nothing to unmarshal. Should be untouched.
734
c.Assert(field, IsNil)
736
c.Assert(field.received, IsNil)
739
expected := item.obj.(bson.M)["_"]
740
c.Assert(field, NotNil, Commentf("Pointer not initialized (%#v)", expected))
741
c.Assert(field.received, DeepEquals, expected)
747
func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) {
749
err := bson.Unmarshal([]byte(sampleItems[0].data), obj)
751
c.Assert(obj.received, DeepEquals, bson.M{"hello": "world"})
754
func (s *S) TestUnmarshalSetterOmits(c *C) {
755
setterResult["2"] = &bson.TypeError{}
756
setterResult["4"] = &bson.TypeError{}
758
delete(setterResult, "2")
759
delete(setterResult, "4")
762
m := map[string]*setterType{}
763
data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" +
764
"\x02def\x00\x02\x00\x00\x002\x00" +
765
"\x02ghi\x00\x02\x00\x00\x003\x00" +
766
"\x02jkl\x00\x02\x00\x00\x004\x00")
767
err := bson.Unmarshal([]byte(data), m)
769
c.Assert(m["abc"], NotNil)
770
c.Assert(m["def"], IsNil)
771
c.Assert(m["ghi"], NotNil)
772
c.Assert(m["jkl"], IsNil)
774
c.Assert(m["abc"].received, Equals, "1")
775
c.Assert(m["ghi"].received, Equals, "3")
778
func (s *S) TestUnmarshalSetterErrors(c *C) {
779
boom := errors.New("BOOM")
780
setterResult["2"] = boom
781
defer delete(setterResult, "2")
783
m := map[string]*setterType{}
784
data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" +
785
"\x02def\x00\x02\x00\x00\x002\x00" +
786
"\x02ghi\x00\x02\x00\x00\x003\x00")
787
err := bson.Unmarshal([]byte(data), m)
788
c.Assert(err, Equals, boom)
789
c.Assert(m["abc"], NotNil)
790
c.Assert(m["def"], IsNil)
791
c.Assert(m["ghi"], IsNil)
793
c.Assert(m["abc"].received, Equals, "1")
796
func (s *S) TestDMap(c *C) {
797
d := bson.D{{"a", 1}, {"b", 2}}
798
c.Assert(d.Map(), DeepEquals, bson.M{"a": 1, "b": 2})
801
func (s *S) TestUnmarshalSetterSetZero(c *C) {
802
setterResult["foo"] = bson.SetZero
803
defer delete(setterResult, "field")
805
data, err := bson.Marshal(bson.M{"field": "foo"})
808
m := map[string]*setterType{}
809
err = bson.Unmarshal([]byte(data), m)
812
value, ok := m["field"]
813
c.Assert(ok, Equals, true)
814
c.Assert(value, IsNil)
818
// --------------------------------------------------------------------------
819
// Getter test cases.
821
type typeWithGetter struct {
826
func (t *typeWithGetter) GetBSON() (interface{}, error) {
827
return t.result, t.err
830
type docWithGetterField struct {
831
Field *typeWithGetter "_"
834
func (s *S) TestMarshalAllItemsWithGetter(c *C) {
835
for i, item := range allItems {
839
obj := &docWithGetterField{}
840
obj.Field = &typeWithGetter{result: item.obj.(bson.M)["_"]}
841
data, err := bson.Marshal(obj)
843
c.Assert(string(data), Equals, wrapInDoc(item.data),
844
Commentf("Failed on item #%d", i))
848
func (s *S) TestMarshalWholeDocumentWithGetter(c *C) {
849
obj := &typeWithGetter{result: sampleItems[0].obj}
850
data, err := bson.Marshal(obj)
852
c.Assert(string(data), Equals, sampleItems[0].data)
855
func (s *S) TestGetterErrors(c *C) {
856
e := errors.New("oops")
858
obj1 := &docWithGetterField{}
859
obj1.Field = &typeWithGetter{sampleItems[0].obj, e}
860
data, err := bson.Marshal(obj1)
861
c.Assert(err, ErrorMatches, "oops")
862
c.Assert(data, IsNil)
864
obj2 := &typeWithGetter{sampleItems[0].obj, e}
865
data, err = bson.Marshal(obj2)
866
c.Assert(err, ErrorMatches, "oops")
867
c.Assert(data, IsNil)
872
func (t intGetter) GetBSON() (interface{}, error) {
876
type typeWithIntGetter struct {
877
V intGetter ",minsize"
880
func (s *S) TestMarshalShortWithGetter(c *C) {
881
obj := typeWithIntGetter{42}
882
data, err := bson.Marshal(obj)
885
err = bson.Unmarshal(data, m)
886
c.Assert(m["v"], Equals, 42)
889
// --------------------------------------------------------------------------
890
// Cross-type conversion tests.
892
type crossTypeItem struct {
897
type condStr struct {
898
V string ",omitempty"
900
type condStrNS struct {
901
V string `a:"A" bson:",omitempty" b:"B"`
903
type condBool struct {
906
type condInt struct {
909
type condUInt struct {
912
type condFloat struct {
913
V float64 ",omitempty"
915
type condIface struct {
916
V interface{} ",omitempty"
918
type condPtr struct {
921
type condSlice struct {
922
V []string ",omitempty"
924
type condMap struct {
925
V map[string]int ",omitempty"
927
type namedCondStr struct {
928
V string "myv,omitempty"
930
type condTime struct {
931
V time.Time ",omitempty"
934
type shortInt struct {
937
type shortUint struct {
940
type shortIface struct {
941
V interface{} ",minsize"
943
type shortPtr struct {
946
type shortNonEmptyInt struct {
947
V int64 ",minsize,omitempty"
950
type inlineInt struct {
951
V struct{ A, B int } ",inline"
953
type inlineCantPtr struct {
954
V *struct{ A, B int } ",inline"
956
type inlineDupName struct {
958
V struct{ A, B int } ",inline"
960
type inlineMap struct {
962
M map[string]interface{} ",inline"
964
type inlineMapInt struct {
966
M map[string]int ",inline"
968
type inlineMapMyM struct {
972
type inlineDupMap struct {
973
M1 map[string]interface{} ",inline"
974
M2 map[string]interface{} ",inline"
976
type inlineBadKeyMap struct {
977
M map[int]int ",inline"
982
type MyD []bson.DocElem
983
type MyM map[string]interface{}
988
var int64var = int64(42)
989
var int64ptr = &int64var
993
func parseURL(s string) *url.URL {
994
u, err := url.Parse(s)
1001
// That's a pretty fun test. It will dump the first item, generate a zero
1002
// value equivalent to the second one, load the dumped data onto it, and then
1003
// verify that the resulting value is deep-equal to the untouched second value.
1004
// Then, it will do the same in the *opposite* direction!
1005
var twoWayCrossItems = []crossTypeItem{
1007
{&struct{ I int }{42}, &struct{ I int8 }{42}},
1008
{&struct{ I int }{42}, &struct{ I int32 }{42}},
1009
{&struct{ I int }{42}, &struct{ I int64 }{42}},
1010
{&struct{ I int8 }{42}, &struct{ I int32 }{42}},
1011
{&struct{ I int8 }{42}, &struct{ I int64 }{42}},
1012
{&struct{ I int32 }{42}, &struct{ I int64 }{42}},
1015
{&struct{ I uint }{42}, &struct{ I uint8 }{42}},
1016
{&struct{ I uint }{42}, &struct{ I uint32 }{42}},
1017
{&struct{ I uint }{42}, &struct{ I uint64 }{42}},
1018
{&struct{ I uint8 }{42}, &struct{ I uint32 }{42}},
1019
{&struct{ I uint8 }{42}, &struct{ I uint64 }{42}},
1020
{&struct{ I uint32 }{42}, &struct{ I uint64 }{42}},
1022
// float32<=>float64
1023
{&struct{ I float32 }{42}, &struct{ I float64 }{42}},
1026
{&struct{ I uint }{42}, &struct{ I int }{42}},
1027
{&struct{ I uint }{42}, &struct{ I int8 }{42}},
1028
{&struct{ I uint }{42}, &struct{ I int32 }{42}},
1029
{&struct{ I uint }{42}, &struct{ I int64 }{42}},
1030
{&struct{ I uint8 }{42}, &struct{ I int }{42}},
1031
{&struct{ I uint8 }{42}, &struct{ I int8 }{42}},
1032
{&struct{ I uint8 }{42}, &struct{ I int32 }{42}},
1033
{&struct{ I uint8 }{42}, &struct{ I int64 }{42}},
1034
{&struct{ I uint32 }{42}, &struct{ I int }{42}},
1035
{&struct{ I uint32 }{42}, &struct{ I int8 }{42}},
1036
{&struct{ I uint32 }{42}, &struct{ I int32 }{42}},
1037
{&struct{ I uint32 }{42}, &struct{ I int64 }{42}},
1038
{&struct{ I uint64 }{42}, &struct{ I int }{42}},
1039
{&struct{ I uint64 }{42}, &struct{ I int8 }{42}},
1040
{&struct{ I uint64 }{42}, &struct{ I int32 }{42}},
1041
{&struct{ I uint64 }{42}, &struct{ I int64 }{42}},
1044
{&struct{ I int }{42}, &struct{ I float64 }{42}},
1047
{&struct{ I int }{1}, &struct{ I bool }{true}},
1048
{&struct{ I int }{0}, &struct{ I bool }{false}},
1051
{&struct{ I uint }{42}, &struct{ I float64 }{42}},
1054
{&struct{ I uint }{1}, &struct{ I bool }{true}},
1055
{&struct{ I uint }{0}, &struct{ I bool }{false}},
1058
{&struct{ I float64 }{1}, &struct{ I bool }{true}},
1059
{&struct{ I float64 }{0}, &struct{ I bool }{false}},
1061
// string <=> string and string <=> []byte
1062
{&struct{ S []byte }{[]byte("abc")}, &struct{ S string }{"abc"}},
1063
{&struct{ S []byte }{[]byte("def")}, &struct{ S bson.Symbol }{"def"}},
1064
{&struct{ S string }{"ghi"}, &struct{ S bson.Symbol }{"ghi"}},
1071
}{struct{ B, C int }{1, 2}},
1072
map[string]map[string]int{"a": map[string]int{"b": 1, "c": 2}}},
1074
{&struct{ A bson.Symbol }{"abc"}, map[string]string{"a": "abc"}},
1075
{&struct{ A bson.Symbol }{"abc"}, map[string][]byte{"a": []byte("abc")}},
1076
{&struct{ A []byte }{[]byte("abc")}, map[string]string{"a": "abc"}},
1077
{&struct{ A uint }{42}, map[string]int{"a": 42}},
1078
{&struct{ A uint }{42}, map[string]float64{"a": 42}},
1079
{&struct{ A uint }{1}, map[string]bool{"a": true}},
1080
{&struct{ A int }{42}, map[string]uint{"a": 42}},
1081
{&struct{ A int }{42}, map[string]float64{"a": 42}},
1082
{&struct{ A int }{1}, map[string]bool{"a": true}},
1083
{&struct{ A float64 }{42}, map[string]float32{"a": 42}},
1084
{&struct{ A float64 }{42}, map[string]int{"a": 42}},
1085
{&struct{ A float64 }{42}, map[string]uint{"a": 42}},
1086
{&struct{ A float64 }{1}, map[string]bool{"a": true}},
1087
{&struct{ A bool }{true}, map[string]int{"a": 1}},
1088
{&struct{ A bool }{true}, map[string]uint{"a": 1}},
1089
{&struct{ A bool }{true}, map[string]float64{"a": 1}},
1090
{&struct{ A **byte }{&byteptr}, map[string]byte{"a": 8}},
1092
// url.URL <=> string
1093
{&struct{ URL *url.URL }{parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}},
1094
{&struct{ URL url.URL }{*parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}},
1097
{&struct{ S []int }{[]int{1, 2, 3}}, map[string][]int{"s": []int{1, 2, 3}}},
1098
{&struct{ S *[]int }{&[]int{1, 2, 3}}, map[string][]int{"s": []int{1, 2, 3}}},
1101
{&condBool{true}, map[string]bool{"v": true}},
1102
{&condBool{}, map[string]bool{}},
1103
{&condInt{1}, map[string]int{"v": 1}},
1104
{&condInt{}, map[string]int{}},
1105
{&condUInt{1}, map[string]uint{"v": 1}},
1106
{&condUInt{}, map[string]uint{}},
1107
{&condFloat{}, map[string]int{}},
1108
{&condStr{"yo"}, map[string]string{"v": "yo"}},
1109
{&condStr{}, map[string]string{}},
1110
{&condStrNS{"yo"}, map[string]string{"v": "yo"}},
1111
{&condStrNS{}, map[string]string{}},
1112
{&condSlice{[]string{"yo"}}, map[string][]string{"v": []string{"yo"}}},
1113
{&condSlice{}, map[string][]string{}},
1114
{&condMap{map[string]int{"k": 1}}, bson.M{"v": bson.M{"k": 1}}},
1115
{&condMap{}, map[string][]string{}},
1116
{&condIface{"yo"}, map[string]string{"v": "yo"}},
1117
{&condIface{""}, map[string]string{"v": ""}},
1118
{&condIface{}, map[string]string{}},
1119
{&condPtr{&truevar}, map[string]bool{"v": true}},
1120
{&condPtr{&falsevar}, map[string]bool{"v": false}},
1121
{&condPtr{}, map[string]string{}},
1123
{&condTime{time.Unix(123456789, 123e6)}, map[string]time.Time{"v": time.Unix(123456789, 123e6)}},
1124
{&condTime{}, map[string]string{}},
1126
{&namedCondStr{"yo"}, map[string]string{"myv": "yo"}},
1127
{&namedCondStr{}, map[string]string{}},
1129
{&shortInt{1}, map[string]interface{}{"v": 1}},
1130
{&shortInt{1 << 30}, map[string]interface{}{"v": 1 << 30}},
1131
{&shortInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1132
{&shortUint{1 << 30}, map[string]interface{}{"v": 1 << 30}},
1133
{&shortUint{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1134
{&shortIface{int64(1) << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1135
{&shortPtr{int64ptr}, map[string]interface{}{"v": intvar}},
1137
{&shortNonEmptyInt{1}, map[string]interface{}{"v": 1}},
1138
{&shortNonEmptyInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
1139
{&shortNonEmptyInt{}, map[string]interface{}{}},
1141
{&inlineInt{struct{ A, B int }{1, 2}}, map[string]interface{}{"a": 1, "b": 2}},
1142
{&inlineMap{A: 1, M: map[string]interface{}{"b": 2}}, map[string]interface{}{"a": 1, "b": 2}},
1143
{&inlineMap{A: 1, M: nil}, map[string]interface{}{"a": 1}},
1144
{&inlineMapInt{A: 1, M: map[string]int{"b": 2}}, map[string]int{"a": 1, "b": 2}},
1145
{&inlineMapInt{A: 1, M: nil}, map[string]int{"a": 1}},
1146
{&inlineMapMyM{A: 1, M: MyM{"b": MyM{"c": 3}}}, map[string]interface{}{"a": 1, "b": map[string]interface{}{"c": 3}}},
1148
// []byte <=> MyBytes
1149
{&struct{ B MyBytes }{[]byte("abc")}, map[string]string{"b": "abc"}},
1150
{&struct{ B MyBytes }{[]byte{}}, map[string]string{"b": ""}},
1151
{&struct{ B MyBytes }{}, map[string]bool{}},
1152
{&struct{ B []byte }{[]byte("abc")}, map[string]MyBytes{"b": []byte("abc")}},
1155
{&struct{ B MyBool }{true}, map[string]bool{"b": true}},
1156
{&struct{ B MyBool }{}, map[string]bool{"b": false}},
1157
{&struct{ B MyBool }{}, map[string]string{}},
1158
{&struct{ B bool }{}, map[string]MyBool{"b": false}},
1161
{&struct{ V [2]int }{[...]int{1, 2}}, map[string][2]int{"v": [2]int{1, 2}}},
1164
{&struct{ V time.Time }{}, map[string]interface{}{"v": time.Time{}}},
1166
// zero time + 1 second + 1 millisecond; overflows int64 as nanoseconds
1167
{&struct{ V time.Time }{time.Unix(-62135596799, 1e6).Local()},
1168
map[string]interface{}{"v": time.Unix(-62135596799, 1e6).Local()}},
1170
// bson.D <=> []DocElem
1171
{&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}},
1172
{&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &MyD{{"a", MyD{{"b", 1}, {"c", 2}}}}},
1175
{bson.M{"a": bson.M{"b": 1, "c": 2}}, MyM{"a": MyM{"b": 1, "c": 2}}},
1176
{bson.M{"a": bson.M{"b": 1, "c": 2}}, map[string]interface{}{"a": map[string]interface{}{"b": 1, "c": 2}}},
1179
// Same thing, but only one way (obj1 => obj2).
1180
var oneWayCrossItems = []crossTypeItem{
1182
{map[string]interface{}{"a": 1, "b": "2", "c": 3}, map[string]int{"a": 1, "c": 3}},
1184
// inline map elides badly typed values
1185
{map[string]interface{}{"a": 1, "b": "2", "c": 3}, &inlineMapInt{A: 1, M: map[string]int{"c": 3}}},
1187
// Can't decode int into struct.
1188
{bson.M{"a": bson.M{"b": 2}}, &struct{ A bool }{}},
1190
// Would get decoded into a int32 too in the opposite direction.
1191
{&shortIface{int64(1) << 30}, map[string]interface{}{"v": 1 << 30}},
1194
func testCrossPair(c *C, dump interface{}, load interface{}) {
1195
c.Logf("Dump: %#v", dump)
1196
c.Logf("Load: %#v", load)
1197
zero := makeZeroDoc(load)
1198
data, err := bson.Marshal(dump)
1199
c.Assert(err, IsNil)
1200
c.Logf("Dumped: %#v", string(data))
1201
err = bson.Unmarshal(data, zero)
1202
c.Assert(err, IsNil)
1203
c.Logf("Loaded: %#v", zero)
1204
c.Assert(zero, DeepEquals, load)
1207
func (s *S) TestTwoWayCrossPairs(c *C) {
1208
for _, item := range twoWayCrossItems {
1209
testCrossPair(c, item.obj1, item.obj2)
1210
testCrossPair(c, item.obj2, item.obj1)
1214
func (s *S) TestOneWayCrossPairs(c *C) {
1215
for _, item := range oneWayCrossItems {
1216
testCrossPair(c, item.obj1, item.obj2)
1220
// --------------------------------------------------------------------------
1221
// ObjectId hex representation test.
1223
func (s *S) TestObjectIdHex(c *C) {
1224
id := bson.ObjectIdHex("4d88e15b60f486e428412dc9")
1225
c.Assert(id.String(), Equals, `ObjectIdHex("4d88e15b60f486e428412dc9")`)
1226
c.Assert(id.Hex(), Equals, "4d88e15b60f486e428412dc9")
1229
func (s *S) TestIsObjectIdHex(c *C) {
1230
test := []struct{ id string; valid bool }{
1231
{"4d88e15b60f486e428412dc9", true},
1232
{"4d88e15b60f486e428412dc", false},
1233
{"4d88e15b60f486e428412dc9e", false},
1234
{"4d88e15b60f486e428412dcx", false},
1236
for _, t := range test {
1237
c.Assert(bson.IsObjectIdHex(t.id), Equals, t.valid)
1241
// --------------------------------------------------------------------------
1242
// ObjectId parts extraction tests.
1244
type objectIdParts struct {
1252
var objectIds = []objectIdParts{
1254
bson.ObjectIdHex("4d88e15b60f486e428412dc9"),
1256
[]byte{0x60, 0xf4, 0x86},
1261
bson.ObjectIdHex("000000000000000000000000"),
1263
[]byte{0x00, 0x00, 0x00},
1268
bson.ObjectIdHex("00000000aabbccddee000001"),
1270
[]byte{0xaa, 0xbb, 0xcc},
1276
func (s *S) TestObjectIdPartsExtraction(c *C) {
1277
for i, v := range objectIds {
1278
t := time.Unix(v.timestamp, 0)
1279
c.Assert(v.id.Time(), Equals, t, Commentf("#%d Wrong timestamp value", i))
1280
c.Assert(v.id.Machine(), DeepEquals, v.machine, Commentf("#%d Wrong machine id value", i))
1281
c.Assert(v.id.Pid(), Equals, v.pid, Commentf("#%d Wrong pid value", i))
1282
c.Assert(v.id.Counter(), Equals, v.counter, Commentf("#%d Wrong counter value", i))
1286
func (s *S) TestNow(c *C) {
1287
before := time.Now()
1292
c.Assert(now.After(before) && now.Before(after), Equals, true, Commentf("now=%s, before=%s, after=%s", now, before, after))
1295
// --------------------------------------------------------------------------
1296
// ObjectId generation tests.
1298
func (s *S) TestNewObjectId(c *C) {
1300
ids := make([]bson.ObjectId, 10)
1301
for i := 0; i < 10; i++ {
1302
ids[i] = bson.NewObjectId()
1304
for i := 1; i < 10; i++ {
1307
// Test for uniqueness among all other 9 generated ids
1308
for j, tid := range ids {
1310
c.Assert(id, Not(Equals), tid, Commentf("Generated ObjectId is not unique"))
1313
// Check that timestamp was incremented and is within 30 seconds of the previous one
1314
secs := id.Time().Sub(prevId.Time()).Seconds()
1315
c.Assert((secs >= 0 && secs <= 30), Equals, true, Commentf("Wrong timestamp in generated ObjectId"))
1316
// Check that machine ids are the same
1317
c.Assert(id.Machine(), DeepEquals, prevId.Machine())
1318
// Check that pids are the same
1319
c.Assert(id.Pid(), Equals, prevId.Pid())
1320
// Test for proper increment
1321
delta := int(id.Counter() - prevId.Counter())
1322
c.Assert(delta, Equals, 1, Commentf("Wrong increment in generated ObjectId"))
1326
func (s *S) TestNewObjectIdWithTime(c *C) {
1327
t := time.Unix(12345678, 0)
1328
id := bson.NewObjectIdWithTime(t)
1329
c.Assert(id.Time(), Equals, t)
1330
c.Assert(id.Machine(), DeepEquals, []byte{0x00, 0x00, 0x00})
1331
c.Assert(int(id.Pid()), Equals, 0)
1332
c.Assert(int(id.Counter()), Equals, 0)
1335
// --------------------------------------------------------------------------
1336
// ObjectId JSON marshalling.
1338
type jsonType struct {
1342
func (s *S) TestObjectIdJSONMarshaling(c *C) {
1343
id := bson.ObjectIdHex("4d88e15b60f486e428412dc9")
1344
v := jsonType{Id: &id}
1345
data, err := json.Marshal(&v)
1346
c.Assert(err, IsNil)
1347
c.Assert(string(data), Equals, `{"Id":"4d88e15b60f486e428412dc9"}`)
1350
func (s *S) TestObjectIdJSONUnmarshaling(c *C) {
1351
data := []byte(`{"Id":"4d88e15b60f486e428412dc9"}`)
1353
err := json.Unmarshal(data, &v)
1354
c.Assert(err, IsNil)
1355
c.Assert(*v.Id, Equals, bson.ObjectIdHex("4d88e15b60f486e428412dc9"))
1358
func (s *S) TestObjectIdJSONUnmarshalingError(c *C) {
1360
err := json.Unmarshal([]byte(`{"Id":"4d88e15b60f486e428412dc9A"}`), &v)
1361
c.Assert(err, ErrorMatches, `Invalid ObjectId in JSON: "4d88e15b60f486e428412dc9A"`)
1362
err = json.Unmarshal([]byte(`{"Id":"4d88e15b60f486e428412dcZ"}`), &v)
1363
c.Assert(err, ErrorMatches, `Invalid ObjectId in JSON: "4d88e15b60f486e428412dcZ" .*`)
1366
// --------------------------------------------------------------------------
1367
// Some simple benchmarks.
1369
type BenchT struct {
1370
A, B, C, D, E, F string
1373
func BenchmarkUnmarhsalStruct(b *testing.B) {
1374
v := BenchT{A: "A", D: "D", E: "E"}
1375
data, err := bson.Marshal(&v)
1380
for i := 0; i < b.N; i++ {
1381
err = bson.Unmarshal(data, &v)
1388
func BenchmarkUnmarhsalMap(b *testing.B) {
1389
m := bson.M{"a": "a", "d": "d", "e": "e"}
1390
data, err := bson.Marshal(&m)
1395
for i := 0; i < b.N; i++ {
1396
err = bson.Unmarshal(data, &m)