animehunter-mongo 0.9

Sign up to get free protection for your applications and to get access to all the features.
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,69 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'mongo'
3
+ require 'test/unit'
4
+
5
+ class ByteBufferTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @buf = ByteBuffer.new
9
+ end
10
+
11
+ def test_nil_get_returns_one_byte
12
+ @buf.put_array([1, 2, 3, 4])
13
+ @buf.rewind
14
+ assert_equal 1, @buf.get
15
+ end
16
+
17
+ def test_one_get_returns_array_length_one
18
+ @buf.put_array([1, 2, 3, 4])
19
+ @buf.rewind
20
+ assert_equal [1], @buf.get(1)
21
+ end
22
+
23
+ def test_zero_get_returns_empty_array
24
+ @buf.put_array([1, 2, 3, 4])
25
+ @buf.rewind
26
+ assert_equal [], @buf.get(0)
27
+ end
28
+
29
+ def test_empty
30
+ assert_equal 0, @buf.length
31
+ end
32
+
33
+ def test_length
34
+ @buf.put_int 3
35
+ assert_equal 4, @buf.length
36
+ end
37
+
38
+ def test_default_order
39
+ assert_equal :little_endian, @buf.order
40
+ end
41
+
42
+ def test_long_length
43
+ @buf.put_long 1027
44
+ assert_equal 8, @buf.length
45
+ end
46
+
47
+ def test_get_long
48
+ @buf.put_long 1027
49
+ @buf.rewind
50
+ assert_equal 1027, @buf.get_long
51
+ end
52
+
53
+ def test_get_double
54
+ @buf.put_double 41.2
55
+ @buf.rewind
56
+ assert_equal 41.2, @buf.get_double
57
+ end
58
+
59
+ def test_rewrite
60
+ @buf.put_int(0)
61
+ @buf.rewind
62
+ @buf.put_int(1027)
63
+ assert_equal 4, @buf.length
64
+ @buf.rewind
65
+ assert_equal 1027, @buf.get_int
66
+ assert_equal 4, @buf.position
67
+ end
68
+
69
+ end
@@ -0,0 +1,84 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'test/unit'
3
+ require 'mongo'
4
+ require 'mongo/gridfs'
5
+
6
+ class ChunkTest < Test::Unit::TestCase
7
+
8
+ include XGen::Mongo::Driver
9
+ include XGen::Mongo::GridFS
10
+
11
+ @@db = Mongo.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
12
+ ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT).db('ruby-mongo-utils-test')
13
+ @@files = @@db.collection('gridfs.files')
14
+ @@chunks = @@db.collection('gridfs.chunks')
15
+
16
+ def setup
17
+ @@chunks.clear
18
+ @@files.clear
19
+
20
+ @f = GridStore.new(@@db, 'foobar', 'w')
21
+ @c = @f.instance_variable_get('@curr_chunk')
22
+ end
23
+
24
+ def teardown
25
+ @@chunks.clear
26
+ @@files.clear
27
+ @@db.error
28
+ end
29
+
30
+ def test_pos
31
+ assert_equal 0, @c.pos
32
+ assert @c.eof? # since data is empty
33
+
34
+ b = ByteBuffer.new
35
+ 3.times { |i| b.put(i) }
36
+ c = Chunk.new(@f, 'data' => b)
37
+ assert !c.eof?
38
+ end
39
+
40
+ def test_getc
41
+ b = ByteBuffer.new
42
+ 3.times { |i| b.put(i) }
43
+ c = Chunk.new(@f, 'data' => b)
44
+
45
+ assert !c.eof?
46
+ assert_equal 0, c.getc
47
+ assert !c.eof?
48
+ assert_equal 1, c.getc
49
+ assert !c.eof?
50
+ assert_equal 2, c.getc
51
+ assert c.eof?
52
+ end
53
+
54
+ def test_putc
55
+ 3.times { |i| @c.putc(i) }
56
+ @c.pos = 0
57
+
58
+ assert !@c.eof?
59
+ assert_equal 0, @c.getc
60
+ assert !@c.eof?
61
+ assert_equal 1, @c.getc
62
+ assert !@c.eof?
63
+ assert_equal 2, @c.getc
64
+ assert @c.eof?
65
+ end
66
+
67
+ def test_truncate
68
+ 10.times { |i| @c.putc(i) }
69
+ assert_equal 10, @c.size
70
+ @c.pos = 3
71
+ @c.truncate
72
+ assert_equal 3, @c.size
73
+
74
+ @c.pos = 0
75
+ assert !@c.eof?
76
+ assert_equal 0, @c.getc
77
+ assert !@c.eof?
78
+ assert_equal 1, @c.getc
79
+ assert !@c.eof?
80
+ assert_equal 2, @c.getc
81
+ assert @c.eof?
82
+ end
83
+
84
+ end
@@ -0,0 +1,121 @@
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 CursorTest < 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
+ @@coll.clear
16
+ @@coll.insert('a' => 1) # collection not created until it's used
17
+ @@coll_full_name = 'ruby-mongo-test.test'
18
+ end
19
+
20
+ def teardown
21
+ @@coll.clear
22
+ @@db.error
23
+ end
24
+
25
+ def test_explain
26
+ cursor = @@coll.find('a' => 1)
27
+ explaination = cursor.explain
28
+ assert_not_nil explaination['cursor']
29
+ assert_kind_of Numeric, explaination['n']
30
+ assert_kind_of Numeric, explaination['millis']
31
+ assert_kind_of Numeric, explaination['nscanned']
32
+ end
33
+
34
+ def test_close_no_query_sent
35
+ begin
36
+ cursor = @@coll.find('a' => 1)
37
+ cursor.close
38
+ assert cursor.closed?
39
+ rescue => ex
40
+ fail ex.to_s
41
+ end
42
+ end
43
+
44
+ def test_refill_via_get_more
45
+ begin
46
+ assert_equal 1, @@coll.count
47
+ 1000.times { |i|
48
+ assert_equal 1 + i, @@coll.count
49
+ @@coll.insert('a' => i)
50
+ }
51
+
52
+ assert_equal 1001, @@coll.count
53
+ count = 0
54
+ @@coll.find.each { |obj|
55
+ count += obj['a']
56
+ }
57
+ assert_equal 1001, @@coll.count
58
+
59
+ # do the same thing again for debugging
60
+ assert_equal 1001, @@coll.count
61
+ count2 = 0
62
+ @@coll.find.each { |obj|
63
+ count2 += obj['a']
64
+ }
65
+ assert_equal 1001, @@coll.count
66
+
67
+ assert_equal count, count2
68
+ assert_equal 499501, count
69
+ rescue Test::Unit::AssertionFailedError => ex
70
+ p @@db.collection_names
71
+ Process.exit 1
72
+ end
73
+ end
74
+
75
+ def test_refill_via_get_more_alt_coll
76
+ begin
77
+ coll = @@db.collection('test-alt-coll')
78
+ coll.clear
79
+ coll.insert('a' => 1) # collection not created until it's used
80
+ assert_equal 1, coll.count
81
+
82
+ 1000.times { |i|
83
+ assert_equal 1 + i, coll.count
84
+ coll.insert('a' => i)
85
+ }
86
+
87
+ assert_equal 1001, coll.count
88
+ count = 0
89
+ coll.find.each { |obj|
90
+ count += obj['a']
91
+ }
92
+ assert_equal 1001, coll.count
93
+
94
+ # do the same thing again for debugging
95
+ assert_equal 1001, coll.count
96
+ count2 = 0
97
+ coll.find.each { |obj|
98
+ count2 += obj['a']
99
+ }
100
+ assert_equal 1001, coll.count
101
+
102
+ assert_equal count, count2
103
+ assert_equal 499501, count
104
+ rescue Test::Unit::AssertionFailedError => ex
105
+ p @@db.collection_names
106
+ Process.exit 1
107
+ end
108
+ end
109
+
110
+ def test_close_after_query_sent
111
+ begin
112
+ cursor = @@coll.find('a' => 1)
113
+ cursor.next_object
114
+ cursor.close
115
+ assert cursor.closed?
116
+ rescue => ex
117
+ fail ex.to_s
118
+ end
119
+ end
120
+
121
+ end
@@ -0,0 +1,160 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'digest/md5'
3
+ require 'mongo'
4
+ require 'test/unit'
5
+
6
+ class TestPKFactory
7
+ def create_pk(row)
8
+ row['_id'] ||= XGen::Mongo::Driver::ObjectID.new
9
+ row
10
+ end
11
+ end
12
+
13
+ # NOTE: assumes Mongo is running
14
+ class DBTest < Test::Unit::TestCase
15
+
16
+ include XGen::Mongo::Driver
17
+
18
+ @@host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
19
+ @@port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT
20
+ @@db = Mongo.new(@@host, @@port).db('ruby-mongo-test')
21
+ @@users = @@db.collection('system.users')
22
+
23
+ def setup
24
+ @spongebob = 'spongebob'
25
+ @spongebob_password = 'squarepants'
26
+ @@users.clear
27
+ @@users.insert(:user => @spongebob, :pwd => @@db.send(:hash_password, @spongebob, @spongebob_password))
28
+ end
29
+
30
+ def teardown
31
+ @@users.clear if @@users
32
+ @@db.error
33
+ end
34
+
35
+ def test_close
36
+ @@db.close
37
+ assert !@@db.connected?
38
+ begin
39
+ @@db.collection('test').insert('a' => 1)
40
+ fail "expected 'NilClass' exception"
41
+ rescue => ex
42
+ assert_match /NilClass/, ex.to_s
43
+ ensure
44
+ @@db = Mongo.new(@@host, @@port).db('ruby-mongo-test')
45
+ @@users = @@db.collection('system.users')
46
+ end
47
+ end
48
+
49
+ def test_full_coll_name
50
+ coll = @@db.collection('test')
51
+ assert_equal 'ruby-mongo-test.test', @@db.full_coll_name(coll.name)
52
+ end
53
+
54
+ def test_pair
55
+ @@db.close
56
+ @@users = nil
57
+ @@db = Mongo.new({:left => "this-should-fail", :right => [@@host, @@port]}).db('ruby-mongo-test')
58
+ assert @@db.connected?
59
+ ensure
60
+ @@db = Mongo.new(@@host, @@port).db('ruby-mongo-test') unless @@db.connected?
61
+ @@users = @@db.collection('system.users')
62
+ end
63
+
64
+ def test_pk_factory
65
+ db = Mongo.new(@@host, @@port).db('ruby-mongo-test', :pk => TestPKFactory.new)
66
+ coll = db.collection('test')
67
+ coll.clear
68
+
69
+ # new id gets added to returned object
70
+ obj = coll.insert('name' => 'Fred', 'age' => 42)
71
+ row = coll.find_first({'name' => 'Fred'}, :limit => 1)
72
+ oid = row['_id']
73
+ assert_not_nil oid
74
+ assert_equal obj, row
75
+
76
+ oid = XGen::Mongo::Driver::ObjectID.new
77
+ obj = coll.insert('_id' => oid, 'name' => 'Barney', 'age' => 41)
78
+ row = coll.find_first({'name' => 'Barney'}, :limit => 1)
79
+ db_oid = row['_id']
80
+ assert_equal oid, db_oid
81
+ assert_equal obj, row
82
+
83
+ coll.clear
84
+ end
85
+
86
+ def test_pk_factory_reset
87
+ db = Mongo.new(@@host, @@port).db('ruby-mongo-test')
88
+ db.pk_factory = Object.new # first time
89
+ begin
90
+ db.pk_factory = Object.new
91
+ fail "error: expected exception"
92
+ rescue => ex
93
+ assert_match /can not change PK factory/, ex.to_s
94
+ ensure
95
+ db.close
96
+ end
97
+ end
98
+
99
+ def test_authenticate
100
+ assert !@@db.authenticate('nobody', 'nopassword')
101
+ assert !@@db.authenticate(@spongebob, 'squareliederhosen')
102
+ assert @@db.authenticate(@spongebob, @spongebob_password)
103
+ end
104
+
105
+ def test_logout
106
+ @@db.logout # only testing that we don't throw exception
107
+ end
108
+
109
+ def test_auto_connect
110
+ @@db.close
111
+ db = Mongo.new(@@host, @@port, :auto_reconnect => true).db('ruby-mongo-test')
112
+ assert db.connected?
113
+ assert db.auto_reconnect?
114
+ db.close
115
+ assert !db.connected?
116
+ assert db.auto_reconnect?
117
+ db.collection('test').insert('a' => 1)
118
+ assert db.connected?
119
+ ensure
120
+ @@db = Mongo.new(@@host, @@port).db('ruby-mongo-test')
121
+ @@users = @@db.collection('system.users')
122
+ end
123
+
124
+ def test_error
125
+ @@db.reset_error_history
126
+ assert_nil @@db.error
127
+ assert !@@db.error?
128
+ assert_nil @@db.previous_error
129
+
130
+ @@db.send(:db_command, :forceerror => 1)
131
+ assert @@db.error?
132
+ assert_not_nil @@db.error
133
+ assert_not_nil @@db.previous_error
134
+
135
+ @@db.send(:db_command, :forceerror => 1)
136
+ assert @@db.error?
137
+ assert @@db.error
138
+ prev_error = @@db.previous_error
139
+ assert_equal 1, prev_error['nPrev']
140
+ assert_equal prev_error["err"], @@db.error
141
+
142
+ @@db.collection('test').find_first
143
+ assert_nil @@db.error
144
+ assert !@@db.error?
145
+ assert @@db.previous_error
146
+ assert_equal 2, @@db.previous_error['nPrev']
147
+
148
+ @@db.reset_error_history
149
+ assert_nil @@db.error
150
+ assert !@@db.error?
151
+ assert_nil @@db.previous_error
152
+ end
153
+
154
+ def test_text_port_number
155
+ db = DB.new('ruby-mongo-test', [[@@host, @@port.to_s]])
156
+ # If there is no error, all is well
157
+ db.collection('users').clear
158
+ end
159
+
160
+ end
@@ -0,0 +1,701 @@
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 DBAPITest < Test::Unit::TestCase
7
+ include XGen::Mongo
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
+ @@coll.clear
16
+ @r1 = @@coll.insert('a' => 1) # collection not created until it's used
17
+ @@coll_full_name = 'ruby-mongo-test.test'
18
+ end
19
+
20
+ def teardown
21
+ @@coll.clear
22
+ @@db.error
23
+ end
24
+
25
+ def test_clear
26
+ assert_equal 1, @@coll.count
27
+ @@coll.clear
28
+ assert_equal 0, @@coll.count
29
+ end
30
+
31
+ def test_insert
32
+ @@coll.insert('a' => 2)
33
+ @@coll.insert('b' => 3)
34
+
35
+ assert_equal 3, @@coll.count
36
+ docs = @@coll.find().to_a
37
+ assert_equal 3, docs.length
38
+ assert docs.detect { |row| row['a'] == 1 }
39
+ assert docs.detect { |row| row['a'] == 2 }
40
+ assert docs.detect { |row| row['b'] == 3 }
41
+
42
+ @@coll << {'b' => 4}
43
+ docs = @@coll.find().to_a
44
+ assert_equal 4, docs.length
45
+ assert docs.detect { |row| row['b'] == 4 }
46
+ end
47
+
48
+ def test_insert_multiple
49
+ @@coll.insert({'a' => 2}, {'b' => 3})
50
+
51
+ assert_equal 3, @@coll.count
52
+ docs = @@coll.find().to_a
53
+ assert_equal 3, docs.length
54
+ assert docs.detect { |row| row['a'] == 1 }
55
+ assert docs.detect { |row| row['a'] == 2 }
56
+ assert docs.detect { |row| row['b'] == 3 }
57
+ end
58
+
59
+ def test_count_on_nonexisting
60
+ @@db.drop_collection('foo')
61
+ assert_equal 0, @@db.collection('foo').count()
62
+ end
63
+
64
+ def test_find_simple
65
+ @r2 = @@coll.insert('a' => 2)
66
+ @r3 = @@coll.insert('b' => 3)
67
+ # Check sizes
68
+ docs = @@coll.find().to_a
69
+ assert_equal 3, docs.size
70
+ assert_equal 3, @@coll.count
71
+
72
+ # Find by other value
73
+ docs = @@coll.find('a' => @r1['a']).to_a
74
+ assert_equal 1, docs.size
75
+ doc = docs.first
76
+ # Can't compare _id values because at insert, an _id was added to @r1 by
77
+ # the database but we don't know what it is without re-reading the record
78
+ # (which is what we are doing right now).
79
+ # assert_equal doc['_id'], @r1['_id']
80
+ assert_equal doc['a'], @r1['a']
81
+ end
82
+
83
+ def test_find_advanced
84
+ @@coll.insert('a' => 2)
85
+ @@coll.insert('b' => 3)
86
+
87
+ # Find by advanced query (less than)
88
+ docs = @@coll.find('a' => { '$lt' => 10 }).to_a
89
+ assert_equal 2, docs.size
90
+ assert docs.detect { |row| row['a'] == 1 }
91
+ assert docs.detect { |row| row['a'] == 2 }
92
+
93
+ # Find by advanced query (greater than)
94
+ docs = @@coll.find('a' => { '$gt' => 1 }).to_a
95
+ assert_equal 1, docs.size
96
+ assert docs.detect { |row| row['a'] == 2 }
97
+
98
+ # Find by advanced query (less than or equal to)
99
+ docs = @@coll.find('a' => { '$lte' => 1 }).to_a
100
+ assert_equal 1, docs.size
101
+ assert docs.detect { |row| row['a'] == 1 }
102
+
103
+ # Find by advanced query (greater than or equal to)
104
+ docs = @@coll.find('a' => { '$gte' => 1 }).to_a
105
+ assert_equal 2, docs.size
106
+ assert docs.detect { |row| row['a'] == 1 }
107
+ assert docs.detect { |row| row['a'] == 2 }
108
+
109
+ # Find by advanced query (between)
110
+ docs = @@coll.find('a' => { '$gt' => 1, '$lt' => 3 }).to_a
111
+ assert_equal 1, docs.size
112
+ assert docs.detect { |row| row['a'] == 2 }
113
+
114
+ # Find by advanced query (in clause)
115
+ docs = @@coll.find('a' => {'$in' => [1,2]}).to_a
116
+ assert_equal 2, docs.size
117
+ assert docs.detect { |row| row['a'] == 1 }
118
+ assert docs.detect { |row| row['a'] == 2 }
119
+
120
+ # Find by advanced query (regexp)
121
+ docs = @@coll.find('a' => /[1|2]/).to_a
122
+ assert_equal 2, docs.size
123
+ assert docs.detect { |row| row['a'] == 1 }
124
+ assert docs.detect { |row| row['a'] == 2 }
125
+ end
126
+
127
+ def test_find_sorting
128
+ @@coll.clear
129
+ @@coll.insert('a' => 1, 'b' => 2)
130
+ @@coll.insert('a' => 2, 'b' => 1)
131
+ @@coll.insert('a' => 3, 'b' => 2)
132
+ @@coll.insert('a' => 4, 'b' => 1)
133
+
134
+ # Sorting (ascending)
135
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => {'a' => 1}).to_a
136
+ assert_equal 4, docs.size
137
+ assert_equal 1, docs[0]['a']
138
+ assert_equal 2, docs[1]['a']
139
+ assert_equal 3, docs[2]['a']
140
+ assert_equal 4, docs[3]['a']
141
+
142
+ # Sorting (descending)
143
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => {'a' => -1}).to_a
144
+ assert_equal 4, docs.size
145
+ assert_equal 4, docs[0]['a']
146
+ assert_equal 3, docs[1]['a']
147
+ assert_equal 2, docs[2]['a']
148
+ assert_equal 1, docs[3]['a']
149
+
150
+ # Sorting using array of names; assumes ascending order.
151
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => ['a']).to_a
152
+ assert_equal 4, docs.size
153
+ assert_equal 1, docs[0]['a']
154
+ assert_equal 2, docs[1]['a']
155
+ assert_equal 3, docs[2]['a']
156
+ assert_equal 4, docs[3]['a']
157
+
158
+ # Sorting using single name; assumes ascending order.
159
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => 'a').to_a
160
+ assert_equal 4, docs.size
161
+ assert_equal 1, docs[0]['a']
162
+ assert_equal 2, docs[1]['a']
163
+ assert_equal 3, docs[2]['a']
164
+ assert_equal 4, docs[3]['a']
165
+
166
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => ['b', 'a']).to_a
167
+ assert_equal 4, docs.size
168
+ assert_equal 2, docs[0]['a']
169
+ assert_equal 4, docs[1]['a']
170
+ assert_equal 1, docs[2]['a']
171
+ assert_equal 3, docs[3]['a']
172
+
173
+ # Sorting using empty array; no order guarantee (Mongo bug #898) but
174
+ # should not blow up.
175
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => []).to_a
176
+ assert_equal 4, docs.size
177
+
178
+ # Sorting using array of hashes; no order guarantee (Mongo bug #898) but
179
+ # should not blow up.
180
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => [{'b' => 1}, {'a' => -1}]).to_a
181
+ assert_equal 4, docs.size
182
+
183
+ # Sorting using ordered hash. You can use an unordered one, but then the
184
+ # order of the keys won't be guaranteed thus your sort won't make sense.
185
+ oh = OrderedHash.new
186
+ oh['a'] = -1
187
+ docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => oh).to_a
188
+ assert_equal 4, docs.size
189
+ assert_equal 4, docs[0]['a']
190
+ assert_equal 3, docs[1]['a']
191
+ assert_equal 2, docs[2]['a']
192
+ assert_equal 1, docs[3]['a']
193
+
194
+ # TODO this will not pass due to known Mongo bug #898
195
+ # oh = OrderedHash.new
196
+ # oh['b'] = -1
197
+ # oh['a'] = 1
198
+ # docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => oh).to_a
199
+ # assert_equal 4, docs.size
200
+ # assert_equal 1, docs[0]['a']
201
+ # assert_equal 3, docs[1]['a']
202
+ # assert_equal 2, docs[2]['a']
203
+ # assert_equal 4, docs[3]['a']
204
+ end
205
+
206
+ def test_find_limits
207
+ @@coll.insert('b' => 2)
208
+ @@coll.insert('c' => 3)
209
+ @@coll.insert('d' => 4)
210
+
211
+ docs = @@coll.find({}, :limit => 1).to_a
212
+ assert_equal 1, docs.size
213
+ docs = @@coll.find({}, :limit => 2).to_a
214
+ assert_equal 2, docs.size
215
+ docs = @@coll.find({}, :limit => 3).to_a
216
+ assert_equal 3, docs.size
217
+ docs = @@coll.find({}, :limit => 4).to_a
218
+ assert_equal 4, docs.size
219
+ docs = @@coll.find({}).to_a
220
+ assert_equal 4, docs.size
221
+ docs = @@coll.find({}, :limit => 99).to_a
222
+ assert_equal 4, docs.size
223
+ end
224
+
225
+ def test_find_first
226
+ x = @@coll.find_first('a' => 1)
227
+ assert_not_nil x
228
+ assert_equal 1, x['a']
229
+ end
230
+
231
+ def test_find_first_no_records
232
+ @@coll.clear
233
+ x = @@coll.find_first('a' => 1)
234
+ assert_nil x
235
+ end
236
+
237
+ def test_drop_collection
238
+ assert @@db.drop_collection(@@coll.name), "drop of collection #{@@coll.name} failed"
239
+ assert !@@db.collection_names.include?(@@coll_full_name)
240
+ end
241
+
242
+ def test_other_drop
243
+ assert @@db.collection_names.include?(@@coll_full_name)
244
+ @@coll.drop
245
+ assert !@@db.collection_names.include?(@@coll_full_name)
246
+ end
247
+
248
+ def test_collection_names
249
+ names = @@db.collection_names
250
+ assert names.length >= 1
251
+ assert names.include?(@@coll_full_name)
252
+
253
+ coll2 = @@db.collection('test2')
254
+ coll2.insert('a' => 1) # collection not created until it's used
255
+ names = @@db.collection_names
256
+ assert names.length >= 2
257
+ assert names.include?(@@coll_full_name)
258
+ assert names.include?('ruby-mongo-test.test2')
259
+ ensure
260
+ @@db.drop_collection('test2')
261
+ end
262
+
263
+ def test_collections_info
264
+ cursor = @@db.collections_info
265
+ rows = cursor.to_a
266
+ assert rows.length >= 1
267
+ row = rows.detect { |r| r['name'] == @@coll_full_name }
268
+ assert_not_nil row
269
+ end
270
+
271
+ def test_collection_options
272
+ @@db.drop_collection('foobar')
273
+ @@db.strict = true
274
+
275
+ begin
276
+ coll = @@db.create_collection('foobar', :capped => true, :size => 1024)
277
+ options = coll.options()
278
+ assert_equal 'foobar', options['create']
279
+ assert_equal true, options['capped']
280
+ assert_equal 1024, options['size']
281
+ rescue => ex
282
+ @@db.drop_collection('foobar')
283
+ fail "did not expect exception \"#{ex}\""
284
+ ensure
285
+ @@db.strict = false
286
+ end
287
+ end
288
+
289
+ def test_index_information
290
+ assert_equal @@coll.index_information.length, 1
291
+
292
+ name = @@db.create_index(@@coll.name, 'a')
293
+ info = @@db.index_information(@@coll.name)
294
+ assert_equal name, "a_1"
295
+ assert_equal @@coll.index_information, info
296
+ assert_equal 2, info.length
297
+
298
+ assert info.has_key?(name)
299
+ assert_equal info[name], [["a", ASCENDING]]
300
+ ensure
301
+ @@db.drop_index(@@coll.name, name)
302
+ end
303
+
304
+ def test_index_create_with_symbol
305
+ assert_equal @@coll.index_information.length, 1
306
+
307
+ name = @@db.create_index(@@coll.name, :a)
308
+ info = @@db.index_information(@@coll.name)
309
+ assert_equal name, "a_1"
310
+ assert_equal @@coll.index_information, info
311
+ assert_equal 2, info.length
312
+
313
+ assert info.has_key?(name)
314
+ assert_equal info[name], [["a", ASCENDING]]
315
+ ensure
316
+ @@db.drop_index(@@coll.name, name)
317
+ end
318
+
319
+ def test_multiple_index_cols
320
+ name = @@db.create_index(@@coll.name, [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]])
321
+ info = @@db.index_information(@@coll.name)
322
+ assert_equal 2, info.length
323
+
324
+ assert_equal name, 'a_-1_b_1_c_-1'
325
+ assert info.has_key?(name)
326
+ assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
327
+ ensure
328
+ @@db.drop_index(@@coll.name, name)
329
+ end
330
+
331
+ def test_multiple_index_cols_with_symbols
332
+ name = @@db.create_index(@@coll.name, [[:a, DESCENDING], [:b, ASCENDING], [:c, DESCENDING]])
333
+ info = @@db.index_information(@@coll.name)
334
+ assert_equal 2, info.length
335
+
336
+ assert_equal name, 'a_-1_b_1_c_-1'
337
+ assert info.has_key?(name)
338
+ assert_equal [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]], info[name]
339
+ ensure
340
+ @@db.drop_index(@@coll.name, name)
341
+ end
342
+
343
+ def test_unique_index
344
+ @@db.drop_collection("blah")
345
+ test = @@db.collection("blah")
346
+ test.create_index("hello")
347
+
348
+ test.insert("hello" => "world")
349
+ test.insert("hello" => "mike")
350
+ test.insert("hello" => "world")
351
+ assert !@@db.error?
352
+
353
+ @@db.drop_collection("blah")
354
+ test = @@db.collection("blah")
355
+ test.create_index("hello", unique=true)
356
+
357
+ test.insert("hello" => "world")
358
+ test.insert("hello" => "mike")
359
+ test.insert("hello" => "world")
360
+ assert @@db.error?
361
+ end
362
+
363
+ def test_index_on_subfield
364
+ @@db.drop_collection("blah")
365
+ test = @@db.collection("blah")
366
+
367
+ test.insert("hello" => {"a" => 4, "b" => 5})
368
+ test.insert("hello" => {"a" => 7, "b" => 2})
369
+ test.insert("hello" => {"a" => 4, "b" => 10})
370
+ assert !@@db.error?
371
+
372
+ @@db.drop_collection("blah")
373
+ test = @@db.collection("blah")
374
+ test.create_index("hello.a", unique=true)
375
+
376
+ test.insert("hello" => {"a" => 4, "b" => 5})
377
+ test.insert("hello" => {"a" => 7, "b" => 2})
378
+ test.insert("hello" => {"a" => 4, "b" => 10})
379
+ assert @@db.error?
380
+ end
381
+
382
+ def test_array
383
+ @@coll << {'b' => [1, 2, 3]}
384
+ rows = @@coll.find({}, {:fields => ['b']}).to_a
385
+ assert_equal 1, rows.length
386
+ assert_equal [1, 2, 3], rows[0]['b']
387
+ end
388
+
389
+ def test_regex
390
+ regex = /foobar/i
391
+ @@coll << {'b' => regex}
392
+ rows = @@coll.find({}, {:fields => ['b']}).to_a
393
+ assert_equal 1, rows.length
394
+ assert_equal regex, rows[0]['b']
395
+ end
396
+
397
+ def test_non_oid_id
398
+ # Note: can't use Time.new because that will include fractional seconds,
399
+ # which Mongo does not store.
400
+ t = Time.at(1234567890)
401
+ @@coll << {'_id' => t}
402
+ rows = @@coll.find({'_id' => t}).to_a
403
+ assert_equal 1, rows.length
404
+ assert_equal t, rows[0]['_id']
405
+ end
406
+
407
+ def test_strict
408
+ assert !@@db.strict?
409
+ @@db.strict = true
410
+ assert @@db.strict?
411
+ ensure
412
+ @@db.strict = false
413
+ end
414
+
415
+ def test_strict_access_collection
416
+ @@db.strict = true
417
+ begin
418
+ @@db.collection('does-not-exist')
419
+ fail "expected exception"
420
+ rescue => ex
421
+ assert_equal "Collection does-not-exist doesn't exist. Currently in strict mode.", ex.to_s
422
+ ensure
423
+ @@db.strict = false
424
+ @@db.drop_collection('does-not-exist')
425
+ end
426
+ end
427
+
428
+ def test_strict_create_collection
429
+ @@db.drop_collection('foobar')
430
+ @@db.strict = true
431
+
432
+ begin
433
+ @@db.create_collection('foobar')
434
+ assert true
435
+ rescue => ex
436
+ fail "did not expect exception \"#{ex}\""
437
+ end
438
+
439
+ # Now the collection exists. This time we should see an exception.
440
+ begin
441
+ @@db.create_collection('foobar')
442
+ fail "expected exception"
443
+ rescue => ex
444
+ assert_equal "Collection foobar already exists. Currently in strict mode.", ex.to_s
445
+ ensure
446
+ @@db.strict = false
447
+ @@db.drop_collection('foobar')
448
+ end
449
+
450
+ # Now we're not in strict mode - should succeed
451
+ @@db.create_collection('foobar')
452
+ @@db.create_collection('foobar')
453
+ @@db.drop_collection('foobar')
454
+ end
455
+
456
+ def test_replace
457
+ assert_equal @@coll.count, 1
458
+ assert_equal @@coll.find_first["a"], 1
459
+
460
+ @@coll.replace({"a" => 1}, {"a" => 2})
461
+ assert_equal @@coll.count, 1
462
+ assert_equal @@coll.find_first["a"], 2
463
+
464
+ @@coll.replace({"b" => 1}, {"a" => 3})
465
+ assert_equal @@coll.count, 1
466
+ assert_equal @@coll.find_first["a"], 2
467
+ end
468
+
469
+ def test_repsert
470
+ assert_equal @@coll.count, 1
471
+ assert_equal @@coll.find_first["a"], 1
472
+
473
+ @@coll.repsert({"a" => 1}, {"a" => 2})
474
+ assert_equal @@coll.count, 1
475
+ assert_equal @@coll.find_first["a"], 2
476
+
477
+ @@coll.repsert({"b" => 1}, {"a" => 3})
478
+ assert_equal @@coll.count, 2
479
+ assert @@coll.find_first({"a" => 3})
480
+ end
481
+
482
+ def test_to_a
483
+ cursor = @@coll.find()
484
+ rows = cursor.to_a
485
+
486
+ # Make sure we get back exactly the same array the next time we ask
487
+ rows2 = cursor.to_a
488
+ assert_same rows, rows2
489
+
490
+ # Make sure we can still iterate after calling to_a
491
+ rows_with_each = cursor.collect{|row| row}
492
+ assert_equal rows, rows_with_each
493
+
494
+ # Make sure we can iterate more than once after calling to_a
495
+ end
496
+
497
+ def test_to_a_after_each
498
+ cursor = @@coll.find
499
+ cursor.each { |row| row }
500
+ begin
501
+ cursor.to_a
502
+ fail "expected \"can't call\" error"
503
+ rescue => ex
504
+ assert_equal "can't call Cursor#to_a after calling Cursor#each", ex.to_s
505
+ end
506
+ end
507
+
508
+ def test_ismaster
509
+ assert @@db.master?
510
+ end
511
+
512
+ def test_master
513
+ assert_equal "#{@@db.host}:#{@@db.port}", @@db.master
514
+ end
515
+
516
+ def test_where
517
+ @@coll.insert('a' => 2)
518
+ @@coll.insert('a' => 3)
519
+
520
+ assert_equal 3, @@coll.count
521
+ assert_equal 1, @@coll.count('$where' => Code.new('this.a > 2'))
522
+ assert_equal 2, @@coll.count('$where' => Code.new('this.a > i', {'i' => 1}))
523
+ end
524
+
525
+ def test_eval
526
+ assert_equal 3, @@db.eval('function (x) {return x;}', 3)
527
+
528
+ assert_equal nil, @@db.eval("function (x) {db.test_eval.save({y:x});}", 5)
529
+ assert_equal 5, @@db.collection('test_eval').find_first['y']
530
+
531
+ assert_equal 5, @@db.eval("function (x, y) {return x + y;}", 2, 3)
532
+ assert_equal 5, @@db.eval("function () {return 5;}")
533
+ assert_equal 5, @@db.eval("2 + 3;")
534
+
535
+ assert_equal 5, @@db.eval(Code.new("2 + 3;"))
536
+ assert_equal 2, @@db.eval(Code.new("return i;", {"i" => 2}))
537
+ assert_equal 5, @@db.eval(Code.new("i + 3;", {"i" => 2}))
538
+
539
+ assert_raise RuntimeError do
540
+ @@db.eval("5 ++ 5;")
541
+ end
542
+ end
543
+
544
+ def test_hint
545
+ name = @@coll.create_index('a')
546
+ begin
547
+ assert_nil @@coll.hint
548
+ assert_equal 1, @@coll.find({'a' => 1}, :hint => 'a').to_a.size
549
+ assert_equal 1, @@coll.find({'a' => 1}, :hint => ['a']).to_a.size
550
+ assert_equal 1, @@coll.find({'a' => 1}, :hint => {'a' => 1}).to_a.size
551
+
552
+ @@coll.hint = 'a'
553
+ assert_equal({'a' => 1}, @@coll.hint)
554
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
555
+
556
+ @@coll.hint = ['a']
557
+ assert_equal({'a' => 1}, @@coll.hint)
558
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
559
+
560
+ @@coll.hint = {'a' => 1}
561
+ assert_equal({'a' => 1}, @@coll.hint)
562
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
563
+
564
+ @@coll.hint = nil
565
+ assert_nil @@coll.hint
566
+ assert_equal 1, @@coll.find('a' => 1).to_a.size
567
+ ensure
568
+ @@coll.drop_index(name)
569
+ end
570
+ end
571
+
572
+ def test_hash_default_value_id
573
+ val = Hash.new(0)
574
+ val["x"] = 5
575
+ @@coll.insert val
576
+ id = @@coll.find_first("x" => 5)["_id"]
577
+ assert id != 0
578
+ end
579
+
580
+ def test_group
581
+ @@db.drop_collection("test")
582
+ test = @@db.collection("test")
583
+
584
+ assert_equal [], test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
585
+
586
+ test.insert("a" => 2)
587
+ test.insert("b" => 5)
588
+ test.insert("a" => 1)
589
+
590
+ assert_equal 3, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
591
+ assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
592
+ end
593
+
594
+ def test_deref
595
+ @@coll.clear
596
+
597
+ assert_equal nil, @@db.dereference(DBRef.new("test", ObjectID.new))
598
+ @@coll.insert({"x" => "hello"})
599
+ key = @@coll.find_first()["_id"]
600
+ assert_equal "hello", @@db.dereference(DBRef.new("test", key))["x"]
601
+
602
+ assert_equal nil, @@db.dereference(DBRef.new("test", 4))
603
+ obj = {"_id" => 4}
604
+ @@coll.insert(obj)
605
+ assert_equal obj, @@db.dereference(DBRef.new("test", 4))
606
+
607
+ @@coll.clear
608
+ @@coll.insert({"x" => "hello"})
609
+ assert_equal nil, @@db.dereference(DBRef.new("test", nil))
610
+ end
611
+
612
+ def test_save
613
+ @@coll.clear
614
+
615
+ a = {"hello" => "world"}
616
+
617
+ @@coll.save(a)
618
+ assert_equal 1, @@coll.count
619
+
620
+ @@coll.save(@@coll.find_first)
621
+ assert_equal 1, @@coll.count
622
+
623
+ assert_equal "world", @@coll.find_first()["hello"]
624
+
625
+ doc = @@coll.find_first
626
+ doc["hello"] = "mike"
627
+ @@coll.save(doc)
628
+ assert_equal 1, @@coll.count
629
+
630
+ assert_equal "mike", @@coll.find_first()["hello"]
631
+
632
+ @@coll.save(a)
633
+ assert_equal 2, @@coll.count
634
+ end
635
+
636
+ def test_save_with_object_that_has_id_but_does_not_actually_exist_in_collection
637
+ @@coll.clear
638
+
639
+ a = {'_id' => '1', 'hello' => 'world'}
640
+ @@coll.save(a)
641
+ assert_equal(1, @@coll.count)
642
+ assert_equal("world", @@coll.find_first()["hello"])
643
+
644
+ a["hello"] = "mike"
645
+ @@coll.save(a)
646
+ assert_equal(1, @@coll.count)
647
+ assert_equal("mike", @@coll.find_first()["hello"])
648
+ end
649
+
650
+ def test_invalid_key_names
651
+ @@coll.clear
652
+
653
+ @@coll.insert({"hello" => "world"})
654
+ @@coll.insert({"hello" => {"hello" => "world"}})
655
+
656
+ assert_raise RuntimeError do
657
+ @@coll.insert({"$hello" => "world"})
658
+ end
659
+ assert_raise RuntimeError do
660
+ @@coll.insert({"hello" => {"$hello" => "world"}})
661
+ end
662
+
663
+ @@coll.insert({"he$llo" => "world"})
664
+ @@coll.insert({"hello" => {"hell$o" => "world"}})
665
+
666
+ assert_raise RuntimeError do
667
+ @@coll.insert({".hello" => "world"})
668
+ end
669
+ assert_raise RuntimeError do
670
+ @@coll.insert({"hello" => {".hello" => "world"}})
671
+ end
672
+ assert_raise RuntimeError do
673
+ @@coll.insert({"hello." => "world"})
674
+ end
675
+ assert_raise RuntimeError do
676
+ @@coll.insert({"hello" => {"hello." => "world"}})
677
+ end
678
+ assert_raise RuntimeError do
679
+ @@coll.insert({"hel.lo" => "world"})
680
+ end
681
+ assert_raise RuntimeError do
682
+ @@coll.insert({"hello" => {"hel.lo" => "world"}})
683
+ end
684
+
685
+ @@coll.modify({"hello" => "world"}, {"$inc" => "hello"})
686
+ end
687
+
688
+ # TODO this test fails with error message "Undefed Before end of object"
689
+ # That is a database error. The undefined type may go away.
690
+
691
+ # def test_insert_undefined
692
+ # doc = {'undef' => Undefined.new}
693
+ # @@coll.clear
694
+ # @@coll.insert(doc)
695
+ # p @@db.error # DEBUG
696
+ # assert_equal 1, @@coll.count
697
+ # row = @@coll.find().next_object
698
+ # assert_not_nil row
699
+ # end
700
+
701
+ end