Ruby mogilefs-client 3.12.2
[ruby-mogilefs-client.git] / test / test_cmogstored.rb
blob0dd920a31a931bd28f286a919312fff492bd3d4b
1 # -*- encoding: binary -*-
2 require "./test/fresh"
4 # cmogstored allows Content-Range on PUT, unlike the original mogstored
5 class Test_cmogstored < Test::Unit::TestCase
6   include TestFreshSetup
7   alias setup setup_mogilefs
8   alias teardown teardown_mogilefs
10   def test_range_put_new_file
11     add_host_device_domain
12     client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
14     io = client.new_file "range0", :largefile => :content_range
15     assert_nil io.close
16     assert_equal "", client.get_file_data("range0")
18     io = client.new_file "writes", :largefile => :content_range
19     %w(a b c d e).each { |x| io.write(x) }
20     assert_nil io.close
21     assert_equal "abcde", client.get_file_data("writes")
23     io = client.new_file "puts", :largefile => :content_range
24     %w(a b c d e).each { |x| io.puts(x) }
25     assert ! client.exist?("puts")
26     assert_nil io.close
27     assert_equal "a\nb\nc\nd\ne\n", client.get_file_data("puts")
28   end
30   def test_garbage
31     add_host_device_domain
32     client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain,
33                                     :timeout => 60
34     nr = 1024 * 1024 * 1024
35     client.new_file('giant', :largefile => :stream,
36                     :content_length => nr) do |io|
37       assert_instance_of MogileFS::NewFile::Stream, io
38       zero = Zero.new
39       before = GC.count
40       wr = IO.copy_stream(zero, io, nr)
41       after = GC.count
42       assert_equal nr, wr
43       assert_in_delta before, after, 1
44     end
45   end if IO.respond_to?(:copy_stream) && defined?(Zero) &&
46          GC.respond_to?(:count) && defined?(RUBY_ENGINE) &&
47          RUBY_ENGINE == 'ruby' && ENV['TEST_EXPENSIVE'].to_i != 0
49   def test_stream_new_file
50     add_host_device_domain
51     client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
52     client.new_file("chunky", :largefile => :stream) do |io|
53       assert_instance_of MogileFS::NewFile::Stream, io
54       assert_equal(5, io.write("HELLO"))
55       assert_nil io.md5
56     end
57     assert_equal "HELLO", client.get_file_data("chunky")
59     io = client.new_file("puts", :largefile => :stream)
60     assert_instance_of MogileFS::NewFile::Stream, io
61     assert_equal io, IO.select(nil, [io])[1][0], "IO.select-able"
63     assert_nil(io.puts("PUTS!"))
64     assert_nil(io.puts("PUTZ"))
65     assert_nil io.close
66     assert_equal "PUTS!\nPUTZ\n", client.get_file_data("puts")
68     io = client.new_file("putc", :largefile => :stream)
69     assert_equal(0x20, io.putc(0x20))
70     assert_nil io.close
71     assert_equal " ", client.get_file_data("putc")
73     io = client.new_file("print splat", :largefile => :stream)
74     io.print(1, 2, 3)
75     assert_nil io.close
76     assert_equal "123", client.get_file_data("print splat")
78     io = client.new_file("printf", :largefile => :stream)
79     assert_nil io.printf("%x", 1638)
80     assert_nil io.close
81     assert_equal "666", client.get_file_data("printf")
83     io = client.new_file("syswrite", :largefile => :stream)
84     assert_equal 4, io.syswrite("good")
85     assert_equal 7, io.syswrite("morning")
86     assert_nil io.close
87     assert_equal "goodmorning", client.get_file_data("syswrite")
89     io = client.new_file("md5", :largefile=>:stream, :content_md5=>:trailer)
90     assert_instance_of Digest::MD5, io.md5
91     assert_nil io.puts("HIHI")
92     assert_nil io.close
93     assert_equal "HIHI\n", client.get_file_data("md5")
94     assert_equal Digest::MD5.hexdigest("HIHI\n"), io.md5.hexdigest
96     io = client.new_file("<<", :largefile=>:stream)
97     assert_equal(io, io << ">>")
98     assert_nil io.close
99     assert_equal ">>", client.get_file_data("<<")
100   end
102   def test_stream_new_file_with_content_length
103     add_host_device_domain
104     client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
105     io = client.new_file("clen", :largefile=>:stream,:content_length=>6)
106     io << "HIHIHI"
107     assert_nil io.close
108     assert_equal "HIHIHI", client.get_file_data("clen")
110     io = client.new_file("clen", :largefile=>:stream,:content_length=>1)
111     io << "FAIL"
112     assert_raises(MogileFS::SizeMismatchError) { io.close }
113     assert_equal "HIHIHI", client.get_file_data("clen")
115     io = client.new_file("md5", :largefile=>:stream,
116                                 :content_length=>6, :content_md5=>:trailer)
117     assert_equal(io, io << "MD5MD5")
118     assert_nil io.close
119     assert_equal "MD5MD5", client.get_file_data("md5")
120     assert_equal Digest::MD5.hexdigest("MD5MD5"), io.md5.hexdigest
122     io = client.new_file("md5", :largefile=>:stream,
123                                 :content_length=>6, :content_md5=>:trailer)
124     assert_equal(io, io << "MD5MD")
125     assert_raises(MogileFS::SizeMismatchError) { io.close }
126     assert_equal Digest::MD5.hexdigest("MD5MD"), io.md5.hexdigest
127   end
129   def test_md5_check
130     add_host_device_domain
131     client = MogileFS::MogileFS.new :hosts => @hosts, :domain => @domain
132     node = "#@test_host:#@mogstored_http_port"
133     pid = fork do
134       # not modifying this hash in the same process
135       MogileFS::HTTPFile::MD5_TRAILER_NODES[node] = true
136       client.store_content("md5_me", nil, "HELLO WORLD")
137     end
138     _, status = Process.waitpid2(pid)
139     assert status.success?, status.inspect
140     assert_equal "HELLO WORLD", client.get_file_data("md5_me")
141   end
143   def setup_mogstored
144     @docroot = Dir.mktmpdir(["mogfresh", "docroot"])
145     Dir.mkdir("#@docroot/dev1")
146     Dir.mkdir("#@docroot/dev2")
147     @mogstored_mgmt = TCPServer.new(@test_host, 0)
148     @mogstored_http = TCPServer.new(@test_host, 0)
149     @mogstored_mgmt_port = @mogstored_mgmt.addr[1]
150     @mogstored_http_port = @mogstored_http.addr[1]
152     @mogstored_pid = fork do
153       mgmt_fd = @mogstored_mgmt.fileno
154       http_fd = @mogstored_http.fileno
155       args = []
156       ENV["CMOGSTORED_FD"] = "#{mgmt_fd},#{http_fd}"
157       if @mogstored_mgmt.respond_to?(:close_on_exec=)
158         @mogstored_mgmt.close_on_exec = @mogstored_http.close_on_exec = false
159         args << { mgmt_fd => mgmt_fd, http_fd => http_fd }
160       end
161       $stderr.reopen('/dev/null', 'a')
162       exec "cmogstored", "--httplisten=#@test_host:#@mogstored_http_port",
163            "--mgmtlisten=#@test_host:#@mogstored_mgmt_port",
164            "--maxconns=1000", "--docroot=#@docroot", *args
165     end
166   end
167 end if `which cmogstored`.chomp.size > 0
169 # The goal of this is to use a synthetic (non-IO) reader
170 # to trigger the read/write loop of IO.copy_stream,
171 # bypassing in-kernel mechanisms like sendfile for zero copy,
172 # so we wrap the /dev/zero IO object:
173 class Zero
174   def initialize
175     @in = File.open('/dev/zero', 'rb')
176   end
178   def read(len, buf)
179     @in.read(len, buf)
180   end
181 end if File.readable?('/dev/zero')