bson 4.1.1-java → 4.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +18 -3
  5. data/lib/bson-ruby.jar +0 -0
  6. data/lib/bson.rb +6 -4
  7. data/lib/bson/array.rb +1 -1
  8. data/lib/bson/binary.rb +4 -2
  9. data/lib/bson/code.rb +1 -1
  10. data/lib/bson/code_with_scope.rb +1 -1
  11. data/lib/bson/config.rb +1 -1
  12. data/lib/bson/date.rb +1 -1
  13. data/lib/bson/date_time.rb +1 -1
  14. data/lib/bson/decimal128.rb +318 -0
  15. data/lib/bson/decimal128/builder.rb +448 -0
  16. data/lib/bson/document.rb +2 -2
  17. data/lib/bson/environment.rb +13 -1
  18. data/lib/bson/false_class.rb +1 -1
  19. data/lib/bson/float.rb +1 -1
  20. data/lib/bson/hash.rb +1 -1
  21. data/lib/bson/int32.rb +46 -0
  22. data/lib/bson/int64.rb +46 -0
  23. data/lib/bson/integer.rb +1 -1
  24. data/lib/bson/max_key.rb +1 -1
  25. data/lib/bson/min_key.rb +1 -1
  26. data/lib/bson/object_id.rb +3 -2
  27. data/lib/bson/open_struct.rb +57 -0
  28. data/lib/bson/regexp.rb +87 -19
  29. data/lib/bson/registry.rb +1 -1
  30. data/lib/bson/specialized.rb +1 -1
  31. data/lib/bson/string.rb +1 -1
  32. data/lib/bson/symbol.rb +1 -1
  33. data/lib/bson/time.rb +1 -1
  34. data/lib/bson/timestamp.rb +2 -2
  35. data/lib/bson/true_class.rb +1 -1
  36. data/lib/bson/version.rb +2 -2
  37. data/spec/bson/array_spec.rb +1 -1
  38. data/spec/bson/binary_spec.rb +2 -1
  39. data/spec/bson/corpus_spec.rb +68 -0
  40. data/spec/bson/decimal128_spec.rb +1583 -0
  41. data/spec/bson/document_spec.rb +1 -1
  42. data/spec/bson/driver_bson_spec.rb +77 -0
  43. data/spec/bson/int32_spec.rb +58 -0
  44. data/spec/bson/int64_spec.rb +58 -0
  45. data/spec/bson/open_struct_spec.rb +144 -0
  46. data/spec/bson/raw_spec.rb +540 -0
  47. data/spec/bson/regexp_spec.rb +7 -7
  48. data/spec/bson/timestamp_spec.rb +1 -1
  49. data/spec/spec_helper.rb +5 -0
  50. data/spec/support/common_driver.rb +347 -0
  51. data/spec/support/corpus-tests/array.json +43 -0
  52. data/spec/support/corpus-tests/boolean.json +27 -0
  53. data/spec/support/corpus-tests/code.json +67 -0
  54. data/spec/support/corpus-tests/code_w_scope.json +78 -0
  55. data/spec/support/corpus-tests/document.json +36 -0
  56. data/spec/support/corpus-tests/double.json +69 -0
  57. data/spec/support/corpus-tests/failures/binary.json +69 -0
  58. data/spec/support/corpus-tests/failures/datetime.json +31 -0
  59. data/spec/support/corpus-tests/failures/dbpointer.json +42 -0
  60. data/spec/support/corpus-tests/failures/int64.json +38 -0
  61. data/spec/support/corpus-tests/failures/symbol.json +62 -0
  62. data/spec/support/corpus-tests/failures/undefined.json +13 -0
  63. data/spec/support/corpus-tests/int32.json +38 -0
  64. data/spec/support/corpus-tests/maxkey.json +12 -0
  65. data/spec/support/corpus-tests/minkey.json +12 -0
  66. data/spec/support/corpus-tests/null.json +12 -0
  67. data/spec/support/corpus-tests/oid.json +28 -0
  68. data/spec/support/corpus-tests/regex.json +37 -0
  69. data/spec/support/corpus-tests/string.json +67 -0
  70. data/spec/support/corpus-tests/timestamp.json +18 -0
  71. data/spec/support/corpus-tests/top.json +62 -0
  72. data/spec/support/corpus.rb +265 -0
  73. data/spec/support/driver-spec-tests/decimal128/decimal128-1.json +363 -0
  74. data/spec/support/driver-spec-tests/decimal128/decimal128-2.json +793 -0
  75. data/spec/support/driver-spec-tests/decimal128/decimal128-3.json +1771 -0
  76. data/spec/support/driver-spec-tests/decimal128/decimal128-4.json +165 -0
  77. data/spec/support/driver-spec-tests/decimal128/decimal128-5.json +402 -0
  78. data/spec/support/driver-spec-tests/decimal128/decimal128-6.json +131 -0
  79. data/spec/support/driver-spec-tests/decimal128/decimal128-7.json +327 -0
  80. data/spec/support/shared_examples.rb +1 -1
  81. metadata +77 -4
  82. metadata.gz.sig +0 -0
@@ -42,7 +42,7 @@ module BSON
42
42
  # @example Encode the min key value.
43
43
  # min_key.to_bson
44
44
  #
45
- # @return [ String ] An empty string.
45
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
46
46
  #
47
47
  # @since 2.0.0
48
48
  def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
@@ -40,7 +40,7 @@ module BSON
40
40
  #
41
41
  # @raise [ EncodingError ] If the string is not UTF-8.
42
42
  #
43
- # @return [ String ] The encoded string.
43
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
44
44
  #
45
45
  # @see http://bsonspec.org/#/specification
46
46
  #
@@ -51,7 +51,7 @@ module BSON
51
51
  # @example Get the symbol as encoded BSON.
52
52
  # :test.to_bson
53
53
  #
54
- # @return [ Symbol ] The encoded symbol.
54
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
55
55
  #
56
56
  # @see http://bsonspec.org/#/specification
57
57
  #
@@ -32,7 +32,7 @@ module BSON
32
32
  # @example Get the time as encoded BSON.
33
33
  # Time.new(2012, 1, 1, 0, 0, 0).to_bson
34
34
  #
35
- # @return [ String ] The encoded string.
35
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
36
36
  #
37
37
  # @see http://bsonspec.org/#/specification
38
38
  #
@@ -61,7 +61,7 @@ module BSON
61
61
  #
62
62
  # @since 2.0.0
63
63
  def as_json(*args)
64
- { "t" => seconds, "i" => increment }
64
+ { "$timestamp" => { "t" => seconds, "i" => increment } }
65
65
  end
66
66
 
67
67
  # Instantiate the new timestamp.
@@ -82,7 +82,7 @@ module BSON
82
82
  # @example Get the timestamp as BSON.
83
83
  # timestamp.to_bson
84
84
  #
85
- # @return [ String ] The raw BSON bytes.
85
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
86
86
  #
87
87
  # @see http://bsonspec.org/#/specification
88
88
  #
@@ -44,7 +44,7 @@ module BSON
44
44
  # @example Get the true boolean as encoded BSON.
45
45
  # true.to_bson
46
46
  #
47
- # @return [ String ] The encoded string.
47
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
48
48
  #
49
49
  # @see http://bsonspec.org/#/specification
50
50
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2015 MongoDB Inc.
1
+ # Copyright (C) 2009-2016 MongoDB Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -13,5 +13,5 @@
13
13
  # limitations under the License.
14
14
 
15
15
  module BSON
16
- VERSION = "4.1.1".freeze
16
+ VERSION = "4.2.0".freeze
17
17
  end
@@ -127,7 +127,7 @@ describe Array do
127
127
  end
128
128
 
129
129
  it "serializes the hash" do
130
- expect(obj.to_bson.length).to eq(251)
130
+ expect(obj.to_bson.length).to eq(252)
131
131
  end
132
132
  end
133
133
  end
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require "spec_helper"
16
+ require "base64"
16
17
 
17
18
  describe BSON::Binary do
18
19
  let(:testing1) { described_class.new("testing") }
@@ -62,7 +63,7 @@ describe BSON::Binary do
62
63
 
63
64
  it "returns the binary data plus type" do
64
65
  expect(object.as_json).to eq(
65
- { "$binary" => "testing", "$type" => :user }
66
+ { "$binary" => Base64.encode64("testing"), "$type" => :user }
66
67
  )
67
68
  end
68
69
 
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Driver BSON Corpus spec tests' do
4
+
5
+ specs = BSON_CORPUS_TESTS.map { |file| BSON::Corpus::Spec.new(file) }
6
+
7
+ specs.each do |spec|
8
+
9
+ context(spec.description) do
10
+
11
+ spec.valid_tests.each do |test|
12
+
13
+ context("VALID CASE: #{test.description}") do
14
+
15
+ it 'roundtrips the given bson correctly' do
16
+ expect(test.reencoded_bson).to eq(test.correct_bson)
17
+ end
18
+
19
+ context 'when the canonical bson is roundtripped', if: test.test_canonical_bson? do
20
+
21
+ it 'encodes the canonical bson correctly' do
22
+ expect(test.reencoded_canonical_bson).to eq(test.correct_bson)
23
+ end
24
+ end
25
+
26
+ context 'when the document can be represented as extended json', if: test.test_extjson? do
27
+
28
+ it 'decodes from the given bson, then encodes the document as extended json correctly' do
29
+ skip 'The extended json in this test case does not match' unless (test.extjson_from_bson == test.correct_extjson)
30
+ expect(test.extjson_from_bson).to eq(test.correct_extjson)
31
+ expect(test.extjson_from_bson[test.test_key]).to eq(test.correct_extjson[test.test_key])
32
+ end
33
+
34
+ it 'decodes from extended json, then encodes the document as extended json correctly' do
35
+ expect(test.extjson_from_encoded_extjson).to eq(test.correct_extjson)
36
+ expect(test.extjson_from_encoded_extjson[test.test_key]).to eq(test.correct_extjson[test.test_key])
37
+ end
38
+
39
+ context 'when the canonical bson can be represented as extended json', if: (test.test_canonical_bson? && test.test_extjson?) do
40
+
41
+ it 'encodes the canonical bson correctly as extended json' do
42
+ expect(test.extjson_from_canonical_bson).to eq(test.correct_extjson)
43
+ expect(test.extjson_from_canonical_bson[test.test_key]).to eq(test.correct_extjson[test.test_key])
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ spec.invalid_tests.each do |test|
51
+
52
+ context("INVALID CASE: #{test.description}") do
53
+
54
+ let(:error) do
55
+ begin; test.reencoded_bson; false; rescue => e; e; end
56
+ end
57
+
58
+ it 'raises an error' do
59
+ skip 'This test case does not raise and error but should' unless error
60
+ expect {
61
+ test.reencoded_bson
62
+ }.to raise_error
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,1583 @@
1
+ # Copyright (C) 2016 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::Decimal128 do
18
+
19
+ let(:low_bits) do
20
+ decimal128.instance_variable_get(:@low)
21
+ end
22
+
23
+ let(:high_bits) do
24
+ decimal128.instance_variable_get(:@high)
25
+ end
26
+
27
+ describe '#initialize' do
28
+
29
+ context 'when the argument is neither a BigDecimal or String' do
30
+
31
+ it 'raises an ArgumentError' do
32
+ expect {
33
+ described_class.new(:invalid)
34
+ }.to raise_exception(ArgumentError)
35
+ end
36
+ end
37
+
38
+ shared_examples_for 'an initialized BSON::Decimal128' do
39
+
40
+ let(:decimal128) do
41
+ described_class.new(argument)
42
+ end
43
+
44
+ let(:buffer) do
45
+ decimal128.to_bson
46
+ end
47
+
48
+ let(:from_bson) do
49
+ described_class.from_bson(buffer)
50
+ end
51
+
52
+ it 'sets the correct high order bits' do
53
+ expect(high_bits).to eq(expected_high_bits)
54
+ end
55
+
56
+ it 'sets the correct low order bits' do
57
+ expect(low_bits).to eq(expected_low_bits)
58
+ end
59
+
60
+ it 'serializes to bson' do
61
+ expect(buffer.length).to eq(16)
62
+ end
63
+
64
+ it 'deserializes to the correct bits' do
65
+ expect(from_bson.instance_variable_get(:@high)).to eq(expected_high_bits)
66
+ expect(from_bson.instance_variable_get(:@low)).to eq(expected_low_bits)
67
+ end
68
+ end
69
+
70
+ context 'when the object represents positive infinity' do
71
+
72
+ let(:expected_high_bits) { 0x7800000000000000 }
73
+ let(:expected_low_bits) { 0x0000000000000000 }
74
+
75
+ context 'when a BigDecimal is passed' do
76
+
77
+ let(:argument) { BigDecimal.new("Infinity") }
78
+
79
+ it_behaves_like 'an initialized BSON::Decimal128'
80
+ end
81
+
82
+ context 'when a String is passed' do
83
+
84
+ let(:argument) { "Infinity" }
85
+
86
+ it_behaves_like 'an initialized BSON::Decimal128'
87
+ end
88
+ end
89
+
90
+ context 'when the object represents negative infinity' do
91
+
92
+ let(:expected_high_bits) { 0xf800000000000000 }
93
+ let(:expected_low_bits) { 0x0000000000000000 }
94
+
95
+ context 'when a BigDecimal is passed' do
96
+
97
+ let(:argument) { BigDecimal.new("-Infinity") }
98
+
99
+ it_behaves_like 'an initialized BSON::Decimal128'
100
+ end
101
+
102
+ context 'when a String is passed' do
103
+
104
+ let(:argument) { "-Infinity" }
105
+
106
+ it_behaves_like 'an initialized BSON::Decimal128'
107
+ end
108
+ end
109
+
110
+ context 'when the object represents NaN' do
111
+
112
+ let(:expected_high_bits) { 0x7c00000000000000 }
113
+ let(:expected_low_bits) { 0x0000000000000000 }
114
+
115
+ context 'when a BigDecimal is passed' do
116
+
117
+ let(:argument) { BigDecimal.new("NaN") }
118
+
119
+ it_behaves_like 'an initialized BSON::Decimal128'
120
+ end
121
+
122
+ context 'when a String is passed' do
123
+
124
+ let(:argument) { "NaN" }
125
+
126
+ it_behaves_like 'an initialized BSON::Decimal128'
127
+ end
128
+ end
129
+
130
+ context 'when the object represents -NaN' do
131
+
132
+ let(:expected_high_bits) { 0xfc00000000000000 }
133
+ let(:expected_low_bits) { 0x0000000000000000 }
134
+
135
+ context 'when a String is passed' do
136
+
137
+ let(:argument) { "-NaN" }
138
+
139
+ it_behaves_like 'an initialized BSON::Decimal128'
140
+ end
141
+ end
142
+
143
+ context 'when the object represents SNaN' do
144
+
145
+ let(:expected_high_bits) { 0x7e00000000000000 }
146
+ let(:expected_low_bits) { 0x0000000000000000 }
147
+
148
+ context 'when a String is passed' do
149
+
150
+ let(:argument) { "SNaN" }
151
+
152
+ it_behaves_like 'an initialized BSON::Decimal128'
153
+ end
154
+ end
155
+
156
+ context 'when the object represents -SNaN' do
157
+
158
+ let(:expected_high_bits) { 0xfe00000000000000 }
159
+ let(:expected_low_bits) { 0x0000000000000000 }
160
+
161
+ context 'when a String is passed' do
162
+
163
+ let(:argument) { "-SNaN" }
164
+
165
+ it_behaves_like 'an initialized BSON::Decimal128'
166
+ end
167
+ end
168
+
169
+ context 'when the object represents -0' do
170
+
171
+ let(:expected_high_bits) { 0xb040000000000000 }
172
+ let(:expected_low_bits) { 0x0000000000000000 }
173
+
174
+ context 'when a BigDecimal is passed' do
175
+
176
+ let(:argument) { BigDecimal.new("-0") }
177
+
178
+ it_behaves_like 'an initialized BSON::Decimal128'
179
+ end
180
+
181
+ context 'when a String is passed' do
182
+
183
+ let(:argument) { "-0" }
184
+
185
+ it_behaves_like 'an initialized BSON::Decimal128'
186
+ end
187
+ end
188
+
189
+ context 'when the object represents a positive integer' do
190
+
191
+ let(:expected_high_bits) { 0x3040000000000000 }
192
+ let(:expected_low_bits) { 0x000000000000000c }
193
+
194
+ context 'when a BigDecimal is passed' do
195
+
196
+ let(:argument) { BigDecimal.new(12) }
197
+
198
+ it_behaves_like 'an initialized BSON::Decimal128'
199
+ end
200
+
201
+ context 'when a String is passed' do
202
+
203
+ let(:argument) { "12" }
204
+
205
+ it_behaves_like 'an initialized BSON::Decimal128'
206
+ end
207
+ end
208
+
209
+ context 'when the object represents a negative integer' do
210
+
211
+ let(:expected_high_bits) { 0xb040000000000000 }
212
+ let(:expected_low_bits) { 0x000000000000000c }
213
+
214
+ context 'when a BigDecimal is passed' do
215
+
216
+ let(:argument) { BigDecimal.new(-12) }
217
+
218
+ it_behaves_like 'an initialized BSON::Decimal128'
219
+ end
220
+
221
+ context 'when a String is passed' do
222
+
223
+ let(:argument) { "-12" }
224
+
225
+ it_behaves_like 'an initialized BSON::Decimal128'
226
+ end
227
+ end
228
+
229
+ context 'when the object represents a positive float' do
230
+
231
+ let(:expected_high_bits) { 0x3036000000000000 }
232
+ let(:expected_low_bits) { 0x0000000000003039 }
233
+
234
+ context 'when a BigDecimal is passed' do
235
+
236
+ let(:argument) { BigDecimal.new(0.12345, 5) }
237
+
238
+ it_behaves_like 'an initialized BSON::Decimal128'
239
+ end
240
+
241
+ context 'when a String is passed' do
242
+
243
+ let(:argument) { "0.12345" }
244
+
245
+ it_behaves_like 'an initialized BSON::Decimal128'
246
+ end
247
+ end
248
+
249
+ context 'when the object represents a negative float' do
250
+
251
+ let(:expected_high_bits) { 0xb036000000000000 }
252
+ let(:expected_low_bits) { 0x0000000000003039 }
253
+
254
+ context 'when a BigDecimal is passed' do
255
+
256
+ let(:argument) { BigDecimal.new(-0.12345, 5) }
257
+
258
+ it_behaves_like 'an initialized BSON::Decimal128'
259
+ end
260
+
261
+ context 'when a String is passed' do
262
+
263
+ let(:argument) { "-0.12345" }
264
+
265
+ it_behaves_like 'an initialized BSON::Decimal128'
266
+ end
267
+ end
268
+
269
+ context 'when the object represents a large positive integer' do
270
+
271
+ let(:expected_high_bits) { 0x30403cde6fff9732 }
272
+ let(:expected_low_bits) { 0xde825cd07e96aff2 }
273
+
274
+ context 'when a BigDecimal is passed' do
275
+
276
+ let(:argument) { BigDecimal.new(1234567890123456789012345678901234) }
277
+
278
+ it_behaves_like 'an initialized BSON::Decimal128'
279
+ end
280
+
281
+ context 'when a String is passed' do
282
+
283
+ let(:argument) { "1234567890123456789012345678901234" }
284
+
285
+ it_behaves_like 'an initialized BSON::Decimal128'
286
+ end
287
+ end
288
+
289
+ context 'when the object represents a large negative integer' do
290
+
291
+ let(:expected_high_bits) { 0xb0403cde6fff9732 }
292
+ let(:expected_low_bits) { 0xde825cd07e96aff2 }
293
+
294
+ context 'when a BigDecimal is passed' do
295
+
296
+ let(:argument) { BigDecimal.new(-1234567890123456789012345678901234) }
297
+
298
+ it_behaves_like 'an initialized BSON::Decimal128'
299
+ end
300
+
301
+ context 'when a String is passed' do
302
+
303
+ let(:argument) { "-1234567890123456789012345678901234" }
304
+
305
+ it_behaves_like 'an initialized BSON::Decimal128'
306
+ end
307
+ end
308
+ end
309
+
310
+ context 'when deserializing' do
311
+
312
+ context 'When the value has trailing zeroes' do
313
+
314
+ let(:hex) do
315
+ '18000000136400D0070000000000000000000000003A3000'
316
+ end
317
+
318
+ let(:packed) do
319
+ [ hex ].pack('H*')
320
+ end
321
+
322
+ let(:buffer) do
323
+ BSON::ByteBuffer.new(packed)
324
+ end
325
+
326
+ let(:decimal128) do
327
+ BSON::Document.from_bson(buffer)['d']
328
+ end
329
+
330
+ let(:object_from_string) do
331
+ BSON::Decimal128.from_string('2.000')
332
+ end
333
+
334
+ it 'has the correct high order' do
335
+ expect(decimal128.instance_variable_get(:@high)).to eq(3475090062469758976)
336
+ end
337
+
338
+ it 'has the correct low order' do
339
+ expect(decimal128.instance_variable_get(:@low)).to eq(2000)
340
+ end
341
+
342
+ it 'matches the object created from a string' do
343
+ expect(object_from_string).to eq(decimal128)
344
+ end
345
+ end
346
+ end
347
+
348
+ describe '#from_string' do
349
+
350
+ shared_examples_for 'a decimal128 initialized from a string' do
351
+
352
+ let(:decimal128) do
353
+ BSON::Decimal128.from_string(string)
354
+ end
355
+
356
+ let(:low_bits) do
357
+ decimal128.instance_variable_get(:@low)
358
+ end
359
+
360
+ let(:high_bits) do
361
+ decimal128.instance_variable_get(:@high)
362
+ end
363
+
364
+ it 'sets the correct high order bits' do
365
+ expect(high_bits).to eq(expected_high_bits)
366
+ end
367
+
368
+ it 'sets the correct low order bits' do
369
+ expect(low_bits).to eq(expected_low_bits)
370
+ end
371
+ end
372
+
373
+ context 'when the string represents a special type' do
374
+
375
+ context "when the string is 'NaN'" do
376
+
377
+ let(:string) { 'NaN' }
378
+
379
+ let(:expected_high_bits) { 0x7c00000000000000 }
380
+ let(:expected_low_bits) { 0x0000000000000000 }
381
+
382
+ it_behaves_like 'a decimal128 initialized from a string'
383
+ end
384
+
385
+ context "when the string is '-NaN'" do
386
+
387
+ let(:string) { '-NaN' }
388
+
389
+ let(:expected_high_bits) { 0xfc00000000000000 }
390
+ let(:expected_low_bits) { 0x0000000000000000 }
391
+
392
+ it_behaves_like 'a decimal128 initialized from a string'
393
+ end
394
+
395
+ context "when the string is 'SNaN'" do
396
+
397
+ let(:string) { 'SNaN' }
398
+
399
+ let(:expected_high_bits) { 0x7e00000000000000 }
400
+ let(:expected_low_bits) { 0x0000000000000000 }
401
+
402
+ it_behaves_like 'a decimal128 initialized from a string'
403
+ end
404
+
405
+ context "when the string is '-SNaN'" do
406
+
407
+ let(:string) { '-SNaN' }
408
+
409
+ let(:expected_high_bits) { 0xfe00000000000000 }
410
+ let(:expected_low_bits) { 0x0000000000000000 }
411
+
412
+ it_behaves_like 'a decimal128 initialized from a string'
413
+ end
414
+
415
+ context "when the string is 'Infinity'" do
416
+
417
+ let(:string) { 'Infinity' }
418
+
419
+ let(:expected_exponent) { nil }
420
+ let(:expected_significand) { nil }
421
+ let(:expected_high_bits) { 0x7800000000000000 }
422
+ let(:expected_low_bits) { 0x0000000000000000 }
423
+
424
+ it_behaves_like 'a decimal128 initialized from a string'
425
+ end
426
+
427
+ context "when the string is '-Infinity'" do
428
+
429
+ let(:string) { '-Infinity' }
430
+
431
+ let(:expected_exponent) { nil }
432
+ let(:expected_significand) { nil }
433
+ let(:expected_high_bits) { 0xf800000000000000 }
434
+ let(:expected_low_bits) { 0x0000000000000000 }
435
+
436
+ it_behaves_like 'a decimal128 initialized from a string'
437
+ end
438
+ end
439
+
440
+ context 'when the string represents 0' do
441
+
442
+ context "when the string is '0'" do
443
+
444
+ let(:string) { '0' }
445
+
446
+ let(:expected_exponent) { 0 }
447
+ let(:expected_significand) { 0 }
448
+ let(:expected_high_bits) { 0x3040000000000000 }
449
+ let(:expected_low_bits) { 0 }
450
+
451
+ it_behaves_like 'a decimal128 initialized from a string'
452
+ end
453
+
454
+ context "when the string is '-0'" do
455
+
456
+ let(:string) { '-0' }
457
+
458
+ let(:expected_exponent) { 0 }
459
+ let(:expected_significand) { 0 }
460
+ let(:expected_high_bits) { 0xb040000000000000 }
461
+ let(:expected_low_bits) { 0 }
462
+
463
+ it_behaves_like 'a decimal128 initialized from a string'
464
+ end
465
+
466
+ context "when the string is '0.0'" do
467
+
468
+ let(:string) { '0.0' }
469
+
470
+ let(:expected_exponent) { -1 }
471
+ let(:expected_significand) { 0 }
472
+ let(:expected_high_bits) { 0x303e000000000000 }
473
+ let(:expected_low_bits) { 0 }
474
+
475
+ it_behaves_like 'a decimal128 initialized from a string'
476
+ end
477
+ end
478
+
479
+ context 'when the string represents an integer' do
480
+
481
+ context "when the string is '1'" do
482
+
483
+ let(:string) { '1' }
484
+
485
+ let(:expected_exponent) { 0 }
486
+ let(:expected_significand) { 1 }
487
+ let(:expected_high_bits) { 0x3040000000000000 }
488
+ let(:expected_low_bits) { 0x1 }
489
+
490
+ it_behaves_like 'a decimal128 initialized from a string'
491
+ end
492
+
493
+ context "when the string is '-1'" do
494
+
495
+ let(:string) { '-1'}
496
+
497
+ let(:expected_exponent) { 0 }
498
+ let(:expected_significand) { 1 }
499
+ let(:expected_high_bits) { 0xb040000000000000 }
500
+ let(:expected_low_bits) { 0x1 }
501
+
502
+ it_behaves_like 'a decimal128 initialized from a string'
503
+ end
504
+
505
+ context "when the string is '20'" do
506
+
507
+ let(:string) { '20' }
508
+
509
+ let(:expected_exponent) { 0 }
510
+ let(:expected_significand) { 20 }
511
+ let(:expected_low_bits) { 0x14 }
512
+ let(:expected_high_bits) { 0x3040000000000000 }
513
+
514
+ it_behaves_like 'a decimal128 initialized from a string'
515
+ end
516
+
517
+ context "when the string is '-20'" do
518
+
519
+ let(:string) { '-20' }
520
+
521
+ let(:expected_exponent) { 0 }
522
+ let(:expected_significand) { 20 }
523
+ let(:expected_low_bits) { 0x14 }
524
+ let(:expected_high_bits) { 0xb040000000000000 }
525
+
526
+ it_behaves_like 'a decimal128 initialized from a string'
527
+ end
528
+
529
+ context "when the string is '12345678901234567'" do
530
+
531
+ let(:string) { '12345678901234567' }
532
+
533
+ let(:expected_exponent) { 0 }
534
+ let(:expected_significand) { 12345678901234567 }
535
+ let(:expected_low_bits) { 0x002bdc545d6b4b87 }
536
+ let(:expected_high_bits) { 0x3040000000000000 }
537
+
538
+ it_behaves_like 'a decimal128 initialized from a string'
539
+ end
540
+
541
+ context "when the string is '-12345678901234567'" do
542
+
543
+ let(:string) { '-12345678901234567' }
544
+
545
+ let(:expected_exponent) { 0 }
546
+ let(:expected_significand) { 12345678901234567 }
547
+ let(:expected_low_bits) { 0x002bdc545d6b4b87 }
548
+ let(:expected_high_bits) { 0xb040000000000000 }
549
+
550
+ it_behaves_like 'a decimal128 initialized from a string'
551
+ end
552
+
553
+ context "when the string is '12345689012345789012345'" do
554
+
555
+ let(:string) { '12345689012345789012345' }
556
+
557
+ let(:expected_exponent) { 0 }
558
+ let(:expected_significand) { 12345689012345789012345 }
559
+ let(:expected_low_bits) { 0x42da3a76f9e0d979 }
560
+ let(:expected_high_bits) { 0x304000000000029d }
561
+
562
+ it_behaves_like 'a decimal128 initialized from a string'
563
+ end
564
+
565
+ context "when the string is '-12345689012345789012345'" do
566
+
567
+ let(:string) { '-12345689012345789012345' }
568
+
569
+ let(:expected_exponent) { 0 }
570
+ let(:expected_significand) { 12345689012345789012345 }
571
+ let(:expected_low_bits) { 0x42da3a76f9e0d979 }
572
+ let(:expected_high_bits) { 0xb04000000000029d }
573
+
574
+ it_behaves_like 'a decimal128 initialized from a string'
575
+ end
576
+ end
577
+
578
+ context 'when the string represents a fraction' do
579
+
580
+ context "when the string is '0.1'" do
581
+
582
+ let(:string) { '0.1' }
583
+
584
+ let(:expected_exponent) { -1 }
585
+ let(:expected_significand) { 1 }
586
+ let(:expected_low_bits) { 0x1 }
587
+ let(:expected_high_bits) { 0x303e000000000000 }
588
+
589
+ it_behaves_like 'a decimal128 initialized from a string'
590
+ end
591
+
592
+ context "when the string is '-0.1'" do
593
+
594
+ let(:string) { '-0.1' }
595
+
596
+ let(:expected_exponent) { -1 }
597
+ let(:expected_significand) { 1 }
598
+ let(:expected_low_bits) { 0x1 }
599
+ let(:expected_high_bits) { 0xb03e000000000000 }
600
+
601
+ it_behaves_like 'a decimal128 initialized from a string'
602
+ end
603
+
604
+ context "when the string is '0.123'" do
605
+
606
+ let(:string) { '0.123' }
607
+
608
+ let(:expected_exponent) { -3 }
609
+ let(:expected_significand) { 123 }
610
+ let(:expected_low_bits) { 0x7b }
611
+ let(:expected_high_bits) { 0x303a000000000000 }
612
+
613
+ it_behaves_like 'a decimal128 initialized from a string'
614
+ end
615
+
616
+ context "when the string is '-0.123'" do
617
+
618
+ let(:string) { '-0.123' }
619
+
620
+ let(:expected_exponent) { -3 }
621
+ let(:expected_significand) { 123 }
622
+ let(:expected_low_bits) { 0x7b }
623
+ let(:expected_high_bits) { 0xb03a000000000000 }
624
+
625
+ it_behaves_like 'a decimal128 initialized from a string'
626
+ end
627
+
628
+ context "when the string is '0.1234567890123456789012345678901234'" do
629
+
630
+ let(:string) { '0.1234567890123456789012345678901234' }
631
+
632
+ let(:expected_exponent) { -34 }
633
+ let(:expected_significand) { 1234567890123456789012345678901234 }
634
+ let(:expected_low_bits) { 0xde825cd07e96aff2 }
635
+ let(:expected_high_bits) { 0x2ffc3cde6fff9732 }
636
+
637
+ it_behaves_like 'a decimal128 initialized from a string'
638
+ end
639
+ end
640
+
641
+ context 'when the string represents a fraction with a whole number' do
642
+
643
+ context "when the string is '1.2'" do
644
+
645
+ let(:string) { '1.2' }
646
+
647
+ let(:expected_exponent) { -1 }
648
+ let(:expected_significand) { 12 }
649
+ let(:expected_low_bits) { 0xc }
650
+ let(:expected_high_bits) { 0x303e000000000000 }
651
+
652
+ it_behaves_like 'a decimal128 initialized from a string'
653
+ end
654
+
655
+ context "when the string is '-1.2'" do
656
+
657
+ let(:string) { '-1.2' }
658
+
659
+ let(:expected_exponent) { -1 }
660
+ let(:expected_significand) { 12 }
661
+ let(:expected_low_bits) { 0xc }
662
+ let(:expected_high_bits) { 0xb03e000000000000 }
663
+
664
+ it_behaves_like 'a decimal128 initialized from a string'
665
+ end
666
+
667
+ context "when the string is '1.234'" do
668
+
669
+ let(:string) { '1.234' }
670
+
671
+ let(:expected_exponent) { -3 }
672
+ let(:expected_significand) { 1234 }
673
+ let(:expected_low_bits) { 0x4d2 }
674
+ let(:expected_high_bits) { 0x303a000000000000 }
675
+
676
+ it_behaves_like 'a decimal128 initialized from a string'
677
+ end
678
+
679
+ context "when the string is '-1.234'" do
680
+
681
+ let(:string) { '-1.234' }
682
+
683
+ let(:expected_exponent) { -3 }
684
+ let(:expected_significand) { 1234 }
685
+ let(:expected_low_bits) { 0x4d2 }
686
+ let(:expected_high_bits) { 0xb03a000000000000 }
687
+
688
+ it_behaves_like 'a decimal128 initialized from a string'
689
+ end
690
+
691
+ context "when the string is '123456789.123456789'" do
692
+
693
+ let(:string) { '123456789.123456789' }
694
+
695
+ let(:expected_exponent) { -9 }
696
+ let(:expected_significand) { 123456789123456789 }
697
+ let(:expected_low_bits) { 0x1b69b4bacd05f15 }
698
+ let(:expected_high_bits) { 0x302e000000000000 }
699
+
700
+ it_behaves_like 'a decimal128 initialized from a string'
701
+ end
702
+
703
+ context "when the string is '-123456789.123456789'" do
704
+
705
+ let(:string) { '-123456789.123456789' }
706
+
707
+ let(:expected_exponent) { -9 }
708
+ let(:expected_significand) { 123456789123456789 }
709
+ let(:expected_low_bits) { 0x1b69b4bacd05f15 }
710
+ let(:expected_high_bits) { 0xb02e000000000000 }
711
+
712
+ it_behaves_like 'a decimal128 initialized from a string'
713
+ end
714
+ end
715
+
716
+ context 'when the string represents a decimal with trailing zeros' do
717
+
718
+ context "when the string is '1.000'" do
719
+
720
+ let(:string) { '1.000' }
721
+
722
+ let(:expected_exponent) { -3 }
723
+ let(:expected_significand) { 1000 }
724
+ let(:expected_low_bits) { 0x3e8 }
725
+ let(:expected_high_bits) { 0x303a000000000000 }
726
+
727
+ it_behaves_like 'a decimal128 initialized from a string'
728
+ end
729
+
730
+ context "when the string is '-1.000'" do
731
+
732
+ let(:string) { '-1.000' }
733
+
734
+ let(:expected_exponent) { -3 }
735
+ let(:expected_significand) { 1000 }
736
+ let(:expected_low_bits) { 0x3e8 }
737
+ let(:expected_high_bits) { 0xb03a000000000000 }
738
+
739
+ it_behaves_like 'a decimal128 initialized from a string'
740
+ end
741
+
742
+ context "when the string is '100.000'" do
743
+
744
+ let(:string) { '100.000' }
745
+
746
+ let(:expected_exponent) { -3 }
747
+ let(:expected_significand) { 100000 }
748
+ let(:expected_low_bits) { 0x186a0 }
749
+ let(:expected_high_bits) { 0x303a000000000000 }
750
+
751
+ it_behaves_like 'a decimal128 initialized from a string'
752
+ end
753
+
754
+ context "when the string is '-100.000'" do
755
+
756
+ let(:string) { '-100.000' }
757
+
758
+ let(:expected_exponent) { -3 }
759
+ let(:expected_significand) { 100000 }
760
+ let(:expected_low_bits) { 0x186a0 }
761
+ let(:expected_high_bits) { 0xb03a000000000000 }
762
+
763
+ it_behaves_like 'a decimal128 initialized from a string'
764
+ end
765
+
766
+ context "when the string is '1.234000000'" do
767
+
768
+ let(:string) { '1.234000000' }
769
+
770
+ let(:expected_exponent) { -9 }
771
+ let(:expected_significand) { 1234000000 }
772
+ let(:expected_low_bits) { 0x498d5880 }
773
+ let(:expected_high_bits) { 0x302e000000000000 }
774
+
775
+ it_behaves_like 'a decimal128 initialized from a string'
776
+ end
777
+
778
+ context "when the string is '-1.234000000'" do
779
+
780
+ let(:string) { '-1.234000000' }
781
+
782
+ let(:expected_exponent) { -9 }
783
+ let(:expected_significand) { 1234000000 }
784
+ let(:expected_low_bits) { 0x498d5880 }
785
+ let(:expected_high_bits) { 0xb02e000000000000 }
786
+
787
+ it_behaves_like 'a decimal128 initialized from a string'
788
+ end
789
+
790
+ context 'when there are zeros following the decimal that are not trailing' do
791
+
792
+ context "when the string is '0.001234'" do
793
+
794
+ let(:string) { '0.001234' }
795
+
796
+ let(:expected_exponent) { -6 }
797
+ let(:expected_significand) { 1234 }
798
+ let(:expected_low_bits) { 0x4d2 }
799
+ let(:expected_high_bits) { 0x3034000000000000 }
800
+
801
+ it_behaves_like 'a decimal128 initialized from a string'
802
+ end
803
+ end
804
+
805
+ context 'when there are zeros following the decimal that are not trailing' do
806
+
807
+ context "when the string is '0.00123400000'" do
808
+
809
+ let(:string) { '0.00123400000' }
810
+
811
+ let(:expected_exponent) { -11 }
812
+ let(:expected_significand) { 123400000 }
813
+ let(:expected_low_bits) { 0x75aef40 }
814
+ let(:expected_high_bits) { 0x302a000000000000 }
815
+
816
+ it_behaves_like 'a decimal128 initialized from a string'
817
+ end
818
+ end
819
+ end
820
+
821
+ context 'when the string uses scientific notation' do
822
+
823
+ context 'when the exponent is positive' do
824
+
825
+ context 'when the positive exponent is denoted with E' do
826
+
827
+ context "when the string is '1.2E4'" do
828
+
829
+ let(:string) { '1.2E4' }
830
+
831
+ let(:expected_exponent) { 3 }
832
+ let(:expected_significand) { 12 }
833
+ let(:expected_low_bits) { 0xc }
834
+ let(:expected_high_bits) { 0x3046000000000000 }
835
+
836
+ it_behaves_like 'a decimal128 initialized from a string'
837
+ end
838
+
839
+ context "when the string is '-1.2E4'" do
840
+
841
+ let(:string) { '-1.2E4' }
842
+
843
+ let(:expected_exponent) { 3 }
844
+ let(:expected_significand) { 12 }
845
+ let(:expected_low_bits) { 0xc }
846
+ let(:expected_high_bits) { 0xb046000000000000 }
847
+
848
+ it_behaves_like 'a decimal128 initialized from a string'
849
+ end
850
+ end
851
+
852
+ context 'when the positive exponent is denoted with E+' do
853
+
854
+ context "when the string is '1.2E+4'" do
855
+
856
+ let(:string) { '1.2E4' }
857
+
858
+ let(:expected_exponent) { 3 }
859
+ let(:expected_significand) { 12 }
860
+ let(:expected_low_bits) { 0xc }
861
+ let(:expected_high_bits) { 0x3046000000000000 }
862
+
863
+ it_behaves_like 'a decimal128 initialized from a string'
864
+ end
865
+
866
+ context "when the string is '-1.2E+4'" do
867
+
868
+ let(:string) { '-1.2E4' }
869
+
870
+ let(:expected_exponent) { 3 }
871
+ let(:expected_significand) { 12 }
872
+ let(:expected_low_bits) { 0xc }
873
+ let(:expected_high_bits) { 0xb046000000000000 }
874
+
875
+ it_behaves_like 'a decimal128 initialized from a string'
876
+ end
877
+ end
878
+ end
879
+
880
+ context 'when the exponent is negative' do
881
+
882
+ context "when the string is '1.2E-4'" do
883
+
884
+ let(:string) { '1.2E-4' }
885
+
886
+ let(:expected_exponent) { -5 }
887
+ let(:expected_significand) { 12 }
888
+ let(:expected_low_bits) { 0xc }
889
+ let(:expected_high_bits) { 0x3036000000000000 }
890
+
891
+ it_behaves_like 'a decimal128 initialized from a string'
892
+ end
893
+
894
+ context "when the string is '-1.2E-4'" do
895
+
896
+ let(:string) { '-1.2E-4' }
897
+
898
+ let(:expected_exponent) { -5 }
899
+ let(:expected_significand) { 12 }
900
+ let(:expected_low_bits) { 0xc }
901
+ let(:expected_high_bits) { 0xb036000000000000 }
902
+
903
+ it_behaves_like 'a decimal128 initialized from a string'
904
+ end
905
+
906
+ context 'when there are trailing zeros' do
907
+
908
+ context "when the string is '1.200E-4'" do
909
+
910
+ let(:string) { '1.200E-4' }
911
+
912
+ let(:expected_exponent) { -7 }
913
+ let(:expected_significand) { 1200 }
914
+ let(:expected_low_bits) { 0x4b0 }
915
+ let(:expected_high_bits) { 0x3032000000000000 }
916
+
917
+ it_behaves_like 'a decimal128 initialized from a string'
918
+ end
919
+
920
+ context "when the string is '-1.200E-4'" do
921
+
922
+ let(:string) { '-1.200E-4' }
923
+
924
+ let(:expected_exponent) { -7 }
925
+ let(:expected_significand) { 1200 }
926
+ let(:expected_low_bits) { 0x4b0 }
927
+ let(:expected_high_bits) { 0xb032000000000000 }
928
+
929
+ it_behaves_like 'a decimal128 initialized from a string'
930
+ end
931
+ end
932
+ end
933
+ end
934
+ end
935
+
936
+ describe '#to_s' do
937
+
938
+ shared_examples_for 'a decimal128 printed to a string' do
939
+
940
+ let(:buffer) do
941
+ buffer = BSON::ByteBuffer.new
942
+ buffer.put_decimal128(low_bits, high_bits)
943
+ end
944
+ let(:decimal) { BSON::Decimal128.from_bson(buffer) }
945
+
946
+ it 'prints the correct string' do
947
+ expect(decimal.to_s).to eq(expected_string)
948
+ end
949
+ end
950
+
951
+ context 'when the bits represent a special type' do
952
+
953
+ context 'when the decimal is NaN' do
954
+
955
+ let(:expected_string) { 'NaN' }
956
+ let(:high_bits) { 0x7c00000000000000 }
957
+ let(:low_bits) { 0x0 }
958
+
959
+ it_behaves_like 'a decimal128 printed to a string'
960
+ end
961
+
962
+ context 'when the decimal is negative NaN' do
963
+
964
+ let(:expected_string) { 'NaN' }
965
+ let(:high_bits) { 0xfc00000000000000 }
966
+ let(:low_bits) { 0x0000000000000000 }
967
+
968
+ it_behaves_like 'a decimal128 printed to a string'
969
+ end
970
+
971
+ context 'when the decimal is SNaN' do
972
+
973
+ let(:expected_string) { 'NaN' }
974
+ let(:high_bits) { 0x7e00000000000000 }
975
+ let(:low_bits) { 0x0000000000000000 }
976
+
977
+ it_behaves_like 'a decimal128 printed to a string'
978
+ end
979
+
980
+ context 'when the decimal is -SNaN' do
981
+
982
+ let(:expected_string) { 'NaN' }
983
+ let(:high_bits) { 0xfe00000000000000 }
984
+ let(:low_bits) { 0x0000000000000000 }
985
+
986
+ it_behaves_like 'a decimal128 printed to a string'
987
+ end
988
+
989
+ context 'when the decimal is NaN with a payload' do
990
+
991
+ let(:expected_string) { 'NaN' }
992
+ let(:high_bits) { 0x7e00000000000000 }
993
+ let(:low_bits) { 0x0000000000000008 }
994
+
995
+ it_behaves_like 'a decimal128 printed to a string'
996
+ end
997
+
998
+ context 'when the decimal is positive Infinity' do
999
+
1000
+ let(:expected_string) { 'Infinity' }
1001
+ let(:high_bits) { 0x7800000000000000 }
1002
+ let(:low_bits) { 0x0000000000000000 }
1003
+
1004
+ it_behaves_like 'a decimal128 printed to a string'
1005
+ end
1006
+
1007
+ context 'when the decimal is negative Infinity' do
1008
+
1009
+ let(:expected_string) { '-Infinity' }
1010
+ let(:high_bits) { 0xf800000000000000 }
1011
+ let(:low_bits) { 0x0000000000000000 }
1012
+
1013
+ it_behaves_like 'a decimal128 printed to a string'
1014
+ end
1015
+ end
1016
+
1017
+ context 'when the string represents an integer' do
1018
+
1019
+ context 'when the decimal is 1' do
1020
+
1021
+ let(:expected_string) { '1' }
1022
+ let(:high_bits) { 0x3040000000000000 }
1023
+ let(:low_bits) { 0x0000000000000001 }
1024
+
1025
+ it_behaves_like 'a decimal128 printed to a string'
1026
+ end
1027
+
1028
+ context 'when the decimal is -1' do
1029
+
1030
+ let(:expected_string) { '-1' }
1031
+ let(:high_bits) { 0xb040000000000000 }
1032
+ let(:low_bits) { 0x0000000000000001 }
1033
+
1034
+ it_behaves_like 'a decimal128 printed to a string'
1035
+ end
1036
+
1037
+ context 'when the decimal is 20' do
1038
+
1039
+ let(:expected_string) { '20' }
1040
+ let(:high_bits) { 0x3040000000000000 }
1041
+ let(:low_bits) { 0x0000000000000014 }
1042
+
1043
+ it_behaves_like 'a decimal128 printed to a string'
1044
+ end
1045
+
1046
+ context 'when the decimal is -20' do
1047
+
1048
+ let(:expected_string) { '-20' }
1049
+ let(:high_bits) { 0xb040000000000000 }
1050
+ let(:low_bits) { 0x0000000000000014 }
1051
+
1052
+ it_behaves_like 'a decimal128 printed to a string'
1053
+ end
1054
+
1055
+ context 'when the decimal is 12345678901234567' do
1056
+
1057
+ let(:expected_string) { '12345678901234567' }
1058
+ let(:high_bits) { 0x3040000000000000 }
1059
+ let(:low_bits) { 0x002bdc545d6b4b87 }
1060
+
1061
+ it_behaves_like 'a decimal128 printed to a string'
1062
+ end
1063
+
1064
+ context 'when the decimal is -12345678901234567' do
1065
+
1066
+ let(:expected_string) { '-12345678901234567' }
1067
+ let(:high_bits) { 0xb040000000000000 }
1068
+ let(:low_bits) { 0x002bdc545d6b4b87 }
1069
+
1070
+ it_behaves_like 'a decimal128 printed to a string'
1071
+ end
1072
+
1073
+ context 'when the decimal is 12345689012345789012345' do
1074
+
1075
+ let(:expected_string) { '12345689012345789012345' }
1076
+ let(:high_bits) { 0x304000000000029d }
1077
+ let(:low_bits) { 0x42da3a76f9e0d979 }
1078
+
1079
+ it_behaves_like 'a decimal128 printed to a string'
1080
+ end
1081
+
1082
+ context 'when the decimal is -12345689012345789012345' do
1083
+
1084
+ let(:expected_string) { '-12345689012345789012345' }
1085
+ let(:high_bits) { 0xb04000000000029d }
1086
+ let(:low_bits) { 0x42da3a76f9e0d979 }
1087
+
1088
+ it_behaves_like 'a decimal128 printed to a string'
1089
+ end
1090
+ end
1091
+
1092
+ context 'when the string represents a fraction' do
1093
+
1094
+ context 'when the decimal is 0.1' do
1095
+
1096
+ let(:expected_string) { '0.1' }
1097
+ let(:high_bits) { 0x303e000000000000 }
1098
+ let(:low_bits) { 0x0000000000000001 }
1099
+
1100
+ it_behaves_like 'a decimal128 printed to a string'
1101
+ end
1102
+
1103
+ context 'when the decimal is -0.1' do
1104
+
1105
+ let(:expected_string) { '-0.1' }
1106
+ let(:high_bits) { 0xb03e000000000000 }
1107
+ let(:low_bits) { 0x0000000000000001 }
1108
+
1109
+ it_behaves_like 'a decimal128 printed to a string'
1110
+ end
1111
+
1112
+ context 'when the decimal is 0.123' do
1113
+
1114
+ let(:expected_string) { '0.123' }
1115
+ let(:high_bits) { 0x303a000000000000 }
1116
+ let(:low_bits) { 0x000000000000007b }
1117
+
1118
+ it_behaves_like 'a decimal128 printed to a string'
1119
+ end
1120
+
1121
+ context 'when the decimal is -0.123' do
1122
+
1123
+ let(:expected_string) { '-0.123' }
1124
+ let(:high_bits) { 0xb03a000000000000 }
1125
+ let(:low_bits) { 0x000000000000007b }
1126
+
1127
+ it_behaves_like 'a decimal128 printed to a string'
1128
+ end
1129
+ end
1130
+
1131
+ context 'when the decimal should have leading zeros' do
1132
+
1133
+ let(:expected_string) { '0.001234' }
1134
+ let(:high_bits) { 0x3034000000000000 }
1135
+ let(:low_bits) { 0x00000000000004d2 }
1136
+
1137
+ it_behaves_like 'a decimal128 printed to a string'
1138
+ end
1139
+
1140
+ context 'when the decimal has trailing zeros' do
1141
+
1142
+ let(:expected_string) { '2.000' }
1143
+ let(:high_bits) { 0x303a000000000000 }
1144
+ let(:low_bits) { 0x00000000000007d0 }
1145
+
1146
+ it_behaves_like 'a decimal128 printed to a string'
1147
+ end
1148
+ end
1149
+
1150
+ describe "#==" do
1151
+
1152
+ context "when the high and low bits are identical" do
1153
+
1154
+ let(:string) do
1155
+ '1.23'
1156
+ end
1157
+
1158
+ let(:decimal128) do
1159
+ described_class.from_string(string)
1160
+ end
1161
+
1162
+ let(:other_decimal) do
1163
+ described_class.from_string(string)
1164
+ end
1165
+
1166
+ it "returns true" do
1167
+ expect(decimal128).to eq(other_decimal)
1168
+ end
1169
+ end
1170
+
1171
+ context "when the high and low bits are different" do
1172
+
1173
+ let(:string) do
1174
+ '1.23'
1175
+ end
1176
+
1177
+ let(:decimal128) do
1178
+ described_class.from_string(string)
1179
+ end
1180
+
1181
+ it "returns false" do
1182
+ expect(decimal128).to_not eq(described_class.new(BigDecimal.new('2.00')))
1183
+ end
1184
+ end
1185
+
1186
+ context "when other is not a decimal128" do
1187
+
1188
+ it "returns false" do
1189
+ expect(described_class.from_string('1')).to_not eq(nil)
1190
+ end
1191
+ end
1192
+ end
1193
+
1194
+ describe "#===" do
1195
+
1196
+ let(:decimal128) do
1197
+ described_class.new(BigDecimal.new('1.23'))
1198
+ end
1199
+
1200
+ context "when comparing with another decimal128" do
1201
+
1202
+ context "when the high and low bits are equal" do
1203
+
1204
+ let(:other) do
1205
+ described_class.from_string(decimal128.to_s)
1206
+ end
1207
+
1208
+ it "returns true" do
1209
+ expect(decimal128 === other).to be true
1210
+ end
1211
+ end
1212
+
1213
+ context "when the high and low bits are not equal" do
1214
+
1215
+ let(:other) do
1216
+ described_class.new(BigDecimal.new('1000.003'))
1217
+ end
1218
+
1219
+ it "returns false" do
1220
+ expect(decimal128 === other).to be false
1221
+ end
1222
+ end
1223
+ end
1224
+
1225
+ context "when comparing to an decimal128 class" do
1226
+
1227
+ it "returns false" do
1228
+ expect(decimal128 === BSON::Decimal128).to be false
1229
+ end
1230
+ end
1231
+
1232
+ context "when comparing with a non string or decimal128" do
1233
+
1234
+ it "returns false" do
1235
+ expect(decimal128 === "test").to be false
1236
+ end
1237
+ end
1238
+
1239
+ context "when comparing with a non decimal128 class" do
1240
+
1241
+ it "returns false" do
1242
+ expect(decimal128 === String).to be false
1243
+ end
1244
+ end
1245
+ end
1246
+
1247
+ describe "#as_json" do
1248
+
1249
+ let(:object) do
1250
+ described_class.new(BigDecimal.new('1.23'))
1251
+ end
1252
+
1253
+ it "returns the decimal128 with $numberDecimal key" do
1254
+ expect(object.as_json).to eq({ "$numberDecimal" => object.to_s })
1255
+ end
1256
+ end
1257
+
1258
+ describe "::BSON_TYPE" do
1259
+
1260
+ it "returns 0x13" do
1261
+ expect(described_class::BSON_TYPE).to eq(19.chr)
1262
+ end
1263
+ end
1264
+
1265
+ describe "#bson_type" do
1266
+
1267
+ let(:code) do
1268
+ described_class.new(BigDecimal.new('1.23'))
1269
+ end
1270
+
1271
+ it "returns 0x13" do
1272
+ expect(code.bson_type).to eq(described_class::BSON_TYPE)
1273
+ end
1274
+ end
1275
+
1276
+ describe "#eql" do
1277
+
1278
+ context "when high and low bits are identical" do
1279
+
1280
+ let(:string) do
1281
+ '2.00'
1282
+ end
1283
+
1284
+ let(:decimal128) do
1285
+ described_class.from_string(string)
1286
+ end
1287
+
1288
+ let(:other_decimal) do
1289
+ described_class.from_string(string)
1290
+ end
1291
+
1292
+ it "returns true" do
1293
+ expect(decimal128).to eql(other_decimal)
1294
+ end
1295
+ end
1296
+
1297
+ context "when the high and low bit are different" do
1298
+
1299
+ let(:string) do
1300
+ '2.00'
1301
+ end
1302
+
1303
+ let(:decimal128) do
1304
+ described_class.from_string(string)
1305
+ end
1306
+
1307
+ it "returns false" do
1308
+ expect(decimal128).to_not eql(described_class.new(BigDecimal.new('2')))
1309
+ end
1310
+ end
1311
+
1312
+ context "when other is not a Decimal128" do
1313
+
1314
+ it "returns false" do
1315
+ expect(described_class.from_string('2')).to_not eql(nil)
1316
+ end
1317
+ end
1318
+ end
1319
+
1320
+ describe "#hash" do
1321
+
1322
+ let(:decimal128) do
1323
+ described_class.new(BigDecimal.new('-1234E+33'))
1324
+ end
1325
+
1326
+ it "returns a hash of the high and low bits" do
1327
+ expect(decimal128.hash).to eq(BSON::Decimal128.from_bson(decimal128.to_bson).hash)
1328
+ end
1329
+ end
1330
+
1331
+ describe "#inspect" do
1332
+
1333
+ let(:decimal128) do
1334
+ described_class.new(BigDecimal.new('1.23'))
1335
+ end
1336
+
1337
+ it "returns the inspection with the decimal128 to_s" do
1338
+ expect(decimal128.inspect).to eq("BSON::Decimal128('#{decimal128.to_s}')")
1339
+ end
1340
+ end
1341
+
1342
+ describe "#to_big_decimal" do
1343
+
1344
+ shared_examples_for 'a decimal128 convertible to a Ruby BigDecimal' do
1345
+
1346
+ let(:decimal128) do
1347
+ described_class.new(big_decimal)
1348
+ end
1349
+
1350
+ it 'properly converts the Decimal128 to a BigDecimal' do
1351
+ expect(decimal128.to_big_decimal).to eq(expected_big_decimal)
1352
+ end
1353
+ end
1354
+
1355
+ context 'when the Decimal128 is a special type' do
1356
+
1357
+ context 'when the value is Infinity' do
1358
+
1359
+ let(:big_decimal) do
1360
+ BigDecimal.new('Infinity')
1361
+ end
1362
+
1363
+ let(:expected_big_decimal) do
1364
+ big_decimal
1365
+ end
1366
+
1367
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1368
+ end
1369
+
1370
+ context 'when the value is -Infinity' do
1371
+
1372
+ let(:big_decimal) do
1373
+ BigDecimal.new('-Infinity')
1374
+ end
1375
+
1376
+ let(:expected_big_decimal) do
1377
+ big_decimal
1378
+ end
1379
+
1380
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1381
+ end
1382
+ end
1383
+
1384
+ context 'when the value represents an Integer' do
1385
+
1386
+ context 'when the value is 1' do
1387
+
1388
+ let(:big_decimal) do
1389
+ BigDecimal.new(1)
1390
+ end
1391
+
1392
+ let(:expected_big_decimal) do
1393
+ big_decimal
1394
+ end
1395
+
1396
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1397
+ end
1398
+
1399
+ context 'when the value is -1' do
1400
+
1401
+ let(:big_decimal) do
1402
+ BigDecimal.new(-1)
1403
+ end
1404
+
1405
+ let(:expected_big_decimal) do
1406
+ big_decimal
1407
+ end
1408
+
1409
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1410
+ end
1411
+
1412
+ context 'when the value is 20' do
1413
+
1414
+ let(:big_decimal) do
1415
+ BigDecimal.new(20)
1416
+ end
1417
+
1418
+ let(:expected_big_decimal) do
1419
+ big_decimal
1420
+ end
1421
+
1422
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1423
+ end
1424
+
1425
+ context 'when the value is -20' do
1426
+
1427
+ let(:big_decimal) do
1428
+ BigDecimal.new(-20)
1429
+ end
1430
+
1431
+ let(:expected_big_decimal) do
1432
+ big_decimal
1433
+ end
1434
+
1435
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1436
+ end
1437
+
1438
+ context 'when the value is 12345678901234567' do
1439
+
1440
+ let(:big_decimal) do
1441
+ BigDecimal.new(12345678901234567)
1442
+ end
1443
+
1444
+ let(:expected_big_decimal) do
1445
+ big_decimal
1446
+ end
1447
+
1448
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1449
+ end
1450
+
1451
+ context 'when the value is -12345678901234567' do
1452
+
1453
+ let(:big_decimal) do
1454
+ BigDecimal.new(-12345678901234567)
1455
+ end
1456
+
1457
+ let(:expected_big_decimal) do
1458
+ big_decimal
1459
+ end
1460
+
1461
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1462
+ end
1463
+
1464
+ context 'when the value is 12345689012345789012345' do
1465
+
1466
+ let(:big_decimal) do
1467
+ BigDecimal.new(12345689012345789012345)
1468
+ end
1469
+
1470
+ let(:expected_big_decimal) do
1471
+ big_decimal
1472
+ end
1473
+
1474
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1475
+ end
1476
+
1477
+ context 'when the value is -12345689012345789012345' do
1478
+
1479
+ let(:big_decimal) do
1480
+ BigDecimal.new(-12345689012345789012345)
1481
+ end
1482
+
1483
+ let(:expected_big_decimal) do
1484
+ big_decimal
1485
+ end
1486
+
1487
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1488
+ end
1489
+ end
1490
+
1491
+ context 'when the value has a fraction' do
1492
+
1493
+ context 'when the value is 0.1' do
1494
+
1495
+ let(:big_decimal) do
1496
+ BigDecimal.new(0.1, 1)
1497
+ end
1498
+
1499
+ let(:expected_big_decimal) do
1500
+ big_decimal
1501
+ end
1502
+
1503
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1504
+ end
1505
+
1506
+ context 'when the value is -0.1' do
1507
+
1508
+ let(:big_decimal) do
1509
+ BigDecimal.new(-0.1, 1)
1510
+ end
1511
+
1512
+ let(:expected_big_decimal) do
1513
+ big_decimal
1514
+ end
1515
+
1516
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1517
+ end
1518
+
1519
+ context 'when the value is 0.123' do
1520
+
1521
+ let(:big_decimal) do
1522
+ BigDecimal.new(0.123, 3)
1523
+ end
1524
+
1525
+ let(:expected_big_decimal) do
1526
+ big_decimal
1527
+ end
1528
+
1529
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1530
+ end
1531
+
1532
+ context 'when the value is -0.123' do
1533
+
1534
+ let(:big_decimal) do
1535
+ BigDecimal.new(-0.123, 3)
1536
+ end
1537
+
1538
+ let(:expected_big_decimal) do
1539
+ big_decimal
1540
+ end
1541
+
1542
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1543
+ end
1544
+ end
1545
+
1546
+ context 'when the value has leading zeros' do
1547
+
1548
+ let(:big_decimal) do
1549
+ BigDecimal.new(0.001234, 4)
1550
+ end
1551
+
1552
+ let(:expected_big_decimal) do
1553
+ big_decimal
1554
+ end
1555
+
1556
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1557
+ end
1558
+
1559
+ context 'when the value has trailing zeros' do
1560
+
1561
+ let(:big_decimal) do
1562
+ BigDecimal.new(2.000, 4)
1563
+ end
1564
+
1565
+ let(:expected_big_decimal) do
1566
+ big_decimal
1567
+ end
1568
+
1569
+ it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal'
1570
+ end
1571
+ end
1572
+
1573
+ context "when the class is loaded" do
1574
+
1575
+ let(:registered) do
1576
+ BSON::Registry.get(described_class::BSON_TYPE, 'field')
1577
+ end
1578
+
1579
+ it "registers the type" do
1580
+ expect(registered).to eq(described_class)
1581
+ end
1582
+ end
1583
+ end