bson 1.7.0-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bson might be problematic. Click here for more details.

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