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
data/spec/bson/undefined_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,30 @@ describe BSON::Undefined 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 "#as_json" do
|
|
32
|
+
|
|
33
|
+
let(:object) do
|
|
34
|
+
described_class.new
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "returns nil" do
|
|
38
|
+
expect(object.as_json).to eq(nil)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it_behaves_like 'a JSON serializable object'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#as_extended_json" do
|
|
45
|
+
|
|
46
|
+
let(:object) do
|
|
47
|
+
described_class.new
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "returns the binary data plus type" do
|
|
51
|
+
expect(object.as_extended_json).to eq({ "$undefined" => true })
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it_behaves_like 'an Extended JSON serializable object'
|
|
55
|
+
end
|
|
29
56
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2025-present MongoDB Inc.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require 'spec_helper'
|
|
18
|
+
|
|
19
|
+
describe BSON::Vector do
|
|
20
|
+
it 'behaves like an Array' do
|
|
21
|
+
expect(described_class.new([ 1, 2, 3 ], :int8)).to be_a(Array)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#initialize' do
|
|
25
|
+
context 'when padding is not provided' do
|
|
26
|
+
let(:vector) { described_class.new([ 1, 2, 3 ], :int8) }
|
|
27
|
+
|
|
28
|
+
it 'sets the padding to 0' do
|
|
29
|
+
expect(vector.padding).to eq(0)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/spec/bson_spec.rb
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'runners/common_driver'
|
|
4
|
+
|
|
5
|
+
module BSON
|
|
6
|
+
module BinaryVector
|
|
7
|
+
class Spec < CommonDriver::Spec
|
|
8
|
+
def initialize(file)
|
|
9
|
+
super
|
|
10
|
+
@valid = @invalid = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def tests
|
|
14
|
+
@spec['tests'].collect do |test|
|
|
15
|
+
BSON::BinaryVector::Test.new(self, test)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def valid_tests
|
|
20
|
+
tests.select(&:valid?)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def invalid_tests
|
|
24
|
+
tests.reject(&:valid?)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Test
|
|
29
|
+
attr_reader :canonical_bson, :description, :dtype, :padding, :vector
|
|
30
|
+
|
|
31
|
+
def initialize(spec, test)
|
|
32
|
+
@spec = spec
|
|
33
|
+
@description = test['description']
|
|
34
|
+
@valid = test['valid']
|
|
35
|
+
@vector = ExtJSON.parse_obj(test['vector'])
|
|
36
|
+
@dtype_hex = test['dtype_hex']
|
|
37
|
+
@dtype_alias = test['dtype_alias']
|
|
38
|
+
@dtype = @dtype_alias.downcase.to_sym
|
|
39
|
+
@padding = test['padding']
|
|
40
|
+
@canonical_bson = test['canonical_bson']
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def valid?
|
|
44
|
+
@valid
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def document_from_canonical_bson
|
|
48
|
+
bson_bytes = decode_hex(@canonical_bson)
|
|
49
|
+
buffer = BSON::ByteBuffer.new(bson_bytes)
|
|
50
|
+
BSON::Document.from_bson(buffer)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def canonical_bson_from_document(use_vector_type: false, validate_vector_data: false)
|
|
54
|
+
args = if use_vector_type
|
|
55
|
+
[ BSON::Vector.new(@vector, @dtype, @padding) ]
|
|
56
|
+
else
|
|
57
|
+
[ @vector, @dtype, @padding ]
|
|
58
|
+
end
|
|
59
|
+
{
|
|
60
|
+
@spec.test_key => BSON::Binary.from_vector(
|
|
61
|
+
*args,
|
|
62
|
+
validate_vector_data: validate_vector_data
|
|
63
|
+
),
|
|
64
|
+
}.to_bson.to_s
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def bson
|
|
68
|
+
decode_hex(@canonical_bson)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def decode_hex(obj)
|
|
74
|
+
[ obj ].pack('H*')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# rubocop:todo all
|
|
2
|
+
# Copyright (C) 2016-2020 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 'json'
|
|
17
|
+
require 'bigdecimal'
|
|
18
|
+
|
|
19
|
+
module BSON
|
|
20
|
+
module CommonDriver
|
|
21
|
+
|
|
22
|
+
# Represents a Common Driver specification test.
|
|
23
|
+
#
|
|
24
|
+
# @since 4.2.0
|
|
25
|
+
class Spec
|
|
26
|
+
|
|
27
|
+
# The spec description.
|
|
28
|
+
#
|
|
29
|
+
# @return [ String ] The spec description.
|
|
30
|
+
#
|
|
31
|
+
# @since 4.2.0
|
|
32
|
+
attr_reader :description
|
|
33
|
+
|
|
34
|
+
# The document key of the object to test.
|
|
35
|
+
#
|
|
36
|
+
# @return [ String ] The document key.
|
|
37
|
+
#
|
|
38
|
+
# @since 4.2.0
|
|
39
|
+
attr_reader :test_key
|
|
40
|
+
|
|
41
|
+
# Instantiate the new spec.
|
|
42
|
+
#
|
|
43
|
+
# @example Create the spec.
|
|
44
|
+
# Spec.new(file)
|
|
45
|
+
#
|
|
46
|
+
# @param [ String ] file The name of the yaml file.
|
|
47
|
+
#
|
|
48
|
+
# @since 4.2.0
|
|
49
|
+
def initialize(file)
|
|
50
|
+
@spec = ::JSON.parse(File.read(file))
|
|
51
|
+
@valid = @spec['valid'] || []
|
|
52
|
+
@invalid = @spec['parseErrors'] || []
|
|
53
|
+
@description = @spec['description']
|
|
54
|
+
@test_key = @spec['test_key']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Get a list of tests that don't raise exceptions.
|
|
58
|
+
#
|
|
59
|
+
# @example Get the list of valid tests.
|
|
60
|
+
# spec.valid_tests
|
|
61
|
+
#
|
|
62
|
+
# @return [ Array<BSON::CommonDriver::Test> ] The list of valid Tests.
|
|
63
|
+
#
|
|
64
|
+
# @since 4.2.0
|
|
65
|
+
def valid_tests
|
|
66
|
+
@valid_tests ||=
|
|
67
|
+
@valid.collect do |test|
|
|
68
|
+
BSON::CommonDriver::Test.new(self, test)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Get a list of tests that raise exceptions.
|
|
73
|
+
#
|
|
74
|
+
# @example Get the list of invalid tests.
|
|
75
|
+
# spec.invalid_tests
|
|
76
|
+
#
|
|
77
|
+
# @return [ Array<BSON::CommonDriver::Test> ] The list of invalid Tests.
|
|
78
|
+
#
|
|
79
|
+
# @since 4.2.0
|
|
80
|
+
def invalid_tests
|
|
81
|
+
@invalid_tests ||=
|
|
82
|
+
@invalid.collect do |test|
|
|
83
|
+
BSON::CommonDriver::Test.new(self, test)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# The class of the bson object to test.
|
|
88
|
+
#
|
|
89
|
+
# @example Get the class of the object to test.
|
|
90
|
+
# spec.klass
|
|
91
|
+
#
|
|
92
|
+
# @return [ Class ] The object class.
|
|
93
|
+
#
|
|
94
|
+
# @since 4.2.0
|
|
95
|
+
def klass
|
|
96
|
+
@klass ||= BSON.const_get(description)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Represents a single CommonDriver test.
|
|
101
|
+
#
|
|
102
|
+
# @since 4.2.0
|
|
103
|
+
class Test
|
|
104
|
+
|
|
105
|
+
# The test description.
|
|
106
|
+
#
|
|
107
|
+
# @return [ String ] The test description.
|
|
108
|
+
#
|
|
109
|
+
# @since 4.2.0
|
|
110
|
+
attr_reader :description
|
|
111
|
+
|
|
112
|
+
# The test subject.
|
|
113
|
+
#
|
|
114
|
+
# @return [ String ] The test subject.
|
|
115
|
+
#
|
|
116
|
+
# @since 4.2.0
|
|
117
|
+
attr_reader :subject
|
|
118
|
+
|
|
119
|
+
# The string to use to create a Decimal128.
|
|
120
|
+
#
|
|
121
|
+
# @return [ String ] The string to use in creating a Decimal128 object.
|
|
122
|
+
#
|
|
123
|
+
# @since 4.2.0
|
|
124
|
+
attr_reader :string
|
|
125
|
+
|
|
126
|
+
# The expected string representation of the Decimal128 object.
|
|
127
|
+
#
|
|
128
|
+
# @return [ String ] The object as a string.
|
|
129
|
+
#
|
|
130
|
+
# @since 4.2.0
|
|
131
|
+
attr_reader :match_string
|
|
132
|
+
|
|
133
|
+
# The json representation of the object.
|
|
134
|
+
#
|
|
135
|
+
# @return [ Hash ] The json representation of the object.
|
|
136
|
+
#
|
|
137
|
+
# @since 4.2.0
|
|
138
|
+
attr_reader :ext_json
|
|
139
|
+
|
|
140
|
+
# Instantiate the new Test.
|
|
141
|
+
#
|
|
142
|
+
# @example Create the test.
|
|
143
|
+
# Test.new(test)
|
|
144
|
+
#
|
|
145
|
+
# @param [ CommonDriver::Spec ] spec The test specification.
|
|
146
|
+
# @param [ Hash ] test The test specification.
|
|
147
|
+
#
|
|
148
|
+
# @since 4.2.0
|
|
149
|
+
def initialize(spec, test)
|
|
150
|
+
@spec = spec
|
|
151
|
+
@description = test['description']
|
|
152
|
+
@string = test['string']
|
|
153
|
+
@match_string = test['match_string']
|
|
154
|
+
@ext_json = ::JSON.parse(test['extjson']) if test['extjson']
|
|
155
|
+
@from_ext_json = test['from_extjson'].nil? ? true : test['from_extjson']
|
|
156
|
+
@to_ext_json = test['to_extjson'].nil? ? true : test['to_extjson']
|
|
157
|
+
@subject = test['subject']
|
|
158
|
+
@test_key = spec.test_key
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Get the reencoded document in hex format.
|
|
162
|
+
#
|
|
163
|
+
# @example Get the reencoded document as hex.
|
|
164
|
+
# test.reencoded_hex
|
|
165
|
+
#
|
|
166
|
+
# @return [ String ] The reencoded document in hex format.
|
|
167
|
+
#
|
|
168
|
+
# @since 4.2.0
|
|
169
|
+
def reencoded_hex
|
|
170
|
+
decoded_document.to_bson.to_s.unpack1("H*").upcase
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# The object tested.
|
|
174
|
+
#
|
|
175
|
+
# @example Get the object for this test.
|
|
176
|
+
# test.object
|
|
177
|
+
#
|
|
178
|
+
# @return [ BSON::Object ] The object.
|
|
179
|
+
#
|
|
180
|
+
# @since 4.2.0
|
|
181
|
+
def object
|
|
182
|
+
@object ||= decoded_document[@test_key]
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# The object as json, in a document with the test key.
|
|
186
|
+
#
|
|
187
|
+
# @example Get a document with the object at the test key.
|
|
188
|
+
# test.document_as_extended_json
|
|
189
|
+
#
|
|
190
|
+
# @return [ Hash ] The extended_json representation of document.
|
|
191
|
+
#
|
|
192
|
+
# @since 4.2.0
|
|
193
|
+
def document_as_extended_json
|
|
194
|
+
{ @test_key => object.as_extended_json }
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Use the string in the extended json to instantiate the bson object.
|
|
198
|
+
#
|
|
199
|
+
# @example Get a bson object from the string in the extended json.
|
|
200
|
+
# test.from_json
|
|
201
|
+
#
|
|
202
|
+
# @return [ BSON::Object ] The BSON object.
|
|
203
|
+
#
|
|
204
|
+
# @since 4.2.0
|
|
205
|
+
def from_json_string
|
|
206
|
+
klass.from_string(@ext_json[@test_key][klass::EXTENDED_JSON_KEY])
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Create an object from the given test string.
|
|
210
|
+
#
|
|
211
|
+
# @example
|
|
212
|
+
# test.parse_string
|
|
213
|
+
#
|
|
214
|
+
# @return [ BSON::Object ] The object.
|
|
215
|
+
#
|
|
216
|
+
# @since 4.2.0
|
|
217
|
+
def parse_string
|
|
218
|
+
klass.from_string(string)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Attempt to create an object from an invalid string.
|
|
222
|
+
#
|
|
223
|
+
# @example
|
|
224
|
+
# test.parse_invalid_string
|
|
225
|
+
#
|
|
226
|
+
# @raise [ Error ] Parsing an invalid string will raise an error.
|
|
227
|
+
#
|
|
228
|
+
# @since 4.2.0
|
|
229
|
+
def parse_invalid_string
|
|
230
|
+
klass.from_string(subject)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# The class of the object being tested.
|
|
234
|
+
#
|
|
235
|
+
# @example
|
|
236
|
+
# test.klass
|
|
237
|
+
#
|
|
238
|
+
# @return [ Class ] The object class.
|
|
239
|
+
#
|
|
240
|
+
# @since 4.2.0
|
|
241
|
+
def klass
|
|
242
|
+
@spec.klass
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# The error class of a parse error.
|
|
246
|
+
#
|
|
247
|
+
# @example
|
|
248
|
+
# test.parse_error
|
|
249
|
+
#
|
|
250
|
+
# @return [ Class ] The parse error class.
|
|
251
|
+
#
|
|
252
|
+
# @since 4.2.0
|
|
253
|
+
def parse_error
|
|
254
|
+
klass::InvalidRange
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Whether the object can be instantiated from extended json.
|
|
258
|
+
#
|
|
259
|
+
# @example Check if an object can be instantiated from the extended json.
|
|
260
|
+
# test.from_ex_json?
|
|
261
|
+
#
|
|
262
|
+
# @return [ true, false ] If the object can be instantiated from
|
|
263
|
+
# the provided extended json.
|
|
264
|
+
#
|
|
265
|
+
# @since 4.2.0
|
|
266
|
+
def from_ext_json?
|
|
267
|
+
@ext_json && @from_ext_json
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Whether the object can be represented as extended json.
|
|
271
|
+
#
|
|
272
|
+
# @example Check if an object can be represented as extended json.
|
|
273
|
+
# test.to_ext_json?
|
|
274
|
+
#
|
|
275
|
+
# @return [ true, false ] If the object can be represented as
|
|
276
|
+
# extended json.
|
|
277
|
+
#
|
|
278
|
+
# @since 4.2.0
|
|
279
|
+
def to_ext_json?
|
|
280
|
+
@ext_json && @to_ext_json
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Whether the object can be instantiated from a string.
|
|
284
|
+
#
|
|
285
|
+
# @example Check if an object can be instantiated from a string.
|
|
286
|
+
# test.from_string?
|
|
287
|
+
#
|
|
288
|
+
# @return [ true, false ] If the object can be instantiated from a string.
|
|
289
|
+
#
|
|
290
|
+
# @since 4.2.0
|
|
291
|
+
def from_string?
|
|
292
|
+
@string && @from_ext_json
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# The expected string representation of the test object.
|
|
296
|
+
#
|
|
297
|
+
# @example Get the expected String representation of the test object.
|
|
298
|
+
# test.expected_to_string
|
|
299
|
+
#
|
|
300
|
+
# @return [ String ] The expected string representation.
|
|
301
|
+
#
|
|
302
|
+
# @since 4.2.0
|
|
303
|
+
def expected_to_string
|
|
304
|
+
match_string || string
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# The Ruby class to which this bson object can be converted via a helper.
|
|
308
|
+
#
|
|
309
|
+
# @example Get the native type to which this object can be converted.
|
|
310
|
+
# test.native_type
|
|
311
|
+
#
|
|
312
|
+
# @return [ Class ] The Ruby native type.
|
|
313
|
+
#
|
|
314
|
+
# @since 4.2.0
|
|
315
|
+
def native_type
|
|
316
|
+
klass::NATIVE_TYPE
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Get the object converted to an instance of the native Ruby type.
|
|
320
|
+
#
|
|
321
|
+
# @example Get a native Ruby instance.
|
|
322
|
+
# test.native_type_conversion
|
|
323
|
+
#
|
|
324
|
+
# @return [ Object ] An instance of the Ruby native type.
|
|
325
|
+
#
|
|
326
|
+
# @since 4.2.0
|
|
327
|
+
def native_type_conversion
|
|
328
|
+
object.send("to_#{to_snake_case(native_type)}")
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
private
|
|
332
|
+
|
|
333
|
+
def to_snake_case(string)
|
|
334
|
+
string.to_s.gsub(/::/, '/').
|
|
335
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
336
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
337
|
+
tr("-", "_").
|
|
338
|
+
downcase
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def decoded_document
|
|
342
|
+
@document ||= (data = [ @subject ].pack('H*')
|
|
343
|
+
buffer = BSON::ByteBuffer.new(data)
|
|
344
|
+
BSON::Document.from_bson(buffer, mode: :bson))
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# rubocop:todo all
|
|
2
|
+
# Copyright (C) 2016-2020 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 'json'
|
|
17
|
+
require 'forwardable'
|
|
18
|
+
|
|
19
|
+
module BSON
|
|
20
|
+
module Corpus
|
|
21
|
+
|
|
22
|
+
# Represents a test from the driver BSON Corpus.
|
|
23
|
+
#
|
|
24
|
+
# @since 4.2.0
|
|
25
|
+
class Spec
|
|
26
|
+
|
|
27
|
+
# The spec description.
|
|
28
|
+
#
|
|
29
|
+
# @return [ String ] The spec description.
|
|
30
|
+
#
|
|
31
|
+
# @since 4.2.0
|
|
32
|
+
attr_reader :description
|
|
33
|
+
|
|
34
|
+
# The document key of the object to test.
|
|
35
|
+
#
|
|
36
|
+
# @return [ String ] The document key.
|
|
37
|
+
#
|
|
38
|
+
# @since 4.2.0
|
|
39
|
+
attr_reader :test_key
|
|
40
|
+
|
|
41
|
+
# Instantiate the new spec.
|
|
42
|
+
#
|
|
43
|
+
# @example Create the spec.
|
|
44
|
+
# Spec.new(file)
|
|
45
|
+
#
|
|
46
|
+
# @param [ String ] file The name of the json file.
|
|
47
|
+
#
|
|
48
|
+
# @since 4.2.0
|
|
49
|
+
def initialize(file)
|
|
50
|
+
@spec = ::JSON.parse(File.read(file).force_encoding('utf-8'))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def description
|
|
54
|
+
@spec['description']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_key
|
|
58
|
+
@spec['test_key']
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def bson_type
|
|
62
|
+
@bson_type ||= @spec['bson_type'].to_i(16).chr
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def valid_tests
|
|
66
|
+
@valid_tests ||=
|
|
67
|
+
@spec['valid']&.map do |test_spec|
|
|
68
|
+
ValidTest.new(self, test_spec)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def decode_error_tests
|
|
73
|
+
@decode_error_tests ||=
|
|
74
|
+
@spec['decodeErrors']&.map do |test_spec|
|
|
75
|
+
DecodeErrorTest.new(self, test_spec)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def parse_error_tests
|
|
80
|
+
@parse_error_tests ||=
|
|
81
|
+
@spec['parseErrors']&.map do |test_spec|
|
|
82
|
+
ParseErrorTest.new(self, test_spec)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# The class of the bson object to test.
|
|
87
|
+
#
|
|
88
|
+
# @example Get the class of the object to test.
|
|
89
|
+
# spec.klass
|
|
90
|
+
#
|
|
91
|
+
# @return [ Class ] The object class.
|
|
92
|
+
#
|
|
93
|
+
# @since 4.2.0
|
|
94
|
+
def klass
|
|
95
|
+
@klass ||= BSON.const_get(description)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class TestBase
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def decode_hex(obj)
|
|
104
|
+
[ obj ].pack('H*')
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Represents a single BSON Corpus test.
|
|
109
|
+
#
|
|
110
|
+
# @since 4.2.0
|
|
111
|
+
class ValidTest < TestBase
|
|
112
|
+
extend Forwardable
|
|
113
|
+
|
|
114
|
+
# Instantiate the new Test.
|
|
115
|
+
#
|
|
116
|
+
# @example Create the test.
|
|
117
|
+
# Test.new(test)
|
|
118
|
+
#
|
|
119
|
+
# @param [ Corpus::Spec ] spec The test specification.
|
|
120
|
+
# @param [ Hash ] test The test specification.
|
|
121
|
+
#
|
|
122
|
+
# @since 4.2.0
|
|
123
|
+
def initialize(spec, test_params)
|
|
124
|
+
@spec = spec
|
|
125
|
+
test_params = test_params.dup
|
|
126
|
+
%w(
|
|
127
|
+
description canonical_extjson relaxed_extjson
|
|
128
|
+
degenerate_extjson converted_extjson
|
|
129
|
+
lossy
|
|
130
|
+
).each do |key|
|
|
131
|
+
instance_variable_set("@#{key}", test_params.delete(key))
|
|
132
|
+
end
|
|
133
|
+
%w(
|
|
134
|
+
canonical_bson degenerate_bson converted_bson
|
|
135
|
+
lossy
|
|
136
|
+
).each do |key|
|
|
137
|
+
if test_params.key?(key)
|
|
138
|
+
instance_variable_set("@#{key}", decode_hex(test_params.delete(key)))
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
unless test_params.empty?
|
|
142
|
+
raise "Test params has unprocessed keys: #{test_params}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def_delegators :@spec, :test_key
|
|
147
|
+
|
|
148
|
+
attr_reader :description,
|
|
149
|
+
:canonical_bson,
|
|
150
|
+
:degenerate_bson,
|
|
151
|
+
:converted_bson,
|
|
152
|
+
:canonical_extjson,
|
|
153
|
+
:relaxed_extjson,
|
|
154
|
+
:degenerate_extjson,
|
|
155
|
+
:converted_extjson
|
|
156
|
+
|
|
157
|
+
def lossy?
|
|
158
|
+
!!@lossy
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def canonical_extjson_doc
|
|
162
|
+
::JSON.parse(canonical_extjson)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def relaxed_extjson_doc
|
|
166
|
+
relaxed_extjson && ::JSON.parse(relaxed_extjson)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
class DecodeErrorTest < TestBase
|
|
171
|
+
def initialize(spec, test_params)
|
|
172
|
+
@spec = spec
|
|
173
|
+
@description = test_params['description']
|
|
174
|
+
@bson = decode_hex(test_params['bson'])
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
attr_reader :description, :bson
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
class ParseErrorTest
|
|
181
|
+
def initialize(spec, test_params)
|
|
182
|
+
@spec = spec
|
|
183
|
+
@description = test_params['description']
|
|
184
|
+
@string = test_params['string']
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
attr_reader :spec
|
|
188
|
+
attr_reader :description, :string
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|