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