bson 4.7.1-java → 4.8.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -2
  3. data.tar.gz.sig +0 -0
  4. data/README.md +5 -1
  5. data/lib/bson-ruby.jar +0 -0
  6. data/lib/bson.rb +3 -0
  7. data/lib/bson/array.rb +21 -3
  8. data/lib/bson/binary.rb +41 -3
  9. data/lib/bson/boolean.rb +3 -1
  10. data/lib/bson/code.rb +15 -1
  11. data/lib/bson/code_with_scope.rb +17 -3
  12. data/lib/bson/db_pointer.rb +104 -0
  13. data/lib/bson/decimal128.rb +15 -1
  14. data/lib/bson/error.rb +17 -0
  15. data/lib/bson/ext_json.rb +374 -0
  16. data/lib/bson/float.rb +47 -1
  17. data/lib/bson/hash.rb +23 -3
  18. data/lib/bson/int32.rb +21 -1
  19. data/lib/bson/int64.rb +28 -3
  20. data/lib/bson/integer.rb +34 -0
  21. data/lib/bson/max_key.rb +12 -0
  22. data/lib/bson/min_key.rb +12 -0
  23. data/lib/bson/nil_class.rb +3 -1
  24. data/lib/bson/object.rb +27 -0
  25. data/lib/bson/object_id.rb +15 -1
  26. data/lib/bson/regexp.rb +19 -2
  27. data/lib/bson/specialized.rb +3 -1
  28. data/lib/bson/string.rb +3 -1
  29. data/lib/bson/symbol.rb +92 -3
  30. data/lib/bson/time.rb +28 -3
  31. data/lib/bson/timestamp.rb +15 -1
  32. data/lib/bson/undefined.rb +11 -0
  33. data/lib/bson/version.rb +1 -1
  34. data/spec/bson/binary_spec.rb +33 -3
  35. data/spec/bson/ext_json_parse_spec.rb +276 -0
  36. data/spec/bson/float_spec.rb +36 -0
  37. data/spec/bson/hash_spec.rb +70 -0
  38. data/spec/bson/int32_spec.rb +20 -0
  39. data/spec/bson/int64_spec.rb +38 -0
  40. data/spec/bson/integer_spec.rb +26 -0
  41. data/spec/bson/raw_spec.rb +22 -1
  42. data/spec/bson/symbol_raw_spec.rb +45 -0
  43. data/spec/bson/symbol_spec.rb +60 -0
  44. data/spec/{support → runners}/common_driver.rb +0 -0
  45. data/spec/runners/corpus.rb +182 -0
  46. data/spec/{support/corpus.rb → runners/corpus_legacy.rb} +40 -58
  47. data/spec/spec_helper.rb +9 -2
  48. data/spec/{bson/driver_bson_spec.rb → spec_tests/common_driver_spec.rb} +1 -0
  49. data/spec/{bson/corpus_spec.rb → spec_tests/corpus_legacy_spec.rb} +4 -4
  50. data/spec/spec_tests/corpus_spec.rb +124 -0
  51. data/spec/spec_tests/data/corpus/README.md +15 -0
  52. data/spec/spec_tests/data/corpus/array.json +49 -0
  53. data/spec/spec_tests/data/corpus/binary.json +85 -0
  54. data/spec/spec_tests/data/corpus/boolean.json +27 -0
  55. data/spec/spec_tests/data/corpus/code.json +67 -0
  56. data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
  57. data/spec/spec_tests/data/corpus/datetime.json +42 -0
  58. data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
  59. data/spec/spec_tests/data/corpus/dbref.json +31 -0
  60. data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
  61. data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
  62. data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
  63. data/spec/spec_tests/data/corpus/decimal128-4.json +117 -0
  64. data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
  65. data/spec/spec_tests/data/corpus/decimal128-6.json +119 -0
  66. data/spec/spec_tests/data/corpus/decimal128-7.json +323 -0
  67. data/spec/spec_tests/data/corpus/document.json +36 -0
  68. data/spec/spec_tests/data/corpus/double.json +87 -0
  69. data/spec/spec_tests/data/corpus/int32.json +43 -0
  70. data/spec/spec_tests/data/corpus/int64.json +43 -0
  71. data/spec/spec_tests/data/corpus/maxkey.json +12 -0
  72. data/spec/spec_tests/data/corpus/minkey.json +12 -0
  73. data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
  74. data/spec/spec_tests/data/corpus/multi-type.json +11 -0
  75. data/spec/spec_tests/data/corpus/null.json +12 -0
  76. data/spec/spec_tests/data/corpus/oid.json +28 -0
  77. data/spec/spec_tests/data/corpus/regex.json +65 -0
  78. data/spec/spec_tests/data/corpus/string.json +72 -0
  79. data/spec/spec_tests/data/corpus/symbol.json +80 -0
  80. data/spec/spec_tests/data/corpus/timestamp.json +24 -0
  81. data/spec/spec_tests/data/corpus/top.json +240 -0
  82. data/spec/spec_tests/data/corpus/undefined.json +15 -0
  83. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/array.json +0 -0
  84. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/binary.json +0 -0
  85. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/boolean.json +0 -0
  86. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code.json +1 -1
  87. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code_w_scope.json +1 -1
  88. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/document.json +1 -1
  89. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/double.json +1 -1
  90. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/datetime.json +0 -0
  91. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/dbpointer.json +0 -0
  92. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/int64.json +0 -0
  93. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/symbol.json +0 -0
  94. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/int32.json +1 -1
  95. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/maxkey.json +1 -1
  96. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/minkey.json +1 -1
  97. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/null.json +1 -1
  98. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/oid.json +0 -0
  99. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/regex.json +1 -1
  100. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/string.json +0 -0
  101. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/timestamp.json +1 -1
  102. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/top.json +0 -0
  103. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/undefined.json +0 -0
  104. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-1.json +0 -0
  105. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-2.json +0 -0
  106. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-3.json +0 -0
  107. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-4.json +0 -0
  108. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-5.json +0 -0
  109. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-6.json +0 -0
  110. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-7.json +0 -0
  111. metadata +170 -94
  112. metadata.gz.sig +0 -0
@@ -89,19 +89,108 @@ module BSON
89
89
  to_s
90
90
  end
91
91
 
92
+ # Converts this object to a representation directly serializable to
93
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
94
+ #
95
+ # @option options [ true | false ] :relaxed Whether to produce relaxed
96
+ # extended JSON representation.
97
+ #
98
+ # @return [ Hash ] The extended json representation.
99
+ def as_extended_json(**options)
100
+ { "$symbol" => to_s }
101
+ end
102
+
103
+ class Raw
104
+ # Create a BSON Symbol
105
+ #
106
+ # @param [ String | Symbol ] str_or_sym The symbol represented by this
107
+ # object. Can be specified as a Symbol or a String.
108
+ #
109
+ # @see http://bsonspec.org/#/specification
110
+ def initialize(str_or_sym)
111
+ unless str_or_sym.is_a?(String) || str_or_sym.is_a?(Symbol)
112
+ raise ArgumentError, "BSON::Symbol::Raw must be given a symbol or a string, not #{str_or_sym}"
113
+ end
114
+
115
+ @symbol = str_or_sym.to_sym
116
+ end
117
+
118
+ # Get the underlying symbol as a Ruby symbol.
119
+ #
120
+ # @return [ Symbol ] The symbol represented by this BSON object.
121
+ def to_sym
122
+ @symbol
123
+ end
124
+
125
+ # Get the underlying symbol as a Ruby string.
126
+ #
127
+ # @return [ String ] The symbol as a string.
128
+ def to_s
129
+ @symbol.to_s
130
+ end
131
+
132
+ # Check equality of the raw bson symbol against another.
133
+ #
134
+ # @param [ Object ] other The object to check against.
135
+ #
136
+ # @return [ true, false ] If the objects are equal.
137
+ def ==(other)
138
+ return false unless other.is_a?(Raw)
139
+ to_sym == other.to_sym
140
+ end
141
+ alias :eql? :==
142
+
143
+ # Get the symbol as encoded BSON.
144
+ #
145
+ # @raise [ EncodingError ] If the symbol is not UTF-8.
146
+ #
147
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
148
+ #
149
+ # @see http://bsonspec.org/#/specification
150
+ def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
151
+ buffer.put_string(to_s)
152
+ end
153
+
154
+ def bson_type
155
+ Symbol::BSON_TYPE
156
+ end
157
+
158
+ # Converts this object to a representation directly serializable to
159
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
160
+ #
161
+ # This method returns the integer value if relaxed representation is
162
+ # requested, otherwise a $numberLong hash.
163
+ #
164
+ # @option options [ true | false ] :relaxed Whether to produce relaxed
165
+ # extended JSON representation.
166
+ #
167
+ # @return [ Hash | Integer ] The extended json representation.
168
+ def as_extended_json(**options)
169
+ {'$symbol' => to_s}
170
+ end
171
+ end
172
+
92
173
  module ClassMethods
93
174
 
94
175
  # Deserialize a symbol from BSON.
95
176
  #
96
177
  # @param [ ByteBuffer ] buffer The byte buffer.
97
178
  #
98
- # @return [ Regexp ] The decoded symbol.
179
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
180
+ #
181
+ # @return [ Symbol | BSON::Symbol::Raw ] The decoded symbol.
99
182
  #
100
183
  # @see http://bsonspec.org/#/specification
101
184
  #
102
185
  # @since 2.0.0
103
- def from_bson(buffer)
104
- buffer.get_string.intern
186
+ def from_bson(buffer, **options)
187
+ sym = buffer.get_string.intern
188
+
189
+ if options[:mode] == :bson
190
+ Raw.new(sym)
191
+ else
192
+ sym
193
+ end
105
194
  end
106
195
  end
107
196
 
@@ -38,7 +38,30 @@ module BSON
38
38
  #
39
39
  # @since 2.0.0
40
40
  def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
41
- buffer.put_int64((to_i * 1000) + (usec / 1000))
41
+ # A previous version of this method used the following implementation:
42
+ # buffer.put_int64((to_i * 1000) + (usec / 1000))
43
+ # Turns out, usec returned incorrect value - 999 for 1 millisecond.
44
+ buffer.put_int64((to_f * 1000).round)
45
+ end
46
+
47
+ # Converts this object to a representation directly serializable to
48
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
49
+ #
50
+ # @option options [ true | false ] :relaxed Whether to produce relaxed
51
+ # extended JSON representation.
52
+ #
53
+ # @return [ Hash ] The extended json representation.
54
+ def as_extended_json(**options)
55
+ utc_time = utc
56
+ if options[:mode] == :relaxed && (1970..9999).include?(utc_time.year)
57
+ if utc_time.usec != 0
58
+ {'$date' => utc_time.strftime('%Y-%m-%dT%H:%M:%S.%LZ')}
59
+ else
60
+ {'$date' => utc_time.strftime('%Y-%m-%dT%H:%M:%SZ')}
61
+ end
62
+ else
63
+ {'$date' => {'$numberLong' => (utc_time.to_f * 1000).round.to_s}}
64
+ end
42
65
  end
43
66
 
44
67
  module ClassMethods
@@ -47,13 +70,15 @@ module BSON
47
70
  #
48
71
  # @param [ ByteBuffer ] buffer The byte buffer.
49
72
  #
73
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
74
+ #
50
75
  # @return [ Time ] The decoded UTC datetime.
51
76
  #
52
77
  # @see http://bsonspec.org/#/specification
53
78
  #
54
79
  # @since 2.0.0
55
- def from_bson(buffer)
56
- seconds, fragment = Int64.from_bson(buffer).divmod(1000)
80
+ def from_bson(buffer, **options)
81
+ seconds, fragment = Int64.from_bson(buffer, mode: nil).divmod(1000)
57
82
  at(seconds, fragment * 1000).utc
58
83
  end
59
84
  end
@@ -84,7 +84,19 @@ module BSON
84
84
  # @return [ Hash ] The timestamp as a JSON hash.
85
85
  #
86
86
  # @since 2.0.0
87
+ # @deprecated Use as_extended_json instead.
87
88
  def as_json(*args)
89
+ as_extended_json
90
+ end
91
+
92
+ # Converts this object to a representation directly serializable to
93
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
94
+ #
95
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
96
+ # (default is canonical extended JSON)
97
+ #
98
+ # @return [ Hash ] The extended json representation.
99
+ def as_extended_json(**options)
88
100
  { "$timestamp" => { "t" => seconds, "i" => increment } }
89
101
  end
90
102
 
@@ -120,12 +132,14 @@ module BSON
120
132
  #
121
133
  # @param [ ByteBuffer ] buffer The byte buffer.
122
134
  #
135
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
136
+ #
123
137
  # @return [ Timestamp ] The decoded timestamp.
124
138
  #
125
139
  # @see http://bsonspec.org/#/specification
126
140
  #
127
141
  # @since 2.0.0
128
- def self.from_bson(buffer)
142
+ def self.from_bson(buffer, **options)
129
143
  increment = buffer.get_int32
130
144
  seconds = buffer.get_int32
131
145
  new(seconds, increment)
@@ -41,6 +41,17 @@ module BSON
41
41
  self.class == other.class
42
42
  end
43
43
 
44
+ # Converts this object to a representation directly serializable to
45
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
46
+ #
47
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
48
+ # (default is canonical extended JSON)
49
+ #
50
+ # @return [ Hash ] The extended json representation.
51
+ def as_extended_json(**options)
52
+ { "$undefined" => true }
53
+ end
54
+
44
55
  # Register this type when the module is loaded.
45
56
  #
46
57
  # @since 2.0.0
@@ -13,5 +13,5 @@
13
13
  # limitations under the License.
14
14
 
15
15
  module BSON
16
- VERSION = "4.7.1".freeze
16
+ VERSION = "4.8.0".freeze
17
17
  end
@@ -63,7 +63,7 @@ describe BSON::Binary do
63
63
 
64
64
  it "returns the binary data plus type" do
65
65
  expect(object.as_json).to eq(
66
- { "$binary" => Base64.encode64("testing"), "$type" => :user }
66
+ { "$binary" => {'base64' => Base64.encode64("testing").strip, "subType" => '80' }}
67
67
  )
68
68
  end
69
69
 
@@ -126,12 +126,34 @@ describe BSON::Binary do
126
126
  end
127
127
 
128
128
  describe '#from_bson' do
129
- let(:bson) { BSON::ByteBuffer.new("#{5.to_bson}#{0.chr}hello".force_encoding('BINARY')) }
130
- let(:obj) { described_class.from_bson(bson) }
129
+ let(:buffer) { BSON::ByteBuffer.new(bson) }
130
+ let(:obj) { described_class.from_bson(buffer) }
131
+
132
+ let(:bson) { "#{5.to_bson}#{0.chr}hello".force_encoding('BINARY') }
131
133
 
132
134
  it 'sets data encoding to binary' do
133
135
  expect(obj.data.encoding).to eq(Encoding.find('BINARY'))
134
136
  end
137
+
138
+ context 'when binary subtype is supported' do
139
+ let(:bson) { [3, 0, 0, 0, 1].map(&:chr).join.force_encoding('BINARY') + 'foo' }
140
+
141
+ it 'works' do
142
+ obj.should be_a(described_class)
143
+ obj.type.should be :function
144
+ end
145
+ end
146
+
147
+ context 'when binary subtype is not supported' do
148
+ let(:bson) { [3, 0, 0, 0, 16].map(&:chr).join.force_encoding('BINARY') + 'foo' }
149
+
150
+ it 'raises an exception' do
151
+ lambda do
152
+ obj
153
+ end.should raise_error(BSON::Error::UnsupportedBinarySubtype,
154
+ /BSON data contains unsupported binary subtype 0x10/)
155
+ end
156
+ end
135
157
  end
136
158
 
137
159
  describe "#to_bson/#from_bson" do
@@ -203,6 +225,14 @@ describe BSON::Binary do
203
225
  it_behaves_like "a deserializable bson element"
204
226
  end
205
227
 
228
+ context "when the type is :cyphertext" do
229
+ let(:obj) { described_class.new("testing", :ciphertext) }
230
+ let(:bson) { "#{7.to_bson}#{6.chr}testing" }
231
+
232
+ it_behaves_like "a serializable bson element"
233
+ it_behaves_like "a deserializable bson element"
234
+ end
235
+
206
236
  context 'when given binary string' do
207
237
  let(:obj) { described_class.new("\x00\xfe\xff".force_encoding('BINARY')) }
208
238
  let(:bson) { "#{3.to_bson}#{0.chr}\x00\xfe\xff".force_encoding('BINARY') }
@@ -0,0 +1,276 @@
1
+ # Copyright (C) 2020 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "spec_helper"
16
+
17
+ describe "BSON::ExtJSON.parse" do
18
+
19
+ let(:parsed) { BSON::ExtJSON.parse_obj(input) }
20
+
21
+ context 'when input is true' do
22
+ let(:input) { true }
23
+
24
+ it 'returns true' do
25
+ parsed.should == true
26
+ end
27
+ end
28
+
29
+ context 'when input is false' do
30
+ let(:input) { false }
31
+
32
+ it 'returns false' do
33
+ parsed.should == false
34
+ end
35
+ end
36
+
37
+ context 'when input is nil' do
38
+ let(:input) { nil }
39
+
40
+ it 'returns nil' do
41
+ parsed.should be nil
42
+ end
43
+ end
44
+
45
+ context 'when input is a string' do
46
+ let(:input) { 'hello' }
47
+
48
+ it 'returns the string' do
49
+ parsed.should == 'hello'
50
+ end
51
+ end
52
+
53
+ context 'when input is a timestamp' do
54
+ let(:input) { {'$timestamp' => {'t' => 12345, 'i' => 42}} }
55
+
56
+ it 'returns a timestamp object' do
57
+ parsed.should == BSON::Timestamp.new(12345, 42)
58
+ end
59
+ end
60
+
61
+ context 'when input is an int32' do
62
+ let(:input) do
63
+ {'$numberInt' => '42'}
64
+ end
65
+
66
+ let(:parsed) { BSON::ExtJSON.parse_obj(input, mode: mode) }
67
+
68
+ context 'when :mode is nil' do
69
+ let(:mode) { nil }
70
+
71
+ it 'returns Integer instance' do
72
+ parsed.should be_a(Integer)
73
+ parsed.should == 42
74
+ end
75
+ end
76
+
77
+ context 'when :mode is :bson' do
78
+ let(:mode) { :bson }
79
+
80
+ it 'returns Integer instance' do
81
+ parsed.should be_a(Integer)
82
+ parsed.should == 42
83
+ end
84
+ end
85
+ end
86
+
87
+ context 'when input is an int64' do
88
+ let(:input) do
89
+ {'$numberLong' => '42'}
90
+ end
91
+
92
+ let(:parsed) { BSON::ExtJSON.parse_obj(input, mode: mode) }
93
+
94
+ context 'when :mode is nil' do
95
+ let(:mode) { nil }
96
+
97
+ it 'returns Integer instance' do
98
+ parsed.should be_a(Integer)
99
+ parsed.should == 42
100
+ end
101
+ end
102
+
103
+ context 'when :mode is :bson' do
104
+ let(:mode) { :bson }
105
+
106
+ it 'returns Int64 instance' do
107
+ parsed.should be_a(BSON::Int64)
108
+ parsed.value.should == 42
109
+ end
110
+ end
111
+ end
112
+
113
+ context 'when input is a hash' do
114
+ let(:input) do
115
+ {}
116
+ end
117
+
118
+ let(:parsed) { BSON::ExtJSON.parse_obj(input, mode: mode) }
119
+
120
+ context 'when mode is invalid' do
121
+ let(:mode) { :foo }
122
+
123
+ it 'raises an exception' do
124
+ lambda do
125
+ parsed
126
+ end.should raise_error(ArgumentError, /Invalid value for :mode option/)
127
+ end
128
+ end
129
+ end
130
+
131
+ context 'when input is a binary' do
132
+ let(:data) do
133
+ Base64.decode64("//8=")
134
+ end
135
+
136
+ context 'in current format' do
137
+ let(:input) do
138
+ { "$binary" => { "base64"=>"//8=", "subType"=>"00" } }
139
+ end
140
+
141
+ context 'when :mode is nil' do
142
+ let(:mode) { nil }
143
+
144
+ it 'returns BSON::Binary instance' do
145
+ parsed.should be_a(BSON::Binary)
146
+ parsed.data.should == data
147
+ end
148
+ end
149
+
150
+ context 'when mode is :bson' do
151
+ let(:mode) { :bson }
152
+
153
+ it 'returns BSON::Binary instance' do
154
+ parsed.should be_a(BSON::Binary)
155
+ parsed.data.should == data
156
+ end
157
+ end
158
+ end
159
+
160
+ context 'in legacy format' do
161
+ let(:input) do
162
+ { "$binary"=>"//8=", "$type"=>"00" }
163
+ end
164
+
165
+ context 'when :mode is nil' do
166
+ let(:mode) { nil }
167
+
168
+ it 'returns BSON::Binary instance' do
169
+ parsed.should be_a(BSON::Binary)
170
+ parsed.data.should == data
171
+ end
172
+ end
173
+
174
+ context 'when mode is :bson' do
175
+ let(:mode) { :bson }
176
+
177
+ it 'returns BSON::Binary instance' do
178
+ parsed.should be_a(BSON::Binary)
179
+ parsed.data.should == data
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ context 'when input is a regex' do
186
+ let(:pattern) { 'abc' }
187
+ let(:options) { 'im' }
188
+
189
+ context 'in current format' do
190
+ let(:input) do
191
+ { "$regularExpression" => { "pattern" => pattern, "options" => options } }
192
+ end
193
+
194
+ context 'when :mode is nil' do
195
+ let(:mode) { nil }
196
+
197
+ it 'returns a BSON::Regexp::Raw instance' do
198
+ parsed.should be_a(BSON::Regexp::Raw)
199
+ parsed.pattern.should == pattern
200
+ parsed.options.should == options
201
+ end
202
+ end
203
+
204
+ context 'when :mode is :bson' do
205
+ let(:mode) { :bson }
206
+
207
+ it 'returns a BSON::Regexp::Raw instance' do
208
+ parsed.should be_a(BSON::Regexp::Raw)
209
+ parsed.pattern.should == pattern
210
+ parsed.options.should == options
211
+ end
212
+ end
213
+ end
214
+
215
+ context 'in legacy format' do
216
+ let(:input) do
217
+ { "$regex" => pattern, "$options" => options }
218
+ end
219
+
220
+ context 'when :mode is nil' do
221
+ let(:mode) { nil }
222
+
223
+ it 'returns a BSON::Regexp::Raw instance' do
224
+ parsed.should be_a(BSON::Regexp::Raw)
225
+ parsed.pattern.should == pattern
226
+ parsed.options.should == options
227
+ end
228
+ end
229
+
230
+ context 'when :mode is :bson' do
231
+ let(:mode) { :bson }
232
+
233
+ it 'returns a BSON::Regexp::Raw instance' do
234
+ parsed.should be_a(BSON::Regexp::Raw)
235
+ parsed.pattern.should == pattern
236
+ parsed.options.should == options
237
+ end
238
+ end
239
+ end
240
+
241
+ context 'when $regularExpression is nested in $regex' do
242
+ context 'with options' do
243
+ let(:input) do
244
+ {
245
+ "$regex" => {
246
+ "$regularExpression" => { "pattern" => "foo*", "options" => "" },
247
+ },
248
+ "$options" => "ix",
249
+ }
250
+ end
251
+
252
+ it 'parses' do
253
+ parsed.should == {
254
+ '$regex' => BSON::Regexp::Raw.new('foo*'), '$options' => 'ix'
255
+ }
256
+ end
257
+ end
258
+
259
+ context 'without options' do
260
+ let(:input) do
261
+ {
262
+ "$regex" => {
263
+ "$regularExpression" => { "pattern" => "foo*", "options" => "" },
264
+ },
265
+ }
266
+ end
267
+
268
+ it 'parses' do
269
+ parsed.should == {
270
+ '$regex' => BSON::Regexp::Raw.new('foo*'),
271
+ }
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end