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")
	}
}
Exemple #2
0
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)
				}
			}
		}
	}
}