bson 4.1.1 → 5.2.0

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 (226) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +106 -7
  3. data/Rakefile +86 -43
  4. data/ext/bson/{native-endian.h → bson-endian.h} +14 -107
  5. data/ext/bson/bson-native.h +135 -0
  6. data/ext/bson/bytebuf.c +133 -0
  7. data/ext/bson/endian.c +117 -0
  8. data/ext/bson/extconf.rb +8 -3
  9. data/ext/bson/init.c +364 -0
  10. data/ext/bson/libbson-utf8.c +230 -0
  11. data/ext/bson/read.c +470 -0
  12. data/ext/bson/util.c +250 -0
  13. data/ext/bson/write.c +675 -0
  14. data/lib/bson/active_support.rb +19 -0
  15. data/lib/bson/array.rb +97 -30
  16. data/lib/bson/big_decimal.rb +77 -0
  17. data/lib/bson/binary.rb +510 -70
  18. data/lib/bson/boolean.rb +15 -4
  19. data/lib/bson/code.rb +25 -12
  20. data/lib/bson/code_with_scope.rb +41 -15
  21. data/lib/bson/config.rb +3 -28
  22. data/lib/bson/date.rb +16 -4
  23. data/lib/bson/date_time.rb +6 -4
  24. data/lib/bson/db_pointer.rb +110 -0
  25. data/lib/bson/dbref.rb +154 -0
  26. data/lib/bson/decimal128/builder.rb +456 -0
  27. data/lib/bson/decimal128.rb +272 -0
  28. data/lib/bson/document.rb +177 -7
  29. data/lib/bson/environment.rb +17 -2
  30. data/lib/bson/error/bson_decode_error.rb +11 -0
  31. data/lib/bson/error/ext_json_parse_error.rb +11 -0
  32. data/lib/bson/error/illegal_key.rb +23 -0
  33. data/lib/bson/error/invalid_binary_type.rb +37 -0
  34. data/lib/bson/error/invalid_dbref_argument.rb +12 -0
  35. data/lib/bson/error/invalid_decimal128_argument.rb +25 -0
  36. data/lib/bson/error/invalid_decimal128_range.rb +27 -0
  37. data/lib/bson/error/invalid_decimal128_string.rb +26 -0
  38. data/lib/bson/error/invalid_key.rb +24 -0
  39. data/lib/bson/error/invalid_object_id.rb +11 -0
  40. data/lib/bson/error/invalid_regexp_pattern.rb +13 -0
  41. data/lib/bson/error/unrepresentable_precision.rb +19 -0
  42. data/lib/bson/error/unserializable_class.rb +13 -0
  43. data/lib/bson/error/unsupported_binary_subtype.rb +12 -0
  44. data/lib/bson/error/unsupported_type.rb +11 -0
  45. data/lib/bson/error.rb +22 -0
  46. data/lib/bson/ext_json.rb +389 -0
  47. data/lib/bson/false_class.rb +6 -4
  48. data/lib/bson/float.rb +43 -7
  49. data/lib/bson/hash.rb +152 -37
  50. data/lib/bson/int32.rb +104 -6
  51. data/lib/bson/int64.rb +111 -8
  52. data/lib/bson/integer.rb +43 -9
  53. data/lib/bson/json.rb +3 -1
  54. data/lib/bson/max_key.rb +21 -10
  55. data/lib/bson/min_key.rb +21 -10
  56. data/lib/bson/nil_class.rb +7 -3
  57. data/lib/bson/object.rb +25 -17
  58. data/lib/bson/object_id.rb +98 -113
  59. data/lib/bson/open_struct.rb +59 -0
  60. data/lib/bson/regexp.rb +129 -56
  61. data/lib/bson/registry.rb +7 -10
  62. data/lib/bson/specialized.rb +8 -4
  63. data/lib/bson/string.rb +12 -32
  64. data/lib/bson/symbol.rb +107 -11
  65. data/lib/bson/time.rb +68 -7
  66. data/lib/bson/time_with_zone.rb +67 -0
  67. data/lib/bson/timestamp.rb +50 -10
  68. data/lib/bson/true_class.rb +6 -4
  69. data/lib/bson/undefined.rb +28 -2
  70. data/lib/bson/vector.rb +44 -0
  71. data/lib/bson/version.rb +6 -14
  72. data/lib/bson.rb +22 -12
  73. data/spec/README.md +14 -0
  74. data/spec/bson/array_spec.rb +38 -62
  75. data/spec/bson/big_decimal_spec.rb +328 -0
  76. data/spec/bson/binary_spec.rb +199 -53
  77. data/spec/bson/binary_uuid_spec.rb +190 -0
  78. data/spec/bson/boolean_spec.rb +2 -1
  79. data/spec/bson/byte_buffer_read_spec.rb +198 -0
  80. data/spec/bson/byte_buffer_spec.rb +122 -381
  81. data/spec/bson/byte_buffer_write_spec.rb +855 -0
  82. data/spec/bson/code_spec.rb +6 -4
  83. data/spec/bson/code_with_scope_spec.rb +6 -4
  84. data/spec/bson/config_spec.rb +1 -35
  85. data/spec/bson/date_spec.rb +2 -1
  86. data/spec/bson/date_time_spec.rb +55 -1
  87. data/spec/bson/dbref_legacy_spec.rb +186 -0
  88. data/spec/bson/dbref_spec.rb +487 -0
  89. data/spec/bson/decimal128_spec.rb +1840 -0
  90. data/spec/bson/document_as_spec.rb +61 -0
  91. data/spec/bson/document_spec.rb +205 -32
  92. data/spec/bson/ext_json_parse_spec.rb +346 -0
  93. data/spec/bson/false_class_spec.rb +9 -1
  94. data/spec/bson/float_spec.rb +42 -1
  95. data/spec/bson/hash_as_spec.rb +58 -0
  96. data/spec/bson/hash_spec.rb +318 -66
  97. data/spec/bson/int32_spec.rb +248 -1
  98. data/spec/bson/int64_spec.rb +308 -1
  99. data/spec/bson/integer_spec.rb +61 -3
  100. data/spec/bson/json_spec.rb +2 -1
  101. data/spec/bson/max_key_spec.rb +6 -4
  102. data/spec/bson/min_key_spec.rb +6 -4
  103. data/spec/bson/nil_class_spec.rb +2 -1
  104. data/spec/bson/object_id_spec.rb +95 -5
  105. data/spec/bson/object_spec.rb +3 -2
  106. data/spec/bson/open_struct_spec.rb +87 -0
  107. data/spec/bson/raw_spec.rb +594 -0
  108. data/spec/bson/regexp_spec.rb +61 -8
  109. data/spec/bson/registry_spec.rb +3 -2
  110. data/spec/bson/string_spec.rb +26 -33
  111. data/spec/bson/symbol_raw_spec.rb +70 -0
  112. data/spec/bson/symbol_spec.rb +77 -20
  113. data/spec/bson/time_spec.rb +206 -2
  114. data/spec/bson/time_with_zone_spec.rb +69 -0
  115. data/spec/bson/timestamp_spec.rb +58 -2
  116. data/spec/bson/true_class_spec.rb +9 -1
  117. data/spec/bson/undefined_spec.rb +28 -1
  118. data/spec/bson/vector_spec.rb +33 -0
  119. data/spec/bson_spec.rb +2 -1
  120. data/spec/runners/binary_vector.rb +78 -0
  121. data/spec/runners/common_driver.rb +348 -0
  122. data/spec/runners/corpus.rb +191 -0
  123. data/spec/runners/corpus_legacy.rb +248 -0
  124. data/spec/shared/LICENSE +20 -0
  125. data/spec/shared/bin/get-mongodb-download-url +17 -0
  126. data/spec/shared/bin/s3-copy +45 -0
  127. data/spec/shared/bin/s3-upload +69 -0
  128. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  129. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  130. data/spec/shared/lib/mrss/constraints.rb +378 -0
  131. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  132. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  133. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  134. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  135. data/spec/shared/lib/mrss/release/candidate.rb +281 -0
  136. data/spec/shared/lib/mrss/release/product_data.rb +144 -0
  137. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  138. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  139. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  140. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  141. data/spec/shared/lib/mrss/utils.rb +37 -0
  142. data/spec/shared/lib/tasks/candidate.rake +64 -0
  143. data/spec/shared/share/Dockerfile.erb +251 -0
  144. data/spec/shared/share/haproxy-1.conf +16 -0
  145. data/spec/shared/share/haproxy-2.conf +17 -0
  146. data/spec/shared/shlib/config.sh +27 -0
  147. data/spec/shared/shlib/distro.sh +84 -0
  148. data/spec/shared/shlib/server.sh +423 -0
  149. data/spec/shared/shlib/set_env.sh +110 -0
  150. data/spec/spec_helper.rb +61 -1
  151. data/spec/spec_tests/binary_vector_spec.rb +82 -0
  152. data/spec/spec_tests/common_driver_spec.rb +84 -0
  153. data/spec/spec_tests/corpus_legacy_spec.rb +72 -0
  154. data/spec/spec_tests/corpus_spec.rb +134 -0
  155. data/spec/spec_tests/data/binary_vector/README.md +61 -0
  156. data/spec/spec_tests/data/binary_vector/float32.json +65 -0
  157. data/spec/spec_tests/data/binary_vector/int8.json +57 -0
  158. data/spec/spec_tests/data/binary_vector/packed_bit.json +83 -0
  159. data/spec/spec_tests/data/corpus/README.md +15 -0
  160. data/spec/spec_tests/data/corpus/array.json +49 -0
  161. data/spec/spec_tests/data/corpus/binary.json +153 -0
  162. data/spec/spec_tests/data/corpus/boolean.json +27 -0
  163. data/spec/spec_tests/data/corpus/code.json +67 -0
  164. data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
  165. data/spec/spec_tests/data/corpus/datetime.json +42 -0
  166. data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
  167. data/spec/spec_tests/data/corpus/dbref.json +51 -0
  168. data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
  169. data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
  170. data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
  171. data/spec/spec_tests/data/corpus/decimal128-4.json +165 -0
  172. data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
  173. data/spec/spec_tests/data/corpus/decimal128-6.json +131 -0
  174. data/spec/spec_tests/data/corpus/decimal128-7.json +327 -0
  175. data/spec/spec_tests/data/corpus/document.json +60 -0
  176. data/spec/spec_tests/data/corpus/double.json +87 -0
  177. data/spec/spec_tests/data/corpus/int32.json +43 -0
  178. data/spec/spec_tests/data/corpus/int64.json +43 -0
  179. data/spec/spec_tests/data/corpus/maxkey.json +12 -0
  180. data/spec/spec_tests/data/corpus/minkey.json +12 -0
  181. data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
  182. data/spec/spec_tests/data/corpus/multi-type.json +11 -0
  183. data/spec/spec_tests/data/corpus/null.json +12 -0
  184. data/spec/spec_tests/data/corpus/oid.json +28 -0
  185. data/spec/spec_tests/data/corpus/regex.json +65 -0
  186. data/spec/spec_tests/data/corpus/string.json +72 -0
  187. data/spec/spec_tests/data/corpus/symbol.json +80 -0
  188. data/spec/spec_tests/data/corpus/timestamp.json +34 -0
  189. data/spec/spec_tests/data/corpus/top.json +262 -0
  190. data/spec/spec_tests/data/corpus/undefined.json +15 -0
  191. data/spec/spec_tests/data/corpus_legacy/array.json +49 -0
  192. data/spec/spec_tests/data/corpus_legacy/binary.json +69 -0
  193. data/spec/spec_tests/data/corpus_legacy/boolean.json +27 -0
  194. data/spec/spec_tests/data/corpus_legacy/code.json +67 -0
  195. data/spec/spec_tests/data/corpus_legacy/code_w_scope.json +78 -0
  196. data/spec/spec_tests/data/corpus_legacy/document.json +36 -0
  197. data/spec/spec_tests/data/corpus_legacy/double.json +69 -0
  198. data/spec/spec_tests/data/corpus_legacy/failures/datetime.json +31 -0
  199. data/spec/spec_tests/data/corpus_legacy/failures/dbpointer.json +42 -0
  200. data/spec/spec_tests/data/corpus_legacy/failures/int64.json +38 -0
  201. data/spec/spec_tests/data/corpus_legacy/failures/symbol.json +62 -0
  202. data/spec/spec_tests/data/corpus_legacy/int32.json +38 -0
  203. data/spec/spec_tests/data/corpus_legacy/maxkey.json +12 -0
  204. data/spec/spec_tests/data/corpus_legacy/minkey.json +12 -0
  205. data/spec/spec_tests/data/corpus_legacy/null.json +12 -0
  206. data/spec/spec_tests/data/corpus_legacy/oid.json +28 -0
  207. data/spec/spec_tests/data/corpus_legacy/regex.json +37 -0
  208. data/spec/spec_tests/data/corpus_legacy/string.json +67 -0
  209. data/spec/spec_tests/data/corpus_legacy/timestamp.json +18 -0
  210. data/spec/spec_tests/data/corpus_legacy/top.json +62 -0
  211. data/spec/spec_tests/data/corpus_legacy/undefined.json +13 -0
  212. data/spec/spec_tests/data/decimal128/decimal128-1.json +363 -0
  213. data/spec/spec_tests/data/decimal128/decimal128-2.json +793 -0
  214. data/spec/spec_tests/data/decimal128/decimal128-3.json +1771 -0
  215. data/spec/spec_tests/data/decimal128/decimal128-4.json +165 -0
  216. data/spec/spec_tests/data/decimal128/decimal128-5.json +402 -0
  217. data/spec/spec_tests/data/decimal128/decimal128-6.json +131 -0
  218. data/spec/spec_tests/data/decimal128/decimal128-7.json +327 -0
  219. data/spec/support/shared_examples.rb +32 -11
  220. data/spec/support/spec_config.rb +17 -0
  221. data/spec/support/utils.rb +58 -0
  222. metadata +284 -45
  223. checksums.yaml.gz.sig +0 -3
  224. data/ext/bson/native.c +0 -722
  225. data.tar.gz.sig +0 -0
  226. metadata.gz.sig +0 -0
@@ -0,0 +1,84 @@
1
+ # rubocop:todo all
2
+ require 'spec_helper'
3
+ require 'runners/common_driver'
4
+
5
+ describe 'Driver common bson tests' do
6
+
7
+ specs = DRIVER_COMMON_BSON_TESTS.map { |file| BSON::CommonDriver::Spec.new(file) }
8
+
9
+ specs.each do |spec|
10
+
11
+ context(spec.description) do
12
+
13
+ spec.valid_tests.each do |test|
14
+
15
+ context(test.description << ' - ' << test.string) do
16
+
17
+ it 'decodes the subject and displays as the correct string' do
18
+ expect(test.object.to_s).to eq(test.expected_to_string)
19
+ end
20
+
21
+ it 'encodes the decoded object correctly (roundtrips)' do
22
+ expect(test.reencoded_hex).to eq(test.subject.upcase)
23
+ end
24
+
25
+ it 'creates the correct object from extended json', if: test.from_ext_json? do
26
+ expect(test.from_json_string).to eq(test.object)
27
+ end
28
+
29
+ it 'serializes to a string', if: test.to_ext_json? do
30
+ expect(test.document_as_extended_json).to eq(test.ext_json)
31
+ end
32
+
33
+ it 'creates the correct extended json document from the decoded object', if: test.to_ext_json? do
34
+ expect(test.document_as_extended_json).to eq(test.ext_json)
35
+ end
36
+
37
+ it 'parses the string value to the same value as the decoded document', if: test.from_string? do
38
+ expect(BSON::Decimal128.new(test.string)).to eq(test.object)
39
+ end
40
+
41
+ it 'parses the #to_s (match_string) value to the same value as the decoded document', if: test.match_string do
42
+ expect(BSON::Decimal128.new(test.match_string)).to eq(test.object)
43
+ end
44
+
45
+ it 'creates the correct object from a non canonical string and then prints to the correct string', if: test.match_string do
46
+ expect(BSON::Decimal128.new(test.string).to_s).to eq(test.match_string)
47
+ end
48
+
49
+ it 'can be converted to a native type' do
50
+ expect(test.native_type_conversion).to be_a(test.native_type)
51
+ end
52
+ end
53
+ end
54
+
55
+ spec.invalid_tests.each do |test|
56
+
57
+ context(test.description << " - " << test.subject ) do
58
+
59
+ let(:error) do
60
+ ex = nil
61
+ begin
62
+ test.parse_invalid_string
63
+ rescue => e
64
+ ex = e
65
+ end
66
+ ex
67
+ end
68
+
69
+ let(:valid_errors) do
70
+ [
71
+ BSON::Error::InvalidDecimal128String,
72
+ BSON::Error::InvalidDecimal128Range,
73
+ BSON::Error::UnrepresentablePrecision,
74
+ ]
75
+ end
76
+
77
+ it 'raises an exception when parsing' do
78
+ expect(error.class).to satisfy { |e| valid_errors.include?(e) }
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,72 @@
1
+ # rubocop:todo all
2
+ require 'spec_helper'
3
+ require 'runners/corpus_legacy'
4
+
5
+ describe 'Driver BSON Corpus Legacy spec tests' do
6
+
7
+ BSON_CORPUS_LEGACY_TESTS.each do |path|
8
+ basename = File.basename(path)
9
+ # All of the tests in the failures subdir are failing apparently
10
+ #basename = path.sub(/.*corpus-tests\//, '')
11
+
12
+ spec = BSON::CorpusLegacy::Spec.new(path)
13
+
14
+ context("(#{basename}): #{spec.description}") do
15
+
16
+ spec.valid_tests.each do |test|
17
+
18
+ context("VALID CASE: #{test.description}") do
19
+
20
+ it 'roundtrips the given bson correctly' do
21
+ expect(test.reencoded_bson).to eq(test.correct_bson)
22
+ end
23
+
24
+ context 'when the canonical bson is roundtripped', if: test.test_canonical_bson? do
25
+
26
+ it 'encodes the canonical bson correctly' do
27
+ expect(test.reencoded_canonical_bson).to eq(test.correct_bson)
28
+ end
29
+ end
30
+
31
+ context 'when the document can be represented as extended json', if: test.test_extjson? do
32
+
33
+ it 'decodes from the given bson, then encodes the document as extended json correctly' do
34
+ expect(test.extjson_from_bson).to eq(test.correct_extjson)
35
+ expect(test.extjson_from_bson[test.test_key]).to eq(test.correct_extjson[test.test_key])
36
+ end
37
+
38
+ it 'decodes from extended json, then encodes the document as extended json correctly' do
39
+ expect(test.extjson_from_encoded_extjson).to eq(test.correct_extjson)
40
+ expect(test.extjson_from_encoded_extjson[test.test_key]).to eq(test.correct_extjson[test.test_key])
41
+ end
42
+
43
+ context 'when the canonical bson can be represented as extended json', if: (test.test_canonical_bson? && test.test_extjson?) do
44
+
45
+ it 'encodes the canonical bson correctly as extended json' do
46
+ expect(test.extjson_from_canonical_bson).to eq(test.correct_extjson)
47
+ expect(test.extjson_from_canonical_bson[test.test_key]).to eq(test.correct_extjson[test.test_key])
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ spec.invalid_tests.each do |test|
55
+
56
+ context("INVALID CASE: #{test.description}") do
57
+
58
+ let(:error) do
59
+ begin; test.reencoded_bson; false; rescue => e; e; end
60
+ end
61
+
62
+ it 'raises an error' do
63
+ skip 'This test case does not raise and error but should' unless error
64
+ expect do
65
+ test.reencoded_bson
66
+ end.to raise_error(error.class)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,134 @@
1
+ # rubocop:todo all
2
+ require 'spec_helper'
3
+ require 'runners/corpus'
4
+
5
+ describe 'BSON Corpus spec tests' do
6
+
7
+ BSON_CORPUS_TESTS.each do |path|
8
+ basename = File.basename(path)
9
+ # All of the tests in the failures subdir are failing apparently
10
+ #basename = path.sub(/.*corpus-tests\//, '')
11
+
12
+ spec = BSON::Corpus::Spec.new(path)
13
+
14
+ context("(#{basename}): #{spec.description}") do
15
+
16
+ spec.valid_tests&.each do |test|
17
+
18
+ context("valid: #{test.description}") do
19
+
20
+ let(:decoded_canonical_bson) do
21
+ BSON::Document.from_bson(BSON::ByteBuffer.new(test.canonical_bson), mode: :bson)
22
+ end
23
+
24
+ it 'round-trips canonical bson' do
25
+ decoded_canonical_bson.to_bson.to_s.should == test.canonical_bson
26
+ end
27
+
28
+ =begin
29
+ it 'converts bson to canonical extended json' do
30
+ pending
31
+ raise NotImplementedError
32
+ end
33
+ =end
34
+
35
+ it 'converts bson to canonical extended json' do
36
+ decoded_canonical_bson.as_extended_json.should == test.canonical_extjson_doc
37
+ end
38
+
39
+ if test.relaxed_extjson
40
+ it 'converts bson to relaxed extended json' do
41
+ decoded_canonical_bson.as_extended_json(mode: :relaxed).should == test.relaxed_extjson_doc
42
+ end
43
+
44
+ let(:parsed_relaxed_extjson) do
45
+ BSON::ExtJSON.parse_obj(test.relaxed_extjson_doc, mode: :bson)
46
+ end
47
+
48
+ let(:round_tripped_relaxed_extjson) do
49
+ parsed_relaxed_extjson.as_extended_json(mode: :relaxed)
50
+ end
51
+
52
+ # Relaxed extended json may parse into something other than the
53
+ # canonical bson. For example, relaxed extjson representation for
54
+ # a small int64 is a number that would serialize to an int32.
55
+ # But round-tripping extended json back to extjson should produce
56
+ # the same representation we started with.
57
+ it 'round-trips relaxed extended json' do
58
+ round_tripped_relaxed_extjson.should == test.relaxed_extjson_doc
59
+ end
60
+ end
61
+
62
+ if test.degenerate_bson
63
+
64
+ let(:decoded_degenerate_bson) do
65
+ BSON::Document.from_bson(BSON::ByteBuffer.new(test.degenerate_bson), mode: :relaxed)
66
+ end
67
+
68
+ it 'round-trips degenerate bson to canonical bson' do
69
+ decoded_degenerate_bson.to_bson.to_s.should == test.canonical_bson
70
+ end
71
+ end
72
+
73
+ let(:parsed_canonical_extjson) do
74
+ BSON::ExtJSON.parse_obj(test.canonical_extjson_doc, mode: :bson)
75
+ end
76
+
77
+ unless test.lossy?
78
+ it 'converts canonical extended json to bson' do
79
+ parsed_canonical_extjson.to_bson.to_s.should == test.canonical_bson
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+
86
+ spec.decode_error_tests&.each do |test|
87
+
88
+ context("decode error: #{test.description}") do
89
+
90
+ let(:decoded_bson) do
91
+ BSON::Document.from_bson(BSON::ByteBuffer.new(test.bson), mode: :bson)
92
+ end
93
+
94
+ # Until bson-ruby gets an exception hierarchy, we can only rescue
95
+ # the basic Exception here.
96
+ # https://jira.mongodb.org/browse/RUBY-1806
97
+ it 'raises an exception' do
98
+ expect do
99
+ decoded_bson
100
+ end.to raise_error(Exception)
101
+ end
102
+ end
103
+ end
104
+
105
+ spec.parse_error_tests&.each do |test|
106
+
107
+ context("parse error: #{test.description}") do
108
+
109
+ # As per:
110
+ # https://github.com/mongodb/specifications/blob/e7ee829329400786e01279b4f37d4e440d1e9cfa/source/bson-corpus/bson-corpus.rst#decimal128-type-0x13
111
+ #
112
+ # Values under test must be parsed in a type-specific manner.
113
+ let(:parsed_value) do
114
+ case spec.bson_type
115
+ when BSON::Decimal128::BSON_TYPE
116
+ BSON::Decimal128.new(test.string)
117
+ else
118
+ BSON::ExtJSON.parse(test.string, mode: :bson)
119
+ end
120
+ end
121
+
122
+ # Until bson-ruby gets an exception hierarchy, we can only rescue
123
+ # the basic Exception here.
124
+ # https://jira.mongodb.org/browse/RUBY-1806
125
+ it 'raises an exception' do
126
+ expect do
127
+ parsed_value
128
+ end.to raise_error(Exception)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,61 @@
1
+ # Testing Binary subtype 9: Vector
2
+
3
+ The JSON files in this directory tree are platform-independent tests that drivers can use to prove their conformance to
4
+ the specification.
5
+
6
+ These tests focus on the roundtrip of the list of numbers as input/output, along with their data type and byte padding.
7
+
8
+ Additional tests exist in `bson_corpus/tests/binary.json` but do not sufficiently test the end-to-end process of Vector
9
+ to BSON. For this reason, drivers must create a bespoke test runner for the vector subtype.
10
+
11
+ ## Format
12
+
13
+ The test data corpus consists of a JSON file for each data type (dtype). Each file contains a number of test cases,
14
+ under the top-level key "tests". Each test case pertains to a single vector. The keys provide the specification of the
15
+ vector. Valid cases also include the Canonical BSON format of a document {test_key: binary}. The "test_key" is common,
16
+ and specified at the top level.
17
+
18
+ #### Top level keys
19
+
20
+ Each JSON file contains three top-level keys.
21
+
22
+ - `description`: human-readable description of what is in the file
23
+ - `test_key`: name used for key when encoding/decoding a BSON document containing the single BSON Binary for the test
24
+ case. Applies to *every* case.
25
+ - `tests`: array of test case objects, each of which have the following keys. Valid cases will also contain additional
26
+ binary and json encoding values.
27
+
28
+ #### Keys of individual tests cases
29
+
30
+ - `description`: string describing the test.
31
+ - `valid`: boolean indicating if the vector, dtype, and padding should be considered a valid input.
32
+ - `vector`: (required if valid is true) list of numbers
33
+ - `dtype_hex`: string defining the data type in hex (e.g. "0x10", "0x27")
34
+ - `dtype_alias`: (optional) string defining the data dtype, perhaps as Enum.
35
+ - `padding`: (optional) integer for byte padding. Defaults to 0.
36
+ - `canonical_bson`: (required if valid is true) an (uppercase) big-endian hex representation of a BSON byte string.
37
+
38
+ ## Required tests
39
+
40
+ #### To prove correct in a valid case (`valid: true`), one MUST
41
+
42
+ - encode a document from the numeric values, dtype, and padding, along with the "test_key", and assert this matches the
43
+ canonical_bson string.
44
+ - decode the canonical_bson into its binary form, and then assert that the numeric values, dtype, and padding all match
45
+ those provided in the JSON.
46
+
47
+ Note: For floating point number types, exact numerical matches may not be possible. Drivers that natively support the
48
+ floating-point type being tested (e.g., when testing float32 vector values in a driver that natively supports float32),
49
+ MUST assert that the input float array is the same after encoding and decoding.
50
+
51
+ #### To prove correct in an invalid case (`valid:false`), one MUST
52
+
53
+ - if the vector field is present, raise an exception when attempting to encode a document from the numeric values,
54
+ dtype, and padding.
55
+ - if the canonical_bson field is present, raise an exception when attempting to deserialize it into the corresponding
56
+ numeric values, as the field contains corrupted data.
57
+
58
+ ## FAQ
59
+
60
+ - What MongoDB Server version does this apply to?
61
+ - Files in the "specifications" repository have no version scheme. They are not tied to a MongoDB server version.
@@ -0,0 +1,65 @@
1
+ {
2
+ "description": "Tests of Binary subtype 9, Vectors, with dtype FLOAT32",
3
+ "test_key": "vector",
4
+ "tests": [
5
+ {
6
+ "description": "Simple Vector FLOAT32",
7
+ "valid": true,
8
+ "vector": [127.0, 7.0],
9
+ "dtype_hex": "0x27",
10
+ "dtype_alias": "FLOAT32",
11
+ "padding": 0,
12
+ "canonical_bson": "1C00000005766563746F72000A0000000927000000FE420000E04000"
13
+ },
14
+ {
15
+ "description": "Vector with decimals and negative value FLOAT32",
16
+ "valid": true,
17
+ "vector": [127.7, -7.7],
18
+ "dtype_hex": "0x27",
19
+ "dtype_alias": "FLOAT32",
20
+ "padding": 0,
21
+ "canonical_bson": "1C00000005766563746F72000A0000000927006666FF426666F6C000"
22
+ },
23
+ {
24
+ "description": "Empty Vector FLOAT32",
25
+ "valid": true,
26
+ "vector": [],
27
+ "dtype_hex": "0x27",
28
+ "dtype_alias": "FLOAT32",
29
+ "padding": 0,
30
+ "canonical_bson": "1400000005766563746F72000200000009270000"
31
+ },
32
+ {
33
+ "description": "Infinity Vector FLOAT32",
34
+ "valid": true,
35
+ "vector": [{"$numberDouble": "-Infinity"}, 0.0, {"$numberDouble": "Infinity"} ],
36
+ "dtype_hex": "0x27",
37
+ "dtype_alias": "FLOAT32",
38
+ "padding": 0,
39
+ "canonical_bson": "2000000005766563746F72000E000000092700000080FF000000000000807F00"
40
+ },
41
+ {
42
+ "description": "FLOAT32 with padding",
43
+ "valid": false,
44
+ "vector": [127.0, 7.0],
45
+ "dtype_hex": "0x27",
46
+ "dtype_alias": "FLOAT32",
47
+ "padding": 3,
48
+ "canonical_bson": "1C00000005766563746F72000A0000000927030000FE420000E04000"
49
+ },
50
+ {
51
+ "description": "Insufficient vector data with 3 bytes FLOAT32",
52
+ "valid": false,
53
+ "dtype_hex": "0x27",
54
+ "dtype_alias": "FLOAT32",
55
+ "canonical_bson": "1700000005766563746F7200050000000927002A2A2A00"
56
+ },
57
+ {
58
+ "description": "Insufficient vector data with 5 bytes FLOAT32",
59
+ "valid": false,
60
+ "dtype_hex": "0x27",
61
+ "dtype_alias": "FLOAT32",
62
+ "canonical_bson": "1900000005766563746F7200070000000927002A2A2A2A2A00"
63
+ }
64
+ ]
65
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "description": "Tests of Binary subtype 9, Vectors, with dtype INT8",
3
+ "test_key": "vector",
4
+ "tests": [
5
+ {
6
+ "description": "Simple Vector INT8",
7
+ "valid": true,
8
+ "vector": [127, 7],
9
+ "dtype_hex": "0x03",
10
+ "dtype_alias": "INT8",
11
+ "padding": 0,
12
+ "canonical_bson": "1600000005766563746F7200040000000903007F0700"
13
+ },
14
+ {
15
+ "description": "Empty Vector INT8",
16
+ "valid": true,
17
+ "vector": [],
18
+ "dtype_hex": "0x03",
19
+ "dtype_alias": "INT8",
20
+ "padding": 0,
21
+ "canonical_bson": "1400000005766563746F72000200000009030000"
22
+ },
23
+ {
24
+ "description": "Overflow Vector INT8",
25
+ "valid": false,
26
+ "vector": [128],
27
+ "dtype_hex": "0x03",
28
+ "dtype_alias": "INT8",
29
+ "padding": 0
30
+ },
31
+ {
32
+ "description": "Underflow Vector INT8",
33
+ "valid": false,
34
+ "vector": [-129],
35
+ "dtype_hex": "0x03",
36
+ "dtype_alias": "INT8",
37
+ "padding": 0
38
+ },
39
+ {
40
+ "description": "INT8 with padding",
41
+ "valid": false,
42
+ "vector": [127, 7],
43
+ "dtype_hex": "0x03",
44
+ "dtype_alias": "INT8",
45
+ "padding": 3,
46
+ "canonical_bson": "1600000005766563746F7200040000000903037F0700"
47
+ },
48
+ {
49
+ "description": "INT8 with float inputs",
50
+ "valid": false,
51
+ "vector": [127.77, 7.77],
52
+ "dtype_hex": "0x03",
53
+ "dtype_alias": "INT8",
54
+ "padding": 0
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,83 @@
1
+ {
2
+ "description": "Tests of Binary subtype 9, Vectors, with dtype PACKED_BIT",
3
+ "test_key": "vector",
4
+ "tests": [
5
+ {
6
+ "description": "Padding specified with no vector data PACKED_BIT",
7
+ "valid": false,
8
+ "vector": [],
9
+ "dtype_hex": "0x10",
10
+ "dtype_alias": "PACKED_BIT",
11
+ "padding": 1,
12
+ "canonical_bson": "1400000005766563746F72000200000009100100"
13
+ },
14
+ {
15
+ "description": "Simple Vector PACKED_BIT",
16
+ "valid": true,
17
+ "vector": [127, 7],
18
+ "dtype_hex": "0x10",
19
+ "dtype_alias": "PACKED_BIT",
20
+ "padding": 0,
21
+ "canonical_bson": "1600000005766563746F7200040000000910007F0700"
22
+ },
23
+ {
24
+ "description": "Empty Vector PACKED_BIT",
25
+ "valid": true,
26
+ "vector": [],
27
+ "dtype_hex": "0x10",
28
+ "dtype_alias": "PACKED_BIT",
29
+ "padding": 0,
30
+ "canonical_bson": "1400000005766563746F72000200000009100000"
31
+ },
32
+ {
33
+ "description": "PACKED_BIT with padding",
34
+ "valid": true,
35
+ "vector": [127, 7],
36
+ "dtype_hex": "0x10",
37
+ "dtype_alias": "PACKED_BIT",
38
+ "padding": 3,
39
+ "canonical_bson": "1600000005766563746F7200040000000910037F0700"
40
+ },
41
+ {
42
+ "description": "Overflow Vector PACKED_BIT",
43
+ "valid": false,
44
+ "vector": [256],
45
+ "dtype_hex": "0x10",
46
+ "dtype_alias": "PACKED_BIT",
47
+ "padding": 0
48
+ },
49
+ {
50
+ "description": "Underflow Vector PACKED_BIT",
51
+ "valid": false,
52
+ "vector": [-1],
53
+ "dtype_hex": "0x10",
54
+ "dtype_alias": "PACKED_BIT",
55
+ "padding": 0
56
+ },
57
+ {
58
+ "description": "Vector with float values PACKED_BIT",
59
+ "valid": false,
60
+ "vector": [127.5],
61
+ "dtype_hex": "0x10",
62
+ "dtype_alias": "PACKED_BIT",
63
+ "padding": 0
64
+ },
65
+ {
66
+ "description": "Exceeding maximum padding PACKED_BIT",
67
+ "valid": false,
68
+ "vector": [1],
69
+ "dtype_hex": "0x10",
70
+ "dtype_alias": "PACKED_BIT",
71
+ "padding": 8,
72
+ "canonical_bson": "1500000005766563746F7200030000000910080100"
73
+ },
74
+ {
75
+ "description": "Negative padding PACKED_BIT",
76
+ "valid": false,
77
+ "vector": [1],
78
+ "dtype_hex": "0x10",
79
+ "dtype_alias": "PACKED_BIT",
80
+ "padding": -1
81
+ }
82
+ ]
83
+ }
@@ -0,0 +1,15 @@
1
+ There are the following deliberate changes made to the corpus tests in Ruby:
2
+
3
+ 1. In double.js, Ruby appears to offer less precision than the spec tests
4
+ demand:
5
+
6
+ irb(main):001:0> -1.23456789012345677E+18
7
+ => -1.2345678901234568e+18
8
+
9
+ Because of this, -1.23456789012345677E+18 was changed to -1.2345678901234568e+18.
10
+ The "e" was lowercased as well. Both the precision reduction and the lowercasing
11
+ of "e" changes are also present in the Python driver, which appears to be
12
+ affected by the same precision limitation.
13
+
14
+ 2. In datetime.js, the millisecond component of iso8601 serialization of
15
+ timestamps is always present, even if it is zero.
@@ -0,0 +1,49 @@
1
+ {
2
+ "description": "Array",
3
+ "bson_type": "0x04",
4
+ "test_key": "a",
5
+ "valid": [
6
+ {
7
+ "description": "Empty",
8
+ "canonical_bson": "0D000000046100050000000000",
9
+ "canonical_extjson": "{\"a\" : []}"
10
+ },
11
+ {
12
+ "description": "Single Element Array",
13
+ "canonical_bson": "140000000461000C0000001030000A0000000000",
14
+ "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}"
15
+ },
16
+ {
17
+ "description": "Single Element Array with index set incorrectly to empty string",
18
+ "degenerate_bson": "130000000461000B00000010000A0000000000",
19
+ "canonical_bson": "140000000461000C0000001030000A0000000000",
20
+ "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}"
21
+ },
22
+ {
23
+ "description": "Single Element Array with index set incorrectly to ab",
24
+ "degenerate_bson": "150000000461000D000000106162000A0000000000",
25
+ "canonical_bson": "140000000461000C0000001030000A0000000000",
26
+ "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}"
27
+ },
28
+ {
29
+ "description": "Multi Element Array with duplicate indexes",
30
+ "degenerate_bson": "1b000000046100130000001030000a000000103000140000000000",
31
+ "canonical_bson": "1b000000046100130000001030000a000000103100140000000000",
32
+ "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}, {\"$numberInt\": \"20\"}]}"
33
+ }
34
+ ],
35
+ "decodeErrors": [
36
+ {
37
+ "description": "Array length too long: eats outer terminator",
38
+ "bson": "140000000461000D0000001030000A0000000000"
39
+ },
40
+ {
41
+ "description": "Array length too short: leaks terminator",
42
+ "bson": "140000000461000B0000001030000A0000000000"
43
+ },
44
+ {
45
+ "description": "Invalid Array: bad string length in field",
46
+ "bson": "1A00000004666F6F00100000000230000500000062617A000000"
47
+ }
48
+ ]
49
+ }