Ruby mogilefs-client 3.12.2
[ruby-mogilefs-client.git] / test / test_mogilefs_integration.rb
blob13ae3f110ccf9e7d073c060d26fd9a8a2693bfd0
1 # -*- encoding: binary -*-
2 require './test/fresh'
4 class TestMogileFSIntegration < Test::Unit::TestCase
5   include TestFreshSetup
6   def setup
7     setup_mogilefs
8     add_host_device_domain
9     @client = MogileFS::MogileFS.new(:hosts => @trackers, :domain => @domain)
10   end
12   alias teardown teardown_mogilefs
14   def test_CRUD
15     assert ! @client.exist?("CRUD")
16     assert_equal 4, @client.store_content("CRUD", "default", "DATA")
17     assert @client.exist?("CRUD")
18     assert_equal 4, @client.size("CRUD")
19     assert_equal "DATA", @client.get_file_data("CRUD")
20     assert_equal "DAT", @client.get_file_data("CRUD", nil, 3)
21     assert_equal "AT", @client.get_file_data("CRUD", nil, 2, 1)
23     tmp = Tempfile.new("z")
24     tmp_path = tmp.path
25     tmp.close!
26     assert_equal 4, @client.get_file_data("CRUD", tmp_path)
27     assert_equal "DATA", File.read(tmp_path)
28     File.unlink(tmp_path)
30     sio = StringIO.new("")
31     rv = @client.get_file_data("CRUD", sio)
32     assert_equal 4, rv
33     assert_equal "DATA", sio.string
34     assert_equal 8, @client.store_content("CRUD", "default", "MOARDATA")
35     assert_equal "MOARDATA", @client.get_file_data("CRUD")
36     assert_equal true, @client.delete("CRUD")
37     assert_raises(MogileFS::Backend::UnknownKeyError) { @client.delete("CRUD") }
39     data = "hello world\n".freeze
40     tmp = tmpfile("blob")
41     tmp.sync = true
42     tmp.write(data)
43     tmp.rewind
44     assert_equal tmp.size, @client.store_file("blob", nil, tmp)
45     assert_equal(data, @client.get_file_data("blob"))
47     data = "pipe!\n".freeze
48     r, w = IO.pipe
49     th = Thread.new do
50       w.write(data)
51       w.close
52     end
53     assert_equal data.size, @client.store_file("pipe", nil, r)
54     r.close
55     th.join
56     assert_equal(data, @client.get_file_data("pipe"))
58     cbk = MogileFS::Util::StoreContent.new(nil) do |write_callback|
59       10.times { write_callback.call("data") }
60     end
61     assert_nil cbk.length
62     nr = @client.store_content('store_content', nil, cbk)
63     assert_equal 40, nr
64     assert_equal("data" * 10, @client.get_file_data('store_content'))
65   end
67   def test_store_non_rewindable
68     tmp = Object.new
69     def tmp.size
70       666
71     end
72     def tmp.read(len, buf = "")
73       raise Errno::EIO
74     end
76     assert_raises(MogileFS::HTTPFile::NonRetryableError) do
77       @client.store_file("non_rewindable", nil, tmp)
78     end
79   end
81   def test_file_info
82     assert_equal 3, @client.store_content("file_info", "default", "FOO")
83     res = @client.file_info("file_info")
84     assert_kind_of Integer, res["fid"]
85     assert_equal 3, res["length"]
86     assert ! res.include?("devids")
87     assert_kind_of Integer, res["devcount"]
89     res = @client.file_info("file_info", :devices => true)
90     assert_kind_of Integer, res["fid"]
91     assert_equal 3, res["length"]
92     assert_kind_of Integer, res["devcount"]
93     devids = res.delete("devids")
94     assert_instance_of Array, devids
95     devids.each { |devid| assert_kind_of Integer, devid }
96     assert_equal res["devcount"], devids.size
97   end
99   def test_file_debug
100     assert_equal 3, @client.store_content("file_debug", "default", "BUG")
101     a = @client.file_debug("file_debug")
102     b = @client.file_debug(:key => "file_debug")
103     fid = @client.file_info("file_debug")["fid"]
104     c = @client.file_debug(fid)
105     d = @client.file_debug(:fid => fid)
107     [ a, b, c, d ].each do |res|
108       assert_equal fid, res["fid_fid"]
109       assert_equal 0, res["fid_classid"]
110       assert_equal "file_debug", res["fid_dkey"]
111       assert_equal 3, res["fid_length"]
112       assert_kind_of Array, res["devids"]
113       assert_kind_of Integer, res["devids"][0]
114       res["devids"].each do |devid|
115         uri = URI.parse(res["devpath_#{devid}"])
116         assert_equal "http", uri.scheme
117       end
118       assert_equal "default", res["fid_class"]
119     end
120     @client.delete("file_debug")
121     rv = @client.file_debug(fid)
122     assert rv.keys.grep(/\Afid_/).empty?, rv.inspect
123   end
125   def test_file_debug_in_progress
126     rv = @client.new_file("file_debug_in_progress") do |http_file|
127       http_file << "ZZZZ"
128       dests = http_file.instance_variable_get(:@dests)
129       dests[0][1] =~ %r{/(\d+)\.fid\z}
130       fid = $1.to_i
131       rv = @client.file_debug(fid)
132       devids = dests.map { |x| x[0].to_i }.sort
133       assert_equal devids, rv["tempfile_devids"].sort
134       assert_equal "file_debug_in_progress", rv["tempfile_dkey"]
135     end
136     assert_equal 4, rv
137   end
139   def test_admin_get_devices
140     admin = MogileFS::Admin.new(:hosts => @trackers)
141     devices = admin.get_devices
142     if any_device = devices[0]
143       %w(mb_asof mb_free mb_used mb_total devid weight hostid).each do |field|
144         case value = any_device[field]
145         when nil
146         when Integer
147           assert value >= 0, "#{field}=#{value.inspect} is negative"
148         else
149           assert false, "#{field}=#{value.inspect} is #{value.class}"
150         end
151       end
153       field = "utilization"
154       case value = any_device[field]
155       when nil
156       when Float
157         assert value >= 0.0, "#{field}=#{value.inspect} is negative"
158       else
159         assert false, "#{field}=#{value.inspect} is #{value.class}"
160       end
161     end
162   end
164   def test_admin_each_fid
165     admin = MogileFS::Admin.new(:hosts => @trackers)
166     input = %w(a b c d e)
167     input.each do |k|
168       rv = @client.new_file(k)
169       rv.write(k)
170       assert_nil rv.close
171     end
172     seen = {}
173     count = admin.each_fid do |info|
174       seen[info["fid"]] = true
175       assert_kind_of Integer, info["fid"]
176       assert_kind_of Integer, info["length"]
177       assert_kind_of Integer, info["devcount"]
178       assert_kind_of String, info["key"]
179       assert_kind_of String, info["class"]
180       assert_kind_of String, info["domain"]
181     end
182     assert_equal count, seen.size
183     assert_equal count, input.size
184   end
186   def test_new_file_no_block
187     rv = @client.new_file("no_block")
188     rv.write "HELLO"
189     assert_nil rv.close
190     assert_equal "HELLO", @client.get_file_data("no_block")
191   end
193   def test_new_file_known_content_length
194     rv = @client.new_file("a", :content_length => 5)
195     rv.write "HELLO"
196     assert_nil rv.close
197     assert_equal "HELLO", @client.get_file_data("a")
199     rv = @client.new_file("a", :content_length => 6)
200     rv.write "GOOD"
201     assert_raises(MogileFS::SizeMismatchError) { rv.close }
202     assert_equal "HELLO", @client.get_file_data("a")
204     rv = @client.new_file("large", :content_length => 6, :largefile => true)
205     assert_instance_of MogileFS::NewFile::Stream, rv
206     assert_equal 6, rv.write("HIHIHI")
207     assert_nil rv.close
208     assert_equal "HIHIHI", @client.get_file_data("large")
209   end
211   def test_new_file_content_md5
212     r, w = IO.pipe
213     b64digest = [ Digest::MD5.digest("HELLO") ].pack('m').strip
214     rv = @client.new_file("a", :content_md5 => b64digest, :content_length => 5)
215     rv.write "HELLO"
216     assert_nil rv.close
217     assert_equal "HELLO", @client.get_file_data("a")
219     w.write "HIHI"
220     w.close
221     assert_raises(ArgumentError) do
222       @client.new_file("a", :content_md5 => b64digest) { |f| f.big_io = r }
223     end
224     assert_equal "HELLO", @client.get_file_data("a")
226     @client.new_file("a", :content_md5 => :trailer) { |f| f.big_io = r }
227     assert_equal "HIHI", @client.get_file_data("a")
229     # legacy, in case anybody used it
230     rv = @client.new_file("a",{:class => "default"}, 6)
231     assert_equal 2, rv.write("HI")
232     assert_raises(MogileFS::SizeMismatchError) { rv.close }
233     assert_equal "HIHI", @client.get_file_data("a")
235     rv = @client.new_file("a",{:class => "default"}, 2)
236     assert_equal 2, rv.write("HI")
237     assert_nil rv.close
238     assert_equal "HI", @client.get_file_data("a")
239     assert_raises(MogileFS::Backend::UnregClassError) {
240       @client.new_file("a", "non-existent", 2)
241     }
242     assert_raises(MogileFS::Backend::UnregClassError) {
243       @client.new_file("a", :class => "non-existent")
244     }
245   ensure
246     r.close if r
247   end
249   def test_store_content_opts
250     b64digest = [ Digest::MD5.digest("HELLO") ].pack('m').strip
251     @client.store_content("c", nil, "HELLO", :content_md5 => b64digest)
252     assert_raises(MogileFS::SizeMismatchError) do
253       @client.store_content("c", nil, "GOODBYE", :content_length => 2)
254     end
255     assert_equal "HELLO", @client.get_file_data("c")
256   end
258   def test_store_file_opts
259     b64digest = [ Digest::MD5.digest("HELLO") ].pack('m').strip
260     io = StringIO.new("HELLO")
261     @client.store_file("c", nil, io, :content_md5 => b64digest)
263     io = StringIO.new("GOODBYE")
264     assert_raises(MogileFS::SizeMismatchError) do
265       @client.store_content("c", nil, io, :content_length => 2)
266     end
267     assert_equal "HELLO", @client.get_file_data("c")
268   end
270   def test_store_file_content_md5_lambda
271     checked = false
272     expect_md5 = lambda do
273       checked = true
274       [ Digest::MD5.digest("HELLO") ].pack('m').strip
275     end
276     io = StringIO.new("HELLO")
277     @client.store_file("c", nil, io, :content_md5 => expect_md5)
279     assert_equal true, checked, "expect_md5 lambda called"
280   end
282   def test_store_file_unlinked_tempfile
283     tmp = Tempfile.new("store_file_unlinked")
284     tmp.unlink
285     tmp.sync = true
286     tmp.write "HIHI"
287     tmp.rewind
288     @client.store_file("unlinked", nil, tmp)
290     assert_equal "HIHI", @client.get_file_data("unlinked")
291   end
293   def test_updateclass
294     admin = MogileFS::Admin.new(:hosts => @trackers)
295     admin.create_class(@domain, "one", 1)
296     admin.create_class(@domain, "two", 2)
297     4.times { admin.clear_cache }
299     assert_equal 4, @client.store_content("uc", "default", "DATA")
300     assert_equal true, @client.updateclass("uc", "one")
301     assert_equal true, @client.updateclass("uc", "two")
302     assert_raises(MogileFS::Backend::ClassNotFoundError) do
303       @client.updateclass("uc", "wtf")
304     end
305     assert_raises(MogileFS::Backend::InvalidKeyError) do
306       @client.updateclass("nonexistent", "one")
307     end
309     @client.delete "uc"
310     admin.delete_class @domain, "one"
311     admin.delete_class @domain, "two"
312   end