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
@@ -5,13 +5,14 @@ require 'test/unit'
5
5
  # NOTE: assumes Mongo is running
6
6
  class DBConnectionTest < Test::Unit::TestCase
7
7
 
8
- include XGen::Mongo::Driver
8
+ include Mongo
9
9
 
10
10
  def test_no_exceptions
11
11
  host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
12
- port = ENV['MONGO_RUBY_DRIVER_PORT'] || Mongo::DEFAULT_PORT
13
- db = Mongo.new(host, port).db('ruby-mongo-demo')
12
+ port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
13
+ db = Connection.new(host, port).db('ruby-mongo-demo')
14
14
  coll = db.collection('test')
15
15
  coll.clear
16
+ db.error
16
17
  end
17
18
  end
@@ -0,0 +1,284 @@
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 GridStoreTest < 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-test')
13
+ @@files = @@db.collection('fs.files')
14
+ @@chunks = @@db.collection('fs.chunks')
15
+
16
+ def setup
17
+ @@chunks.clear
18
+ @@files.clear
19
+ GridStore.open(@@db, 'foobar', 'w') { |f| f.write("hello, world!") }
20
+ end
21
+
22
+ def teardown
23
+ @@chunks.clear
24
+ @@files.clear
25
+ @@db.error
26
+ end
27
+
28
+ def test_exist
29
+ assert GridStore.exist?(@@db, 'foobar')
30
+ assert !GridStore.exist?(@@db, 'does_not_exist')
31
+ assert !GridStore.exist?(@@db, 'foobar', 'another_root')
32
+ end
33
+
34
+ def test_list
35
+ assert_equal ['foobar'], GridStore.list(@@db)
36
+ assert_equal ['foobar'], GridStore.list(@@db, 'fs')
37
+ assert_equal [], GridStore.list(@@db, 'my_fs')
38
+
39
+ GridStore.open(@@db, 'test', 'w') { |f| f.write("my file") }
40
+
41
+ assert_equal ['foobar', 'test'], GridStore.list(@@db)
42
+ end
43
+
44
+ def test_small_write
45
+ rows = @@files.find({'filename' => 'foobar'}).to_a
46
+ assert_not_nil rows
47
+ assert_equal 1, rows.length
48
+ row = rows[0]
49
+ assert_not_nil row
50
+
51
+ file_id = row['_id']
52
+ assert_kind_of ObjectID, file_id
53
+ rows = @@chunks.find({'files_id' => file_id}).to_a
54
+ assert_not_nil rows
55
+ assert_equal 1, rows.length
56
+ end
57
+
58
+ def test_small_file
59
+ rows = @@files.find({'filename' => 'foobar'}).to_a
60
+ assert_not_nil rows
61
+ assert_equal 1, rows.length
62
+ row = rows[0]
63
+ assert_not_nil row
64
+ assert_equal "hello, world!", GridStore.read(@@db, 'foobar')
65
+ end
66
+
67
+ def test_overwrite
68
+ GridStore.open(@@db, 'foobar', 'w') { |f| f.write("overwrite") }
69
+ assert_equal "overwrite", GridStore.read(@@db, 'foobar')
70
+ end
71
+
72
+ def test_read_length
73
+ assert_equal "hello", GridStore.read(@@db, 'foobar', 5)
74
+ end
75
+
76
+ # Also tests seek
77
+ def test_read_with_offset
78
+ assert_equal "world", GridStore.read(@@db, 'foobar', 5, 7)
79
+ assert_equal "world!", GridStore.read(@@db, 'foobar', nil, 7)
80
+ end
81
+
82
+ def test_seek
83
+ GridStore.open(@@db, 'foobar', 'r') { |f|
84
+ f.seek(0)
85
+ assert_equal 'h', f.getc.chr
86
+ f.seek(7)
87
+ assert_equal 'w', f.getc.chr
88
+ f.seek(4)
89
+ assert_equal 'o', f.getc.chr
90
+
91
+ f.seek(-1, IO::SEEK_END)
92
+ assert_equal '!', f.getc.chr
93
+ f.seek(-6, IO::SEEK_END)
94
+ assert_equal 'w', f.getc.chr
95
+
96
+ f.seek(0)
97
+ f.seek(7, IO::SEEK_CUR)
98
+ assert_equal 'w', f.getc.chr
99
+ f.seek(-1, IO::SEEK_CUR)
100
+ assert_equal 'w', f.getc.chr
101
+ f.seek(-4, IO::SEEK_CUR)
102
+ assert_equal 'o', f.getc.chr
103
+ f.seek(3, IO::SEEK_CUR)
104
+ assert_equal 'o', f.getc.chr
105
+ }
106
+ end
107
+
108
+ def test_multi_chunk
109
+ @@chunks.clear
110
+ @@files.clear
111
+
112
+ size = 512
113
+ GridStore.open(@@db, 'biggie', 'w') { |f|
114
+ f.chunk_size = size
115
+ f.write('x' * size)
116
+ f.write('y' * size)
117
+ f.write('z' * size)
118
+ }
119
+
120
+ assert_equal 3, @@chunks.count
121
+ assert_equal ('x' * size) + ('y' * size) + ('z' * size), GridStore.read(@@db, 'biggie')
122
+ end
123
+
124
+ def test_puts_and_readlines
125
+ GridStore.open(@@db, 'multiline', 'w') { |f|
126
+ f.puts "line one"
127
+ f.puts "line two\n"
128
+ f.puts "line three"
129
+ }
130
+
131
+ lines = GridStore.readlines(@@db, 'multiline')
132
+ assert_equal ["line one\n", "line two\n", "line three\n"], lines
133
+ end
134
+
135
+ def test_unlink
136
+ assert_equal 1, @@files.count
137
+ assert_equal 1, @@chunks.count
138
+ GridStore.unlink(@@db, 'foobar')
139
+ assert_equal 0, @@files.count
140
+ assert_equal 0, @@chunks.count
141
+ end
142
+
143
+ def test_append
144
+ GridStore.open(@@db, 'foobar', 'w+') { |f| f.write(" how are you?") }
145
+ assert_equal 1, @@chunks.count
146
+ assert_equal "hello, world! how are you?", GridStore.read(@@db, 'foobar')
147
+ end
148
+
149
+ def test_rewind_and_truncate_on_write
150
+ GridStore.open(@@db, 'foobar', 'w') { |f|
151
+ f.write("some text is inserted here")
152
+ f.rewind
153
+ f.write("abc")
154
+ }
155
+ assert_equal "abc", GridStore.read(@@db, 'foobar')
156
+ end
157
+
158
+ def test_tell
159
+ GridStore.open(@@db, 'foobar', 'r') { |f|
160
+ f.read(5)
161
+ assert_equal 5, f.tell
162
+ }
163
+ end
164
+
165
+ def test_empty_block_ok
166
+ GridStore.open(@@db, 'empty', 'w')
167
+ end
168
+
169
+ def test_save_empty_file
170
+ @@chunks.clear
171
+ @@files.clear
172
+ GridStore.open(@@db, 'empty', 'w') {} # re-write with zero bytes
173
+ assert_equal 1, @@files.count
174
+ assert_equal 0, @@chunks.count
175
+ end
176
+
177
+ def test_empty_file_eof
178
+ GridStore.open(@@db, 'empty', 'w')
179
+ GridStore.open(@@db, 'empty', 'r') { |f|
180
+ assert f.eof?
181
+ }
182
+ end
183
+
184
+ def test_cannot_change_chunk_size_on_read
185
+ begin
186
+ GridStore.open(@@db, 'foobar', 'r') { |f| f.chunk_size = 42 }
187
+ fail "should have seen error"
188
+ rescue => ex
189
+ assert_match /error: can only change chunk size/, ex.to_s
190
+ end
191
+ end
192
+
193
+ def test_cannot_change_chunk_size_after_data_written
194
+ begin
195
+ GridStore.open(@@db, 'foobar', 'w') { |f|
196
+ f.write("some text")
197
+ f.chunk_size = 42
198
+ }
199
+ fail "should have seen error"
200
+ rescue => ex
201
+ assert_match /error: can only change chunk size/, ex.to_s
202
+ end
203
+ end
204
+
205
+ def test_change_chunk_size
206
+ GridStore.open(@@db, 'new-file', 'w') { |f|
207
+ f.chunk_size = 42
208
+ f.write("foo")
209
+ }
210
+ GridStore.open(@@db, 'new-file', 'r') { |f|
211
+ assert f.chunk_size == 42
212
+ }
213
+ end
214
+
215
+ def test_chunk_size_in_option
216
+ GridStore.open(@@db, 'new-file', 'w', :chunk_size => 42) { |f| f.write("foo") }
217
+ GridStore.open(@@db, 'new-file', 'r') { |f|
218
+ assert f.chunk_size == 42
219
+ }
220
+ end
221
+
222
+ def test_md5
223
+ GridStore.open(@@db, 'new-file', 'w') { |f| f.write("hello world\n")}
224
+ GridStore.open(@@db, 'new-file', 'r') { |f|
225
+ assert f.md5 == '6f5902ac237024bdd0c176cb93063dc4'
226
+ begin
227
+ f.md5 = 'cant do this'
228
+ fail "should have seen error"
229
+ rescue => ex
230
+ true
231
+ end
232
+ }
233
+ GridStore.open(@@db, 'new-file', 'w') {}
234
+ GridStore.open(@@db, 'new-file', 'r') { |f|
235
+ assert f.md5 == 'd41d8cd98f00b204e9800998ecf8427e'
236
+ }
237
+ end
238
+
239
+ def test_upload_date
240
+ now = Time.now
241
+ orig_file_upload_date = nil
242
+ GridStore.open(@@db, 'foobar', 'r') { |f| orig_file_upload_date = f.upload_date }
243
+ assert_not_nil orig_file_upload_date
244
+ assert (orig_file_upload_date - now) < 5 # even a really slow system < 5 secs
245
+
246
+ sleep(2)
247
+ GridStore.open(@@db, 'foobar', 'w') { |f| f.write "new data" }
248
+ file_upload_date = nil
249
+ GridStore.open(@@db, 'foobar', 'r') { |f| file_upload_date = f.upload_date }
250
+ assert_equal orig_file_upload_date, file_upload_date
251
+ end
252
+
253
+ def test_content_type
254
+ ct = nil
255
+ GridStore.open(@@db, 'foobar', 'r') { |f| ct = f.content_type }
256
+ assert_equal GridStore::DEFAULT_CONTENT_TYPE, ct
257
+
258
+ GridStore.open(@@db, 'foobar', 'w+') { |f| f.content_type = 'text/html' }
259
+ ct2 = nil
260
+ GridStore.open(@@db, 'foobar', 'r') { |f| ct2 = f.content_type }
261
+ assert_equal 'text/html', ct2
262
+ end
263
+
264
+ def test_content_type_option
265
+ GridStore.open(@@db, 'new-file', 'w', :content_type => 'image/jpg') { |f| f.write('foo') }
266
+ ct = nil
267
+ GridStore.open(@@db, 'new-file', 'r') { |f| ct = f.content_type }
268
+ assert_equal 'image/jpg', ct
269
+ end
270
+
271
+ def test_unknown_mode
272
+ GridStore.open(@@db, 'foobar', 'x')
273
+ fail 'should have seen "illegal mode" error raised'
274
+ rescue => ex
275
+ assert_equal "error: illegal mode x", ex.to_s
276
+ end
277
+
278
+ def test_metadata
279
+ GridStore.open(@@db, 'foobar', 'r') { |f| assert_nil f.metadata }
280
+ GridStore.open(@@db, 'foobar', 'w+') { |f| f.metadata = {'a' => 1} }
281
+ GridStore.open(@@db, 'foobar', 'r') { |f| assert_equal({'a' => 1}, f.metadata) }
282
+ end
283
+
284
+ end
@@ -4,7 +4,7 @@ require 'test/unit'
4
4
 
5
5
  class MessageTest < Test::Unit::TestCase
6
6
 
7
- include XGen::Mongo::Driver
7
+ include Mongo
8
8
 
9
9
  def setup
10
10
  @msg = Message.new(42)
@@ -0,0 +1,105 @@
1
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'mongo'
3
+ require 'test/unit'
4
+
5
+ class ObjectIDTest < Test::Unit::TestCase
6
+
7
+ include Mongo
8
+
9
+ def setup
10
+ @o = ObjectID.new()
11
+ end
12
+
13
+ def test_different
14
+ a = ObjectID.new
15
+ b = ObjectID.new
16
+ assert_not_equal a.to_a, b.to_a
17
+ assert_not_equal a, b
18
+ end
19
+
20
+ def test_eql?
21
+ o2 = ObjectID.new(@o.to_a)
22
+ assert_equal @o, o2
23
+ end
24
+
25
+ def test_to_s
26
+ s = @o.to_s
27
+ assert_equal 24, s.length
28
+ s =~ /^([0-9a-f]+)$/
29
+ assert_equal 24, $1.length
30
+ end
31
+
32
+ def test_to_s_legacy
33
+ s = @o.to_s_legacy
34
+ assert_equal 24, s.length
35
+ s =~ /^([0-9a-f]+)$/
36
+ assert_equal 24, $1.length
37
+
38
+ assert_not_equal s, @o.to_s
39
+ end
40
+
41
+ def test_save_and_restore
42
+ host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
43
+ port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
44
+ db = Connection.new(host, port).db('ruby-mongo-test')
45
+ coll = db.collection('test')
46
+
47
+ coll.clear
48
+ coll << {'a' => 1, '_id' => @o}
49
+
50
+ row = coll.find().collect.first
51
+ assert_equal 1, row['a']
52
+ assert_equal @o, row['_id']
53
+ end
54
+
55
+ def test_from_string
56
+ hex_str = @o.to_s
57
+ o2 = ObjectID.from_string(hex_str)
58
+ assert_equal hex_str, o2.to_s
59
+ assert_equal @o, o2
60
+ assert_equal @o.to_s, o2.to_s
61
+ end
62
+
63
+ def test_from_string_legacy
64
+ hex_str = @o.to_s_legacy
65
+ o2 = ObjectID.from_string_legacy(hex_str)
66
+ assert_equal hex_str, o2.to_s_legacy
67
+ assert_equal @o, o2
68
+ assert_equal @o.to_s, o2.to_s
69
+ end
70
+
71
+ def test_legal
72
+ assert !ObjectID.legal?(nil)
73
+ assert !ObjectID.legal?("fred")
74
+ assert !ObjectID.legal?("0000")
75
+ assert !ObjectID.legal?('000102030405060708090A0')
76
+ assert ObjectID.legal?('000102030405060708090A0B')
77
+ assert ObjectID.legal?('abcdefABCDEF123456789012')
78
+ assert !ObjectID.legal?('abcdefABCDEF12345678901x')
79
+ end
80
+
81
+ def test_from_string_leading_zeroes
82
+ hex_str = '000000000000000000000000'
83
+ o = ObjectID.from_string(hex_str)
84
+ assert_equal hex_str, o.to_s
85
+ end
86
+
87
+ def test_byte_order
88
+ hex_str = '000102030405060708090A0B'
89
+ o = ObjectID.from_string(hex_str)
90
+ assert_equal [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b], o.to_a
91
+ end
92
+
93
+ def test_legacy_byte_order
94
+ hex_str = '000102030405060708090A0B'
95
+ o = ObjectID.from_string_legacy(hex_str)
96
+ assert_equal [0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0b, 0x0a, 0x09, 0x08], o.to_a
97
+ end
98
+
99
+ def test_legacy_string_convert
100
+ l = @o.to_s_legacy
101
+ s = @o.to_s
102
+ assert_equal s, ObjectID.legacy_string_convert(l)
103
+ end
104
+
105
+ end
@@ -12,10 +12,46 @@ class OrderedHashTest < Test::Unit::TestCase
12
12
  @ordered_keys = %w(c a z)
13
13
  end
14
14
 
15
+ def test_initialize
16
+ a = OrderedHash.new
17
+ a['x'] = 1
18
+ a['y'] = 2
19
+
20
+ b = OrderedHash['x' => 1, 'y' => 2]
21
+ assert_equal a, b
22
+ end
23
+
15
24
  def test_empty
16
25
  assert_equal [], OrderedHash.new.keys
17
26
  end
18
27
 
28
+ def test_equality
29
+ a = OrderedHash.new
30
+ a['x'] = 1
31
+ a['y'] = 2
32
+
33
+ b = OrderedHash.new
34
+ b['y'] = 2
35
+ b['x'] = 1
36
+
37
+ c = OrderedHash.new
38
+ c['x'] = 1
39
+ c['y'] = 2
40
+
41
+ d = OrderedHash.new
42
+ d['x'] = 2
43
+ d['y'] = 3
44
+
45
+ e = OrderedHash.new
46
+ e['z'] = 1
47
+ e['y'] = 2
48
+
49
+ assert_equal a, c
50
+ assert_not_equal a, b
51
+ assert_not_equal a, d
52
+ assert_not_equal a, e
53
+ end
54
+
19
55
  def test_order_preserved
20
56
  assert_equal @ordered_keys, @oh.keys
21
57
  end
@@ -36,6 +72,8 @@ class OrderedHashTest < Test::Unit::TestCase
36
72
 
37
73
  @oh['z'] = 42
38
74
  assert_equal keys, @oh.keys
75
+
76
+ assert_equal @oh, @oh.each {|k,v|}
39
77
  end
40
78
 
41
79
  def test_values
@@ -82,4 +120,21 @@ class OrderedHashTest < Test::Unit::TestCase
82
120
  assert_equal '{"c"=>1, "a"=>2, "z"=>3}', @oh.inspect
83
121
  end
84
122
 
123
+ def test_clear
124
+ @oh.clear
125
+ assert @oh.keys.empty?
126
+ end
127
+
128
+ def test_delete
129
+ assert @oh.keys.include?('z')
130
+ @oh.delete('z')
131
+ assert !@oh.keys.include?('z')
132
+ end
133
+
134
+ def test_delete_if
135
+ assert @oh.keys.include?('z')
136
+ @oh.delete_if { |k,v| k == 'z' }
137
+ assert !@oh.keys.include?('z')
138
+ end
139
+
85
140
  end