1 # -*- encoding: binary -*-
7 class TestMogileFS__MogileFS < TestMogileFS
11 @klass = MogileFS::MogileFS
16 assert_equal 'test', @client.domain
18 assert_raises ArgumentError do
19 MogileFS::MogileFS.new :hosts => ['kaa:6001']
23 def test_get_file_data_http
24 tmp = Tempfile.new('accept')
25 accept = File.open(tmp.path, "ab")
26 svr = Proc.new do |serv, port|
27 client, client_addr = serv.accept
29 readed = client.recv(4096, 0)
31 %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
33 client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
36 t1 = TempServer.new(svr)
37 t2 = TempServer.new(svr)
38 path1 = "http://127.0.0.1:#{t1.port}/dev1/0/000/000/0000000062.fid"
39 path2 = "http://127.0.0.1:#{t2.port}/dev2/0/000/000/0000000062.fid"
41 @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
43 assert_equal 'data!', @client.get_file_data('key')
44 assert_equal 1, accept.stat.size
46 TempServer.destroy_all!
49 def test_get_file_data_http_not_found_failover
50 tmp = Tempfile.new('accept')
51 accept = File.open(tmp.path, 'ab')
52 svr1 = Proc.new do |serv, port|
53 client, client_addr = serv.accept
55 readed = client.recv(4096, 0)
57 %r{\AGET /dev1/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
59 client.send("HTTP/1.0 404 Not Found\r\n\r\ndata!", 0)
63 svr2 = Proc.new do |serv, port|
64 client, client_addr = serv.accept
66 readed = client.recv(4096, 0)
68 %r{\AGET /dev2/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
70 client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
74 t1 = TempServer.new(svr1)
75 t2 = TempServer.new(svr2)
76 path1 = "http://127.0.0.1:#{t1.port}/dev1/0/000/000/0000000062.fid"
77 path2 = "http://127.0.0.1:#{t2.port}/dev2/0/000/000/0000000062.fid"
78 @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
80 assert_equal 'data!', @client.get_file_data('key')
81 assert_equal 2, accept.stat.size
83 TempServer.destroy_all!
86 def test_get_file_data_http_block
87 tmpfp = Tempfile.new('test_mogilefs.open_data')
89 chunk_size = 1024 * 1024
90 expect_size = nr * chunk_size
91 header = "HTTP/1.0 200 OK\r\n" \
92 "Content-Length: #{expect_size}\r\n\r\n"
93 assert_equal header.size, tmpfp.syswrite(header)
94 nr.times { assert_equal chunk_size, tmpfp.syswrite(' ' * chunk_size) }
95 assert_equal expect_size + header.size, File.size(tmpfp.path)
98 accept = Tempfile.new('accept')
99 svr = Proc.new do |serv, port|
100 client, client_addr = serv.accept
103 readed = client.recv(4096, 0)
105 %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
106 copy_stream(tmpfp, client)
110 t1 = TempServer.new(svr)
111 t2 = TempServer.new(svr)
112 path1 = "http://127.0.0.1:#{t1.port}/dev1/0/000/000/0000000062.fid"
113 path2 = "http://127.0.0.1:#{t2.port}/dev2/0/000/000/0000000062.fid"
115 @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
117 data = Tempfile.new('test_mogilefs.dest_data')
119 @client.get_file_data('key') do |fp|
123 fp.sysread(16384, buf)
126 assert_equal read_nr, data.syswrite(buf), "partial write"
134 assert_equal expect_size, nr, "size mismatch"
135 assert_equal 1, accept.stat.size
139 path1 = 'http://rur-1/dev1/0/000/000/0000000062.fid'
140 path2 = 'http://rur-2/dev2/0/000/000/0000000062.fid'
142 @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
144 expected = [ path1, path2 ]
146 assert_equal expected, @client.get_paths('key').sort
150 path1 = 'http://rur-1/dev1/0/000/000/0000000062.fid'
151 path2 = 'http://rur-2/dev2/0/000/000/0000000062.fid'
153 @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
155 expected = [ URI.parse(path1), URI.parse(path2) ]
157 assert_equal expected, @client.get_uris('key')
161 def test_get_paths_unknown_key
162 @backend.get_paths = ['unknown_key', '']
164 assert_raises MogileFS::Backend::UnknownKeyError do
165 assert_equal nil, @client.get_paths('key')
169 def test_delete_existing
170 @backend.delete = { }
171 assert_nothing_raised do
172 @client.delete 'no_such_key'
176 def test_delete_nonexisting
177 @backend.delete = 'unknown_key', ''
178 assert_raises MogileFS::Backend::UnknownKeyError do
179 @client.delete('no_such_key')
183 def test_delete_readonly
184 @client.readonly = true
185 assert_raises MogileFS::ReadOnlyError do
186 @client.delete 'no_such_key'
191 @backend.list_keys = { 'key_count' => 2, 'next_after' => 'new_key_2',
192 'key_1' => 'new_key_1', 'key_2' => 'new_key_2' }
193 @backend.list_keys = { 'key_count' => 2, 'next_after' => 'new_key_4',
194 'key_1' => 'new_key_3', 'key_2' => 'new_key_4' }
195 @backend.list_keys = { 'key_count' => 0, 'next_after' => 'new_key_4' }
197 @client.each_key 'new' do |key|
201 assert_equal %w[new_key_1 new_key_2 new_key_3 new_key_4], keys
205 @backend.list_keys = { 'key_count' => '2', 'next_after' => 'new_key_2',
206 'key_1' => 'new_key_1', 'key_2' => 'new_key_2' }
208 keys, next_after = @client.list_keys 'new'
209 assert_equal ['new_key_1', 'new_key_2'], keys.sort
210 assert_equal 'new_key_2', next_after
213 def test_list_keys_block
214 @backend.list_keys = { 'key_count' => '2', 'next_after' => 'new_key_2',
215 'key_1' => 'new_key_1', 'key_2' => 'new_key_2' }
216 http_resp = "HTTP/1.0 200 OK\r\nContent-Length: %u\r\n"
217 srv = Proc.new do |serv, port, size|
218 client, client_addr = serv.accept
220 readed = client.readpartial(4096)
221 assert %r{\AHEAD } =~ readed
222 client.send(http_resp % size, 0)
225 t1 = TempServer.new(Proc.new { |serv, port| srv.call(serv, port, 5) })
226 t2 = TempServer.new(Proc.new { |serv, port| srv.call(serv, port, 5) })
227 t3 = TempServer.new(Proc.new { |serv, port| srv.call(serv, port, 10) })
228 @backend.get_paths = { 'paths' => '2',
229 'path1' => "http://127.0.0.1:#{t1.port}/",
230 'path2' => "http://127.0.0.1:#{t2.port}/" }
231 @backend.get_paths = { 'paths' => '1',
232 'path1' => "http://127.0.0.1:#{t3.port}/" }
235 keys, next_after = @client.list_keys('new') do |key,length,devcount|
236 res << [ key, length, devcount ]
239 expect_res = [ [ 'new_key_1', 5, 2 ], [ 'new_key_2', 10, 1 ] ]
240 assert_equal expect_res, res
241 assert_equal ['new_key_1', 'new_key_2'], keys.sort
242 assert_equal 'new_key_2', next_after
244 TempServer.destroy_all!
247 def test_new_file_http
248 @client.readonly = true
249 assert_raises MogileFS::ReadOnlyError do
250 @client.new_file 'new_key', 'test'
254 def test_new_file_readonly
255 @client.readonly = true
256 assert_raises MogileFS::ReadOnlyError do
257 @client.new_file 'new_key', 'test'
262 accept = Tempfile.new('accept')
263 t = TempServer.new(Proc.new do |serv,port|
264 client, client_addr = serv.accept
266 readed = client.recv(4096, 0) rescue nil
268 assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed
269 client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\n", 0)
273 path = "http://127.0.0.1:#{t.port}/path"
274 @backend.get_paths = { 'paths' => 1, 'path1' => path }
276 assert_equal 5, @client.size('key')
277 assert_equal 1, accept.stat.size
280 def test_bad_size_http
281 tmp = Tempfile.new('accept')
282 t = TempServer.new(Proc.new do |serv,port|
283 client, client_addr = serv.accept
285 readed = client.recv(4096, 0) rescue nil
286 assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed
288 client.send("HTTP/1.0 404 Not Found\r\nContent-Length: 5\r\n\r\n", 0)
292 path = "http://127.0.0.1:#{t.port}/path"
293 @backend.get_paths = { 'paths' => 1, 'path1' => path }
295 assert_raises(MogileFS::Error) { @client.size('key') }
296 assert_equal 1, tmp.stat.size
299 def test_store_file_small_http
300 received = Tempfile.new('received')
301 to_store = Tempfile.new('small')
302 to_store.syswrite('data')
304 expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
305 t = TempServer.new(Proc.new do |serv, accept|
306 client, client_addr = serv.accept
308 received.syswrite(client.recv(4096, 0))
309 client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
313 @backend.create_open = {
315 'path' => "http://127.0.0.1:#{t.port}/path",
317 nr = @client.store_file 'new_key', 'test', to_store.path
320 assert_equal expected, received.sysread(4096)
322 TempServer.destroy_all!
325 def test_store_content_http
326 received = Tempfile.new('recieved')
327 expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
329 t = TempServer.new(Proc.new do |serv, accept|
330 client, client_addr = serv.accept
332 received.syswrite(client.recv(4096, 0))
333 client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
337 @backend.create_open = {
339 'path' => "http://127.0.0.1:#{t.port}/path",
342 nr = @client.store_content 'new_key', 'test', 'data'
347 assert_equal expected, received.sysread(4096)
349 TempServer.destroy_all!
353 def test_store_content_with_writer_callback
354 received = Tempfile.new('recieved')
355 expected = "PUT /path HTTP/1.0\r\nContent-Length: 40\r\n\r\n"
359 t = TempServer.new(Proc.new do |serv, accept|
360 client, client_addr = serv.accept
364 buf = client.readpartial(8192) or break
365 break if buf.length == 0
366 assert_equal buf.length, received.syswrite(buf)
368 break if nr >= expected.size
370 client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
374 @backend.create_open = {
376 'path' => "http://127.0.0.1:#{t.port}/path",
379 cbk = MogileFS::Util::StoreContent.new(40) do |write_callback|
381 write_callback.call("data")
384 assert_equal 40, cbk.length
385 nr = @client.store_content('new_key', 'test', cbk)
389 assert_equal expected, received.sysread(4096)
391 TempServer.destroy_all!
394 def test_store_content_multi_dest_failover
395 received1 = Tempfile.new('received')
396 received2 = Tempfile.new('received')
397 expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
399 t1 = TempServer.new(Proc.new do |serv, accept|
400 client, client_addr = serv.accept
402 received1.syswrite(client.recv(4096, 0))
403 client.send("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0)
407 t2 = TempServer.new(Proc.new do |serv, accept|
408 client, client_addr = serv.accept
410 received2.syswrite(client.recv(4096, 0))
411 client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
415 @backend.create_open = {
418 'path_1' => "http://127.0.0.1:#{t1.port}/path",
420 'path_2' => "http://127.0.0.1:#{t2.port}/path",
423 nr = @client.store_content 'new_key', 'test', 'data'
427 assert_equal expected, received1.sysread(4096)
428 assert_equal expected, received2.sysread(4096)
430 TempServer.destroy_all!
433 def test_store_content_http_fail
434 t = TempServer.new(Proc.new do |serv, accept|
435 client, client_addr = serv.accept
438 client.send("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0)
442 @backend.create_open = {
444 'path' => "http://127.0.0.1:#{t.port}/path",
447 assert_raises MogileFS::HTTPFile::NoStorageNodesError do
448 @client.store_content 'new_key', 'test', 'data'
452 def test_store_content_http_empty
453 received = Tempfile.new('received')
454 expected = "PUT /path HTTP/1.0\r\nContent-Length: 0\r\n\r\n"
455 t = TempServer.new(Proc.new do |serv, accept|
456 client, client_addr = serv.accept
458 received.syswrite(client.recv(4096, 0))
459 client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
463 @backend.create_open = {
465 'path' => "http://127.0.0.1:#{t.port}/path",
468 nr = @client.store_content 'new_key', 'test', ''
471 assert_equal expected, received.sysread(4096)
474 def test_store_content_nfs
475 @backend.create_open = {
480 assert_raises MogileFS::UnsupportedPathError do
481 @client.store_content 'new_key', 'test', 'data'
485 def test_new_file_http_large
486 expect = Tempfile.new('test_mogilefs.expect')
487 to_put = Tempfile.new('test_mogilefs.to_put')
488 received = Tempfile.new('test_mogilefs.received')
491 chunk_size = 1024 * 1024
492 expect_size = nr * chunk_size
494 header = "PUT /path HTTP/1.0\r\n" \
495 "Content-Length: #{expect_size}\r\n\r\n"
496 assert_equal header.size, expect.syswrite(header)
498 assert_equal chunk_size, expect.syswrite(' ' * chunk_size)
499 assert_equal chunk_size, to_put.syswrite(' ' * chunk_size)
501 assert_equal expect_size + header.size, expect.stat.size
502 assert_equal expect_size, to_put.stat.size
504 readed = Tempfile.new('readed')
505 t = TempServer.new(Proc.new do |serv, accept|
506 client, client_addr = serv.accept
510 buf = client.readpartial(8192) or break
511 break if buf.length == 0
512 assert_equal buf.length, received.syswrite(buf)
514 break if nr >= expect.stat.size
516 readed.syswrite("#{nr}")
517 client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
521 @backend.create_open = {
523 'path' => "http://127.0.0.1:#{t.port}/path",
526 orig_size = to_put.size
527 nr = @client.store_file('new_key', 'test', to_put.path)
529 assert_equal orig_size, nr
530 assert_equal orig_size, to_put.size
532 assert_equal expect.stat.size, readed.sysread(4096).to_i
534 ENV['PATH'].split(/:/).each do |path|
535 cmp_bin = "#{path}/cmp"
536 File.executable?(cmp_bin) or next
537 # puts "running #{cmp_bin} #{expect.path} #{received.path}"
538 assert( system(cmp_bin, expect.path, received.path) )
543 TempServer.destroy_all!
546 def test_store_content_readonly
547 @client.readonly = true
549 assert_raises MogileFS::ReadOnlyError do
550 @client.store_content 'new_key', 'test', nil
554 def test_store_file_readonly
555 @client.readonly = true
556 assert_raises MogileFS::ReadOnlyError do
557 @client.store_file 'new_key', 'test', nil
561 def test_rename_existing
564 assert_nil @client.rename('from_key', 'to_key')
567 def test_rename_nonexisting
568 @backend.rename = 'unknown_key', ''
570 assert_raises MogileFS::Backend::UnknownKeyError do
571 @client.rename('from_key', 'to_key')
575 def test_rename_no_key
576 @backend.rename = 'no_key', 'no_key'
578 e = assert_raises MogileFS::Backend::NoKeyError do
579 @client.rename 'new_key', 'test'
582 assert_equal 'no_key', e.message
585 def test_rename_readonly
586 @client.readonly = true
588 e = assert_raises MogileFS::ReadOnlyError do
589 @client.rename 'new_key', 'test'
592 assert_equal 'readonly mogilefs', e.message
597 assert_nothing_raised do
598 assert_equal({}, @client.sleep(2))
604 # tested with 1000, though it takes a while
606 ENV['NR_CHUNKS'] ? ENV['NR_CHUNKS'].to_i : 10