5 require 'mogilefs/backend'
7 class MogileFS::Backend
10 attr_reader :timeout, :dead
11 attr_writer :lasterr, :lasterrstr, :socket
31 ['AF_INET', 6001, 'localhost', '127.0.0.1']
36 class TestBackend < Test::Unit::TestCase
39 @backend = MogileFS::Backend.new :hosts => ['localhost:1']
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
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!' }))
71 def test_do_request_send_error
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!' }
83 assert_equal nil, @backend.instance_variable_get('@socket')
86 def test_do_request_truncated
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!' }
100 assert_equal "go! fight=team+fight%21\r\n",
101 @backend.make_request('go!', { 'fight' => 'team fight!' })
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'
116 def test_readable_eh_readable
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?
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
133 rescue MogileFS::UnreadableSocketError => e
134 assert_equal '127.0.0.1:6001 never became readable', e.message
136 flunk "MogileFS::UnreadableSocketError not raised"
138 flunk "MogileFS::UnreadableSocketError not raised"
143 assert_equal({}, @backend.dead)
144 assert_raises RuntimeError do @backend.socket end
145 assert_equal(['localhost:1'], @backend.dead.keys)
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
155 assert_equal({}, @backend.dead)
157 assert_equal false, @backend.dead.keys.empty?
161 fake_socket = FakeSocket.new
162 @backend.socket = fake_socket
163 assert_equal fake_socket, @backend.socket
165 assert_equal nil, @backend.instance_variable_get(:@socket)
169 assert_equal({"\272z" => "\360opy", "f\000" => "\272r"},
170 @backend.url_decode("%baz=%f0opy&f%00=%bar"))
174 params = [["f\000", "\272r"], ["\272z", "\360opy"]]
175 assert_equal "f%00=%bar&%baz=%f0opy", @backend.url_encode(params)
178 def test_url_escape # \n for unit_diff
179 actual = (0..255).map { |c| @backend.url_escape c.chr }.join "\n"
182 expected.push(*(0..0x1f).map { |c| "%%%0.2x" % c })
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
198 def test_url_unescape
200 input.push(*(0..0x1f).map { |c| "%%%0.2x" % c })
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