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.
Files changed (89) hide show
  1. data/README.rdoc +268 -71
  2. data/Rakefile +27 -62
  3. data/bin/bson_benchmark.rb +59 -0
  4. data/bin/mongo_console +3 -3
  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 +35 -0
  19. data/lib/mongo.rb +9 -2
  20. data/lib/mongo/admin.rb +65 -68
  21. data/lib/mongo/collection.rb +379 -117
  22. data/lib/mongo/connection.rb +151 -0
  23. data/lib/mongo/cursor.rb +271 -216
  24. data/lib/mongo/db.rb +500 -315
  25. data/lib/mongo/errors.rb +26 -0
  26. data/lib/mongo/gridfs.rb +16 -0
  27. data/lib/mongo/gridfs/chunk.rb +92 -0
  28. data/lib/mongo/gridfs/grid_store.rb +464 -0
  29. data/lib/mongo/message.rb +16 -0
  30. data/lib/mongo/message/get_more_message.rb +24 -13
  31. data/lib/mongo/message/insert_message.rb +29 -11
  32. data/lib/mongo/message/kill_cursors_message.rb +23 -12
  33. data/lib/mongo/message/message.rb +74 -62
  34. data/lib/mongo/message/message_header.rb +35 -24
  35. data/lib/mongo/message/msg_message.rb +21 -9
  36. data/lib/mongo/message/opcodes.rb +26 -15
  37. data/lib/mongo/message/query_message.rb +63 -43
  38. data/lib/mongo/message/remove_message.rb +29 -12
  39. data/lib/mongo/message/update_message.rb +30 -13
  40. data/lib/mongo/query.rb +97 -89
  41. data/lib/mongo/types/binary.rb +25 -21
  42. data/lib/mongo/types/code.rb +30 -0
  43. data/lib/mongo/types/dbref.rb +19 -23
  44. data/lib/mongo/types/objectid.rb +130 -116
  45. data/lib/mongo/types/regexp_of_holding.rb +27 -31
  46. data/lib/mongo/util/bson.rb +273 -160
  47. data/lib/mongo/util/byte_buffer.rb +32 -28
  48. data/lib/mongo/util/ordered_hash.rb +88 -42
  49. data/lib/mongo/util/xml_to_ruby.rb +18 -15
  50. data/mongo-ruby-driver.gemspec +103 -0
  51. data/test/mongo-qa/_common.rb +8 -0
  52. data/test/mongo-qa/admin +26 -0
  53. data/test/mongo-qa/capped +22 -0
  54. data/test/mongo-qa/count1 +18 -0
  55. data/test/mongo-qa/dbs +22 -0
  56. data/test/mongo-qa/find +10 -0
  57. data/test/mongo-qa/find1 +15 -0
  58. data/test/mongo-qa/gridfs_in +16 -0
  59. data/test/mongo-qa/gridfs_out +17 -0
  60. data/test/mongo-qa/indices +49 -0
  61. data/test/mongo-qa/remove +25 -0
  62. data/test/mongo-qa/stress1 +35 -0
  63. data/test/mongo-qa/test1 +11 -0
  64. data/test/mongo-qa/update +18 -0
  65. data/{tests → test}/test_admin.rb +25 -16
  66. data/test/test_bson.rb +268 -0
  67. data/{tests → test}/test_byte_buffer.rb +0 -0
  68. data/test/test_chunk.rb +84 -0
  69. data/test/test_collection.rb +282 -0
  70. data/test/test_connection.rb +101 -0
  71. data/test/test_cursor.rb +321 -0
  72. data/test/test_db.rb +196 -0
  73. data/test/test_db_api.rb +798 -0
  74. data/{tests → test}/test_db_connection.rb +4 -3
  75. data/test/test_grid_store.rb +284 -0
  76. data/{tests → test}/test_message.rb +1 -1
  77. data/test/test_objectid.rb +105 -0
  78. data/{tests → test}/test_ordered_hash.rb +55 -0
  79. data/{tests → test}/test_round_trip.rb +13 -9
  80. data/test/test_threading.rb +37 -0
  81. metadata +74 -32
  82. data/bin/validate +0 -51
  83. data/lib/mongo/mongo.rb +0 -74
  84. data/lib/mongo/types/undefined.rb +0 -31
  85. data/tests/test_bson.rb +0 -135
  86. data/tests/test_cursor.rb +0 -66
  87. data/tests/test_db.rb +0 -51
  88. data/tests/test_db_api.rb +0 -349
  89. data/tests/test_objectid.rb +0 -88
File without changes
@@ -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 Mongo
9
+ include GridFS
10
+
11
+ @@db = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
12
+ ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::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,282 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+
17
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
18
+ require 'mongo'
19
+ require 'test/unit'
20
+
21
+ # NOTE: assumes Mongo is running
22
+ class TestCollection < Test::Unit::TestCase
23
+ include Mongo
24
+
25
+ @@db = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
26
+ ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT).db('ruby-mongo-test')
27
+ @@test = @@db.collection("test")
28
+
29
+ def setup
30
+ @@test.drop()
31
+ end
32
+
33
+ def test_collection
34
+ assert_raise InvalidName do
35
+ @@db["te$t"]
36
+ end
37
+
38
+ assert_kind_of Collection, @@db["test"]
39
+ assert_equal @@db["test"].name(), @@db.collection("test").name()
40
+ assert_equal @@db["test"].name(), @@db[:test].name()
41
+
42
+ assert_kind_of Collection, @@db["test"]["foo"]
43
+ assert_equal @@db["test"]["foo"].name(), @@db.collection("test.foo").name()
44
+ assert_equal @@db["test"]["foo"].name(), @@db["test.foo"].name()
45
+
46
+ @@db["test"]["foo"].clear
47
+ @@db["test"]["foo"].insert("x" => 5)
48
+ assert_equal 5, @@db.collection("test.foo").find_one()["x"]
49
+ end
50
+
51
+ def test_safe_insert
52
+ a = {"hello" => "world"}
53
+ @@test.insert(a)
54
+ @@test.insert(a)
55
+ assert(@@db.error.include?("E11000"))
56
+
57
+ assert_raise OperationFailure do
58
+ @@test.insert(a, :safe => true)
59
+ end
60
+ end
61
+
62
+ def test_update
63
+ id1 = @@test.save("x" => 5)
64
+ @@test.update({}, {"$inc" => {"x" => 1}})
65
+ assert_equal 1, @@test.count()
66
+ assert_equal 6, @@test.find_one(:_id => id1)["x"]
67
+
68
+ id2 = @@test.save("x" => 1)
69
+ @@test.update({"x" => 6}, {"$inc" => {"x" => 1}})
70
+ assert_equal 7, @@test.find_one(:_id => id1)["x"]
71
+ assert_equal 1, @@test.find_one(:_id => id2)["x"]
72
+ end
73
+
74
+ def test_upsert
75
+ @@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
76
+ @@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
77
+
78
+ assert_equal 1, @@test.count()
79
+ assert_equal 2, @@test.find_one()["count"]
80
+ end
81
+
82
+ def test_safe_update
83
+ @@test.create_index("x")
84
+ @@test.insert("x" => 5)
85
+
86
+ @@test.update({}, {"$inc" => {"x" => 1}})
87
+ assert @@db.error?
88
+
89
+ assert_raise OperationFailure do
90
+ @@test.update({}, {"$inc" => {"x" => 1}}, :safe => true)
91
+ end
92
+ end
93
+
94
+ def test_safe_save
95
+ @@test.create_index("hello", true)
96
+
97
+ @@test.save("hello" => "world")
98
+ @@test.save("hello" => "world")
99
+ assert(@@db.error.include?("E11000"))
100
+
101
+ assert_raise OperationFailure do
102
+ @@test.save({"hello" => "world"}, :safe => true)
103
+ end
104
+ end
105
+
106
+ def test_count
107
+ @@test.drop
108
+
109
+ assert_equal 0, @@test.count
110
+ @@test.save("x" => 1)
111
+ @@test.save("x" => 2)
112
+ assert_equal 2, @@test.count
113
+ end
114
+
115
+ def test_find_one
116
+ id = @@test.save("hello" => "world", "foo" => "bar")
117
+
118
+ assert_equal "world", @@test.find_one()["hello"]
119
+ assert_equal @@test.find_one(id), @@test.find_one()
120
+ assert_equal @@test.find_one(nil), @@test.find_one()
121
+ assert_equal @@test.find_one({}), @@test.find_one()
122
+ assert_equal @@test.find_one("hello" => "world"), @@test.find_one()
123
+ assert_equal @@test.find_one(OrderedHash["hello", "world"]), @@test.find_one()
124
+
125
+ assert @@test.find_one(nil, :fields => ["hello"]).include?("hello")
126
+ assert !@@test.find_one(nil, :fields => ["foo"]).include?("hello")
127
+ assert_equal ["_id"], @@test.find_one(nil, :fields => []).keys()
128
+
129
+ assert_equal nil, @@test.find_one("hello" => "foo")
130
+ assert_equal nil, @@test.find_one(OrderedHash["hello", "foo"])
131
+ assert_equal nil, @@test.find_one(ObjectID.new)
132
+
133
+ assert_raise TypeError do
134
+ @@test.find_one(6)
135
+ end
136
+ end
137
+
138
+ def test_insert_adds_id
139
+ doc = {"hello" => "world"}
140
+ @@test.insert(doc)
141
+ assert(doc.include?(:_id))
142
+
143
+ docs = [{"hello" => "world"}, {"hello" => "world"}]
144
+ @@test.insert(docs)
145
+ docs.each do |doc|
146
+ assert(doc.include?(:_id))
147
+ end
148
+ end
149
+
150
+ def test_save_adds_id
151
+ doc = {"hello" => "world"}
152
+ @@test.save(doc)
153
+ assert(doc.include?(:_id))
154
+ end
155
+
156
+ def test_optional_find_block
157
+ 10.times do |i|
158
+ @@test.save("i" => i)
159
+ end
160
+
161
+ x = nil
162
+ @@test.find("i" => 2) { |cursor|
163
+ x = cursor.count()
164
+ }
165
+ assert_equal 1, x
166
+
167
+ i = 0
168
+ @@test.find({}, :skip => 5) do |cursor|
169
+ cursor.each do |doc|
170
+ i = i + 1
171
+ end
172
+ end
173
+ assert_equal 5, i
174
+
175
+ c = nil
176
+ @@test.find() do |cursor|
177
+ c = cursor
178
+ end
179
+ assert c.closed?
180
+ end
181
+
182
+ def test_saving_dates_pre_epoch
183
+ begin
184
+ @@test.save({'date' => Time.utc(1600)})
185
+ assert_in_delta Time.utc(1600), @@test.find_one()["date"], 0.001
186
+ rescue ArgumentError
187
+ # See note in test_date_before_epoch (BSONTest)
188
+ end
189
+ end
190
+
191
+ def test_save_symbol_find_string
192
+ @@test.save(:foo => :mike)
193
+
194
+ assert_equal :mike, @@test.find_one(:foo => :mike)["foo"]
195
+ assert_equal :mike, @@test.find_one("foo" => :mike)["foo"]
196
+
197
+ # TODO enable these tests conditionally based on server version (if >1.0)
198
+ # assert_equal :mike, @@test.find_one(:foo => "mike")["foo"]
199
+ # assert_equal :mike, @@test.find_one("foo" => "mike")["foo"]
200
+ end
201
+
202
+ def test_limit_and_skip
203
+ 10.times do |i|
204
+ @@test.save(:foo => i)
205
+ end
206
+
207
+ # TODO remove test for deprecated :offset option
208
+ assert_equal 5, @@test.find({}, :offset => 5).next_object()["foo"]
209
+
210
+ assert_equal 5, @@test.find({}, :skip => 5).next_object()["foo"]
211
+ assert_equal nil, @@test.find({}, :skip => 10).next_object()
212
+
213
+ assert_equal 5, @@test.find({}, :limit => 5).to_a.length
214
+
215
+ assert_equal 3, @@test.find({}, :skip => 3, :limit => 5).next_object()["foo"]
216
+ assert_equal 5, @@test.find({}, :skip => 3, :limit => 5).to_a.length
217
+ end
218
+
219
+ def test_large_limit
220
+ 2000.times do |i|
221
+ @@test.insert("x" => i, "y" => "mongomongo" * 1000)
222
+ end
223
+
224
+ assert_equal 2000, @@test.count
225
+
226
+ i = 0
227
+ y = 0
228
+ @@test.find({}, :limit => 1900).each do |doc|
229
+ i += 1
230
+ y += doc["x"]
231
+ end
232
+
233
+ assert_equal 1900, i
234
+ assert_equal 1804050, y
235
+ end
236
+
237
+ def test_small_limit
238
+ @@test.insert("x" => "hello world")
239
+ @@test.insert("x" => "goodbye world")
240
+
241
+ assert_equal 2, @@test.count
242
+
243
+ x = 0
244
+ @@test.find({}, :limit => 1).each do |doc|
245
+ x += 1
246
+ assert_equal "hello world", doc["x"]
247
+ end
248
+
249
+ assert_equal 1, x
250
+ end
251
+
252
+ def test_group_with_scope
253
+ @@test.save("a" => 1)
254
+ @@test.save("b" => 1)
255
+
256
+ reduce_function = "function (obj, prev) { prev.count += inc_value; }"
257
+
258
+ assert_equal 2, @@test.group([], {}, {"count" => 0},
259
+ Code.new(reduce_function,
260
+ {"inc_value" => 1}))[0]["count"]
261
+
262
+ # TODO enable these tests when SERVER-262 is fixed
263
+
264
+ # assert_equal 2, @@test.group([], {}, {"count" => 0},
265
+ # Code.new(reduce_function,
266
+ # {"inc_value" => 1}), true)[0]["count"]
267
+
268
+ assert_equal 4, @@test.group([], {}, {"count" => 0},
269
+ Code.new(reduce_function,
270
+ {"inc_value" => 2}))[0]["count"]
271
+ # assert_equal 4, @@test.group([], {}, {"count" => 0},
272
+ # Code.new(reduce_function,
273
+ # {"inc_value" => 2}), true)[0]["count"]
274
+
275
+ assert_equal 1, @@test.group([], {}, {"count" => 0},
276
+ Code.new(reduce_function,
277
+ {"inc_value" => 0.5}))[0]["count"]
278
+ # assert_equal 1, @@test.group([], {}, {"count" => 0},
279
+ # Code.new(reduce_function,
280
+ # {"inc_value" => 0.5}), true)[0]["count"]
281
+ end
282
+ end
@@ -0,0 +1,101 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'logger'
5
+ require 'stringio'
6
+
7
+ # NOTE: assumes Mongo is running
8
+ class TestConnection < Test::Unit::TestCase
9
+
10
+ include Mongo
11
+
12
+ def setup
13
+ @host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
14
+ @port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
15
+ @mongo = Connection.new(@host, @port)
16
+ end
17
+
18
+ def teardown
19
+ @mongo.db('ruby-mongo-test').error
20
+ end
21
+
22
+ def test_invalid_database_names
23
+ assert_raise TypeError do @mongo.db(4) end
24
+
25
+ assert_raise InvalidName do @mongo.db('') end
26
+ assert_raise InvalidName do @mongo.db('te$t') end
27
+ assert_raise InvalidName do @mongo.db('te.t') end
28
+ assert_raise InvalidName do @mongo.db('te\\t') end
29
+ assert_raise InvalidName do @mongo.db('te/t') end
30
+ assert_raise InvalidName do @mongo.db('te st') end
31
+ end
32
+
33
+ def test_database_info
34
+ @mongo.drop_database('ruby-mongo-info-test')
35
+ @mongo.db('ruby-mongo-info-test').collection('info-test').insert('a' => 1)
36
+
37
+ info = @mongo.database_info
38
+ assert_not_nil info
39
+ assert_kind_of Hash, info
40
+ assert_not_nil info['ruby-mongo-info-test']
41
+ assert info['ruby-mongo-info-test'] > 0
42
+
43
+ @mongo.drop_database('ruby-mongo-info-test')
44
+ end
45
+
46
+ def test_database_names
47
+ @mongo.drop_database('ruby-mongo-info-test')
48
+ @mongo.db('ruby-mongo-info-test').collection('info-test').insert('a' => 1)
49
+
50
+ names = @mongo.database_names
51
+ assert_not_nil names
52
+ assert_kind_of Array, names
53
+ assert names.length >= 1
54
+ assert names.include?('ruby-mongo-info-test')
55
+
56
+ @mongo.drop_database('ruby-mongo-info-test')
57
+ end
58
+
59
+ def test_logging
60
+ output = StringIO.new
61
+ logger = Logger.new(output)
62
+ logger.level = Logger::DEBUG
63
+ db = Connection.new(@host, @port, :logger => logger).db('ruby-mongo-test')
64
+ db['test'].find().to_a
65
+
66
+ assert output.string.include?("db.test.find")
67
+ assert !output.string.include?("db.test.remove")
68
+ end
69
+
70
+ def test_drop_database
71
+ db = @mongo.db('ruby-mongo-will-be-deleted')
72
+ coll = db.collection('temp')
73
+ coll.clear
74
+ coll.insert(:name => 'temp')
75
+ assert_equal 1, coll.count()
76
+ assert @mongo.database_names.include?('ruby-mongo-will-be-deleted')
77
+
78
+ @mongo.drop_database('ruby-mongo-will-be-deleted')
79
+ assert !@mongo.database_names.include?('ruby-mongo-will-be-deleted')
80
+ end
81
+
82
+ def test_pair
83
+ db = Connection.new({:left => ['foo', 123]})
84
+ pair = db.instance_variable_get('@pair')
85
+ assert_equal 2, pair.length
86
+ assert_equal ['foo', 123], pair[0]
87
+ assert_equal ['localhost', Connection::DEFAULT_PORT], pair[1]
88
+
89
+ db = Connection.new({:right => 'bar'})
90
+ pair = db.instance_variable_get('@pair')
91
+ assert_equal 2, pair.length
92
+ assert_equal ['localhost', Connection::DEFAULT_PORT], pair[0]
93
+ assert_equal ['bar', Connection::DEFAULT_PORT], pair[1]
94
+
95
+ db = Connection.new({:right => ['foo', 123], :left => 'bar'})
96
+ pair = db.instance_variable_get('@pair')
97
+ assert_equal 2, pair.length
98
+ assert_equal ['bar', Connection::DEFAULT_PORT], pair[0]
99
+ assert_equal ['foo', 123], pair[1]
100
+ end
101
+ end