Branching mogilefs-client to version 1.2.1
[ruby-mogilefs-client.git] / test / test_backend.rb
blob7fa9a7cb42f0bc303d3a3a22c385527629c7e8b8
1 require 'test/unit'
3 $TESTING = true
5 require 'mogilefs/backend'
7 class MogileFS::Backend
9   attr_accessor :hosts
10   attr_reader :timeout, :dead
11   attr_writer :lasterr, :lasterrstr, :socket
13 end
15 class FakeSocket
17   def initialize
18     @closed = false
19   end
21   def closed?
22     @closed
23   end
25   def close
26     @closed = true
27     return nil
28   end
30   def peeraddr
31     ['AF_INET', 6001, 'localhost', '127.0.0.1']
32   end
34 end
36 class TestBackend < Test::Unit::TestCase
38   def setup
39     @backend = MogileFS::Backend.new :hosts => ['localhost:1']
40   end
42   def test_initialize
43     assert_raises ArgumentError do MogileFS::Backend.new end
44     assert_raises ArgumentError do MogileFS::Backend.new :hosts => [] end
45     assert_raises ArgumentError do MogileFS::Backend.new :hosts => [''] end
47     assert_equal ['localhost:1'], @backend.hosts
48     assert_equal 3, @backend.timeout
49     assert_equal nil, @backend.lasterr
50     assert_equal nil, @backend.lasterrstr
51     assert_equal({}, @backend.dead)
53     @backend = MogileFS::Backend.new :hosts => ['localhost:6001'], :timeout => 1
54     assert_equal 1, @backend.timeout
55   end
57   def test_do_request
58     socket_request = ''
59     socket = Object.new
60     def socket.closed?() false end
61     def socket.send(request, flags) return request.length end
62     def @backend.select(*args) return [true] end
63     def socket.gets() return 'OK 1 you=win' end
65     @backend.instance_variable_set '@socket', socket
67     assert_equal({'you' => 'win'},
68                  @backend.do_request('go!', { 'fight' => 'team fight!' }))
69   end
71   def test_do_request_send_error
72     socket_request = ''
73     socket = Object.new
74     def socket.closed?() false end
75     def socket.send(request, flags) raise SystemCallError, 'dummy' end
77     @backend.instance_variable_set '@socket', socket
79     assert_raises RuntimeError do
80       @backend.do_request 'go!', { 'fight' => 'team fight!' }
81     end
83     assert_equal nil, @backend.instance_variable_get('@socket')
84   end
86   def test_do_request_truncated
87     socket_request = ''
88     socket = Object.new
89     def socket.closed?() false end
90     def socket.send(request, flags) return request.length - 1 end
92     @backend.instance_variable_set '@socket', socket
94     assert_raises RuntimeError do
95       @backend.do_request 'go!', { 'fight' => 'team fight!' }
96     end
97   end
99   def test_make_request
100     assert_equal "go! fight=team+fight%21\r\n",
101                  @backend.make_request('go!', { 'fight' => 'team fight!' })
102   end
104   def test_parse_response
105     assert_equal({'foo' => 'bar', 'baz' => 'hoge'},
106                  @backend.parse_response('OK 1 foo=bar&baz=hoge'))
107     assert_equal nil, @backend.parse_response('ERR you totally suck')
108     assert_equal 'you', @backend.lasterr
109     assert_equal 'totally suck', @backend.lasterrstr
111     assert_raises RuntimeError do
112       @backend.parse_response 'garbage'
113     end
114   end
116   def test_readable_eh_readable
117     socket = Object.new
118     def socket.closed?() false end
119     def @backend.select(*args) return [true] end
120     @backend.instance_variable_set '@socket', socket
122     assert_equal true, @backend.readable?
123   end
125   def test_readable_eh_not_readable
126     socket = FakeSocket.new
127     def socket.closed?() false end
128     def @backend.select(*args) return [] end
129     @backend.instance_variable_set '@socket', socket
131     begin
132       @backend.readable?
133     rescue MogileFS::UnreadableSocketError => e
134       assert_equal '127.0.0.1:6001 never became readable', e.message
135     rescue Exception
136       flunk "MogileFS::UnreadableSocketError not raised"
137     else
138       flunk "MogileFS::UnreadableSocketError not raised"
139     end
140   end
142   def test_socket
143     assert_equal({}, @backend.dead)
144     assert_raises RuntimeError do @backend.socket end
145     assert_equal(['localhost:1'], @backend.dead.keys)
146   end
148   def test_socket_robust
149     @backend.hosts = ['localhost:6001', 'localhost:6002']
150     def @backend.connect_to(host, port)
151       @first = (defined? @first) ? false : true
152       raise Errno::ECONNREFUSED if @first
153     end
155     assert_equal({}, @backend.dead)
156     @backend.socket
157     assert_equal false, @backend.dead.keys.empty?
158   end
160   def test_shutdown
161     fake_socket = FakeSocket.new
162     @backend.socket = fake_socket
163     assert_equal fake_socket, @backend.socket
164     @backend.shutdown
165     assert_equal nil, @backend.instance_variable_get(:@socket)
166   end
168   def test_url_decode
169     assert_equal({"\272z" => "\360opy", "f\000" => "\272r"},
170                  @backend.url_decode("%baz=%f0opy&f%00=%bar"))
171   end
173   def test_url_encode
174     params = [["f\000", "\272r"], ["\272z", "\360opy"]]
175     assert_equal "f%00=%bar&%baz=%f0opy", @backend.url_encode(params)
176   end
178   def test_url_escape # \n for unit_diff
179     actual = (0..255).map { |c| @backend.url_escape c.chr }.join "\n"
181     expected = []
182     expected.push(*(0..0x1f).map { |c| "%%%0.2x" % c })
183     expected << '+'
184     expected.push(*(0x21..0x2b).map { |c| "%%%0.2x" % c })
185     expected.push(*%w[, - . /])
186     expected.push(*('0'..'9'))
187     expected.push(*%w[: %3b %3c %3d %3e %3f %40])
188     expected.push(*('A'..'Z'))
189     expected.push(*%w[%5b \\ %5d %5e _ %60])
190     expected.push(*('a'..'z'))
191     expected.push(*(0x7b..0xff).map { |c| "%%%0.2x" % c })
193     expected = expected.join "\n"
195     assert_equal expected, actual
196   end
198   def test_url_unescape
199     input = []
200     input.push(*(0..0x1f).map { |c| "%%%0.2x" % c })
201     input << '+'
202     input.push(*(0x21..0x2b).map { |c| "%%%0.2x" % c })
203     input.push(*%w[, - . /])
204     input.push(*('0'..'9'))
205     input.push(*%w[: %3b %3c %3d %3e %3f %40])
206     input.push(*('A'..'Z'))
207     input.push(*%w[%5b \\ %5d %5e _ %60])
208     input.push(*('a'..'z'))
209     input.push(*(0x7b..0xff).map { |c| "%%%0.2x" % c })
211     actual = input.map { |c| @backend.url_unescape c }.join "\n"
213     expected = (0..255).map { |c| c.chr }.join "\n"
214     expected.sub! '+', ' '
216     assert_equal expected, actual
217   end