mongo 0.1.0 → 0.15

Sign up to get free protection for your applications and to get access to all the features.
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