jmongo 1.0.3 → 1.1.0

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 (96) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +43 -0
  3. data/Rakefile +72 -0
  4. data/jmongo.gemspec +84 -6
  5. data/lib/jmongo.rb +6 -14
  6. data/lib/jmongo/collection.rb +196 -114
  7. data/lib/jmongo/connection.rb +39 -13
  8. data/lib/jmongo/cursor.rb +161 -63
  9. data/lib/jmongo/db.rb +119 -30
  10. data/lib/jmongo/exceptions.rb +39 -0
  11. data/lib/jmongo/mongo-2.6.5.gb1.jar +0 -0
  12. data/lib/jmongo/mongo/bson.rb +130 -0
  13. data/lib/jmongo/mongo/collection.rb +185 -0
  14. data/lib/jmongo/mongo/connection.rb +45 -0
  15. data/lib/jmongo/mongo/db.rb +31 -0
  16. data/lib/jmongo/mongo/jmongo.rb +44 -0
  17. data/lib/jmongo/mongo/mongo.rb +98 -0
  18. data/lib/jmongo/mongo/ruby_ext.rb +38 -0
  19. data/lib/jmongo/mongo/utils.rb +136 -0
  20. data/lib/jmongo/version.rb +1 -1
  21. data/test-results.txt +98 -0
  22. data/test/auxillary/1.4_features.rb +166 -0
  23. data/test/auxillary/authentication_test.rb +68 -0
  24. data/test/auxillary/autoreconnect_test.rb +41 -0
  25. data/test/auxillary/fork_test.rb +30 -0
  26. data/test/auxillary/repl_set_auth_test.rb +58 -0
  27. data/test/auxillary/slave_connection_test.rb +36 -0
  28. data/test/auxillary/threaded_authentication_test.rb +101 -0
  29. data/test/bson/binary_test.rb +15 -0
  30. data/test/bson/bson_test.rb +657 -0
  31. data/test/bson/byte_buffer_test.rb +208 -0
  32. data/test/bson/hash_with_indifferent_access_test.rb +38 -0
  33. data/test/bson/json_test.rb +17 -0
  34. data/test/bson/object_id_test.rb +138 -0
  35. data/test/bson/ordered_hash_test.rb +245 -0
  36. data/test/bson/test_helper.rb +46 -0
  37. data/test/bson/timestamp_test.rb +46 -0
  38. data/test/collection_test.rb +933 -0
  39. data/test/connection_test.rb +325 -0
  40. data/test/conversions_test.rb +121 -0
  41. data/test/cursor_fail_test.rb +75 -0
  42. data/test/cursor_message_test.rb +43 -0
  43. data/test/cursor_test.rb +547 -0
  44. data/test/data/empty_data +0 -0
  45. data/test/data/sample_data +0 -0
  46. data/test/data/sample_file.pdf +0 -0
  47. data/test/data/small_data.txt +1 -0
  48. data/test/db_api_test.rb +739 -0
  49. data/test/db_connection_test.rb +15 -0
  50. data/test/db_test.rb +325 -0
  51. data/test/grid_file_system_test.rb +260 -0
  52. data/test/grid_io_test.rb +210 -0
  53. data/test/grid_test.rb +259 -0
  54. data/test/load/thin/config.ru +6 -0
  55. data/test/load/thin/config.yml.template +6 -0
  56. data/test/load/thin/load.rb +24 -0
  57. data/test/load/unicorn/config.ru +6 -0
  58. data/test/load/unicorn/load.rb +23 -0
  59. data/test/load/unicorn/unicorn.rb.template +29 -0
  60. data/test/replica_sets/connect_test.rb +111 -0
  61. data/test/replica_sets/connection_string_test.rb +29 -0
  62. data/test/replica_sets/count_test.rb +36 -0
  63. data/test/replica_sets/insert_test.rb +54 -0
  64. data/test/replica_sets/pooled_insert_test.rb +58 -0
  65. data/test/replica_sets/query_secondaries.rb +109 -0
  66. data/test/replica_sets/query_test.rb +52 -0
  67. data/test/replica_sets/read_preference_test.rb +43 -0
  68. data/test/replica_sets/refresh_test.rb +123 -0
  69. data/test/replica_sets/replication_ack_test.rb +71 -0
  70. data/test/replica_sets/rs_test_helper.rb +27 -0
  71. data/test/safe_test.rb +68 -0
  72. data/test/support/hash_with_indifferent_access.rb +186 -0
  73. data/test/support/keys.rb +45 -0
  74. data/test/support_test.rb +19 -0
  75. data/test/test_helper.rb +111 -0
  76. data/test/threading/threading_with_large_pool_test.rb +90 -0
  77. data/test/threading_test.rb +88 -0
  78. data/test/tools/auth_repl_set_manager.rb +14 -0
  79. data/test/tools/keyfile.txt +1 -0
  80. data/test/tools/repl_set_manager.rb +377 -0
  81. data/test/unit/collection_test.rb +128 -0
  82. data/test/unit/connection_test.rb +85 -0
  83. data/test/unit/cursor_test.rb +127 -0
  84. data/test/unit/db_test.rb +96 -0
  85. data/test/unit/grid_test.rb +51 -0
  86. data/test/unit/node_test.rb +73 -0
  87. data/test/unit/pool_manager_test.rb +47 -0
  88. data/test/unit/pool_test.rb +9 -0
  89. data/test/unit/read_test.rb +101 -0
  90. data/test/unit/safe_test.rb +125 -0
  91. data/test/uri_test.rb +92 -0
  92. metadata +170 -99
  93. data/lib/jmongo/ajrb.rb +0 -189
  94. data/lib/jmongo/jmongo_jext.rb +0 -302
  95. data/lib/jmongo/mongo-2.6.3.jar +0 -0
  96. data/lib/jmongo/utils.rb +0 -61
@@ -0,0 +1,15 @@
1
+ require './test/test_helper'
2
+
3
+ class DBConnectionTest < Test::Unit::TestCase
4
+
5
+ include Mongo
6
+
7
+ def test_no_exceptions
8
+ host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
9
+ port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
10
+ db = Connection.new(host, port).db(MONGO_TEST_DB)
11
+ coll = db.collection('test')
12
+ coll.remove
13
+ db.get_last_error
14
+ end
15
+ end
@@ -0,0 +1,325 @@
1
+ require './test/test_helper'
2
+ require 'digest/md5'
3
+ require 'stringio'
4
+ require 'logger'
5
+
6
+ class TestPKFactory
7
+ def create_pk(row)
8
+ row['_id'] ||= BSON::ObjectId.new
9
+ row
10
+ end
11
+ end
12
+
13
+ class DBTest < Test::Unit::TestCase
14
+
15
+ include Mongo
16
+
17
+ @@conn = standard_connection
18
+ @@db = @@conn.db(MONGO_TEST_DB)
19
+ @@users = @@db.collection('system.users')
20
+ @@version = @@conn.server_version
21
+
22
+ def test_close
23
+ @@conn.close
24
+ assert !@@conn.connected?
25
+ begin
26
+ @@db.collection('test').insert('a' => 1)
27
+ fail "expected 'NilClass' exception"
28
+ rescue => ex
29
+ assert_match(/NilClass/, ex.to_s)
30
+ ensure
31
+ @@db = standard_connection.db(MONGO_TEST_DB)
32
+ @@users = @@db.collection('system.users')
33
+ end
34
+ end
35
+
36
+ def test_create_collection
37
+ col = @@db.create_collection('foo')
38
+ assert_equal @@db['foo'].name, col.name
39
+
40
+ col = @@db.create_collection(:foo)
41
+ assert_equal @@db['foo'].name, col.name
42
+
43
+ @@db.drop_collection('foo')
44
+ end
45
+
46
+ def test_get_and_drop_collection
47
+ db = @@conn.db(MONGO_TEST_DB, :strict => true)
48
+ db.create_collection('foo')
49
+ assert db.collection('foo')
50
+ assert db.drop_collection('foo')
51
+
52
+ db.create_collection(:foo)
53
+ assert db.collection(:foo)
54
+ assert db.drop_collection(:foo)
55
+ end
56
+
57
+ def test_logger
58
+ output = StringIO.new
59
+ logger = Logger.new(output)
60
+ logger.level = Logger::DEBUG
61
+ conn = standard_connection(:logger => logger)
62
+ assert_equal logger, conn.logger
63
+
64
+ conn.logger.debug 'testing'
65
+ assert output.string.include?('testing')
66
+ end
67
+
68
+ def test_full_coll_name
69
+ coll = @@db.collection('test')
70
+ assert_equal "#{MONGO_TEST_DB}.test", @@db.full_collection_name(coll.name)
71
+ end
72
+
73
+ def test_collection_names
74
+ @@db.collection("test").insert("foo" => 5)
75
+ @@db.collection("test.mike").insert("bar" => 0)
76
+
77
+ colls = @@db.collection_names()
78
+ assert colls.include?("test")
79
+ assert colls.include?("test.mike")
80
+ colls.each { |name|
81
+ assert !name.include?("$")
82
+ }
83
+ end
84
+
85
+ def test_collections
86
+ @@db.collection("test.durran").insert("foo" => 5)
87
+ @@db.collection("test.les").insert("bar" => 0)
88
+
89
+ colls = @@db.collections()
90
+ assert_not_nil colls.select { |coll| coll.name == "test.durran" }
91
+ assert_not_nil colls.select { |coll| coll.name == "test.les" }
92
+ assert_equal [], colls.select { |coll| coll.name == "does_not_exist" }
93
+
94
+ assert_kind_of Collection, colls[0]
95
+ end
96
+
97
+ def test_pk_factory
98
+ db = standard_connection.db(MONGO_TEST_DB, :pk => TestPKFactory.new)
99
+ coll = db.collection('test')
100
+ coll.remove
101
+
102
+ insert_id = coll.insert('name' => 'Fred', 'age' => 42)
103
+ # new id gets added to returned object
104
+ row = coll.find_one({'name' => 'Fred'})
105
+ oid = row['_id']
106
+ assert_not_nil oid
107
+ assert_equal insert_id, oid
108
+
109
+ oid = BSON::ObjectId.new
110
+ data = {'_id' => oid, 'name' => 'Barney', 'age' => 41}
111
+ coll.insert(data)
112
+ row = coll.find_one({'name' => data['name']})
113
+ db_oid = row['_id']
114
+ assert_equal oid, db_oid
115
+ assert_equal data, row
116
+
117
+ coll.remove
118
+ end
119
+
120
+ def test_pk_factory_reset
121
+ conn = standard_connection
122
+ db = conn.db(MONGO_TEST_DB)
123
+ db.pk_factory = Object.new # first time
124
+ begin
125
+ db.pk_factory = Object.new
126
+ fail "error: expected exception"
127
+ rescue => ex
128
+ assert_match(/Cannot change/, ex.to_s)
129
+ ensure
130
+ conn.close
131
+ end
132
+ end
133
+
134
+ def test_authenticate
135
+ @@db.add_user('spongebob', 'squarepants')
136
+ assert_raise Mongo::AuthenticationError do
137
+ assert !@@db.authenticate('nobody', 'nopassword')
138
+ end
139
+ assert_raise Mongo::AuthenticationError do
140
+ assert !@@db.authenticate('spongebob' , 'squareliederhosen')
141
+ end
142
+ assert @@db.authenticate('spongebob', 'squarepants')
143
+ @@db.logout
144
+ @@db.remove_user('spongebob')
145
+ end
146
+
147
+ def test_authenticate_with_special_characters
148
+ assert @@db.add_user('foo:bar', '@foo')
149
+ assert @@db.authenticate('foo:bar', '@foo')
150
+ @@db.logout
151
+ @@db.remove_user('foo:bar')
152
+ end
153
+
154
+ def test_authenticate_with_connection_uri
155
+ @@db.add_user('spongebob', 'squarepants')
156
+ assert Mongo::Connection.from_uri("mongodb://spongebob:squarepants@#{host_port}/#{@@db.name}")
157
+
158
+ assert_raise Mongo::AuthenticationError do
159
+ con = Mongo::Connection.from_uri("mongodb://wrong:info@#{host_port}/#{@@db.name}")
160
+ con['test']['foo'].find_one
161
+ end
162
+ end
163
+
164
+ def test_logout
165
+ assert @@db.logout
166
+ end
167
+
168
+ def test_command
169
+ assert_raise OperationFailure do
170
+ @@db.command({:non_command => 1}, :check_response => true)
171
+ end
172
+
173
+ result = @@db.command({:non_command => 1}, :check_response => false)
174
+ assert !Mongo::Support.ok?(result)
175
+ end
176
+
177
+ def test_error
178
+ @@db.reset_error_history
179
+ assert_nil @@db.get_last_error['err']
180
+ assert !@@db.error?
181
+ assert_nil @@db.previous_error
182
+
183
+ @@db.command({:forceerror => 1}, :check_response => false)
184
+ assert @@db.error?
185
+ assert_not_nil @@db.get_last_error['err']
186
+ assert_not_nil @@db.previous_error
187
+
188
+ @@db.command({:forceerror => 1}, :check_response => false)
189
+ assert @@db.error?
190
+ assert @@db.get_last_error['err']
191
+ prev_error = @@db.previous_error
192
+ assert_equal 1, prev_error['nPrev']
193
+ assert_equal prev_error["err"], @@db.get_last_error['err']
194
+
195
+ @@db.collection('test').find_one
196
+ assert_nil @@db.get_last_error['err']
197
+ assert !@@db.error?
198
+ assert @@db.previous_error
199
+ assert_equal 2, @@db.previous_error['nPrev']
200
+
201
+ @@db.reset_error_history
202
+ assert_nil @@db.get_last_error['err']
203
+ assert !@@db.error?
204
+ assert_nil @@db.previous_error
205
+ end
206
+
207
+ def test_check_command_response
208
+ command = {:forceerror => 1}
209
+ raised = false
210
+ begin
211
+ @@db.command(command)
212
+ rescue => ex
213
+ raised = true
214
+ assert ex.message.include?("forced error"),
215
+ "error message does not contain 'forced error'"
216
+ assert_equal 10038, ex.error_code
217
+ assert_equal 10038, ex.result['assertionCode']
218
+ ensure
219
+ assert raised, "No assertion raised!"
220
+ end
221
+ end
222
+
223
+ def test_last_status
224
+ @@db['test'].remove
225
+ @@db['test'].save("i" => 1)
226
+
227
+ @@db['test'].update({"i" => 1}, {"$set" => {"i" => 2}})
228
+ assert @@db.get_last_error()["updatedExisting"]
229
+
230
+ @@db['test'].update({"i" => 1}, {"$set" => {"i" => 500}})
231
+ assert !@@db.get_last_error()["updatedExisting"]
232
+ end
233
+
234
+ def test_text_port_number_raises_no_errors
235
+ conn = standard_connection
236
+ db = conn[MONGO_TEST_DB]
237
+ db.collection('users').remove
238
+ end
239
+
240
+ def test_user_management
241
+ @@db.add_user("bob", "secret")
242
+ assert @@db.authenticate("bob", "secret")
243
+ @@db.logout
244
+ assert @@db.remove_user("bob")
245
+ assert_raise Mongo::AuthenticationError do
246
+ @@db.authenticate("bob", "secret")
247
+ end
248
+ end
249
+
250
+ def test_remove_non_existant_user
251
+ assert !@@db.remove_user("joe")
252
+ end
253
+
254
+ def test_stored_function_management
255
+ @@db.add_stored_function("sum", "function (x, y) { return x + y; }")
256
+ assert_equal @@db.eval("return sum(2,3);"), 5
257
+ assert @@db.remove_stored_function("sum")
258
+ assert_raise OperationFailure do
259
+ @@db.eval("return sum(2,3);")
260
+ end
261
+ end
262
+
263
+ def test_eval
264
+ @@db.eval("db.system.save({_id:'hello', value: function() { print('hello'); } })")
265
+ assert_equal 'hello', @@db['system'].find_one['_id']
266
+ end
267
+
268
+ if @@version >= "1.3.5"
269
+ def test_db_stats
270
+ stats = @@db.stats
271
+ assert stats.has_key?('collections')
272
+ assert stats.has_key?('dataSize')
273
+ end
274
+ end
275
+
276
+ context "database profiling" do
277
+ setup do
278
+ @db = @@conn[MONGO_TEST_DB]
279
+ @coll = @db['test']
280
+ @coll.remove
281
+ @r1 = @coll.insert('a' => 1) # collection not created until it's used
282
+ end
283
+
284
+ should "set default profiling level" do
285
+ assert_equal :off, @db.profiling_level
286
+ end
287
+
288
+ should "change profiling level" do
289
+ @db.profiling_level = :slow_only
290
+ assert_equal :slow_only, @db.profiling_level
291
+ @db.profiling_level = :off
292
+ assert_equal :off, @db.profiling_level
293
+ @db.profiling_level = :all
294
+ assert_equal :all, @db.profiling_level
295
+ begin
296
+ @db.profiling_level = :medium
297
+ fail "shouldn't be able to do this"
298
+ rescue
299
+ end
300
+ end
301
+
302
+ should "return profiling info" do
303
+ @db.profiling_level = :all
304
+ @coll.find()
305
+ @db.profiling_level = :off
306
+
307
+ info = @db.profiling_info
308
+ assert_kind_of Array, info
309
+ assert info.length >= 1
310
+ first = info.first
311
+ assert_kind_of Time, first['ts']
312
+ assert_kind_of Numeric, first['millis']
313
+ end
314
+
315
+ should "validate collection" do
316
+ doc = @db.validate_collection(@coll.name)
317
+ if @@version >= "1.9.1"
318
+ assert doc['valid']
319
+ else
320
+ assert doc['result']
321
+ end
322
+ end
323
+
324
+ end
325
+ end
@@ -0,0 +1,260 @@
1
+ __END__
2
+ require './test/test_helper'
3
+
4
+ class GridFileSystemTest < Test::Unit::TestCase
5
+ context "GridFileSystem:" do
6
+ setup do
7
+ @con = standard_connection
8
+ @db = @con.db(MONGO_TEST_DB)
9
+ end
10
+
11
+ teardown do
12
+ @db.drop_collection('fs.files')
13
+ @db.drop_collection('fs.chunks')
14
+ end
15
+
16
+ context "Initialization" do
17
+ setup do
18
+ @chunks_data = "CHUNKS" * 50000
19
+ @grid = GridFileSystem.new(@db)
20
+ @opts = {:safe => true}
21
+ @original_opts = @opts.dup
22
+ @grid.open('sample.file', 'w', @opts) do |f|
23
+ f.write @chunks_data
24
+ end
25
+ end
26
+
27
+ should "not modify original opts" do
28
+ assert_equal @original_opts, @opts
29
+ end
30
+ end
31
+
32
+ context "When reading:" do
33
+ setup do
34
+ @chunks_data = "CHUNKS" * 50000
35
+ @grid = GridFileSystem.new(@db)
36
+ @grid.open('sample.file', 'w') do |f|
37
+ f.write @chunks_data
38
+ end
39
+
40
+ @grid = GridFileSystem.new(@db)
41
+ end
42
+
43
+ should "return existence of the file" do
44
+ file = @grid.exist?(:filename => 'sample.file')
45
+ assert_equal 'sample.file', file['filename']
46
+ end
47
+
48
+ should "return nil if the file doesn't exist" do
49
+ assert_nil @grid.exist?(:filename => 'foo.file')
50
+ end
51
+
52
+ should "read sample data" do
53
+ data = @grid.open('sample.file', 'r') { |f| f.read }
54
+ assert_equal data.length, @chunks_data.length
55
+ end
56
+
57
+ should "have a unique index on chunks" do
58
+ assert @db['fs.chunks'].index_information['files_id_1_n_1']['unique']
59
+ end
60
+
61
+ should "have an index on filename" do
62
+ assert @db['fs.files'].index_information['filename_1_uploadDate_-1']
63
+ end
64
+
65
+ should "return an empty string if length is zero" do
66
+ data = @grid.open('sample.file', 'r') { |f| f.read(0) }
67
+ assert_equal '', data
68
+ end
69
+
70
+ should "return the first n bytes" do
71
+ data = @grid.open('sample.file', 'r') {|f| f.read(288888) }
72
+ assert_equal 288888, data.length
73
+ assert_equal @chunks_data[0...288888], data
74
+ end
75
+
76
+ should "return the first n bytes even with an offset" do
77
+ data = @grid.open('sample.file', 'r') do |f|
78
+ f.seek(1000)
79
+ f.read(288888)
80
+ end
81
+ assert_equal 288888, data.length
82
+ assert_equal @chunks_data[1000...289888], data
83
+ end
84
+ end
85
+
86
+ context "When writing:" do
87
+ setup do
88
+ @data = "BYTES" * 50
89
+ @grid = GridFileSystem.new(@db)
90
+ @grid.open('sample', 'w') do |f|
91
+ f.write @data
92
+ end
93
+ end
94
+
95
+ should "read sample data" do
96
+ data = @grid.open('sample', 'r') { |f| f.read }
97
+ assert_equal data.length, @data.length
98
+ end
99
+
100
+ should "return the total number of bytes written" do
101
+ data = 'a' * 300000
102
+ assert_equal 300000, @grid.open('sample', 'w') {|f| f.write(data) }
103
+ end
104
+
105
+ should "more read sample data" do
106
+ data = @grid.open('sample', 'r') { |f| f.read }
107
+ assert_equal data.length, @data.length
108
+ end
109
+
110
+ should "raise exception if file not found" do
111
+ assert_raise GridFileNotFound do
112
+ @grid.open('io', 'r') { |f| f.write('hello') }
113
+ end
114
+ end
115
+
116
+ should "raise exception if not opened for write" do
117
+ assert_raise GridError do
118
+ @grid.open('sample', 'r') { |f| f.write('hello') }
119
+ end
120
+ end
121
+
122
+ context "and when overwriting the file" do
123
+ setup do
124
+ @old = @grid.open('sample', 'r')
125
+
126
+ @new_data = "DATA" * 10
127
+ sleep(2)
128
+ @grid.open('sample', 'w') do |f|
129
+ f.write @new_data
130
+ end
131
+
132
+ @new = @grid.open('sample', 'r')
133
+ end
134
+
135
+ should "have a newer upload date" do
136
+ assert @new.upload_date > @old.upload_date, "New data is not greater than old date."
137
+ end
138
+
139
+ should "have a different files_id" do
140
+ assert_not_equal @new.files_id, @old.files_id
141
+ end
142
+
143
+ should "contain the new data" do
144
+ assert_equal @new_data, @new.read, "Expected DATA"
145
+ end
146
+
147
+ context "and on a second overwrite" do
148
+ setup do
149
+ sleep(2)
150
+ @new_data = "NEW" * 1000
151
+ @grid.open('sample', 'w') do |f|
152
+ f.write @new_data
153
+ end
154
+
155
+ @ids = @db['fs.files'].find({'filename' => 'sample'}).map {|file| file['_id']}
156
+ end
157
+
158
+ should "write a third version of the file" do
159
+ assert_equal 3, @db['fs.files'].find({'filename' => 'sample'}).count
160
+ assert_equal 3, @db['fs.chunks'].find({'files_id' => {'$in' => @ids}}).count
161
+ end
162
+
163
+ should "remove all versions and their data on delete" do
164
+ @grid.delete('sample')
165
+ assert_equal 0, @db['fs.files'].find({'filename' => 'sample'}).count
166
+ assert_equal 0, @db['fs.chunks'].find({'files_id' => {'$in' => @ids}}).count
167
+ end
168
+
169
+ should "delete old versions on write with :delete_old is passed in" do
170
+ @grid.open('sample', 'w', :delete_old => true) do |f|
171
+ f.write @new_data
172
+ end
173
+ @new_ids = @db['fs.files'].find({'filename' => 'sample'}).map {|file| file['_id']}
174
+ assert_equal 1, @new_ids.length
175
+ id = @new_ids.first
176
+ assert !@ids.include?(id)
177
+ assert_equal 1, @db['fs.files'].find({'filename' => 'sample'}).count
178
+ assert_equal 1, @db['fs.chunks'].find({'files_id' => id}).count
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ context "When writing chunks:" do
185
+ setup do
186
+ data = "B" * 50000
187
+ @grid = GridFileSystem.new(@db)
188
+ @grid.open('sample', 'w', :chunk_size => 1000) do |f|
189
+ f.write data
190
+ end
191
+ end
192
+
193
+ should "write the correct number of chunks" do
194
+ file = @db['fs.files'].find_one({:filename => 'sample'})
195
+ chunks = @db['fs.chunks'].find({'files_id' => file['_id']}).to_a
196
+ assert_equal 50, chunks.length
197
+ end
198
+ end
199
+
200
+ context "Positioning:" do
201
+ setup do
202
+ data = 'hello, world' + '1' * 5000 + 'goodbye!' + '2' * 1000 + '!'
203
+ @grid = GridFileSystem.new(@db)
204
+ @grid.open('hello', 'w', :chunk_size => 1000) do |f|
205
+ f.write data
206
+ end
207
+ end
208
+
209
+ should "seek within chunks" do
210
+ @grid.open('hello', 'r') do |f|
211
+ f.seek(0)
212
+ assert_equal 'h', f.read(1)
213
+ f.seek(7)
214
+ assert_equal 'w', f.read(1)
215
+ f.seek(4)
216
+ assert_equal 'o', f.read(1)
217
+ f.seek(0)
218
+ f.seek(7, IO::SEEK_CUR)
219
+ assert_equal 'w', f.read(1)
220
+ f.seek(-2, IO::SEEK_CUR)
221
+ assert_equal ' ', f.read(1)
222
+ f.seek(-4, IO::SEEK_CUR)
223
+ assert_equal 'l', f.read(1)
224
+ f.seek(3, IO::SEEK_CUR)
225
+ assert_equal 'w', f.read(1)
226
+ end
227
+ end
228
+
229
+ should "seek between chunks" do
230
+ @grid.open('hello', 'r') do |f|
231
+ f.seek(1000)
232
+ assert_equal '11111', f.read(5)
233
+
234
+ f.seek(5009)
235
+ assert_equal '111goodbye!222', f.read(14)
236
+
237
+ f.seek(-1, IO::SEEK_END)
238
+ assert_equal '!', f.read(1)
239
+ f.seek(-6, IO::SEEK_END)
240
+ assert_equal '2', f.read(1)
241
+ end
242
+ end
243
+
244
+ should "tell the current position" do
245
+ @grid.open('hello', 'r') do |f|
246
+ assert_equal 0, f.tell
247
+
248
+ f.seek(999)
249
+ assert_equal 999, f.tell
250
+ end
251
+ end
252
+
253
+ should "seek only in read mode" do
254
+ assert_raise GridError do
255
+ @grid.open('hello', 'w') {|f| f.seek(0) }
256
+ end
257
+ end
258
+ end
259
+ end
260
+ end