jonbell-mongo 1.3.1.2

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