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.
- data/Gemfile +8 -0
- data/Gemfile.lock +43 -0
- data/Rakefile +72 -0
- data/jmongo.gemspec +84 -6
- data/lib/jmongo.rb +6 -14
- data/lib/jmongo/collection.rb +196 -114
- data/lib/jmongo/connection.rb +39 -13
- data/lib/jmongo/cursor.rb +161 -63
- data/lib/jmongo/db.rb +119 -30
- data/lib/jmongo/exceptions.rb +39 -0
- data/lib/jmongo/mongo-2.6.5.gb1.jar +0 -0
- data/lib/jmongo/mongo/bson.rb +130 -0
- data/lib/jmongo/mongo/collection.rb +185 -0
- data/lib/jmongo/mongo/connection.rb +45 -0
- data/lib/jmongo/mongo/db.rb +31 -0
- data/lib/jmongo/mongo/jmongo.rb +44 -0
- data/lib/jmongo/mongo/mongo.rb +98 -0
- data/lib/jmongo/mongo/ruby_ext.rb +38 -0
- data/lib/jmongo/mongo/utils.rb +136 -0
- data/lib/jmongo/version.rb +1 -1
- data/test-results.txt +98 -0
- data/test/auxillary/1.4_features.rb +166 -0
- data/test/auxillary/authentication_test.rb +68 -0
- data/test/auxillary/autoreconnect_test.rb +41 -0
- data/test/auxillary/fork_test.rb +30 -0
- data/test/auxillary/repl_set_auth_test.rb +58 -0
- data/test/auxillary/slave_connection_test.rb +36 -0
- data/test/auxillary/threaded_authentication_test.rb +101 -0
- data/test/bson/binary_test.rb +15 -0
- data/test/bson/bson_test.rb +657 -0
- data/test/bson/byte_buffer_test.rb +208 -0
- data/test/bson/hash_with_indifferent_access_test.rb +38 -0
- data/test/bson/json_test.rb +17 -0
- data/test/bson/object_id_test.rb +138 -0
- data/test/bson/ordered_hash_test.rb +245 -0
- data/test/bson/test_helper.rb +46 -0
- data/test/bson/timestamp_test.rb +46 -0
- data/test/collection_test.rb +933 -0
- data/test/connection_test.rb +325 -0
- data/test/conversions_test.rb +121 -0
- data/test/cursor_fail_test.rb +75 -0
- data/test/cursor_message_test.rb +43 -0
- data/test/cursor_test.rb +547 -0
- data/test/data/empty_data +0 -0
- data/test/data/sample_data +0 -0
- data/test/data/sample_file.pdf +0 -0
- data/test/data/small_data.txt +1 -0
- data/test/db_api_test.rb +739 -0
- data/test/db_connection_test.rb +15 -0
- data/test/db_test.rb +325 -0
- data/test/grid_file_system_test.rb +260 -0
- data/test/grid_io_test.rb +210 -0
- data/test/grid_test.rb +259 -0
- data/test/load/thin/config.ru +6 -0
- data/test/load/thin/config.yml.template +6 -0
- data/test/load/thin/load.rb +24 -0
- data/test/load/unicorn/config.ru +6 -0
- data/test/load/unicorn/load.rb +23 -0
- data/test/load/unicorn/unicorn.rb.template +29 -0
- data/test/replica_sets/connect_test.rb +111 -0
- data/test/replica_sets/connection_string_test.rb +29 -0
- data/test/replica_sets/count_test.rb +36 -0
- data/test/replica_sets/insert_test.rb +54 -0
- data/test/replica_sets/pooled_insert_test.rb +58 -0
- data/test/replica_sets/query_secondaries.rb +109 -0
- data/test/replica_sets/query_test.rb +52 -0
- data/test/replica_sets/read_preference_test.rb +43 -0
- data/test/replica_sets/refresh_test.rb +123 -0
- data/test/replica_sets/replication_ack_test.rb +71 -0
- data/test/replica_sets/rs_test_helper.rb +27 -0
- data/test/safe_test.rb +68 -0
- data/test/support/hash_with_indifferent_access.rb +186 -0
- data/test/support/keys.rb +45 -0
- data/test/support_test.rb +19 -0
- data/test/test_helper.rb +111 -0
- data/test/threading/threading_with_large_pool_test.rb +90 -0
- data/test/threading_test.rb +88 -0
- data/test/tools/auth_repl_set_manager.rb +14 -0
- data/test/tools/keyfile.txt +1 -0
- data/test/tools/repl_set_manager.rb +377 -0
- data/test/unit/collection_test.rb +128 -0
- data/test/unit/connection_test.rb +85 -0
- data/test/unit/cursor_test.rb +127 -0
- data/test/unit/db_test.rb +96 -0
- data/test/unit/grid_test.rb +51 -0
- data/test/unit/node_test.rb +73 -0
- data/test/unit/pool_manager_test.rb +47 -0
- data/test/unit/pool_test.rb +9 -0
- data/test/unit/read_test.rb +101 -0
- data/test/unit/safe_test.rb +125 -0
- data/test/uri_test.rb +92 -0
- metadata +170 -99
- data/lib/jmongo/ajrb.rb +0 -189
- data/lib/jmongo/jmongo_jext.rb +0 -302
- data/lib/jmongo/mongo-2.6.3.jar +0 -0
- 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
|
data/test/db_test.rb
ADDED
@@ -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
|