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,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