func TestMap(t *testing.T) {
	m := bson.Map{
		"int":     int(1),
		"int8":    int8(2),
		"float64": float64(123.456),
		"bson": map[string]interface{}{
			"i_int": int(10),
		},
		"array":    []interface{}{int(1), float64(123.456), "hello", bson.NewObjectId()},
		"objectid": bson.NewObjectId(),
		"bool":     true,
		"null":     nil,
		"maxkey":   bson.MaxKey,
		"minkey":   bson.MinKey,
		"string":   "hello",
	}

	m2 := m.Bson().Map()

	if len(m2) != len(m) {
		t.Errorf("bson fields num: %d, map fileds num: %d", len(m2), len(m))
	}

	for k, _ := range m {
		_, exist := m2[k]
		if !exist {
			t.Errorf("bson missing field [%s]", k)
		}
	}
}
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 TestObjectId(t *testing.T) {
	oid := bson.NewObjectId()
	if !oid.IsValid() {
		t.Errorf("invalid ObjectId: %s", oid)
	}
}