mongo 0.1.0 → 0.15
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.
- data/README.rdoc +268 -71
- data/Rakefile +27 -62
- data/bin/bson_benchmark.rb +59 -0
- data/bin/mongo_console +3 -3
- 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 +9 -2
- data/lib/mongo/admin.rb +65 -68
- data/lib/mongo/collection.rb +379 -117
- data/lib/mongo/connection.rb +151 -0
- data/lib/mongo/cursor.rb +271 -216
- data/lib/mongo/db.rb +500 -315
- 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 +16 -0
- data/lib/mongo/message/get_more_message.rb +24 -13
- data/lib/mongo/message/insert_message.rb +29 -11
- data/lib/mongo/message/kill_cursors_message.rb +23 -12
- data/lib/mongo/message/message.rb +74 -62
- data/lib/mongo/message/message_header.rb +35 -24
- data/lib/mongo/message/msg_message.rb +21 -9
- data/lib/mongo/message/opcodes.rb +26 -15
- data/lib/mongo/message/query_message.rb +63 -43
- data/lib/mongo/message/remove_message.rb +29 -12
- data/lib/mongo/message/update_message.rb +30 -13
- data/lib/mongo/query.rb +97 -89
- data/lib/mongo/types/binary.rb +25 -21
- data/lib/mongo/types/code.rb +30 -0
- data/lib/mongo/types/dbref.rb +19 -23
- data/lib/mongo/types/objectid.rb +130 -116
- data/lib/mongo/types/regexp_of_holding.rb +27 -31
- data/lib/mongo/util/bson.rb +273 -160
- data/lib/mongo/util/byte_buffer.rb +32 -28
- data/lib/mongo/util/ordered_hash.rb +88 -42
- data/lib/mongo/util/xml_to_ruby.rb +18 -15
- 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/{tests → test}/test_admin.rb +25 -16
- data/test/test_bson.rb +268 -0
- data/{tests → test}/test_byte_buffer.rb +0 -0
- data/test/test_chunk.rb +84 -0
- data/test/test_collection.rb +282 -0
- data/test/test_connection.rb +101 -0
- data/test/test_cursor.rb +321 -0
- data/test/test_db.rb +196 -0
- data/test/test_db_api.rb +798 -0
- data/{tests → test}/test_db_connection.rb +4 -3
- data/test/test_grid_store.rb +284 -0
- data/{tests → test}/test_message.rb +1 -1
- data/test/test_objectid.rb +105 -0
- data/{tests → test}/test_ordered_hash.rb +55 -0
- data/{tests → test}/test_round_trip.rb +13 -9
- data/test/test_threading.rb +37 -0
- metadata +74 -32
- data/bin/validate +0 -51
- data/lib/mongo/mongo.rb +0 -74
- data/lib/mongo/types/undefined.rb +0 -31
- data/tests/test_bson.rb +0 -135
- data/tests/test_cursor.rb +0 -66
- data/tests/test_db.rb +0 -51
- data/tests/test_db_api.rb +0 -349
- data/tests/test_objectid.rb +0 -88
@@ -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
|
@@ -5,26 +5,24 @@ require 'test/unit'
|
|
5
5
|
# NOTE: assumes Mongo is running
|
6
6
|
class AdminTest < Test::Unit::TestCase
|
7
7
|
|
8
|
-
include
|
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')
|
9
13
|
|
10
14
|
def setup
|
11
|
-
host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
|
12
|
-
port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT
|
13
|
-
@db = Mongo.new(host, port).db('ruby-mongo-test')
|
14
15
|
# Insert some data to make sure the database itself exists.
|
15
|
-
|
16
|
-
@coll.
|
17
|
-
|
18
|
-
@
|
19
|
-
@admin = @db.admin
|
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
20
|
end
|
21
21
|
|
22
22
|
def teardown
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@db.close
|
27
|
-
end
|
23
|
+
@admin.profiling_level = :off
|
24
|
+
@@coll.clear if @@coll
|
25
|
+
@@db.error
|
28
26
|
end
|
29
27
|
|
30
28
|
def test_default_profiling_level
|
@@ -36,12 +34,19 @@ class AdminTest < Test::Unit::TestCase
|
|
36
34
|
assert_equal :slow_only, @admin.profiling_level
|
37
35
|
@admin.profiling_level = :off
|
38
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
|
39
44
|
end
|
40
45
|
|
41
46
|
def test_profiling_info
|
42
47
|
# Perform at least one query while profiling so we have something to see.
|
43
48
|
@admin.profiling_level = :all
|
44
|
-
|
49
|
+
@@coll.find()
|
45
50
|
@admin.profiling_level = :off
|
46
51
|
|
47
52
|
info = @admin.profiling_info
|
@@ -54,7 +59,11 @@ class AdminTest < Test::Unit::TestCase
|
|
54
59
|
end
|
55
60
|
|
56
61
|
def test_validate_collection
|
57
|
-
|
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
|
58
67
|
end
|
59
68
|
|
60
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
|