Skip to content
This repository was archived by the owner on Feb 3, 2022. It is now read-only.

Commit 0902753

Browse files
committed
Double precision EJSON fix and Spec update
1 parent 148193b commit 0902753

34 files changed

+72
-2850
lines changed

etc/update-spec-tests.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env bash
2+
3+
# This script is used to fetch the latest JSON tests for the BSON spec.
4+
# It puts the tests in the direcory $spec_root It should be run from the root of the repository.
5+
6+
set -o errexit
7+
set -o nounset
8+
9+
if [ ! -d ".git" ]; then
10+
echo "$0: This script must be run from the root of the repository" >&2
11+
exit 1
12+
fi
13+
14+
spec_root="test"
15+
16+
tmpdir=$(mktemp -d -t spec_testsXXXX)
17+
curl -sL https://github.com/mongodb/specifications/archive/master.zip -o "$tmpdir/specs.zip"
18+
unzip -d "$tmpdir" "$tmpdir/specs.zip" > /dev/null
19+
20+
mkdir -p "$spec_root/bson-corpus"
21+
rsync -ah "$tmpdir/specifications-master/source/bson-corpus/tests/" "$spec_root/bson-corpus" --delete
22+
23+
rm -rf "$tmpdir"

lib/bson/double.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
11
'use strict';
22

33
function toExtendedJSON(obj, options) {
4-
if (options && options.relaxed && isFinite(obj.value)) return obj.value;
5-
return { $numberDouble: obj.value.toString() };
4+
if (options && (options.legacy || (options.relaxed && isFinite(obj.value)))) {
5+
return obj.value;
6+
}
7+
// NOTE: JavaScript has +0 and -0, apparently to model limit calculations. If a user
8+
// explicitly provided `-0` then we need to ensure the sign makes it into the output
9+
if (Object.is(Math.sign(obj.value), -0)) {
10+
return { $numberDouble: `-${obj.value.toFixed(1)}` };
11+
}
12+
13+
var numberDouble;
14+
if (Number.isInteger(obj.value)) {
15+
numberDouble = obj.value.toFixed(1);
16+
if (numberDouble.length >= 13) {
17+
numberDouble = obj.value.toExponential(13).toUpperCase();
18+
}
19+
} else {
20+
numberDouble = obj.value.toString();
21+
}
22+
23+
return { $numberDouble: numberDouble };
624
}
725

826
function fromExtendedJSON(BSON, doc, options) {

test/bson-corpus/array.json

100755100644
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,22 @@
1414
"canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}"
1515
},
1616
{
17-
"description": "Single Element Array with index set incorrectly",
17+
"description": "Single Element Array with index set incorrectly to empty string",
1818
"degenerate_bson": "130000000461000B00000010000A0000000000",
1919
"canonical_bson": "140000000461000C0000001030000A0000000000",
2020
"canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}"
2121
},
2222
{
23-
"description": "Single Element Array with index set incorrectly",
23+
"description": "Single Element Array with index set incorrectly to ab",
2424
"degenerate_bson": "150000000461000D000000106162000A0000000000",
2525
"canonical_bson": "140000000461000C0000001030000A0000000000",
2626
"canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}"
27+
},
28+
{
29+
"description": "Multi Element Array with duplicate indexes",
30+
"degenerate_bson": "1b000000046100130000001030000a000000103000140000000000",
31+
"canonical_bson": "1b000000046100130000001030000a000000103100140000000000",
32+
"canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}, {\"$numberInt\": \"20\"}]}"
2733
}
2834
],
2935
"decodeErrors": [

test/bson-corpus/binary.json

100755100644
File mode changed.

test/bson-corpus/boolean.json

100755100644
File mode changed.

test/bson-corpus/code.json

100755100644
File mode changed.

test/bson-corpus/code_w_scope.json

100755100644
File mode changed.

test/bson-corpus/datetime.json

100755100644
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
"description" : "Y10K",
2626
"canonical_bson" : "1000000009610000DC1FD277E6000000",
2727
"canonical_extjson" : "{\"a\":{\"$date\":{\"$numberLong\":\"253402300800000\"}}}"
28+
},
29+
{
30+
"description": "leading zero ms",
31+
"canonical_bson": "10000000096100D1D6D6CC3B01000000",
32+
"relaxed_extjson": "{\"a\" : {\"$date\" : \"2012-12-24T12:15:30.001Z\"}}",
33+
"canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"1356351330001\"}}}"
2834
}
2935
],
3036
"decodeErrors": [

test/bson-corpus/dbpointer.json

100755100644
File mode changed.

test/bson-corpus/dbref.json

100755100644
File mode changed.

test/bson-corpus/decimal128-1.json

100755100644
File mode changed.

test/bson-corpus/decimal128-2.json

100755100644
File mode changed.

test/bson-corpus/decimal128-3.json

100755100644
File mode changed.

test/bson-corpus/decimal128-4.json

100755100644
File mode changed.

test/bson-corpus/decimal128-5.json

100755100644
File mode changed.

test/bson-corpus/decimal128-6.json

100755100644
File mode changed.

test/bson-corpus/decimal128-7.json

100755100644
File mode changed.

test/bson-corpus/document.json

100755100644
File mode changed.

test/bson-corpus/double.json

100755100644
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@
2828
"relaxed_extjson": "{\"d\" : -1.0001220703125}"
2929
},
3030
{
31-
"description": "1.23456789012345677E+18",
32-
"canonical_bson": "1000000001640081E97DF41022B14300",
33-
"canonical_extjson": "{\"d\" : {\"$numberDouble\": \"1.23456789012345677E+18\"}}",
34-
"relaxed_extjson": "{\"d\" : 1.23456789012345677E+18}"
31+
"description": "1.2345678921232E+18",
32+
"canonical_bson": "100000000164002a1bf5f41022b14300",
33+
"canonical_extjson": "{\"d\" : {\"$numberDouble\": \"1.2345678921232E+18\"}}",
34+
"relaxed_extjson": "{\"d\" : 1.2345678921232E+18}"
3535
},
3636
{
37-
"description": "-1.23456789012345677E+18",
38-
"canonical_bson": "1000000001640081E97DF41022B1C300",
39-
"canonical_extjson": "{\"d\" : {\"$numberDouble\": \"-1.23456789012345677E+18\"}}",
40-
"relaxed_extjson": "{\"d\" : -1.23456789012345677E+18}"
37+
"description": "-1.2345678921232E+18",
38+
"canonical_bson": "100000000164002a1bf5f41022b1c300",
39+
"canonical_extjson": "{\"d\" : {\"$numberDouble\": \"-1.2345678921232E+18\"}}",
40+
"relaxed_extjson": "{\"d\" : -1.2345678921232E+18}"
4141
},
4242
{
4343
"description": "0.0",

test/bson-corpus/int32.json

100755100644
File mode changed.

test/bson-corpus/int64.json

100755100644
File mode changed.

test/bson-corpus/maxkey.json

100755100644
File mode changed.

test/bson-corpus/minkey.json

100755100644
File mode changed.

test/bson-corpus/multi-type-deprecated.json

100755100644
File mode changed.

test/bson-corpus/multi-type.json

100755100644
File mode changed.

test/bson-corpus/null.json

100755100644
File mode changed.

test/bson-corpus/oid.json

100755100644
File mode changed.

test/bson-corpus/regex.json

100755100644
File mode changed.

test/bson-corpus/string.json

100755100644
File mode changed.

test/bson-corpus/symbol.json

100755100644
File mode changed.

test/bson-corpus/top.json

100755100644
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@
6969
"parseErrors": [
7070
{
7171
"description" : "Bad $regularExpression (extra field)",
72-
"string" : "{\"a\" : \"$regularExpression\": {\"pattern\": \"abc\", \"options\": \"\", \"unrelated\": true}}}"
72+
"string" : "{\"a\" : {\"$regularExpression\": {\"pattern\": \"abc\", \"options\": \"\", \"unrelated\": true}}}"
7373
},
7474
{
7575
"description" : "Bad $regularExpression (missing options field)",
76-
"string" : "{\"a\" : \"$regularExpression\": {\"pattern\": \"abc\"}}}"
76+
"string" : "{\"a\" : {\"$regularExpression\": {\"pattern\": \"abc\"}}}"
7777
},
7878
{
7979
"description": "Bad $regularExpression (pattern is number, not string)",
@@ -85,7 +85,7 @@
8585
},
8686
{
8787
"description" : "Bad $regularExpression (missing pattern field)",
88-
"string" : "{\"a\" : \"$regularExpression\": {\"options\":\"ix\"}}}"
88+
"string" : "{\"a\" : {\"$regularExpression\": {\"options\":\"ix\"}}}"
8989
},
9090
{
9191
"description": "Bad $oid (number, not string)",
@@ -151,6 +151,10 @@
151151
"description": "Bad $code (type is number, not string)",
152152
"string": "{\"a\" : {\"$code\" : 42}}"
153153
},
154+
{
155+
"description": "Bad $code (type is number, not string) when $scope is also present",
156+
"string": "{\"a\" : {\"$code\" : 42, \"$scope\" : {}}}"
157+
},
154158
{
155159
"description": "Bad $code (extra field)",
156160
"string": "{\"a\" : {\"$code\" : \"\", \"unrelated\": true}}"

test/bson-corpus/undefined.json

100755100644
File mode changed.

test/bson_corpus_tests.js

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -54,56 +54,13 @@ var skip = {
5454
'Current BSON implementation of timestamp/long cannot hold these values - 1 too large.'
5555
};
5656

57-
var modifiedDoubles = {
58-
'+1.0': { canonical_extjson: '{"d":{"$numberDouble":"1"}}' },
59-
'-1.0': { canonical_extjson: '{"d":{"$numberDouble":"-1"}}' },
60-
'1.23456789012345677E+18': { canonical_extjson: '{"d":{"$numberDouble":"1234567890123456800"}}' },
61-
'-1.23456789012345677E+18': {
62-
canonical_extjson: '{"d":{"$numberDouble":"-1234567890123456800"}}'
63-
},
64-
'0.0': { canonical_extjson: '{"d":{"$numberDouble":"0"}}' },
65-
'-0.0': {
66-
canonical_extjson: '{"d":{"$numberDouble":"0"}}',
67-
canonical_bson: '10000000016400000000000000000000'
68-
}
69-
};
70-
71-
var modifiedMultitype = {
72-
'All BSON types': {
73-
canonical_extjson:
74-
'{"_id":{"$oid":"57e193d7a9cc81b4027498b5"},"Symbol":"symbol","String":"string","Int32":{"$numberInt":"42"},"Int64":{"$numberLong":"42"},"Double":{"$numberDouble":"-1"},"Binary":{"$binary":{"base64":"o0w498Or7cijeBSpkquNtg==","subType":"03"}},"BinaryUserDefined":{"$binary":{"base64":"AQIDBAU=","subType":"80"}},"Code":{"$code":"function() {}"},"CodeWithScope":{"$code":"function() {}","$scope":{}},"Subdocument":{"foo":"bar"},"Array":[{"$numberInt":"1"},{"$numberInt":"2"},{"$numberInt":"3"},{"$numberInt":"4"},{"$numberInt":"5"}],"Timestamp":{"$timestamp":{"t":42,"i":1}},"Regex":{"$regularExpression":{"pattern":"pattern","options":""}},"DatetimeEpoch":{"$date":{"$numberLong":"0"}},"DatetimePositive":{"$date":{"$numberLong":"2147483647"}},"DatetimeNegative":{"$date":{"$numberLong":"-2147483648"}},"True":true,"False":false,"DBPointer":{"$ref":"collection","$id":{"$oid":"57e193d7a9cc81b4027498b1"}},"DBRef":{"$ref":"collection","$id":{"$oid":"57fd71e96e32ab4225b723fb"},"$db":"database"},"Minkey":{"$minKey":1},"Maxkey":{"$maxKey":1},"Null":null,"Undefined":null}',
75-
canonical_bson:
76-
'48020000075f69640057e193d7a9cc81b4027498b50253796d626f6c000700000073796d626f6c0002537472696e670007000000737472696e670010496e743332002a00000012496e743634002a0000000000000001446f75626c6500000000000000f0bf0542696e617279001000000003a34c38f7c3abedc8a37814a992ab8db60542696e61727955736572446566696e656400050000008001020304050d436f6465000e00000066756e6374696f6e2829207b7d000f436f64655769746853636f7065001b0000000e00000066756e6374696f6e2829207b7d00050000000003537562646f63756d656e74001200000002666f6f0004000000626172000004417272617900280000001030000100000010310002000000103200030000001033000400000010340005000000001154696d657374616d7000010000002a0000000b5265676578007061747465726e0000094461746574696d6545706f6368000000000000000000094461746574696d65506f73697469766500ffffff7f00000000094461746574696d654e656761746976650000000080ffffffff085472756500010846616c73650000034442506f696e746572002b0000000224726566000b000000636f6c6c656374696f6e00072469640057e193d7a9cc81b4027498b100034442526566003d0000000224726566000b000000636f6c6c656374696f6e00072469640057fd71e96e32ab4225b723fb02246462000900000064617461626173650000ff4d696e6b6579007f4d61786b6579000a4e756c6c000a556e646566696e65640000',
77-
converted_extjson:
78-
'{"_id":{"$oid":"57e193d7a9cc81b4027498b5"},"Symbol":"symbol","String":"string","Int32":{"$numberInt":"42"},"Int64":{"$numberLong":"42"},"Double":{"$numberDouble":"-1"},"Binary":{"$binary":{"base64":"o0w498Or7cijeBSpkquNtg==","subType":"03"}},"BinaryUserDefined":{"$binary":{"base64":"AQIDBAU=","subType":"80"}},"Code":{"$code":"function() {}"},"CodeWithScope":{"$code":"function() {}","$scope":{}},"Subdocument":{"foo":"bar"},"Array":[{"$numberInt":"1"},{"$numberInt":"2"},{"$numberInt":"3"},{"$numberInt":"4"},{"$numberInt":"5"}],"Timestamp":{"$timestamp":{"t":42,"i":1}},"Regex":{"$regularExpression":{"pattern":"pattern","options":""}},"DatetimeEpoch":{"$date":{"$numberLong":"0"}},"DatetimePositive":{"$date":{"$numberLong":"2147483647"}},"DatetimeNegative":{"$date":{"$numberLong":"-2147483648"}},"True":true,"False":false,"DBPointer":{"$ref":"collection","$id":{"$oid":"57e193d7a9cc81b4027498b1"}},"DBRef":{"$ref":"collection","$id":{"$oid":"57fd71e96e32ab4225b723fb"},"$db":"database"},"Minkey":{"$minKey":1},"Maxkey":{"$maxKey":1},"Null":null,"Undefined":null}',
79-
converted_bson:
80-
'48020000075f69640057e193d7a9cc81b4027498b50253796d626f6c000700000073796d626f6c0002537472696e670007000000737472696e670010496e743332002a00000012496e743634002a0000000000000001446f75626c6500000000000000f0bf0542696e617279001000000003a34c38f7c3abedc8a37814a992ab8db60542696e61727955736572446566696e656400050000008001020304050d436f6465000e00000066756e6374696f6e2829207b7d000f436f64655769746853636f7065001b0000000e00000066756e6374696f6e2829207b7d00050000000003537562646f63756d656e74001200000002666f6f0004000000626172000004417272617900280000001030000100000010310002000000103200030000001033000400000010340005000000001154696d657374616d7000010000002a0000000b5265676578007061747465726e0000094461746574696d6545706f6368000000000000000000094461746574696d65506f73697469766500ffffff7f00000000094461746574696d654e656761746976650000000080ffffffff085472756500010846616c73650000034442506f696e746572002b0000000224726566000b000000636f6c6c656374696f6e00072469640057e193d7a9cc81b4027498b100034442526566003d0000000224726566000b000000636f6c6c656374696f6e00072469640057fd71e96e32ab4225b723fb02246462000900000064617461626173650000ff4d696e6b6579007f4d61786b6579000a4e756c6c000a556e646566696e65640000'
81-
}
82-
};
83-
8457
describe('BSON Corpus Tests:', function() {
8558
findScenarios().forEach(scenario => {
8659
var scenarioData = scenario[1],
8760
deprecated = scenarioData.deprecated,
8861
description = scenarioData.description,
8962
valid = scenarioData.valid || [];
9063

91-
// since doubles are formatted differently in JS than in corpus, overwrite expected results
92-
if (description === 'Double type') {
93-
valid.forEach(v => {
94-
if (modifiedDoubles[v.description]) {
95-
Object.assign(v, modifiedDoubles[v.description]);
96-
}
97-
});
98-
// multitype test has a double nested in object, so change those expected values too
99-
} else if (description === 'Multiple types within the same document') {
100-
valid.forEach(v => {
101-
if (modifiedMultitype[v.description]) {
102-
Object.assign(v, modifiedMultitype[v.description]);
103-
}
104-
});
105-
}
106-
10764
valid.forEach(v => {
10865
// tests we need to skip for various reasons
10966
if (skip.hasOwnProperty(v.description)) {

0 commit comments

Comments
 (0)