bson 4.1.1-java → 4.2.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.
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