github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/gopkg.in/mgo.v2/bson/bson_test.go (about) 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/hex" 33 "encoding/json" 34 "encoding/xml" 35 "errors" 36 "net/url" 37 "reflect" 38 "strings" 39 "testing" 40 "time" 41 42 . "gopkg.in/check.v1" 43 "gopkg.in/mgo.v2/bson" 44 "gopkg.in/yaml.v2" 45 ) 46 47 func TestAll(t *testing.T) { 48 TestingT(t) 49 } 50 51 type S struct{} 52 53 var _ = Suite(&S{}) 54 55 // Wrap up the document elements contained in data, prepending the int32 56 // length of the data, and appending the '\x00' value closing the document. 57 func wrapInDoc(data string) string { 58 result := make([]byte, len(data)+5) 59 binary.LittleEndian.PutUint32(result, uint32(len(result))) 60 copy(result[4:], []byte(data)) 61 return string(result) 62 } 63 64 func makeZeroDoc(value interface{}) (zero interface{}) { 65 v := reflect.ValueOf(value) 66 t := v.Type() 67 switch t.Kind() { 68 case reflect.Map: 69 mv := reflect.MakeMap(t) 70 zero = mv.Interface() 71 case reflect.Ptr: 72 pv := reflect.New(v.Type().Elem()) 73 zero = pv.Interface() 74 case reflect.Slice, reflect.Int, reflect.Int64, reflect.Struct: 75 zero = reflect.New(t).Interface() 76 default: 77 panic("unsupported doc type: " + t.Name()) 78 } 79 return zero 80 } 81 82 func testUnmarshal(c *C, data string, obj interface{}) { 83 zero := makeZeroDoc(obj) 84 err := bson.Unmarshal([]byte(data), zero) 85 c.Assert(err, IsNil) 86 c.Assert(zero, DeepEquals, obj) 87 } 88 89 type testItemType struct { 90 obj interface{} 91 data string 92 } 93 94 // -------------------------------------------------------------------------- 95 // Samples from bsonspec.org: 96 97 var sampleItems = []testItemType{ 98 {bson.M{"hello": "world"}, 99 "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"}, 100 {bson.M{"BSON": []interface{}{"awesome", float64(5.05), 1986}}, 101 "1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" + 102 "awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"}, 103 } 104 105 func (s *S) TestMarshalSampleItems(c *C) { 106 for i, item := range sampleItems { 107 data, err := bson.Marshal(item.obj) 108 c.Assert(err, IsNil) 109 c.Assert(string(data), Equals, item.data, Commentf("Failed on item %d", i)) 110 } 111 } 112 113 func (s *S) TestUnmarshalSampleItems(c *C) { 114 for i, item := range sampleItems { 115 value := bson.M{} 116 err := bson.Unmarshal([]byte(item.data), value) 117 c.Assert(err, IsNil) 118 c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d", i)) 119 } 120 } 121 122 // -------------------------------------------------------------------------- 123 // Every type, ordered by the type flag. These are not wrapped with the 124 // length and last \x00 from the document. wrapInDoc() computes them. 125 // Note that all of them should be supported as two-way conversions. 126 127 var allItems = []testItemType{ 128 {bson.M{}, 129 ""}, 130 {bson.M{"_": float64(5.05)}, 131 "\x01_\x00333333\x14@"}, 132 {bson.M{"_": "yo"}, 133 "\x02_\x00\x03\x00\x00\x00yo\x00"}, 134 {bson.M{"_": bson.M{"a": true}}, 135 "\x03_\x00\x09\x00\x00\x00\x08a\x00\x01\x00"}, 136 {bson.M{"_": []interface{}{true, false}}, 137 "\x04_\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"}, 138 {bson.M{"_": []byte("yo")}, 139 "\x05_\x00\x02\x00\x00\x00\x00yo"}, 140 {bson.M{"_": bson.Binary{0x80, []byte("udef")}}, 141 "\x05_\x00\x04\x00\x00\x00\x80udef"}, 142 {bson.M{"_": bson.Undefined}, // Obsolete, but still seen in the wild. 143 "\x06_\x00"}, 144 {bson.M{"_": bson.ObjectId("0123456789ab")}, 145 "\x07_\x000123456789ab"}, 146 {bson.M{"_": bson.DBPointer{"testnamespace", bson.ObjectId("0123456789ab")}}, 147 "\x0C_\x00\x0e\x00\x00\x00testnamespace\x000123456789ab"}, 148 {bson.M{"_": false}, 149 "\x08_\x00\x00"}, 150 {bson.M{"_": true}, 151 "\x08_\x00\x01"}, 152 {bson.M{"_": time.Unix(0, 258e6)}, // Note the NS <=> MS conversion. 153 "\x09_\x00\x02\x01\x00\x00\x00\x00\x00\x00"}, 154 {bson.M{"_": nil}, 155 "\x0A_\x00"}, 156 {bson.M{"_": bson.RegEx{"ab", "cd"}}, 157 "\x0B_\x00ab\x00cd\x00"}, 158 {bson.M{"_": bson.JavaScript{"code", nil}}, 159 "\x0D_\x00\x05\x00\x00\x00code\x00"}, 160 {bson.M{"_": bson.Symbol("sym")}, 161 "\x0E_\x00\x04\x00\x00\x00sym\x00"}, 162 {bson.M{"_": bson.JavaScript{"code", bson.M{"": nil}}}, 163 "\x0F_\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" + 164 "\x07\x00\x00\x00\x0A\x00\x00"}, 165 {bson.M{"_": 258}, 166 "\x10_\x00\x02\x01\x00\x00"}, 167 {bson.M{"_": bson.MongoTimestamp(258)}, 168 "\x11_\x00\x02\x01\x00\x00\x00\x00\x00\x00"}, 169 {bson.M{"_": int64(258)}, 170 "\x12_\x00\x02\x01\x00\x00\x00\x00\x00\x00"}, 171 {bson.M{"_": int64(258 << 32)}, 172 "\x12_\x00\x00\x00\x00\x00\x02\x01\x00\x00"}, 173 {bson.M{"_": bson.MaxKey}, 174 "\x7F_\x00"}, 175 {bson.M{"_": bson.MinKey}, 176 "\xFF_\x00"}, 177 } 178 179 func (s *S) TestMarshalAllItems(c *C) { 180 for i, item := range allItems { 181 data, err := bson.Marshal(item.obj) 182 c.Assert(err, IsNil) 183 c.Assert(string(data), Equals, wrapInDoc(item.data), Commentf("Failed on item %d: %#v", i, item)) 184 } 185 } 186 187 func (s *S) TestUnmarshalAllItems(c *C) { 188 for i, item := range allItems { 189 value := bson.M{} 190 err := bson.Unmarshal([]byte(wrapInDoc(item.data)), value) 191 c.Assert(err, IsNil) 192 c.Assert(value, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item)) 193 } 194 } 195 196 func (s *S) TestUnmarshalRawAllItems(c *C) { 197 for i, item := range allItems { 198 if len(item.data) == 0 { 199 continue 200 } 201 value := item.obj.(bson.M)["_"] 202 if value == nil { 203 continue 204 } 205 pv := reflect.New(reflect.ValueOf(value).Type()) 206 raw := bson.Raw{item.data[0], []byte(item.data[3:])} 207 c.Logf("Unmarshal raw: %#v, %#v", raw, pv.Interface()) 208 err := raw.Unmarshal(pv.Interface()) 209 c.Assert(err, IsNil) 210 c.Assert(pv.Elem().Interface(), DeepEquals, value, Commentf("Failed on item %d: %#v", i, item)) 211 } 212 } 213 214 func (s *S) TestUnmarshalRawIncompatible(c *C) { 215 raw := bson.Raw{0x08, []byte{0x01}} // true 216 err := raw.Unmarshal(&struct{}{}) 217 c.Assert(err, ErrorMatches, "BSON kind 0x08 isn't compatible with type struct \\{\\}") 218 } 219 220 func (s *S) TestUnmarshalZeroesStruct(c *C) { 221 data, err := bson.Marshal(bson.M{"b": 2}) 222 c.Assert(err, IsNil) 223 type T struct{ A, B int } 224 v := T{A: 1} 225 err = bson.Unmarshal(data, &v) 226 c.Assert(err, IsNil) 227 c.Assert(v.A, Equals, 0) 228 c.Assert(v.B, Equals, 2) 229 } 230 231 func (s *S) TestUnmarshalZeroesMap(c *C) { 232 data, err := bson.Marshal(bson.M{"b": 2}) 233 c.Assert(err, IsNil) 234 m := bson.M{"a": 1} 235 err = bson.Unmarshal(data, &m) 236 c.Assert(err, IsNil) 237 c.Assert(m, DeepEquals, bson.M{"b": 2}) 238 } 239 240 func (s *S) TestUnmarshalNonNilInterface(c *C) { 241 data, err := bson.Marshal(bson.M{"b": 2}) 242 c.Assert(err, IsNil) 243 m := bson.M{"a": 1} 244 var i interface{} 245 i = m 246 err = bson.Unmarshal(data, &i) 247 c.Assert(err, IsNil) 248 c.Assert(i, DeepEquals, bson.M{"b": 2}) 249 c.Assert(m, DeepEquals, bson.M{"a": 1}) 250 } 251 252 // -------------------------------------------------------------------------- 253 // Some one way marshaling operations which would unmarshal differently. 254 255 var oneWayMarshalItems = []testItemType{ 256 // These are being passed as pointers, and will unmarshal as values. 257 {bson.M{"": &bson.Binary{0x02, []byte("old")}}, 258 "\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"}, 259 {bson.M{"": &bson.Binary{0x80, []byte("udef")}}, 260 "\x05\x00\x04\x00\x00\x00\x80udef"}, 261 {bson.M{"": &bson.RegEx{"ab", "cd"}}, 262 "\x0B\x00ab\x00cd\x00"}, 263 {bson.M{"": &bson.JavaScript{"code", nil}}, 264 "\x0D\x00\x05\x00\x00\x00code\x00"}, 265 {bson.M{"": &bson.JavaScript{"code", bson.M{"": nil}}}, 266 "\x0F\x00\x14\x00\x00\x00\x05\x00\x00\x00code\x00" + 267 "\x07\x00\x00\x00\x0A\x00\x00"}, 268 269 // There's no float32 type in BSON. Will encode as a float64. 270 {bson.M{"": float32(5.05)}, 271 "\x01\x00\x00\x00\x00@33\x14@"}, 272 273 // The array will be unmarshaled as a slice instead. 274 {bson.M{"": [2]bool{true, false}}, 275 "\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"}, 276 277 // The typed slice will be unmarshaled as []interface{}. 278 {bson.M{"": []bool{true, false}}, 279 "\x04\x00\r\x00\x00\x00\x080\x00\x01\x081\x00\x00\x00"}, 280 281 // Will unmarshal as a []byte. 282 {bson.M{"": bson.Binary{0x00, []byte("yo")}}, 283 "\x05\x00\x02\x00\x00\x00\x00yo"}, 284 {bson.M{"": bson.Binary{0x02, []byte("old")}}, 285 "\x05\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"}, 286 287 // No way to preserve the type information here. We might encode as a zero 288 // value, but this would mean that pointer values in structs wouldn't be 289 // able to correctly distinguish between unset and set to the zero value. 290 {bson.M{"": (*byte)(nil)}, 291 "\x0A\x00"}, 292 293 // No int types smaller than int32 in BSON. Could encode this as a char, 294 // but it would still be ambiguous, take more, and be awkward in Go when 295 // loaded without typing information. 296 {bson.M{"": byte(8)}, 297 "\x10\x00\x08\x00\x00\x00"}, 298 299 // There are no unsigned types in BSON. Will unmarshal as int32 or int64. 300 {bson.M{"": uint32(258)}, 301 "\x10\x00\x02\x01\x00\x00"}, 302 {bson.M{"": uint64(258)}, 303 "\x12\x00\x02\x01\x00\x00\x00\x00\x00\x00"}, 304 {bson.M{"": uint64(258 << 32)}, 305 "\x12\x00\x00\x00\x00\x00\x02\x01\x00\x00"}, 306 307 // This will unmarshal as int. 308 {bson.M{"": int32(258)}, 309 "\x10\x00\x02\x01\x00\x00"}, 310 311 // That's a special case. The unsigned value is too large for an int32, 312 // so an int64 is used instead. 313 {bson.M{"": uint32(1<<32 - 1)}, 314 "\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"}, 315 {bson.M{"": uint(1<<32 - 1)}, 316 "\x12\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"}, 317 } 318 319 func (s *S) TestOneWayMarshalItems(c *C) { 320 for i, item := range oneWayMarshalItems { 321 data, err := bson.Marshal(item.obj) 322 c.Assert(err, IsNil) 323 c.Assert(string(data), Equals, wrapInDoc(item.data), 324 Commentf("Failed on item %d", i)) 325 } 326 } 327 328 // -------------------------------------------------------------------------- 329 // Two-way tests for user-defined structures using the samples 330 // from bsonspec.org. 331 332 type specSample1 struct { 333 Hello string 334 } 335 336 type specSample2 struct { 337 BSON []interface{} "BSON" 338 } 339 340 var structSampleItems = []testItemType{ 341 {&specSample1{"world"}, 342 "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00"}, 343 {&specSample2{[]interface{}{"awesome", float64(5.05), 1986}}, 344 "1\x00\x00\x00\x04BSON\x00&\x00\x00\x00\x020\x00\x08\x00\x00\x00" + 345 "awesome\x00\x011\x00333333\x14@\x102\x00\xc2\x07\x00\x00\x00\x00"}, 346 } 347 348 func (s *S) TestMarshalStructSampleItems(c *C) { 349 for i, item := range structSampleItems { 350 data, err := bson.Marshal(item.obj) 351 c.Assert(err, IsNil) 352 c.Assert(string(data), Equals, item.data, 353 Commentf("Failed on item %d", i)) 354 } 355 } 356 357 func (s *S) TestUnmarshalStructSampleItems(c *C) { 358 for _, item := range structSampleItems { 359 testUnmarshal(c, item.data, item.obj) 360 } 361 } 362 363 func (s *S) Test64bitInt(c *C) { 364 var i int64 = (1 << 31) 365 if int(i) > 0 { 366 data, err := bson.Marshal(bson.M{"i": int(i)}) 367 c.Assert(err, IsNil) 368 c.Assert(string(data), Equals, wrapInDoc("\x12i\x00\x00\x00\x00\x80\x00\x00\x00\x00")) 369 370 var result struct{ I int } 371 err = bson.Unmarshal(data, &result) 372 c.Assert(err, IsNil) 373 c.Assert(int64(result.I), Equals, i) 374 } 375 } 376 377 // -------------------------------------------------------------------------- 378 // Generic two-way struct marshaling tests. 379 380 var bytevar = byte(8) 381 var byteptr = &bytevar 382 383 var structItems = []testItemType{ 384 {&struct{ Ptr *byte }{nil}, 385 "\x0Aptr\x00"}, 386 {&struct{ Ptr *byte }{&bytevar}, 387 "\x10ptr\x00\x08\x00\x00\x00"}, 388 {&struct{ Ptr **byte }{&byteptr}, 389 "\x10ptr\x00\x08\x00\x00\x00"}, 390 {&struct{ Byte byte }{8}, 391 "\x10byte\x00\x08\x00\x00\x00"}, 392 {&struct{ Byte byte }{0}, 393 "\x10byte\x00\x00\x00\x00\x00"}, 394 {&struct { 395 V byte "Tag" 396 }{8}, 397 "\x10Tag\x00\x08\x00\x00\x00"}, 398 {&struct { 399 V *struct { 400 Byte byte 401 } 402 }{&struct{ Byte byte }{8}}, 403 "\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"}, 404 {&struct{ priv byte }{}, ""}, 405 406 // The order of the dumped fields should be the same in the struct. 407 {&struct{ A, C, B, D, F, E *byte }{}, 408 "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x0Ae\x00"}, 409 410 {&struct{ V bson.Raw }{bson.Raw{0x03, []byte("\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00")}}, 411 "\x03v\x00" + "\x0f\x00\x00\x00\x10byte\x00\b\x00\x00\x00\x00"}, 412 {&struct{ V bson.Raw }{bson.Raw{0x10, []byte("\x00\x00\x00\x00")}}, 413 "\x10v\x00" + "\x00\x00\x00\x00"}, 414 415 // Byte arrays. 416 {&struct{ V [2]byte }{[2]byte{'y', 'o'}}, 417 "\x05v\x00\x02\x00\x00\x00\x00yo"}, 418 } 419 420 func (s *S) TestMarshalStructItems(c *C) { 421 for i, item := range structItems { 422 data, err := bson.Marshal(item.obj) 423 c.Assert(err, IsNil) 424 c.Assert(string(data), Equals, wrapInDoc(item.data), 425 Commentf("Failed on item %d", i)) 426 } 427 } 428 429 func (s *S) TestUnmarshalStructItems(c *C) { 430 for _, item := range structItems { 431 testUnmarshal(c, wrapInDoc(item.data), item.obj) 432 } 433 } 434 435 func (s *S) TestUnmarshalRawStructItems(c *C) { 436 for i, item := range structItems { 437 raw := bson.Raw{0x03, []byte(wrapInDoc(item.data))} 438 zero := makeZeroDoc(item.obj) 439 err := raw.Unmarshal(zero) 440 c.Assert(err, IsNil) 441 c.Assert(zero, DeepEquals, item.obj, Commentf("Failed on item %d: %#v", i, item)) 442 } 443 } 444 445 func (s *S) TestUnmarshalRawNil(c *C) { 446 // Regression test: shouldn't try to nil out the pointer itself, 447 // as it's not settable. 448 raw := bson.Raw{0x0A, []byte{}} 449 err := raw.Unmarshal(&struct{}{}) 450 c.Assert(err, IsNil) 451 } 452 453 // -------------------------------------------------------------------------- 454 // One-way marshaling tests. 455 456 type dOnIface struct { 457 D interface{} 458 } 459 460 type ignoreField struct { 461 Before string 462 Ignore string `bson:"-"` 463 After string 464 } 465 466 var marshalItems = []testItemType{ 467 // Ordered document dump. Will unmarshal as a dictionary by default. 468 {bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}}, 469 "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"}, 470 {MyD{{"a", nil}, {"c", nil}, {"b", nil}, {"d", nil}, {"f", nil}, {"e", true}}, 471 "\x0Aa\x00\x0Ac\x00\x0Ab\x00\x0Ad\x00\x0Af\x00\x08e\x00\x01"}, 472 {&dOnIface{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}}, 473 "\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")}, 474 475 {bson.RawD{{"a", bson.Raw{0x0A, nil}}, {"c", bson.Raw{0x0A, nil}}, {"b", bson.Raw{0x08, []byte{0x01}}}}, 476 "\x0Aa\x00" + "\x0Ac\x00" + "\x08b\x00\x01"}, 477 {MyRawD{{"a", bson.Raw{0x0A, nil}}, {"c", bson.Raw{0x0A, nil}}, {"b", bson.Raw{0x08, []byte{0x01}}}}, 478 "\x0Aa\x00" + "\x0Ac\x00" + "\x08b\x00\x01"}, 479 {&dOnIface{bson.RawD{{"a", bson.Raw{0x0A, nil}}, {"c", bson.Raw{0x0A, nil}}, {"b", bson.Raw{0x08, []byte{0x01}}}}}, 480 "\x03d\x00" + wrapInDoc("\x0Aa\x00"+"\x0Ac\x00"+"\x08b\x00\x01")}, 481 482 {&ignoreField{"before", "ignore", "after"}, 483 "\x02before\x00\a\x00\x00\x00before\x00\x02after\x00\x06\x00\x00\x00after\x00"}, 484 485 // Marshalling a Raw document does nothing. 486 {bson.Raw{0x03, []byte(wrapInDoc("anything"))}, 487 "anything"}, 488 {bson.Raw{Data: []byte(wrapInDoc("anything"))}, 489 "anything"}, 490 } 491 492 func (s *S) TestMarshalOneWayItems(c *C) { 493 for _, item := range marshalItems { 494 data, err := bson.Marshal(item.obj) 495 c.Assert(err, IsNil) 496 c.Assert(string(data), Equals, wrapInDoc(item.data)) 497 } 498 } 499 500 // -------------------------------------------------------------------------- 501 // One-way unmarshaling tests. 502 503 var unmarshalItems = []testItemType{ 504 // Field is private. Should not attempt to unmarshal it. 505 {&struct{ priv byte }{}, 506 "\x10priv\x00\x08\x00\x00\x00"}, 507 508 // Wrong casing. Field names are lowercased. 509 {&struct{ Byte byte }{}, 510 "\x10Byte\x00\x08\x00\x00\x00"}, 511 512 // Ignore non-existing field. 513 {&struct{ Byte byte }{9}, 514 "\x10boot\x00\x08\x00\x00\x00" + "\x10byte\x00\x09\x00\x00\x00"}, 515 516 // Do not unmarshal on ignored field. 517 {&ignoreField{"before", "", "after"}, 518 "\x02before\x00\a\x00\x00\x00before\x00" + 519 "\x02-\x00\a\x00\x00\x00ignore\x00" + 520 "\x02after\x00\x06\x00\x00\x00after\x00"}, 521 522 // Ignore unsuitable types silently. 523 {map[string]string{"str": "s"}, 524 "\x02str\x00\x02\x00\x00\x00s\x00" + "\x10int\x00\x01\x00\x00\x00"}, 525 {map[string][]int{"array": []int{5, 9}}, 526 "\x04array\x00" + wrapInDoc("\x100\x00\x05\x00\x00\x00"+"\x021\x00\x02\x00\x00\x00s\x00"+"\x102\x00\x09\x00\x00\x00")}, 527 528 // Wrong type. Shouldn't init pointer. 529 {&struct{ Str *byte }{}, 530 "\x02str\x00\x02\x00\x00\x00s\x00"}, 531 {&struct{ Str *struct{ Str string } }{}, 532 "\x02str\x00\x02\x00\x00\x00s\x00"}, 533 534 // Ordered document. 535 {&struct{ bson.D }{bson.D{{"a", nil}, {"c", nil}, {"b", nil}, {"d", true}}}, 536 "\x03d\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x0Ab\x00\x08d\x00\x01")}, 537 538 // Raw document. 539 {&bson.Raw{0x03, []byte(wrapInDoc("\x10byte\x00\x08\x00\x00\x00"))}, 540 "\x10byte\x00\x08\x00\x00\x00"}, 541 542 // RawD document. 543 {&struct{ bson.RawD }{bson.RawD{{"a", bson.Raw{0x0A, []byte{}}}, {"c", bson.Raw{0x0A, []byte{}}}, {"b", bson.Raw{0x08, []byte{0x01}}}}}, 544 "\x03rawd\x00" + wrapInDoc("\x0Aa\x00\x0Ac\x00\x08b\x00\x01")}, 545 546 // Decode old binary. 547 {bson.M{"_": []byte("old")}, 548 "\x05_\x00\x07\x00\x00\x00\x02\x03\x00\x00\x00old"}, 549 550 // Decode old binary without length. According to the spec, this shouldn't happen. 551 {bson.M{"_": []byte("old")}, 552 "\x05_\x00\x03\x00\x00\x00\x02old"}, 553 554 // Decode a doc within a doc in to a slice within a doc; shouldn't error 555 {&struct{ Foo []string }{}, 556 "\x03\x66\x6f\x6f\x00\x05\x00\x00\x00\x00"}, 557 } 558 559 func (s *S) TestUnmarshalOneWayItems(c *C) { 560 for _, item := range unmarshalItems { 561 testUnmarshal(c, wrapInDoc(item.data), item.obj) 562 } 563 } 564 565 func (s *S) TestUnmarshalNilInStruct(c *C) { 566 // Nil is the default value, so we need to ensure it's indeed being set. 567 b := byte(1) 568 v := &struct{ Ptr *byte }{&b} 569 err := bson.Unmarshal([]byte(wrapInDoc("\x0Aptr\x00")), v) 570 c.Assert(err, IsNil) 571 c.Assert(v, DeepEquals, &struct{ Ptr *byte }{nil}) 572 } 573 574 // -------------------------------------------------------------------------- 575 // Marshalling error cases. 576 577 type structWithDupKeys struct { 578 Name byte 579 Other byte "name" // Tag should precede. 580 } 581 582 var marshalErrorItems = []testItemType{ 583 {bson.M{"": uint64(1 << 63)}, 584 "BSON has no uint64 type, and value is too large to fit correctly in an int64"}, 585 {bson.M{"": bson.ObjectId("tooshort")}, 586 "ObjectIDs must be exactly 12 bytes long \\(got 8\\)"}, 587 {int64(123), 588 "Can't marshal int64 as a BSON document"}, 589 {bson.M{"": 1i}, 590 "Can't marshal complex128 in a BSON document"}, 591 {&structWithDupKeys{}, 592 "Duplicated key 'name' in struct bson_test.structWithDupKeys"}, 593 {bson.Raw{0xA, []byte{}}, 594 "Attempted to marshal Raw kind 10 as a document"}, 595 {bson.Raw{0x3, []byte{}}, 596 "Attempted to marshal empty Raw document"}, 597 {bson.M{"w": bson.Raw{0x3, []byte{}}}, 598 "Attempted to marshal empty Raw document"}, 599 {&inlineCantPtr{&struct{ A, B int }{1, 2}}, 600 "Option ,inline needs a struct value or map field"}, 601 {&inlineDupName{1, struct{ A, B int }{2, 3}}, 602 "Duplicated key 'a' in struct bson_test.inlineDupName"}, 603 {&inlineDupMap{}, 604 "Multiple ,inline maps in struct bson_test.inlineDupMap"}, 605 {&inlineBadKeyMap{}, 606 "Option ,inline needs a map with string keys in struct bson_test.inlineBadKeyMap"}, 607 {&inlineMap{A: 1, M: map[string]interface{}{"a": 1}}, 608 `Can't have key "a" in inlined map; conflicts with struct field`}, 609 } 610 611 func (s *S) TestMarshalErrorItems(c *C) { 612 for _, item := range marshalErrorItems { 613 data, err := bson.Marshal(item.obj) 614 c.Assert(err, ErrorMatches, item.data) 615 c.Assert(data, IsNil) 616 } 617 } 618 619 // -------------------------------------------------------------------------- 620 // Unmarshalling error cases. 621 622 type unmarshalErrorType struct { 623 obj interface{} 624 data string 625 error string 626 } 627 628 var unmarshalErrorItems = []unmarshalErrorType{ 629 // Tag name conflicts with existing parameter. 630 {&structWithDupKeys{}, 631 "\x10name\x00\x08\x00\x00\x00", 632 "Duplicated key 'name' in struct bson_test.structWithDupKeys"}, 633 634 // Non-string map key. 635 {map[int]interface{}{}, 636 "\x10name\x00\x08\x00\x00\x00", 637 "BSON map must have string keys. Got: map\\[int\\]interface \\{\\}"}, 638 639 {nil, 640 "\xEEname\x00", 641 "Unknown element kind \\(0xEE\\)"}, 642 643 {struct{ Name bool }{}, 644 "\x10name\x00\x08\x00\x00\x00", 645 "Unmarshal can't deal with struct values. Use a pointer."}, 646 647 {123, 648 "\x10name\x00\x08\x00\x00\x00", 649 "Unmarshal needs a map or a pointer to a struct."}, 650 651 {nil, 652 "\x08\x62\x00\x02", 653 "encoded boolean must be 1 or 0, found 2"}, 654 } 655 656 func (s *S) TestUnmarshalErrorItems(c *C) { 657 for _, item := range unmarshalErrorItems { 658 data := []byte(wrapInDoc(item.data)) 659 var value interface{} 660 switch reflect.ValueOf(item.obj).Kind() { 661 case reflect.Map, reflect.Ptr: 662 value = makeZeroDoc(item.obj) 663 case reflect.Invalid: 664 value = bson.M{} 665 default: 666 value = item.obj 667 } 668 err := bson.Unmarshal(data, value) 669 c.Assert(err, ErrorMatches, item.error) 670 } 671 } 672 673 type unmarshalRawErrorType struct { 674 obj interface{} 675 raw bson.Raw 676 error string 677 } 678 679 var unmarshalRawErrorItems = []unmarshalRawErrorType{ 680 // Tag name conflicts with existing parameter. 681 {&structWithDupKeys{}, 682 bson.Raw{0x03, []byte("\x10byte\x00\x08\x00\x00\x00")}, 683 "Duplicated key 'name' in struct bson_test.structWithDupKeys"}, 684 685 {&struct{}{}, 686 bson.Raw{0xEE, []byte{}}, 687 "Unknown element kind \\(0xEE\\)"}, 688 689 {struct{ Name bool }{}, 690 bson.Raw{0x10, []byte("\x08\x00\x00\x00")}, 691 "Raw Unmarshal can't deal with struct values. Use a pointer."}, 692 693 {123, 694 bson.Raw{0x10, []byte("\x08\x00\x00\x00")}, 695 "Raw Unmarshal needs a map or a valid pointer."}, 696 } 697 698 func (s *S) TestUnmarshalRawErrorItems(c *C) { 699 for i, item := range unmarshalRawErrorItems { 700 err := item.raw.Unmarshal(item.obj) 701 c.Assert(err, ErrorMatches, item.error, Commentf("Failed on item %d: %#v\n", i, item)) 702 } 703 } 704 705 var corruptedData = []string{ 706 "\x04\x00\x00\x00\x00", // Document shorter than minimum 707 "\x06\x00\x00\x00\x00", // Not enough data 708 "\x05\x00\x00", // Broken length 709 "\x05\x00\x00\x00\xff", // Corrupted termination 710 "\x0A\x00\x00\x00\x0Aooop\x00", // Unfinished C string 711 712 // Array end past end of string (s[2]=0x07 is correct) 713 wrapInDoc("\x04\x00\x09\x00\x00\x00\x0A\x00\x00"), 714 715 // Array end within string, but past acceptable. 716 wrapInDoc("\x04\x00\x08\x00\x00\x00\x0A\x00\x00"), 717 718 // Document end within string, but past acceptable. 719 wrapInDoc("\x03\x00\x08\x00\x00\x00\x0A\x00\x00"), 720 721 // String with corrupted end. 722 wrapInDoc("\x02\x00\x03\x00\x00\x00yo\xFF"), 723 724 // String with negative length (issue #116). 725 "\x0c\x00\x00\x00\x02x\x00\xff\xff\xff\xff\x00", 726 727 // String with zero length (must include trailing '\x00') 728 "\x0c\x00\x00\x00\x02x\x00\x00\x00\x00\x00\x00", 729 730 // Binary with negative length. 731 "\r\x00\x00\x00\x05x\x00\xff\xff\xff\xff\x00\x00", 732 } 733 734 func (s *S) TestUnmarshalMapDocumentTooShort(c *C) { 735 for _, data := range corruptedData { 736 err := bson.Unmarshal([]byte(data), bson.M{}) 737 c.Assert(err, ErrorMatches, "Document is corrupted") 738 739 err = bson.Unmarshal([]byte(data), &struct{}{}) 740 c.Assert(err, ErrorMatches, "Document is corrupted") 741 } 742 } 743 744 // -------------------------------------------------------------------------- 745 // Setter test cases. 746 747 var setterResult = map[string]error{} 748 749 type setterType struct { 750 received interface{} 751 } 752 753 func (o *setterType) SetBSON(raw bson.Raw) error { 754 err := raw.Unmarshal(&o.received) 755 if err != nil { 756 panic("The panic:" + err.Error()) 757 } 758 if s, ok := o.received.(string); ok { 759 if result, ok := setterResult[s]; ok { 760 return result 761 } 762 } 763 return nil 764 } 765 766 type ptrSetterDoc struct { 767 Field *setterType "_" 768 } 769 770 type valSetterDoc struct { 771 Field setterType "_" 772 } 773 774 func (s *S) TestUnmarshalAllItemsWithPtrSetter(c *C) { 775 for _, item := range allItems { 776 for i := 0; i != 2; i++ { 777 var field *setterType 778 if i == 0 { 779 obj := &ptrSetterDoc{} 780 err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj) 781 c.Assert(err, IsNil) 782 field = obj.Field 783 } else { 784 obj := &valSetterDoc{} 785 err := bson.Unmarshal([]byte(wrapInDoc(item.data)), obj) 786 c.Assert(err, IsNil) 787 field = &obj.Field 788 } 789 if item.data == "" { 790 // Nothing to unmarshal. Should be untouched. 791 if i == 0 { 792 c.Assert(field, IsNil) 793 } else { 794 c.Assert(field.received, IsNil) 795 } 796 } else { 797 expected := item.obj.(bson.M)["_"] 798 c.Assert(field, NotNil, Commentf("Pointer not initialized (%#v)", expected)) 799 c.Assert(field.received, DeepEquals, expected) 800 } 801 } 802 } 803 } 804 805 func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) { 806 obj := &setterType{} 807 err := bson.Unmarshal([]byte(sampleItems[0].data), obj) 808 c.Assert(err, IsNil) 809 c.Assert(obj.received, DeepEquals, bson.M{"hello": "world"}) 810 } 811 812 func (s *S) TestUnmarshalSetterOmits(c *C) { 813 setterResult["2"] = &bson.TypeError{} 814 setterResult["4"] = &bson.TypeError{} 815 defer func() { 816 delete(setterResult, "2") 817 delete(setterResult, "4") 818 }() 819 820 m := map[string]*setterType{} 821 data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" + 822 "\x02def\x00\x02\x00\x00\x002\x00" + 823 "\x02ghi\x00\x02\x00\x00\x003\x00" + 824 "\x02jkl\x00\x02\x00\x00\x004\x00") 825 err := bson.Unmarshal([]byte(data), m) 826 c.Assert(err, IsNil) 827 c.Assert(m["abc"], NotNil) 828 c.Assert(m["def"], IsNil) 829 c.Assert(m["ghi"], NotNil) 830 c.Assert(m["jkl"], IsNil) 831 832 c.Assert(m["abc"].received, Equals, "1") 833 c.Assert(m["ghi"].received, Equals, "3") 834 } 835 836 func (s *S) TestUnmarshalSetterErrors(c *C) { 837 boom := errors.New("BOOM") 838 setterResult["2"] = boom 839 defer delete(setterResult, "2") 840 841 m := map[string]*setterType{} 842 data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" + 843 "\x02def\x00\x02\x00\x00\x002\x00" + 844 "\x02ghi\x00\x02\x00\x00\x003\x00") 845 err := bson.Unmarshal([]byte(data), m) 846 c.Assert(err, Equals, boom) 847 c.Assert(m["abc"], NotNil) 848 c.Assert(m["def"], IsNil) 849 c.Assert(m["ghi"], IsNil) 850 851 c.Assert(m["abc"].received, Equals, "1") 852 } 853 854 func (s *S) TestDMap(c *C) { 855 d := bson.D{{"a", 1}, {"b", 2}} 856 c.Assert(d.Map(), DeepEquals, bson.M{"a": 1, "b": 2}) 857 } 858 859 func (s *S) TestUnmarshalSetterSetZero(c *C) { 860 setterResult["foo"] = bson.SetZero 861 defer delete(setterResult, "field") 862 863 data, err := bson.Marshal(bson.M{"field": "foo"}) 864 c.Assert(err, IsNil) 865 866 m := map[string]*setterType{} 867 err = bson.Unmarshal([]byte(data), m) 868 c.Assert(err, IsNil) 869 870 value, ok := m["field"] 871 c.Assert(ok, Equals, true) 872 c.Assert(value, IsNil) 873 } 874 875 // -------------------------------------------------------------------------- 876 // Getter test cases. 877 878 type typeWithGetter struct { 879 result interface{} 880 err error 881 } 882 883 func (t *typeWithGetter) GetBSON() (interface{}, error) { 884 if t == nil { 885 return "<value is nil>", nil 886 } 887 return t.result, t.err 888 } 889 890 type docWithGetterField struct { 891 Field *typeWithGetter "_" 892 } 893 894 func (s *S) TestMarshalAllItemsWithGetter(c *C) { 895 for i, item := range allItems { 896 if item.data == "" { 897 continue 898 } 899 obj := &docWithGetterField{} 900 obj.Field = &typeWithGetter{result: item.obj.(bson.M)["_"]} 901 data, err := bson.Marshal(obj) 902 c.Assert(err, IsNil) 903 c.Assert(string(data), Equals, wrapInDoc(item.data), 904 Commentf("Failed on item #%d", i)) 905 } 906 } 907 908 func (s *S) TestMarshalWholeDocumentWithGetter(c *C) { 909 obj := &typeWithGetter{result: sampleItems[0].obj} 910 data, err := bson.Marshal(obj) 911 c.Assert(err, IsNil) 912 c.Assert(string(data), Equals, sampleItems[0].data) 913 } 914 915 func (s *S) TestGetterErrors(c *C) { 916 e := errors.New("oops") 917 918 obj1 := &docWithGetterField{} 919 obj1.Field = &typeWithGetter{sampleItems[0].obj, e} 920 data, err := bson.Marshal(obj1) 921 c.Assert(err, ErrorMatches, "oops") 922 c.Assert(data, IsNil) 923 924 obj2 := &typeWithGetter{sampleItems[0].obj, e} 925 data, err = bson.Marshal(obj2) 926 c.Assert(err, ErrorMatches, "oops") 927 c.Assert(data, IsNil) 928 } 929 930 type intGetter int64 931 932 func (t intGetter) GetBSON() (interface{}, error) { 933 return int64(t), nil 934 } 935 936 type typeWithIntGetter struct { 937 V intGetter ",minsize" 938 } 939 940 func (s *S) TestMarshalShortWithGetter(c *C) { 941 obj := typeWithIntGetter{42} 942 data, err := bson.Marshal(obj) 943 c.Assert(err, IsNil) 944 m := bson.M{} 945 err = bson.Unmarshal(data, m) 946 c.Assert(err, IsNil) 947 c.Assert(m["v"], Equals, 42) 948 } 949 950 func (s *S) TestMarshalWithGetterNil(c *C) { 951 obj := docWithGetterField{} 952 data, err := bson.Marshal(obj) 953 c.Assert(err, IsNil) 954 m := bson.M{} 955 err = bson.Unmarshal(data, m) 956 c.Assert(err, IsNil) 957 c.Assert(m, DeepEquals, bson.M{"_": "<value is nil>"}) 958 } 959 960 // -------------------------------------------------------------------------- 961 // Cross-type conversion tests. 962 963 type crossTypeItem struct { 964 obj1 interface{} 965 obj2 interface{} 966 } 967 968 type condStr struct { 969 V string ",omitempty" 970 } 971 type condStrNS struct { 972 V string `a:"A" bson:",omitempty" b:"B"` 973 } 974 type condBool struct { 975 V bool ",omitempty" 976 } 977 type condInt struct { 978 V int ",omitempty" 979 } 980 type condUInt struct { 981 V uint ",omitempty" 982 } 983 type condFloat struct { 984 V float64 ",omitempty" 985 } 986 type condIface struct { 987 V interface{} ",omitempty" 988 } 989 type condPtr struct { 990 V *bool ",omitempty" 991 } 992 type condSlice struct { 993 V []string ",omitempty" 994 } 995 type condMap struct { 996 V map[string]int ",omitempty" 997 } 998 type namedCondStr struct { 999 V string "myv,omitempty" 1000 } 1001 type condTime struct { 1002 V time.Time ",omitempty" 1003 } 1004 type condStruct struct { 1005 V struct{ A []int } ",omitempty" 1006 } 1007 type condRaw struct { 1008 V bson.Raw ",omitempty" 1009 } 1010 1011 type shortInt struct { 1012 V int64 ",minsize" 1013 } 1014 type shortUint struct { 1015 V uint64 ",minsize" 1016 } 1017 type shortIface struct { 1018 V interface{} ",minsize" 1019 } 1020 type shortPtr struct { 1021 V *int64 ",minsize" 1022 } 1023 type shortNonEmptyInt struct { 1024 V int64 ",minsize,omitempty" 1025 } 1026 1027 type inlineInt struct { 1028 V struct{ A, B int } ",inline" 1029 } 1030 type inlineCantPtr struct { 1031 V *struct{ A, B int } ",inline" 1032 } 1033 type inlineDupName struct { 1034 A int 1035 V struct{ A, B int } ",inline" 1036 } 1037 type inlineMap struct { 1038 A int 1039 M map[string]interface{} ",inline" 1040 } 1041 type inlineMapInt struct { 1042 A int 1043 M map[string]int ",inline" 1044 } 1045 type inlineMapMyM struct { 1046 A int 1047 M MyM ",inline" 1048 } 1049 type inlineDupMap struct { 1050 M1 map[string]interface{} ",inline" 1051 M2 map[string]interface{} ",inline" 1052 } 1053 type inlineBadKeyMap struct { 1054 M map[int]int ",inline" 1055 } 1056 type inlineUnexported struct { 1057 M map[string]interface{} ",inline" 1058 unexported ",inline" 1059 } 1060 type unexported struct { 1061 A int 1062 } 1063 1064 type getterSetterD bson.D 1065 1066 func (s getterSetterD) GetBSON() (interface{}, error) { 1067 if len(s) == 0 { 1068 return bson.D{}, nil 1069 } 1070 return bson.D(s[:len(s)-1]), nil 1071 } 1072 1073 func (s *getterSetterD) SetBSON(raw bson.Raw) error { 1074 var doc bson.D 1075 err := raw.Unmarshal(&doc) 1076 doc = append(doc, bson.DocElem{"suffix", true}) 1077 *s = getterSetterD(doc) 1078 return err 1079 } 1080 1081 type getterSetterInt int 1082 1083 func (i getterSetterInt) GetBSON() (interface{}, error) { 1084 return bson.D{{"a", int(i)}}, nil 1085 } 1086 1087 func (i *getterSetterInt) SetBSON(raw bson.Raw) error { 1088 var doc struct{ A int } 1089 err := raw.Unmarshal(&doc) 1090 *i = getterSetterInt(doc.A) 1091 return err 1092 } 1093 1094 type ifaceType interface { 1095 Hello() 1096 } 1097 1098 type ifaceSlice []ifaceType 1099 1100 func (s *ifaceSlice) SetBSON(raw bson.Raw) error { 1101 var ns []int 1102 if err := raw.Unmarshal(&ns); err != nil { 1103 return err 1104 } 1105 *s = make(ifaceSlice, ns[0]) 1106 return nil 1107 } 1108 1109 func (s ifaceSlice) GetBSON() (interface{}, error) { 1110 return []int{len(s)}, nil 1111 } 1112 1113 type ( 1114 MyString string 1115 MyBytes []byte 1116 MyBool bool 1117 MyD []bson.DocElem 1118 MyRawD []bson.RawDocElem 1119 MyM map[string]interface{} 1120 ) 1121 1122 var ( 1123 truevar = true 1124 falsevar = false 1125 1126 int64var = int64(42) 1127 int64ptr = &int64var 1128 intvar = int(42) 1129 intptr = &intvar 1130 1131 gsintvar = getterSetterInt(42) 1132 ) 1133 1134 func parseURL(s string) *url.URL { 1135 u, err := url.Parse(s) 1136 if err != nil { 1137 panic(err) 1138 } 1139 return u 1140 } 1141 1142 // That's a pretty fun test. It will dump the first item, generate a zero 1143 // value equivalent to the second one, load the dumped data onto it, and then 1144 // verify that the resulting value is deep-equal to the untouched second value. 1145 // Then, it will do the same in the *opposite* direction! 1146 var twoWayCrossItems = []crossTypeItem{ 1147 // int<=>int 1148 {&struct{ I int }{42}, &struct{ I int8 }{42}}, 1149 {&struct{ I int }{42}, &struct{ I int32 }{42}}, 1150 {&struct{ I int }{42}, &struct{ I int64 }{42}}, 1151 {&struct{ I int8 }{42}, &struct{ I int32 }{42}}, 1152 {&struct{ I int8 }{42}, &struct{ I int64 }{42}}, 1153 {&struct{ I int32 }{42}, &struct{ I int64 }{42}}, 1154 1155 // uint<=>uint 1156 {&struct{ I uint }{42}, &struct{ I uint8 }{42}}, 1157 {&struct{ I uint }{42}, &struct{ I uint32 }{42}}, 1158 {&struct{ I uint }{42}, &struct{ I uint64 }{42}}, 1159 {&struct{ I uint8 }{42}, &struct{ I uint32 }{42}}, 1160 {&struct{ I uint8 }{42}, &struct{ I uint64 }{42}}, 1161 {&struct{ I uint32 }{42}, &struct{ I uint64 }{42}}, 1162 1163 // float32<=>float64 1164 {&struct{ I float32 }{42}, &struct{ I float64 }{42}}, 1165 1166 // int<=>uint 1167 {&struct{ I uint }{42}, &struct{ I int }{42}}, 1168 {&struct{ I uint }{42}, &struct{ I int8 }{42}}, 1169 {&struct{ I uint }{42}, &struct{ I int32 }{42}}, 1170 {&struct{ I uint }{42}, &struct{ I int64 }{42}}, 1171 {&struct{ I uint8 }{42}, &struct{ I int }{42}}, 1172 {&struct{ I uint8 }{42}, &struct{ I int8 }{42}}, 1173 {&struct{ I uint8 }{42}, &struct{ I int32 }{42}}, 1174 {&struct{ I uint8 }{42}, &struct{ I int64 }{42}}, 1175 {&struct{ I uint32 }{42}, &struct{ I int }{42}}, 1176 {&struct{ I uint32 }{42}, &struct{ I int8 }{42}}, 1177 {&struct{ I uint32 }{42}, &struct{ I int32 }{42}}, 1178 {&struct{ I uint32 }{42}, &struct{ I int64 }{42}}, 1179 {&struct{ I uint64 }{42}, &struct{ I int }{42}}, 1180 {&struct{ I uint64 }{42}, &struct{ I int8 }{42}}, 1181 {&struct{ I uint64 }{42}, &struct{ I int32 }{42}}, 1182 {&struct{ I uint64 }{42}, &struct{ I int64 }{42}}, 1183 1184 // int <=> float 1185 {&struct{ I int }{42}, &struct{ I float64 }{42}}, 1186 1187 // int <=> bool 1188 {&struct{ I int }{1}, &struct{ I bool }{true}}, 1189 {&struct{ I int }{0}, &struct{ I bool }{false}}, 1190 1191 // uint <=> float64 1192 {&struct{ I uint }{42}, &struct{ I float64 }{42}}, 1193 1194 // uint <=> bool 1195 {&struct{ I uint }{1}, &struct{ I bool }{true}}, 1196 {&struct{ I uint }{0}, &struct{ I bool }{false}}, 1197 1198 // float64 <=> bool 1199 {&struct{ I float64 }{1}, &struct{ I bool }{true}}, 1200 {&struct{ I float64 }{0}, &struct{ I bool }{false}}, 1201 1202 // string <=> string and string <=> []byte 1203 {&struct{ S []byte }{[]byte("abc")}, &struct{ S string }{"abc"}}, 1204 {&struct{ S []byte }{[]byte("def")}, &struct{ S bson.Symbol }{"def"}}, 1205 {&struct{ S string }{"ghi"}, &struct{ S bson.Symbol }{"ghi"}}, 1206 1207 // map <=> struct 1208 {&struct { 1209 A struct { 1210 B, C int 1211 } 1212 }{struct{ B, C int }{1, 2}}, 1213 map[string]map[string]int{"a": map[string]int{"b": 1, "c": 2}}}, 1214 1215 {&struct{ A bson.Symbol }{"abc"}, map[string]string{"a": "abc"}}, 1216 {&struct{ A bson.Symbol }{"abc"}, map[string][]byte{"a": []byte("abc")}}, 1217 {&struct{ A []byte }{[]byte("abc")}, map[string]string{"a": "abc"}}, 1218 {&struct{ A uint }{42}, map[string]int{"a": 42}}, 1219 {&struct{ A uint }{42}, map[string]float64{"a": 42}}, 1220 {&struct{ A uint }{1}, map[string]bool{"a": true}}, 1221 {&struct{ A int }{42}, map[string]uint{"a": 42}}, 1222 {&struct{ A int }{42}, map[string]float64{"a": 42}}, 1223 {&struct{ A int }{1}, map[string]bool{"a": true}}, 1224 {&struct{ A float64 }{42}, map[string]float32{"a": 42}}, 1225 {&struct{ A float64 }{42}, map[string]int{"a": 42}}, 1226 {&struct{ A float64 }{42}, map[string]uint{"a": 42}}, 1227 {&struct{ A float64 }{1}, map[string]bool{"a": true}}, 1228 {&struct{ A bool }{true}, map[string]int{"a": 1}}, 1229 {&struct{ A bool }{true}, map[string]uint{"a": 1}}, 1230 {&struct{ A bool }{true}, map[string]float64{"a": 1}}, 1231 {&struct{ A **byte }{&byteptr}, map[string]byte{"a": 8}}, 1232 1233 // url.URL <=> string 1234 {&struct{ URL *url.URL }{parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}}, 1235 {&struct{ URL url.URL }{*parseURL("h://e.c/p")}, map[string]string{"url": "h://e.c/p"}}, 1236 1237 // Slices 1238 {&struct{ S []int }{[]int{1, 2, 3}}, map[string][]int{"s": []int{1, 2, 3}}}, 1239 {&struct{ S *[]int }{&[]int{1, 2, 3}}, map[string][]int{"s": []int{1, 2, 3}}}, 1240 1241 // Conditionals 1242 {&condBool{true}, map[string]bool{"v": true}}, 1243 {&condBool{}, map[string]bool{}}, 1244 {&condInt{1}, map[string]int{"v": 1}}, 1245 {&condInt{}, map[string]int{}}, 1246 {&condUInt{1}, map[string]uint{"v": 1}}, 1247 {&condUInt{}, map[string]uint{}}, 1248 {&condFloat{}, map[string]int{}}, 1249 {&condStr{"yo"}, map[string]string{"v": "yo"}}, 1250 {&condStr{}, map[string]string{}}, 1251 {&condStrNS{"yo"}, map[string]string{"v": "yo"}}, 1252 {&condStrNS{}, map[string]string{}}, 1253 {&condSlice{[]string{"yo"}}, map[string][]string{"v": []string{"yo"}}}, 1254 {&condSlice{}, map[string][]string{}}, 1255 {&condMap{map[string]int{"k": 1}}, bson.M{"v": bson.M{"k": 1}}}, 1256 {&condMap{}, map[string][]string{}}, 1257 {&condIface{"yo"}, map[string]string{"v": "yo"}}, 1258 {&condIface{""}, map[string]string{"v": ""}}, 1259 {&condIface{}, map[string]string{}}, 1260 {&condPtr{&truevar}, map[string]bool{"v": true}}, 1261 {&condPtr{&falsevar}, map[string]bool{"v": false}}, 1262 {&condPtr{}, map[string]string{}}, 1263 1264 {&condTime{time.Unix(123456789, 123e6)}, map[string]time.Time{"v": time.Unix(123456789, 123e6)}}, 1265 {&condTime{}, map[string]string{}}, 1266 1267 {&condStruct{struct{ A []int }{[]int{1}}}, bson.M{"v": bson.M{"a": []interface{}{1}}}}, 1268 {&condStruct{struct{ A []int }{}}, bson.M{}}, 1269 1270 {&condRaw{bson.Raw{Kind: 0x0A, Data: []byte{}}}, bson.M{"v": nil}}, 1271 {&condRaw{bson.Raw{Kind: 0x00}}, bson.M{}}, 1272 1273 {&namedCondStr{"yo"}, map[string]string{"myv": "yo"}}, 1274 {&namedCondStr{}, map[string]string{}}, 1275 1276 {&shortInt{1}, map[string]interface{}{"v": 1}}, 1277 {&shortInt{1 << 30}, map[string]interface{}{"v": 1 << 30}}, 1278 {&shortInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}}, 1279 {&shortUint{1 << 30}, map[string]interface{}{"v": 1 << 30}}, 1280 {&shortUint{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}}, 1281 {&shortIface{int64(1) << 31}, map[string]interface{}{"v": int64(1 << 31)}}, 1282 {&shortPtr{int64ptr}, map[string]interface{}{"v": intvar}}, 1283 1284 {&shortNonEmptyInt{1}, map[string]interface{}{"v": 1}}, 1285 {&shortNonEmptyInt{1 << 31}, map[string]interface{}{"v": int64(1 << 31)}}, 1286 {&shortNonEmptyInt{}, map[string]interface{}{}}, 1287 1288 {&inlineInt{struct{ A, B int }{1, 2}}, map[string]interface{}{"a": 1, "b": 2}}, 1289 {&inlineMap{A: 1, M: map[string]interface{}{"b": 2}}, map[string]interface{}{"a": 1, "b": 2}}, 1290 {&inlineMap{A: 1, M: nil}, map[string]interface{}{"a": 1}}, 1291 {&inlineMapInt{A: 1, M: map[string]int{"b": 2}}, map[string]int{"a": 1, "b": 2}}, 1292 {&inlineMapInt{A: 1, M: nil}, map[string]int{"a": 1}}, 1293 {&inlineMapMyM{A: 1, M: MyM{"b": MyM{"c": 3}}}, map[string]interface{}{"a": 1, "b": map[string]interface{}{"c": 3}}}, 1294 {&inlineUnexported{M: map[string]interface{}{"b": 1}, unexported: unexported{A: 2}}, map[string]interface{}{"b": 1, "a": 2}}, 1295 1296 // []byte <=> Binary 1297 {&struct{ B []byte }{[]byte("abc")}, map[string]bson.Binary{"b": bson.Binary{Data: []byte("abc")}}}, 1298 1299 // []byte <=> MyBytes 1300 {&struct{ B MyBytes }{[]byte("abc")}, map[string]string{"b": "abc"}}, 1301 {&struct{ B MyBytes }{[]byte{}}, map[string]string{"b": ""}}, 1302 {&struct{ B MyBytes }{}, map[string]bool{}}, 1303 {&struct{ B []byte }{[]byte("abc")}, map[string]MyBytes{"b": []byte("abc")}}, 1304 1305 // bool <=> MyBool 1306 {&struct{ B MyBool }{true}, map[string]bool{"b": true}}, 1307 {&struct{ B MyBool }{}, map[string]bool{"b": false}}, 1308 {&struct{ B MyBool }{}, map[string]string{}}, 1309 {&struct{ B bool }{}, map[string]MyBool{"b": false}}, 1310 1311 // arrays 1312 {&struct{ V [2]int }{[...]int{1, 2}}, map[string][2]int{"v": [2]int{1, 2}}}, 1313 {&struct{ V [2]byte }{[...]byte{1, 2}}, map[string][2]byte{"v": [2]byte{1, 2}}}, 1314 1315 // zero time 1316 {&struct{ V time.Time }{}, map[string]interface{}{"v": time.Time{}}}, 1317 1318 // zero time + 1 second + 1 millisecond; overflows int64 as nanoseconds 1319 {&struct{ V time.Time }{time.Unix(-62135596799, 1e6).Local()}, 1320 map[string]interface{}{"v": time.Unix(-62135596799, 1e6).Local()}}, 1321 1322 // bson.D <=> []DocElem 1323 {&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}}, 1324 {&bson.D{{"a", bson.D{{"b", 1}, {"c", 2}}}}, &MyD{{"a", MyD{{"b", 1}, {"c", 2}}}}}, 1325 {&struct{ V MyD }{MyD{{"a", 1}}}, &bson.D{{"v", bson.D{{"a", 1}}}}}, 1326 1327 // bson.RawD <=> []RawDocElem 1328 {&bson.RawD{{"a", bson.Raw{0x08, []byte{0x01}}}}, &bson.RawD{{"a", bson.Raw{0x08, []byte{0x01}}}}}, 1329 {&bson.RawD{{"a", bson.Raw{0x08, []byte{0x01}}}}, &MyRawD{{"a", bson.Raw{0x08, []byte{0x01}}}}}, 1330 1331 // bson.M <=> map 1332 {bson.M{"a": bson.M{"b": 1, "c": 2}}, MyM{"a": MyM{"b": 1, "c": 2}}}, 1333 {bson.M{"a": bson.M{"b": 1, "c": 2}}, map[string]interface{}{"a": map[string]interface{}{"b": 1, "c": 2}}}, 1334 1335 // bson.M <=> map[MyString] 1336 {bson.M{"a": bson.M{"b": 1, "c": 2}}, map[MyString]interface{}{"a": map[MyString]interface{}{"b": 1, "c": 2}}}, 1337 1338 // json.Number <=> int64, float64 1339 {&struct{ N json.Number }{"5"}, map[string]interface{}{"n": int64(5)}}, 1340 {&struct{ N json.Number }{"5.05"}, map[string]interface{}{"n": 5.05}}, 1341 {&struct{ N json.Number }{"9223372036854776000"}, map[string]interface{}{"n": float64(1 << 63)}}, 1342 1343 // bson.D <=> non-struct getter/setter 1344 {&bson.D{{"a", 1}}, &getterSetterD{{"a", 1}, {"suffix", true}}}, 1345 {&bson.D{{"a", 42}}, &gsintvar}, 1346 1347 // Interface slice setter. 1348 {&struct{ V ifaceSlice }{ifaceSlice{nil, nil, nil}}, bson.M{"v": []interface{}{3}}}, 1349 } 1350 1351 // Same thing, but only one way (obj1 => obj2). 1352 var oneWayCrossItems = []crossTypeItem{ 1353 // map <=> struct 1354 {map[string]interface{}{"a": 1, "b": "2", "c": 3}, map[string]int{"a": 1, "c": 3}}, 1355 1356 // inline map elides badly typed values 1357 {map[string]interface{}{"a": 1, "b": "2", "c": 3}, &inlineMapInt{A: 1, M: map[string]int{"c": 3}}}, 1358 1359 // Can't decode int into struct. 1360 {bson.M{"a": bson.M{"b": 2}}, &struct{ A bool }{}}, 1361 1362 // Would get decoded into a int32 too in the opposite direction. 1363 {&shortIface{int64(1) << 30}, map[string]interface{}{"v": 1 << 30}}, 1364 1365 // Ensure omitempty on struct with private fields works properly. 1366 {&struct { 1367 V struct{ v time.Time } ",omitempty" 1368 }{}, map[string]interface{}{}}, 1369 1370 // Attempt to marshal slice into RawD (issue #120). 1371 {bson.M{"x": []int{1, 2, 3}}, &struct{ X bson.RawD }{}}, 1372 } 1373 1374 func testCrossPair(c *C, dump interface{}, load interface{}) { 1375 c.Logf("Dump: %#v", dump) 1376 c.Logf("Load: %#v", load) 1377 zero := makeZeroDoc(load) 1378 data, err := bson.Marshal(dump) 1379 c.Assert(err, IsNil) 1380 c.Logf("Dumped: %#v", string(data)) 1381 err = bson.Unmarshal(data, zero) 1382 c.Assert(err, IsNil) 1383 c.Logf("Loaded: %#v", zero) 1384 c.Assert(zero, DeepEquals, load) 1385 } 1386 1387 func (s *S) TestTwoWayCrossPairs(c *C) { 1388 for _, item := range twoWayCrossItems { 1389 testCrossPair(c, item.obj1, item.obj2) 1390 testCrossPair(c, item.obj2, item.obj1) 1391 } 1392 } 1393 1394 func (s *S) TestOneWayCrossPairs(c *C) { 1395 for _, item := range oneWayCrossItems { 1396 testCrossPair(c, item.obj1, item.obj2) 1397 } 1398 } 1399 1400 // -------------------------------------------------------------------------- 1401 // ObjectId hex representation test. 1402 1403 func (s *S) TestObjectIdHex(c *C) { 1404 id := bson.ObjectIdHex("4d88e15b60f486e428412dc9") 1405 c.Assert(id.String(), Equals, `ObjectIdHex("4d88e15b60f486e428412dc9")`) 1406 c.Assert(id.Hex(), Equals, "4d88e15b60f486e428412dc9") 1407 } 1408 1409 func (s *S) TestIsObjectIdHex(c *C) { 1410 test := []struct { 1411 id string 1412 valid bool 1413 }{ 1414 {"4d88e15b60f486e428412dc9", true}, 1415 {"4d88e15b60f486e428412dc", false}, 1416 {"4d88e15b60f486e428412dc9e", false}, 1417 {"4d88e15b60f486e428412dcx", false}, 1418 } 1419 for _, t := range test { 1420 c.Assert(bson.IsObjectIdHex(t.id), Equals, t.valid) 1421 } 1422 } 1423 1424 // -------------------------------------------------------------------------- 1425 // ObjectId parts extraction tests. 1426 1427 type objectIdParts struct { 1428 id bson.ObjectId 1429 timestamp int64 1430 machine []byte 1431 pid uint16 1432 counter int32 1433 } 1434 1435 var objectIds = []objectIdParts{ 1436 objectIdParts{ 1437 bson.ObjectIdHex("4d88e15b60f486e428412dc9"), 1438 1300816219, 1439 []byte{0x60, 0xf4, 0x86}, 1440 0xe428, 1441 4271561, 1442 }, 1443 objectIdParts{ 1444 bson.ObjectIdHex("000000000000000000000000"), 1445 0, 1446 []byte{0x00, 0x00, 0x00}, 1447 0x0000, 1448 0, 1449 }, 1450 objectIdParts{ 1451 bson.ObjectIdHex("00000000aabbccddee000001"), 1452 0, 1453 []byte{0xaa, 0xbb, 0xcc}, 1454 0xddee, 1455 1, 1456 }, 1457 } 1458 1459 func (s *S) TestObjectIdPartsExtraction(c *C) { 1460 for i, v := range objectIds { 1461 t := time.Unix(v.timestamp, 0) 1462 c.Assert(v.id.Time(), Equals, t, Commentf("#%d Wrong timestamp value", i)) 1463 c.Assert(v.id.Machine(), DeepEquals, v.machine, Commentf("#%d Wrong machine id value", i)) 1464 c.Assert(v.id.Pid(), Equals, v.pid, Commentf("#%d Wrong pid value", i)) 1465 c.Assert(v.id.Counter(), Equals, v.counter, Commentf("#%d Wrong counter value", i)) 1466 } 1467 } 1468 1469 func (s *S) TestNow(c *C) { 1470 before := time.Now() 1471 time.Sleep(1e6) 1472 now := bson.Now() 1473 time.Sleep(1e6) 1474 after := time.Now() 1475 c.Assert(now.After(before) && now.Before(after), Equals, true, Commentf("now=%s, before=%s, after=%s", now, before, after)) 1476 } 1477 1478 // -------------------------------------------------------------------------- 1479 // ObjectId generation tests. 1480 1481 func (s *S) TestNewObjectId(c *C) { 1482 // Generate 10 ids 1483 ids := make([]bson.ObjectId, 10) 1484 for i := 0; i < 10; i++ { 1485 ids[i] = bson.NewObjectId() 1486 } 1487 for i := 1; i < 10; i++ { 1488 prevId := ids[i-1] 1489 id := ids[i] 1490 // Test for uniqueness among all other 9 generated ids 1491 for j, tid := range ids { 1492 if j != i { 1493 c.Assert(id, Not(Equals), tid, Commentf("Generated ObjectId is not unique")) 1494 } 1495 } 1496 // Check that timestamp was incremented and is within 30 seconds of the previous one 1497 secs := id.Time().Sub(prevId.Time()).Seconds() 1498 c.Assert((secs >= 0 && secs <= 30), Equals, true, Commentf("Wrong timestamp in generated ObjectId")) 1499 // Check that machine ids are the same 1500 c.Assert(id.Machine(), DeepEquals, prevId.Machine()) 1501 // Check that pids are the same 1502 c.Assert(id.Pid(), Equals, prevId.Pid()) 1503 // Test for proper increment 1504 delta := int(id.Counter() - prevId.Counter()) 1505 c.Assert(delta, Equals, 1, Commentf("Wrong increment in generated ObjectId")) 1506 } 1507 } 1508 1509 func (s *S) TestNewObjectIdWithTime(c *C) { 1510 t := time.Unix(12345678, 0) 1511 id := bson.NewObjectIdWithTime(t) 1512 c.Assert(id.Time(), Equals, t) 1513 c.Assert(id.Machine(), DeepEquals, []byte{0x00, 0x00, 0x00}) 1514 c.Assert(int(id.Pid()), Equals, 0) 1515 c.Assert(int(id.Counter()), Equals, 0) 1516 } 1517 1518 // -------------------------------------------------------------------------- 1519 // ObjectId JSON marshalling. 1520 1521 type jsonType struct { 1522 Id bson.ObjectId 1523 } 1524 1525 var jsonIdTests = []struct { 1526 value jsonType 1527 json string 1528 marshal bool 1529 unmarshal bool 1530 error string 1531 }{{ 1532 value: jsonType{Id: bson.ObjectIdHex("4d88e15b60f486e428412dc9")}, 1533 json: `{"Id":"4d88e15b60f486e428412dc9"}`, 1534 marshal: true, 1535 unmarshal: true, 1536 }, { 1537 value: jsonType{}, 1538 json: `{"Id":""}`, 1539 marshal: true, 1540 unmarshal: true, 1541 }, { 1542 value: jsonType{}, 1543 json: `{"Id":null}`, 1544 marshal: false, 1545 unmarshal: true, 1546 }, { 1547 json: `{"Id":"4d88e15b60f486e428412dc9A"}`, 1548 error: `invalid ObjectId in JSON: "4d88e15b60f486e428412dc9A"`, 1549 marshal: false, 1550 unmarshal: true, 1551 }, { 1552 json: `{"Id":"4d88e15b60f486e428412dcZ"}`, 1553 error: `invalid ObjectId in JSON: "4d88e15b60f486e428412dcZ" .*`, 1554 marshal: false, 1555 unmarshal: true, 1556 }} 1557 1558 func (s *S) TestObjectIdJSONMarshaling(c *C) { 1559 for _, test := range jsonIdTests { 1560 if test.marshal { 1561 data, err := json.Marshal(&test.value) 1562 if test.error == "" { 1563 c.Assert(err, IsNil) 1564 c.Assert(string(data), Equals, test.json) 1565 } else { 1566 c.Assert(err, ErrorMatches, test.error) 1567 } 1568 } 1569 1570 if test.unmarshal { 1571 var value jsonType 1572 err := json.Unmarshal([]byte(test.json), &value) 1573 if test.error == "" { 1574 c.Assert(err, IsNil) 1575 c.Assert(value, DeepEquals, test.value) 1576 } else { 1577 c.Assert(err, ErrorMatches, test.error) 1578 } 1579 } 1580 } 1581 } 1582 1583 // -------------------------------------------------------------------------- 1584 // Spec tests 1585 1586 type specTest struct { 1587 Description string 1588 Documents []struct { 1589 Decoded map[string]interface{} 1590 Encoded string 1591 DecodeOnly bool `yaml:"decodeOnly"` 1592 Error interface{} 1593 } 1594 } 1595 1596 func (s *S) TestSpecTests(c *C) { 1597 for _, data := range specTests { 1598 var test specTest 1599 err := yaml.Unmarshal([]byte(data), &test) 1600 c.Assert(err, IsNil) 1601 1602 c.Logf("Running spec test set %q", test.Description) 1603 1604 for _, doc := range test.Documents { 1605 if doc.Error != nil { 1606 continue 1607 } 1608 c.Logf("Ensuring %q decodes as %v", doc.Encoded, doc.Decoded) 1609 var decoded map[string]interface{} 1610 encoded, err := hex.DecodeString(doc.Encoded) 1611 c.Assert(err, IsNil) 1612 err = bson.Unmarshal(encoded, &decoded) 1613 c.Assert(err, IsNil) 1614 c.Assert(decoded, DeepEquals, doc.Decoded) 1615 } 1616 1617 for _, doc := range test.Documents { 1618 if doc.DecodeOnly || doc.Error != nil { 1619 continue 1620 } 1621 c.Logf("Ensuring %v encodes as %q", doc.Decoded, doc.Encoded) 1622 encoded, err := bson.Marshal(doc.Decoded) 1623 c.Assert(err, IsNil) 1624 c.Assert(strings.ToUpper(hex.EncodeToString(encoded)), Equals, doc.Encoded) 1625 } 1626 1627 for _, doc := range test.Documents { 1628 if doc.Error == nil { 1629 continue 1630 } 1631 c.Logf("Ensuring %q errors when decoded: %s", doc.Encoded, doc.Error) 1632 var decoded map[string]interface{} 1633 encoded, err := hex.DecodeString(doc.Encoded) 1634 c.Assert(err, IsNil) 1635 err = bson.Unmarshal(encoded, &decoded) 1636 c.Assert(err, NotNil) 1637 c.Logf("Failed with: %v", err) 1638 } 1639 } 1640 } 1641 1642 // -------------------------------------------------------------------------- 1643 // ObjectId Text encoding.TextUnmarshaler. 1644 1645 var textIdTests = []struct { 1646 value bson.ObjectId 1647 text string 1648 marshal bool 1649 unmarshal bool 1650 error string 1651 }{{ 1652 value: bson.ObjectIdHex("4d88e15b60f486e428412dc9"), 1653 text: "4d88e15b60f486e428412dc9", 1654 marshal: true, 1655 unmarshal: true, 1656 }, { 1657 text: "", 1658 marshal: true, 1659 unmarshal: true, 1660 }, { 1661 text: "4d88e15b60f486e428412dc9A", 1662 marshal: false, 1663 unmarshal: true, 1664 error: `invalid ObjectId: 4d88e15b60f486e428412dc9A`, 1665 }, { 1666 text: "4d88e15b60f486e428412dcZ", 1667 marshal: false, 1668 unmarshal: true, 1669 error: `invalid ObjectId: 4d88e15b60f486e428412dcZ .*`, 1670 }} 1671 1672 func (s *S) TestObjectIdTextMarshaling(c *C) { 1673 for _, test := range textIdTests { 1674 if test.marshal { 1675 data, err := test.value.MarshalText() 1676 if test.error == "" { 1677 c.Assert(err, IsNil) 1678 c.Assert(string(data), Equals, test.text) 1679 } else { 1680 c.Assert(err, ErrorMatches, test.error) 1681 } 1682 } 1683 1684 if test.unmarshal { 1685 err := test.value.UnmarshalText([]byte(test.text)) 1686 if test.error == "" { 1687 c.Assert(err, IsNil) 1688 if test.value != "" { 1689 value := bson.ObjectIdHex(test.text) 1690 c.Assert(value, DeepEquals, test.value) 1691 } 1692 } else { 1693 c.Assert(err, ErrorMatches, test.error) 1694 } 1695 } 1696 } 1697 } 1698 1699 // -------------------------------------------------------------------------- 1700 // ObjectId XML marshalling. 1701 1702 type xmlType struct { 1703 Id bson.ObjectId 1704 } 1705 1706 var xmlIdTests = []struct { 1707 value xmlType 1708 xml string 1709 marshal bool 1710 unmarshal bool 1711 error string 1712 }{{ 1713 value: xmlType{Id: bson.ObjectIdHex("4d88e15b60f486e428412dc9")}, 1714 xml: "<xmlType><Id>4d88e15b60f486e428412dc9</Id></xmlType>", 1715 marshal: true, 1716 unmarshal: true, 1717 }, { 1718 value: xmlType{}, 1719 xml: "<xmlType><Id></Id></xmlType>", 1720 marshal: true, 1721 unmarshal: true, 1722 }, { 1723 xml: "<xmlType><Id>4d88e15b60f486e428412dc9A</Id></xmlType>", 1724 marshal: false, 1725 unmarshal: true, 1726 error: `invalid ObjectId: 4d88e15b60f486e428412dc9A`, 1727 }, { 1728 xml: "<xmlType><Id>4d88e15b60f486e428412dcZ</Id></xmlType>", 1729 marshal: false, 1730 unmarshal: true, 1731 error: `invalid ObjectId: 4d88e15b60f486e428412dcZ .*`, 1732 }} 1733 1734 func (s *S) TestObjectIdXMLMarshaling(c *C) { 1735 for _, test := range xmlIdTests { 1736 if test.marshal { 1737 data, err := xml.Marshal(&test.value) 1738 if test.error == "" { 1739 c.Assert(err, IsNil) 1740 c.Assert(string(data), Equals, test.xml) 1741 } else { 1742 c.Assert(err, ErrorMatches, test.error) 1743 } 1744 } 1745 1746 if test.unmarshal { 1747 var value xmlType 1748 err := xml.Unmarshal([]byte(test.xml), &value) 1749 if test.error == "" { 1750 c.Assert(err, IsNil) 1751 c.Assert(value, DeepEquals, test.value) 1752 } else { 1753 c.Assert(err, ErrorMatches, test.error) 1754 } 1755 } 1756 } 1757 } 1758 1759 // -------------------------------------------------------------------------- 1760 // Some simple benchmarks. 1761 1762 type BenchT struct { 1763 A, B, C, D, E, F string 1764 } 1765 1766 type BenchRawT struct { 1767 A string 1768 B int 1769 C bson.M 1770 D []float64 1771 } 1772 1773 func (s *S) BenchmarkUnmarhsalStruct(c *C) { 1774 v := BenchT{A: "A", D: "D", E: "E"} 1775 data, err := bson.Marshal(&v) 1776 if err != nil { 1777 panic(err) 1778 } 1779 c.ResetTimer() 1780 for i := 0; i < c.N; i++ { 1781 err = bson.Unmarshal(data, &v) 1782 } 1783 if err != nil { 1784 panic(err) 1785 } 1786 } 1787 1788 func (s *S) BenchmarkUnmarhsalMap(c *C) { 1789 m := bson.M{"a": "a", "d": "d", "e": "e"} 1790 data, err := bson.Marshal(&m) 1791 if err != nil { 1792 panic(err) 1793 } 1794 c.ResetTimer() 1795 for i := 0; i < c.N; i++ { 1796 err = bson.Unmarshal(data, &m) 1797 } 1798 if err != nil { 1799 panic(err) 1800 } 1801 } 1802 1803 func (s *S) BenchmarkUnmarshalRaw(c *C) { 1804 var err error 1805 m := BenchRawT{ 1806 A: "test_string", 1807 B: 123, 1808 C: bson.M{ 1809 "subdoc_int": 12312, 1810 "subdoc_doc": bson.M{"1": 1}, 1811 }, 1812 D: []float64{0.0, 1.3333, -99.9997, 3.1415}, 1813 } 1814 data, err := bson.Marshal(&m) 1815 if err != nil { 1816 panic(err) 1817 } 1818 raw := bson.Raw{} 1819 c.ResetTimer() 1820 for i := 0; i < c.N; i++ { 1821 err = bson.Unmarshal(data, &raw) 1822 } 1823 if err != nil { 1824 panic(err) 1825 } 1826 } 1827 1828 func (s *S) BenchmarkNewObjectId(c *C) { 1829 for i := 0; i < c.N; i++ { 1830 bson.NewObjectId() 1831 } 1832 }