bson 4.13.0-java → 4.15.0-java

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.
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+ require 'json'
6
+
7
+ # These tests are copied from driver when the driver implemented Mongo:DBRef
8
+ # class, and are intended to verify that the current DBRef implementation is
9
+ # compatible with the legacy driver DBRef interface.
10
+
11
+ describe BSON::DBRef do
12
+
13
+ let(:object_id) do
14
+ BSON::ObjectId.new
15
+ end
16
+
17
+ describe '#as_json' do
18
+
19
+ context 'when the database is not provided' do
20
+
21
+ let(:dbref) do
22
+ described_class.new('users', object_id)
23
+ end
24
+
25
+ it 'returns the json document without database' do
26
+ expect(dbref.as_json).to eq({ '$ref' => 'users', '$id' => object_id })
27
+ end
28
+ end
29
+
30
+ context 'when the database is provided' do
31
+
32
+ let(:dbref) do
33
+ described_class.new('users', object_id, 'database')
34
+ end
35
+
36
+ it 'returns the json document with database' do
37
+ expect(dbref.as_json).to eq({
38
+ '$ref' => 'users',
39
+ '$id' => object_id,
40
+ '$db' => 'database'
41
+ })
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '#initialize' do
47
+
48
+ let(:dbref) do
49
+ described_class.new('users', object_id)
50
+ end
51
+
52
+ it 'sets the collection' do
53
+ expect(dbref.collection).to eq('users')
54
+ end
55
+
56
+ it 'sets the id' do
57
+ expect(dbref.id).to eq(object_id)
58
+ end
59
+
60
+ context 'when a database is provided' do
61
+
62
+ let(:dbref) do
63
+ described_class.new('users', object_id, 'db')
64
+ end
65
+
66
+ it 'sets the database' do
67
+ expect(dbref.database).to eq('db')
68
+ end
69
+
70
+ context 'when id is not provided' do
71
+
72
+ let(:dbref) do
73
+ described_class.new('users', nil, 'db')
74
+ end
75
+
76
+ it 'raises ArgumentError' do
77
+ lambda do
78
+ dbref
79
+ end.should raise_error(ArgumentError)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ describe '#to_bson' do
86
+
87
+ let(:dbref) do
88
+ described_class.new('users', object_id, 'database')
89
+ end
90
+
91
+ it 'converts the underlying document to bson' do
92
+ expect(dbref.to_bson.to_s).to eq(dbref.as_json.to_bson.to_s)
93
+ end
94
+ end
95
+
96
+ describe '#to_json' do
97
+
98
+ context 'when the database is not provided' do
99
+
100
+ let(:dbref) do
101
+ described_class.new('users', object_id)
102
+ end
103
+
104
+ it 'returns the json document without database' do
105
+ expect(dbref.to_json).to eq("{\"$ref\":\"users\",\"$id\":#{object_id.to_json}}")
106
+ end
107
+ end
108
+
109
+ context 'when the database is provided' do
110
+
111
+ let(:dbref) do
112
+ described_class.new('users', object_id, 'database')
113
+ end
114
+
115
+ it 'returns the json document with database' do
116
+ expect(dbref.to_json).to eq("{\"$ref\":\"users\",\"$id\":#{object_id.to_json},\"$db\":\"database\"}")
117
+ end
118
+ end
119
+ end
120
+
121
+ describe '#from_bson' do
122
+
123
+ let(:buffer) do
124
+ dbref.to_bson
125
+ end
126
+
127
+ let(:decoded) do
128
+ BSON::Document.from_bson(BSON::ByteBuffer.new(buffer.to_s))
129
+ end
130
+
131
+ context 'when a database exists' do
132
+
133
+ let(:dbref) do
134
+ described_class.new('users', object_id, 'database')
135
+ end
136
+
137
+ it 'decodes the ref' do
138
+ expect(decoded.collection).to eq('users')
139
+ end
140
+
141
+ it 'decodes the id' do
142
+ expect(decoded.id).to eq(object_id)
143
+ end
144
+
145
+ it 'decodes the database' do
146
+ expect(decoded.database).to eq('database')
147
+ end
148
+ end
149
+
150
+ context 'when no database exists' do
151
+
152
+ let(:dbref) do
153
+ described_class.new('users', object_id)
154
+ end
155
+
156
+ it 'decodes the ref' do
157
+ expect(decoded.collection).to eq('users')
158
+ end
159
+
160
+ it 'decodes the id' do
161
+ expect(decoded.id).to eq(object_id)
162
+ end
163
+
164
+ it 'sets the database to nil' do
165
+ expect(decoded.database).to be_nil
166
+ end
167
+ end
168
+ end
169
+ end
@@ -73,6 +73,32 @@ describe BSON::DBRef do
73
73
  expect(dbref.id).to eq(object_id)
74
74
  end
75
75
 
76
+ context 'when first argument is a hash and two arguments are provided' do
77
+
78
+ let(:dbref) do
79
+ described_class.new({:$ref => 'users', :$id => object_id}, object_id)
80
+ end
81
+
82
+ it 'raises ArgumentError' do
83
+ lambda do
84
+ dbref
85
+ end.should raise_error(ArgumentError)
86
+ end
87
+ end
88
+
89
+ context 'when first argument is a hash and three arguments are provided' do
90
+
91
+ let(:dbref) do
92
+ described_class.new({:$ref => 'users', :$id => object_id}, object_id, 'db')
93
+ end
94
+
95
+ it 'raises ArgumentError' do
96
+ lambda do
97
+ dbref
98
+ end.should raise_error(ArgumentError)
99
+ end
100
+ end
101
+
76
102
  context 'when a database is provided' do
77
103
 
78
104
  let(:hash) do
@@ -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
@@ -254,6 +254,26 @@ describe Hash do
254
254
  expect(Hash.from_bson(buffer)).to eq('foo' => 42)
255
255
  end
256
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
257
277
  end
258
278
 
259
279
  describe '#to_bson' do
@@ -319,6 +339,18 @@ describe Hash do
319
339
  end.not_to raise_error
320
340
  end
321
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
322
354
  end
323
355
 
324
356
  describe '#from_bson' do
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'aws-sdk-s3'
5
+
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = "Usage: s3-copy options"
9
+
10
+ opts.on("-r", "--region=REGION", "AWS region to use (default us-east-1)") do |v|
11
+ options[:region] = v
12
+ end
13
+
14
+ opts.on("-p", "--param=KEY=VALUE", "Specify parameter for new files") do |v|
15
+ options[:params] ||= {}
16
+ k, v = v.split('=', 2)
17
+ options[:params][k.to_sym] = v
18
+ end
19
+
20
+ opts.on("-f", "--from=BUCKET:PATH", "Bucket name and key (or path) to copy from") do |v|
21
+ options[:from] = v
22
+ end
23
+
24
+ opts.on("-t", "--to=BUCKET:PATH", "Bucket name and key (or path) to write to (may be specified more than once)") do |v|
25
+ options[:to] ||= []
26
+ options[:to] << v
27
+ end
28
+ end.parse!
29
+
30
+ ENV['AWS_REGION'] ||= options[:region] || 'us-east-1'
31
+
32
+ bucket, key = options.fetch(:from).split(':', 2)
33
+
34
+ s3 = Aws::S3::Client.new
35
+
36
+ options.fetch(:to).each do |dest|
37
+ STDERR.puts "Copying to #{dest}"
38
+ dbucket, dkey = dest.split(':', 2)
39
+ s3.copy_object(
40
+ bucket: dbucket,
41
+ key: dkey,
42
+ copy_source: "/#{bucket}/#{key}",
43
+ **options[:params] || {},
44
+ )
45
+ end
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'aws-sdk-s3'
5
+
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = "Usage: s3-upload options"
9
+
10
+ opts.on("-r", "--region=REGION", "AWS region to use (default us-east-1)") do |v|
11
+ options[:region] = v
12
+ end
13
+
14
+ opts.on("-p", "--param=KEY=VALUE", "Specify parameter for S3 upload") do |v|
15
+ options[:params] ||= {}
16
+ k, v = v.split('=', 2)
17
+ options[:params][k.to_sym] = v
18
+ end
19
+
20
+ opts.on("-f", "--file=PATH", "Path to the file to upload, - to upload standard input") do |v|
21
+ options[:file] = v
22
+ end
23
+
24
+ opts.on("-w", "--write=BUCKET:PATH", "Bucket name and key (or path) to upload to") do |v|
25
+ options[:write] = v
26
+ end
27
+
28
+ opts.on("-c", "--copy=BUCKET:PATH", "Bucket name and key (or path) to copy to (may be specified more than once)") do |v|
29
+ options[:copy] ||= []
30
+ options[:copy] << v
31
+ end
32
+ end.parse!
33
+
34
+ ENV['AWS_REGION'] ||= options[:region] || 'us-east-1'
35
+
36
+ def upload(f, options)
37
+ s3 = Aws::S3::Client.new
38
+ write = options.fetch(:write)
39
+ STDERR.puts "Writing #{write}"
40
+ bucket, key = write.split(':', 2)
41
+ s3.put_object(
42
+ body: f.read,
43
+ bucket: bucket,
44
+ key: key,
45
+ **options[:params] || {},
46
+ )
47
+ if copy = options[:copy]
48
+ copy.each do |dest|
49
+ STDERR.puts "Copying to #{dest}"
50
+ dbucket, dkey = dest.split(':', 2)
51
+ s3.copy_object(
52
+ bucket: dbucket,
53
+ key: dkey,
54
+ copy_source: "/#{bucket}/#{key}",
55
+ **options[:params] || {},
56
+ )
57
+ end
58
+ end
59
+ end
60
+
61
+ if options[:file] == '-'
62
+ upload(STDIN, options)
63
+ elsif options[:file]
64
+ File.open(options[:file]) do |f|
65
+ upload(f, options)
66
+ end
67
+ else
68
+ upload(STDIN, options)
69
+ end
@@ -15,6 +15,11 @@ module Mrss
15
15
  @single_server
16
16
  end
17
17
 
18
+ def sharded_ish?
19
+ determine_cluster_config
20
+ @topology == :sharded || @topology == :load_balanced
21
+ end
22
+
18
23
  def replica_set_name
19
24
  determine_cluster_config
20
25
  @replica_set_name
@@ -48,7 +53,7 @@ module Mrss
48
53
  raise "Deployment server version not known - check that connection to deployment succeeded"
49
54
  end
50
55
 
51
- if server_version >= '3.4' && topology != :sharded
56
+ if server_version >= '3.4' && !sharded_ish?
52
57
  fcv
53
58
  else
54
59
  if short_server_version == '4.1'
@@ -115,7 +120,7 @@ module Mrss
115
120
  :mmapv1
116
121
  else
117
122
  client = ClientRegistry.instance.global_client('root_authorized')
118
- if topology == :sharded
123
+ if sharded_ish?
119
124
  shards = client.use(:admin).command(listShards: 1).first
120
125
  if shards['shards'].empty?
121
126
  raise 'Shards are empty'
@@ -204,9 +209,14 @@ module Mrss
204
209
  @server_version = build_info['version']
205
210
  @enterprise = build_info['modules'] && build_info['modules'].include?('enterprise')
206
211
 
207
- @server_parameters = client.use(:admin).command(getParameter: '*').first
212
+ @server_parameters = begin
213
+ client.use(:admin).command(getParameter: '*').first
214
+ rescue => e
215
+ STDERR.puts("WARNING: Failed to obtain server parameters: #{e.class}: #{e.message}")
216
+ {}
217
+ end
208
218
 
209
- if @topology != :sharded && short_server_version >= '3.4'
219
+ if !sharded_ish? && short_server_version >= '3.4'
210
220
  rv = @server_parameters['featureCompatibilityVersion']
211
221
  @fcv = rv['version'] || rv
212
222
  end