bson 4.9.0 → 4.15.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +15 -6
- data/ext/bson/bson-native.h +4 -0
- data/ext/bson/init.c +75 -23
- data/ext/bson/read.c +63 -11
- data/ext/bson/write.c +42 -3
- data/lib/bson/active_support.rb +1 -0
- data/lib/bson/array.rb +5 -1
- data/lib/bson/big_decimal.rb +67 -0
- data/lib/bson/binary.rb +8 -5
- data/lib/bson/boolean.rb +2 -1
- data/lib/bson/code.rb +2 -1
- data/lib/bson/code_with_scope.rb +2 -1
- data/lib/bson/config.rb +1 -0
- data/lib/bson/date.rb +1 -0
- data/lib/bson/date_time.rb +2 -1
- data/lib/bson/db_pointer.rb +2 -1
- data/lib/bson/dbref.rb +152 -0
- data/lib/bson/decimal128/builder.rb +27 -20
- data/lib/bson/decimal128.rb +39 -14
- data/lib/bson/document.rb +61 -18
- data/lib/bson/environment.rb +1 -0
- data/lib/bson/error.rb +13 -0
- data/lib/bson/ext_json.rb +24 -11
- data/lib/bson/false_class.rb +2 -1
- data/lib/bson/float.rb +21 -32
- data/lib/bson/hash.rb +18 -6
- data/lib/bson/int32.rb +3 -2
- data/lib/bson/int64.rb +3 -2
- data/lib/bson/integer.rb +3 -2
- data/lib/bson/json.rb +1 -0
- data/lib/bson/max_key.rb +3 -2
- data/lib/bson/min_key.rb +3 -2
- data/lib/bson/nil_class.rb +2 -1
- data/lib/bson/object.rb +1 -0
- data/lib/bson/object_id.rb +4 -3
- data/lib/bson/open_struct.rb +1 -0
- data/lib/bson/regexp.rb +24 -7
- data/lib/bson/registry.rb +1 -0
- data/lib/bson/specialized.rb +1 -0
- data/lib/bson/string.rb +3 -2
- data/lib/bson/symbol.rb +2 -1
- data/lib/bson/time.rb +4 -3
- data/lib/bson/time_with_zone.rb +1 -0
- data/lib/bson/timestamp.rb +7 -6
- data/lib/bson/true_class.rb +2 -1
- data/lib/bson/undefined.rb +2 -1
- data/lib/bson/version.rb +2 -1
- data/lib/bson.rb +8 -5
- data/spec/README.md +14 -0
- data/spec/bson/array_spec.rb +17 -0
- data/spec/bson/big_decimal_spec.rb +316 -0
- data/spec/bson/binary_spec.rb +1 -1
- data/spec/bson/binary_uuid_spec.rb +12 -0
- data/spec/bson/byte_buffer_read_spec.rb +59 -3
- data/spec/bson/byte_buffer_spec.rb +129 -6
- data/spec/bson/byte_buffer_write_spec.rb +96 -0
- data/spec/bson/date_time_spec.rb +53 -0
- data/spec/bson/dbref_legacy_spec.rb +169 -0
- data/spec/bson/dbref_spec.rb +487 -0
- data/spec/bson/decimal128_spec.rb +231 -0
- data/spec/bson/document_as_spec.rb +46 -0
- data/spec/bson/document_spec.rb +43 -1
- data/spec/bson/ext_json_parse_spec.rb +37 -0
- data/spec/bson/hash_as_spec.rb +57 -0
- data/spec/bson/hash_spec.rb +105 -0
- data/spec/bson/int64_spec.rb +4 -24
- data/spec/bson/raw_spec.rb +18 -1
- data/spec/bson/regexp_spec.rb +52 -0
- data/spec/runners/common_driver.rb +1 -1
- 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 +386 -0
- data/spec/shared/lib/mrss/docker_runner.rb +271 -0
- data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +120 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +338 -0
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/distro.sh +74 -0
- data/spec/shared/shlib/server.sh +367 -0
- data/spec/shared/shlib/set_env.sh +131 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/spec_tests/common_driver_spec.rb +2 -1
- data/spec/spec_tests/data/corpus/binary.json +33 -0
- data/spec/spec_tests/data/corpus/dbref.json +21 -1
- data/spec/spec_tests/data/corpus/document.json +4 -0
- data/spec/spec_tests/data/corpus/regex.json +2 -2
- data/spec/spec_tests/data/corpus/timestamp.json +10 -0
- data/spec/spec_tests/data/corpus/top.json +23 -12
- data/spec/support/spec_config.rb +8 -1
- data.tar.gz.sig +0 -0
- metadata +168 -93
- metadata.gz.sig +1 -0
@@ -309,6 +309,22 @@ describe BSON::Decimal128 do
|
|
309
309
|
it_behaves_like 'an initialized BSON::Decimal128'
|
310
310
|
end
|
311
311
|
end
|
312
|
+
|
313
|
+
context 'when range is exceeded' do
|
314
|
+
it 'raises InvalidRange' do
|
315
|
+
lambda do
|
316
|
+
described_class.new('1e10000')
|
317
|
+
end.should raise_error(BSON::Decimal128::InvalidRange, /Value out of range/)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
context 'when precision is exceeded' do
|
322
|
+
it 'raises UnrepresentablePrecision' do
|
323
|
+
lambda do
|
324
|
+
described_class.new('1.000000000000000000000000000000000000000000000000001')
|
325
|
+
end.should raise_error(BSON::Decimal128::UnrepresentablePrecision, /The value contains too much precision/)
|
326
|
+
end
|
327
|
+
end
|
312
328
|
end
|
313
329
|
|
314
330
|
context 'when deserializing' do
|
@@ -1586,4 +1602,219 @@ describe BSON::Decimal128 do
|
|
1586
1602
|
expect(registered).to eq(described_class)
|
1587
1603
|
end
|
1588
1604
|
end
|
1605
|
+
|
1606
|
+
%w(== ===).each do |eq_op|
|
1607
|
+
let(:lhs) { described_class.new('1.2e12') }
|
1608
|
+
|
1609
|
+
describe "##{eq_op}" do
|
1610
|
+
context 'when rhs is equal to lhs' do
|
1611
|
+
context 'when both are Decimal128 instances' do
|
1612
|
+
let(:rhs) { described_class.new('1.2e12') }
|
1613
|
+
|
1614
|
+
it 'is true' do
|
1615
|
+
(lhs == rhs).should be true
|
1616
|
+
end
|
1617
|
+
end
|
1618
|
+
|
1619
|
+
context 'when rhs is of a different type' do
|
1620
|
+
[
|
1621
|
+
1200000000000,
|
1622
|
+
1200000000000.0,
|
1623
|
+
BigDecimal('1.2e12'),
|
1624
|
+
].each do |rhs|
|
1625
|
+
context "when rhs is #{rhs.class}" do
|
1626
|
+
it 'is true' do
|
1627
|
+
pending 'RUBY-2952'
|
1628
|
+
|
1629
|
+
(lhs == rhs).should be true
|
1630
|
+
end
|
1631
|
+
end
|
1632
|
+
end
|
1633
|
+
end
|
1634
|
+
end
|
1635
|
+
|
1636
|
+
context 'when rhs is not equal to lhs' do
|
1637
|
+
context 'when both are Decimal128 instances' do
|
1638
|
+
let(:rhs) { described_class.new('1.21e12') }
|
1639
|
+
|
1640
|
+
it 'is false' do
|
1641
|
+
(lhs == rhs).should be false
|
1642
|
+
end
|
1643
|
+
end
|
1644
|
+
|
1645
|
+
context 'when rhs is of a different type' do
|
1646
|
+
|
1647
|
+
[
|
1648
|
+
1200000000001,
|
1649
|
+
1200000000001.0,
|
1650
|
+
BigDecimal('1.21e12'),
|
1651
|
+
].each do |rhs|
|
1652
|
+
context "when rhs is #{rhs.class}" do
|
1653
|
+
it 'is false' do
|
1654
|
+
(lhs == rhs).should be false
|
1655
|
+
end
|
1656
|
+
end
|
1657
|
+
end
|
1658
|
+
end
|
1659
|
+
end
|
1660
|
+
end
|
1661
|
+
end
|
1662
|
+
|
1663
|
+
describe "#<=>" do
|
1664
|
+
|
1665
|
+
let(:lhs) { described_class.new('1.2e12') }
|
1666
|
+
|
1667
|
+
context 'when lhs is less than rhs' do
|
1668
|
+
context 'when both are Decimal128 instances' do
|
1669
|
+
let(:rhs) { described_class.new('1.21e12') }
|
1670
|
+
|
1671
|
+
it 'is -1' do
|
1672
|
+
(lhs <=> rhs).should be -1
|
1673
|
+
end
|
1674
|
+
end
|
1675
|
+
|
1676
|
+
context 'when rhs is of a different type' do
|
1677
|
+
[
|
1678
|
+
1200000000001,
|
1679
|
+
1200000000001.0,
|
1680
|
+
BigDecimal('1.21e12'),
|
1681
|
+
].each do |rhs|
|
1682
|
+
context "when rhs is #{rhs.class}" do
|
1683
|
+
it 'is -1' do
|
1684
|
+
(lhs <=> rhs).should be -1
|
1685
|
+
end
|
1686
|
+
end
|
1687
|
+
end
|
1688
|
+
end
|
1689
|
+
end
|
1690
|
+
|
1691
|
+
context 'when rhs is equal to lhs' do
|
1692
|
+
context 'when both are Decimal128 instances' do
|
1693
|
+
let(:rhs) { described_class.new('1.2e12') }
|
1694
|
+
|
1695
|
+
it 'is 0' do
|
1696
|
+
(lhs <=> rhs).should be 0
|
1697
|
+
end
|
1698
|
+
end
|
1699
|
+
|
1700
|
+
context 'when rhs is of a different type' do
|
1701
|
+
|
1702
|
+
[
|
1703
|
+
1200000000000,
|
1704
|
+
1200000000000.0,
|
1705
|
+
BigDecimal('1.2e12'),
|
1706
|
+
].each do |rhs|
|
1707
|
+
context "when rhs is #{rhs.class}" do
|
1708
|
+
it 'is 0' do
|
1709
|
+
(lhs <=> rhs).should be 0
|
1710
|
+
end
|
1711
|
+
end
|
1712
|
+
end
|
1713
|
+
end
|
1714
|
+
end
|
1715
|
+
|
1716
|
+
context 'when rhs is greater than lhs' do
|
1717
|
+
context 'when both are Decimal128 instances' do
|
1718
|
+
let(:rhs) { described_class.new('1.1e12') }
|
1719
|
+
|
1720
|
+
it 'is 1' do
|
1721
|
+
(lhs <=> rhs).should be 1
|
1722
|
+
end
|
1723
|
+
end
|
1724
|
+
|
1725
|
+
context 'when rhs is of a different type' do
|
1726
|
+
|
1727
|
+
[
|
1728
|
+
1100000000000,
|
1729
|
+
1100000000000.0,
|
1730
|
+
BigDecimal('1.1e12'),
|
1731
|
+
].each do |rhs|
|
1732
|
+
context "when rhs is #{rhs.class}" do
|
1733
|
+
it 'is 1' do
|
1734
|
+
(lhs <=> rhs).should be 1
|
1735
|
+
end
|
1736
|
+
end
|
1737
|
+
end
|
1738
|
+
end
|
1739
|
+
end
|
1740
|
+
end
|
1741
|
+
|
1742
|
+
describe "#<" do
|
1743
|
+
|
1744
|
+
let(:lhs) { described_class.new('1.2e12') }
|
1745
|
+
|
1746
|
+
context 'when lhs is less than rhs' do
|
1747
|
+
context 'when both are Decimal128 instances' do
|
1748
|
+
let(:rhs) { described_class.new('1.21e12') }
|
1749
|
+
|
1750
|
+
it 'is true' do
|
1751
|
+
(lhs < rhs).should be true
|
1752
|
+
end
|
1753
|
+
end
|
1754
|
+
|
1755
|
+
context 'when rhs is of a different type' do
|
1756
|
+
[
|
1757
|
+
1200000000001,
|
1758
|
+
1200000000001.0,
|
1759
|
+
BigDecimal('1.21e12'),
|
1760
|
+
].each do |rhs|
|
1761
|
+
context "when rhs is #{rhs.class}" do
|
1762
|
+
it 'is true' do
|
1763
|
+
(lhs < rhs).should be true
|
1764
|
+
end
|
1765
|
+
end
|
1766
|
+
end
|
1767
|
+
end
|
1768
|
+
end
|
1769
|
+
|
1770
|
+
context 'when rhs is equal to lhs' do
|
1771
|
+
context 'when both are Decimal128 instances' do
|
1772
|
+
let(:rhs) { described_class.new('1.2e12') }
|
1773
|
+
|
1774
|
+
it 'is false' do
|
1775
|
+
(lhs < rhs).should be false
|
1776
|
+
end
|
1777
|
+
end
|
1778
|
+
|
1779
|
+
context 'when rhs is of a different type' do
|
1780
|
+
|
1781
|
+
[
|
1782
|
+
1200000000000,
|
1783
|
+
1200000000000.0,
|
1784
|
+
BigDecimal('1.2e12'),
|
1785
|
+
].each do |rhs|
|
1786
|
+
context "when rhs is #{rhs.class}" do
|
1787
|
+
it 'is false' do
|
1788
|
+
(lhs < rhs).should be false
|
1789
|
+
end
|
1790
|
+
end
|
1791
|
+
end
|
1792
|
+
end
|
1793
|
+
end
|
1794
|
+
|
1795
|
+
context 'when rhs is greater than lhs' do
|
1796
|
+
context 'when both are Decimal128 instances' do
|
1797
|
+
let(:rhs) { described_class.new('1.1e12') }
|
1798
|
+
|
1799
|
+
it 'is false' do
|
1800
|
+
(lhs < rhs).should be false
|
1801
|
+
end
|
1802
|
+
end
|
1803
|
+
|
1804
|
+
context 'when rhs is of a different type' do
|
1805
|
+
|
1806
|
+
[
|
1807
|
+
1100000000000,
|
1808
|
+
1100000000000.0,
|
1809
|
+
BigDecimal('1.1e12'),
|
1810
|
+
].each do |rhs|
|
1811
|
+
context "when rhs is #{rhs.class}" do
|
1812
|
+
it 'is false' do
|
1813
|
+
(lhs < rhs).should be false
|
1814
|
+
end
|
1815
|
+
end
|
1816
|
+
end
|
1817
|
+
end
|
1818
|
+
end
|
1819
|
+
end
|
1589
1820
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright (C) 2021 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
|
+
# BSON::Document ActiveSupport extensions
|
18
|
+
describe BSON::Document do
|
19
|
+
require_active_support
|
20
|
+
|
21
|
+
describe '#symbolize_keys' do
|
22
|
+
context 'string keys' do
|
23
|
+
let(:doc) do
|
24
|
+
described_class.new('foo' => 'bar')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'works correctly' do
|
28
|
+
doc.symbolize_keys.should == {foo: 'bar'}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#symbolize_keys!' do
|
34
|
+
context 'string keys' do
|
35
|
+
let(:doc) do
|
36
|
+
described_class.new('foo' => 'bar')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'raises ArgumentError' do
|
40
|
+
lambda do
|
41
|
+
doc.symbolize_keys!
|
42
|
+
end.should raise_error(ArgumentError, /symbolize_keys! is not supported on BSON::Document instances/)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/bson/document_spec.rb
CHANGED
@@ -215,6 +215,10 @@ describe BSON::Document do
|
|
215
215
|
|
216
216
|
context "when provided string keys" do
|
217
217
|
|
218
|
+
it "is a BSON Document" do
|
219
|
+
expect(document.slice("key1")).to be_a(BSON::Document)
|
220
|
+
end
|
221
|
+
|
218
222
|
it "returns the partial document" do
|
219
223
|
expect(document.slice("key1")).to contain_exactly(['key1', 'value1'])
|
220
224
|
end
|
@@ -222,13 +226,45 @@ describe BSON::Document do
|
|
222
226
|
|
223
227
|
context "when provided symbol keys" do
|
224
228
|
|
229
|
+
it "is a BSON Document" do
|
230
|
+
expect(document.slice(:key1)).to be_a(BSON::Document)
|
231
|
+
end
|
232
|
+
|
225
233
|
it "returns the partial document" do
|
226
234
|
expect(document.slice(:key1)).to contain_exactly(['key1', 'value1'])
|
227
235
|
end
|
228
236
|
end
|
237
|
+
|
238
|
+
context "when provided keys that do not exist in the document" do
|
239
|
+
|
240
|
+
it "returns only the keys that exist in the document" do
|
241
|
+
expect(document.slice(:key1, :key3)).to contain_exactly(['key1', 'value1'])
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "#except" do
|
248
|
+
let(:document) do
|
249
|
+
described_class.new("key1" => "value1", key2: "value2")
|
250
|
+
end
|
251
|
+
|
252
|
+
context "when provided string keys" do
|
253
|
+
|
254
|
+
it "returns the partial document" do
|
255
|
+
expect(document.except("key1")).to contain_exactly(['key2', 'value2'])
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "when provided symbol keys" do
|
260
|
+
|
261
|
+
it "returns the partial document" do
|
262
|
+
expect(document.except(:key1)).to contain_exactly(['key2', 'value2'])
|
263
|
+
end
|
229
264
|
end
|
230
265
|
end
|
231
266
|
|
267
|
+
|
232
268
|
describe "#delete" do
|
233
269
|
|
234
270
|
shared_examples_for "a document with deletable pairs" do
|
@@ -484,7 +520,13 @@ describe BSON::Document do
|
|
484
520
|
context "when the document has been serialized" do
|
485
521
|
|
486
522
|
let(:deserialized) do
|
487
|
-
YAML.
|
523
|
+
if YAML.respond_to?(:unsafe_load)
|
524
|
+
# In psych >= 4.0.0 `load` is basically an alias to `safe_load`,
|
525
|
+
# which will fail here.
|
526
|
+
YAML.unsafe_load(YAML.dump(doc))
|
527
|
+
else
|
528
|
+
YAML.load(YAML.dump(doc))
|
529
|
+
end
|
488
530
|
end
|
489
531
|
|
490
532
|
let!(:enum) do
|
@@ -148,6 +148,7 @@ describe "BSON::ExtJSON.parse" do
|
|
148
148
|
end
|
149
149
|
|
150
150
|
let(:parsed) { BSON::ExtJSON.parse_obj(input, mode: mode) }
|
151
|
+
let(:mode) { :bson }
|
151
152
|
|
152
153
|
context 'when mode is invalid' do
|
153
154
|
let(:mode) { :foo }
|
@@ -158,6 +159,42 @@ describe "BSON::ExtJSON.parse" do
|
|
158
159
|
end.should raise_error(ArgumentError, /Invalid value for :mode option/)
|
159
160
|
end
|
160
161
|
end
|
162
|
+
|
163
|
+
context 'when it contains a string key with a null byte' do
|
164
|
+
let(:input) do
|
165
|
+
{ "key\x00" => 1 }
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'raises an exception' do
|
169
|
+
lambda do
|
170
|
+
parsed
|
171
|
+
end.should raise_error(BSON::Error::ExtJSONParseError, /Hash key cannot contain a null byte/)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'when it contains a symbol key with a null byte' do
|
176
|
+
let(:input) do
|
177
|
+
{ "key\x00".to_sym => 1 }
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'raises an exception' do
|
181
|
+
lambda do
|
182
|
+
parsed
|
183
|
+
end.should raise_error(BSON::Error::ExtJSONParseError, /Hash key cannot contain a null byte/)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'when it contains an integer key' do
|
188
|
+
let(:input) do
|
189
|
+
{ 0 => 1 }
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'does not raises an exception' do
|
193
|
+
lambda do
|
194
|
+
parsed
|
195
|
+
end.should_not raise_error
|
196
|
+
end
|
197
|
+
end
|
161
198
|
end
|
162
199
|
|
163
200
|
context 'when input is a binary' do
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright (C) 2021 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 'Hash ActiveSupport extensions' do
|
18
|
+
require_active_support
|
19
|
+
|
20
|
+
describe '#symbolize_keys' do
|
21
|
+
let(:symbolized) { hash.symbolize_keys }
|
22
|
+
|
23
|
+
shared_examples 'works correctly' do
|
24
|
+
it 'returns a hash' do
|
25
|
+
symbolized.class.should be Hash
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'works correctly' do
|
29
|
+
hash.symbolize_keys.should == {foo: 'bar'}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'string keys' do
|
34
|
+
let(:hash) do
|
35
|
+
{'foo' => 'bar'}
|
36
|
+
end
|
37
|
+
|
38
|
+
include_examples 'works correctly'
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'symbol keys' do
|
42
|
+
let(:hash) do
|
43
|
+
{foo: 'bar'}
|
44
|
+
end
|
45
|
+
|
46
|
+
include_examples 'works correctly'
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'both string and symbol keys' do
|
50
|
+
let(:hash) do
|
51
|
+
{'foo' => 42, foo: 'bar'}
|
52
|
+
end
|
53
|
+
|
54
|
+
include_examples 'works correctly'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/spec/bson/hash_spec.rb
CHANGED
@@ -227,6 +227,53 @@ describe Hash do
|
|
227
227
|
end
|
228
228
|
end
|
229
229
|
end
|
230
|
+
|
231
|
+
context 'when hash contains value of an unserializable class' do
|
232
|
+
class HashSpecUnserializableClass
|
233
|
+
end
|
234
|
+
|
235
|
+
let(:obj) do
|
236
|
+
{foo: HashSpecUnserializableClass.new}
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'raises UnserializableClass' do
|
240
|
+
lambda do
|
241
|
+
obj.to_bson
|
242
|
+
end.should raise_error(BSON::Error::UnserializableClass,
|
243
|
+
# C extension does not provide hash key in the exception message.
|
244
|
+
/(Hash value for key 'foo'|Value) does not define its BSON serialized type:.*HashSpecUnserializableClass/)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'when reading from a byte buffer that was previously written to' do
|
249
|
+
let(:buffer) do
|
250
|
+
{foo: 42}.to_bson
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'returns the original hash' do
|
254
|
+
expect(Hash.from_bson(buffer)).to eq('foo' => 42)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context 'when round-tripping a BigDecimal' do
|
259
|
+
let(:to_bson) do
|
260
|
+
{"x" => BigDecimal('1')}.to_bson
|
261
|
+
end
|
262
|
+
|
263
|
+
let(:from_bson) do
|
264
|
+
Hash.from_bson(to_bson)
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'doesn\'t raise on serialization' do
|
268
|
+
expect do
|
269
|
+
to_bson
|
270
|
+
end.to_not raise_error
|
271
|
+
end
|
272
|
+
|
273
|
+
it 'deserializes as a BSON::Decimal128' do
|
274
|
+
expect(from_bson).to eq({"x" => BSON::Decimal128.new('1')})
|
275
|
+
end
|
276
|
+
end
|
230
277
|
end
|
231
278
|
|
232
279
|
describe '#to_bson' do
|
@@ -292,5 +339,63 @@ describe Hash do
|
|
292
339
|
end.not_to raise_error
|
293
340
|
end
|
294
341
|
end
|
342
|
+
|
343
|
+
context 'when serializing a hash with a BigDecimal' do
|
344
|
+
let(:hash) do
|
345
|
+
{'foo' => BigDecimal('1')}
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'works' do
|
349
|
+
expect do
|
350
|
+
hash.to_bson
|
351
|
+
end.not_to raise_error
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
describe '#from_bson' do
|
357
|
+
context 'when bson document has duplicate keys' do
|
358
|
+
let(:buf) do
|
359
|
+
buf = BSON::ByteBuffer.new
|
360
|
+
buf.put_int32(37)
|
361
|
+
buf.put_byte("\x02")
|
362
|
+
buf.put_cstring('foo')
|
363
|
+
buf.put_string('bar')
|
364
|
+
buf.put_byte("\x02")
|
365
|
+
buf.put_cstring('foo')
|
366
|
+
buf.put_string('overwrite')
|
367
|
+
buf.put_byte("\x00")
|
368
|
+
|
369
|
+
BSON::ByteBuffer.new(buf.to_s)
|
370
|
+
end
|
371
|
+
|
372
|
+
let(:doc) { Hash.from_bson(buf) }
|
373
|
+
|
374
|
+
it 'overwrites first value with second value' do
|
375
|
+
doc.should == {'foo' => 'overwrite'}
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
context 'when bson document has string and symbol keys of the same name' do
|
380
|
+
let(:buf) do
|
381
|
+
buf = BSON::ByteBuffer.new
|
382
|
+
buf.put_int32(31)
|
383
|
+
buf.put_byte("\x02")
|
384
|
+
buf.put_cstring('foo')
|
385
|
+
buf.put_string('bar')
|
386
|
+
buf.put_byte("\x0e")
|
387
|
+
buf.put_cstring('foo')
|
388
|
+
buf.put_string('bar')
|
389
|
+
buf.put_byte("\x00")
|
390
|
+
|
391
|
+
BSON::ByteBuffer.new(buf.to_s)
|
392
|
+
end
|
393
|
+
|
394
|
+
let(:doc) { Hash.from_bson(buf) }
|
395
|
+
|
396
|
+
it 'overwrites first value with second value' do
|
397
|
+
doc.should == {'foo' => :bar}
|
398
|
+
end
|
399
|
+
end
|
295
400
|
end
|
296
401
|
end
|
data/spec/bson/int64_spec.rb
CHANGED
@@ -106,18 +106,8 @@ describe BSON::Int64 do
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
it "deserializes to a Fixnum object" do
|
112
|
-
expect(described_class.from_bson(bson).class).to be(Fixnum)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
context "when using MRI >= 2.4", if: (!BSON::Environment.jruby? && RUBY_VERSION >= '2.4') do
|
117
|
-
|
118
|
-
it "deserializes to an Integer object" do
|
119
|
-
expect(described_class.from_bson(bson).class).to be(Integer)
|
120
|
-
end
|
109
|
+
it "deserializes to an Integer object" do
|
110
|
+
expect(described_class.from_bson(bson).class).to be(Integer)
|
121
111
|
end
|
122
112
|
end
|
123
113
|
|
@@ -136,18 +126,8 @@ describe BSON::Int64 do
|
|
136
126
|
end
|
137
127
|
end
|
138
128
|
|
139
|
-
|
140
|
-
|
141
|
-
it "deserializes to a Bignum object" do
|
142
|
-
expect(described_class.from_bson(bson).class).to be(Bignum)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
context "when using MRI >= 2.4", if: (!BSON::Environment.jruby? && RUBY_VERSION >= '2.4') do
|
147
|
-
|
148
|
-
it "deserializes to an Integer object" do
|
149
|
-
expect(described_class.from_bson(bson).class).to be(Integer)
|
150
|
-
end
|
129
|
+
it "deserializes to an Integer object" do
|
130
|
+
expect(described_class.from_bson(bson).class).to be(Integer)
|
151
131
|
end
|
152
132
|
end
|
153
133
|
end
|
data/spec/bson/raw_spec.rb
CHANGED
@@ -580,4 +580,21 @@ describe Regexp::Raw do
|
|
580
580
|
end
|
581
581
|
end
|
582
582
|
end
|
583
|
-
|
583
|
+
|
584
|
+
describe 'yaml loading' do
|
585
|
+
let(:regexp) { described_class.new('hello.world', 's') }
|
586
|
+
|
587
|
+
it 'round-trips' do
|
588
|
+
actual = if YAML.respond_to?(:unsafe_load)
|
589
|
+
# In psych >= 4.0.0 `load` is basically an alias to `safe_load`,
|
590
|
+
# which will fail here.
|
591
|
+
YAML.unsafe_load(regexp.to_yaml)
|
592
|
+
else
|
593
|
+
YAML.load(regexp.to_yaml)
|
594
|
+
end
|
595
|
+
actual.pattern.should == 'hello.world'
|
596
|
+
actual.options.should == 's'
|
597
|
+
actual.compile.should =~ "hello\nworld"
|
598
|
+
end
|
599
|
+
end
|
600
|
+
end
|