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
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
# rubocop:todo all
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
|
|
4
|
+
describe Regexp::Raw do
|
|
5
|
+
|
|
6
|
+
let(:pattern) { '\W+' }
|
|
7
|
+
let(:options) { '' }
|
|
8
|
+
let(:bson) { "#{pattern}#{BSON::NULL_BYTE}#{options}#{BSON::NULL_BYTE}" }
|
|
9
|
+
|
|
10
|
+
describe "#as_json" do
|
|
11
|
+
|
|
12
|
+
let(:object) do
|
|
13
|
+
described_class.new(pattern, 'im')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "returns the legacy serialization including regex pattern and options" do
|
|
17
|
+
expect(object.as_json).to eq({ "$regex" => "\\W+", "$options" => "im" })
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it_behaves_like "a JSON serializable object"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#as_extended_json' do
|
|
24
|
+
|
|
25
|
+
let(:object) do
|
|
26
|
+
described_class.new(pattern, 'im')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context 'legacy mode' do
|
|
30
|
+
it "returns the legacy serialization including regex pattern and options" do
|
|
31
|
+
expect(object.as_extended_json(mode: :legacy)).to eq({ "$regex" => "\\W+", "$options" => "im" })
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'canonical/relaxed mode' do
|
|
36
|
+
it "returns the extended json 2.0 serialization" do
|
|
37
|
+
expect(object.as_extended_json).to eq(
|
|
38
|
+
"$regularExpression" => {'pattern' => "\\W+", "options" => "im"}
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#to_bson/#from_bson" do
|
|
45
|
+
|
|
46
|
+
let(:options) { 'ilmsux' }
|
|
47
|
+
let(:obj) { described_class.new(pattern, options) }
|
|
48
|
+
let(:type) { 11.chr }
|
|
49
|
+
let(:bson) { "#{pattern}#{BSON::NULL_BYTE}#{options}#{BSON::NULL_BYTE}" }
|
|
50
|
+
|
|
51
|
+
let(:klass) { ::Regexp }
|
|
52
|
+
|
|
53
|
+
it_behaves_like "a bson element"
|
|
54
|
+
it_behaves_like "a serializable bson element"
|
|
55
|
+
it_behaves_like "a deserializable bson element"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "#initialize" do
|
|
59
|
+
|
|
60
|
+
let(:object) do
|
|
61
|
+
described_class.new(pattern, options)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context "when options are not passed" do
|
|
65
|
+
|
|
66
|
+
it "sets the options on the raw regex" do
|
|
67
|
+
expect(object.options). to eq(options)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "When the raw regexp is compiled" do
|
|
71
|
+
|
|
72
|
+
let(:regexp) do
|
|
73
|
+
object.compile
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "sets the options on the compiled regexp object" do
|
|
77
|
+
expect(regexp.options).to eq(0)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "when options are passed" do
|
|
83
|
+
|
|
84
|
+
context "when options are an Integer" do
|
|
85
|
+
|
|
86
|
+
let(:options) { ::Regexp::EXTENDED }
|
|
87
|
+
|
|
88
|
+
it "raises an error" do
|
|
89
|
+
expect do
|
|
90
|
+
object
|
|
91
|
+
end.to raise_error(ArgumentError, /Regexp options must be a String or Symbol/)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "when options are a String" do
|
|
96
|
+
|
|
97
|
+
let(:options) { 'x' }
|
|
98
|
+
|
|
99
|
+
it "sets the options on the raw regex" do
|
|
100
|
+
expect(object.options). to eq(options)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "When the raw regexp is compiled" do
|
|
104
|
+
|
|
105
|
+
let(:regexp) do
|
|
106
|
+
object.compile
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "sets the options on the compiled regexp object" do
|
|
110
|
+
expect(regexp.options).to eq(::Regexp::EXTENDED)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context 'when options are not passed' do
|
|
117
|
+
|
|
118
|
+
let(:object) do
|
|
119
|
+
described_class.new(pattern)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "sets no options on the raw regex" do
|
|
123
|
+
expect(object.options). to eq('')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
context "When the raw regexp is compiled" do
|
|
127
|
+
|
|
128
|
+
let(:regexp) do
|
|
129
|
+
object.compile
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "sets the options on the compiled regexp object" do
|
|
133
|
+
expect(regexp.options).to eq(0)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "#from_bson" do
|
|
140
|
+
|
|
141
|
+
let(:obj) { ::Regexp.from_bson(io) }
|
|
142
|
+
let(:io) { BSON::ByteBuffer.new(bson) }
|
|
143
|
+
|
|
144
|
+
it "deserializes to a Regexp::Raw object" do
|
|
145
|
+
expect(obj).to be_a(Regexp::Raw)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "deserializes the pattern" do
|
|
149
|
+
expect(obj.pattern).to eq(pattern)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context "when there are no options" do
|
|
153
|
+
|
|
154
|
+
it "does not set any options on the raw regexp object" do
|
|
155
|
+
expect(obj.options).to eq(options)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context "when there are options" do
|
|
160
|
+
|
|
161
|
+
context "when there is the i ignorecase option" do
|
|
162
|
+
|
|
163
|
+
let(:options) { 'i' }
|
|
164
|
+
|
|
165
|
+
it "deserializes the pattern" do
|
|
166
|
+
expect(obj.pattern).to eq(pattern)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "sets the i option on the raw regexp object" do
|
|
170
|
+
expect(obj.options).to eq(options)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
context "when there is the l locale dependent option" do
|
|
175
|
+
|
|
176
|
+
let(:options) { 'l' }
|
|
177
|
+
|
|
178
|
+
it "deserializes the pattern" do
|
|
179
|
+
expect(obj.pattern).to eq(pattern)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "sets the l option on the raw regexp object" do
|
|
183
|
+
expect(obj.options).to eq(options)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context "when there is the m multiline option" do
|
|
188
|
+
|
|
189
|
+
let(:options) { 'm' }
|
|
190
|
+
|
|
191
|
+
it "deserializes the pattern" do
|
|
192
|
+
expect(obj.pattern).to eq(pattern)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "sets the m option on the raw regexp object" do
|
|
196
|
+
expect(obj.options).to eq(options)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
context "when there is the s dotall option" do
|
|
201
|
+
|
|
202
|
+
let(:options) { 's' }
|
|
203
|
+
|
|
204
|
+
it "deserializes the pattern" do
|
|
205
|
+
expect(obj.pattern).to eq(pattern)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "sets the s option on the raw regexp object" do
|
|
209
|
+
expect(obj.options).to eq(options)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
context "when there is the u match unicode option" do
|
|
214
|
+
|
|
215
|
+
let(:options) { 'u' }
|
|
216
|
+
|
|
217
|
+
it "deserializes the pattern" do
|
|
218
|
+
expect(obj.pattern).to eq(pattern)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "sets the u option on the raw regexp object" do
|
|
222
|
+
expect(obj.options).to eq(options)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
context "when there is the x verbose option" do
|
|
227
|
+
|
|
228
|
+
let(:options) { 'x' }
|
|
229
|
+
|
|
230
|
+
it "deserializes the pattern" do
|
|
231
|
+
expect(obj.pattern).to eq(pattern)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it "sets the x option on the raw regexp object" do
|
|
235
|
+
expect(obj.options).to eq(options)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
context "when all options are set" do
|
|
240
|
+
|
|
241
|
+
let(:options) { 'ilmsux' }
|
|
242
|
+
|
|
243
|
+
it "deserializes the pattern" do
|
|
244
|
+
expect(obj.pattern).to eq(pattern)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it "sets all options on the raw regexp object" do
|
|
248
|
+
expect(obj.options).to eq(options)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
context "when a method is called on a Raw regexp object" do
|
|
255
|
+
|
|
256
|
+
let(:obj) { ::Regexp.from_bson(io) }
|
|
257
|
+
let(:io) { BSON::ByteBuffer.new(bson) }
|
|
258
|
+
|
|
259
|
+
it "forwards the method call on to the compiled Ruby Regexp object" do
|
|
260
|
+
expect(obj.source).to eq(pattern)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
context "when respond_to? is called on the Raw Regexp object" do
|
|
265
|
+
|
|
266
|
+
let(:obj) { Regexp::Raw.new(pattern, options) }
|
|
267
|
+
|
|
268
|
+
context "when include_private is false" do
|
|
269
|
+
|
|
270
|
+
it "does not consider private methods" do
|
|
271
|
+
expect(obj.respond_to?(:initialize_copy)).to eq(false)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
context "when include private is true" do
|
|
276
|
+
|
|
277
|
+
it "considers private methods" do
|
|
278
|
+
expect(obj.respond_to?(:initialize_copy, true)).to eq(true)
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
context "when include_private is not specified" do
|
|
283
|
+
|
|
284
|
+
it "does not consider private methods" do
|
|
285
|
+
expect(obj.respond_to?(:initialize_copy)).to eq(false)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
context "#to_bson" do
|
|
291
|
+
|
|
292
|
+
let(:obj) { Regexp::Raw.new(pattern, options) }
|
|
293
|
+
let(:options) { '' }
|
|
294
|
+
let(:bson) { "#{pattern}#{BSON::NULL_BYTE}#{options}#{BSON::NULL_BYTE}" }
|
|
295
|
+
let(:serialized) { obj.to_bson.to_s }
|
|
296
|
+
|
|
297
|
+
it "serializes the pattern" do
|
|
298
|
+
expect(serialized).to eq(bson)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
context "where there are no options" do
|
|
302
|
+
|
|
303
|
+
it "does not set any options on the bson regex object" do
|
|
304
|
+
expect(serialized).to eq(bson)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
context "when there are options" do
|
|
309
|
+
|
|
310
|
+
context "when options are specified as an Integer" do
|
|
311
|
+
|
|
312
|
+
let(:options) { ::Regexp::EXTENDED }
|
|
313
|
+
let(:bson) { "#{pattern}#{BSON::NULL_BYTE}mx#{BSON::NULL_BYTE}" }
|
|
314
|
+
|
|
315
|
+
it "raises an error" do
|
|
316
|
+
expect do
|
|
317
|
+
serialized
|
|
318
|
+
end.to raise_error(ArgumentError, /Regexp options must be a String or Symbol/)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context "when there is the i ignorecase option" do
|
|
323
|
+
|
|
324
|
+
let(:options) { 'i' }
|
|
325
|
+
|
|
326
|
+
it "sets the option on the serialized bson object" do
|
|
327
|
+
expect(serialized).to eq(bson)
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
context "when there is the l locale dependent option" do
|
|
332
|
+
|
|
333
|
+
let(:options) { 'l' }
|
|
334
|
+
|
|
335
|
+
it "sets the option on the serialized bson object" do
|
|
336
|
+
expect(serialized).to eq(bson)
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
context "when there is the m multiline option" do
|
|
341
|
+
|
|
342
|
+
let(:options) { 'm' }
|
|
343
|
+
|
|
344
|
+
it "sets the option on the serialized bson object" do
|
|
345
|
+
expect(serialized).to eq(bson)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context "when there is the s dotall option" do
|
|
350
|
+
|
|
351
|
+
let(:options) { 's' }
|
|
352
|
+
|
|
353
|
+
it "sets the option on the serialized bson object" do
|
|
354
|
+
expect(serialized).to eq(bson)
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
context "when there is the u match unicode option" do
|
|
359
|
+
|
|
360
|
+
let(:options) { 'u' }
|
|
361
|
+
|
|
362
|
+
it "sets the option on the serialized bson object" do
|
|
363
|
+
expect(serialized).to eq(bson)
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
context "when there is the x verbose option" do
|
|
368
|
+
|
|
369
|
+
let(:options) { 'x' }
|
|
370
|
+
|
|
371
|
+
it "sets the option on the serialized bson object" do
|
|
372
|
+
expect(serialized).to eq(bson)
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
context "when all options are set" do
|
|
377
|
+
|
|
378
|
+
let(:options) { 'ilmsux' }
|
|
379
|
+
|
|
380
|
+
it "sets all options on the serialized bson object" do
|
|
381
|
+
expect(serialized).to eq(bson)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
context "when the options are not provided in alphabetical order" do
|
|
385
|
+
|
|
386
|
+
let(:options) { 'mislxu' }
|
|
387
|
+
let(:bson) { "#{pattern}#{BSON::NULL_BYTE}ilmsux#{BSON::NULL_BYTE}" }
|
|
388
|
+
|
|
389
|
+
it "serializes the options in alphabetical order" do
|
|
390
|
+
expect(serialized).to eq(bson)
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
describe "#compile" do
|
|
398
|
+
|
|
399
|
+
let(:obj) { Regexp.from_bson(io) }
|
|
400
|
+
let(:io) { BSON::ByteBuffer.new(bson) }
|
|
401
|
+
let(:ruby_regexp) { obj.compile }
|
|
402
|
+
|
|
403
|
+
it "sets the pattern on the Ruby Regexp object" do
|
|
404
|
+
expect(obj.pattern).to eq(ruby_regexp.source)
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
context "when there are no options set" do
|
|
408
|
+
|
|
409
|
+
it "does not set any options on the Ruby Regexp object" do
|
|
410
|
+
expect(ruby_regexp.options).to eq(0)
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
context "when there are options set" do
|
|
415
|
+
|
|
416
|
+
context "when there is the i ignorecase option" do
|
|
417
|
+
|
|
418
|
+
let(:options) { 'i' }
|
|
419
|
+
|
|
420
|
+
it "sets the i option on the Ruby Regexp object" do
|
|
421
|
+
expect(ruby_regexp.options).to eq(::Regexp::IGNORECASE)
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
context "when there is the l locale dependent option" do
|
|
426
|
+
|
|
427
|
+
let(:options) { 'l' }
|
|
428
|
+
|
|
429
|
+
it "does not set an option on the Ruby Regexp object" do
|
|
430
|
+
expect(ruby_regexp.options).to eq(0)
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
context "when there is the m multiline option" do
|
|
435
|
+
|
|
436
|
+
let(:options) { 'm' }
|
|
437
|
+
|
|
438
|
+
it "does not set an option on the Ruby Regexp object" do
|
|
439
|
+
expect(ruby_regexp.options).to eq(0)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
context "when there is the s dotall option" do
|
|
444
|
+
|
|
445
|
+
let(:options) { 's' }
|
|
446
|
+
|
|
447
|
+
# s in a bson regex maps to a Ruby Multiline Regexp option
|
|
448
|
+
it "sets the m option on the Ruby Regexp object" do
|
|
449
|
+
expect(ruby_regexp.options).to eq(::Regexp::MULTILINE)
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
context "when there is the u match unicode option" do
|
|
454
|
+
|
|
455
|
+
let(:options) { 'u' }
|
|
456
|
+
|
|
457
|
+
it "does not set an option on the Ruby Regexp object" do
|
|
458
|
+
expect(ruby_regexp.options).to eq(0)
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
context "when there is the x verbose option" do
|
|
463
|
+
|
|
464
|
+
let(:options) { 'x' }
|
|
465
|
+
|
|
466
|
+
it "sets the x option on the Ruby Regexp object" do
|
|
467
|
+
expect(ruby_regexp.options).to eq(::Regexp::EXTENDED)
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
context "when all options are set" do
|
|
472
|
+
|
|
473
|
+
let(:options) { 'ilmsux' }
|
|
474
|
+
|
|
475
|
+
# s in a bson regex maps to a Ruby Multiline Regexp option
|
|
476
|
+
it "sets the i, m, and x options on the Ruby Regexp object" do
|
|
477
|
+
expect(ruby_regexp.options).to eq(::Regexp::IGNORECASE | ::Regexp::MULTILINE | ::Regexp::EXTENDED)
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
context "when a Regexp::Raw object is roundtripped" do
|
|
484
|
+
|
|
485
|
+
let(:obj) { Regexp::Raw.new(pattern, options) }
|
|
486
|
+
let(:serialized) { obj.to_bson.to_s }
|
|
487
|
+
let(:roundtripped) { Regexp.from_bson(BSON::ByteBuffer.new(serialized)) }
|
|
488
|
+
|
|
489
|
+
it "roundtrips the pattern" do
|
|
490
|
+
expect(roundtripped.pattern).to eq(pattern)
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
context "when there are no options" do
|
|
494
|
+
|
|
495
|
+
let(:options) { '' }
|
|
496
|
+
|
|
497
|
+
it "does not set any options on the roundtripped Regexp::Raw object" do
|
|
498
|
+
expect(roundtripped.options).to eq(options)
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
context "when there are options set" do
|
|
503
|
+
|
|
504
|
+
context "when there is the i ignorecase option" do
|
|
505
|
+
|
|
506
|
+
let(:options) { 'i' }
|
|
507
|
+
|
|
508
|
+
it "sets the i option on the roundtripped Regexp::Raw object" do
|
|
509
|
+
expect(roundtripped.options).to eq(options)
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
context "when there is the l locale dependent option" do
|
|
514
|
+
|
|
515
|
+
let(:options) { 'l' }
|
|
516
|
+
|
|
517
|
+
it "sets the l option on the roundtripped Regexp::Raw object" do
|
|
518
|
+
expect(roundtripped.options).to eq(options)
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
context "when there is the m multiline option" do
|
|
523
|
+
|
|
524
|
+
let(:options) { 'm' }
|
|
525
|
+
|
|
526
|
+
it "sets the m option on the roundtripped Regexp::Raw object" do
|
|
527
|
+
expect(roundtripped.options).to eq(options)
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
context "when there is the s dotall option" do
|
|
532
|
+
|
|
533
|
+
let(:options) { 's' }
|
|
534
|
+
|
|
535
|
+
it "sets the s option on the roundtripped Regexp::Raw object" do
|
|
536
|
+
expect(roundtripped.options).to eq(options)
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
context "when there is the u match unicode option" do
|
|
541
|
+
|
|
542
|
+
let(:options) { 'u' }
|
|
543
|
+
|
|
544
|
+
it "sets the u option on the roundtripped Regexp::Raw object" do
|
|
545
|
+
expect(roundtripped.options).to eq(options)
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
context "when there is the x verbose option" do
|
|
550
|
+
|
|
551
|
+
let(:options) { 'x' }
|
|
552
|
+
|
|
553
|
+
it "sets the x option on the roundtripped Regexp::Raw object" do
|
|
554
|
+
expect(roundtripped.options).to eq(options)
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
context "when all options are set" do
|
|
559
|
+
|
|
560
|
+
let(:options) { 'ilmsux' }
|
|
561
|
+
|
|
562
|
+
it "sets all the options on the roundtripped Regexp::Raw object" do
|
|
563
|
+
expect(roundtripped.options).to eq(options)
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
context "when the options are passed in not in alphabetical order" do
|
|
567
|
+
|
|
568
|
+
let(:options) { 'sumlxi' }
|
|
569
|
+
|
|
570
|
+
it "sets all the options on the roundtripped Regexp::Raw object in order" do
|
|
571
|
+
expect(roundtripped.options).to eq(options.chars.sort.join)
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
describe 'yaml loading' do
|
|
579
|
+
let(:regexp) { described_class.new('hello.world', 's') }
|
|
580
|
+
|
|
581
|
+
it 'round-trips' do
|
|
582
|
+
actual = if YAML.respond_to?(:unsafe_load)
|
|
583
|
+
# In psych >= 4.0.0 `load` is basically an alias to `safe_load`,
|
|
584
|
+
# which will fail here.
|
|
585
|
+
YAML.unsafe_load(regexp.to_yaml)
|
|
586
|
+
else
|
|
587
|
+
YAML.load(regexp.to_yaml)
|
|
588
|
+
end
|
|
589
|
+
actual.pattern.should == 'hello.world'
|
|
590
|
+
actual.options.should == 's'
|
|
591
|
+
actual.compile.should =~ "hello\nworld"
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
end
|
data/spec/bson/regexp_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.
|
|
@@ -24,7 +25,7 @@ describe Regexp do
|
|
|
24
25
|
|
|
25
26
|
it "returns the binary data plus type" do
|
|
26
27
|
expect(object.as_json).to eq(
|
|
27
|
-
{ "$regex" => "\\W+", "$options" => "
|
|
28
|
+
{ "$regex" => "\\W+", "$options" => "im" }
|
|
28
29
|
)
|
|
29
30
|
end
|
|
30
31
|
|
|
@@ -55,9 +56,7 @@ describe Regexp do
|
|
|
55
56
|
/\d+/
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
let
|
|
59
|
-
[obj.source, BSON::NULL_BYTE, BSON::NULL_BYTE].join ''
|
|
60
|
-
end
|
|
59
|
+
let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}m#{BSON::NULL_BYTE}" }
|
|
61
60
|
|
|
62
61
|
it_behaves_like "a serializable bson element"
|
|
63
62
|
|
|
@@ -69,7 +68,9 @@ describe Regexp do
|
|
|
69
68
|
context "when the regexp has no options" do
|
|
70
69
|
|
|
71
70
|
let(:obj) { /\d+/ }
|
|
72
|
-
|
|
71
|
+
# Ruby always has a BSON regex's equivalent of multiline on
|
|
72
|
+
# http://www.regular-expressions.info/modifiers.html
|
|
73
|
+
let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}m#{BSON::NULL_BYTE}" }
|
|
73
74
|
|
|
74
75
|
it_behaves_like "a serializable bson element"
|
|
75
76
|
|
|
@@ -83,7 +84,7 @@ describe Regexp do
|
|
|
83
84
|
context "when ignoring case" do
|
|
84
85
|
|
|
85
86
|
let(:obj) { /\W+/i }
|
|
86
|
-
let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}
|
|
87
|
+
let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}im#{BSON::NULL_BYTE}" }
|
|
87
88
|
|
|
88
89
|
it_behaves_like "a serializable bson element"
|
|
89
90
|
|
|
@@ -107,7 +108,7 @@ describe Regexp do
|
|
|
107
108
|
context "when matching extended" do
|
|
108
109
|
|
|
109
110
|
let(:obj) { /\W+/x }
|
|
110
|
-
let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}
|
|
111
|
+
let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}mx#{BSON::NULL_BYTE}" }
|
|
111
112
|
|
|
112
113
|
it_behaves_like "a serializable bson element"
|
|
113
114
|
|
|
@@ -127,6 +128,58 @@ describe Regexp do
|
|
|
127
128
|
expect(result).to eq(obj)
|
|
128
129
|
end
|
|
129
130
|
end
|
|
131
|
+
|
|
132
|
+
context "when the regexp options contains a null byte" do
|
|
133
|
+
|
|
134
|
+
let(:regexp) do
|
|
135
|
+
Regexp::Raw.new("pattern", "options\x00")
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "raises an error" do
|
|
139
|
+
expect do
|
|
140
|
+
regexp
|
|
141
|
+
end.to raise_error(BSON::Error::InvalidRegexpPattern, /Regexp options cannot contain a null byte/)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context "when the regexp options is an integer" do
|
|
146
|
+
|
|
147
|
+
let(:regexp) do
|
|
148
|
+
Regexp::Raw.new("pattern", 1)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "raises an error" do
|
|
152
|
+
expect do
|
|
153
|
+
regexp
|
|
154
|
+
end.to raise_error(ArgumentError, /Regexp options must be a String or Symbol/)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context "when the regexp options is an invalid type" do
|
|
159
|
+
|
|
160
|
+
let(:regexp) do
|
|
161
|
+
Regexp::Raw.new("pattern", [2])
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "raises an error" do
|
|
165
|
+
expect do
|
|
166
|
+
regexp
|
|
167
|
+
end.to raise_error(ArgumentError, /Regexp options must be a String or Symbol/)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context "when the pattern contains a null byte" do
|
|
173
|
+
|
|
174
|
+
let(:regexp) do
|
|
175
|
+
Regexp::Raw.new("pattern\x00", "options")
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "raises an error" do
|
|
179
|
+
expect do
|
|
180
|
+
regexp
|
|
181
|
+
end.to raise_error(BSON::Error::InvalidRegexpPattern, /Regexp pattern cannot contain a null byte/)
|
|
182
|
+
end
|
|
130
183
|
end
|
|
131
184
|
end
|
|
132
185
|
end
|
data/spec/bson/registry_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.
|
|
@@ -38,7 +39,7 @@ describe BSON::Registry do
|
|
|
38
39
|
it "raises an error" do
|
|
39
40
|
expect {
|
|
40
41
|
described_class.get(25.chr, "field")
|
|
41
|
-
}.to raise_error(BSON::
|
|
42
|
+
}.to raise_error(BSON::Error::UnsupportedType)
|
|
42
43
|
end
|
|
43
44
|
end
|
|
44
45
|
end
|