bson 4.9.0 → 4.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +15 -6
  4. data/ext/bson/bson-native.h +4 -0
  5. data/ext/bson/init.c +75 -23
  6. data/ext/bson/read.c +63 -11
  7. data/ext/bson/write.c +42 -3
  8. data/lib/bson/active_support.rb +1 -0
  9. data/lib/bson/array.rb +5 -1
  10. data/lib/bson/big_decimal.rb +67 -0
  11. data/lib/bson/binary.rb +8 -5
  12. data/lib/bson/boolean.rb +2 -1
  13. data/lib/bson/code.rb +2 -1
  14. data/lib/bson/code_with_scope.rb +2 -1
  15. data/lib/bson/config.rb +1 -0
  16. data/lib/bson/date.rb +1 -0
  17. data/lib/bson/date_time.rb +2 -1
  18. data/lib/bson/db_pointer.rb +2 -1
  19. data/lib/bson/dbref.rb +152 -0
  20. data/lib/bson/decimal128/builder.rb +27 -20
  21. data/lib/bson/decimal128.rb +39 -14
  22. data/lib/bson/document.rb +61 -18
  23. data/lib/bson/environment.rb +1 -0
  24. data/lib/bson/error.rb +13 -0
  25. data/lib/bson/ext_json.rb +24 -11
  26. data/lib/bson/false_class.rb +2 -1
  27. data/lib/bson/float.rb +21 -32
  28. data/lib/bson/hash.rb +18 -6
  29. data/lib/bson/int32.rb +3 -2
  30. data/lib/bson/int64.rb +3 -2
  31. data/lib/bson/integer.rb +3 -2
  32. data/lib/bson/json.rb +1 -0
  33. data/lib/bson/max_key.rb +3 -2
  34. data/lib/bson/min_key.rb +3 -2
  35. data/lib/bson/nil_class.rb +2 -1
  36. data/lib/bson/object.rb +1 -0
  37. data/lib/bson/object_id.rb +4 -3
  38. data/lib/bson/open_struct.rb +1 -0
  39. data/lib/bson/regexp.rb +24 -7
  40. data/lib/bson/registry.rb +1 -0
  41. data/lib/bson/specialized.rb +1 -0
  42. data/lib/bson/string.rb +3 -2
  43. data/lib/bson/symbol.rb +2 -1
  44. data/lib/bson/time.rb +4 -3
  45. data/lib/bson/time_with_zone.rb +1 -0
  46. data/lib/bson/timestamp.rb +7 -6
  47. data/lib/bson/true_class.rb +2 -1
  48. data/lib/bson/undefined.rb +2 -1
  49. data/lib/bson/version.rb +2 -1
  50. data/lib/bson.rb +8 -5
  51. data/spec/README.md +14 -0
  52. data/spec/bson/array_spec.rb +17 -0
  53. data/spec/bson/big_decimal_spec.rb +316 -0
  54. data/spec/bson/binary_spec.rb +1 -1
  55. data/spec/bson/binary_uuid_spec.rb +12 -0
  56. data/spec/bson/byte_buffer_read_spec.rb +59 -3
  57. data/spec/bson/byte_buffer_spec.rb +129 -6
  58. data/spec/bson/byte_buffer_write_spec.rb +96 -0
  59. data/spec/bson/date_time_spec.rb +53 -0
  60. data/spec/bson/dbref_legacy_spec.rb +169 -0
  61. data/spec/bson/dbref_spec.rb +487 -0
  62. data/spec/bson/decimal128_spec.rb +231 -0
  63. data/spec/bson/document_as_spec.rb +46 -0
  64. data/spec/bson/document_spec.rb +43 -1
  65. data/spec/bson/ext_json_parse_spec.rb +37 -0
  66. data/spec/bson/hash_as_spec.rb +57 -0
  67. data/spec/bson/hash_spec.rb +105 -0
  68. data/spec/bson/int64_spec.rb +4 -24
  69. data/spec/bson/raw_spec.rb +18 -1
  70. data/spec/bson/regexp_spec.rb +52 -0
  71. data/spec/runners/common_driver.rb +1 -1
  72. data/spec/shared/LICENSE +20 -0
  73. data/spec/shared/bin/get-mongodb-download-url +17 -0
  74. data/spec/shared/bin/s3-copy +45 -0
  75. data/spec/shared/bin/s3-upload +69 -0
  76. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  77. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  78. data/spec/shared/lib/mrss/constraints.rb +386 -0
  79. data/spec/shared/lib/mrss/docker_runner.rb +271 -0
  80. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  81. data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
  82. data/spec/shared/lib/mrss/server_version_registry.rb +120 -0
  83. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  84. data/spec/shared/lib/mrss/utils.rb +15 -0
  85. data/spec/shared/share/Dockerfile.erb +338 -0
  86. data/spec/shared/share/haproxy-1.conf +16 -0
  87. data/spec/shared/share/haproxy-2.conf +17 -0
  88. data/spec/shared/shlib/distro.sh +74 -0
  89. data/spec/shared/shlib/server.sh +367 -0
  90. data/spec/shared/shlib/set_env.sh +131 -0
  91. data/spec/spec_helper.rb +31 -0
  92. data/spec/spec_tests/common_driver_spec.rb +2 -1
  93. data/spec/spec_tests/data/corpus/binary.json +33 -0
  94. data/spec/spec_tests/data/corpus/dbref.json +21 -1
  95. data/spec/spec_tests/data/corpus/document.json +4 -0
  96. data/spec/spec_tests/data/corpus/regex.json +2 -2
  97. data/spec/spec_tests/data/corpus/timestamp.json +10 -0
  98. data/spec/spec_tests/data/corpus/top.json +23 -12
  99. data/spec/support/spec_config.rb +8 -1
  100. data.tar.gz.sig +0 -0
  101. metadata +168 -93
  102. metadata.gz.sig +1 -0
data/lib/bson.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2009-2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,22 +39,22 @@ module BSON
38
39
  # Constant for binary string encoding.
39
40
  #
40
41
  # @since 2.0.0
41
- BINARY = "BINARY".freeze
42
+ BINARY = "BINARY"
42
43
 
43
44
  # Constant for bson types that don't actually serialize a value.
44
45
  #
45
46
  # @since 2.0.0
46
- NO_VALUE = "".force_encoding(BINARY).freeze
47
+ NO_VALUE = ::String.new(encoding: BINARY).freeze
47
48
 
48
49
  # Constant for a null byte (0x00).
49
50
  #
50
51
  # @since 2.0.0
51
- NULL_BYTE = 0.chr.force_encoding(BINARY).freeze
52
+ NULL_BYTE = ::String.new(0.chr, encoding: BINARY).freeze
52
53
 
53
54
  # Constant for UTF-8 string encoding.
54
55
  #
55
56
  # @since 2.0.0
56
- UTF8 = "UTF-8".freeze
57
+ UTF8 = "UTF-8"
57
58
  end
58
59
 
59
60
  require "bson/config"
@@ -73,11 +74,13 @@ require "bson/date"
73
74
  require "bson/date_time"
74
75
  require "bson/db_pointer"
75
76
  require "bson/decimal128"
77
+ require "bson/big_decimal"
76
78
  require "bson/document"
77
79
  require "bson/ext_json"
78
80
  require "bson/false_class"
79
81
  require "bson/float"
80
82
  require "bson/hash"
83
+ require "bson/dbref"
81
84
  require "bson/open_struct"
82
85
  require "bson/max_key"
83
86
  require "bson/min_key"
@@ -100,7 +103,7 @@ require "bson/version"
100
103
  begin
101
104
  if BSON::Environment.jruby?
102
105
  require "bson-ruby.jar"
103
- org.bson.NativeService.new.basicLoad(JRuby.runtime)
106
+ JRuby::Util.load_ext("org.bson.NativeService")
104
107
  else
105
108
  require "bson_native"
106
109
  end
data/spec/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # Running BSON Ruby Tests
2
+
3
+ ## Quick Start
4
+
5
+ The test suite requires shared tooling that is stored in a separate repository
6
+ and is referenced as a submodule. After checking out the desired bson-ruby
7
+ branch, check out the matching submodules:
8
+
9
+ git submodule init
10
+ git submodule update
11
+
12
+ Then, to run the test suite:
13
+
14
+ rake
@@ -132,6 +132,23 @@ describe Array do
132
132
  end
133
133
  end
134
134
  end
135
+
136
+ context 'when array contains value of an unserializable class' do
137
+ class ArraySpecUnserializableClass
138
+ end
139
+
140
+ let(:obj) do
141
+ [ArraySpecUnserializableClass.new]
142
+ end
143
+
144
+ it 'raises UnserializableClass' do
145
+ lambda do
146
+ obj.to_bson
147
+ end.should raise_error(BSON::Error::UnserializableClass,
148
+ # C extension does not provide element position in the exception message.
149
+ /(Array element at position 0|Value) does not define its BSON serialized type:.*ArraySpecUnserializableClass/)
150
+ end
151
+ end
135
152
  end
136
153
 
137
154
  describe "#to_bson_normalized_value" do
@@ -0,0 +1,316 @@
1
+ # Copyright (C) 2016-2021 MongoDB Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "spec_helper"
16
+
17
+ describe BSON::BigDecimal do
18
+
19
+ describe '#from_bson' do
20
+ shared_examples_for 'a BSON::BigDecimal deserializer' do
21
+
22
+ let(:decimal128) do
23
+ BSON::Decimal128.new(argument)
24
+ end
25
+
26
+ let(:deserialized_big_decimal) do
27
+ BigDecimal.from_bson(decimal128.to_bson)
28
+ end
29
+
30
+ let(:deserialized_decimal128) do
31
+ BSON::Decimal128.from_bson(decimal128.to_bson)
32
+ end
33
+
34
+ it 'deserializes Decimal128 encoded bson correctly' do
35
+ if deserialized_decimal128.to_s == "NaN"
36
+ expect(deserialized_big_decimal.nan?).to be true
37
+ else
38
+ expect(deserialized_big_decimal).to eq(deserialized_decimal128.to_big_decimal)
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'when Infinity is passed' do
44
+
45
+ let(:argument) { "Infinity" }
46
+
47
+ it_behaves_like 'a BSON::BigDecimal deserializer'
48
+ end
49
+
50
+ context 'when -Infinity is passed' do
51
+
52
+ let(:argument) { "-Infinity" }
53
+
54
+ it_behaves_like 'a BSON::BigDecimal deserializer'
55
+ end
56
+
57
+ context 'when NaN is passed' do
58
+
59
+ let(:argument) { "NaN" }
60
+
61
+ it_behaves_like 'a BSON::BigDecimal deserializer'
62
+ end
63
+
64
+ context 'when -NaN is passed' do
65
+ let(:argument) { "-NaN" }
66
+
67
+ it_behaves_like 'a BSON::BigDecimal deserializer'
68
+ end
69
+
70
+ context 'when SNaN is passed' do
71
+ let(:argument) { "SNaN" }
72
+
73
+ it_behaves_like 'a BSON::BigDecimal deserializer'
74
+ end
75
+
76
+ context 'when -SNaN is passed' do
77
+ let(:argument) { "SNaN" }
78
+
79
+ it_behaves_like 'a BSON::BigDecimal deserializer'
80
+ end
81
+
82
+ context 'when -0 is passed' do
83
+ let(:argument) { "-0" }
84
+
85
+ it_behaves_like 'a BSON::BigDecimal deserializer'
86
+ end
87
+
88
+ context 'when a positive integer is passed' do
89
+ let(:argument) { "12" }
90
+
91
+ it_behaves_like 'a BSON::BigDecimal deserializer'
92
+ end
93
+
94
+ context 'when a negative integer is passed' do
95
+ let(:argument) { "-12" }
96
+
97
+ it_behaves_like 'a BSON::BigDecimal deserializer'
98
+ end
99
+
100
+ context 'when a positive float is passed' do
101
+ let(:argument) { "0.12345" }
102
+
103
+ it_behaves_like 'a BSON::BigDecimal deserializer'
104
+ end
105
+
106
+ context 'when a negative float is passed' do
107
+ let(:argument) { "-0.12345" }
108
+
109
+ it_behaves_like 'a BSON::BigDecimal deserializer'
110
+ end
111
+
112
+ context 'when a large positive integer is passed' do
113
+ let(:argument) { "1234567890123456789012345678901234" }
114
+
115
+ it_behaves_like 'a BSON::BigDecimal deserializer'
116
+ end
117
+
118
+ context 'when a large negative integer is passed' do
119
+ let(:argument) { "-1234567890123456789012345678901234" }
120
+
121
+ it_behaves_like 'a BSON::BigDecimal deserializer'
122
+ end
123
+ end
124
+
125
+ describe "#to_bson" do
126
+ shared_examples_for 'a BSON::BigDecimal serializer' do
127
+
128
+ let(:decimal128) do
129
+ BSON::Decimal128.new(BigDecimal(argument).to_s)
130
+ end
131
+
132
+ let(:decimal_128_bson) do
133
+ decimal128.to_bson
134
+ end
135
+
136
+ let(:big_decimal_bson) do
137
+ BigDecimal(argument).to_bson
138
+ end
139
+
140
+ it 'serializes BigDecimals correctly' do
141
+ expect(decimal_128_bson.to_s).to eq(big_decimal_bson.to_s)
142
+ end
143
+ end
144
+
145
+ context 'when Infinity is passed' do
146
+
147
+ let(:argument) { "Infinity" }
148
+
149
+ it_behaves_like 'a BSON::BigDecimal serializer'
150
+ end
151
+
152
+ context 'when -Infinity is passed' do
153
+
154
+ let(:argument) { "-Infinity" }
155
+
156
+ it_behaves_like 'a BSON::BigDecimal serializer'
157
+ end
158
+
159
+ context 'when NaN is passed' do
160
+
161
+ let(:argument) { "NaN" }
162
+
163
+ it_behaves_like 'a BSON::BigDecimal serializer'
164
+ end
165
+
166
+ context 'when -0 is passed' do
167
+ let(:argument) { "-0" }
168
+
169
+ it_behaves_like 'a BSON::BigDecimal serializer'
170
+ end
171
+
172
+ context 'when a positive integer is passed' do
173
+ let(:argument) { "12" }
174
+
175
+ it_behaves_like 'a BSON::BigDecimal serializer'
176
+ end
177
+
178
+ context 'when a negative integer is passed' do
179
+ let(:argument) { "-12" }
180
+
181
+ it_behaves_like 'a BSON::BigDecimal serializer'
182
+ end
183
+
184
+ context 'when a positive float is passed' do
185
+ let(:argument) { "0.12345" }
186
+
187
+ it_behaves_like 'a BSON::BigDecimal serializer'
188
+ end
189
+
190
+ context 'when a negative float is passed' do
191
+ let(:argument) { "-0.12345" }
192
+
193
+ it_behaves_like 'a BSON::BigDecimal serializer'
194
+ end
195
+
196
+ context 'when a large positive integer is passed' do
197
+ let(:argument) { "1234567890123456789012345678901234" }
198
+
199
+ it_behaves_like 'a BSON::BigDecimal serializer'
200
+ end
201
+
202
+ context 'when a large negative integer is passed' do
203
+ let(:argument) { "-1234567890123456789012345678901234" }
204
+
205
+ it_behaves_like 'a BSON::BigDecimal serializer'
206
+ end
207
+
208
+ context "when passing an out of range Decimal128" do
209
+ let(:argument) { "1E1000000" }
210
+
211
+ it "raises an error" do
212
+ expect do
213
+ BigDecimal(argument).to_bson
214
+ end.to raise_error(BSON::Decimal128::InvalidRange)
215
+ end
216
+ end
217
+
218
+ context "when passing a number with too much precision for Decimal128" do
219
+ let(:argument) { "1.000000000000000000000000000000000000000000000000001" }
220
+
221
+ it "raises an error" do
222
+ expect do
223
+ BigDecimal(argument).to_bson
224
+ end.to raise_error(BSON::Decimal128::UnrepresentablePrecision)
225
+ end
226
+ end
227
+ end
228
+
229
+ describe "#from_bson/#to_bson" do
230
+ shared_examples_for 'a BSON::BigDecimal round trip' do
231
+
232
+ let(:big_decimal) do
233
+ BigDecimal(argument)
234
+ end
235
+
236
+ let(:big_decimal_bson) do
237
+ big_decimal.to_bson
238
+ end
239
+
240
+ let(:deserialized_big_decimal) do
241
+ BigDecimal.from_bson(big_decimal_bson)
242
+ end
243
+
244
+ it 'serializes BigDecimals correctly' do
245
+ if big_decimal.nan?
246
+ expect(deserialized_big_decimal.nan?).to be true
247
+ else
248
+ expect(deserialized_big_decimal).to eq(big_decimal)
249
+ end
250
+ end
251
+ end
252
+
253
+ context 'when Infinity is passed' do
254
+
255
+ let(:argument) { "Infinity" }
256
+
257
+ it_behaves_like 'a BSON::BigDecimal round trip'
258
+ end
259
+
260
+ context 'when -Infinity is passed' do
261
+
262
+ let(:argument) { "-Infinity" }
263
+
264
+ it_behaves_like 'a BSON::BigDecimal round trip'
265
+ end
266
+
267
+ context 'when NaN is passed' do
268
+
269
+ let(:argument) { "NaN" }
270
+
271
+ it_behaves_like 'a BSON::BigDecimal round trip'
272
+ end
273
+
274
+ context 'when -0 is passed' do
275
+ let(:argument) { "-0" }
276
+
277
+ it_behaves_like 'a BSON::BigDecimal round trip'
278
+ end
279
+
280
+ context 'when a positive integer is passed' do
281
+ let(:argument) { "12" }
282
+
283
+ it_behaves_like 'a BSON::BigDecimal round trip'
284
+ end
285
+
286
+ context 'when a negative integer is passed' do
287
+ let(:argument) { "-12" }
288
+
289
+ it_behaves_like 'a BSON::BigDecimal round trip'
290
+ end
291
+
292
+ context 'when a positive float is passed' do
293
+ let(:argument) { "0.12345" }
294
+
295
+ it_behaves_like 'a BSON::BigDecimal round trip'
296
+ end
297
+
298
+ context 'when a negative float is passed' do
299
+ let(:argument) { "-0.12345" }
300
+
301
+ it_behaves_like 'a BSON::BigDecimal round trip'
302
+ end
303
+
304
+ context 'when a large positive integer is passed' do
305
+ let(:argument) { "1234567890123456789012345678901234" }
306
+
307
+ it_behaves_like 'a BSON::BigDecimal round trip'
308
+ end
309
+
310
+ context 'when a large negative integer is passed' do
311
+ let(:argument) { "-1234567890123456789012345678901234" }
312
+
313
+ it_behaves_like 'a BSON::BigDecimal round trip'
314
+ end
315
+ end
316
+ end
@@ -255,7 +255,7 @@ describe BSON::Binary do
255
255
  let(:obj) { described_class.new("\x00" * 16, :uuid) }
256
256
 
257
257
  it 'accepts symbol representation' do
258
- expect(obj.to_uuid(:standard)).to eq('00000000-0000-0000-0000000000000000')
258
+ expect(obj.to_uuid(:standard)).to eq('00000000-0000-0000-0000-000000000000')
259
259
  end
260
260
 
261
261
  it 'rejects string representation' do
@@ -136,6 +136,10 @@ describe "BSON::Binary - UUID spec tests" do
136
136
  it 'decodes as python legacy' do
137
137
  expect(binary.to_uuid(:python_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
138
138
  end
139
+
140
+ it 'expects four dashes when output as String' do
141
+ expect(binary.to_uuid(:csharp_legacy)).to eq("00112233-4455-6677-8899-aabbccddeeff")
142
+ end
139
143
  end
140
144
 
141
145
  context ':uuid_old, java legacy encoded' do
@@ -154,6 +158,10 @@ describe "BSON::Binary - UUID spec tests" do
154
158
  it 'decodes as python legacy' do
155
159
  expect(binary.to_uuid(:python_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
156
160
  end
161
+
162
+ it 'expects four dashes when output as String' do
163
+ expect(binary.to_uuid(:java_legacy)).to eq("00112233-4455-6677-8899-aabbccddeeff")
164
+ end
157
165
  end
158
166
 
159
167
  context ':uuid_old, python legacy encoded' do
@@ -172,6 +180,10 @@ describe "BSON::Binary - UUID spec tests" do
172
180
  it 'decodes as python legacy' do
173
181
  expect(binary.to_uuid(:python_legacy).gsub('-', '').upcase).to eq("00112233445566778899AABBCCDDEEFF")
174
182
  end
183
+
184
+ it 'expects four dashes when output as String' do
185
+ expect(binary.to_uuid(:python_legacy)).to eq("00112233-4455-6677-8899-aabbccddeeff")
186
+ end
175
187
  end
176
188
  end
177
189
  end
@@ -66,7 +66,7 @@ describe BSON::ByteBuffer do
66
66
  describe '#get_double' do
67
67
 
68
68
  let(:buffer) do
69
- described_class.new("#{12.5.to_bson.to_s}")
69
+ described_class.new(12.5.to_bson.to_s)
70
70
  end
71
71
 
72
72
  let!(:double) do
@@ -85,7 +85,7 @@ describe BSON::ByteBuffer do
85
85
  describe '#get_int32' do
86
86
 
87
87
  let(:buffer) do
88
- described_class.new("#{12.to_bson.to_s}")
88
+ described_class.new(12.to_bson.to_s)
89
89
  end
90
90
 
91
91
  let!(:int32) do
@@ -101,10 +101,66 @@ describe BSON::ByteBuffer do
101
101
  end
102
102
  end
103
103
 
104
+ describe '#get_uint32' do
105
+ context 'when using 2^32-1' do
106
+ let(:buffer) do
107
+ described_class.new(4294967295.to_bson.to_s)
108
+ end
109
+
110
+ let!(:int32) do
111
+ buffer.get_uint32
112
+ end
113
+
114
+ it 'gets the uint32 from the buffer' do
115
+ expect(int32).to eq(4294967295)
116
+ end
117
+
118
+ it 'increments the position by 4' do
119
+ expect(buffer.read_position).to eq(4)
120
+ end
121
+ end
122
+
123
+ context 'when using 2^32-2' do
124
+ let(:buffer) do
125
+ described_class.new(4294967294.to_bson.to_s)
126
+ end
127
+
128
+ let!(:int32) do
129
+ buffer.get_uint32
130
+ end
131
+
132
+ it 'gets the uint32 from the buffer' do
133
+ expect(int32).to eq(4294967294)
134
+ end
135
+
136
+ it 'increments the position by 4' do
137
+ expect(buffer.read_position).to eq(4)
138
+ end
139
+ end
140
+
141
+ context 'when using 0' do
142
+ let(:buffer) do
143
+ described_class.new(0.to_bson.to_s)
144
+ end
145
+
146
+ let!(:int32) do
147
+ buffer.get_uint32
148
+ end
149
+
150
+ it 'gets the uint32 from the buffer' do
151
+ expect(int32).to eq(0)
152
+ end
153
+
154
+ it 'increments the position by 4' do
155
+ expect(buffer.read_position).to eq(4)
156
+ end
157
+ end
158
+ end
159
+
104
160
  describe '#get_int64' do
105
161
 
106
162
  let(:buffer) do
107
- described_class.new("#{(Integer::MAX_64BIT - 1).to_bson.to_s}")
163
+ described_class.new((Integer::MAX_64BIT - 1).to_bson.to_s)
108
164
  end
109
165
 
110
166
  let!(:int64) do
@@ -31,12 +31,14 @@ describe BSON::ByteBuffer do
31
31
  described_class.new
32
32
  end
33
33
 
34
- before do
35
- buffer.put_int32(5)
36
- end
37
-
38
- it 'returns the length of the buffer' do
39
- expect(buffer.length).to eq(4)
34
+ context '#put_int32' do
35
+ before do
36
+ buffer.put_int32(5)
37
+ end
38
+
39
+ it 'returns the length of the buffer' do
40
+ expect(buffer.length).to eq(4)
41
+ end
40
42
  end
41
43
  end
42
44
 
@@ -50,6 +52,50 @@ describe BSON::ByteBuffer do
50
52
  expect(buffer.length).to eq(2)
51
53
  end
52
54
  end
55
+
56
+ context 'after the byte buffer was read from' do
57
+
58
+ let(:buffer) do
59
+ described_class.new({}.to_bson.to_s)
60
+ end
61
+
62
+ it 'returns the number of bytes remaining in the buffer' do
63
+ expect(buffer.length).to eq(5)
64
+ buffer.get_int32
65
+ expect(buffer.length).to eq(1)
66
+ end
67
+ end
68
+
69
+ context 'after the byte buffer was converted to string' do
70
+
71
+ shared_examples 'returns the total buffer length' do
72
+ it 'returns the total buffer length' do
73
+ expect(buffer.length).to eq(5)
74
+ buffer.to_s.length.should == 5
75
+ expect(buffer.length).to eq(5)
76
+ end
77
+ end
78
+
79
+ context 'read buffer' do
80
+
81
+ let(:buffer) do
82
+ described_class.new({}.to_bson.to_s)
83
+ end
84
+
85
+ include_examples 'returns the total buffer length'
86
+ end
87
+
88
+ context 'write buffer' do
89
+
90
+ let(:buffer) do
91
+ described_class.new.tap do |buffer|
92
+ buffer.put_bytes('hello')
93
+ end
94
+ end
95
+
96
+ include_examples 'returns the total buffer length'
97
+ end
98
+ end
53
99
  end
54
100
 
55
101
  describe '#rewind!' do
@@ -104,4 +150,81 @@ describe BSON::ByteBuffer do
104
150
  expect(buffer.write_position).to eq(1)
105
151
  end
106
152
  end
153
+
154
+ describe 'write followed by read' do
155
+ let(:buffer) do
156
+ described_class.new
157
+ end
158
+
159
+ context 'one cycle' do
160
+ it 'returns the written data' do
161
+ buffer.put_cstring('hello')
162
+ buffer.get_cstring.should == 'hello'
163
+ end
164
+ end
165
+
166
+ context 'two cycles' do
167
+ it 'returns the written data' do
168
+ buffer.put_cstring('hello')
169
+ buffer.get_cstring.should == 'hello'
170
+
171
+ buffer.put_cstring('world')
172
+ buffer.get_cstring.should == 'world'
173
+ end
174
+ end
175
+
176
+ context 'mixed cycles' do
177
+ it 'returns the written data' do
178
+ if BSON::Environment.jruby?
179
+ pending 'RUBY-2334'
180
+ end
181
+
182
+ buffer.put_int32(1)
183
+ buffer.put_int32(2)
184
+
185
+ buffer.get_int32.should == 1
186
+
187
+ buffer.put_int32(3)
188
+
189
+ buffer.get_int32.should == 2
190
+ buffer.get_int32.should == 3
191
+ end
192
+ end
193
+ end
194
+
195
+ describe '#to_s' do
196
+ context 'read buffer' do
197
+ let(:buffer) do
198
+ described_class.new("\x18\x00\x00\x00*\x00\x00\x00")
199
+ end
200
+
201
+ it 'returns the data' do
202
+ buffer.to_s.should == "\x18\x00\x00\x00*\x00\x00\x00"
203
+ end
204
+
205
+ it 'returns the remaining buffer contents after a read' do
206
+ buffer.to_s.should == "\x18\x00\x00\x00*\x00\x00\x00"
207
+ buffer.get_int32.should == 24
208
+ buffer.to_s.should == "*\x00\x00\x00"
209
+ end
210
+ end
211
+
212
+ context 'write buffer' do
213
+ let(:buffer) do
214
+ described_class.new.tap do |buffer|
215
+ buffer.put_int32(24)
216
+ end
217
+ end
218
+
219
+ it 'returns the data' do
220
+ buffer.to_s.should == "\x18\x00\x00\x00".force_encoding('binary')
221
+ end
222
+
223
+ it 'returns the complete buffer contents after a write' do
224
+ buffer.to_s.should == "\x18\x00\x00\x00".force_encoding('binary')
225
+ buffer.put_int32(42)
226
+ buffer.to_s.should == "\x18\x00\x00\x00*\x00\x00\x00".force_encoding('binary')
227
+ end
228
+ end
229
+ end
107
230
  end