test_mysql: remove unnecessary requires
[ruby-mogilefs-client.git] / test / test_backend.rb
blob5db8189ffc81683d4ee7deb34eaed55ce5a42850
1 require 'test/unit'
2 require 'test/setup'
4 $TESTING = true
6 require 'mogilefs/backend'
8 class MogileFS::Backend
10   attr_accessor :hosts
11   attr_reader :timeout, :dead
12   attr_writer :lasterr, :lasterrstr, :socket
14 end
16 class TestBackend < Test::Unit::TestCase
18   def setup
19     TCPSocket.connections = []
20     TCPSocket.sockets = []
21     @backend = MogileFS::Backend.new :hosts => ['localhost:1']
22   end
24   def test_initialize
25     assert_raises ArgumentError do MogileFS::Backend.new end
26     assert_raises ArgumentError do MogileFS::Backend.new :hosts => [] end
27     assert_raises ArgumentError do MogileFS::Backend.new :hosts => [''] end
29     assert_equal ['localhost:1'], @backend.hosts
30     assert_equal 3, @backend.timeout
31     assert_equal nil, @backend.lasterr
32     assert_equal nil, @backend.lasterrstr
33     assert_equal({}, @backend.dead)
35     @backend = MogileFS::Backend.new :hosts => ['localhost:6001'], :timeout => 1
36     assert_equal 1, @backend.timeout
37   end
39   def test_do_request
40     socket_request = ''
41     socket = Object.new
42     def socket.closed?() false end
43     def socket.send(request, flags) return request.length end
44     def @backend.select(*args) return [true] end
45     def socket.gets() return 'OK 1 you=win' end
47     @backend.instance_variable_set '@socket', socket
49     assert_equal({'you' => 'win'},
50                  @backend.do_request('go!', { 'fight' => 'team fight!' }))
51   end
53   def test_do_request_send_error
54     socket_request = ''
55     socket = Object.new
56     def socket.closed?() false end
57     def socket.send(request, flags) raise SystemCallError, 'dummy' end
59     @backend.instance_variable_set '@socket', socket
61     assert_raises MogileFS::UnreachableBackendError do
62       @backend.do_request 'go!', { 'fight' => 'team fight!' }
63     end
65     assert_equal nil, @backend.instance_variable_get('@socket')
66   end
68   def test_automatic_exception
69     assert ! MogileFS::Backend.const_defined?('PebkacError')
70     assert @backend.error('pebkac')
71     assert_equal MogileFS::Error, @backend.error('PebkacError').superclass
72     assert MogileFS::Backend.const_defined?('PebkacError')
74     assert ! MogileFS::Backend.const_defined?('PebKacError')
75     assert @backend.error('peb_kac')
76     assert_equal MogileFS::Error, @backend.error('PebKacError').superclass
77     assert MogileFS::Backend.const_defined?('PebKacError')
78   end
80   def test_do_request_truncated
81     socket_request = ''
82     socket = Object.new
83     def socket.closed?() false end
84     def socket.send(request, flags) return request.length - 1 end
86     @backend.instance_variable_set '@socket', socket
88     assert_raises MogileFS::RequestTruncatedError do
89       @backend.do_request 'go!', { 'fight' => 'team fight!' }
90     end
91   end
93   def test_make_request
94     assert_equal "go! fight=team+fight%21\r\n",
95                  @backend.make_request('go!', { 'fight' => 'team fight!' })
96   end
98   def test_parse_response
99     assert_equal({'foo' => 'bar', 'baz' => 'hoge'},
100                  @backend.parse_response('OK 1 foo=bar&baz=hoge'))
102     err = nil
103     begin
104       @backend.parse_response('ERR you totally suck')
105     rescue MogileFS::Error => err
106       assert_equal 'MogileFS::Backend::YouError', err.class.to_s
107     end
108     assert_equal 'MogileFS::Backend::YouError', err.class.to_s
110     assert_equal 'you', @backend.lasterr
111     assert_equal 'totally suck', @backend.lasterrstr
113     assert_raises MogileFS::InvalidResponseError do
114       @backend.parse_response 'garbage'
115     end
116   end
118   def test_readable_eh_readable
119     socket = Object.new
120     def socket.closed?() false end
121     def @backend.select(*args) return [true] end
122     @backend.instance_variable_set '@socket', socket
124     assert_equal true, @backend.readable?
125   end
127   def test_readable_eh_not_readable
128     socket = FakeSocket.new
129     def socket.closed?() false end
130     def @backend.select(r=nil, w=nil, e=nil, t=1)
131       Kernel.sleep(t.to_f + 0.1)
132       []
133     end
134     @backend.instance_variable_set '@socket', socket
136     begin
137       @backend.readable?
138     rescue MogileFS::UnreadableSocketError => e
139       assert_equal '127.0.0.1:6001 never became readable', e.message
140     rescue Exception => err
141       flunk "MogileFS::UnreadableSocketError not raised #{err} #{err.backtrace}"
142     else
143       flunk "MogileFS::UnreadableSocketError not raised"
144     end
145   end
147   def test_socket
148     assert_equal({}, @backend.dead)
149     assert_raises MogileFS::UnreachableBackendError do @backend.socket end
150     assert_equal(['localhost:1'], @backend.dead.keys)
151   end
153   def test_socket_robust
154     @backend.hosts = ['localhost:6001', 'localhost:6002']
155     def @backend.connect_to(host, port)
156       @first = (defined? @first) ? false : true
157       raise Errno::ECONNREFUSED if @first
158     end
160     assert_equal({}, @backend.dead)
161     @backend.socket
162     assert_equal false, @backend.dead.keys.empty?
163   end
165   def test_shutdown
166     fake_socket = FakeSocket.new
167     @backend.socket = fake_socket
168     assert_equal fake_socket, @backend.socket
169     @backend.shutdown
170     assert_equal nil, @backend.instance_variable_get(:@socket)
171   end
173   def test_url_decode
174     assert_equal({"\272z" => "\360opy", "f\000" => "\272r"},
175                  @backend.url_decode("%baz=%f0opy&f%00=%bar"))
176   end
178   def test_url_encode
179     params = [["f\000", "\272r"], ["\272z", "\360opy"]]
180     assert_equal "f%00=%bar&%baz=%f0opy", @backend.url_encode(params)
181   end
183   def test_url_escape # \n for unit_diff
184     actual = (0..255).map { |c| @backend.url_escape c.chr }.join "\n"
186     expected = []
187     expected.push(*(0..0x1f).map { |c| "%%%0.2x" % c })
188     expected << '+'
189     expected.push(*(0x21..0x2b).map { |c| "%%%0.2x" % c })
190     expected.push(*%w[, - . /])
191     expected.push(*('0'..'9'))
192     expected.push(*%w[: %3b %3c %3d %3e %3f %40])
193     expected.push(*('A'..'Z'))
194     expected.push(*%w[%5b \\ %5d %5e _ %60])
195     expected.push(*('a'..'z'))
196     expected.push(*(0x7b..0xff).map { |c| "%%%0.2x" % c })
198     expected = expected.join "\n"
200     assert_equal expected, actual
201   end
203   def test_url_unescape
204     input = []
205     input.push(*(0..0x1f).map { |c| "%%%0.2x" % c })
206     input << '+'
207     input.push(*(0x21..0x2b).map { |c| "%%%0.2x" % c })
208     input.push(*%w[, - . /])
209     input.push(*('0'..'9'))
210     input.push(*%w[: %3b %3c %3d %3e %3f %40])
211     input.push(*('A'..'Z'))
212     input.push(*%w[%5b \\ %5d %5e _ %60])
213     input.push(*('a'..'z'))
214     input.push(*(0x7b..0xff).map { |c| "%%%0.2x" % c })
216     actual = input.map { |c| @backend.url_unescape c }.join "\n"
218     expected = (0..255).map { |c| c.chr }.join "\n"
219     expected.sub! '+', ' '
221     assert_equal expected, actual
222   end