jonbell-mongo 1.3.1.2

Sign up to get free protection for your applications and to get access to all the features.
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