test_mogilefs: fix broken test case that was timing out
[ruby-mogilefs-client.git] / test / test_mogilefs.rb
blob93de32363c3129df554df95fa3bff381d8743b8e
1 require 'test/setup'
2 require 'stringio'
3 require 'tempfile'
4 require 'fileutils'
6 class TestMogileFS__MogileFS < TestMogileFS
7   include MogileFS::Util
9   def setup
10     @klass = MogileFS::MogileFS
11     super
12   end
14   def test_initialize
15     assert_equal 'test', @client.domain
17     assert_raises ArgumentError do
18       MogileFS::MogileFS.new :hosts => ['kaa:6001']
19     end
20   end
22   def test_get_file_data_http
23     accept_nr = 0
24     svr = Proc.new do |serv, port|
25       client, client_addr = serv.accept
26       client.sync = true
27       readed = client.recv(4096, 0)
28       assert(readed =~ \
29             %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
30       client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\ndata!", 0)
31       accept_nr += 1
32       client.close
33     end
34     t1 = TempServer.new(svr)
35     t2 = TempServer.new(svr)
36     path1 = "http://127.0.0.1:#{t1.port}/dev1/0/000/000/0000000062.fid"
37     path2 = "http://127.0.0.1:#{t2.port}/dev2/0/000/000/0000000062.fid"
39     @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
41     assert_equal 'data!', @client.get_file_data('key')
42     assert_equal 1, accept_nr
43     ensure
44       TempServer.destroy_all!
45   end
47   def test_get_file_data_http_block
48     tmpfp = Tempfile.new('test_mogilefs.open_data')
49     nr = nr_chunks
50     chunk_size = 1024 * 1024
51     expect_size = nr * chunk_size
52     header = "HTTP/1.0 200 OK\r\n" \
53              "Content-Length: #{expect_size}\r\n\r\n"
54     assert_equal header.size, tmpfp.syswrite(header)
55     nr.times { assert_equal chunk_size, tmpfp.syswrite(' ' * chunk_size) }
56     assert_equal expect_size + header.size, File.size(tmpfp.path)
57     tmpfp.sysseek(0)
59     accept_nr = 0
60     svr = Proc.new do |serv, port|
61       client, client_addr = serv.accept
62       client.sync = true
63       accept_nr += 1
64       readed = client.recv(4096, 0)
65       assert(readed =~ \
66             %r{\AGET /dev[12]/0/000/000/0000000062\.fid HTTP/1.[01]\r\n\r\n\Z})
67       sysrwloop(tmpfp, client)
68       client.close
69     end
70     t1 = TempServer.new(svr)
71     t2 = TempServer.new(svr)
72     path1 = "http://127.0.0.1:#{t1.port}/dev1/0/000/000/0000000062.fid"
73     path2 = "http://127.0.0.1:#{t2.port}/dev2/0/000/000/0000000062.fid"
75     @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
77     data = Tempfile.new('test_mogilefs.dest_data')
78     read_nr = nr = 0
79     @client.get_file_data('key') do |fp|
80       buf = ''
81       loop do
82         begin
83           fp.sysread(16384, buf)
84           read_nr = buf.size
85           nr += read_nr
86           assert_equal read_nr, data.syswrite(buf), "partial write"
87         rescue EOFError
88           break
89         end
90       end
91     end
92     assert_equal expect_size, nr, "size mismatch"
93     assert_equal 1, accept_nr
94   end
96   def test_get_paths
97     path1 = 'http://rur-1/dev1/0/000/000/0000000062.fid'
98     path2 = 'http://rur-2/dev2/0/000/000/0000000062.fid'
100     @backend.get_paths = { 'paths' => 2, 'path1' => path1, 'path2' => path2 }
102     expected = [ path1, path2 ]
104     assert_equal expected, @client.get_paths('key').sort
105   end
107   def test_get_paths_unknown_key
108     @backend.get_paths = ['unknown_key', '']
110     assert_raises MogileFS::Backend::UnknownKeyError do
111       assert_equal nil, @client.get_paths('key')
112     end
113   end
115   def test_delete_existing
116     @backend.delete = { }
117     assert_nothing_raised do
118       @client.delete 'no_such_key'
119     end
120   end
122   def test_delete_nonexisting
123     @backend.delete = 'unknown_key', ''
124     assert_raises MogileFS::Backend::UnknownKeyError do
125       @client.delete('no_such_key')
126     end
127   end
129   def test_delete_readonly
130     @client.readonly = true
131     assert_raises MogileFS::ReadOnlyError do
132       @client.delete 'no_such_key'
133     end
134   end
136   def test_each_key
137     @backend.list_keys = { 'key_count' => 2, 'next_after' => 'new_key_2',
138                            'key_1' => 'new_key_1', 'key_2' => 'new_key_2' }
139     @backend.list_keys = { 'key_count' => 2, 'next_after' => 'new_key_4',
140                            'key_1' => 'new_key_3', 'key_2' => 'new_key_4' }
141     @backend.list_keys = { 'key_count' => 0, 'next_after' => 'new_key_4' }
142     keys = []
143     @client.each_key 'new' do |key|
144       keys << key
145     end
147     assert_equal %w[new_key_1 new_key_2 new_key_3 new_key_4], keys
148   end
150   def test_list_keys
151     @backend.list_keys = { 'key_count' => 2, 'next_after' => 'new_key_2',
152                            'key_1' => 'new_key_1', 'key_2' => 'new_key_2' }
154     keys, next_after = @client.list_keys 'new'
155     assert_equal ['new_key_1', 'new_key_2'], keys.sort
156     assert_equal 'new_key_2', next_after
157   end
159   def test_list_keys_block
160     @backend.list_keys = { 'key_count' => 2, 'next_after' => 'new_key_2',
161                            'key_1' => 'new_key_1', 'key_2' => 'new_key_2' }
162     http_resp = "HTTP/1.0 200 OK\r\nContent-Length: %u\r\n"
163     srv = Proc.new do |serv, port, size|
164       client, client_addr = serv.accept
165       client.sync = true
166       readed = client.readpartial(4096)
167       assert %r{\AHEAD } =~ readed
168       client.send(http_resp % size, 0)
169       client.close
170     end
171     t1 = TempServer.new(Proc.new { |serv, port| srv.call(serv, port, 5) })
172     t2 = TempServer.new(Proc.new { |serv, port| srv.call(serv, port, 5) })
173     t3 = TempServer.new(Proc.new { |serv, port| srv.call(serv, port, 10) })
174     @backend.get_paths = { 'paths' => 2,
175                            'path1' => "http://127.0.0.1:#{t1.port}/",
176                            'path2' => "http://127.0.0.1:#{t2.port}/" }
177     @backend.get_paths = { 'paths' => 1,
178                            'path1' => "http://127.0.0.1:#{t3.port}/" }
180     res = []
181     keys, next_after = @client.list_keys('new') do |key,length,devcount|
182       res << [ key, length, devcount ]
183     end
185     expect_res = [ [ 'new_key_1', 5, 2 ], [ 'new_key_2', 10, 1 ] ]
186     assert_equal expect_res, res
187     assert_equal ['new_key_1', 'new_key_2'], keys.sort
188     assert_equal 'new_key_2', next_after
189     ensure
190       TempServer.destroy_all!
191   end
193   def test_new_file_http
194     @client.readonly = true
195     assert_raises MogileFS::ReadOnlyError do
196       @client.new_file 'new_key', 'test'
197     end
198   end
200   def test_new_file_readonly
201     @client.readonly = true
202     assert_raises MogileFS::ReadOnlyError do
203       @client.new_file 'new_key', 'test'
204     end
205   end
207   def test_size_http
208     accept_nr = 0
209     t = TempServer.new(Proc.new do |serv,port|
210       client, client_addr = serv.accept
211       client.sync = true
212       readed = client.recv(4096, 0) rescue nil
213       assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed
214       client.send("HTTP/1.0 200 OK\r\nContent-Length: 5\r\n\r\n", 0)
215       accept_nr += 1
216       client.close
217     end)
219     path = "http://127.0.0.1:#{t.port}/path"
220     @backend.get_paths = { 'paths' => 1, 'path1' => path }
222     assert_equal 5, @client.size('key')
223     assert_equal 1, accept_nr
224   end
226   def test_store_content_http
227     received = ''
228     expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
230     t = TempServer.new(Proc.new do |serv, accept|
231       client, client_addr = serv.accept
232       client.sync = true
233       received = client.recv(4096, 0)
234       client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
235       client.close
236     end)
238     @backend.create_open = {
239       'devid' => '1',
240       'path' => "http://127.0.0.1:#{t.port}/path",
241     }
243     @client.store_content 'new_key', 'test', 'data'
245     assert_equal expected, received
246     ensure
247       TempServer.destroy_all!
248   end
250   def test_store_content_multi_dest_failover
251     received1 = received2 = nil
252     expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata"
254     t1 = TempServer.new(Proc.new do |serv, accept|
255       client, client_addr = serv.accept
256       client.sync = true
257       received1 = client.recv(4096, 0)
258       client.send("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0)
259       client.close
260     end)
262     t2 = TempServer.new(Proc.new do |serv, accept|
263       client, client_addr = serv.accept
264       client.sync = true
265       received2 = client.recv(4096, 0)
266       client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
267       client.close
268     end)
270     @backend.create_open = {
271       'dev_count' => '2',
272       'devid_1' => '1',
273       'path_1' => "http://127.0.0.1:#{t1.port}/path",
274       'devid_2' => '2',
275       'path_2' => "http://127.0.0.1:#{t2.port}/path",
276     }
278     @client.store_content 'new_key', 'test', 'data'
279     assert_equal expected, received1
280     assert_equal expected, received2
281     ensure
282       TempServer.destroy_all!
283   end
285   def test_store_content_http_fail
286     t = TempServer.new(Proc.new do |serv, accept|
287       client, client_addr = serv.accept
288       client.sync = true
289       client.recv(4096, 0)
290       client.send("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0)
291       client.close
292     end)
294     @backend.create_open = {
295       'devid' => '1',
296       'path' => "http://127.0.0.1:#{t.port}/path",
297     }
299     assert_raises MogileFS::HTTPFile::BadResponseError do
300       @client.store_content 'new_key', 'test', 'data'
301     end
302   end
304   def test_store_content_http_empty
305     received = ''
306     expected = "PUT /path HTTP/1.0\r\nContent-Length: 0\r\n\r\n"
307     t = TempServer.new(Proc.new do |serv, accept|
308       client, client_addr = serv.accept
309       client.sync = true
310       received = client.recv(4096, 0)
311       client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
312       client.close
313     end)
315     @backend.create_open = {
316       'devid' => '1',
317       'path' => "http://127.0.0.1:#{t.port}/path",
318     }
320     @client.store_content 'new_key', 'test', ''
321     assert_equal expected, received
322   end
324   def test_store_content_nfs
325     @backend.create_open = {
326       'dev_count' => '1',
327       'devid_1' => '1',
328       'path_1' => '/path',
329     }
330     assert_raises MogileFS::UnsupportedPathError do
331       @client.store_content 'new_key', 'test', 'data'
332     end
333   end
335   def test_new_file_http_large
336     expect = Tempfile.new('test_mogilefs.expect')
337     to_put = Tempfile.new('test_mogilefs.to_put')
338     received = Tempfile.new('test_mogilefs.received')
340     nr = nr_chunks
341     chunk_size = 1024 * 1024
342     expect_size = nr * chunk_size
344     header = "PUT /path HTTP/1.0\r\n" \
345              "Content-Length: #{expect_size}\r\n\r\n"
346     assert_equal header.size, expect.syswrite(header)
347     nr.times do
348       assert_equal chunk_size, expect.syswrite(' ' * chunk_size)
349       assert_equal chunk_size, to_put.syswrite(' ' * chunk_size)
350     end
351     assert_equal expect_size + header.size, expect.stat.size
352     assert_equal expect_size, to_put.stat.size
354     readed = 0
355     t = TempServer.new(Proc.new do |serv, accept|
356       client, client_addr = serv.accept
357       client.sync = true
358       loop do
359         buf = client.readpartial(8192) or break
360         break if buf.length == 0
361         assert_equal buf.length, received.syswrite(buf)
362         readed += buf.length
363         break if readed >= expect.stat.size
364       end
365       client.send("HTTP/1.0 200 OK\r\n\r\n", 0)
366       client.close
367     end)
369     @backend.create_open = {
370       'devid' => '1',
371       'path' => "http://127.0.0.1:#{t.port}/path",
372     }
374     @client.store_file('new_key', 'test', to_put.path)
375     assert_equal expect.stat.size, readed
377     ENV['PATH'].split(/:/).each do |path|
378       cmp_bin = "#{path}/cmp"
379       File.executable?(cmp_bin) or next
380       # puts "running #{cmp_bin} #{expect.path} #{received.path}"
381       assert( system(cmp_bin, expect.path, received.path) )
382       break
383     end
385     ensure
386       TempServer.destroy_all!
387   end
389   def test_store_content_readonly
390     @client.readonly = true
392     assert_raises MogileFS::ReadOnlyError do
393       @client.store_content 'new_key', 'test', nil
394     end
395   end
397   def test_store_file_readonly
398     @client.readonly = true
399     assert_raises MogileFS::ReadOnlyError do
400       @client.store_file 'new_key', 'test', nil
401     end
402   end
404   def test_rename_existing
405     @backend.rename = {}
407     assert_nil @client.rename('from_key', 'to_key')
408   end
410   def test_rename_nonexisting
411     @backend.rename = 'unknown_key', ''
413     assert_raises MogileFS::Backend::UnknownKeyError do
414       @client.rename('from_key', 'to_key')
415     end
416   end
418   def test_rename_no_key
419     @backend.rename = 'no_key', 'no_key'
421     e = assert_raises MogileFS::Backend::NoKeyError do
422       @client.rename 'new_key', 'test'
423     end
425     assert_equal 'no_key', e.message
426   end
428   def test_rename_readonly
429     @client.readonly = true
431     e = assert_raises MogileFS::ReadOnlyError do
432       @client.rename 'new_key', 'test'
433     end
435     assert_equal 'readonly mogilefs', e.message
436   end
438   def test_sleep
439     @backend.sleep = {}
440     assert_nothing_raised do
441       assert_equal({}, @client.sleep(2))
442     end
443   end
445   private
447     # tested with 1000, though it takes a while
448     def nr_chunks
449       ENV['NR_CHUNKS'] ? ENV['NR_CHUNKS'].to_i : 10
450     end