/
grid_file_system_test.rb
273 lines (231 loc) · 7.98 KB
/
grid_file_system_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
require 'test_helper'
class GridFileSystemTest < Test::Unit::TestCase
context "GridFileSystem:" do
setup do
@con = standard_connection
@db = @con.db(MONGO_TEST_DB)
end
teardown do
@db.drop_collection('fs.files')
@db.drop_collection('fs.chunks')
end
context "Initialization" do
setup do
@chunks_data = "CHUNKS" * 50000
@grid = GridFileSystem.new(@db)
@opts = {:safe => true}
@original_opts = @opts.dup
@grid.open('sample.file', 'w', @opts) do |f|
f.write @chunks_data
end
end
should "not modify original opts" do
assert_equal @original_opts, @opts
end
end
context "When reading:" do
setup do
@chunks_data = "CHUNKS" * 50000
@grid = GridFileSystem.new(@db)
@grid.open('sample.file', 'w') do |f|
f.write @chunks_data
end
@grid = GridFileSystem.new(@db)
end
should "return existence of the file" do
file = @grid.exist?(:filename => 'sample.file')
assert_equal 'sample.file', file['filename']
end
should "return nil if the file doesn't exist" do
assert_nil @grid.exist?(:filename => 'foo.file')
end
should "read sample data" do
data = @grid.open('sample.file', 'r') { |f| f.read }
assert_equal data.length, @chunks_data.length
end
should "have a unique index on chunks" do
assert @db['fs.chunks'].index_information['files_id_1_n_1']['unique']
end
should "have an index on filename" do
assert @db['fs.files'].index_information['filename_1_uploadDate_-1']
end
should "return an empty string if length is zero" do
data = @grid.open('sample.file', 'r') { |f| f.read(0) }
assert_equal '', data
end
should "return the first n bytes" do
data = @grid.open('sample.file', 'r') {|f| f.read(288888) }
assert_equal 288888, data.length
assert_equal @chunks_data[0...288888], data
end
should "return the first n bytes even with an offset" do
data = @grid.open('sample.file', 'r') do |f|
f.seek(1000)
f.read(288888)
end
assert_equal 288888, data.length
assert_equal @chunks_data[1000...289888], data
end
end
context "When writing:" do
setup do
@data = "BYTES" * 50
@grid = GridFileSystem.new(@db)
@grid.open('sample', 'w') do |f|
f.write @data
end
end
should "read sample data" do
data = @grid.open('sample', 'r') { |f| f.read }
assert_equal data.length, @data.length
end
should "return the total number of bytes written" do
data = 'a' * 300000
assert_equal 300000, @grid.open('sample', 'w') {|f| f.write(data) }
end
should "more read sample data" do
data = @grid.open('sample', 'r') { |f| f.read }
assert_equal data.length, @data.length
end
should "raise exception if file not found" do
assert_raise GridFileNotFound do
@grid.open('io', 'r') { |f| f.write('hello') }
end
end
should "raise exception if not opened for write" do
assert_raise GridError do
@grid.open('sample', 'r') { |f| f.write('hello') }
end
end
context "and when overwriting the file" do
setup do
@old = @grid.open('sample', 'r')
@new_data = "DATA" * 10
sleep(2)
@grid.open('sample', 'w') do |f|
f.write @new_data
end
@new = @grid.open('sample', 'r')
end
should "have a newer upload date" do
assert @new.upload_date > @old.upload_date, "New data is not greater than old date."
end
should "have a different files_id" do
assert_not_equal @new.files_id, @old.files_id
end
should "contain the new data" do
assert_equal @new_data, @new.read, "Expected DATA"
end
context "and on a second overwrite" do
setup do
sleep(2)
@new_data = "NEW" * 1000
@grid.open('sample', 'w') do |f|
f.write @new_data
end
@ids = @db['fs.files'].find({'filename' => 'sample'}).map {|file| file['_id']}
end
should "write a third version of the file" do
assert_equal 3, @db['fs.files'].find({'filename' => 'sample'}).count
assert_equal 3, @db['fs.chunks'].find({'files_id' => {'$in' => @ids}}).count
end
should "remove all versions and their data on delete" do
@grid.delete('sample')
assert_equal 0, @db['fs.files'].find({'filename' => 'sample'}).count
assert_equal 0, @db['fs.chunks'].find({'files_id' => {'$in' => @ids}}).count
end
should "delete all versions which exceed the number of versions to keep specified by the option :versions" do
@versions = 1 + rand(4-1)
@grid.open('sample', 'w', :versions => @versions) do |f|
f.write @new_data
end
@new_ids = @db['fs.files'].find({'filename' => 'sample'}).map {|file| file['_id']}
assert_equal @versions, @new_ids.length
id = @new_ids.first
assert !@ids.include?(id)
assert_equal @versions, @db['fs.files'].find({'filename' => 'sample'}).count
end
should "delete old versions on write with :delete_old is passed in" do
@grid.open('sample', 'w', :delete_old => true) do |f|
f.write @new_data
end
@new_ids = @db['fs.files'].find({'filename' => 'sample'}).map {|file| file['_id']}
assert_equal 1, @new_ids.length
id = @new_ids.first
assert !@ids.include?(id)
assert_equal 1, @db['fs.files'].find({'filename' => 'sample'}).count
assert_equal 1, @db['fs.chunks'].find({'files_id' => id}).count
end
end
end
end
context "When writing chunks:" do
setup do
data = "B" * 50000
@grid = GridFileSystem.new(@db)
@grid.open('sample', 'w', :chunk_size => 1000) do |f|
f.write data
end
end
should "write the correct number of chunks" do
file = @db['fs.files'].find_one({:filename => 'sample'})
chunks = @db['fs.chunks'].find({'files_id' => file['_id']}).to_a
assert_equal 50, chunks.length
end
end
context "Positioning:" do
setup do
data = 'hello, world' + '1' * 5000 + 'goodbye!' + '2' * 1000 + '!'
@grid = GridFileSystem.new(@db)
@grid.open('hello', 'w', :chunk_size => 1000) do |f|
f.write data
end
end
should "seek within chunks" do
@grid.open('hello', 'r') do |f|
f.seek(0)
assert_equal 'h', f.read(1)
f.seek(7)
assert_equal 'w', f.read(1)
f.seek(4)
assert_equal 'o', f.read(1)
f.seek(0)
f.seek(7, IO::SEEK_CUR)
assert_equal 'w', f.read(1)
f.seek(-2, IO::SEEK_CUR)
assert_equal ' ', f.read(1)
f.seek(-4, IO::SEEK_CUR)
assert_equal 'l', f.read(1)
f.seek(3, IO::SEEK_CUR)
assert_equal 'w', f.read(1)
end
end
should "seek between chunks" do
@grid.open('hello', 'r') do |f|
f.seek(1000)
assert_equal '11111', f.read(5)
f.seek(5009)
assert_equal '111goodbye!222', f.read(14)
f.seek(-1, IO::SEEK_END)
assert_equal '!', f.read(1)
f.seek(-6, IO::SEEK_END)
assert_equal '2', f.read(1)
end
end
should "tell the current position" do
@grid.open('hello', 'r') do |f|
assert_equal 0, f.tell
f.seek(999)
assert_equal 999, f.tell
end
end
should "seek only in read mode" do
assert_raise GridError do
silently do
@grid.open('hello', 'w') { |f| f.seek(0) }
end
end
end
end
end
end