func TestBsonIterator(t *testing.T) { obj := bson.NewBsonBuilder().AppendString("name", "hello").Finish().Bson() array := bson.NewBsonArrayBuilder().AppendString("hello").Finish().BsonArray() var tests = [...]struct { bsonType bson.BsonType name string value interface{} }{ {bson.BsonTypeFloat64, "double", float64(123.45)}, {bson.BsonTypeString, "string", "hello, bson"}, {bson.BsonTypeBson, "bson", obj}, {bson.BsonTypeArray, "array", array}, {bson.BsonTypeBinary, "binary", bson.Binary{Subtype: bson.BinaryTypeGeneral, Data: []byte("hello")}}, {bson.BsonTypeObjectId, "objectid", bson.NewObjectId()}, {bson.BsonTypeBool, "bool", true}, {bson.BsonTypeDate, "date", bson.Date(12345678)}, {bson.BsonTypeNull, "null", nil}, {bson.BsonTypeRegEx, "regex", bson.RegEx{Pattern: "/s/", Options: "g"}}, {bson.BsonTypeInt32, "int32", int32(100)}, {bson.BsonTypeTimestamp, "timestamp", bson.Timestamp{Second: 123, Increment: 10}}, {bson.BsonTypeInt64, "int64", int64(5000000000)}, {bson.BsonTypeMaxKey, "maxkey", nil}, {bson.BsonTypeMinKey, "minkey", nil}, } doc := bson.NewBsonBuilder() for i := 0; i < len(tests); i++ { test := tests[i] switch test.bsonType { case bson.BsonTypeFloat64: doc.AppendFloat64(test.name, test.value.(float64)) case bson.BsonTypeString: doc.AppendString(test.name, test.value.(string)) case bson.BsonTypeBson: doc.AppendBson(test.name, test.value.(*bson.Bson)) case bson.BsonTypeArray: doc.AppendArray(test.name, test.value.(*bson.BsonArray)) case bson.BsonTypeBinary: doc.AppendBinary(test.name, test.value.(bson.Binary)) case bson.BsonTypeObjectId: doc.AppendObjectId(test.name, test.value.(bson.ObjectId)) case bson.BsonTypeBool: doc.AppendBool(test.name, test.value.(bool)) case bson.BsonTypeDate: doc.AppendDate(test.name, test.value.(bson.Date)) case bson.BsonTypeNull: doc.AppendNull(test.name) case bson.BsonTypeRegEx: doc.AppendRegex(test.name, test.value.(bson.RegEx)) case bson.BsonTypeInt32: doc.AppendInt32(test.name, test.value.(int32)) case bson.BsonTypeInt64: doc.AppendInt64(test.name, test.value.(int64)) case bson.BsonTypeTimestamp: doc.AppendTimestamp(test.name, test.value.(bson.Timestamp)) case bson.BsonTypeMaxKey: doc.AppendMaxKey(test.name) case bson.BsonTypeMinKey: doc.AppendMinKey(test.name) default: t.Fatalf("invalid bson type") } } doc.Finish() it := doc.Bson().Iterator() id := 0 for it.Next() { ts := tests[id] tp := it.BsonType() name := it.Name() id++ if tp != ts.bsonType { t.Errorf("expected type: %v, actual type: %v", ts.bsonType, tp) } if name != ts.name { t.Errorf("expected name: %v, len=%v; actual name: %v, len=%v", ts.name, len(ts.name), name, len(name)) } switch tp { case bson.BsonTypeFloat64: val := it.Float64() if val != ts.value.(float64) { t.Errorf("double value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeString: val := it.UTF8String() if val != ts.value.(string) { t.Errorf("string value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeBson: val := it.Bson() obj := ts.value.(*bson.Bson) valIt := val.Iterator() objIt := obj.Iterator() for valIt.Next() && objIt.Next() { if valIt.BsonType() != objIt.BsonType() { t.Errorf("value type in doc, expected %v, actual %v", objIt.BsonType(), valIt.BsonType()) } if valIt.Name() != objIt.Name() { t.Errorf("name in doc, expected %v, actual %v", objIt.Name(), valIt.Name()) } } if valIt.More() || objIt.More() { t.Errorf("invalid it.More()") } case bson.BsonTypeArray: val := it.BsonArray() obj := ts.value.(*bson.BsonArray) valIt := val.Iterator() objIt := obj.Iterator() for valIt.Next() && objIt.Next() { if valIt.BsonType() != objIt.BsonType() { t.Errorf("value type in doc, expected %v, actual %v", objIt.BsonType(), valIt.BsonType()) } if valIt.Name() != objIt.Name() { t.Errorf("name in doc, expected %v, actual %v", objIt.Name(), valIt.Name()) } } case bson.BsonTypeBinary: val := it.Binary() expected := ts.value.(bson.Binary) if val.Subtype != expected.Subtype { t.Errorf("binary subtype, expected %v, actual %v", expected.Subtype, val.Subtype) } if string(val.Data) != string(expected.Data) { t.Errorf("binary data, expected %v, actual %v", expected.Data, val.Data) } case bson.BsonTypeObjectId: val := it.ObjectId() if val != ts.value.(bson.ObjectId) { t.Errorf("objectid value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeBool: val := it.Bool() if val != ts.value.(bool) { t.Errorf("bool value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeDate: val := it.Date() if val != ts.value.(bson.Date) { t.Errorf("date value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeNull: // no value case bson.BsonTypeRegEx: val := it.RegEx() expected := ts.value.(bson.RegEx) if val.Pattern != expected.Pattern || val.Options != expected.Options { t.Errorf("regex value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeInt32: val := it.Int32() if val != ts.value.(int32) { t.Errorf("int32 value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeInt64: val := it.Int64() if val != ts.value.(int64) { t.Errorf("int64 value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeTimestamp: val := it.Timestamp() expected := ts.value.(bson.Timestamp) if val.Increment != expected.Increment || val.Second != expected.Second { t.Errorf("timestamp value, expected %v, actual %v", ts.value, val) } case bson.BsonTypeMaxKey: // no value case bson.BsonTypeMinKey: // no value default: t.Fatalf("invalid bson type") } } if it.More() { t.Errorf("invalid it.More()") } if it.BsonType() != bson.BsonTypeEOD { t.Errorf("invalid end of iterator") } }
func TestSingleBsonAppend(t *testing.T) { var tests = []struct { bsonType bson.BsonType name string value interface{} want []byte }{ {bson.BsonTypeFloat64, "_", 5.05, []byte("\x10\x00\x00\x00\x01_\x00333333\x14@\x00")}, {bson.BsonTypeString, "_", "hello!", []byte("\x13\x00\x00\x00\x02_\x00\x07\x00\x00\x00hello!\x00\x00")}, {bson.BsonTypeBinary, "_", bson.Binary{Data: []byte("abc")}, []byte("\x10\x00\x00\x00\x05_\x00\x03\x00\x00\x00\x00abc\x00")}, {bson.BsonTypeObjectId, "_", bson.ObjectId("123456789012"), []byte("\x14\x00\x00\x00\x07_\x00123456789012\x00")}, {bson.BsonTypeBool, "_", true, []byte("\x09\x00\x00\x00\x08_\x00\x01\x00")}, {bson.BsonTypeDate, "_", bson.Date(12345), []byte("\x10\x00\x00\x00\x09_\x00\x39\x30\x00\x00\x00\x00\x00\x00\x00")}, {bson.BsonTypeNull, "_", "", []byte("\x08\x00\x00\x00\x0A_\x00\x00")}, {bson.BsonTypeRegEx, "_", bson.RegEx{Pattern: "pat", Options: "opt"}, []byte("\x10\x00\x00\x00\x0B_\x00pat\x00opt\x00\x00")}, {bson.BsonTypeInt32, "_", int32(12345), []byte("\x0C\x00\x00\x00\x10_\x00\x39\x30\x00\x00\x00")}, {bson.BsonTypeInt64, "_", int64(12345), []byte("\x10\x00\x00\x00\x12_\x00\x39\x30\x00\x00\x00\x00\x00\x00\x00")}, {bson.BsonTypeTimestamp, "_", bson.Timestamp{Second: 10, Increment: 20}, []byte("\x10\x00\x00\x00\x11_\x00\x14\x00\x00\x00\x0A\x00\x00\x00\x00")}, {bson.BsonTypeMaxKey, "_", "", []byte("\x08\x00\x00\x00\x7F_\x00\x00")}, {bson.BsonTypeMinKey, "_", "", []byte("\x08\x00\x00\x00\xFF_\x00\x00")}, } for _, test := range tests { doc := bson.NewBsonBuilder() switch test.bsonType { case bson.BsonTypeFloat64: doc.AppendFloat64(test.name, test.value.(float64)) case bson.BsonTypeString: doc.AppendString(test.name, test.value.(string)) case bson.BsonTypeBinary: doc.AppendBinary(test.name, test.value.(bson.Binary)) case bson.BsonTypeObjectId: doc.AppendObjectId(test.name, test.value.(bson.ObjectId)) case bson.BsonTypeBool: doc.AppendBool(test.name, test.value.(bool)) case bson.BsonTypeDate: doc.AppendDate(test.name, test.value.(bson.Date)) case bson.BsonTypeNull: doc.AppendNull(test.name) case bson.BsonTypeRegEx: doc.AppendRegex(test.name, test.value.(bson.RegEx)) case bson.BsonTypeInt32: doc.AppendInt32(test.name, test.value.(int32)) case bson.BsonTypeInt64: doc.AppendInt64(test.name, test.value.(int64)) case bson.BsonTypeTimestamp: doc.AppendTimestamp(test.name, test.value.(bson.Timestamp)) case bson.BsonTypeMaxKey: doc.AppendMaxKey(test.name) case bson.BsonTypeMinKey: doc.AppendMinKey(test.name) default: t.Fatalf("invalid bson type") } doc.Finish() data := doc.Bson().Raw() if len(data) != len(test.want) { t.Errorf("type: %v\nexpected: %v\n actual: %v", test.bsonType, test.want, data) } else { for i, b := range data { if b != test.want[i] { t.Errorf("type: %v\nexpected: %v\n actual: %v", test.bsonType, test.want, data) } } } } }