diff options
author | alabid <alabidan@gmail.com> | 2014-10-14 18:15:38 -0400 |
---|---|---|
committer | alabid <alabidan@gmail.com> | 2014-10-17 18:28:31 -0400 |
commit | fcb1a3d5bc92beb19fbd6d6e6d5c0d81b0093399 (patch) | |
tree | 8a07d1b300306698aad82eaa5a3ec3221878a647 | |
parent | 544a35e4e65e023b1cb1291df39df58077edcbbb (diff) | |
download | mongo-fcb1a3d5bc92beb19fbd6d6e6d5c0d81b0093399.tar.gz |
TOOLS-279 added basic unit tests for BSON -> JSON conversion
Former-commit-id: 4c116ef3645c5629c9e883b56a88fe0c1e6e5a63
-rw-r--r-- | common/bsonutil/converter.go | 21 | ||||
-rw-r--r-- | common/bsonutil/converter_test.go | 295 | ||||
-rw-r--r-- | common/json/csv_format.go | 7 | ||||
-rw-r--r-- | common/json/json_format.go | 16 | ||||
-rw-r--r-- | common/json/mongo_extjson.go | 9 | ||||
-rw-r--r-- | src/github.com/mongodb/mongo-tools/common/bsonutil/converter_test.go | 268 |
6 files changed, 606 insertions, 10 deletions
diff --git a/common/bsonutil/converter.go b/common/bsonutil/converter.go index 54187d36ead..17c44cb5fc2 100644 --- a/common/bsonutil/converter.go +++ b/common/bsonutil/converter.go @@ -11,7 +11,6 @@ import ( "time" ) - // ConvertJSONValueToBSON walks through a document or an array and // replaces any extended JSON value with its corresponding BSON type. func ConvertJSONValueToBSON(x interface{}) (interface{}, error) { @@ -52,7 +51,7 @@ func ConvertJSONValueToBSON(x interface{}) (interface{}, error) { case json.Date: // Date n := int64(v) - return time.Unix(n/1e3, n%1e3 * 1e6), nil + return time.Unix(n/1e3, n%1e3*1e6), nil case json.NumberLong: // NumberLong return int64(v), nil @@ -70,6 +69,9 @@ func ConvertJSONValueToBSON(x interface{}) (interface{}, error) { case json.DBRef: // DBRef return mgo.DBRef{v.Collection, v.Id, v.Database}, nil + case json.DBPointer: // DBPointer, for backwards compatibility + return bson.DBPointer{v.Namespace, v.Id}, nil + case json.RegExp: // RegExp return bson.RegEx{v.Pattern, v.Options}, nil @@ -77,6 +79,9 @@ func ConvertJSONValueToBSON(x interface{}) (interface{}, error) { ts := (int64(v.Seconds) << 32) | int64(v.Increment) return bson.MongoTimestamp(ts), nil + case json.JavaScript: // Javascript + return bson.JavaScript{v.Code, v.Scope}, nil + case json.MinKey: // MinKey return bson.MinKey, nil @@ -85,6 +90,7 @@ func ConvertJSONValueToBSON(x interface{}) (interface{}, error) { case json.Undefined: // undefined return bson.Undefined, nil + default: return nil, fmt.Errorf("Conversion of JSON type '%v' unsupported", v) } @@ -151,7 +157,7 @@ func ConvertBSONValueToJSON(x interface{}) (interface{}, error) { return json.ObjectId(v.Hex()), nil case time.Time: // Date - return json.Date(v.UnixNano()/1e6), nil + return json.Date(v.UnixNano() / 1e6), nil case int64: // NumberLong return json.NumberLong(v), nil @@ -176,6 +182,9 @@ func ConvertBSONValueToJSON(x interface{}) (interface{}, error) { case mgo.DBRef: // DBRef return json.DBRef{v.Collection, v.Id, v.Database}, nil + case bson.DBPointer: // DBPointer + return json.DBPointer{v.Namespace, v.Id}, nil + case bson.RegEx: // RegExp return json.RegExp{v.Pattern, v.Options}, nil @@ -185,9 +194,9 @@ func ConvertBSONValueToJSON(x interface{}) (interface{}, error) { Seconds: uint32(timestamp >> 32), Increment: uint32(timestamp), }, nil - case bson.JavaScript: - //TODO handle code with scope - return json.Javascript{v.Code, nil}, nil + + case bson.JavaScript: // JavaScript + return json.JavaScript{v.Code, v.Scope}, nil default: switch x { diff --git a/common/bsonutil/converter_test.go b/common/bsonutil/converter_test.go new file mode 100644 index 00000000000..fa510aeb860 --- /dev/null +++ b/common/bsonutil/converter_test.go @@ -0,0 +1,295 @@ +package bsonutil + +import ( + . "github.com/smartystreets/goconvey/convey" + "github.com/mongodb/mongo-tools/common/json" + "testing" + "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" + "time" + "fmt" + "encoding/base64" +) + + +func TestObjectIdBSONToJSON(t *testing.T) { + Convey("Converting a BSON ObjectId", t, func() { + Convey("that is valid to JSON should produce a json.ObjectId", func() { + bsonObjId := bson.NewObjectId() + jsonObjId := json.ObjectId(bsonObjId.Hex()) + + _jObjId, err := ConvertBSONValueToJSON(bsonObjId) + So(err, ShouldBeNil) + jObjId, ok := _jObjId.(json.ObjectId) + So(ok, ShouldBeTrue) + + So(jObjId, ShouldNotEqual, bsonObjId) + So(jObjId, ShouldEqual, jsonObjId) + }) + }) +} + +func TestArraysBSONToJSON(t *testing.T) { + Convey("Converting BSON arrays to JSON arrays", t, func() { + Convey("should work for empty arrays", func() { + jArr, err := ConvertBSONValueToJSON([]interface{}{}) + So(err, ShouldBeNil) + + So(jArr, ShouldResemble, []interface{}{}) + }) + + Convey("should work for one-level deep arrays", func() { + objId := bson.NewObjectId() + bsonArr := []interface{}{objId, 28, 0.999, "plain"} + _jArr, err := ConvertBSONValueToJSON(bsonArr) + So(err, ShouldBeNil) + jArr, ok := _jArr.([]interface{}) + So(ok, ShouldBeTrue) + + So(len(jArr), ShouldEqual, 4) + So(jArr[0], ShouldEqual, json.ObjectId(objId.Hex())) + So(jArr[1], ShouldEqual, 28) + So(jArr[2], ShouldEqual, 0.999) + So(jArr[3], ShouldEqual, "plain") + }) + + Convey("should work for arrays with embedded objects", func() { + bsonObj := []interface{}{80, bson.M{"a":int64(20), "b":bson.M{"c": bson.RegEx{"hi", "i"}}}} + + __jObj, err := ConvertBSONValueToJSON(bsonObj) + So(err, ShouldBeNil) + _jObj, ok := __jObj.([]interface{}) + So(ok, ShouldBeTrue) + jObj, ok := _jObj[1].(map[string]interface{}) + So(ok, ShouldBeTrue) + So(len(jObj), ShouldEqual, 2) + So(jObj["a"], ShouldEqual, json.NumberLong(20)) + jjObj, ok := jObj["b"].(map[string]interface{}) + So(ok, ShouldBeTrue) + + So(jjObj["c"], ShouldResemble, json.RegExp{"hi", "i"}) + So(jjObj["c"], ShouldNotResemble, json.RegExp{"i", "hi"}) + }) + + }) +} + +func TestDateBSONToJSON(t *testing.T) { + + timeNow := time.Now() + secs := int64(timeNow.Unix()) + nanosecs := timeNow.Nanosecond() + millis := int64(nanosecs/1e6) + + timeNowSecs := time.Unix(secs, int64(0)) + timeNowMillis := time.Unix(secs, int64(millis*1e6)) + + Convey("Converting BSON time.Time 's dates to JSON", t, func() { + // json.Date is stored as an int64 representing the number of milliseconds since the epoch + Convey(fmt.Sprintf("should work with second granularity: %v", timeNowSecs), func() { + _jObj, err := ConvertBSONValueToJSON(timeNowSecs) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Date) + So(ok, ShouldBeTrue) + + So(int64(jObj), ShouldEqual, secs*1e3) + }) + + Convey(fmt.Sprintf("should work with millisecond granularity: %v", timeNowMillis), func() { + _jObj, err := ConvertBSONValueToJSON(timeNowMillis) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Date) + So(ok, ShouldBeTrue) + + So(int64(jObj), ShouldEqual, secs*1e3 + millis) + }) + + Convey(fmt.Sprintf("should work with nanosecond granularity: %v", timeNow), func() { + _jObj, err := ConvertBSONValueToJSON(timeNow) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Date) + So(ok, ShouldBeTrue) + + // we lose nanosecond precision + So(int64(jObj), ShouldEqual, secs*1e3 + millis) + }) + + }) +} + +func TestMaxKeyBSONToJSON(t *testing.T) { + Convey("Converting a BSON Maxkey to JSON", t, func() { + Convey("should produce a json.MaxKey", func() { + _jObj, err := ConvertBSONValueToJSON(bson.MaxKey) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.MaxKey) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.MaxKey{}) + }) + }) +} + +func TestMinKeyBSONToJSON(t *testing.T) { + Convey("Converting a BSON Maxkey to JSON", t, func() { + Convey("should produce a json.MinKey", func() { + _jObj, err := ConvertBSONValueToJSON(bson.MinKey) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.MinKey) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.MinKey{}) + }) + }) +} + +func Test64BitIntBSONToJSON(t *testing.T) { + Convey("Converting a BSON int64 to JSON", t, func() { + Convey("should produce a json.NumberLong", func() { + _jObj, err := ConvertBSONValueToJSON(int32(243)) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.NumberInt) + So(ok, ShouldBeTrue) + + So(jObj, ShouldEqual, json.NumberInt(243)) + }) + }) + +} + +func Test32BitIntBSONToJSON(t *testing.T) { + Convey("Converting a BSON int32 integer to JSON", t, func() { + Convey("should produce a json.NumberInt", func() { + _jObj, err := ConvertBSONValueToJSON(int64(888234334343)) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.NumberLong) + So(ok, ShouldBeTrue) + + So(jObj, ShouldEqual, json.NumberLong(888234334343)) + }) + }) + +} + +func TestRegExBSONToJSON(t *testing.T) { + Convey("Converting a BSON Regular Expression (= /decision/gi) to JSON", t, func() { + Convey("should produce a json.RegExp", func() { + _jObj, err := ConvertBSONValueToJSON(bson.RegEx{"decision", "gi"}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.RegExp) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.RegExp{"decision", "gi"}) + }) + }) + +} + +func TestUndefinedValueBSONToJSON(t *testing.T) { + Convey("Converting a BSON Undefined type to JSON", t, func() { + Convey("should produce a json.Undefined", func() { + _jObj, err := ConvertBSONValueToJSON(bson.Undefined) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Undefined) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.Undefined{}) + }) + }) +} + +func TestDBRefBSONToJSON(t *testing.T) { + Convey("Converting BSON DBRef to JSON", t, func() { + Convey("should produce a json.DBRef", func() { + _jObj, err := ConvertBSONValueToJSON(mgo.DBRef{"coll1", "some_id", "test"}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.DBRef) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.DBRef{"coll1", "some_id", "test"}) + So(jObj, ShouldNotResemble, json.DBRef{"coll1", "test", "some_id"}) + }) + }) +} + +func TestTimestampBSONToJSON(t *testing.T) { + Convey("Converting a BSON Timestamp to JSON", t, func() { + Convey("should produce a json.Timestamp", func() { + // {t:803434343, i:9} == bson.MongoTimestamp(803434343*2**32 + 9) + _jObj, err := ConvertBSONValueToJSON(bson.MongoTimestamp(uint64(803434343<<32) | uint64(9))) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Timestamp) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.Timestamp{Seconds:803434343, Increment:9}) + So(jObj, ShouldNotResemble, json.Timestamp{Seconds:803434343, Increment:8}) + }) + }) +} + +func TestBinaryBSONToJSON(t *testing.T) { + Convey("Converting BSON Binary data to JSON", t, func() { + Convey("should produce a json.BinData", func() { + _jObj, err := ConvertBSONValueToJSON(bson.Binary{'\x01', []byte("\x05\x20\x02\xae\xf7")}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.BinData) + So(ok, ShouldBeTrue) + + base64data1 := base64.StdEncoding.EncodeToString([]byte("\x05\x20\x02\xae\xf7")) + base64data2 := base64.StdEncoding.EncodeToString([]byte("\x05\x20\x02\xaf\xf7")) + So(jObj, ShouldResemble, json.BinData{'\x01', base64data1}) + So(jObj, ShouldNotResemble, json.BinData{'\x01', base64data2}) + }) + }) +} + +func TestGenericBytesBSONToJSON(t *testing.T) { + Convey("Converting Go bytes to JSON", t, func() { + Convey("should produce a json.BinData with Type=0x00 (Generic)", func() { + _jObj, err := ConvertBSONValueToJSON([]byte("this is something that's cool")) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.BinData) + So(ok, ShouldBeTrue) + + base64data := base64.StdEncoding.EncodeToString([]byte("this is something that's cool")) + So(jObj, ShouldResemble, json.BinData{0x00, base64data}) + So(jObj, ShouldNotResemble, json.BinData{0x01, base64data}) + }) + }) +} + +func TestUnknownBSONTypeToJSON(t *testing.T) { + Convey("Converting an unknown BSON type to JSON", t, func() { + Convey("should produce an error", func() { + _, err := ConvertBSONValueToJSON(func(){}) + So(err, ShouldNotBeNil) + }) + }) +} + +func TestJSCodeBSONToJSON(t *testing.T) { + Convey("Converting BSON Javascript code to JSON", t, func() { + Convey("should produce a json.Javascript", func() { + _jObj, err := ConvertBSONValueToJSON(bson.JavaScript{"function() { return null; }", nil}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.JavaScript) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.JavaScript{"function() { return null; }", nil}) + }) + }) +} + +func TestDBPointerBSONToJSON(t *testing.T) { + Convey("Converting BSON DBPointer to JSON", t, func() { + Convey("should produce a json.DBPointer", func() { + objId := bson.NewObjectId() + _jObj, err := ConvertBSONValueToJSON(bson.DBPointer{"dbrefnamespace", objId}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.DBPointer) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.DBPointer{"dbrefnamespace", objId}) + }) + }) +} diff --git a/common/json/csv_format.go b/common/json/csv_format.go index fca3373f7f3..15be6857d5f 100644 --- a/common/json/csv_format.go +++ b/common/json/csv_format.go @@ -19,7 +19,7 @@ func (b BinData) String() string { return fmt.Sprintf("%X", data) // use uppercase hexadecimal } -func (js Javascript) String() string { +func (js JavaScript) String() string { return js.Code } @@ -39,6 +39,11 @@ func (d DBRef) String() string { d.Collection, d.Id, d.Database) } +func (d DBPointer) String() string { + return fmt.Sprintf(`{ "$ref": "%v", "$id": %v }`, + d.Namespace, d.Id) +} + func (f Float) String() string { return fmt.Sprintf("%v", float64(f)) } diff --git a/common/json/json_format.go b/common/json/json_format.go index 90f7ad75778..ebe8eb9d2d4 100644 --- a/common/json/json_format.go +++ b/common/json/json_format.go @@ -13,7 +13,7 @@ func (b BinData) MarshalJSON() ([]byte, error) { return []byte(data), nil } -func (js Javascript) MarshalJSON() ([]byte, error) { +func (js JavaScript) MarshalJSON() ([]byte, error) { return []byte(js.Code), nil } @@ -43,8 +43,9 @@ func (d DBRef) MarshalJSON() ([]byte, error) { var dbChunk []byte if d.Database != "" { - dbChunk = []byte(fmt.Sprintf(`, "$db": "%v" }`, d.Database)) + dbChunk = []byte(fmt.Sprintf(`, "$db": "%v" `, d.Database)) } + dbChunk = append(dbChunk, '}') data := make([]byte, len(refChunk)+len(idChunk)+len(dbChunk)) copy(data, refChunk) @@ -54,6 +55,17 @@ func (d DBRef) MarshalJSON() ([]byte, error) { return data, nil } +func (d DBPointer) MarshalJSON() ([]byte, error) { + // Convert the $id field to JSON + idChunk, err := Marshal(d.Id) + if err != nil { + return nil, err + } + + data := append([]byte(fmt.Sprintf(`{ "$ref": "%v", "$id": `, d.Namespace)), idChunk...) + return append(data, '}'), nil +} + func (_ MinKey) MarshalJSON() ([]byte, error) { data := `{ "$minKey": 1 }` return []byte(data), nil diff --git a/common/json/mongo_extjson.go b/common/json/mongo_extjson.go index e61a18fff66..99390e32b16 100644 --- a/common/json/mongo_extjson.go +++ b/common/json/mongo_extjson.go @@ -22,6 +22,13 @@ type DBRef struct { Database string // optional } +// Refers to a document in some namespace by wrapping a string containing the namespace +// and the objectId in which the _id of the document is contained +type DBPointer struct { + Namespace string + Id bson.ObjectId +} + // Represents the literal MinKey. type MinKey struct{} @@ -48,7 +55,7 @@ type Timestamp struct { Increment uint32 } -type Javascript struct { +type JavaScript struct { Code string Scope interface{} } diff --git a/src/github.com/mongodb/mongo-tools/common/bsonutil/converter_test.go b/src/github.com/mongodb/mongo-tools/common/bsonutil/converter_test.go new file mode 100644 index 00000000000..3f60f5bcd6f --- /dev/null +++ b/src/github.com/mongodb/mongo-tools/common/bsonutil/converter_test.go @@ -0,0 +1,268 @@ +package bsonutil + +import ( + . "github.com/smartystreets/goconvey/convey" + "github.com/mongodb/mongo-tools/common/json" + "testing" + "gopkg.in/mgo.v2" + "gopkg.in/mgo.v2/bson" + "time" + "fmt" + "encoding/base64" +) + + +func TestObjectIdBSONToJSON(t *testing.T) { + Convey("Converting a BSON ObjectId", t, func() { + Convey("that is valid to JSON should produce a json.ObjectId", func() { + bsonObjId := bson.NewObjectId() + jsonObjId := json.ObjectId(bsonObjId.Hex()) + + _jObjId, err := ConvertBSONValueToJSON(bsonObjId) + So(err, ShouldBeNil) + jObjId, ok := _jObjId.(json.ObjectId) + So(ok, ShouldBeTrue) + + So(jObjId, ShouldNotEqual, bsonObjId) + So(jObjId, ShouldEqual, jsonObjId) + }) + }) +} + +func TestArraysBSONToJSON(t *testing.T) { + Convey("Converting BSON arrays to JSON arrays", t, func() { + Convey("should work for empty arrays", func() { + jArr, err := ConvertBSONValueToJSON([]interface{}{}) + So(err, ShouldBeNil) + + So(jArr, ShouldResemble, []interface{}{}) + }) + + Convey("should work for one-level deep arrays", func() { + objId := bson.NewObjectId() + bsonArr := []interface{}{objId, 28, 0.999, "plain"} + _jArr, err := ConvertBSONValueToJSON(bsonArr) + So(err, ShouldBeNil) + jArr, ok := _jArr.([]interface{}) + So(ok, ShouldBeTrue) + + So(len(jArr), ShouldEqual, 4) + So(jArr[0], ShouldEqual, json.ObjectId(objId.Hex())) + So(jArr[1], ShouldEqual, 28) + So(jArr[2], ShouldEqual, 0.999) + So(jArr[3], ShouldEqual, "plain") + }) + + Convey("should work for arrays with embedded objects", func() { + bsonObj := []interface{}{80, bson.M{"a":int64(20), "b":bson.M{"c": bson.RegEx{"hi", "i"}}}} + + __jObj, err := ConvertBSONValueToJSON(bsonObj) + So(err, ShouldBeNil) + _jObj, ok := __jObj.([]interface{}) + So(ok, ShouldBeTrue) + jObj, ok := _jObj[1].(map[string]interface{}) + So(ok, ShouldBeTrue) + So(len(jObj), ShouldEqual, 2) + So(jObj["a"], ShouldEqual, json.NumberLong(20)) + jjObj, ok := jObj["b"].(map[string]interface{}) + So(ok, ShouldBeTrue) + + So(jjObj["c"], ShouldResemble, json.RegExp{"hi", "i"}) + So(jjObj["c"], ShouldNotResemble, json.RegExp{"i", "hi"}) + }) + + }) +} + +func TestDateBSONToJSON(t *testing.T) { + + timeNow := time.Now() + secs := int64(timeNow.Unix()) + nanosecs := timeNow.Nanosecond() + millis := int64(nanosecs/1e6) + + timeNowSecs := time.Unix(secs, int64(0)) + timeNowMillis := time.Unix(secs, int64(millis*1e6)) + + Convey("Converting BSON time.Time 's dates to JSON", t, func() { + // json.Date is stored as an int64 representing the number of milliseconds since the epoch + Convey(fmt.Sprintf("should work with second granularity: %v", timeNowSecs), func() { + _jObj, err := ConvertBSONValueToJSON(timeNowSecs) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Date) + So(ok, ShouldBeTrue) + + So(int64(jObj), ShouldEqual, secs*1e3) + }) + + Convey(fmt.Sprintf("should work with millisecond granularity: %v", timeNowMillis), func() { + _jObj, err := ConvertBSONValueToJSON(timeNowMillis) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Date) + So(ok, ShouldBeTrue) + + So(int64(jObj), ShouldEqual, secs*1e3 + millis) + }) + + Convey(fmt.Sprintf("should work with nanosecond granularity: %v", timeNow), func() { + _jObj, err := ConvertBSONValueToJSON(timeNow) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Date) + So(ok, ShouldBeTrue) + + // we lose nanosecond precision + So(int64(jObj), ShouldEqual, secs*1e3 + millis) + }) + + }) +} + +func TestMaxKeyBSONToJSON(t *testing.T) { + Convey("Converting a BSON Maxkey to JSON", t, func() { + Convey("should produce a json.MaxKey", func() { + _jObj, err := ConvertBSONValueToJSON(bson.MaxKey) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.MaxKey) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.MaxKey{}) + }) + }) +} + +func TestMinKeyBSONToJSON(t *testing.T) { + Convey("Converting a BSON Maxkey to JSON", t, func() { + Convey("should produce a json.MinKey", func() { + _jObj, err := ConvertBSONValueToJSON(bson.MinKey) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.MinKey) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.MinKey{}) + }) + }) +} + +func Test64BitIntBSONToJSON(t *testing.T) { + Convey("Converting a BSON int64 to JSON", t, func() { + Convey("should produce a json.NumberLong", func() { + _jObj, err := ConvertBSONValueToJSON(int32(243)) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.NumberInt) + So(ok, ShouldBeTrue) + + So(jObj, ShouldEqual, json.NumberInt(243)) + }) + }) + +} + +func Test32BitIntBSONToJSON(t *testing.T) { + Convey("Converting a BSON int32 integer to JSON", t, func() { + Convey("should produce a json.NumberInt", func() { + _jObj, err := ConvertBSONValueToJSON(int64(888234334343)) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.NumberLong) + So(ok, ShouldBeTrue) + + So(jObj, ShouldEqual, json.NumberLong(888234334343)) + }) + }) + +} + +func TestRegExBSONToJSON(t *testing.T) { + Convey("Converting a BSON Regular Expression (= /decision/gi) to JSON", t, func() { + Convey("should produce a json.RegExp", func() { + _jObj, err := ConvertBSONValueToJSON(bson.RegEx{"decision", "gi"}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.RegExp) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.RegExp{"decision", "gi"}) + }) + }) + +} + +func TestUndefinedValueBSONToJSON(t *testing.T) { + Convey("Converting a BSON Undefined type to JSON", t, func() { + Convey("should produce a json.Undefined", func() { + _jObj, err := ConvertBSONValueToJSON(bson.Undefined) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Undefined) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.Undefined{}) + }) + }) +} + +func TestDBRefBSONToJSON(t *testing.T) { + Convey("Converting BSON DBRef to JSON", t, func() { + Convey("should produce a json.DBRef", func() { + _jObj, err := ConvertBSONValueToJSON(mgo.DBRef{"coll1", "some_id", "test"}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.DBRef) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.DBRef{"coll1", "some_id", "test"}) + So(jObj, ShouldNotResemble, json.DBRef{"coll1", "test", "some_id"}) + }) + }) +} + +func TestTimestampBSONToJSON(t *testing.T) { + Convey("Converting a BSON Timestamp to JSON", t, func() { + Convey("should produce a json.Timestamp", func() { + // {t:803434343, i:9} == bson.MongoTimestamp(803434343*2**32 + 9) + _jObj, err := ConvertBSONValueToJSON(bson.MongoTimestamp(uint64(803434343<<32) | uint64(9))) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.Timestamp) + So(ok, ShouldBeTrue) + + So(jObj, ShouldResemble, json.Timestamp{Seconds:803434343, Increment:9}) + So(jObj, ShouldNotResemble, json.Timestamp{Seconds:803434343, Increment:8}) + }) + }) +} + +func TestBinaryBSONToJSON(t *testing.T) { + Convey("Converting BSON Binary data to JSON", t, func() { + Convey("should produce a json.BinData", func() { + _jObj, err := ConvertBSONValueToJSON(bson.Binary{'\x01', []byte("\x05\x20\x02\xae\xf7")}) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.BinData) + So(ok, ShouldBeTrue) + + base64data1 := base64.StdEncoding.EncodeToString([]byte("\x05\x20\x02\xae\xf7")) + base64data2 := base64.StdEncoding.EncodeToString([]byte("\x05\x20\x02\xaf\xf7")) + So(jObj, ShouldResemble, json.BinData{'\x01', base64data1}) + So(jObj, ShouldNotResemble, json.BinData{'\x01', base64data2}) + }) + }) +} + +func TestGenericBytesBSONToJSON(t *testing.T) { + Convey("Converting Go bytes to JSON", t, func() { + Convey("should produce a json.BinData with Type=0x00 (Generic)", func() { + _jObj, err := ConvertBSONValueToJSON([]byte("this is something that's cool")) + So(err, ShouldBeNil) + jObj, ok := _jObj.(json.BinData) + So(ok, ShouldBeTrue) + + base64data := base64.StdEncoding.EncodeToString([]byte("this is something that's cool")) + So(jObj, ShouldResemble, json.BinData{0x00, base64data}) + So(jObj, ShouldNotResemble, json.BinData{0x01, base64data}) + }) + }) +} + +func TestUnknownBSONTypeToJSON(t *testing.T) { + Convey("Converting an unknown BSON type to JSON", t, func() { + Convey("should produce an error", func() { + _, err := ConvertBSONValueToJSON(func(){}) + So(err, ShouldNotBeNil) + }) + }) +} |