bson 4.2.2 → 4.12.1

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 (169) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +25 -7
  5. data/Rakefile +16 -9
  6. data/ext/bson/{native-endian.h → bson-endian.h} +5 -99
  7. data/ext/bson/bson-native.h +125 -0
  8. data/ext/bson/bytebuf.c +133 -0
  9. data/ext/bson/endian.c +117 -0
  10. data/ext/bson/init.c +355 -0
  11. data/ext/bson/libbson-utf8.c +230 -0
  12. data/ext/bson/read.c +411 -0
  13. data/ext/bson/util.c +95 -0
  14. data/ext/bson/write.c +680 -0
  15. data/lib/bson.rb +6 -3
  16. data/lib/bson/active_support.rb +17 -0
  17. data/lib/bson/array.rb +57 -17
  18. data/lib/bson/binary.rb +185 -13
  19. data/lib/bson/boolean.rb +12 -3
  20. data/lib/bson/code.rb +16 -2
  21. data/lib/bson/code_with_scope.rb +32 -5
  22. data/lib/bson/config.rb +1 -1
  23. data/lib/bson/date.rb +12 -2
  24. data/lib/bson/date_time.rb +2 -2
  25. data/lib/bson/db_pointer.rb +110 -0
  26. data/lib/bson/decimal128.rb +17 -3
  27. data/lib/bson/decimal128/builder.rb +1 -1
  28. data/lib/bson/document.rb +152 -5
  29. data/lib/bson/environment.rb +2 -1
  30. data/lib/bson/error.rb +27 -0
  31. data/lib/bson/ext_json.rb +383 -0
  32. data/lib/bson/false_class.rb +1 -1
  33. data/lib/bson/float.rb +48 -2
  34. data/lib/bson/hash.rb +68 -17
  35. data/lib/bson/int32.rb +52 -13
  36. data/lib/bson/int64.rb +59 -15
  37. data/lib/bson/integer.rb +36 -2
  38. data/lib/bson/json.rb +1 -1
  39. data/lib/bson/max_key.rb +13 -1
  40. data/lib/bson/min_key.rb +13 -1
  41. data/lib/bson/nil_class.rb +4 -2
  42. data/lib/bson/object.rb +28 -1
  43. data/lib/bson/object_id.rb +16 -2
  44. data/lib/bson/open_struct.rb +1 -1
  45. data/lib/bson/regexp.rb +27 -4
  46. data/lib/bson/registry.rb +3 -3
  47. data/lib/bson/specialized.rb +4 -2
  48. data/lib/bson/string.rb +5 -3
  49. data/lib/bson/symbol.rb +99 -7
  50. data/lib/bson/time.rb +63 -4
  51. data/lib/bson/time_with_zone.rb +54 -0
  52. data/lib/bson/timestamp.rb +44 -6
  53. data/lib/bson/true_class.rb +1 -1
  54. data/lib/bson/undefined.rb +12 -1
  55. data/lib/bson/version.rb +2 -2
  56. data/spec/bson/array_spec.rb +18 -1
  57. data/spec/bson/binary_spec.rb +100 -3
  58. data/spec/bson/binary_uuid_spec.rb +189 -0
  59. data/spec/bson/boolean_spec.rb +1 -1
  60. data/spec/bson/byte_buffer_read_spec.rb +197 -0
  61. data/spec/bson/byte_buffer_spec.rb +121 -381
  62. data/spec/bson/byte_buffer_write_spec.rb +854 -0
  63. data/spec/bson/code_spec.rb +1 -1
  64. data/spec/bson/code_with_scope_spec.rb +1 -1
  65. data/spec/bson/date_spec.rb +1 -1
  66. data/spec/bson/date_time_spec.rb +54 -1
  67. data/spec/bson/decimal128_spec.rb +35 -35
  68. data/spec/bson/document_as_spec.rb +46 -0
  69. data/spec/bson/document_spec.rb +197 -30
  70. data/spec/bson/ext_json_parse_spec.rb +308 -0
  71. data/spec/bson/false_class_spec.rb +1 -1
  72. data/spec/bson/float_spec.rb +37 -1
  73. data/spec/bson/hash_as_spec.rb +57 -0
  74. data/spec/bson/hash_spec.rb +209 -1
  75. data/spec/bson/int32_spec.rb +180 -6
  76. data/spec/bson/int64_spec.rb +199 -6
  77. data/spec/bson/integer_spec.rb +29 -3
  78. data/spec/bson/json_spec.rb +1 -1
  79. data/spec/bson/max_key_spec.rb +1 -1
  80. data/spec/bson/min_key_spec.rb +1 -1
  81. data/spec/bson/nil_class_spec.rb +1 -1
  82. data/spec/bson/object_id_spec.rb +1 -1
  83. data/spec/bson/object_spec.rb +1 -1
  84. data/spec/bson/open_struct_spec.rb +1 -1
  85. data/spec/bson/raw_spec.rb +34 -2
  86. data/spec/bson/regexp_spec.rb +1 -1
  87. data/spec/bson/registry_spec.rb +1 -1
  88. data/spec/bson/string_spec.rb +19 -1
  89. data/spec/bson/symbol_raw_spec.rb +45 -0
  90. data/spec/bson/symbol_spec.rb +63 -3
  91. data/spec/bson/time_spec.rb +205 -2
  92. data/spec/bson/time_with_zone_spec.rb +68 -0
  93. data/spec/bson/timestamp_spec.rb +56 -1
  94. data/spec/bson/true_class_spec.rb +1 -1
  95. data/spec/bson/undefined_spec.rb +1 -1
  96. data/spec/bson_spec.rb +1 -1
  97. data/spec/{support → runners}/common_driver.rb +1 -1
  98. data/spec/runners/corpus.rb +185 -0
  99. data/spec/{support/corpus.rb → runners/corpus_legacy.rb} +41 -59
  100. data/spec/spec_helper.rb +40 -3
  101. data/spec/{bson/driver_bson_spec.rb → spec_tests/common_driver_spec.rb} +1 -0
  102. data/spec/{bson/corpus_spec.rb → spec_tests/corpus_legacy_spec.rb} +10 -7
  103. data/spec/spec_tests/corpus_spec.rb +124 -0
  104. data/spec/spec_tests/data/corpus/README.md +15 -0
  105. data/spec/spec_tests/data/corpus/array.json +49 -0
  106. data/spec/spec_tests/data/corpus/binary.json +113 -0
  107. data/spec/spec_tests/data/corpus/boolean.json +27 -0
  108. data/spec/spec_tests/data/corpus/code.json +67 -0
  109. data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
  110. data/spec/spec_tests/data/corpus/datetime.json +42 -0
  111. data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
  112. data/spec/spec_tests/data/corpus/dbref.json +31 -0
  113. data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
  114. data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
  115. data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
  116. data/spec/spec_tests/data/corpus/decimal128-4.json +117 -0
  117. data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
  118. data/spec/spec_tests/data/corpus/decimal128-6.json +119 -0
  119. data/spec/spec_tests/data/corpus/decimal128-7.json +323 -0
  120. data/spec/spec_tests/data/corpus/document.json +36 -0
  121. data/spec/spec_tests/data/corpus/double.json +87 -0
  122. data/spec/spec_tests/data/corpus/int32.json +43 -0
  123. data/spec/spec_tests/data/corpus/int64.json +43 -0
  124. data/spec/spec_tests/data/corpus/maxkey.json +12 -0
  125. data/spec/spec_tests/data/corpus/minkey.json +12 -0
  126. data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
  127. data/spec/spec_tests/data/corpus/multi-type.json +11 -0
  128. data/spec/spec_tests/data/corpus/null.json +12 -0
  129. data/spec/spec_tests/data/corpus/oid.json +28 -0
  130. data/spec/spec_tests/data/corpus/regex.json +65 -0
  131. data/spec/spec_tests/data/corpus/string.json +72 -0
  132. data/spec/spec_tests/data/corpus/symbol.json +80 -0
  133. data/spec/spec_tests/data/corpus/timestamp.json +34 -0
  134. data/spec/spec_tests/data/corpus/top.json +236 -0
  135. data/spec/spec_tests/data/corpus/undefined.json +15 -0
  136. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/array.json +8 -2
  137. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/binary.json +0 -0
  138. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/boolean.json +0 -0
  139. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code.json +1 -1
  140. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code_w_scope.json +1 -1
  141. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/document.json +1 -1
  142. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/double.json +1 -1
  143. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/datetime.json +0 -0
  144. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/dbpointer.json +0 -0
  145. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/int64.json +0 -0
  146. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/symbol.json +0 -0
  147. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/int32.json +1 -1
  148. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/maxkey.json +1 -1
  149. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/minkey.json +1 -1
  150. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/null.json +1 -1
  151. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/oid.json +0 -0
  152. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/regex.json +1 -1
  153. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/string.json +0 -0
  154. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/timestamp.json +1 -1
  155. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/top.json +0 -0
  156. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/undefined.json +0 -0
  157. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-1.json +0 -0
  158. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-2.json +0 -0
  159. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-3.json +0 -0
  160. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-4.json +0 -0
  161. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-5.json +0 -0
  162. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-6.json +0 -0
  163. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-7.json +0 -0
  164. data/spec/support/shared_examples.rb +3 -5
  165. data/spec/support/spec_config.rb +16 -0
  166. data/spec/support/utils.rb +10 -0
  167. metadata +227 -124
  168. metadata.gz.sig +0 -0
  169. data/ext/bson/bson_native.c +0 -762
@@ -0,0 +1,54 @@
1
+ # Copyright (C) 2018-2020 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 "active_support/time_with_zone"
16
+
17
+ module BSON
18
+
19
+ # Injects behaviour for encoding ActiveSupport::TimeWithZone values to
20
+ # raw bytes as specified by the BSON spec for time.
21
+ #
22
+ # @see http://bsonspec.org/#/specification
23
+ #
24
+ # @since 4.4.0
25
+ module TimeWithZone
26
+
27
+ # Get the ActiveSupport::TimeWithZone as encoded BSON.
28
+ #
29
+ # @example Get the ActiveSupport::TimeWithZone as encoded BSON.
30
+ # Time.utc(2012, 12, 12, 0, 0, 0).in_time_zone("Pacific Time (US & Canada)").to_bson
31
+ #
32
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
33
+ #
34
+ # @see http://bsonspec.org/#/specification
35
+ #
36
+ # @since 4.4.0
37
+ def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
38
+ buffer.put_int64((to_i * 1000) + (usec / 1000))
39
+ end
40
+
41
+ # Get the BSON type for the ActiveSupport::TimeWithZone.
42
+ #
43
+ # As the ActiveSupport::TimeWithZone is converted to a time, this returns
44
+ # the BSON type for time.
45
+ def bson_type
46
+ ::Time::BSON_TYPE
47
+ end
48
+ end
49
+
50
+ # Enrich the ActiveSupport::TimeWithZone class with this module.
51
+ #
52
+ # @since 4.4.0
53
+ ActiveSupport::TimeWithZone.send(:include, TimeWithZone)
54
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # Copyright (C) 2009-2020 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.
@@ -21,12 +21,18 @@ module BSON
21
21
  # @since 2.0.0
22
22
  class Timestamp
23
23
  include JSON
24
+ include Comparable
24
25
 
25
26
  # A timestamp is type 0x11 in the BSON spec.
26
27
  #
27
28
  # @since 2.0.0
28
29
  BSON_TYPE = 17.chr.force_encoding(BINARY).freeze
29
30
 
31
+ # Error message if an object other than a Timestamp is compared with this object.
32
+ #
33
+ # @since 4.3.0
34
+ COMPARISON_ERROR_MESSAGE = 'comparison of %s with Timestamp failed'.freeze
35
+
30
36
  # @!attribute seconds
31
37
  # @return [ Integer ] The number of seconds.
32
38
  # @since 2.0.0
@@ -52,6 +58,24 @@ module BSON
52
58
  seconds == other.seconds && increment == other.increment
53
59
  end
54
60
 
61
+ # Determine if this timestamp is greater or less than another object.
62
+ #
63
+ # @example Compare the timestamp.
64
+ # timestamp < other
65
+ #
66
+ # @param [ Object ] other The object to compare against.
67
+ #
68
+ # @return [ true, false ] The result of the comparison.
69
+ #
70
+ # @since 4.3.0
71
+ def <=>(other)
72
+ raise ArgumentError.new(COMPARISON_ERROR_MESSAGE % other.class) unless other.is_a?(Timestamp)
73
+ return 0 if self == other
74
+ a = [ seconds, increment ]
75
+ b = [ other.seconds, other.increment ]
76
+ [ a, b ].sort[0] == a ? -1 : 1
77
+ end
78
+
55
79
  # Get the timestamp as JSON hash data.
56
80
  #
57
81
  # @example Get the timestamp as a JSON hash.
@@ -60,7 +84,19 @@ module BSON
60
84
  # @return [ Hash ] The timestamp as a JSON hash.
61
85
  #
62
86
  # @since 2.0.0
87
+ # @deprecated Use as_extended_json instead.
63
88
  def as_json(*args)
89
+ as_extended_json
90
+ end
91
+
92
+ # Converts this object to a representation directly serializable to
93
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
94
+ #
95
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
96
+ # (default is canonical extended JSON)
97
+ #
98
+ # @return [ Hash ] The extended json representation.
99
+ def as_extended_json(**options)
64
100
  { "$timestamp" => { "t" => seconds, "i" => increment } }
65
101
  end
66
102
 
@@ -88,22 +124,24 @@ module BSON
88
124
  #
89
125
  # @since 2.0.0
90
126
  def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
91
- buffer.put_int32(increment)
92
- buffer.put_int32(seconds)
127
+ buffer.put_uint32(increment)
128
+ buffer.put_uint32(seconds)
93
129
  end
94
130
 
95
131
  # Deserialize timestamp from BSON.
96
132
  #
97
133
  # @param [ ByteBuffer ] buffer The byte buffer.
98
134
  #
135
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
136
+ #
99
137
  # @return [ Timestamp ] The decoded timestamp.
100
138
  #
101
139
  # @see http://bsonspec.org/#/specification
102
140
  #
103
141
  # @since 2.0.0
104
- def self.from_bson(buffer)
105
- increment = buffer.get_int32
106
- seconds = buffer.get_int32
142
+ def self.from_bson(buffer, **options)
143
+ increment = buffer.get_uint32
144
+ seconds = buffer.get_uint32
107
145
  new(seconds, increment)
108
146
  end
109
147
 
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # Copyright (C) 2009-2020 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.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # Copyright (C) 2009-2020 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.
@@ -41,6 +41,17 @@ module BSON
41
41
  self.class == other.class
42
42
  end
43
43
 
44
+ # Converts this object to a representation directly serializable to
45
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
46
+ #
47
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
48
+ # (default is canonical extended JSON)
49
+ #
50
+ # @return [ Hash ] The extended json representation.
51
+ def as_extended_json(**options)
52
+ { "$undefined" => true }
53
+ end
54
+
44
55
  # Register this type when the module is loaded.
45
56
  #
46
57
  # @since 2.0.0
data/lib/bson/version.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2016 MongoDB Inc.
1
+ # Copyright (C) 2009-2020 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.2.2".freeze
16
+ VERSION = "4.12.1".freeze
17
17
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # Copyright (C) 2009-2020 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.
@@ -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
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # Copyright (C) 2009-2020 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.
@@ -63,7 +63,7 @@ describe BSON::Binary do
63
63
 
64
64
  it "returns the binary data plus type" do
65
65
  expect(object.as_json).to eq(
66
- { "$binary" => Base64.encode64("testing"), "$type" => :user }
66
+ { "$binary" => {'base64' => Base64.encode64("testing").strip, "subType" => '80' }}
67
67
  )
68
68
  end
69
69
 
@@ -72,6 +72,14 @@ describe BSON::Binary do
72
72
 
73
73
  describe "#initialize" do
74
74
 
75
+ context 'when type is not given' do
76
+ let(:obj) { described_class.new('foo') }
77
+
78
+ it 'defaults to generic type' do
79
+ expect(obj.type).to eq(:generic)
80
+ end
81
+ end
82
+
75
83
  context "when he type is invalid" do
76
84
 
77
85
  it "raises an error" do
@@ -105,7 +113,11 @@ describe BSON::Binary do
105
113
  expect(object.inspect).to eq("<BSON::Binary:0x#{object.object_id} type=user data=0x1f8b08000c787055...>")
106
114
  end
107
115
 
108
- it 'is not different from default encoding' do
116
+ it 'is not binary' do
117
+ # As long as the default Ruby encoding is not binary, the inspected
118
+ # string should also not be in the binary encoding (it should be
119
+ # in one of the text encodings, but which one could depend on
120
+ # the Ruby runtime environment).
109
121
  expect(object.inspect.encoding).not_to eq(Encoding::BINARY)
110
122
  end
111
123
 
@@ -113,6 +125,37 @@ describe BSON::Binary do
113
125
 
114
126
  end
115
127
 
128
+ describe '#from_bson' do
129
+ let(:buffer) { BSON::ByteBuffer.new(bson) }
130
+ let(:obj) { described_class.from_bson(buffer) }
131
+
132
+ let(:bson) { "#{5.to_bson}#{0.chr}hello".force_encoding('BINARY') }
133
+
134
+ it 'sets data encoding to binary' do
135
+ expect(obj.data.encoding).to eq(Encoding.find('BINARY'))
136
+ end
137
+
138
+ context 'when binary subtype is supported' do
139
+ let(:bson) { [3, 0, 0, 0, 1].map(&:chr).join.force_encoding('BINARY') + 'foo' }
140
+
141
+ it 'works' do
142
+ obj.should be_a(described_class)
143
+ obj.type.should be :function
144
+ end
145
+ end
146
+
147
+ context 'when binary subtype is not supported' do
148
+ let(:bson) { [3, 0, 0, 0, 16].map(&:chr).join.force_encoding('BINARY') + 'foo' }
149
+
150
+ it 'raises an exception' do
151
+ lambda do
152
+ obj
153
+ end.should raise_error(BSON::Error::UnsupportedBinarySubtype,
154
+ /BSON data contains unsupported binary subtype 0x10/)
155
+ end
156
+ end
157
+ end
158
+
116
159
  describe "#to_bson/#from_bson" do
117
160
 
118
161
  let(:type) { 5.chr }
@@ -181,5 +224,59 @@ describe BSON::Binary do
181
224
  it_behaves_like "a serializable bson element"
182
225
  it_behaves_like "a deserializable bson element"
183
226
  end
227
+
228
+ context "when the type is :cyphertext" do
229
+ let(:obj) { described_class.new("testing", :ciphertext) }
230
+ let(:bson) { "#{7.to_bson}#{6.chr}testing" }
231
+
232
+ it_behaves_like "a serializable bson element"
233
+ it_behaves_like "a deserializable bson element"
234
+ end
235
+
236
+ context 'when given binary string' do
237
+ let(:obj) { described_class.new("\x00\xfe\xff".force_encoding('BINARY')) }
238
+ let(:bson) { "#{3.to_bson}#{0.chr}\x00\xfe\xff".force_encoding('BINARY') }
239
+
240
+ it_behaves_like "a serializable bson element"
241
+ it_behaves_like "a deserializable bson element"
242
+ end
243
+
244
+ context 'when given a frozen string' do
245
+ let(:str) { "\x00\xfe\xff".force_encoding('BINARY').freeze }
246
+ let(:obj) { described_class.new(str) }
247
+ let(:bson) { "#{3.to_bson}#{0.chr}\x00\xfe\xff".force_encoding('BINARY') }
248
+
249
+ it_behaves_like "a serializable bson element"
250
+ it_behaves_like "a deserializable bson element"
251
+ end
252
+ end
253
+
254
+ describe '#to_uuid' do
255
+ let(:obj) { described_class.new("\x00" * 16, :uuid) }
256
+
257
+ it 'accepts symbol representation' do
258
+ expect(obj.to_uuid(:standard)).to eq('00000000-0000-0000-0000-000000000000')
259
+ end
260
+
261
+ it 'rejects string representation' do
262
+ expect do
263
+ obj.to_uuid('standard')
264
+ end.to raise_error(ArgumentError, /Representation must be given as a symbol/)
265
+ end
266
+ end
267
+
268
+ describe '#from_uuid' do
269
+ let(:uuid) { '00000000-0000-0000-0000000000000000' }
270
+
271
+ it 'accepts symbol representation' do
272
+ obj = described_class.from_uuid(uuid, :standard)
273
+ expect(obj.data).to eq("\x00" * 16)
274
+ end
275
+
276
+ it 'rejects string representation' do
277
+ expect do
278
+ described_class.from_uuid(uuid, 'standard')
279
+ end.to raise_error(ArgumentError, /Representation must be given as a symbol/)
280
+ end
184
281
  end
185
282
  end
@@ -0,0 +1,189 @@
1
+ # Copyright (C) 2019-2020 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
+ require "base64"
17
+
18
+ describe "BSON::Binary - UUID spec tests" do
19
+ def make_binary(uuid_hex_str, type)
20
+ uuid_binary_str = uuid_hex_str.scan(/../).map(&:hex).map(&:chr).join
21
+ BSON::Binary.new(uuid_binary_str, type)
22
+ end
23
+
24
+ describe 'explicit encoding' do
25
+ let(:uuid_str) { '00112233-4455-6677-8899-aabbccddeeff' }
26
+
27
+ shared_examples_for 'creates binary' do
28
+ it 'creates subtype 4 binary' do
29
+ expect(binary.type).to eq(expected_type)
30
+ end
31
+
32
+ it 'creates binary with correct value' do
33
+ expect(binary.data).to eq(expected_hex_value.scan(/../).map(&:hex).map(&:chr).join)
34
+ end
35
+ end
36
+
37
+ context 'no representation' do
38
+ let(:binary) { BSON::Binary.from_uuid(uuid_str) }
39
+ let(:expected_type) { :uuid }
40
+ let(:expected_hex_value) { '00112233445566778899AABBCCDDEEFF' }
41
+
42
+ it_behaves_like 'creates binary'
43
+ end
44
+
45
+ context 'standard representation' do
46
+ let(:binary) { BSON::Binary.from_uuid(uuid_str, :standard) }
47
+ let(:expected_type) { :uuid }
48
+ let(:expected_hex_value) { '00112233445566778899AABBCCDDEEFF' }
49
+
50
+ it_behaves_like 'creates binary'
51
+ end
52
+
53
+ context 'csharp legacy representation' do
54
+ let(:binary) { BSON::Binary.from_uuid(uuid_str, :csharp_legacy) }
55
+ let(:expected_type) { :uuid_old }
56
+ let(:expected_hex_value) { '33221100554477668899AABBCCDDEEFF' }
57
+
58
+ it_behaves_like 'creates binary'
59
+ end
60
+
61
+ context 'java legacy representation' do
62
+ let(:binary) { BSON::Binary.from_uuid(uuid_str, :java_legacy) }
63
+ let(:expected_type) { :uuid_old }
64
+ let(:expected_hex_value) { '7766554433221100FFEEDDCCBBAA9988' }
65
+
66
+ it_behaves_like 'creates binary'
67
+ end
68
+
69
+ context 'python legacy representation' do
70
+ let(:binary) { BSON::Binary.from_uuid(uuid_str, :python_legacy) }
71
+ let(:expected_type) { :uuid_old }
72
+ let(:expected_hex_value) { '00112233445566778899AABBCCDDEEFF' }
73
+
74
+ it_behaves_like 'creates binary'
75
+ end
76
+ end
77
+
78
+ describe 'explicit decoding' do
79
+ context ':uuid, standard encoded' do
80
+ let(:binary) { make_binary("00112233445566778899AABBCCDDEEFF", :uuid) }
81
+
82
+ it 'decodes without arguments' do
83
+ expect(binary.to_uuid.gsub('-', '').upcase).to eq("00112233445566778899AABBCCDDEEFF")
84
+ end
85
+
86
+ it 'decodes as standard' do
87
+ expect(binary.to_uuid(:standard).gsub('-', '').upcase).to eq("00112233445566778899AABBCCDDEEFF")
88
+ end
89
+
90
+ it 'does not decode as csharp legacy' do
91
+ expect do
92
+ binary.to_uuid(:csharp_legacy)
93
+ end.to raise_error(ArgumentError, /Binary of type :uuid can only be stringified to :standard representation/)
94
+ end
95
+
96
+ it 'does not decode as java legacy' do
97
+ expect do
98
+ binary.to_uuid(:java_legacy)
99
+ end.to raise_error(ArgumentError, /Binary of type :uuid can only be stringified to :standard representation/)
100
+ end
101
+
102
+ it 'does not decode as python legacy' do
103
+ expect do
104
+ binary.to_uuid(:python_legacy)
105
+ end.to raise_error(ArgumentError, /Binary of type :uuid can only be stringified to :standard representation/)
106
+ end
107
+ end
108
+
109
+ shared_examples_for 'a legacy uuid' do
110
+ it 'does not decode without arguments' do
111
+ expect do
112
+ binary.to_uuid
113
+ end.to raise_error(ArgumentError, /Representation must be specified for BSON::Binary objects of type :uuid_old/)
114
+ end
115
+
116
+ it 'does not decode as standard' do
117
+ expect do
118
+ binary.to_uuid(:standard)
119
+ end.to raise_error(ArgumentError, /BSON::Binary objects of type :uuid_old cannot be stringified to :standard representation/)
120
+ end
121
+ end
122
+
123
+ context ':uuid_old, csharp legacy encoded' do
124
+ let(:binary) { make_binary("33221100554477668899AABBCCDDEEFF", :uuid_old) }
125
+
126
+ it_behaves_like 'a legacy uuid'
127
+
128
+ it 'decodes as csharp legacy' do
129
+ expect(binary.to_uuid(:csharp_legacy).gsub('-', '').upcase).to eq("00112233445566778899AABBCCDDEEFF")
130
+ end
131
+
132
+ it 'decodes as java legacy' do
133
+ expect(binary.to_uuid(:java_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
134
+ end
135
+
136
+ it 'decodes as python legacy' do
137
+ expect(binary.to_uuid(:python_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
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
143
+ end
144
+
145
+ context ':uuid_old, java legacy encoded' do
146
+ let(:binary) { make_binary("7766554433221100FFEEDDCCBBAA9988", :uuid_old) }
147
+
148
+ it_behaves_like 'a legacy uuid'
149
+
150
+ it 'decodes as csharp legacy' do
151
+ expect(binary.to_uuid(:csharp_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
152
+ end
153
+
154
+ it 'decodes as java legacy' do
155
+ expect(binary.to_uuid(:java_legacy).gsub('-', '').upcase).to eq("00112233445566778899AABBCCDDEEFF")
156
+ end
157
+
158
+ it 'decodes as python legacy' do
159
+ expect(binary.to_uuid(:python_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
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
165
+ end
166
+
167
+ context ':uuid_old, python legacy encoded' do
168
+ let(:binary) { make_binary("00112233445566778899AABBCCDDEEFF", :uuid_old) }
169
+
170
+ it_behaves_like 'a legacy uuid'
171
+
172
+ it 'decodes as csharp legacy' do
173
+ expect(binary.to_uuid(:csharp_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
174
+ end
175
+
176
+ it 'decodes as java legacy' do
177
+ expect(binary.to_uuid(:java_legacy).gsub('-', '').upcase).not_to eq("00112233445566778899AABBCCDDEEFF")
178
+ end
179
+
180
+ it 'decodes as python legacy' do
181
+ expect(binary.to_uuid(:python_legacy).gsub('-', '').upcase).to eq("00112233445566778899AABBCCDDEEFF")
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
187
+ end
188
+ end
189
+ end