~juju-qa/ubuntu/yakkety/juju/2.0-rc3-again

« back to all changes in this revision

Viewing changes to src/labix.org/v2/mgo/bson/bson_test.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-04-24 22:34:47 UTC
  • Revision ID: package-import@ubuntu.com-20130424223447-f0qdji7ubnyo0s71
Tags: upstream-1.10.0.1
ImportĀ upstreamĀ versionĀ 1.10.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// BSON library for Go
 
2
// 
 
3
// Copyright (c) 2010-2012 - Gustavo Niemeyer <gustavo@niemeyer.net>
 
4
// 
 
5
// All rights reserved.
 
6
//
 
7
// Redistribution and use in source and binary forms, with or without
 
8
// modification, are permitted provided that the following conditions are met: 
 
9
// 
 
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. 
 
15
// 
 
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.
 
27
 
 
28
package bson_test
 
29
 
 
30
import (
 
31
        "encoding/binary"
 
32
        "encoding/json"
 
33
        "errors"
 
34
        . "launchpad.net/gocheck"
 
35
        "labix.org/v2/mgo/bson"
 
36
        "net/url"
 
37
        "reflect"
 
38
        "testing"
 
39
        "time"
 
40
)
 
41
 
 
42
func TestAll(t *testing.T) {
 
43
        TestingT(t)
 
44
}
 
45
 
 
46
type S struct{}
 
47
 
 
48
var _ = Suite(&S{})
 
49
 
 
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))
 
56
        return string(result)
 
57
}
 
58
 
 
59
func makeZeroDoc(value interface{}) (zero interface{}) {
 
60
        v := reflect.ValueOf(value)
 
61
        t := v.Type()
 
62
        switch t.Kind() {
 
63
        case reflect.Map:
 
64
                mv := reflect.MakeMap(t)
 
65
                zero = mv.Interface()
 
66
        case reflect.Ptr:
 
67
                pv := reflect.New(v.Type().Elem())
 
68
                zero = pv.Interface()
 
69
        case reflect.Slice:
 
70
                zero = reflect.New(t).Interface()
 
71
        default:
 
72
                panic("unsupported doc type")
 
73
        }
 
74
        return zero
 
75
}
 
76
 
 
77
func testUnmarshal(c *C, data string, obj interface{}) {
 
78
        zero := makeZeroDoc(obj)
 
79
        err := bson.Unmarshal([]byte(data), zero)
 
80
        c.Assert(err, IsNil)
 
81
        c.Assert(zero, DeepEquals, obj)
 
82
}
 
83
 
 
84
type testItemType struct {
 
85
        obj  interface{}
 
86
        data string
 
87
}
 
88
 
 
89
// --------------------------------------------------------------------------
 
90
// Samples from bsonspec.org:
 
91
 
 
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"},
 
98
}
 
99
 
 
100
func (s *S) TestMarshalSampleItems(c *C) {
 
101
        for i, item := range sampleItems {
 
102
                data, err := bson.Marshal(item.obj)
 
103
                c.Assert(err, IsNil)
 
104
                c.Assert(string(data), Equals, item.data, Commentf("Failed on item %d", i))
 
105
        }
 
106
}
 
107
 
 
108
func (s *S) TestUnmarshalSampleItems(c *C) {
 
109
        for i, item := range sampleItems {
 
110
                value := bson.M{}
 
111
                err := bson.Unmarshal([]byte(item.data), value)
 
112
                c.Assert(err, IsNil)
 
113
                c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d", i))
 
114
        }
 
115
}
 
116
 
 
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.
 
121
 
 
122
var allItems = []testItemType{
 
123
        {bson.M{},
 
124
                ""},
 
125
        {bson.M{"_": float64(5.05)},
 
126
                "\x01_\x00333333\x14@"},
 
127
        {bson.M{"_": "yo"},
 
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.
 
138
                "\x06_\x00"},
 
139
        {bson.M{"_": bson.ObjectId("0123456789ab")},
 
140
                "\x07_\x000123456789ab"},
 
141
        {bson.M{"_": false},
 
142
                "\x08_\x00\x00"},
 
143
        {bson.M{"_": true},
 
144
                "\x08_\x00\x01"},
 
145
        {bson.M{"_": time.Unix(0, 258e6)}, // Note the NS <=> MS conversion.
 
146
                "\x09_\x00\x02\x01\x00\x00\x00\x00\x00\x00"},
 
147
        {bson.M{"_": nil},
 
148
                "\x0A_\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"},
 
158
        {bson.M{"_": 258},
 
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},
 
167
                "\x7F_\x00"},
 
168
        {bson.M{"_": bson.MinKey},
 
169
                "\xFF_\x00"},
 
170
}
 
171
 
 
172
func (s *S) TestMarshalAllItems(c *C) {
 
173
        for i, item := range allItems {
 
174
                data, err := bson.Marshal(item.obj)
 
175
                c.Assert(err, IsNil)
 
176
                c.Assert(string(data), Equals, wrapInDoc(item.data), Commentf("Failed on item %d: %#v", i, item))
 
177
        }
 
178
}
 
179
 
 
180
func (s *S) TestUnmarshalAllItems(c *C) {
 
181
        for i, item := range allItems {
 
182
                value := bson.M{}
 
183
                err := bson.Unmarshal([]byte(wrapInDoc(item.data)), value)
 
184
                c.Assert(err, IsNil)
 
185
                c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item))
 
186
        }
 
187
}
 
188
 
 
189
func (s *S) TestUnmarshalRawAllItems(c *C) {
 
190
        for i, item := range allItems {
 
191
                if len(item.data) == 0 {
 
192
                        continue
 
193
                }
 
194
                value := item.obj.(bson.M)["_"]
 
195
                if value == nil {
 
196
                        continue
 
197
                }
 
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())
 
202
                c.Assert(err, IsNil)
 
203
                c.Assert(pv.Elem().Interface(), DeepEquals, value, Commentf("Failed on item %d: %#v", i, item))
 
204
        }
 
205
}
 
206
 
 
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 \\{\\}")
 
211
}
 
212
 
 
213
func (s *S) TestUnmarshalZeroesStruct(c *C) {
 
214
        data, err := bson.Marshal(bson.M{"b": 2})
 
215
        c.Assert(err, IsNil)
 
216
        type T struct{ A, B int }
 
217
        v := T{A: 1}
 
218
        err = bson.Unmarshal(data, &v)
 
219
        c.Assert(err, IsNil)
 
220
        c.Assert(v.A, Equals, 0)
 
221
        c.Assert(v.B, Equals, 2)
 
222
}
 
223
 
 
224
func (s *S) TestUnmarshalZeroesMap(c *C) {
 
225
        data, err := bson.Marshal(bson.M{"b": 2})
 
226
        c.Assert(err, IsNil)
 
227
        m := bson.M{"a": 1}
 
228
        err = bson.Unmarshal(data, &m)
 
229
        c.Assert(err, IsNil)
 
230
        c.Assert(m, DeepEquals, bson.M{"b": 2})
 
231
}
 
232
 
 
233
func (s *S) TestUnmarshalNonNilInterface(c *C) {
 
234
        data, err := bson.Marshal(bson.M{"b": 2})
 
235
        c.Assert(err, IsNil)
 
236
        m := bson.M{"a": 1}
 
237
        var i interface{}
 
238
        i = m
 
239
        err = bson.Unmarshal(data, &i)
 
240
        c.Assert(err, IsNil)
 
241
        c.Assert(i, DeepEquals, bson.M{"b": 2})
 
242
        c.Assert(m, DeepEquals, bson.M{"a": 1})
 
243
}
 
244
 
 
245
// --------------------------------------------------------------------------
 
246
// Some one way marshaling operations which would unmarshal differently.
 
247
 
 
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"},
 
261
 
 
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@"},
 
265
 
 
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"},
 
269
 
 
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"},
 
273
 
 
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"},
 
279
 
 
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)},
 
284
                "\x0A\x00"},
 
285
 
 
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"},
 
291
 
 
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"},
 
299
 
 
300
        // This will unmarshal as int.
 
301
        {bson.M{"": int32(258)},
 
302
                "\x10\x00\x02\x01\x00\x00"},
 
303
 
 
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"},
 
310
}
 
311
 
 
312
func (s *S) TestOneWayMarshalItems(c *C) {
 
313
        for i, item := range oneWayMarshalItems {
 
314
                data, err := bson.Marshal(item.obj)
 
315
                c.Assert(err, IsNil)
 
316
                c.Assert(string(data), Equals, wrapInDoc(item.data),
 
317
                        Commentf("Failed on item %d", i))
 
318
        }
 
319
}
 
320
 
 
321
// --------------------------------------------------------------------------
 
322
// Two-way tests for user-defined structures using the samples
 
323
// from bsonspec.org.
 
324
 
 
325
type specSample1 struct {
 
326
        Hello string
 
327
}
 
328
 
 
329
type specSample2 struct {
 
330
        BSON []interface{} "BSON"
 
331
}
 
332
 
 
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"},
 
339
}
 
340
 
 
341
func (s *S) TestMarshalStructSampleItems(c *C) {
 
342
        for i, item := range structSampleItems {
 
343
                data, err := bson.Marshal(item.obj)
 
344
                c.Assert(err, IsNil)
 
345
                c.Assert(string(data), Equals, item.data,
 
346
                        Commentf("Failed on item %d", i))
 
347
        }
 
348
}
 
349
 
 
350
func (s *S) TestUnmarshalStructSampleItems(c *C) {
 
351
        for _, item := range structSampleItems {
 
352
                testUnmarshal(c, item.data, item.obj)
 
353
        }
 
354
}
 
355
 
 
356
// --------------------------------------------------------------------------
 
357
// Generic two-way struct marshaling tests.
 
358
 
 
359
var bytevar = byte(8)
 
360
var byteptr = &bytevar
 
361
 
 
362
var structItems = []testItemType{
 
363
        {&struct{ Ptr *byte }{nil},
 
364
                "\x0Aptr\x00"},
 
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"},
 
373
        {&struct {
 
374
                V byte "Tag"
 
375
        }{8},
 
376
                "\x10Tag\x00\x08\x00\x00\x00"},
 
377
        {&struct {
 
378
                V *struct {
 
379
                        Byte byte
 
380
                }
 
381
        }{&struct{ Byte byte }{8}},
 
382
                "\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"},
 
383
        {&struct{ priv byte }{}, ""},
 
384
 
 
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"},
 
388
 
 
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"},
 
393
 
 
394
        // Byte arrays.
 
395
        {&struct{ V [2]byte }{[2]byte{'y', 'o'}},
 
396
                "\x05v\x00\x02\x00\x00\x00\x00yo"},
 
397
}
 
398
 
 
399
func (s *S) TestMarshalStructItems(c *C) {
 
400
        for i, item := range structItems {
 
401
                data, err := bson.Marshal(item.obj)
 
402
                c.Assert(err, IsNil)
 
403
                c.Assert(string(data), Equals, wrapInDoc(item.data),
 
404
                        Commentf("Failed on item %d", i))
 
405
        }
 
406
}
 
407
 
 
408
func (s *S) TestUnmarshalStructItems(c *C) {
 
409
        for _, item := range structItems {
 
410
                testUnmarshal(c, wrapInDoc(item.data), item.obj)
 
411
        }
 
412
}
 
413
 
 
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)
 
419
                c.Assert(err, IsNil)
 
420
                c.Assert(zero, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item))
 
421
        }
 
422
}
 
423
 
 
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{}{})
 
429
        c.Assert(err, IsNil)
 
430
}
 
431
 
 
432
// --------------------------------------------------------------------------
 
433
// One-way marshaling tests.
 
434
 
 
435
type dOnIface struct {
 
436
        D interface{}
 
437
}
 
438
 
 
439
type ignoreField struct {
 
440
        Before string
 
441
        Ignore string `bson:"-"`
 
442
        After  string
 
443
}
 
444
 
 
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"},
 
455
 
 
456
        // Marshalling a Raw document does nothing.
 
457
        {bson.Raw{0x03, []byte(wrapInDoc("anything"))},
 
458
                "anything"},
 
459
        {bson.Raw{Data: []byte(wrapInDoc("anything"))},
 
460
                "anything"},
 
461
}
 
462
 
 
463
func (s *S) TestMarshalOneWayItems(c *C) {
 
464
        for _, item := range marshalItems {
 
465
                data, err := bson.Marshal(item.obj)
 
466
                c.Assert(err, IsNil)
 
467
                c.Assert(string(data), Equals, wrapInDoc(item.data))
 
468
        }
 
469
}
 
470
 
 
471
// --------------------------------------------------------------------------
 
472
// One-way unmarshaling tests.
 
473
 
 
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"},
 
478
 
 
479
        // Wrong casing. Field names are lowercased.
 
480
        {&struct{ Byte byte }{},
 
481
                "\x10Byte\x00\x08\x00\x00\x00"},
 
482
 
 
483
        // Ignore non-existing field.
 
484
        {&struct{ Byte byte }{9},
 
485
                "\x10boot\x00\x08\x00\x00\x00" + "\x10byte\x00\x09\x00\x00\x00"},
 
486
 
 
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"},
 
492
 
 
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")},
 
498
 
 
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"},
 
504
 
 
505
        // Ordered document.
 
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")},
 
508
 
 
509
        // Raw document.
 
510
        {&bson.Raw{0x03, []byte(wrapInDoc("\x10byte\x00\x08\x00\x00\x00"))},
 
511
                "\x10byte\x00\x08\x00\x00\x00"},
 
512
 
 
513
        // Decode old binary.
 
514
        {bson.M{"_": []byte("old")},
 
515
                "\x05_\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"},
 
516
}
 
517
 
 
518
func (s *S) TestUnmarshalOneWayItems(c *C) {
 
519
        for _, item := range unmarshalItems {
 
520
                testUnmarshal(c, wrapInDoc(item.data), item.obj)
 
521
        }
 
522
}
 
523
 
 
524
func (s *S) TestUnmarshalNilInStruct(c *C) {
 
525
        // Nil is the default value, so we need to ensure it's indeed being set.
 
526
        b := byte(1)
 
527
        v := &struct{ Ptr *byte }{&b}
 
528
        err := bson.Unmarshal([]byte(wrapInDoc("\x0Aptr\x00")), v)
 
529
        c.Assert(err, IsNil)
 
530
        c.Assert(v, DeepEquals, &struct{ Ptr *byte }{nil})
 
531
}
 
532
 
 
533
// --------------------------------------------------------------------------
 
534
// Marshalling error cases.
 
535
 
 
536
type structWithDupKeys struct {
 
537
        Name  byte
 
538
        Other byte "name" // Tag should precede.
 
539
}
 
540
 
 
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\\)"},
 
546
        {int64(123),
 
547
                "Can't marshal int64 as a BSON document"},
 
548
        {bson.M{"": 1i},
 
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"},
 
558
        {&inlineDupMap{},
 
559
                "Multiple ,inline maps in struct bson_test.inlineDupMap"},
 
560
        {&inlineBadKeyMap{},
 
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`},
 
564
}
 
565
 
 
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)
 
571
        }
 
572
}
 
573
 
 
574
// --------------------------------------------------------------------------
 
575
// Unmarshalling error cases.
 
576
 
 
577
type unmarshalErrorType struct {
 
578
        obj   interface{}
 
579
        data  string
 
580
        error string
 
581
}
 
582
 
 
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"},
 
588
 
 
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 \\{\\}"},
 
593
 
 
594
        {nil,
 
595
                "\xEEname\x00",
 
596
                "Unknown element kind \\(0xEE\\)"},
 
597
 
 
598
        {struct{ Name bool }{},
 
599
                "\x10name\x00\x08\x00\x00\x00",
 
600
                "Unmarshal can't deal with struct values. Use a pointer."},
 
601
 
 
602
        {123,
 
603
                "\x10name\x00\x08\x00\x00\x00",
 
604
                "Unmarshal needs a map or a pointer to a struct."},
 
605
}
 
606
 
 
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:
 
615
                        value = bson.M{}
 
616
                default:
 
617
                        value = item.obj
 
618
                }
 
619
                err := bson.Unmarshal(data, value)
 
620
                c.Assert(err, ErrorMatches, item.error)
 
621
        }
 
622
}
 
623
 
 
624
type unmarshalRawErrorType struct {
 
625
        obj   interface{}
 
626
        raw   bson.Raw
 
627
        error string
 
628
}
 
629
 
 
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"},
 
635
 
 
636
        {&struct{}{},
 
637
                bson.Raw{0xEE, []byte{}},
 
638
                "Unknown element kind \\(0xEE\\)"},
 
639
 
 
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."},
 
643
 
 
644
        {123,
 
645
                bson.Raw{0x10, []byte("\x08\x00\x00\x00")},
 
646
                "Raw Unmarshal needs a map or a valid pointer."},
 
647
}
 
648
 
 
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))
 
653
        }
 
654
}
 
655
 
 
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
 
662
 
 
663
        // Array end past end of string (s[2]=0x07 is correct)
 
664
        wrapInDoc("\x04\x00\x09\x00\x00\x00\x0A\x00\x00"),
 
665
 
 
666
        // Array end within string, but past acceptable.
 
667
        wrapInDoc("\x04\x00\x08\x00\x00\x00\x0A\x00\x00"),
 
668
 
 
669
        // Document end within string, but past acceptable.
 
670
        wrapInDoc("\x03\x00\x08\x00\x00\x00\x0A\x00\x00"),
 
671
 
 
672
        // String with corrupted end.
 
673
        wrapInDoc("\x02\x00\x03\x00\x00\x00yo\xFF"),
 
674
}
 
675
 
 
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")
 
680
 
 
681
                err = bson.Unmarshal([]byte(data), &struct{}{})
 
682
                c.Assert(err, ErrorMatches, "Document is corrupted")
 
683
        }
 
684
}
 
685
 
 
686
// --------------------------------------------------------------------------
 
687
// Setter test cases.
 
688
 
 
689
var setterResult = map[string]error{}
 
690
 
 
691
type setterType struct {
 
692
        received interface{}
 
693
}
 
694
 
 
695
func (o *setterType) SetBSON(raw bson.Raw) error {
 
696
        err := raw.Unmarshal(&o.received)
 
697
        if err != nil {
 
698
                panic("The panic:" + err.Error())
 
699
        }
 
700
        if s, ok := o.received.(string); ok {
 
701
                if result, ok := setterResult[s]; ok {
 
702
                        return result
 
703
                }
 
704
        }
 
705
        return nil
 
706
}
 
707
 
 
708
type ptrSetterDoc struct {
 
709
        Field *setterType "_"
 
710
}
 
711
 
 
712
type valSetterDoc struct {
 
713
        Field setterType "_"
 
714
}
 
715
 
 
716
func (s *S) TestUnmarshalAllItemsWithPtrSetter(c *C) {
 
717
        for _, item := range allItems {
 
718
                for i := 0; i != 2; i++ {
 
719
                        var field *setterType
 
720
                        if i == 0 {
 
721
                                obj := &ptrSetterDoc{}
 
722
                                err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj)
 
723
                                c.Assert(err, IsNil)
 
724
                                field = obj.Field
 
725
                        } else {
 
726
                                obj := &valSetterDoc{}
 
727
                                err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj)
 
728
                                c.Assert(err, IsNil)
 
729
                                field = &obj.Field
 
730
                        }
 
731
                        if item.data == "" {
 
732
                                // Nothing to unmarshal. Should be untouched.
 
733
                                if i == 0 {
 
734
                                        c.Assert(field, IsNil)
 
735
                                } else {
 
736
                                        c.Assert(field.received, IsNil)
 
737
                                }
 
738
                        } else {
 
739
                                expected := item.obj.(bson.M)["_"]
 
740
                                c.Assert(field, NotNil, Commentf("Pointer not initialized (%#v)", expected))
 
741
                                c.Assert(field.received, DeepEquals, expected)
 
742
                        }
 
743
                }
 
744
        }
 
745
}
 
746
 
 
747
func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) {
 
748
        obj := &setterType{}
 
749
        err := bson.Unmarshal([]byte(sampleItems[0].data), obj)
 
750
        c.Assert(err, IsNil)
 
751
        c.Assert(obj.received, DeepEquals, bson.M{"hello": "world"})
 
752
}
 
753
 
 
754
func (s *S) TestUnmarshalSetterOmits(c *C) {
 
755
        setterResult["2"] = &bson.TypeError{}
 
756
        setterResult["4"] = &bson.TypeError{}
 
757
        defer func() {
 
758
                delete(setterResult, "2")
 
759
                delete(setterResult, "4")
 
760
        }()
 
761
 
 
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)
 
768
        c.Assert(err, IsNil)
 
769
        c.Assert(m["abc"], NotNil)
 
770
        c.Assert(m["def"], IsNil)
 
771
        c.Assert(m["ghi"], NotNil)
 
772
        c.Assert(m["jkl"], IsNil)
 
773
 
 
774
        c.Assert(m["abc"].received, Equals, "1")
 
775
        c.Assert(m["ghi"].received, Equals, "3")
 
776
}
 
777
 
 
778
func (s *S) TestUnmarshalSetterErrors(c *C) {
 
779
        boom := errors.New("BOOM")
 
780
        setterResult["2"] = boom
 
781
        defer delete(setterResult, "2")
 
782
 
 
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)
 
792
 
 
793
        c.Assert(m["abc"].received, Equals, "1")
 
794
}
 
795
 
 
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})
 
799
}
 
800
 
 
801
func (s *S) TestUnmarshalSetterSetZero(c *C) {
 
802
        setterResult["foo"] = bson.SetZero
 
803
        defer delete(setterResult, "field")
 
804
 
 
805
        data, err := bson.Marshal(bson.M{"field": "foo"})
 
806
        c.Assert(err, IsNil)
 
807
 
 
808
        m := map[string]*setterType{}
 
809
        err = bson.Unmarshal([]byte(data), m)
 
810
        c.Assert(err, IsNil)
 
811
 
 
812
        value, ok := m["field"]
 
813
        c.Assert(ok, Equals, true)
 
814
        c.Assert(value, IsNil)
 
815
}
 
816
 
 
817
 
 
818
// --------------------------------------------------------------------------
 
819
// Getter test cases.
 
820
 
 
821
type typeWithGetter struct {
 
822
        result interface{}
 
823
        err    error
 
824
}
 
825
 
 
826
func (t *typeWithGetter) GetBSON() (interface{}, error) {
 
827
        return t.result, t.err
 
828
}
 
829
 
 
830
type docWithGetterField struct {
 
831
        Field *typeWithGetter "_"
 
832
}
 
833
 
 
834
func (s *S) TestMarshalAllItemsWithGetter(c *C) {
 
835
        for i, item := range allItems {
 
836
                if item.data == "" {
 
837
                        continue
 
838
                }
 
839
                obj := &docWithGetterField{}
 
840
                obj.Field = &typeWithGetter{result: item.obj.(bson.M)["_"]}
 
841
                data, err := bson.Marshal(obj)
 
842
                c.Assert(err, IsNil)
 
843
                c.Assert(string(data), Equals, wrapInDoc(item.data),
 
844
                        Commentf("Failed on item #%d", i))
 
845
        }
 
846
}
 
847
 
 
848
func (s *S) TestMarshalWholeDocumentWithGetter(c *C) {
 
849
        obj := &typeWithGetter{result: sampleItems[0].obj}
 
850
        data, err := bson.Marshal(obj)
 
851
        c.Assert(err, IsNil)
 
852
        c.Assert(string(data), Equals, sampleItems[0].data)
 
853
}
 
854
 
 
855
func (s *S) TestGetterErrors(c *C) {
 
856
        e := errors.New("oops")
 
857
 
 
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)
 
863
 
 
864
        obj2 := &typeWithGetter{sampleItems[0].obj, e}
 
865
        data, err = bson.Marshal(obj2)
 
866
        c.Assert(err, ErrorMatches, "oops")
 
867
        c.Assert(data, IsNil)
 
868
}
 
869
 
 
870
type intGetter int64
 
871
 
 
872
func (t intGetter) GetBSON() (interface{}, error) {
 
873
        return int64(t), nil
 
874
}
 
875
 
 
876
type typeWithIntGetter struct {
 
877
        V intGetter ",minsize"
 
878
}
 
879
 
 
880
func (s *S) TestMarshalShortWithGetter(c *C) {
 
881
        obj := typeWithIntGetter{42}
 
882
        data, err := bson.Marshal(obj)
 
883
        c.Assert(err, IsNil)
 
884
        m := bson.M{}
 
885
        err = bson.Unmarshal(data, m)
 
886
        c.Assert(m["v"], Equals, 42)
 
887
}
 
888
 
 
889
// --------------------------------------------------------------------------
 
890
// Cross-type conversion tests.
 
891
 
 
892
type crossTypeItem struct {
 
893
        obj1 interface{}
 
894
        obj2 interface{}
 
895
}
 
896
 
 
897
type condStr struct {
 
898
        V string ",omitempty"
 
899
}
 
900
type condStrNS struct {
 
901
        V string `a:"A" bson:",omitempty" b:"B"`
 
902
}
 
903
type condBool struct {
 
904
        V bool ",omitempty"
 
905
}
 
906
type condInt struct {
 
907
        V int ",omitempty"
 
908
}
 
909
type condUInt struct {
 
910
        V uint ",omitempty"
 
911
}
 
912
type condFloat struct {
 
913
        V float64 ",omitempty"
 
914
}
 
915
type condIface struct {
 
916
        V interface{} ",omitempty"
 
917
}
 
918
type condPtr struct {
 
919
        V *bool ",omitempty"
 
920
}
 
921
type condSlice struct {
 
922
        V []string ",omitempty"
 
923
}
 
924
type condMap struct {
 
925
        V map[string]int ",omitempty"
 
926
}
 
927
type namedCondStr struct {
 
928
        V string "myv,omitempty"
 
929
}
 
930
type condTime struct {
 
931
        V time.Time ",omitempty"
 
932
}
 
933
 
 
934
type shortInt struct {
 
935
        V int64 ",minsize"
 
936
}
 
937
type shortUint struct {
 
938
        V uint64 ",minsize"
 
939
}
 
940
type shortIface struct {
 
941
        V interface{} ",minsize"
 
942
}
 
943
type shortPtr struct {
 
944
        V *int64 ",minsize"
 
945
}
 
946
type shortNonEmptyInt struct {
 
947
        V int64 ",minsize,omitempty"
 
948
}
 
949
 
 
950
type inlineInt struct {
 
951
        V struct{ A, B int } ",inline"
 
952
}
 
953
type inlineCantPtr struct {
 
954
        V *struct{ A, B int } ",inline"
 
955
}
 
956
type inlineDupName struct {
 
957
        A int
 
958
        V struct{ A, B int } ",inline"
 
959
}
 
960
type inlineMap struct {
 
961
        A int
 
962
        M map[string]interface{} ",inline"
 
963
}
 
964
type inlineMapInt struct {
 
965
        A int
 
966
        M map[string]int ",inline"
 
967
}
 
968
type inlineMapMyM struct {
 
969
        A int
 
970
        M MyM ",inline"
 
971
}
 
972
type inlineDupMap struct {
 
973
        M1 map[string]interface{} ",inline"
 
974
        M2 map[string]interface{} ",inline"
 
975
}
 
976
type inlineBadKeyMap struct {
 
977
        M map[int]int ",inline"
 
978
}
 
979
 
 
980
type MyBytes []byte
 
981
type MyBool bool
 
982
type MyD []bson.DocElem
 
983
type MyM map[string]interface{}
 
984
 
 
985
var truevar = true
 
986
var falsevar = false
 
987
 
 
988
var int64var = int64(42)
 
989
var int64ptr = &int64var
 
990
var intvar = int(42)
 
991
var intptr = &intvar
 
992
 
 
993
func parseURL(s string) *url.URL {
 
994
        u, err := url.Parse(s)
 
995
        if err != nil {
 
996
                panic(err)
 
997
        }
 
998
        return u
 
999
}
 
1000
 
 
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{
 
1006
        // int<=>int
 
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}},
 
1013
 
 
1014
        // uint<=>uint
 
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}},
 
1021
 
 
1022
        // float32<=>float64
 
1023
        {&struct{ I float32 }{42}, &struct{ I float64 }{42}},
 
1024
 
 
1025
        // int<=>uint
 
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}},
 
1042
 
 
1043
        // int <=> float
 
1044
        {&struct{ I int }{42}, &struct{ I float64 }{42}},
 
1045
 
 
1046
        // int <=> bool
 
1047
        {&struct{ I int }{1}, &struct{ I bool }{true}},
 
1048
        {&struct{ I int }{0}, &struct{ I bool }{false}},
 
1049
 
 
1050
        // uint <=> float64
 
1051
        {&struct{ I uint }{42}, &struct{ I float64 }{42}},
 
1052
 
 
1053
        // uint <=> bool
 
1054
        {&struct{ I uint }{1}, &struct{ I bool }{true}},
 
1055
        {&struct{ I uint }{0}, &struct{ I bool }{false}},
 
1056
 
 
1057
        // float64 <=> bool
 
1058
        {&struct{ I float64 }{1}, &struct{ I bool }{true}},
 
1059
        {&struct{ I float64 }{0}, &struct{ I bool }{false}},
 
1060
 
 
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"}},
 
1065
 
 
1066
        // map <=> struct
 
1067
        {&struct {
 
1068
                A struct {
 
1069
                        B, C int
 
1070
                }
 
1071
        }{struct{ B, C int }{1, 2}},
 
1072
                map[string]map[string]int{"a": map[string]int{"b": 1, "c": 2}}},
 
1073
 
 
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}},
 
1091
 
 
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"}},
 
1095
 
 
1096
        // Slices
 
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}}},
 
1099
 
 
1100
        // Conditionals
 
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{}},
 
1122
 
 
1123
        {&condTime{time.Unix(123456789, 123e6)}, map[string]time.Time{"v": time.Unix(123456789, 123e6)}},
 
1124
        {&condTime{}, map[string]string{}},
 
1125
 
 
1126
        {&namedCondStr{"yo"}, map[string]string{"myv": "yo"}},
 
1127
        {&namedCondStr{}, map[string]string{}},
 
1128
 
 
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}},
 
1136
 
 
1137
        {&shortNonEmptyInt{1}, map[string]interface{}{"v": 1}},
 
1138
        {&shortNonEmptyInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}},
 
1139
        {&shortNonEmptyInt{}, map[string]interface{}{}},
 
1140
 
 
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}}},
 
1147
 
 
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")}},
 
1153
 
 
1154
        // bool <=> MyBool
 
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}},
 
1159
 
 
1160
        // arrays
 
1161
        {&struct{ V [2]int }{[...]int{1, 2}}, map[string][2]int{"v": [2]int{1, 2}}},
 
1162
 
 
1163
        // zero time
 
1164
        {&struct{ V time.Time }{}, map[string]interface{}{"v": time.Time{}}},
 
1165
 
 
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()}},
 
1169
 
 
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}}}}},
 
1173
 
 
1174
        // bson.M <=> map
 
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}}},
 
1177
}
 
1178
 
 
1179
// Same thing, but only one way (obj1 => obj2).
 
1180
var oneWayCrossItems = []crossTypeItem{
 
1181
        // map <=> struct
 
1182
        {map[string]interface{}{"a": 1, "b": "2", "c": 3}, map[string]int{"a": 1, "c": 3}},
 
1183
 
 
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}}},
 
1186
 
 
1187
        // Can't decode int into struct.
 
1188
        {bson.M{"a": bson.M{"b": 2}}, &struct{ A bool }{}},
 
1189
 
 
1190
        // Would get decoded into a int32 too in the opposite direction.
 
1191
        {&shortIface{int64(1) << 30}, map[string]interface{}{"v": 1 << 30}},
 
1192
}
 
1193
 
 
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)
 
1205
}
 
1206
 
 
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)
 
1211
        }
 
1212
}
 
1213
 
 
1214
func (s *S) TestOneWayCrossPairs(c *C) {
 
1215
        for _, item := range oneWayCrossItems {
 
1216
                testCrossPair(c, item.obj1, item.obj2)
 
1217
        }
 
1218
}
 
1219
 
 
1220
// --------------------------------------------------------------------------
 
1221
// ObjectId hex representation test.
 
1222
 
 
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")
 
1227
}
 
1228
 
 
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},
 
1235
        }
 
1236
        for _, t := range test {
 
1237
                c.Assert(bson.IsObjectIdHex(t.id), Equals, t.valid)
 
1238
        }
 
1239
}
 
1240
 
 
1241
// --------------------------------------------------------------------------
 
1242
// ObjectId parts extraction tests.
 
1243
 
 
1244
type objectIdParts struct {
 
1245
        id        bson.ObjectId
 
1246
        timestamp int64
 
1247
        machine   []byte
 
1248
        pid       uint16
 
1249
        counter   int32
 
1250
}
 
1251
 
 
1252
var objectIds = []objectIdParts{
 
1253
        objectIdParts{
 
1254
                bson.ObjectIdHex("4d88e15b60f486e428412dc9"),
 
1255
                1300816219,
 
1256
                []byte{0x60, 0xf4, 0x86},
 
1257
                0xe428,
 
1258
                4271561,
 
1259
        },
 
1260
        objectIdParts{
 
1261
                bson.ObjectIdHex("000000000000000000000000"),
 
1262
                0,
 
1263
                []byte{0x00, 0x00, 0x00},
 
1264
                0x0000,
 
1265
                0,
 
1266
        },
 
1267
        objectIdParts{
 
1268
                bson.ObjectIdHex("00000000aabbccddee000001"),
 
1269
                0,
 
1270
                []byte{0xaa, 0xbb, 0xcc},
 
1271
                0xddee,
 
1272
                1,
 
1273
        },
 
1274
}
 
1275
 
 
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))
 
1283
        }
 
1284
}
 
1285
 
 
1286
func (s *S) TestNow(c *C) {
 
1287
        before := time.Now()
 
1288
        time.Sleep(1e6)
 
1289
        now := bson.Now()
 
1290
        time.Sleep(1e6)
 
1291
        after := time.Now()
 
1292
        c.Assert(now.After(before) && now.Before(after), Equals, true, Commentf("now=%s, before=%s, after=%s", now, before, after))
 
1293
}
 
1294
 
 
1295
// --------------------------------------------------------------------------
 
1296
// ObjectId generation tests.
 
1297
 
 
1298
func (s *S) TestNewObjectId(c *C) {
 
1299
        // Generate 10 ids
 
1300
        ids := make([]bson.ObjectId, 10)
 
1301
        for i := 0; i < 10; i++ {
 
1302
                ids[i] = bson.NewObjectId()
 
1303
        }
 
1304
        for i := 1; i < 10; i++ {
 
1305
                prevId := ids[i-1]
 
1306
                id := ids[i]
 
1307
                // Test for uniqueness among all other 9 generated ids
 
1308
                for j, tid := range ids {
 
1309
                        if j != i {
 
1310
                                c.Assert(id, Not(Equals), tid, Commentf("Generated ObjectId is not unique"))
 
1311
                        }
 
1312
                }
 
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"))
 
1323
        }
 
1324
}
 
1325
 
 
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)
 
1333
}
 
1334
 
 
1335
// --------------------------------------------------------------------------
 
1336
// ObjectId JSON marshalling.
 
1337
 
 
1338
type jsonType struct {
 
1339
        Id *bson.ObjectId
 
1340
}
 
1341
 
 
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"}`)
 
1348
}
 
1349
 
 
1350
func (s *S) TestObjectIdJSONUnmarshaling(c *C) {
 
1351
        data := []byte(`{"Id":"4d88e15b60f486e428412dc9"}`)
 
1352
        v := jsonType{}
 
1353
        err := json.Unmarshal(data, &v)
 
1354
        c.Assert(err, IsNil)
 
1355
        c.Assert(*v.Id, Equals, bson.ObjectIdHex("4d88e15b60f486e428412dc9"))
 
1356
}
 
1357
 
 
1358
func (s *S) TestObjectIdJSONUnmarshalingError(c *C) {
 
1359
        v := jsonType{}
 
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" .*`)
 
1364
}
 
1365
 
 
1366
// --------------------------------------------------------------------------
 
1367
// Some simple benchmarks.
 
1368
 
 
1369
type BenchT struct {
 
1370
        A, B, C, D, E, F string
 
1371
}
 
1372
 
 
1373
func BenchmarkUnmarhsalStruct(b *testing.B) {
 
1374
        v := BenchT{A: "A", D: "D", E: "E"}
 
1375
        data, err := bson.Marshal(&v)
 
1376
        if err != nil {
 
1377
                panic(err)
 
1378
        }
 
1379
        b.ResetTimer()
 
1380
        for i := 0; i < b.N; i++ {
 
1381
                err = bson.Unmarshal(data, &v)
 
1382
        }
 
1383
        if err != nil {
 
1384
                panic(err)
 
1385
        }
 
1386
}
 
1387
 
 
1388
func BenchmarkUnmarhsalMap(b *testing.B) {
 
1389
        m := bson.M{"a": "a", "d": "d", "e": "e"}
 
1390
        data, err := bson.Marshal(&m)
 
1391
        if err != nil {
 
1392
                panic(err)
 
1393
        }
 
1394
        b.ResetTimer()
 
1395
        for i := 0; i < b.N; i++ {
 
1396
                err = bson.Unmarshal(data, &m)
 
1397
        }
 
1398
        if err != nil {
 
1399
                panic(err)
 
1400
        }
 
1401
}