pahagon-mongo-abd 0.14.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +353 -0
- data/Rakefile +62 -0
- data/bin/bson_benchmark.rb +59 -0
- data/bin/mongo_console +21 -0
- data/bin/run_test_script +19 -0
- data/bin/standard_benchmark +109 -0
- data/examples/admin.rb +41 -0
- data/examples/benchmarks.rb +42 -0
- data/examples/blog.rb +76 -0
- data/examples/capped.rb +23 -0
- data/examples/cursor.rb +47 -0
- data/examples/gridfs.rb +87 -0
- data/examples/index_test.rb +125 -0
- data/examples/info.rb +30 -0
- data/examples/queries.rb +69 -0
- data/examples/simple.rb +23 -0
- data/examples/strict.rb +34 -0
- data/examples/types.rb +35 -0
- data/lib/mongo.rb +19 -0
- data/lib/mongo/admin.rb +83 -0
- data/lib/mongo/collection.rb +415 -0
- data/lib/mongo/connection.rb +151 -0
- data/lib/mongo/cursor.rb +279 -0
- data/lib/mongo/db.rb +560 -0
- data/lib/mongo/errors.rb +26 -0
- data/lib/mongo/gridfs.rb +16 -0
- data/lib/mongo/gridfs/chunk.rb +92 -0
- data/lib/mongo/gridfs/grid_store.rb +464 -0
- data/lib/mongo/message.rb +20 -0
- data/lib/mongo/message/get_more_message.rb +32 -0
- data/lib/mongo/message/insert_message.rb +37 -0
- data/lib/mongo/message/kill_cursors_message.rb +31 -0
- data/lib/mongo/message/message.rb +80 -0
- data/lib/mongo/message/message_header.rb +45 -0
- data/lib/mongo/message/msg_message.rb +29 -0
- data/lib/mongo/message/opcodes.rb +27 -0
- data/lib/mongo/message/query_message.rb +78 -0
- data/lib/mongo/message/remove_message.rb +37 -0
- data/lib/mongo/message/update_message.rb +38 -0
- data/lib/mongo/query.rb +118 -0
- data/lib/mongo/types/binary.rb +38 -0
- data/lib/mongo/types/code.rb +30 -0
- data/lib/mongo/types/dbref.rb +33 -0
- data/lib/mongo/types/objectid.rb +143 -0
- data/lib/mongo/types/regexp_of_holding.rb +40 -0
- data/lib/mongo/util/bson.rb +546 -0
- data/lib/mongo/util/byte_buffer.rb +167 -0
- data/lib/mongo/util/ordered_hash.rb +113 -0
- data/lib/mongo/util/xml_to_ruby.rb +105 -0
- data/mongo-ruby-driver.gemspec +103 -0
- data/test/mongo-qa/_common.rb +8 -0
- data/test/mongo-qa/admin +26 -0
- data/test/mongo-qa/capped +22 -0
- data/test/mongo-qa/count1 +18 -0
- data/test/mongo-qa/dbs +22 -0
- data/test/mongo-qa/find +10 -0
- data/test/mongo-qa/find1 +15 -0
- data/test/mongo-qa/gridfs_in +16 -0
- data/test/mongo-qa/gridfs_out +17 -0
- data/test/mongo-qa/indices +49 -0
- data/test/mongo-qa/remove +25 -0
- data/test/mongo-qa/stress1 +35 -0
- data/test/mongo-qa/test1 +11 -0
- data/test/mongo-qa/update +18 -0
- data/test/test_admin.rb +69 -0
- data/test/test_bson.rb +268 -0
- data/test/test_byte_buffer.rb +69 -0
- data/test/test_chunk.rb +84 -0
- data/test/test_collection.rb +249 -0
- data/test/test_connection.rb +101 -0
- data/test/test_cursor.rb +331 -0
- data/test/test_db.rb +185 -0
- data/test/test_db_api.rb +798 -0
- data/test/test_db_connection.rb +18 -0
- data/test/test_grid_store.rb +284 -0
- data/test/test_message.rb +35 -0
- data/test/test_objectid.rb +105 -0
- data/test/test_ordered_hash.rb +138 -0
- data/test/test_round_trip.rb +120 -0
- data/test/test_threading.rb +37 -0
- metadata +135 -0
data/test/mongo-qa/admin
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '_common.rb')
|
4
|
+
db = Connection.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 = Connection.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 = Connection.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').find('i' => 'a').count
|
17
|
+
puts db.collection('test3').find('i' => 3).count
|
18
|
+
puts db.collection('test3').find({'i' => {'$gte' => 67}}).count
|
data/test/mongo-qa/dbs
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '_common.rb')
|
4
|
+
db = Connection.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)
|
data/test/mongo-qa/find
ADDED
data/test/mongo-qa/find1
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '_common.rb')
|
4
|
+
db = Connection.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', :skip => 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 GridFS
|
7
|
+
|
8
|
+
db = Connection.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 GridFS
|
7
|
+
|
8
|
+
db = Connection.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 Mongo
|
6
|
+
|
7
|
+
db = Connection.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 = Connection.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 = Connection.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_one({: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
|
data/test/mongo-qa/test1
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '_common.rb')
|
4
|
+
db = Connection.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
|
data/test/test_admin.rb
ADDED
@@ -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 Mongo
|
9
|
+
|
10
|
+
@@db = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
|
11
|
+
ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::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
|
data/test/test_bson.rb
ADDED
@@ -0,0 +1,268 @@
|
|
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 Mongo
|
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 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 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_date_before_epoch
|
128
|
+
begin
|
129
|
+
doc = {'date' => Time.utc(1600)}
|
130
|
+
@b.serialize(doc)
|
131
|
+
doc2 = @b.deserialize
|
132
|
+
# Mongo only stores up to the millisecond
|
133
|
+
assert_in_delta doc['date'], doc2['date'], 0.001
|
134
|
+
rescue ArgumentError
|
135
|
+
# some versions of Ruby won't let you create pre-epoch Time instances
|
136
|
+
#
|
137
|
+
# TODO figure out how that will work if somebady has saved data
|
138
|
+
# w/ early dates already and is just querying for it.
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_dbref
|
143
|
+
oid = ObjectID.new
|
144
|
+
doc = {}
|
145
|
+
doc['dbref'] = DBRef.new('namespace', oid)
|
146
|
+
@b.serialize(doc)
|
147
|
+
doc2 = @b.deserialize
|
148
|
+
assert_equal 'namespace', doc2['dbref'].namespace
|
149
|
+
assert_equal oid, doc2['dbref'].object_id
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_symbol
|
153
|
+
doc = {'sym' => :foo}
|
154
|
+
@b.serialize(doc)
|
155
|
+
doc2 = @b.deserialize
|
156
|
+
assert_equal :foo, doc2['sym']
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_binary
|
160
|
+
bin = Binary.new
|
161
|
+
'binstring'.each_byte { |b| bin.put(b) }
|
162
|
+
|
163
|
+
doc = {'bin' => bin}
|
164
|
+
@b.serialize(doc)
|
165
|
+
doc2 = @b.deserialize
|
166
|
+
bin2 = doc2['bin']
|
167
|
+
assert_kind_of Binary, bin2
|
168
|
+
assert_equal 'binstring', bin2.to_s
|
169
|
+
assert_equal Binary::SUBTYPE_BYTES, bin2.subtype
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_binary_type
|
173
|
+
bin = Binary.new([1, 2, 3, 4, 5], Binary::SUBTYPE_USER_DEFINED)
|
174
|
+
|
175
|
+
doc = {'bin' => bin}
|
176
|
+
@b.serialize(doc)
|
177
|
+
doc2 = @b.deserialize
|
178
|
+
bin2 = doc2['bin']
|
179
|
+
assert_kind_of Binary, bin2
|
180
|
+
assert_equal [1, 2, 3, 4, 5], bin2.to_a
|
181
|
+
assert_equal Binary::SUBTYPE_USER_DEFINED, bin2.subtype
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_binary_byte_buffer
|
185
|
+
bb = ByteBuffer.new
|
186
|
+
5.times { |i| bb.put(i + 1) }
|
187
|
+
|
188
|
+
doc = {'bin' => bb}
|
189
|
+
@b.serialize(doc)
|
190
|
+
doc2 = @b.deserialize
|
191
|
+
bin2 = doc2['bin']
|
192
|
+
assert_kind_of Binary, bin2
|
193
|
+
assert_equal [1, 2, 3, 4, 5], bin2.to_a
|
194
|
+
assert_equal Binary::SUBTYPE_BYTES, bin2.subtype
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_put_id_first
|
198
|
+
val = OrderedHash.new
|
199
|
+
val['not_id'] = 1
|
200
|
+
val['_id'] = 2
|
201
|
+
roundtrip = @b.deserialize(@b.serialize(val).to_a)
|
202
|
+
assert_kind_of OrderedHash, roundtrip
|
203
|
+
assert_equal '_id', roundtrip.keys.first
|
204
|
+
|
205
|
+
val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'}
|
206
|
+
roundtrip = @b.deserialize(@b.serialize(val).to_a)
|
207
|
+
assert_kind_of OrderedHash, roundtrip
|
208
|
+
assert_equal '_id', roundtrip.keys.first
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_nil_id
|
212
|
+
doc = {"_id" => nil}
|
213
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_timestamp
|
217
|
+
val = {"test" => [4, 20]}
|
218
|
+
assert_equal val, @b.deserialize([0x13, 0x00, 0x00, 0x00,
|
219
|
+
0x11, 0x74, 0x65, 0x73,
|
220
|
+
0x74, 0x00, 0x04, 0x00,
|
221
|
+
0x00, 0x00, 0x14, 0x00,
|
222
|
+
0x00, 0x00, 0x00])
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_overflow
|
226
|
+
doc = {"x" => 2**75}
|
227
|
+
assert_raise RangeError do
|
228
|
+
@b.serialize(doc)
|
229
|
+
end
|
230
|
+
|
231
|
+
doc = {"x" => 9223372036854775}
|
232
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
233
|
+
|
234
|
+
doc = {"x" => 9223372036854775807}
|
235
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
236
|
+
|
237
|
+
doc["x"] = doc["x"] + 1
|
238
|
+
assert_raise RangeError do
|
239
|
+
@b.serialize(doc)
|
240
|
+
end
|
241
|
+
|
242
|
+
doc = {"x" => -9223372036854775}
|
243
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
244
|
+
|
245
|
+
doc = {"x" => -9223372036854775808}
|
246
|
+
assert_equal doc, @b.deserialize(@b.serialize(doc).to_a)
|
247
|
+
|
248
|
+
doc["x"] = doc["x"] - 1
|
249
|
+
assert_raise RangeError do
|
250
|
+
@b.serialize(doc)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_do_not_change_original_object
|
255
|
+
val = OrderedHash.new
|
256
|
+
val['not_id'] = 1
|
257
|
+
val['_id'] = 2
|
258
|
+
assert val.keys.include?('_id')
|
259
|
+
@b.serialize(val)
|
260
|
+
assert val.keys.include?('_id')
|
261
|
+
|
262
|
+
val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'}
|
263
|
+
assert val.keys.include?(:_id)
|
264
|
+
@b.serialize(val)
|
265
|
+
assert val.keys.include?(:_id)
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|