bson 1.12.5-java → 2.0.0-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bson might be problematic. Click here for more details.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +80 -0
- data/CONTRIBUTING.md +42 -0
- data/NOTICE +2 -0
- data/README.md +190 -0
- data/Rakefile +109 -0
- data/lib/bson-ruby.jar +0 -0
- data/lib/bson.rb +60 -87
- data/lib/bson/array.rb +104 -0
- data/lib/bson/binary.rb +193 -0
- data/lib/bson/boolean.rb +48 -0
- data/lib/bson/code.rb +109 -0
- data/lib/bson/code_with_scope.rb +120 -0
- data/lib/bson/document.rb +549 -0
- data/lib/bson/encodable.rb +86 -0
- data/lib/bson/environment.rb +98 -0
- data/lib/bson/false_class.rb +61 -0
- data/lib/bson/float.rb +82 -0
- data/lib/bson/hash.rb +84 -0
- data/lib/bson/int32.rb +59 -0
- data/lib/bson/int64.rb +59 -0
- data/lib/bson/integer.rb +185 -0
- data/lib/bson/json.rb +37 -0
- data/lib/bson/max_key.rb +70 -0
- data/lib/bson/min_key.rb +70 -0
- data/lib/bson/nil_class.rb +70 -0
- data/lib/bson/object_id.rb +395 -0
- data/lib/bson/regexp.rb +124 -0
- data/lib/bson/registry.rb +70 -0
- data/lib/bson/specialized.rb +74 -0
- data/lib/bson/string.rb +203 -0
- data/lib/bson/symbol.rb +87 -0
- data/lib/bson/time.rb +72 -0
- data/lib/bson/timestamp.rb +113 -0
- data/lib/bson/true_class.rb +61 -0
- data/lib/bson/undefined.rb +74 -0
- data/lib/bson/version.rb +17 -0
- data/spec/bson/array_spec.rb +58 -0
- data/spec/bson/binary_spec.rb +115 -0
- data/spec/bson/boolean_spec.rb +48 -0
- data/spec/bson/code_spec.rb +42 -0
- data/spec/bson/code_with_scope_spec.rb +74 -0
- data/spec/bson/document_spec.rb +778 -0
- data/spec/bson/false_class_spec.rb +28 -0
- data/spec/bson/float_spec.rb +29 -0
- data/spec/bson/hash_spec.rb +56 -0
- data/spec/bson/int32_spec.rb +28 -0
- data/spec/bson/int64_spec.rb +28 -0
- data/spec/bson/integer_spec.rb +76 -0
- data/spec/bson/json_spec.rb +53 -0
- data/spec/bson/max_key_spec.rb +75 -0
- data/spec/bson/min_key_spec.rb +75 -0
- data/spec/bson/nil_class_spec.rb +29 -0
- data/spec/bson/object_id_spec.rb +527 -0
- data/spec/bson/regexp_spec.rb +89 -0
- data/spec/bson/registry_spec.rb +55 -0
- data/spec/bson/string_spec.rb +298 -0
- data/spec/bson/symbol_spec.rb +55 -0
- data/spec/bson/time_spec.rb +43 -0
- data/spec/bson/timestamp_spec.rb +74 -0
- data/spec/bson/true_class_spec.rb +28 -0
- data/spec/bson/undefined_spec.rb +29 -0
- data/{lib/bson/types/dbref.rb → spec/bson_spec.rb} +22 -16
- data/spec/spec_helper.rb +32 -0
- data/spec/support/shared_examples.rb +95 -0
- metadata +116 -48
- metadata.gz.sig +1 -1
- data/VERSION +0 -1
- data/bin/b2json +0 -63
- data/bin/j2bson +0 -64
- data/bson.gemspec +0 -34
- data/ext/jbson/lib/java-bson.jar +0 -0
- data/ext/jbson/target/jbson.jar +0 -0
- data/lib/bson/bson_c.rb +0 -37
- data/lib/bson/bson_java.rb +0 -49
- data/lib/bson/bson_ruby.rb +0 -645
- data/lib/bson/byte_buffer.rb +0 -241
- data/lib/bson/exceptions.rb +0 -37
- data/lib/bson/grow.rb +0 -173
- data/lib/bson/ordered_hash.rb +0 -197
- data/lib/bson/support/hash_with_indifferent_access.rb +0 -174
- data/lib/bson/types/binary.rb +0 -52
- data/lib/bson/types/code.rb +0 -55
- data/lib/bson/types/min_max_keys.rb +0 -56
- data/lib/bson/types/object_id.rb +0 -226
- data/lib/bson/types/regex.rb +0 -116
- data/lib/bson/types/timestamp.rb +0 -72
@@ -0,0 +1,42 @@
|
|
1
|
+
# Copyright (C) 2009-2013 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::Code do
|
18
|
+
|
19
|
+
describe "#as_json" do
|
20
|
+
|
21
|
+
let(:object) do
|
22
|
+
described_class.new("this.value = 5")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns the binary data plus type" do
|
26
|
+
expect(object.as_json).to eq({ "$code" => "this.value = 5" })
|
27
|
+
end
|
28
|
+
|
29
|
+
it_behaves_like "a JSON serializable object"
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#to_bson/#from_bson" do
|
33
|
+
|
34
|
+
let(:type) { 13.chr }
|
35
|
+
let(:obj) { described_class.new("this.value = 5") }
|
36
|
+
let(:bson) { "#{15.to_bson}this.value = 5#{BSON::NULL_BYTE}" }
|
37
|
+
|
38
|
+
it_behaves_like "a bson element"
|
39
|
+
it_behaves_like "a serializable bson element"
|
40
|
+
it_behaves_like "a deserializable bson element"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright (C) 2009-2013 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::CodeWithScope do
|
18
|
+
|
19
|
+
describe "#as_json" do
|
20
|
+
|
21
|
+
let(:object) do
|
22
|
+
described_class.new("this.value = val", :val => "test")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns the binary data plus type" do
|
26
|
+
expect(object.as_json).to eq(
|
27
|
+
{ "$code" => "this.value = val", "$scope" => { :val => "test" }}
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
it_behaves_like "a JSON serializable object"
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#to_bson" do
|
35
|
+
|
36
|
+
let(:type) { 15.chr }
|
37
|
+
let(:code) { "this.value == name" }
|
38
|
+
let(:scope) do
|
39
|
+
{ :name => "test" }
|
40
|
+
end
|
41
|
+
let(:obj) { described_class.new(code, scope) }
|
42
|
+
let(:bson) do
|
43
|
+
"#{47.to_bson}#{(code.length + 1).to_bson}#{code}#{BSON::NULL_BYTE}" +
|
44
|
+
"#{scope.to_bson}"
|
45
|
+
end
|
46
|
+
|
47
|
+
it_behaves_like "a bson element"
|
48
|
+
it_behaves_like "a serializable bson element"
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#from_bson" do
|
52
|
+
|
53
|
+
let(:type) { 15.chr }
|
54
|
+
let(:code) { "this.value == name" }
|
55
|
+
let(:scope) do
|
56
|
+
{ "name" => "test" }
|
57
|
+
end
|
58
|
+
let(:obj) { described_class.new(code, scope) }
|
59
|
+
let(:bson) { StringIO.new(obj.to_bson) }
|
60
|
+
let!(:deserialized) { described_class.from_bson(bson) }
|
61
|
+
|
62
|
+
it "deserializes the javascript" do
|
63
|
+
expect(deserialized.javascript).to eq(code)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "deserializes the scope" do
|
67
|
+
expect(deserialized.scope).to eq(scope)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "does not leave any extra bytes" do
|
71
|
+
expect(bson.read(1)).to be_nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,778 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (C) 2009-2013 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::Document do
|
20
|
+
|
21
|
+
let(:keys) { %w(blue green red pink orange) }
|
22
|
+
let(:vals) { %w(000099 009900 aa0000 cc0066 cc6633) }
|
23
|
+
let(:doc) { described_class.new }
|
24
|
+
let(:hash) do
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
let(:enum_class) do
|
28
|
+
BSON::Environment.ruby_18? ? Enumerable::Enumerator : Enumerator
|
29
|
+
end
|
30
|
+
|
31
|
+
before do
|
32
|
+
keys.each_with_index do |key, index|
|
33
|
+
hash[key] = vals[index]
|
34
|
+
doc[key] = vals[index]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#keys" do
|
39
|
+
|
40
|
+
it "retains the insertion order" do
|
41
|
+
expect(doc.keys).to eq(keys)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#values" do
|
46
|
+
|
47
|
+
it "retains the insertion order" do
|
48
|
+
expect(doc.values).to eq(vals)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#[]" do
|
53
|
+
|
54
|
+
let(:document) do
|
55
|
+
described_class["key", "value", "key2", "value"]
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when provided string keys" do
|
59
|
+
|
60
|
+
it "returns the value" do
|
61
|
+
expect(document["key"]).to eq("value")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when provided symbol keys" do
|
66
|
+
|
67
|
+
it "returns the value" do
|
68
|
+
expect(document[:key]).to eq("value")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#[]=" do
|
74
|
+
|
75
|
+
let(:key) { "purple" }
|
76
|
+
let(:val) { "5422a8" }
|
77
|
+
|
78
|
+
before do
|
79
|
+
doc[key] = val
|
80
|
+
end
|
81
|
+
|
82
|
+
it "updates the length" do
|
83
|
+
expect(doc.length).to eq(keys.length + 1)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "adds the key to the end" do
|
87
|
+
expect(doc.keys.last).to eq(key)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "adds the value to the end" do
|
91
|
+
expect(doc.values.last).to eq(val)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "sets the value" do
|
95
|
+
expect(doc[key]).to eq(val)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#delete" do
|
100
|
+
|
101
|
+
let(:key) { "white" }
|
102
|
+
let(:val) { "ffffff" }
|
103
|
+
let(:bad_key) { "black" }
|
104
|
+
|
105
|
+
before do
|
106
|
+
doc[key] = val
|
107
|
+
end
|
108
|
+
|
109
|
+
let!(:deleted) { doc.delete(key) }
|
110
|
+
|
111
|
+
it "returns the deleted value" do
|
112
|
+
expect(deleted).to eq(val)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "removes the key from the list" do
|
116
|
+
expect(doc.keys.length).to eq(keys.length)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "matches the keys length to the document length" do
|
120
|
+
expect(doc.length).to eq(doc.keys.length)
|
121
|
+
end
|
122
|
+
|
123
|
+
context "when removind a bad key" do
|
124
|
+
|
125
|
+
it "returns nil" do
|
126
|
+
expect(doc.delete(bad_key)).to be_nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#to_hash" do
|
132
|
+
|
133
|
+
it "returns the document" do
|
134
|
+
expect(doc.to_hash).to eq(doc)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#to_a" do
|
139
|
+
|
140
|
+
it "returns the key/value pairs as an array" do
|
141
|
+
expect(doc.to_a).to eq(keys.zip(vals))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
[ :has_key?, :key?, :include?, :member? ].each do |method|
|
146
|
+
|
147
|
+
describe "##{method}" do
|
148
|
+
|
149
|
+
context "when the key exists" do
|
150
|
+
|
151
|
+
it "returns true" do
|
152
|
+
expect(doc.send(method, "blue")).to be_true
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when the key does not exist" do
|
157
|
+
|
158
|
+
it "returns false" do
|
159
|
+
expect(doc.send(method, "indigo")).to be_false
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
[ :has_value?, :value? ].each do |method|
|
166
|
+
|
167
|
+
describe "##{method}" do
|
168
|
+
|
169
|
+
context "when the value exists" do
|
170
|
+
|
171
|
+
it "returns true" do
|
172
|
+
expect(doc.send(method, "000099")).to be_true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "when the value does not exist" do
|
177
|
+
|
178
|
+
it "returns false" do
|
179
|
+
expect(doc.send(method, "ABCABC")).to be_false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "#each_key" do
|
186
|
+
|
187
|
+
let(:iter_keys) {[]}
|
188
|
+
|
189
|
+
context "when passed a block" do
|
190
|
+
|
191
|
+
let!(:enum) do
|
192
|
+
doc.each_key{ |k| iter_keys << k }
|
193
|
+
end
|
194
|
+
|
195
|
+
it "returns the document" do
|
196
|
+
expect(enum).to equal(doc)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "iterates over each of the keys" do
|
200
|
+
expect(iter_keys).to eq(keys)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context "when not passed a block" do
|
205
|
+
|
206
|
+
let!(:enum) do
|
207
|
+
doc.each_key
|
208
|
+
end
|
209
|
+
|
210
|
+
it "returns an enumerator" do
|
211
|
+
expect(enum).to be_a(enum_class)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "#each_value" do
|
217
|
+
|
218
|
+
let(:iter_vals) {[]}
|
219
|
+
|
220
|
+
context "when passed a block" do
|
221
|
+
|
222
|
+
let!(:enum) do
|
223
|
+
doc.each_value{ |v| iter_vals << v }
|
224
|
+
end
|
225
|
+
|
226
|
+
it "returns the document" do
|
227
|
+
expect(enum).to equal(doc)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "iterates over each of the vals" do
|
231
|
+
expect(iter_vals).to eq(vals)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context "when not passed a block" do
|
236
|
+
|
237
|
+
let!(:enum) do
|
238
|
+
doc.each_value
|
239
|
+
end
|
240
|
+
|
241
|
+
it "returns an enumerator" do
|
242
|
+
expect(enum).to be_a(enum_class)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
[ :each, :each_pair ].each do |method|
|
248
|
+
|
249
|
+
describe "##{method}" do
|
250
|
+
|
251
|
+
let(:iter_keys) {[]}
|
252
|
+
let(:iter_vals) {[]}
|
253
|
+
|
254
|
+
context "when passed a block" do
|
255
|
+
|
256
|
+
let!(:enum) do
|
257
|
+
doc.send(method) do |k, v|
|
258
|
+
iter_keys << k
|
259
|
+
iter_vals << v
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
it "returns the document" do
|
264
|
+
expect(enum).to equal(doc)
|
265
|
+
end
|
266
|
+
|
267
|
+
it "iterates over each of the keys" do
|
268
|
+
expect(iter_keys).to eq(keys)
|
269
|
+
end
|
270
|
+
|
271
|
+
it "iterates over each of the vals" do
|
272
|
+
expect(iter_vals).to eq(vals)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context "when not passed a block" do
|
277
|
+
|
278
|
+
let!(:enum) do
|
279
|
+
doc.send(method)
|
280
|
+
end
|
281
|
+
|
282
|
+
it "returns an enumerator" do
|
283
|
+
expect(enum).to be_a(enum_class)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
context "when the document has been serialized" do
|
288
|
+
|
289
|
+
let(:deserialized) do
|
290
|
+
YAML.load(YAML.dump(doc))
|
291
|
+
end
|
292
|
+
|
293
|
+
let!(:enum) do
|
294
|
+
deserialized.send(method) do |k, v|
|
295
|
+
iter_keys << k
|
296
|
+
iter_vals << v
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
it "iterates over each of the keys" do
|
301
|
+
expect(iter_keys).to eq(keys)
|
302
|
+
end
|
303
|
+
|
304
|
+
it "iterates over each of the vals" do
|
305
|
+
expect(iter_vals).to eq(vals)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "#each_with_index" do
|
312
|
+
|
313
|
+
it "iterates over the document passing an index" do
|
314
|
+
doc.each_with_index do |pair, index|
|
315
|
+
expect(pair).to eq([ keys[index], vals[index] ])
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
describe "#find_all" do
|
321
|
+
|
322
|
+
it "iterates in the correct order" do
|
323
|
+
expect(doc.find_all{ true }.map(&:first)).to eq(keys)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
describe "#select" do
|
328
|
+
|
329
|
+
it "iterates in the correct order" do
|
330
|
+
expect(doc.select{ true }.map(&:first)).to eq(keys)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
[ :delete_if, :reject! ].each do |method|
|
335
|
+
|
336
|
+
describe "##{method}" do
|
337
|
+
|
338
|
+
let(:copy) { doc.dup }
|
339
|
+
|
340
|
+
before do
|
341
|
+
copy.delete("pink")
|
342
|
+
end
|
343
|
+
|
344
|
+
let!(:deleted) do
|
345
|
+
doc.send(method){ |k, _| k == "pink" }
|
346
|
+
end
|
347
|
+
|
348
|
+
it "deletes elements for which the block is true" do
|
349
|
+
expect(deleted).to eq(copy)
|
350
|
+
end
|
351
|
+
|
352
|
+
it "deletes the matching keys from the document" do
|
353
|
+
expect(doc.keys).to_not include("pink")
|
354
|
+
end
|
355
|
+
|
356
|
+
it "returns the same document" do
|
357
|
+
expect(deleted).to equal(doc)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe "#reject" do
|
363
|
+
|
364
|
+
let(:copy) { doc.dup }
|
365
|
+
|
366
|
+
before do
|
367
|
+
copy.delete("pink")
|
368
|
+
end
|
369
|
+
|
370
|
+
let!(:deleted) do
|
371
|
+
doc.reject{ |k, _| k == "pink" }
|
372
|
+
end
|
373
|
+
|
374
|
+
it "deletes elements for which the block is true" do
|
375
|
+
expect(deleted).to eq(copy)
|
376
|
+
end
|
377
|
+
|
378
|
+
it "deletes the matching keys from the new document" do
|
379
|
+
expect(deleted.keys).to_not include("pink")
|
380
|
+
end
|
381
|
+
|
382
|
+
it "returns a new document" do
|
383
|
+
expect(deleted).to_not equal(doc)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
describe "#clear" do
|
388
|
+
|
389
|
+
before do
|
390
|
+
doc.clear
|
391
|
+
end
|
392
|
+
|
393
|
+
it "clears out the keys" do
|
394
|
+
expect(doc.keys).to be_empty
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
describe "#merge" do
|
399
|
+
|
400
|
+
let(:other) { described_class.new }
|
401
|
+
|
402
|
+
context "when passed no block" do
|
403
|
+
|
404
|
+
before do
|
405
|
+
other["purple"] = "800080"
|
406
|
+
other["violet"] = "ee82ee"
|
407
|
+
end
|
408
|
+
|
409
|
+
let!(:merged) do
|
410
|
+
doc.merge(other)
|
411
|
+
end
|
412
|
+
|
413
|
+
it "merges the keys" do
|
414
|
+
expect(merged.keys).to eq(keys + [ "purple", "violet" ])
|
415
|
+
end
|
416
|
+
|
417
|
+
it "adds to the length" do
|
418
|
+
expect(merged.length).to eq(doc.length + other.length)
|
419
|
+
end
|
420
|
+
|
421
|
+
it "returns a new document" do
|
422
|
+
expect(merged).to_not equal(doc)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
context "when passed a block" do
|
427
|
+
|
428
|
+
before do
|
429
|
+
other[:a] = 0
|
430
|
+
other[:b] = 0
|
431
|
+
end
|
432
|
+
|
433
|
+
let(:merged) do
|
434
|
+
other.merge(:b => 2, :c => 7) do |key, old_val, new_val|
|
435
|
+
new_val + 1
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
it "executes the block on each merged element" do
|
440
|
+
expect(merged[:a]).to eq(0)
|
441
|
+
expect(merged[:b]).to eq(3)
|
442
|
+
expect(merged[:c]).to eq(7)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe "#merge!" do
|
448
|
+
|
449
|
+
let(:other) { described_class.new }
|
450
|
+
|
451
|
+
context "when passed no block" do
|
452
|
+
|
453
|
+
before do
|
454
|
+
other["purple"] = "800080"
|
455
|
+
other["violet"] = "ee82ee"
|
456
|
+
end
|
457
|
+
|
458
|
+
let(:merged) do
|
459
|
+
doc.merge!(other)
|
460
|
+
end
|
461
|
+
|
462
|
+
it "merges the keys" do
|
463
|
+
expect(merged.keys).to eq(keys + [ "purple", "violet" ])
|
464
|
+
end
|
465
|
+
|
466
|
+
it "adds to the length" do
|
467
|
+
expect(merged.length).to eq(doc.length)
|
468
|
+
end
|
469
|
+
|
470
|
+
it "returns the same document" do
|
471
|
+
expect(merged).to equal(doc)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context "when passed a block" do
|
476
|
+
|
477
|
+
before do
|
478
|
+
other[:a] = 0
|
479
|
+
other[:b] = 0
|
480
|
+
end
|
481
|
+
|
482
|
+
let!(:merged) do
|
483
|
+
other.merge!(:b => 2, :c => 7) do |key, old_val, new_val|
|
484
|
+
new_val + 1
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
it "executes the block on each merged element" do
|
489
|
+
expect(other[:a]).to eq(0)
|
490
|
+
expect(other[:b]).to eq(3)
|
491
|
+
expect(other[:c]).to eq(7)
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
describe "#shift" do
|
497
|
+
|
498
|
+
let(:pair) do
|
499
|
+
doc.shift
|
500
|
+
end
|
501
|
+
|
502
|
+
it "returns the first pair in the document" do
|
503
|
+
expect(pair).to eq([ keys.first, vals.first ])
|
504
|
+
end
|
505
|
+
|
506
|
+
it "removes the pair from the document" do
|
507
|
+
expect(doc.keys).to_not eq(pair.first)
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
describe "#inspect" do
|
512
|
+
|
513
|
+
it "includes the hash inspect" do
|
514
|
+
expect(doc.inspect).to include(hash.inspect)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
describe "#initialize" do
|
519
|
+
|
520
|
+
context "when provided for splat args" do
|
521
|
+
|
522
|
+
context "when an even number of args" do
|
523
|
+
|
524
|
+
let(:alternate) do
|
525
|
+
described_class[1, 2, 3, 4]
|
526
|
+
end
|
527
|
+
|
528
|
+
it "treats the arguments are an array" do
|
529
|
+
expect(alternate.keys).to eq([ 1, 3 ])
|
530
|
+
end
|
531
|
+
|
532
|
+
it "instantiates a document" do
|
533
|
+
expect(alternate).to be_a(BSON::Document)
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
context "when an odd number of arguments" do
|
538
|
+
|
539
|
+
it "raises an argument error" do
|
540
|
+
expect {
|
541
|
+
described_class[1, 2, 3]
|
542
|
+
}.to raise_error(ArgumentError)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
context "when provided an array" do
|
548
|
+
|
549
|
+
let(:alternate) do
|
550
|
+
described_class[[[ 1, 2 ], [ 3, 4 ], [ "missing" ]]]
|
551
|
+
end
|
552
|
+
|
553
|
+
it "sets the keys" do
|
554
|
+
expect(alternate.keys).to eq([ 1, 3, "missing" ])
|
555
|
+
end
|
556
|
+
|
557
|
+
it "sets the values" do
|
558
|
+
expect(alternate.values).to eq([ 2, 4, nil ])
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
if BSON::Environment.retaining_hash_order?
|
563
|
+
|
564
|
+
context "when provided hashes" do
|
565
|
+
|
566
|
+
let(:alternate) do
|
567
|
+
described_class[1 => 2, 3 => 4]
|
568
|
+
end
|
569
|
+
|
570
|
+
it "sets the keys" do
|
571
|
+
expect(alternate.keys).to eq([ 1, 3 ])
|
572
|
+
end
|
573
|
+
|
574
|
+
it "sets the values" do
|
575
|
+
expect(alternate.values).to eq([ 2, 4 ])
|
576
|
+
end
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
581
|
+
describe "#replace" do
|
582
|
+
|
583
|
+
let(:other) do
|
584
|
+
described_class[:black, "000000", :white, "000000"]
|
585
|
+
end
|
586
|
+
|
587
|
+
let!(:original) { doc.replace(other) }
|
588
|
+
|
589
|
+
it "replaces the keys" do
|
590
|
+
expect(doc.keys).to eq(other.keys)
|
591
|
+
end
|
592
|
+
|
593
|
+
it "returns the document" do
|
594
|
+
expect(original).to eq(doc)
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
describe "#update" do
|
599
|
+
|
600
|
+
let(:updated) { described_class.new }
|
601
|
+
|
602
|
+
before do
|
603
|
+
updated.update(:name => "Bob")
|
604
|
+
end
|
605
|
+
|
606
|
+
it "updates the keys" do
|
607
|
+
expect(updated.keys).to eq([ :name ])
|
608
|
+
end
|
609
|
+
|
610
|
+
it "updates the values" do
|
611
|
+
expect(updated.values).to eq([ "Bob" ])
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
describe "#invert" do
|
616
|
+
|
617
|
+
let(:expected) do
|
618
|
+
described_class[vals.zip(keys)]
|
619
|
+
end
|
620
|
+
|
621
|
+
it "inverts the hash in inverse order" do
|
622
|
+
expect(doc.invert).to eq(expected)
|
623
|
+
end
|
624
|
+
|
625
|
+
it "inverts the keys" do
|
626
|
+
expect(vals.zip(keys)).to eq(doc.invert.to_a)
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
describe "#to_bson/#from_bson" do
|
631
|
+
|
632
|
+
let(:type) { 3.chr }
|
633
|
+
|
634
|
+
it_behaves_like "a bson element"
|
635
|
+
|
636
|
+
context "when the hash is a single level" do
|
637
|
+
|
638
|
+
let(:obj) do
|
639
|
+
described_class["key","value"]
|
640
|
+
end
|
641
|
+
|
642
|
+
let(:bson) do
|
643
|
+
"#{20.to_bson}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" +
|
644
|
+
"#{6.to_bson}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}"
|
645
|
+
end
|
646
|
+
|
647
|
+
it_behaves_like "a serializable bson element"
|
648
|
+
it_behaves_like "a deserializable bson element"
|
649
|
+
end
|
650
|
+
|
651
|
+
context "when the hash is embedded" do
|
652
|
+
|
653
|
+
let(:obj) do
|
654
|
+
described_class["field", BSON::Document["key", "value"]]
|
655
|
+
end
|
656
|
+
|
657
|
+
let(:bson) do
|
658
|
+
"#{32.to_bson}#{Hash::BSON_TYPE}field#{BSON::NULL_BYTE}" +
|
659
|
+
"#{20.to_bson}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" +
|
660
|
+
"#{6.to_bson}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}"
|
661
|
+
end
|
662
|
+
|
663
|
+
it_behaves_like "a serializable bson element"
|
664
|
+
it_behaves_like "a deserializable bson element"
|
665
|
+
|
666
|
+
let(:raw) do
|
667
|
+
StringIO.new(bson)
|
668
|
+
end
|
669
|
+
|
670
|
+
it "returns an instance of a BSON::Document" do
|
671
|
+
expect(described_class.from_bson(raw)).to be_a(BSON::Document)
|
672
|
+
end
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
context "when encoding and decoding" do
|
677
|
+
|
678
|
+
context "when the keys are utf-8" do
|
679
|
+
|
680
|
+
let(:document) do
|
681
|
+
described_class["gültig", "type"]
|
682
|
+
end
|
683
|
+
|
684
|
+
it_behaves_like "a document able to handle utf-8"
|
685
|
+
end
|
686
|
+
|
687
|
+
context "when the values are utf-8" do
|
688
|
+
|
689
|
+
let(:document) do
|
690
|
+
described_class["type", "gültig"]
|
691
|
+
end
|
692
|
+
|
693
|
+
it_behaves_like "a document able to handle utf-8"
|
694
|
+
end
|
695
|
+
|
696
|
+
context "when both the keys and values are utf-8" do
|
697
|
+
|
698
|
+
let(:document) do
|
699
|
+
described_class["gültig", "gültig"]
|
700
|
+
end
|
701
|
+
|
702
|
+
it_behaves_like "a document able to handle utf-8"
|
703
|
+
end
|
704
|
+
|
705
|
+
context "when the regexps are utf-8" do
|
706
|
+
|
707
|
+
let(:document) do
|
708
|
+
described_class["type", /^gültig/]
|
709
|
+
end
|
710
|
+
|
711
|
+
it_behaves_like "a document able to handle utf-8"
|
712
|
+
end
|
713
|
+
|
714
|
+
context "when the symbols are utf-8" do
|
715
|
+
|
716
|
+
let(:document) do
|
717
|
+
described_class["type", "gültig".to_sym]
|
718
|
+
end
|
719
|
+
|
720
|
+
it_behaves_like "a document able to handle utf-8"
|
721
|
+
end
|
722
|
+
|
723
|
+
context "when utf-8 string values are in an array" do
|
724
|
+
|
725
|
+
let(:document) do
|
726
|
+
described_class["type", ["gültig"]]
|
727
|
+
end
|
728
|
+
|
729
|
+
it_behaves_like "a document able to handle utf-8"
|
730
|
+
end
|
731
|
+
|
732
|
+
context "when utf-8 code values are present" do
|
733
|
+
|
734
|
+
let(:document) do
|
735
|
+
described_class["code", BSON::Code.new("// gültig")]
|
736
|
+
end
|
737
|
+
|
738
|
+
it_behaves_like "a document able to handle utf-8"
|
739
|
+
end
|
740
|
+
|
741
|
+
pending "when utf-8 code with scope values are present" do
|
742
|
+
|
743
|
+
let(:document) do
|
744
|
+
described_class["code", BSON::CodeWithScope.new("// gültig", {})]
|
745
|
+
end
|
746
|
+
|
747
|
+
it_behaves_like "a document able to handle utf-8"
|
748
|
+
end
|
749
|
+
|
750
|
+
context "when non utf-8 values exist" do
|
751
|
+
|
752
|
+
let(:string) { "gültig" }
|
753
|
+
let(:document) do
|
754
|
+
described_class["type", string.encode("iso-8859-1")]
|
755
|
+
end
|
756
|
+
|
757
|
+
it "encodes and decodes the document properly" do
|
758
|
+
expect(
|
759
|
+
BSON::Document.from_bson(StringIO.new(document.to_bson))
|
760
|
+
).to eq({ "type" => string })
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
context "when binary strings with utf-8 values exist" do
|
765
|
+
|
766
|
+
let(:string) { "europäischen" }
|
767
|
+
let(:document) do
|
768
|
+
described_class["type", string.encode("binary", "binary")]
|
769
|
+
end
|
770
|
+
|
771
|
+
it "encodes and decodes the document properly" do
|
772
|
+
expect(
|
773
|
+
BSON::Document.from_bson(StringIO.new(document.to_bson))
|
774
|
+
).to eq({ "type" => string })
|
775
|
+
end
|
776
|
+
end
|
777
|
+
end
|
778
|
+
end
|