animehunter-mongo 0.9

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 (79) hide show
  1. data/README.rdoc +311 -0
  2. data/Rakefile +62 -0
  3. data/bin/bson_benchmark.rb +59 -0
  4. data/bin/mongo_console +21 -0
  5. data/bin/run_test_script +19 -0
  6. data/bin/standard_benchmark +109 -0
  7. data/examples/admin.rb +41 -0
  8. data/examples/benchmarks.rb +42 -0
  9. data/examples/blog.rb +76 -0
  10. data/examples/capped.rb +23 -0
  11. data/examples/cursor.rb +47 -0
  12. data/examples/gridfs.rb +87 -0
  13. data/examples/index_test.rb +125 -0
  14. data/examples/info.rb +30 -0
  15. data/examples/queries.rb +69 -0
  16. data/examples/simple.rb +23 -0
  17. data/examples/strict.rb +34 -0
  18. data/examples/types.rb +40 -0
  19. data/lib/mongo.rb +19 -0
  20. data/lib/mongo/admin.rb +87 -0
  21. data/lib/mongo/collection.rb +235 -0
  22. data/lib/mongo/cursor.rb +227 -0
  23. data/lib/mongo/db.rb +538 -0
  24. data/lib/mongo/gridfs.rb +16 -0
  25. data/lib/mongo/gridfs/chunk.rb +96 -0
  26. data/lib/mongo/gridfs/grid_store.rb +468 -0
  27. data/lib/mongo/message.rb +20 -0
  28. data/lib/mongo/message/get_more_message.rb +37 -0
  29. data/lib/mongo/message/insert_message.rb +35 -0
  30. data/lib/mongo/message/kill_cursors_message.rb +36 -0
  31. data/lib/mongo/message/message.rb +84 -0
  32. data/lib/mongo/message/message_header.rb +50 -0
  33. data/lib/mongo/message/msg_message.rb +33 -0
  34. data/lib/mongo/message/opcodes.rb +32 -0
  35. data/lib/mongo/message/query_message.rb +77 -0
  36. data/lib/mongo/message/remove_message.rb +36 -0
  37. data/lib/mongo/message/update_message.rb +37 -0
  38. data/lib/mongo/mongo.rb +164 -0
  39. data/lib/mongo/query.rb +119 -0
  40. data/lib/mongo/types/binary.rb +42 -0
  41. data/lib/mongo/types/code.rb +34 -0
  42. data/lib/mongo/types/dbref.rb +37 -0
  43. data/lib/mongo/types/objectid.rb +137 -0
  44. data/lib/mongo/types/regexp_of_holding.rb +44 -0
  45. data/lib/mongo/types/undefined.rb +31 -0
  46. data/lib/mongo/util/bson.rb +534 -0
  47. data/lib/mongo/util/byte_buffer.rb +167 -0
  48. data/lib/mongo/util/ordered_hash.rb +96 -0
  49. data/lib/mongo/util/xml_to_ruby.rb +107 -0
  50. data/mongo-ruby-driver.gemspec +99 -0
  51. data/tests/mongo-qa/_common.rb +8 -0
  52. data/tests/mongo-qa/admin +26 -0
  53. data/tests/mongo-qa/capped +22 -0
  54. data/tests/mongo-qa/count1 +18 -0
  55. data/tests/mongo-qa/dbs +22 -0
  56. data/tests/mongo-qa/find +10 -0
  57. data/tests/mongo-qa/find1 +15 -0
  58. data/tests/mongo-qa/gridfs_in +16 -0
  59. data/tests/mongo-qa/gridfs_out +17 -0
  60. data/tests/mongo-qa/indices +49 -0
  61. data/tests/mongo-qa/remove +25 -0
  62. data/tests/mongo-qa/stress1 +35 -0
  63. data/tests/mongo-qa/test1 +11 -0
  64. data/tests/mongo-qa/update +18 -0
  65. data/tests/test_admin.rb +69 -0
  66. data/tests/test_bson.rb +246 -0
  67. data/tests/test_byte_buffer.rb +69 -0
  68. data/tests/test_chunk.rb +84 -0
  69. data/tests/test_cursor.rb +121 -0
  70. data/tests/test_db.rb +160 -0
  71. data/tests/test_db_api.rb +701 -0
  72. data/tests/test_db_connection.rb +18 -0
  73. data/tests/test_grid_store.rb +284 -0
  74. data/tests/test_message.rb +35 -0
  75. data/tests/test_mongo.rb +78 -0
  76. data/tests/test_objectid.rb +98 -0
  77. data/tests/test_ordered_hash.rb +129 -0
  78. data/tests/test_round_trip.rb +116 -0
  79. metadata +133 -0
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '../..', 'lib')
2
+ require 'mongo'
3
+
4
+ DEFAULT_HOST = '127.0.0.1'
5
+ DEFAULT_PORT = 27017
6
+ DEFAULT_DB = 'driver_test_framework'
7
+
8
+ include XGen::Mongo::Driver
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+
6
+ db.collection('test').insert({'test' => 1})
7
+ admin = db.admin
8
+
9
+ if $DEBUG
10
+ db.drop_collection('tester')
11
+ admin.profiling_level = :slow_only
12
+ end
13
+
14
+ ['test', 'pdlskwmf', '$'].each { |name|
15
+ begin
16
+ admin.validate_collection(name)
17
+ puts 'true'
18
+ rescue => ex
19
+ puts 'false'
20
+ end
21
+ }
22
+
23
+ level_xlation = {:off => 'off', :all => 'all', :slow_only => 'slowOnly'}
24
+ puts level_xlation[admin.profiling_level]
25
+ admin.profiling_level = :off
26
+ puts level_xlation[admin.profiling_level]
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+
6
+ if $DEBUG
7
+ db.drop_collection('capped1')
8
+ db.drop_collection('capped2')
9
+ end
10
+
11
+ db.create_collection('capped1', :capped => true, :size => 500)
12
+ coll = db.collection('capped1')
13
+ coll.insert('x' => 1)
14
+ coll.insert('x' => 2)
15
+
16
+ db.create_collection('capped2', :capped => true, :size => 1000, :max => 11)
17
+ coll = db.collection('capped2')
18
+ str = ''
19
+ 100.times {
20
+ coll.insert('dashes' => str)
21
+ str << '-'
22
+ }
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+
6
+ if $DEBUG
7
+ 3.times { |i| db.drop_collection("test#{i+1}") }
8
+ db.create_collection('test1')
9
+ db.collection('test2').insert({:name => 'a'})
10
+ c = db.collection('test3')
11
+ 100.times { |i| c.insert(:i => i, :foo => 'bar') }
12
+ end
13
+
14
+ puts db.collection('test1').count
15
+ puts db.collection('test2').count
16
+ puts db.collection('test3').count('i' => 'a')
17
+ puts db.collection('test3').count('i' => 3)
18
+ puts db.collection('test3').count({'i' => {'$gte' => 67}})
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+
6
+ if $DEBUG
7
+ 3.times { |i| db.drop_collection("dbs_#{i+1}") }
8
+ end
9
+
10
+ def print_dbs_names(db)
11
+ db.collection_names.select{ |n| n =~ /\.dbs/ }.sort.each { |name|
12
+ puts name.sub(/^#{db.name}\./, '')
13
+ }
14
+ end
15
+
16
+ db.collection('dbs_1').insert('foo' => 'bar')
17
+ db.collection('dbs_2').insert('psi' => 'phi')
18
+ puts db.name
19
+ print_dbs_names(db)
20
+ db.drop_collection('dbs_1')
21
+ db.create_collection('dbs_3')
22
+ print_dbs_names(db)
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+
6
+ if $DEBUG
7
+ db.drop_collection('test')
8
+ end
9
+
10
+ db.collection('test').insert('a' => 2)
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+
6
+ if $DEBUG
7
+ db.drop_collection('c')
8
+ c = db.collection('c')
9
+ (5..15).each { |i| c.insert(:x => 0, :y => i, :z => (i+64).chr) }
10
+ (1..50).each { |i| c.insert(:x => 1, :y => i, :z => (i+64).chr) }
11
+ (5..15).each { |i| c.insert(:x => 2, :y => i, :z => (i+64).chr) }
12
+ end
13
+
14
+ cursor = db.collection('c').find({'x' => 1}, :sort => 'y', :offset => 20, :limit => 10)
15
+ cursor.each { |row| puts row['z'] }
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+
5
+ require 'mongo/gridfs'
6
+ include XGen::Mongo::GridFS
7
+
8
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
9
+
10
+ input_file = ARGV[0]
11
+
12
+ File.open(input_file, "r") { |f|
13
+ GridStore.open(db, input_file, "w") { |g|
14
+ g.write(f.read)
15
+ }
16
+ }
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+
5
+ require 'mongo/gridfs'
6
+ include XGen::Mongo::GridFS
7
+
8
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
9
+
10
+ input_file = ARGV[0]
11
+ output_file = ARGV[1]
12
+
13
+ File.open(output_file, "w") { |f|
14
+ GridStore.open(db, input_file, "r") { |g|
15
+ f.write(g.read)
16
+ }
17
+ }
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+
5
+ include XGen::Mongo
6
+
7
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
8
+ x = db.collection('x')
9
+ y = db.collection('y')
10
+
11
+ def sorted_index_info(c)
12
+ c.index_information.sort { |a,b| a[:name] <=> b[:name] }
13
+ end
14
+
15
+ def sorted_info_keys(info)
16
+ info[:keys].keys.sort.collect { |key| "#{key}_1" }.join("_")
17
+ end
18
+
19
+ def check_keys(c, expected)
20
+ keys = sorted_index_info(c).collect {|info| sorted_info_keys(info)}
21
+ if keys == expected
22
+ ''
23
+ else
24
+ "#{c.name} indices should start out #{expected.inspect} but is #{keys.inspect}"
25
+ end
26
+ end
27
+
28
+ if $DEBUG
29
+ x.drop # also drops indexes
30
+ x.insert('field1' => 'f1', 'field2' => 'f2')
31
+ x.create_index('field1_1', 'field1')
32
+ x.create_index('field2_1', 'field2')
33
+ y.drop
34
+ end
35
+
36
+ # There should only be two indices on x, and none on y. We raise an error if
37
+ # the preconditions are not met. (They were not, on our testing harness, for a
38
+ # while due to Mongo behavior.)
39
+ err = []
40
+ err << check_keys(x, ['field1_1', 'field2_1'])
41
+ err << check_keys(y, [])
42
+ raise "\n#{err.join("\n")}" unless err == ['', '']
43
+
44
+ x.drop_index('field1_1')
45
+ sorted_index_info(x).each { |info| puts sorted_info_keys(info) }
46
+
47
+ y.create_index([['a', ASCENDING], ['b', ASCENDING], ['c', ASCENDING]])
48
+ y.create_index('d')
49
+ sorted_index_info(y).each { |info| puts sorted_info_keys(info) }
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+
6
+ if $DEBUG
7
+ c = db.collection('remove1')
8
+ c.clear
9
+ 50.times { |i| c.insert(:a => i) }
10
+ c = db.collection('remove2')
11
+ c.clear
12
+ c.insert(:a => 3, :b => 1)
13
+ c.insert(:a => 3, :b => 3)
14
+ c.insert(:a => 2, :b => 3)
15
+ c.insert(:b => 3)
16
+ end
17
+
18
+ db.collection('remove1').clear
19
+ db.collection('remove2').remove('a' => 3)
20
+
21
+ if $DEBUG
22
+ puts "remove1 count = #{db.collection('remove1').count}"
23
+ puts "remove2 count = #{db.collection('remove2').count}"
24
+ db.collection('remove2').find.each { |row| puts row.inspect }
25
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ LONG_STRING = "lksjhasoh1298alshasoidiohaskjasiouashoasasiugoas" * 6
4
+
5
+ require File.join(File.dirname(__FILE__), '_common.rb')
6
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
7
+ c = db.collection('stress1')
8
+
9
+ n1 = 50_000
10
+ n2 = 10_000
11
+
12
+ if $DEBUG
13
+ n1 = 5
14
+ n2 = 1
15
+ c.drop
16
+ end
17
+
18
+ n1.times { |i|
19
+ c.insert(:name => "asdf#{i}", :date => Time.now, :id => i,
20
+ :blah => LONG_STRING, :subarray => [])
21
+ }
22
+ puts
23
+
24
+ n2.times { |i|
25
+ x = c.find_first({:id => i})
26
+ x['subarray'] = "foo#{i}"
27
+ p x
28
+ c.modify({:id => i}, x)
29
+ }
30
+ puts
31
+
32
+ if $DEBUG
33
+ puts "stress1 has #{c.count} records"
34
+ c.find.each { |row| puts "#{row['id']}: #{row['subarray'].inspect}" }
35
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+ coll = db.collection('part1')
6
+
7
+ if $DEBUG
8
+ coll.drop
9
+ end
10
+
11
+ 100.times { |i| coll.insert('x' => i) }
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '_common.rb')
4
+ db = Mongo.new(DEFAULT_HOST, DEFAULT_PORT).db(DEFAULT_DB)
5
+ foo = db.collection('foo')
6
+
7
+ if $DEBUG
8
+ foo.drop
9
+ foo.insert(:x => 1)
10
+ end
11
+
12
+ foo.modify({:x => 1}, {:x => 1, :y => 2})
13
+ foo.modify({:x => 2}, {:x => 1, :y => 7})
14
+ foo.repsert({:x => 3}, {:x => 4, :y => 1})
15
+
16
+ if $DEBUG
17
+ foo.find.each { |row| puts row.inspect }
18
+ end
@@ -0,0 +1,69 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'mongo'
3
+ require 'test/unit'
4
+
5
+ # NOTE: assumes Mongo is running
6
+ class AdminTest < Test::Unit::TestCase
7
+
8
+ include XGen::Mongo::Driver
9
+
10
+ @@db = Mongo.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
11
+ ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT).db('ruby-mongo-test')
12
+ @@coll = @@db.collection('test')
13
+
14
+ def setup
15
+ # Insert some data to make sure the database itself exists.
16
+ @@coll.clear
17
+ @r1 = @@coll.insert('a' => 1) # collection not created until it's used
18
+ @@coll_full_name = 'ruby-mongo-test.test'
19
+ @admin = @@db.admin
20
+ end
21
+
22
+ def teardown
23
+ @admin.profiling_level = :off
24
+ @@coll.clear if @@coll
25
+ @@db.error
26
+ end
27
+
28
+ def test_default_profiling_level
29
+ assert_equal :off, @admin.profiling_level
30
+ end
31
+
32
+ def test_change_profiling_level
33
+ @admin.profiling_level = :slow_only
34
+ assert_equal :slow_only, @admin.profiling_level
35
+ @admin.profiling_level = :off
36
+ assert_equal :off, @admin.profiling_level
37
+ @admin.profiling_level = :all
38
+ assert_equal :all, @admin.profiling_level
39
+ begin
40
+ @admin.profiling_level = :medium
41
+ fail "shouldn't be able to do this"
42
+ rescue
43
+ end
44
+ end
45
+
46
+ def test_profiling_info
47
+ # Perform at least one query while profiling so we have something to see.
48
+ @admin.profiling_level = :all
49
+ @@coll.find()
50
+ @admin.profiling_level = :off
51
+
52
+ info = @admin.profiling_info
53
+ assert_kind_of Array, info
54
+ assert info.length >= 1
55
+ first = info.first
56
+ assert_kind_of String, first['info']
57
+ assert_kind_of Time, first['ts']
58
+ assert_kind_of Numeric, first['millis']
59
+ end
60
+
61
+ def test_validate_collection
62
+ doc = @admin.validate_collection(@@coll.name)
63
+ assert_not_nil doc
64
+ result = doc['result']
65
+ assert_not_nil result
66
+ assert_match /firstExtent/, result
67
+ end
68
+
69
+ end
@@ -0,0 +1,246 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'mongo'
3
+ require 'mongo/util/ordered_hash'
4
+ require 'test/unit'
5
+
6
+ class BSONTest < Test::Unit::TestCase
7
+
8
+ include XGen::Mongo::Driver
9
+
10
+ def setup
11
+ # We don't pass a DB to the constructor, even though we are about to test
12
+ # deserialization. This means that when we deserialize, any DBRefs will
13
+ # have nil @db ivars. That's fine for now.
14
+ @b = BSON.new
15
+ end
16
+
17
+ def test_string
18
+ doc = {'doc' => 'hello, world'}
19
+ @b.serialize(doc)
20
+ assert_equal doc, @b.deserialize
21
+ end
22
+
23
+ def test_code
24
+ doc = {'$where' => Code.new('this.a.b < this.b')}
25
+ @b.serialize(doc)
26
+ assert_equal doc, @b.deserialize
27
+ end
28
+
29
+ def test_number
30
+ doc = {'doc' => 41.99}
31
+ @b.serialize(doc)
32
+ assert_equal doc, @b.deserialize
33
+ end
34
+
35
+ def test_int
36
+ doc = {'doc' => 42}
37
+ @b.serialize(doc)
38
+ assert_equal doc, @b.deserialize
39
+
40
+ doc = {"doc" => -5600}
41
+ @b.serialize(doc)
42
+ assert_equal doc, @b.deserialize
43
+
44
+ doc = {"doc" => 2147483647}
45
+ @b.serialize(doc)
46
+ assert_equal doc, @b.deserialize
47
+
48
+ doc = {"doc" => -2147483648}
49
+ @b.serialize(doc)
50
+ assert_equal doc, @b.deserialize
51
+ end
52
+
53
+ def test_ordered_hash
54
+ doc = OrderedHash.new
55
+ doc["b"] = 1
56
+ doc["a"] = 2
57
+ doc["c"] = 3
58
+ doc["d"] = 4
59
+ @b.serialize(doc)
60
+ assert_equal doc, @b.deserialize
61
+ end
62
+
63
+ def test_object
64
+ doc = {'doc' => {'age' => 42, 'name' => 'Spongebob', 'shoe_size' => 9.5}}
65
+ @b.serialize(doc)
66
+ assert_equal doc, @b.deserialize
67
+ end
68
+
69
+ def test_oid
70
+ doc = {'doc' => ObjectID.new}
71
+ @b.serialize(doc)
72
+ assert_equal doc, @b.deserialize
73
+ end
74
+
75
+ def test_array
76
+ doc = {'doc' => [1, 2, 'a', 'b']}
77
+ @b.serialize(doc)
78
+ assert_equal doc, @b.deserialize
79
+ end
80
+
81
+ def test_regex
82
+ doc = {'doc' => /foobar/i}
83
+ @b.serialize(doc)
84
+ doc2 = @b.deserialize
85
+ assert_equal doc, doc2
86
+
87
+ r = doc2['doc']
88
+ assert_kind_of XGen::Mongo::Driver::RegexpOfHolding, r
89
+ assert_equal '', r.extra_options_str
90
+
91
+ r.extra_options_str << 'zywcab'
92
+ assert_equal 'zywcab', r.extra_options_str
93
+
94
+ b = BSON.new
95
+ doc = {'doc' => r}
96
+ b.serialize(doc)
97
+ doc2 = nil
98
+ doc2 = b.deserialize
99
+ assert_equal doc, doc2
100
+
101
+ r = doc2['doc']
102
+ assert_kind_of XGen::Mongo::Driver::RegexpOfHolding, r
103
+ assert_equal 'abcwyz', r.extra_options_str # must be sorted
104
+ end
105
+
106
+ def test_boolean
107
+ doc = {'doc' => true}
108
+ @b.serialize(doc)
109
+ assert_equal doc, @b.deserialize
110
+ end
111
+
112
+ def test_date
113
+ doc = {'date' => Time.now}
114
+ @b.serialize(doc)
115
+ doc2 = @b.deserialize
116
+ # Mongo only stores up to the millisecond
117
+ assert_in_delta doc['date'], doc2['date'], 0.001
118
+ end
119
+
120
+ def test_date_returns_as_utc
121
+ doc = {'date' => Time.now}
122
+ @b.serialize(doc)
123
+ doc2 = @b.deserialize
124
+ assert doc2['date'].utc?
125
+ end
126
+
127
+ def test_dbref
128
+ oid = ObjectID.new
129
+ doc = {}
130
+ doc['dbref'] = DBRef.new('namespace', oid)
131
+ @b.serialize(doc)
132
+ doc2 = @b.deserialize
133
+ assert_equal 'namespace', doc2['dbref'].namespace
134
+ assert_equal oid, doc2['dbref'].object_id
135
+ end
136
+
137
+ def test_symbol
138
+ doc = {'sym' => :foo}
139
+ @b.serialize(doc)
140
+ doc2 = @b.deserialize
141
+ assert_equal :foo, doc2['sym']
142
+ end
143
+
144
+ def test_binary
145
+ bin = Binary.new
146
+ 'binstring'.each_byte { |b| bin.put(b) }
147
+
148
+ doc = {'bin' => bin}
149
+ @b.serialize(doc)
150
+ doc2 = @b.deserialize
151
+ bin2 = doc2['bin']
152
+ assert_kind_of Binary, bin2
153
+ assert_equal 'binstring', bin2.to_s
154
+ assert_equal Binary::SUBTYPE_BYTES, bin2.subtype
155
+ end
156
+
157
+ def test_binary_type
158
+ bin = Binary.new([1, 2, 3, 4, 5], Binary::SUBTYPE_USER_DEFINED)
159
+
160
+ doc = {'bin' => bin}
161
+ @b.serialize(doc)
162
+ doc2 = @b.deserialize
163
+ bin2 = doc2['bin']
164
+ assert_kind_of Binary, bin2
165
+ assert_equal [1, 2, 3, 4, 5], bin2.to_a
166
+ assert_equal Binary::SUBTYPE_USER_DEFINED, bin2.subtype
167
+ end
168
+
169
+ def test_binary_byte_buffer
170
+ bb = ByteBuffer.new
171
+ 5.times { |i| bb.put(i + 1) }
172
+
173
+ doc = {'bin' => bb}
174
+ @b.serialize(doc)
175
+ doc2 = @b.deserialize
176
+ bin2 = doc2['bin']
177
+ assert_kind_of Binary, bin2
178
+ assert_equal [1, 2, 3, 4, 5], bin2.to_a
179
+ assert_equal Binary::SUBTYPE_BYTES, bin2.subtype
180
+ end
181
+
182
+ def test_undefined
183
+ doc = {'undef' => Undefined.new}
184
+ @b.serialize(doc)
185
+ doc2 = @b.deserialize
186
+ assert_kind_of Undefined, doc2['undef']
187
+ end
188
+
189
+ def test_put_id_first
190
+ val = OrderedHash.new
191
+ val['not_id'] = 1
192
+ val['_id'] = 2
193
+ roundtrip = @b.deserialize(@b.serialize(val).to_a)
194
+ assert_kind_of OrderedHash, roundtrip
195
+ assert_equal '_id', roundtrip.keys.first
196
+
197
+ val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'}
198
+ roundtrip = @b.deserialize(@b.serialize(val).to_a)
199
+ assert_kind_of OrderedHash, roundtrip
200
+ assert_equal '_id', roundtrip.keys.first
201
+ end
202
+
203
+ def test_nil_id
204
+ doc = {"_id" => nil}
205
+ assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
206
+ end
207
+
208
+ def test_timestamp
209
+ val = {"test" => [4, 20]}
210
+ assert_equal val, @b.deserialize([0x13, 0x00, 0x00, 0x00,
211
+ 0x11, 0x74, 0x65, 0x73,
212
+ 0x74, 0x00, 0x04, 0x00,
213
+ 0x00, 0x00, 0x14, 0x00,
214
+ 0x00, 0x00, 0x00])
215
+ end
216
+
217
+ def test_overflow
218
+ doc = {"x" => 2**45}
219
+ assert_raise RangeError do
220
+ @b.serialize(doc)
221
+ end
222
+
223
+ doc = {"x" => 2147483647}
224
+ assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
225
+
226
+ doc["x"] = doc["x"] + 1
227
+ assert_raise RangeError do
228
+ @b.serialize(doc)
229
+ end
230
+ end
231
+
232
+ def test_do_not_change_original_object
233
+ val = OrderedHash.new
234
+ val['not_id'] = 1
235
+ val['_id'] = 2
236
+ assert val.keys.include?('_id')
237
+ @b.serialize(val)
238
+ assert val.keys.include?('_id')
239
+
240
+ val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'}
241
+ assert val.keys.include?(:_id)
242
+ @b.serialize(val)
243
+ assert val.keys.include?(:_id)
244
+ end
245
+
246
+ end