jonbell-mongo 1.3.1.2

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 (88) hide show
  1. data/LICENSE.txt +190 -0
  2. data/README.md +333 -0
  3. data/Rakefile +215 -0
  4. data/bin/mongo_console +21 -0
  5. data/docs/CREDITS.md +123 -0
  6. data/docs/FAQ.md +116 -0
  7. data/docs/GridFS.md +158 -0
  8. data/docs/HISTORY.md +263 -0
  9. data/docs/RELEASES.md +33 -0
  10. data/docs/REPLICA_SETS.md +72 -0
  11. data/docs/TUTORIAL.md +247 -0
  12. data/docs/WRITE_CONCERN.md +28 -0
  13. data/lib/mongo.rb +97 -0
  14. data/lib/mongo/collection.rb +895 -0
  15. data/lib/mongo/connection.rb +926 -0
  16. data/lib/mongo/cursor.rb +474 -0
  17. data/lib/mongo/db.rb +617 -0
  18. data/lib/mongo/exceptions.rb +71 -0
  19. data/lib/mongo/gridfs/grid.rb +107 -0
  20. data/lib/mongo/gridfs/grid_ext.rb +57 -0
  21. data/lib/mongo/gridfs/grid_file_system.rb +146 -0
  22. data/lib/mongo/gridfs/grid_io.rb +485 -0
  23. data/lib/mongo/gridfs/grid_io_fix.rb +38 -0
  24. data/lib/mongo/repl_set_connection.rb +356 -0
  25. data/lib/mongo/util/conversions.rb +89 -0
  26. data/lib/mongo/util/core_ext.rb +60 -0
  27. data/lib/mongo/util/pool.rb +177 -0
  28. data/lib/mongo/util/server_version.rb +71 -0
  29. data/lib/mongo/util/support.rb +82 -0
  30. data/lib/mongo/util/uri_parser.rb +185 -0
  31. data/mongo.gemspec +34 -0
  32. data/test/auxillary/1.4_features.rb +166 -0
  33. data/test/auxillary/authentication_test.rb +68 -0
  34. data/test/auxillary/autoreconnect_test.rb +41 -0
  35. data/test/auxillary/fork_test.rb +30 -0
  36. data/test/auxillary/repl_set_auth_test.rb +58 -0
  37. data/test/auxillary/slave_connection_test.rb +36 -0
  38. data/test/auxillary/threaded_authentication_test.rb +101 -0
  39. data/test/bson/binary_test.rb +15 -0
  40. data/test/bson/bson_test.rb +654 -0
  41. data/test/bson/byte_buffer_test.rb +208 -0
  42. data/test/bson/hash_with_indifferent_access_test.rb +38 -0
  43. data/test/bson/json_test.rb +17 -0
  44. data/test/bson/object_id_test.rb +154 -0
  45. data/test/bson/ordered_hash_test.rb +210 -0
  46. data/test/bson/timestamp_test.rb +24 -0
  47. data/test/collection_test.rb +910 -0
  48. data/test/connection_test.rb +324 -0
  49. data/test/conversions_test.rb +119 -0
  50. data/test/cursor_fail_test.rb +75 -0
  51. data/test/cursor_message_test.rb +43 -0
  52. data/test/cursor_test.rb +483 -0
  53. data/test/db_api_test.rb +738 -0
  54. data/test/db_connection_test.rb +15 -0
  55. data/test/db_test.rb +315 -0
  56. data/test/grid_file_system_test.rb +259 -0
  57. data/test/grid_io_test.rb +209 -0
  58. data/test/grid_test.rb +258 -0
  59. data/test/load/thin/load.rb +24 -0
  60. data/test/load/unicorn/load.rb +23 -0
  61. data/test/replica_sets/connect_test.rb +112 -0
  62. data/test/replica_sets/connection_string_test.rb +32 -0
  63. data/test/replica_sets/count_test.rb +35 -0
  64. data/test/replica_sets/insert_test.rb +53 -0
  65. data/test/replica_sets/pooled_insert_test.rb +55 -0
  66. data/test/replica_sets/query_secondaries.rb +108 -0
  67. data/test/replica_sets/query_test.rb +51 -0
  68. data/test/replica_sets/replication_ack_test.rb +66 -0
  69. data/test/replica_sets/rs_test_helper.rb +27 -0
  70. data/test/safe_test.rb +68 -0
  71. data/test/support/hash_with_indifferent_access.rb +186 -0
  72. data/test/support/keys.rb +45 -0
  73. data/test/support_test.rb +18 -0
  74. data/test/test_helper.rb +102 -0
  75. data/test/threading/threading_with_large_pool_test.rb +90 -0
  76. data/test/threading_test.rb +87 -0
  77. data/test/tools/auth_repl_set_manager.rb +14 -0
  78. data/test/tools/repl_set_manager.rb +266 -0
  79. data/test/unit/collection_test.rb +130 -0
  80. data/test/unit/connection_test.rb +85 -0
  81. data/test/unit/cursor_test.rb +109 -0
  82. data/test/unit/db_test.rb +94 -0
  83. data/test/unit/grid_test.rb +49 -0
  84. data/test/unit/pool_test.rb +9 -0
  85. data/test/unit/repl_set_connection_test.rb +59 -0
  86. data/test/unit/safe_test.rb +125 -0
  87. data/test/uri_test.rb +91 -0
  88. metadata +224 -0
@@ -0,0 +1,15 @@
1
+ # encoding:utf-8
2
+ require './test/test_helper'
3
+
4
+ class BinaryTest < Test::Unit::TestCase
5
+ context "Inspecting" do
6
+ setup do
7
+ @data = ("THIS IS BINARY " * 50).unpack("c*")
8
+ end
9
+
10
+ should "not display actual data" do
11
+ binary = BSON::Binary.new(@data)
12
+ assert_equal "<BSON::Binary:#{binary.object_id}>", binary.inspect
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,654 @@
1
+ # encoding:utf-8
2
+ require './test/test_helper'
3
+
4
+ if RUBY_VERSION < '1.9'
5
+ require 'complex'
6
+ require 'rational'
7
+ end
8
+ require 'bigdecimal'
9
+
10
+ begin
11
+ require 'tzinfo'
12
+ require 'active_support/core_ext'
13
+ Time.zone = "Pacific Time (US & Canada)"
14
+ Zone = Time.zone.now
15
+ rescue LoadError
16
+ warn 'Mocking time with zone'
17
+ module ActiveSupport
18
+ class TimeWithZone
19
+ def initialize(utc_time, zone)
20
+ end
21
+ end
22
+ end
23
+ Zone = ActiveSupport::TimeWithZone.new(Time.now.utc, 'EST')
24
+ end
25
+
26
+ class BSONTest < Test::Unit::TestCase
27
+
28
+ include BSON
29
+
30
+ def setup
31
+ @encoder = BSON::BSON_CODER
32
+ end
33
+
34
+ def assert_doc_pass(doc, options={})
35
+ bson = @encoder.serialize(doc)
36
+ if options[:debug]
37
+ puts "DEBUGGING DOC:"
38
+ p bson.to_a
39
+ puts "DESERIALIZES TO:"
40
+ end
41
+ assert_equal @encoder.serialize(doc).to_a, bson.to_a
42
+ assert_equal doc, @encoder.deserialize(bson)
43
+ end
44
+
45
+ def test_require_hash
46
+ assert_raise_error InvalidDocument, "takes a Hash" do
47
+ BSON.serialize('foo')
48
+ end
49
+
50
+ assert_raise_error InvalidDocument, "takes a Hash" do
51
+ BSON.serialize(Object.new)
52
+ end
53
+
54
+ assert_raise_error InvalidDocument, "takes a Hash" do
55
+ BSON.serialize(Set.new)
56
+ end
57
+ end
58
+
59
+ def test_string
60
+ doc = {'doc' => 'hello, world'}
61
+ assert_doc_pass(doc)
62
+ end
63
+
64
+ def test_valid_utf8_string
65
+ doc = {'doc' => 'aé'}
66
+ assert_doc_pass(doc)
67
+ end
68
+
69
+ def test_valid_utf8_key
70
+ doc = {'aé' => 'hello'}
71
+ assert_doc_pass(doc)
72
+ end
73
+
74
+ def test_limit_max_bson_size
75
+ doc = {'name' => 'a' * BSON_CODER.max_bson_size}
76
+ assert_raise InvalidDocument do
77
+ assert @encoder.serialize(doc)
78
+ end
79
+ end
80
+
81
+ def test_max_bson_size
82
+ assert BSON_CODER.max_bson_size >= BSON::DEFAULT_MAX_BSON_SIZE
83
+ end
84
+
85
+ def test_update_max_bson_size
86
+ require 'ostruct'
87
+ mock_conn = OpenStruct.new
88
+ size = 7 * 1024 * 1024
89
+ mock_conn.max_bson_size = size
90
+ assert_equal size, BSON_CODER.update_max_bson_size(mock_conn)
91
+ assert_equal size, BSON_CODER.max_bson_size
92
+ end
93
+
94
+ def test_round_trip
95
+ doc = {'doc' => 123}
96
+ @encoder.deserialize(@encoder.serialize(doc))
97
+ end
98
+
99
+ # In 1.8 we test that other string encodings raise an exception.
100
+ # In 1.9 we test that they get auto-converted.
101
+ if RUBY_VERSION < '1.9'
102
+ if ! RUBY_PLATFORM =~ /java/
103
+ require 'iconv'
104
+ def test_non_utf8_string
105
+ string = Iconv.conv('iso-8859-1', 'utf-8', 'aé')
106
+ doc = {'doc' => string}
107
+ assert_doc_pass(doc)
108
+ assert_raise InvalidStringEncoding do
109
+ @encoder.serialize(doc)
110
+ end
111
+ end
112
+
113
+ def test_non_utf8_key
114
+ key = Iconv.conv('iso-8859-1', 'utf-8', 'aé')
115
+ doc = {key => 'hello'}
116
+ assert_raise InvalidStringEncoding do
117
+ @encoder.serialize(doc)
118
+ end
119
+ end
120
+ end
121
+ else
122
+ def test_non_utf8_string
123
+ assert_raise BSON::InvalidStringEncoding do
124
+ BSON::BSON_CODER.serialize({'str' => 'aé'.encode('iso-8859-1')})
125
+ end
126
+ end
127
+
128
+ def test_invalid_utf8_string
129
+ str = "123\xD9"
130
+ assert !str.valid_encoding?
131
+ assert_raise BSON::InvalidStringEncoding do
132
+ BSON::BSON_CODER.serialize({'str' => str})
133
+ end
134
+ end
135
+
136
+ def test_non_utf8_key
137
+ assert_raise BSON::InvalidStringEncoding do
138
+ BSON::BSON_CODER.serialize({'aé'.encode('iso-8859-1') => 'hello'})
139
+ end
140
+ end
141
+
142
+ # Based on a test from sqlite3-ruby
143
+ def test_default_internal_is_honored
144
+ before_enc = Encoding.default_internal
145
+
146
+ str = "壁に耳あり、障子に目あり"
147
+ bson = BSON::BSON_CODER.serialize("x" => str)
148
+
149
+ silently { Encoding.default_internal = 'EUC-JP' }
150
+ out = BSON::BSON_CODER.deserialize(bson)["x"]
151
+
152
+ assert_equal Encoding.default_internal, out.encoding
153
+ assert_equal str.encode('EUC-JP'), out
154
+ assert_equal str, out.encode(str.encoding)
155
+ ensure
156
+ silently { Encoding.default_internal = before_enc }
157
+ end
158
+ end
159
+
160
+ def test_code
161
+ doc = {'$where' => Code.new('this.a.b < this.b')}
162
+ assert_doc_pass(doc)
163
+ end
164
+
165
+ def test_code_with_symbol
166
+ assert_raise_error ArgumentError, "BSON::Code must be in the form of a String" do
167
+ Code.new(:fubar)
168
+ end
169
+ end
170
+
171
+ def test_code_with_scope
172
+ doc = {'$where' => Code.new('this.a.b < this.b', {'foo' => 1})}
173
+ assert_doc_pass(doc)
174
+ end
175
+
176
+ def test_double
177
+ doc = {'doc' => 41.25}
178
+ assert_doc_pass(doc)
179
+ end
180
+
181
+ def test_int
182
+ doc = {'doc' => 42}
183
+ assert_doc_pass(doc)
184
+
185
+ doc = {"doc" => -5600}
186
+ assert_doc_pass(doc)
187
+
188
+ doc = {"doc" => 2147483647}
189
+ assert_doc_pass(doc)
190
+
191
+ doc = {"doc" => -2147483648}
192
+ assert_doc_pass(doc)
193
+ end
194
+
195
+ def test_ordered_hash
196
+ doc = BSON::OrderedHash.new
197
+ doc["b"] = 1
198
+ doc["a"] = 2
199
+ doc["c"] = 3
200
+ doc["d"] = 4
201
+ assert_doc_pass(doc)
202
+ end
203
+
204
+ def test_object
205
+ doc = {'doc' => {'age' => 42, 'name' => 'Spongebob', 'shoe_size' => 9.5}}
206
+ assert_doc_pass(doc)
207
+ end
208
+
209
+ def test_embedded_document_with_nil
210
+ doc = {'doc' => {'age' => 42, 'name' => nil, 'shoe_size' => 9.5}}
211
+ assert_doc_pass(doc)
212
+ end
213
+
214
+ def test_embedded_document_with_date
215
+ doc = {'doc' => {'age' => 42, 'date' => Time.now.utc, 'shoe_size' => 9.5}}
216
+ bson = @encoder.serialize(doc)
217
+ doc2 = @encoder.deserialize(bson)
218
+ assert doc['doc']
219
+ assert_equal 42, doc['doc']['age']
220
+ assert_equal 9.5, doc['doc']['shoe_size']
221
+ assert_in_delta Time.now, doc['doc']['date'], 1
222
+ end
223
+
224
+ def test_oid
225
+ doc = {'doc' => ObjectId.new}
226
+ assert_doc_pass(doc)
227
+ end
228
+
229
+ def test_array
230
+ doc = {'doc' => [1, 2, 'a', 'b']}
231
+ assert_doc_pass(doc)
232
+ end
233
+
234
+ def test_array_keys
235
+ doc = {'doc' => [1, 2, 'a', 'b']}
236
+ bson = @encoder.serialize(doc).to_a
237
+ assert_equal 48, bson[14]
238
+ assert_equal 49, bson[21]
239
+ assert_equal 50, bson[28]
240
+ assert_equal 51, bson[37]
241
+ end
242
+
243
+ def test_regex
244
+ doc = {'doc' => /foobar/i}
245
+ assert_doc_pass(doc)
246
+ end
247
+
248
+ def test_regex_multiline
249
+ doc = {'doc' => /foobar/m}
250
+ assert_doc_pass(doc)
251
+ end
252
+
253
+ def test_boolean
254
+ doc = {'doc' => true}
255
+ assert_doc_pass(doc)
256
+ end
257
+
258
+ def test_date
259
+ doc = {'date' => Time.now}
260
+ bson = @encoder.serialize(doc)
261
+ doc2 = @encoder.deserialize(bson)
262
+ # Mongo only stores up to the millisecond
263
+ assert_in_delta doc['date'], doc2['date'], 0.001
264
+ end
265
+
266
+ def test_date_in_array
267
+ doc = {'date' => [Time.now.utc]}
268
+ bson = @encoder.serialize(doc)
269
+ doc2 = @encoder.deserialize(bson)
270
+ end
271
+
272
+ def test_date_returns_as_utc
273
+ doc = {'date' => Time.now.utc}
274
+ bson = @encoder.serialize(doc)
275
+ doc2 = @encoder.deserialize(bson)
276
+ assert doc2['date'].utc?
277
+ end
278
+
279
+ def test_date_before_epoch
280
+ begin
281
+ doc = {'date' => Time.utc(1600)}
282
+ bson = @encoder.serialize(doc)
283
+ doc2 = @encoder.deserialize(bson)
284
+ # Mongo only stores up to the millisecond
285
+ assert_in_delta doc['date'], doc2['date'], 2
286
+ rescue ArgumentError
287
+ # some versions of Ruby won't let you create pre-epoch Time instances
288
+ #
289
+ # TODO figure out how that will work if somebady has saved data
290
+ # w/ early dates already and is just querying for it.
291
+ end
292
+ end
293
+
294
+ def test_exeption_on_using_unsupported_date_class
295
+ [DateTime.now, Date.today, Zone].each do |invalid_date|
296
+ doc = {:date => invalid_date}
297
+ begin
298
+ bson = BSON::BSON_CODER.serialize(doc)
299
+ rescue => e
300
+ ensure
301
+ if !invalid_date.is_a? Time
302
+ assert_equal InvalidDocument, e.class
303
+ assert_match(/UTC Time/, e.message)
304
+ end
305
+ end
306
+ end
307
+ end
308
+
309
+ def test_dbref
310
+ oid = ObjectId.new
311
+ doc = {}
312
+ doc['dbref'] = DBRef.new('namespace', oid)
313
+ bson = @encoder.serialize(doc)
314
+ doc2 = @encoder.deserialize(bson)
315
+
316
+ # Java doesn't deserialize to DBRefs
317
+ if RUBY_PLATFORM =~ /java/
318
+ assert_equal 'namespace', doc2['dbref']['$ns']
319
+ assert_equal oid, doc2['dbref']['$id']
320
+ else
321
+ assert_equal 'namespace', doc2['dbref'].namespace
322
+ assert_equal oid, doc2['dbref'].object_id
323
+ end
324
+ end
325
+
326
+ def test_symbol
327
+ doc = {'sym' => :foo}
328
+ bson = @encoder.serialize(doc)
329
+ doc2 = @encoder.deserialize(bson)
330
+ assert_equal :foo, doc2['sym']
331
+ end
332
+
333
+ def test_binary
334
+ bin = Binary.new
335
+ 'binstring'.each_byte { |b| bin.put(b) }
336
+
337
+ doc = {'bin' => bin}
338
+ bson = @encoder.serialize(doc)
339
+ doc2 = @encoder.deserialize(bson)
340
+ bin2 = doc2['bin']
341
+ assert_kind_of Binary, bin2
342
+ assert_equal 'binstring', bin2.to_s
343
+ assert_equal Binary::SUBTYPE_SIMPLE, bin2.subtype
344
+ end
345
+
346
+ def test_binary_with_deprecated_subtype
347
+ bin = Binary.new
348
+ 'binstring'.each_byte { |b| bin.put(b) }
349
+ bin.subtype = Binary::SUBTYPE_BYTES
350
+
351
+ doc = {'bin' => bin}
352
+ bson = @encoder.serialize(doc)
353
+ doc2 = @encoder.deserialize(bson)
354
+ bin2 = doc2['bin']
355
+ assert_kind_of Binary, bin2
356
+ assert_equal 'binstring', bin2.to_s
357
+ assert_equal Binary::SUBTYPE_BYTES, bin2.subtype
358
+ end
359
+
360
+ def test_binary_with_string
361
+ b = Binary.new('somebinarystring')
362
+ doc = {'bin' => b}
363
+ bson = @encoder.serialize(doc)
364
+ doc2 = @encoder.deserialize(bson)
365
+ bin2 = doc2['bin']
366
+ assert_kind_of Binary, bin2
367
+ assert_equal 'somebinarystring', bin2.to_s
368
+ assert_equal Binary::SUBTYPE_SIMPLE, bin2.subtype
369
+ end
370
+
371
+ def test_binary_type
372
+ bin = Binary.new([1, 2, 3, 4, 5], Binary::SUBTYPE_USER_DEFINED)
373
+
374
+ doc = {'bin' => bin}
375
+ bson = @encoder.serialize(doc)
376
+ doc2 = @encoder.deserialize(bson)
377
+ bin2 = doc2['bin']
378
+ assert_kind_of Binary, bin2
379
+ assert_equal [1, 2, 3, 4, 5], bin2.to_a
380
+ assert_equal Binary::SUBTYPE_USER_DEFINED, bin2.subtype
381
+ end
382
+
383
+ # Java doesn't support binary subtype 0 yet
384
+ if !(RUBY_PLATFORM =~ /java/)
385
+ def test_binary_subtype_0
386
+ bin = Binary.new([1, 2, 3, 4, 5], Binary::SUBTYPE_SIMPLE)
387
+
388
+ doc = {'bin' => bin}
389
+ bson = @encoder.serialize(doc)
390
+ doc2 = @encoder.deserialize(bson)
391
+ bin2 = doc2['bin']
392
+ assert_kind_of Binary, bin2
393
+ assert_equal [1, 2, 3, 4, 5], bin2.to_a
394
+ assert_equal Binary::SUBTYPE_SIMPLE, bin2.subtype
395
+ end
396
+ end
397
+
398
+ def test_binary_byte_buffer
399
+ bb = Binary.new
400
+ 5.times { |i| bb.put(i + 1) }
401
+
402
+ doc = {'bin' => bb}
403
+ bson = @encoder.serialize(doc)
404
+ doc2 = @encoder.deserialize(bson)
405
+ bin2 = doc2['bin']
406
+ assert_kind_of Binary, bin2
407
+ assert_equal [1, 2, 3, 4, 5], bin2.to_a
408
+ assert_equal Binary::SUBTYPE_SIMPLE, bin2.subtype
409
+ end
410
+
411
+ def test_put_id_first
412
+ val = BSON::OrderedHash.new
413
+ val['not_id'] = 1
414
+ val['_id'] = 2
415
+ roundtrip = @encoder.deserialize(@encoder.serialize(val, false, true).to_s)
416
+ assert_kind_of BSON::OrderedHash, roundtrip
417
+ assert_equal '_id', roundtrip.keys.first
418
+
419
+ val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'}
420
+ roundtrip = @encoder.deserialize(@encoder.serialize(val, false, true).to_s)
421
+ assert_kind_of BSON::OrderedHash, roundtrip
422
+ assert_equal '_id', roundtrip.keys.first
423
+ end
424
+
425
+ def test_nil_id
426
+ doc = {"_id" => nil}
427
+ assert_doc_pass(doc)
428
+ end
429
+
430
+ if !(RUBY_PLATFORM =~ /java/)
431
+ def test_timestamp
432
+ val = {"test" => [4, 20]}
433
+ result = @encoder.deserialize([0x13, 0x00, 0x00, 0x00,
434
+ 0x11, 0x74, 0x65, 0x73,
435
+ 0x74, 0x00, 0x04, 0x00,
436
+ 0x00, 0x00, 0x14, 0x00,
437
+ 0x00, 0x00, 0x00])
438
+
439
+ assert_equal 4, result["test"][0]
440
+ assert_equal 20, result["test"][1]
441
+ end
442
+ end
443
+
444
+ def test_timestamp_type
445
+ ts = Timestamp.new(5000, 100)
446
+ doc = {:ts => ts}
447
+ bson = @encoder.serialize(doc)
448
+ assert_equal ts, @encoder.deserialize(bson)["ts"]
449
+ end
450
+
451
+ def test_overflow
452
+ doc = {"x" => 2**75}
453
+ assert_raise RangeError do
454
+ bson = @encoder.serialize(doc)
455
+ end
456
+
457
+ doc = {"x" => 9223372036854775}
458
+ assert_doc_pass(doc)
459
+
460
+ doc = {"x" => 9223372036854775807}
461
+ assert_doc_pass(doc)
462
+
463
+ doc["x"] = doc["x"] + 1
464
+ assert_raise RangeError do
465
+ bson = @encoder.serialize(doc)
466
+ end
467
+
468
+ doc = {"x" => -9223372036854775}
469
+ assert_doc_pass(doc)
470
+
471
+ doc = {"x" => -9223372036854775808}
472
+ assert_doc_pass(doc)
473
+
474
+ doc["x"] = doc["x"] - 1
475
+ assert_raise RangeError do
476
+ bson = BSON::BSON_CODER.serialize(doc)
477
+ end
478
+ end
479
+
480
+ def test_invalid_numeric_types
481
+ [BigDecimal.new("1.0"), Complex(0, 1), Rational(2, 3)].each do |type|
482
+ doc = {"x" => type}
483
+ begin
484
+ @encoder.serialize(doc)
485
+ rescue => e
486
+ ensure
487
+ assert_equal InvalidDocument, e.class
488
+ assert_match(/Cannot serialize/, e.message)
489
+ end
490
+ end
491
+ end
492
+
493
+ def test_do_not_change_original_object
494
+ val = BSON::OrderedHash.new
495
+ val['not_id'] = 1
496
+ val['_id'] = 2
497
+ assert val.keys.include?('_id')
498
+ @encoder.serialize(val)
499
+ assert val.keys.include?('_id')
500
+
501
+ val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'}
502
+ assert val.keys.include?(:_id)
503
+ @encoder.serialize(val)
504
+ assert val.keys.include?(:_id)
505
+ end
506
+
507
+ # note we only test for _id here because in the general case we will
508
+ # write duplicates for :key and "key". _id is a special case because
509
+ # we call has_key? to check for it's existence rather than just iterating
510
+ # over it like we do for the rest of the keys. thus, things like
511
+ # HashWithIndifferentAccess can cause problems for _id but not for other
512
+ # keys. rather than require rails to test with HWIA directly, we do this
513
+ # somewhat hacky test.
514
+ #
515
+ # Note that the driver only eliminates duplicate ids when move_id is true.
516
+ def test_no_duplicate_id
517
+ dup = {"_id" => "foo", :_id => "foo"}
518
+ one = {"_id" => "foo"}
519
+
520
+ assert_equal @encoder.serialize(one, false, true).to_a, @encoder.serialize(dup, false, true).to_a
521
+ end
522
+
523
+ def test_duplicate_keys
524
+ #dup = {"_foo" => "foo", :_foo => "foo"}
525
+ #one = {"_foo" => "foo"}
526
+
527
+ #assert_equal @encoder.serialize(one).to_a, @encoder.serialize(dup).to_a
528
+ warn "Pending test for duplicate keys"
529
+ end
530
+
531
+ def test_no_duplicate_id_when_moving_id
532
+ dup = {"_id" => "foo", :_id => "foo"}
533
+ one = {:_id => "foo"}
534
+
535
+ assert_equal @encoder.serialize(one, false, true).to_s, @encoder.serialize(dup, false, true).to_s
536
+ end
537
+
538
+ def test_null_character
539
+ doc = {"a" => "\x00"}
540
+
541
+ assert_doc_pass(doc)
542
+
543
+ assert_raise InvalidDocument do
544
+ @encoder.serialize({"\x00" => "a"})
545
+ end
546
+
547
+ assert_raise InvalidDocument do
548
+ @encoder.serialize({"a" => (Regexp.compile "ab\x00c")})
549
+ end
550
+ end
551
+
552
+ def test_max_key
553
+ doc = {"a" => MaxKey.new}
554
+ assert_doc_pass(doc)
555
+ end
556
+
557
+ def test_min_key
558
+ doc = {"a" => MinKey.new}
559
+ assert_doc_pass(doc)
560
+ end
561
+
562
+ def test_invalid_object
563
+ o = Object.new
564
+ assert_raise InvalidDocument do
565
+ @encoder.serialize({:foo => o})
566
+ end
567
+
568
+ assert_raise InvalidDocument do
569
+ @encoder.serialize({:foo => Date.today})
570
+ end
571
+ end
572
+
573
+ def test_move_id
574
+ a = BSON::OrderedHash.new
575
+ a['text'] = 'abc'
576
+ a['key'] = 'abc'
577
+ a['_id'] = 1
578
+
579
+
580
+ assert_equal ")\000\000\000\020_id\000\001\000\000\000\002text" +
581
+ "\000\004\000\000\000abc\000\002key\000\004\000\000\000abc\000\000",
582
+ @encoder.serialize(a, false, true).to_s
583
+
584
+ assert_equal ")\000\000\000\002text\000\004\000\000\000abc\000\002key" +
585
+ "\000\004\000\000\000abc\000\020_id\000\001\000\000\000\000",
586
+ @encoder.serialize(a, false, false).to_s
587
+ end
588
+
589
+ def test_move_id_with_nested_doc
590
+ b = BSON::OrderedHash.new
591
+ b['text'] = 'abc'
592
+ b['_id'] = 2
593
+ c = BSON::OrderedHash.new
594
+ c['text'] = 'abc'
595
+ c['hash'] = b
596
+ c['_id'] = 3
597
+ assert_equal ">\000\000\000\020_id\000\003\000\000\000\002text" +
598
+ "\000\004\000\000\000abc\000\003hash\000\034\000\000" +
599
+ "\000\002text\000\004\000\000\000abc\000\020_id\000\002\000\000\000\000\000",
600
+ @encoder.serialize(c, false, true).to_s
601
+
602
+ # Java doesn't support this. Isn't actually necessary.
603
+ if !(RUBY_PLATFORM =~ /java/)
604
+ assert_equal ">\000\000\000\002text\000\004\000\000\000abc\000\003hash" +
605
+ "\000\034\000\000\000\002text\000\004\000\000\000abc\000\020_id" +
606
+ "\000\002\000\000\000\000\020_id\000\003\000\000\000\000",
607
+ @encoder.serialize(c, false, false).to_s
608
+ end
609
+ end
610
+
611
+ def test_invalid_key_names
612
+ assert @encoder.serialize({"hello" => "world"}, true)
613
+ assert @encoder.serialize({"hello" => {"hello" => "world"}}, true)
614
+
615
+ assert @encoder.serialize({"he$llo" => "world"}, true)
616
+ assert @encoder.serialize({"hello" => {"hell$o" => "world"}}, true)
617
+
618
+ assert_raise BSON::InvalidDocument do
619
+ @encoder.serialize({"he\0llo" => "world"}, true)
620
+ end
621
+
622
+ assert_raise BSON::InvalidKeyName do
623
+ @encoder.serialize({"$hello" => "world"}, true)
624
+ end
625
+
626
+ assert_raise BSON::InvalidKeyName do
627
+ @encoder.serialize({"hello" => {"$hello" => "world"}}, true)
628
+ end
629
+
630
+ assert_raise BSON::InvalidKeyName do
631
+ @encoder.serialize({".hello" => "world"}, true)
632
+ end
633
+
634
+ assert_raise BSON::InvalidKeyName do
635
+ @encoder.serialize({"hello" => {".hello" => "world"}}, true)
636
+ end
637
+
638
+ assert_raise BSON::InvalidKeyName do
639
+ @encoder.serialize({"hello." => "world"}, true)
640
+ end
641
+
642
+ assert_raise BSON::InvalidKeyName do
643
+ @encoder.serialize({"hello" => {"hello." => "world"}}, true)
644
+ end
645
+
646
+ assert_raise BSON::InvalidKeyName do
647
+ @encoder.serialize({"hel.lo" => "world"}, true)
648
+ end
649
+
650
+ assert_raise BSON::InvalidKeyName do
651
+ @encoder.serialize({"hello" => {"hel.lo" => "world"}}, true)
652
+ end
653
+ end
654
+ end