bson 4.1.1 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +106 -7
- data/Rakefile +86 -43
- data/ext/bson/{native-endian.h → bson-endian.h} +14 -107
- data/ext/bson/bson-native.h +135 -0
- data/ext/bson/bytebuf.c +133 -0
- data/ext/bson/endian.c +117 -0
- data/ext/bson/extconf.rb +8 -3
- data/ext/bson/init.c +364 -0
- data/ext/bson/libbson-utf8.c +230 -0
- data/ext/bson/read.c +470 -0
- data/ext/bson/util.c +250 -0
- data/ext/bson/write.c +675 -0
- data/lib/bson/active_support.rb +19 -0
- data/lib/bson/array.rb +97 -30
- data/lib/bson/big_decimal.rb +77 -0
- data/lib/bson/binary.rb +510 -70
- data/lib/bson/boolean.rb +15 -4
- data/lib/bson/code.rb +25 -12
- data/lib/bson/code_with_scope.rb +41 -15
- data/lib/bson/config.rb +3 -28
- data/lib/bson/date.rb +16 -4
- data/lib/bson/date_time.rb +6 -4
- data/lib/bson/db_pointer.rb +110 -0
- data/lib/bson/dbref.rb +154 -0
- data/lib/bson/decimal128/builder.rb +456 -0
- data/lib/bson/decimal128.rb +272 -0
- data/lib/bson/document.rb +177 -7
- data/lib/bson/environment.rb +17 -2
- data/lib/bson/error/bson_decode_error.rb +11 -0
- data/lib/bson/error/ext_json_parse_error.rb +11 -0
- data/lib/bson/error/illegal_key.rb +23 -0
- data/lib/bson/error/invalid_binary_type.rb +37 -0
- data/lib/bson/error/invalid_dbref_argument.rb +12 -0
- data/lib/bson/error/invalid_decimal128_argument.rb +25 -0
- data/lib/bson/error/invalid_decimal128_range.rb +27 -0
- data/lib/bson/error/invalid_decimal128_string.rb +26 -0
- data/lib/bson/error/invalid_key.rb +24 -0
- data/lib/bson/error/invalid_object_id.rb +11 -0
- data/lib/bson/error/invalid_regexp_pattern.rb +13 -0
- data/lib/bson/error/unrepresentable_precision.rb +19 -0
- data/lib/bson/error/unserializable_class.rb +13 -0
- data/lib/bson/error/unsupported_binary_subtype.rb +12 -0
- data/lib/bson/error/unsupported_type.rb +11 -0
- data/lib/bson/error.rb +22 -0
- data/lib/bson/ext_json.rb +389 -0
- data/lib/bson/false_class.rb +6 -4
- data/lib/bson/float.rb +43 -7
- data/lib/bson/hash.rb +152 -37
- data/lib/bson/int32.rb +104 -6
- data/lib/bson/int64.rb +111 -8
- data/lib/bson/integer.rb +43 -9
- data/lib/bson/json.rb +3 -1
- data/lib/bson/max_key.rb +21 -10
- data/lib/bson/min_key.rb +21 -10
- data/lib/bson/nil_class.rb +7 -3
- data/lib/bson/object.rb +25 -17
- data/lib/bson/object_id.rb +98 -113
- data/lib/bson/open_struct.rb +59 -0
- data/lib/bson/regexp.rb +129 -56
- data/lib/bson/registry.rb +7 -10
- data/lib/bson/specialized.rb +8 -4
- data/lib/bson/string.rb +12 -32
- data/lib/bson/symbol.rb +107 -11
- data/lib/bson/time.rb +68 -7
- data/lib/bson/time_with_zone.rb +67 -0
- data/lib/bson/timestamp.rb +50 -10
- data/lib/bson/true_class.rb +6 -4
- data/lib/bson/undefined.rb +28 -2
- data/lib/bson/vector.rb +44 -0
- data/lib/bson/version.rb +6 -14
- data/lib/bson.rb +22 -12
- data/spec/README.md +14 -0
- data/spec/bson/array_spec.rb +38 -62
- data/spec/bson/big_decimal_spec.rb +328 -0
- data/spec/bson/binary_spec.rb +199 -53
- data/spec/bson/binary_uuid_spec.rb +190 -0
- data/spec/bson/boolean_spec.rb +2 -1
- data/spec/bson/byte_buffer_read_spec.rb +198 -0
- data/spec/bson/byte_buffer_spec.rb +122 -381
- data/spec/bson/byte_buffer_write_spec.rb +855 -0
- data/spec/bson/code_spec.rb +6 -4
- data/spec/bson/code_with_scope_spec.rb +6 -4
- data/spec/bson/config_spec.rb +1 -35
- data/spec/bson/date_spec.rb +2 -1
- data/spec/bson/date_time_spec.rb +55 -1
- data/spec/bson/dbref_legacy_spec.rb +186 -0
- data/spec/bson/dbref_spec.rb +487 -0
- data/spec/bson/decimal128_spec.rb +1840 -0
- data/spec/bson/document_as_spec.rb +61 -0
- data/spec/bson/document_spec.rb +205 -32
- data/spec/bson/ext_json_parse_spec.rb +346 -0
- data/spec/bson/false_class_spec.rb +9 -1
- data/spec/bson/float_spec.rb +42 -1
- data/spec/bson/hash_as_spec.rb +58 -0
- data/spec/bson/hash_spec.rb +318 -66
- data/spec/bson/int32_spec.rb +248 -1
- data/spec/bson/int64_spec.rb +308 -1
- data/spec/bson/integer_spec.rb +61 -3
- data/spec/bson/json_spec.rb +2 -1
- data/spec/bson/max_key_spec.rb +6 -4
- data/spec/bson/min_key_spec.rb +6 -4
- data/spec/bson/nil_class_spec.rb +2 -1
- data/spec/bson/object_id_spec.rb +95 -5
- data/spec/bson/object_spec.rb +3 -2
- data/spec/bson/open_struct_spec.rb +87 -0
- data/spec/bson/raw_spec.rb +594 -0
- data/spec/bson/regexp_spec.rb +61 -8
- data/spec/bson/registry_spec.rb +3 -2
- data/spec/bson/string_spec.rb +26 -33
- data/spec/bson/symbol_raw_spec.rb +70 -0
- data/spec/bson/symbol_spec.rb +77 -20
- data/spec/bson/time_spec.rb +206 -2
- data/spec/bson/time_with_zone_spec.rb +69 -0
- data/spec/bson/timestamp_spec.rb +58 -2
- data/spec/bson/true_class_spec.rb +9 -1
- data/spec/bson/undefined_spec.rb +28 -1
- data/spec/bson/vector_spec.rb +33 -0
- data/spec/bson_spec.rb +2 -1
- data/spec/runners/binary_vector.rb +78 -0
- data/spec/runners/common_driver.rb +348 -0
- data/spec/runners/corpus.rb +191 -0
- data/spec/runners/corpus_legacy.rb +248 -0
- data/spec/shared/LICENSE +20 -0
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
- data/spec/shared/lib/mrss/cluster_config.rb +231 -0
- data/spec/shared/lib/mrss/constraints.rb +378 -0
- data/spec/shared/lib/mrss/docker_runner.rb +298 -0
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
- data/spec/shared/lib/mrss/release/candidate.rb +281 -0
- data/spec/shared/lib/mrss/release/product_data.rb +144 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
- data/spec/shared/lib/mrss/session_registry.rb +69 -0
- data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
- data/spec/shared/lib/mrss/utils.rb +37 -0
- data/spec/shared/lib/tasks/candidate.rake +64 -0
- data/spec/shared/share/Dockerfile.erb +251 -0
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/config.sh +27 -0
- data/spec/shared/shlib/distro.sh +84 -0
- data/spec/shared/shlib/server.sh +423 -0
- data/spec/shared/shlib/set_env.sh +110 -0
- data/spec/spec_helper.rb +61 -1
- data/spec/spec_tests/binary_vector_spec.rb +82 -0
- data/spec/spec_tests/common_driver_spec.rb +84 -0
- data/spec/spec_tests/corpus_legacy_spec.rb +72 -0
- data/spec/spec_tests/corpus_spec.rb +134 -0
- data/spec/spec_tests/data/binary_vector/README.md +61 -0
- data/spec/spec_tests/data/binary_vector/float32.json +65 -0
- data/spec/spec_tests/data/binary_vector/int8.json +57 -0
- data/spec/spec_tests/data/binary_vector/packed_bit.json +83 -0
- data/spec/spec_tests/data/corpus/README.md +15 -0
- data/spec/spec_tests/data/corpus/array.json +49 -0
- data/spec/spec_tests/data/corpus/binary.json +153 -0
- data/spec/spec_tests/data/corpus/boolean.json +27 -0
- data/spec/spec_tests/data/corpus/code.json +67 -0
- data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
- data/spec/spec_tests/data/corpus/datetime.json +42 -0
- data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
- data/spec/spec_tests/data/corpus/dbref.json +51 -0
- data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
- data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
- data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
- data/spec/spec_tests/data/corpus/decimal128-4.json +165 -0
- data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
- data/spec/spec_tests/data/corpus/decimal128-6.json +131 -0
- data/spec/spec_tests/data/corpus/decimal128-7.json +327 -0
- data/spec/spec_tests/data/corpus/document.json +60 -0
- data/spec/spec_tests/data/corpus/double.json +87 -0
- data/spec/spec_tests/data/corpus/int32.json +43 -0
- data/spec/spec_tests/data/corpus/int64.json +43 -0
- data/spec/spec_tests/data/corpus/maxkey.json +12 -0
- data/spec/spec_tests/data/corpus/minkey.json +12 -0
- data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
- data/spec/spec_tests/data/corpus/multi-type.json +11 -0
- data/spec/spec_tests/data/corpus/null.json +12 -0
- data/spec/spec_tests/data/corpus/oid.json +28 -0
- data/spec/spec_tests/data/corpus/regex.json +65 -0
- data/spec/spec_tests/data/corpus/string.json +72 -0
- data/spec/spec_tests/data/corpus/symbol.json +80 -0
- data/spec/spec_tests/data/corpus/timestamp.json +34 -0
- data/spec/spec_tests/data/corpus/top.json +262 -0
- data/spec/spec_tests/data/corpus/undefined.json +15 -0
- data/spec/spec_tests/data/corpus_legacy/array.json +49 -0
- data/spec/spec_tests/data/corpus_legacy/binary.json +69 -0
- data/spec/spec_tests/data/corpus_legacy/boolean.json +27 -0
- data/spec/spec_tests/data/corpus_legacy/code.json +67 -0
- data/spec/spec_tests/data/corpus_legacy/code_w_scope.json +78 -0
- data/spec/spec_tests/data/corpus_legacy/document.json +36 -0
- data/spec/spec_tests/data/corpus_legacy/double.json +69 -0
- data/spec/spec_tests/data/corpus_legacy/failures/datetime.json +31 -0
- data/spec/spec_tests/data/corpus_legacy/failures/dbpointer.json +42 -0
- data/spec/spec_tests/data/corpus_legacy/failures/int64.json +38 -0
- data/spec/spec_tests/data/corpus_legacy/failures/symbol.json +62 -0
- data/spec/spec_tests/data/corpus_legacy/int32.json +38 -0
- data/spec/spec_tests/data/corpus_legacy/maxkey.json +12 -0
- data/spec/spec_tests/data/corpus_legacy/minkey.json +12 -0
- data/spec/spec_tests/data/corpus_legacy/null.json +12 -0
- data/spec/spec_tests/data/corpus_legacy/oid.json +28 -0
- data/spec/spec_tests/data/corpus_legacy/regex.json +37 -0
- data/spec/spec_tests/data/corpus_legacy/string.json +67 -0
- data/spec/spec_tests/data/corpus_legacy/timestamp.json +18 -0
- data/spec/spec_tests/data/corpus_legacy/top.json +62 -0
- data/spec/spec_tests/data/corpus_legacy/undefined.json +13 -0
- data/spec/spec_tests/data/decimal128/decimal128-1.json +363 -0
- data/spec/spec_tests/data/decimal128/decimal128-2.json +793 -0
- data/spec/spec_tests/data/decimal128/decimal128-3.json +1771 -0
- data/spec/spec_tests/data/decimal128/decimal128-4.json +165 -0
- data/spec/spec_tests/data/decimal128/decimal128-5.json +402 -0
- data/spec/spec_tests/data/decimal128/decimal128-6.json +131 -0
- data/spec/spec_tests/data/decimal128/decimal128-7.json +327 -0
- data/spec/support/shared_examples.rb +32 -11
- data/spec/support/spec_config.rb +17 -0
- data/spec/support/utils.rb +58 -0
- metadata +284 -45
- checksums.yaml.gz.sig +0 -3
- data/ext/bson/native.c +0 -722
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# rubocop:todo all
|
|
2
|
+
# Copyright (C) 2009-2020 MongoDB Inc.
|
|
2
3
|
#
|
|
3
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
5
|
# you may not use this file except in compliance with the License.
|
|
@@ -25,4 +26,11 @@ describe FalseClass do
|
|
|
25
26
|
it_behaves_like "a bson element"
|
|
26
27
|
it_behaves_like "a serializable bson element"
|
|
27
28
|
end
|
|
29
|
+
|
|
30
|
+
describe '#as_extended_json' do
|
|
31
|
+
let(:object) { false }
|
|
32
|
+
|
|
33
|
+
it_behaves_like '#as_extended_json returns self'
|
|
34
|
+
it_behaves_like 'an Extended JSON serializable object'
|
|
35
|
+
end
|
|
28
36
|
end
|
data/spec/bson/float_spec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# rubocop:todo all
|
|
2
|
+
# Copyright (C) 2009-2020 MongoDB Inc.
|
|
2
3
|
#
|
|
3
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
5
|
# you may not use this file except in compliance with the License.
|
|
@@ -26,4 +27,44 @@ describe Float do
|
|
|
26
27
|
it_behaves_like "a serializable bson element"
|
|
27
28
|
it_behaves_like "a deserializable bson element"
|
|
28
29
|
end
|
|
30
|
+
|
|
31
|
+
describe '#to_json' do
|
|
32
|
+
it 'returns float' do
|
|
33
|
+
42.0.to_json.should == '42.0'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe '#as_extended_json' do
|
|
38
|
+
let(:object) { 42.0 }
|
|
39
|
+
|
|
40
|
+
context 'canonical mode' do
|
|
41
|
+
it 'returns $numberDouble' do
|
|
42
|
+
object.as_extended_json.should == {'$numberDouble' => '42.0'}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'relaxed mode' do
|
|
47
|
+
let(:serialized) do
|
|
48
|
+
object.as_extended_json(mode: :relaxed)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'returns float' do
|
|
52
|
+
serialized.should be_a(Float)
|
|
53
|
+
serialized.should be_within(0.00001).of(42)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context 'legacy mode' do
|
|
58
|
+
let(:serialized) do
|
|
59
|
+
object.as_extended_json(mode: :legacy)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'returns float' do
|
|
63
|
+
serialized.should be_a(Float)
|
|
64
|
+
serialized.should be_within(0.00001).of(42)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it_behaves_like "an Extended JSON serializable object"
|
|
69
|
+
end
|
|
29
70
|
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# rubocop:todo all
|
|
2
|
+
# Copyright (C) 2021 MongoDB Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
require "spec_helper"
|
|
17
|
+
|
|
18
|
+
describe 'Hash ActiveSupport extensions' do
|
|
19
|
+
require_active_support
|
|
20
|
+
|
|
21
|
+
describe '#symbolize_keys' do
|
|
22
|
+
let(:symbolized) { hash.symbolize_keys }
|
|
23
|
+
|
|
24
|
+
shared_examples 'works correctly' do
|
|
25
|
+
it 'returns a hash' do
|
|
26
|
+
symbolized.class.should be Hash
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'works correctly' do
|
|
30
|
+
hash.symbolize_keys.should == {foo: 'bar'}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'string keys' do
|
|
35
|
+
let(:hash) do
|
|
36
|
+
{'foo' => 'bar'}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
include_examples 'works correctly'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'symbol keys' do
|
|
43
|
+
let(:hash) do
|
|
44
|
+
{foo: 'bar'}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
include_examples 'works correctly'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'both string and symbol keys' do
|
|
51
|
+
let(:hash) do
|
|
52
|
+
{'foo' => 42, foo: 'bar'}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
include_examples 'works correctly'
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/spec/bson/hash_spec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# rubocop:todo all
|
|
2
|
+
# Copyright (C) 2009-2020 MongoDB Inc.
|
|
2
3
|
#
|
|
3
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
5
|
# you may not use this file except in compliance with the License.
|
|
@@ -52,110 +53,361 @@ describe Hash do
|
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
|
|
55
|
-
context "when the hash has
|
|
56
|
+
context "when the hash has dollar keys" do
|
|
56
57
|
|
|
57
58
|
let(:obj) do
|
|
58
59
|
{ "$testing" => "value" }
|
|
59
60
|
end
|
|
60
61
|
|
|
61
|
-
context "when validating keys" do
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
end
|
|
63
|
+
let(:bson) do
|
|
64
|
+
"#{25.to_bson.to_s}#{String::BSON_TYPE}$testing#{BSON::NULL_BYTE}" +
|
|
65
|
+
"#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}"
|
|
66
|
+
end
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
it "serializes the hash" do
|
|
69
|
+
expect(obj.to_bson.to_s).to eq(bson)
|
|
70
|
+
end
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
expect {
|
|
75
|
-
obj.to_bson
|
|
76
|
-
}.to raise_error(BSON::String::IllegalKey)
|
|
77
|
-
end
|
|
72
|
+
context "when the hash contains an array of documents containing invalid keys" do
|
|
78
73
|
|
|
79
|
-
|
|
74
|
+
let(:obj) do
|
|
75
|
+
{ "array" => [{ "$testing" => "value" }] }
|
|
76
|
+
end
|
|
80
77
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
let(:bson) do
|
|
79
|
+
"#{45.to_bson.to_s}#{Array::BSON_TYPE}array#{BSON::NULL_BYTE}" +
|
|
80
|
+
"#{[{ "$testing" => "value" }].to_bson.to_s}#{BSON::NULL_BYTE}"
|
|
81
|
+
end
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
obj.to_bson
|
|
88
|
-
}.to raise_error(BSON::String::IllegalKey)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
83
|
+
it "serializes the hash" do
|
|
84
|
+
expect(obj.to_bson.to_s).to eq(bson)
|
|
91
85
|
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
92
88
|
|
|
93
|
-
|
|
89
|
+
context "when the hash is embedded" do
|
|
94
90
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
91
|
+
let(:obj) do
|
|
92
|
+
{ "field" => { "key" => "value" }}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
let(:bson) do
|
|
96
|
+
"#{32.to_bson.to_s}#{Hash::BSON_TYPE}field#{BSON::NULL_BYTE}" +
|
|
97
|
+
"#{20.to_bson.to_s}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" +
|
|
98
|
+
"#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it_behaves_like "a serializable bson element"
|
|
102
|
+
it_behaves_like "a deserializable bson element"
|
|
103
|
+
end
|
|
100
104
|
|
|
101
|
-
|
|
105
|
+
context 'with symbol values' do
|
|
106
|
+
let(:value) { :foo }
|
|
102
107
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
let(:serialized) do
|
|
109
|
+
{foo: value}.to_bson.to_s
|
|
110
|
+
end
|
|
106
111
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
def perform_test(bson_type_to_use)
|
|
113
|
+
Symbol.class_eval do
|
|
114
|
+
alias_method :bson_type_orig, :bson_type
|
|
115
|
+
define_method(:bson_type) do
|
|
116
|
+
bson_type_to_use
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
begin
|
|
121
|
+
yield
|
|
122
|
+
ensure
|
|
123
|
+
Symbol.class_eval do
|
|
124
|
+
alias_method :bson_type, :bson_type_orig
|
|
125
|
+
remove_method :bson_type_orig
|
|
112
126
|
end
|
|
113
127
|
end
|
|
114
128
|
end
|
|
115
129
|
|
|
116
|
-
|
|
130
|
+
let(:bson_with_symbol) do
|
|
131
|
+
"\x12\x00\x00\x00\x0Efoo\x00\x04\x00\x00\x00bar\x00\x00".force_encoding('binary')
|
|
132
|
+
end
|
|
117
133
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
134
|
+
let(:deserialized) do
|
|
135
|
+
Hash.from_bson(BSON::ByteBuffer.new(bson_with_symbol))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
context 'when Symbol#bson_type is set to symbol' do
|
|
139
|
+
let(:bson_type_to_use) { BSON::Symbol::BSON_TYPE }
|
|
140
|
+
|
|
141
|
+
let(:expected) do
|
|
142
|
+
"\x12\x00\x00\x00\x0Efoo\x00\x04\x00\x00\x00foo\x00\x00".force_encoding('binary')
|
|
121
143
|
end
|
|
122
144
|
|
|
123
|
-
it
|
|
124
|
-
|
|
145
|
+
it 'serializes to BSON symbol' do
|
|
146
|
+
perform_test(bson_type_to_use) do
|
|
147
|
+
serialized
|
|
148
|
+
end.should == expected
|
|
125
149
|
end
|
|
126
150
|
|
|
127
|
-
|
|
151
|
+
it 'deserializes to Symbol' do
|
|
152
|
+
deserialized.should == {'foo' => :bar}
|
|
153
|
+
end
|
|
154
|
+
end
|
|
128
155
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
end
|
|
156
|
+
context 'when Symbol#bson_type is set to string' do
|
|
157
|
+
let(:bson_type_to_use) { BSON::String::BSON_TYPE }
|
|
132
158
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
end
|
|
159
|
+
let(:expected) do
|
|
160
|
+
"\x12\x00\x00\x00\x02foo\x00\x04\x00\x00\x00foo\x00\x00".force_encoding('binary')
|
|
161
|
+
end
|
|
137
162
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
163
|
+
it 'serializes to BSON string' do
|
|
164
|
+
perform_test(bson_type_to_use) do
|
|
165
|
+
serialized
|
|
166
|
+
end.should == expected
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it 'deserializes to Symbol' do
|
|
170
|
+
deserialized.should == {'foo' => :bar}
|
|
141
171
|
end
|
|
142
172
|
end
|
|
143
173
|
end
|
|
144
174
|
|
|
145
|
-
context
|
|
175
|
+
context 'when hash contains value of an unserializable class' do
|
|
176
|
+
class HashSpecUnserializableClass
|
|
177
|
+
end
|
|
146
178
|
|
|
147
179
|
let(:obj) do
|
|
148
|
-
{
|
|
180
|
+
{foo: HashSpecUnserializableClass.new}
|
|
149
181
|
end
|
|
150
182
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
183
|
+
it 'raises UnserializableClass' do
|
|
184
|
+
lambda do
|
|
185
|
+
obj.to_bson
|
|
186
|
+
end.should raise_error(BSON::Error::UnserializableClass,
|
|
187
|
+
# C extension does not provide hash key in the exception message.
|
|
188
|
+
/(Hash value for key 'foo'|Value) does not define its BSON serialized type:.*HashSpecUnserializableClass/)
|
|
155
189
|
end
|
|
190
|
+
end
|
|
156
191
|
|
|
157
|
-
|
|
158
|
-
|
|
192
|
+
context 'when reading from a byte buffer that was previously written to' do
|
|
193
|
+
let(:buffer) do
|
|
194
|
+
{foo: 42}.to_bson
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it 'returns the original hash' do
|
|
198
|
+
expect(Hash.from_bson(buffer)).to eq('foo' => 42)
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
context 'when round-tripping a BigDecimal' do
|
|
203
|
+
let(:to_bson) do
|
|
204
|
+
{"x" => BigDecimal('1')}.to_bson
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
let(:from_bson) do
|
|
208
|
+
Hash.from_bson(to_bson)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'doesn\'t raise on serialization' do
|
|
212
|
+
expect do
|
|
213
|
+
to_bson
|
|
214
|
+
end.to_not raise_error
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'deserializes as a BigDecimal' do
|
|
218
|
+
expect(from_bson).to eq({"x" => BigDecimal(1)})
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
context 'when deserializing round-tripping a Decimal128' do
|
|
223
|
+
let(:to_bson) do
|
|
224
|
+
{x:BSON::Decimal128.new('1')}.to_bson
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
let(:from_bson) do
|
|
228
|
+
Hash.from_bson(to_bson)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'doesn\'t raise on serialization' do
|
|
232
|
+
expect do
|
|
233
|
+
to_bson
|
|
234
|
+
end.to_not raise_error
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it 'deserializes as a BigDecimal' do
|
|
238
|
+
expect(from_bson).to eq({"x" => BigDecimal(1)})
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
describe '#to_bson' do
|
|
244
|
+
context 'when a key is not valid utf-8' do
|
|
245
|
+
let(:key) { Utils.make_byte_string([254, 253, 255]) }
|
|
246
|
+
let(:hash) do
|
|
247
|
+
{key => 'foo'}
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
let(:expected_message) do
|
|
251
|
+
if BSON::Environment.jruby?
|
|
252
|
+
# Uses JRE conversion to another encoding
|
|
253
|
+
/Error serializing key.*Encoding::UndefinedConversionError/
|
|
254
|
+
else
|
|
255
|
+
# Uses our validator
|
|
256
|
+
/Key.*is not valid UTF-8/
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'raises EncodingError' do
|
|
261
|
+
expect do
|
|
262
|
+
hash.to_bson
|
|
263
|
+
end.to raise_error(EncodingError, expected_message)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context 'when a key contains null bytes' do
|
|
268
|
+
let(:hash) do
|
|
269
|
+
{"\x00".force_encoding('BINARY') => 'foo'}
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
it 'raises ArgumentError' do
|
|
273
|
+
expect do
|
|
274
|
+
hash.to_bson
|
|
275
|
+
end.to raise_error(ArgumentError, /[Kk]ey.*contains null bytes/)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
context 'when a value is not valid utf-8' do
|
|
280
|
+
let(:hash) do
|
|
281
|
+
{'foo' => [254, 253, 255].map(&:chr).join.force_encoding('BINARY')}
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
let(:expected_message) do
|
|
285
|
+
/from ASCII-8BIT to UTF-8/
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it 'raises EncodingError' do
|
|
289
|
+
expect do
|
|
290
|
+
hash.to_bson
|
|
291
|
+
end.to raise_error(EncodingError, expected_message)
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
context 'when a value contains null bytes' do
|
|
296
|
+
let(:hash) do
|
|
297
|
+
{'foo' => "\x00".force_encoding('BINARY')}
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it 'works' do
|
|
301
|
+
expect do
|
|
302
|
+
hash.to_bson
|
|
303
|
+
end.not_to raise_error
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
context 'when serializing a hash with a BigDecimal' do
|
|
308
|
+
let(:hash) do
|
|
309
|
+
{'foo' => BigDecimal('1')}
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
it 'works' do
|
|
313
|
+
expect do
|
|
314
|
+
hash.to_bson
|
|
315
|
+
end.to_not raise_error
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
describe '#from_bson' do
|
|
321
|
+
context 'when bson document has duplicate keys' do
|
|
322
|
+
let(:buf) do
|
|
323
|
+
buf = BSON::ByteBuffer.new
|
|
324
|
+
buf.put_int32(37)
|
|
325
|
+
buf.put_byte("\x02")
|
|
326
|
+
buf.put_cstring('foo')
|
|
327
|
+
buf.put_string('bar')
|
|
328
|
+
buf.put_byte("\x02")
|
|
329
|
+
buf.put_cstring('foo')
|
|
330
|
+
buf.put_string('overwrite')
|
|
331
|
+
buf.put_byte("\x00")
|
|
332
|
+
|
|
333
|
+
BSON::ByteBuffer.new(buf.to_s)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
let(:doc) { Hash.from_bson(buf) }
|
|
337
|
+
|
|
338
|
+
it 'overwrites first value with second value' do
|
|
339
|
+
expect(doc).to eq({ 'foo' => 'overwrite' })
|
|
340
|
+
end
|
|
159
341
|
end
|
|
342
|
+
|
|
343
|
+
context 'when bson document has string and symbol keys of the same name' do
|
|
344
|
+
let(:buf) do
|
|
345
|
+
buf = BSON::ByteBuffer.new
|
|
346
|
+
buf.put_int32(31)
|
|
347
|
+
buf.put_byte("\x02")
|
|
348
|
+
buf.put_cstring('foo')
|
|
349
|
+
buf.put_string('bar')
|
|
350
|
+
buf.put_byte("\x0e")
|
|
351
|
+
buf.put_cstring('foo')
|
|
352
|
+
buf.put_string('bar')
|
|
353
|
+
buf.put_byte("\x00")
|
|
354
|
+
|
|
355
|
+
BSON::ByteBuffer.new(buf.to_s)
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
let(:doc) { Hash.from_bson(buf) }
|
|
359
|
+
|
|
360
|
+
it 'overwrites first value with second value' do
|
|
361
|
+
expect(doc).to eq({ 'foo' => :bar })
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'when deserializing a hash with a BigDecimal' do
|
|
366
|
+
let(:to_bson) do
|
|
367
|
+
{x: BigDecimal('1')}.to_bson
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
context 'when it has mode: :bson' do
|
|
371
|
+
|
|
372
|
+
let(:from_bson) do
|
|
373
|
+
Hash.from_bson(to_bson, mode: :bson)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
it 'deserializes as a BigDecimal' do
|
|
377
|
+
expect(from_bson).to eq({"x" => BSON::Decimal128.new('1')})
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
context 'when it doesn\'t have mode: :bson' do
|
|
382
|
+
|
|
383
|
+
let(:from_bson) do
|
|
384
|
+
Hash.from_bson(to_bson)
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
it 'deserializes as a BigDecimal' do
|
|
388
|
+
expect(from_bson).to eq({"x" => BigDecimal(1)})
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
describe '#as_extended_json' do
|
|
395
|
+
let(:object) do
|
|
396
|
+
{ 'foo' => :bar, 'baz' => ['qux', 1, 2.0, { 'lorem' => 1 }] }
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
let(:expected) do
|
|
400
|
+
{ "foo" => { "$symbol" => "bar" },
|
|
401
|
+
"baz" => [ "qux",
|
|
402
|
+
{ "$numberInt" => "1" },
|
|
403
|
+
{ "$numberDouble" => "2.0" },
|
|
404
|
+
{ "lorem" => { "$numberInt" => "1" } } ] }
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it "returns the binary data plus type" do
|
|
408
|
+
expect(object.as_extended_json).to eq(expected)
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
it_behaves_like 'an Extended JSON serializable object'
|
|
160
412
|
end
|
|
161
413
|
end
|