fluent-plugin-hoop 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'fluent/test'
16
+
17
+ if ENV['FLUENT_TEST_DEBUG'] == 'TRUE'
18
+ nulllogger = Object.new
19
+ nulllogger.instance_eval {|obj|
20
+ def method_missing(method, *args)
21
+ # pass
22
+ end
23
+ }
24
+ $log = nulllogger
25
+ end
26
+
27
+ require 'fluent/plugin/out_hoop'
28
+
29
+ class Test::Unit::TestCase
30
+ end
31
+
32
+ require 'webrick'
33
+
34
+ # to handle PUT/DELETE ...
35
+ module WEBrick::HTTPServlet
36
+ class ProcHandler < AbstractServlet
37
+ alias do_PUT do_GET
38
+ alias do_DELETE do_GET
39
+ end
40
+ end
41
+
42
+ def get_code(server, port, path, headers)
43
+ require 'net/http'
44
+ Net::HTTP.start(server, port){|http|
45
+ http.get(path, headers).code
46
+ }
47
+ end
48
+ def get_content(server, port, path, headers)
49
+ require 'net/http'
50
+ Net::HTTP.start(server, port){|http|
51
+ http.get(path, headers).body
52
+ }
53
+ end
@@ -0,0 +1,441 @@
1
+ require 'helper'
2
+
3
+ class HoopOutputTest < Test::Unit::TestCase
4
+ # setup/teardown and tests of dummy hoop server defined at the end of this class...
5
+
6
+ CONFIG = %[
7
+ hoop_server localhost:14000
8
+ path /logs/from/fluentd/foo-%Y%m%d
9
+ username hoopuser
10
+ ]
11
+
12
+ def create_driver(conf=CONFIG, tag='test')
13
+ Fluent::Test::TimeSlicedOutputTestDriver.new(Fluent::HoopOutput, tag).configure(conf)
14
+ end
15
+
16
+ def test_configure
17
+ assert_raise(Fluent::ConfigError) {
18
+ d = create_driver %[
19
+ ]
20
+ }
21
+ assert_raise(Fluent::ConfigError) {
22
+ d = create_driver %[
23
+ path /logs/from/fluentd/foo-%Y%m%d%H
24
+ username hoopuser
25
+ ]
26
+ }
27
+ assert_raise(Fluent::ConfigError) {
28
+ d = create_driver %[
29
+ hoop_server hoop.master.local:14000
30
+ username hoopuser
31
+ ]
32
+ }
33
+ assert_raise(Fluent::ConfigError) {
34
+ d = create_driver %[
35
+ hoop_server hoop.master.local:14000
36
+ path /logs/from/fluentd/foo-%Y%m%d%H
37
+ ]
38
+ }
39
+ assert_raise(Fluent::ConfigError) {
40
+ d = create_driver %[
41
+ hoop_server hoop.master.local
42
+ path /logs/from/fluentd/foo-%Y%m%d%H
43
+ username hoopuser
44
+ ]
45
+ }
46
+ assert_raise(Fluent::ConfigError) {
47
+ d = create_driver %[
48
+ hoop_server hoop.master.local:xxx
49
+ path /logs/from/fluentd/foo-%Y%m%d%H
50
+ username hoopuser
51
+ ]
52
+ }
53
+ assert_raise(Fluent::ConfigError) {
54
+ d = create_driver %[
55
+ hoop_server hoop.master.local:xxx
56
+ path logs/from/fluentd/foo-%Y%m%d%H
57
+ username hoopuser
58
+ ]
59
+ }
60
+ assert_raise(Fluent::ConfigError) {
61
+ d = create_driver %[
62
+ hoop_server hoop.master.local:14000
63
+ path /logs/from/fluentd/access.log.%Y%m%d
64
+ output_include_tag true
65
+ remove_prefix testing
66
+ ]
67
+ }
68
+
69
+ # config_param :path, :string # /path/pattern/to/hdfs/file can use %Y %m %d %H %M %S and %T(tag, not-supported-yet)
70
+
71
+ d = create_driver(CONFIG)
72
+
73
+ assert_equal '%Y%m%d', d.instance.time_slice_format
74
+
75
+ assert_equal 'localhost:14000', d.instance.hoop_server
76
+ assert_equal '/logs/from/fluentd/foo-%Y%m%d', d.instance.path
77
+ assert_equal 'hoopuser', d.instance.username
78
+
79
+ assert_equal true, d.instance.output_include_time
80
+ assert_equal true, d.instance.output_include_tag
81
+ assert_equal 'json', d.instance.output_data_type
82
+ assert_equal true, d.instance.add_newline
83
+ assert_equal "\t", d.instance.field_separator
84
+
85
+ assert_nil d.instance.remove_prefix
86
+
87
+ d = create_driver(CONFIG + %[
88
+ add_newline false
89
+ remove_prefix testing
90
+ default_tag unknown
91
+ ], 'testing.error')
92
+ assert_equal 'testing.error', d.tag
93
+
94
+ assert_equal '%Y%m%d', d.instance.time_slice_format
95
+
96
+ assert_equal 'localhost:14000', d.instance.hoop_server
97
+ assert_equal '/logs/from/fluentd/foo-%Y%m%d', d.instance.path
98
+ assert_equal 'hoopuser', d.instance.username
99
+
100
+ assert_equal true, d.instance.output_include_time
101
+ assert_equal true, d.instance.output_include_tag
102
+ assert_equal 'json', d.instance.output_data_type
103
+ assert_equal false, d.instance.add_newline
104
+ assert_equal "\t", d.instance.field_separator
105
+
106
+ assert_equal 'testing', d.instance.remove_prefix
107
+ assert_equal 'unknown', d.instance.default_tag
108
+ end
109
+
110
+ def test_configure_path_and_slice_format
111
+ d = create_driver(CONFIG)
112
+ assert_equal '%Y%m%d', d.instance.time_slice_format
113
+ assert_equal '/logs/from/fluentd/foo-%Y%m%d', d.instance.path
114
+ assert_equal '/logs/from/fluentd/foo-20111125', d.instance.path_format('20111125')
115
+
116
+ d = create_driver CONFIG + %[
117
+ path /logs/from/fluentd/foo-%Y%m
118
+ ]
119
+ assert_equal '%Y%m%d', d.instance.time_slice_format
120
+ assert_equal '/logs/from/fluentd/foo-%Y%m', d.instance.path
121
+ assert_equal '/logs/from/fluentd/foo-201111', d.instance.path_format('20111125')
122
+
123
+ d = create_driver CONFIG + %[
124
+ path /logs/from/fluentd/foo-%Y%m%d%H
125
+ ]
126
+ assert_equal '%Y%m%d%H', d.instance.time_slice_format
127
+ assert_equal '/logs/from/fluentd/foo-%Y%m%d%H', d.instance.path
128
+ assert_equal '/logs/from/fluentd/foo-2011112508', d.instance.path_format('2011112508')
129
+
130
+ d = create_driver CONFIG + %[
131
+ path /logs/from/fluentd/foo-%Y%m%d%H%M
132
+ ]
133
+ assert_equal '%Y%m%d%H%M', d.instance.time_slice_format
134
+ assert_equal '/logs/from/fluentd/foo-%Y%m%d%H%M', d.instance.path
135
+ assert_equal '/logs/from/fluentd/foo-201111250811', d.instance.path_format('201111250811')
136
+
137
+ d = create_driver CONFIG + %[
138
+ path /logs/from/fluentd/foo-%Y%m%d%H%M%S
139
+ ]
140
+ assert_equal '%Y%m%d%H%M%S', d.instance.time_slice_format
141
+ assert_equal '/logs/from/fluentd/foo-%Y%m%d%H%M%S', d.instance.path
142
+ assert_equal '/logs/from/fluentd/foo-20111125081159', d.instance.path_format('20111125081159')
143
+
144
+ d = create_driver CONFIG + %[
145
+ path /logs/from/fluentd/foo-%m%d%H
146
+ ]
147
+ assert_equal '%Y%m%d%H', d.instance.time_slice_format
148
+ assert_equal '/logs/from/fluentd/foo-%m%d%H', d.instance.path
149
+ assert_equal '/logs/from/fluentd/foo-112508', d.instance.path_format('2011112508')
150
+
151
+ d = create_driver CONFIG + %[
152
+ path /logs/from/fluentd/foo-%M%S.log
153
+ ]
154
+ assert_equal '%Y%m%d%H%M%S', d.instance.time_slice_format
155
+ assert_equal '/logs/from/fluentd/foo-%M%S.log', d.instance.path
156
+ assert_equal '/logs/from/fluentd/foo-1159.log', d.instance.path_format('20111125081159')
157
+
158
+ d = create_driver CONFIG + %[
159
+ path /logs/from/fluentd/%Y%m%d/%H/foo-%M-%S.log
160
+ ]
161
+ assert_equal '%Y%m%d%H%M%S', d.instance.time_slice_format
162
+ assert_equal '/logs/from/fluentd/%Y%m%d/%H/foo-%M-%S.log', d.instance.path
163
+ assert_equal '/logs/from/fluentd/20111125/08/foo-11-59.log', d.instance.path_format('20111125081159')
164
+ end
165
+
166
+ def test_format
167
+ d = create_driver
168
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
169
+ d.emit({"a"=>1}, time)
170
+ d.emit({"a"=>2}, time)
171
+ d.expect_format %[2011-11-25T13:14:15Z\ttest\t{"a":1}\n]
172
+ d.expect_format %[2011-11-25T13:14:15Z\ttest\t{"a":2}\n]
173
+ d.run
174
+
175
+ d = create_driver(CONFIG + %[
176
+ remove_prefix testing
177
+ default_tag unknown
178
+ ], 'testing.log')
179
+ assert_equal 'testing.log', d.tag
180
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
181
+ d.emit({"a"=>1}, time)
182
+ d.emit({"a"=>2}, time)
183
+ d.expect_format %[2011-11-25T13:14:15Z\tlog\t{"a":1}\n]
184
+ d.expect_format %[2011-11-25T13:14:15Z\tlog\t{"a":2}\n]
185
+ d.run
186
+
187
+ d = create_driver(CONFIG + %[
188
+ remove_prefix testing
189
+ default_tag unknown
190
+ ], 'extra.testing.log')
191
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
192
+ d.emit({"a"=>1}, time)
193
+ d.emit({"a"=>2}, time)
194
+ d.expect_format %[2011-11-25T13:14:15Z\textra.testing.log\t{"a":1}\n]
195
+ d.expect_format %[2011-11-25T13:14:15Z\textra.testing.log\t{"a":2}\n]
196
+ d.run
197
+
198
+ d = create_driver(CONFIG + %[
199
+ remove_prefix testing
200
+ default_tag unknown
201
+ ], 'testing')
202
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
203
+ d.emit({"a"=>1}, time)
204
+ d.emit({"a"=>2}, time)
205
+ d.expect_format %[2011-11-25T13:14:15Z\tunknown\t{"a":1}\n]
206
+ d.expect_format %[2011-11-25T13:14:15Z\tunknown\t{"a":2}\n]
207
+ d.run
208
+
209
+ d = create_driver CONFIG + %[
210
+ output_include_tag false
211
+ ]
212
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
213
+ d.emit({"a"=>1}, time)
214
+ d.emit({"a"=>2}, time)
215
+ d.expect_format %[2011-11-25T13:14:15Z\t{"a":1}\n]
216
+ d.expect_format %[2011-11-25T13:14:15Z\t{"a":2}\n]
217
+ d.run
218
+
219
+ d = create_driver CONFIG + %[
220
+ output_include_time false
221
+ ]
222
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
223
+ d.emit({"a"=>1}, time)
224
+ d.emit({"a"=>2}, time)
225
+ d.expect_format %[test\t{"a":1}\n]
226
+ d.expect_format %[test\t{"a":2}\n]
227
+ d.run
228
+
229
+ d = create_driver CONFIG + %[
230
+ output_include_time false
231
+ output_include_tag false
232
+ ]
233
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
234
+ d.emit({"a"=>1}, time)
235
+ d.emit({"a"=>2}, time)
236
+ d.expect_format %[{"a":1}\n]
237
+ d.expect_format %[{"a":2}\n]
238
+ d.run
239
+
240
+ d = create_driver CONFIG + %[
241
+ output_include_time false
242
+ output_include_tag false
243
+ output_data_type attr:a
244
+ add_newline true # default
245
+ ]
246
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
247
+ d.emit({"a"=>1}, time)
248
+ d.emit({"a"=>2}, time)
249
+ d.expect_format %[1\n]
250
+ d.expect_format %[2\n]
251
+ d.run
252
+
253
+ d = create_driver CONFIG + %[
254
+ output_include_time false
255
+ output_include_tag false
256
+ output_data_type attr:a
257
+ add_newline false
258
+ ]
259
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
260
+ d.emit({"a"=>1}, time)
261
+ d.emit({"a"=>2}, time)
262
+ d.expect_format %[1]
263
+ d.expect_format %[2]
264
+ d.run
265
+
266
+ d = create_driver CONFIG + %[
267
+ output_include_time false
268
+ output_include_tag false
269
+ output_data_type attr:a,b,c
270
+ add_newline true
271
+ ]
272
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
273
+ d.emit({"a"=>1}, time)
274
+ d.emit({"a"=>2,"c"=>6,"b"=>4}, time)
275
+ d.expect_format %[1\tNULL\tNULL\n]
276
+ d.expect_format %[2\t4\t6\n]
277
+ d.run
278
+
279
+ d = create_driver CONFIG + %[
280
+ output_include_time false
281
+ output_include_tag false
282
+ output_data_type attr:message
283
+ add_newline false
284
+ ]
285
+ time = Time.parse("2011-11-25 13:14:15 UTC").to_i
286
+ d.emit({"tag"=>"from.scribe", "message"=>'127.0.0.1 - tagomoris [25/Nov/2011:20:19:04 +0900] "GET http://example.com/api/ HTTP/1.1" 200 39 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2" "-" 71383"' + "\n"}, time)
287
+ d.expect_format '127.0.0.1 - tagomoris [25/Nov/2011:20:19:04 +0900] "GET http://example.com/api/ HTTP/1.1" 200 39 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2" "-" 71383"' + "\n"
288
+ d.run
289
+ end
290
+
291
+ def test_write
292
+ d = create_driver CONFIG + %[
293
+ utc
294
+ ]
295
+
296
+ assert_equal '404', get_code('localhost', 14000, '/logs/from/fluentd/foo-20111124', {'Cookie' => VALID_COOKIE_STRING})
297
+
298
+ time = Time.parse("2011-11-24 00:14:15 UTC").to_i
299
+ d.emit({"a"=>1}, time)
300
+ d.emit({"a"=>2}, time)
301
+ paths = d.run
302
+ assert_equal ['/logs/from/fluentd/foo-20111124'], paths
303
+ assert_equal %[2011-11-24T00:14:15Z\ttest\t{"a":1}\n2011-11-24T00:14:15Z\ttest\t{"a":2}\n], get_content('localhost', 14000, paths.first, {'Cookie' => VALID_COOKIE_STRING})
304
+ end
305
+
306
+ VALID_COOKIE_VALUE = 'u=hoopuser&p=hoopuser&t=simple&e=1322203001386&s=SErpv88rOAVEItSOIoCtIV/DSpE='
307
+ VALID_COOKIE_STRING = 'alfredo.auth="u=hoopuser&p=hoopuser&t=simple&e=1322203001386&s=SErpv88rOAVEItSOIoCtIV/DSpE="'
308
+ RES_COOKIE_AUTH_FAILURE = WEBrick::Cookie.parse_set_cookie('alfredo.auth=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/')
309
+ RES_COOKIE_AUTH_SUCCESS = WEBrick::Cookie.parse_set_cookie(VALID_COOKIE_STRING + '; Version=1; Path=/')
310
+ RES_BODY_STATUS_ROOT = '{"path":"http:\/\/localhost:14000\/","isDir":true,"len":0,"owner":"hoopuser","group":"supergroup","permission":"-rwxr-xr-x","accessTime":0,"modificationTime":1320055230010,"blockSize":0,"replication":0}'
311
+ RES_FORMAT_ALREADY_EXISTS = "{\"statusCode\":500,\"reason\":\"Internal Server Error\",\"message\":\"java.io.IOException: failed to create file %s on client 127.0.0.1 either because the filename is invalid or the file exists\",\"exception\":\"org.apache.hadoop.ipc.RemoteException\"}"
312
+ RES_FORMAT_NOT_FOUND = "{\"statusCode\":404,\"reason\":\"Not Found\",\"message\":\"java.io.FileNotFoundException: failed to append to non-existent file %s on client 127.0.0.1\",\"exception\":\"java.io.FileNotFoundException\"}"
313
+ RES_FORMAT_NOT_FOUND_GET = "{\"statusCode\":404,\"reason\":\"Not Found\",\"message\":\"File does not exist: %s\",\"exception\":\"java.io.FileNotFoundException\"}"
314
+
315
+ CONTENT_TYPE_JSON = 'application/json'
316
+
317
+ def setup
318
+ Fluent::Test.setup
319
+ @dummy_server_thread = Thread.new do
320
+ srv = if ENV['FLUENT_TEST_DEBUG']
321
+ logger = WEBrick::Log.new('/dev/null', WEBrick::BasicLog::DEBUG)
322
+ WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => 14000, :Logger => logger, :AccessLog => []})
323
+ else
324
+ WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1', :Port => 14000})
325
+ end
326
+ @fsdata = {}
327
+ begin
328
+ srv.mount_proc('/'){|req,res|
329
+ # status only...
330
+ if req.query['user.name'] or req.cookies.index{|item| item.name == 'alfredo.auth' and item.value}
331
+ res.status = 200
332
+ res.content_type = CONTENT_TYPE_JSON
333
+ res.cookies << RES_COOKIE_AUTH_SUCCESS
334
+ res.body = RES_BODY_STATUS_ROOT
335
+ else
336
+ res.cookies << RES_COOKIE_AUTH_FAILURE
337
+ res.status = 401
338
+ end
339
+ }
340
+ srv.mount_proc('/logs/from/fluentd') {|req, res|
341
+ if req.request_method == 'POST' or req.request_method == 'PUT' or req.request_method == 'DELETE'
342
+ # WEBrick's default handler ignores query parameter of URI without method GET
343
+ req.query.update(Hash[*(req.request_line.split(' ')[1].split('?')[1].split('&').map{|kv|kv.split('=')}.flatten)])
344
+ end
345
+ case
346
+ when (not req.query['user.name'] and req.cookies.index{|i| i.name == 'alfredo.auth' and i.value == VALID_COOKIE_VALUE} < 0)
347
+ res.cookies << RES_COOKIE_AUTH_FAILURE
348
+ res.status = 401
349
+ when (req.query['op'] == 'create' and @fsdata[req.path] and req.query['overwrite'] and req.query['overwrite'] == 'false')
350
+ res.status = 500
351
+ res.content_type = CONTENT_TYPE_JSON
352
+ res.body = sprintf RES_FORMAT_ALREADY_EXISTS, req.path
353
+ when req.query['op'] == 'create'
354
+ @fsdata[req.path] = req.body
355
+ res.status = 201
356
+ res['Location'] = 'http://localhost:14000' + req.path
357
+ res.content_type = CONTENT_TYPE_JSON
358
+ when (req.query['op'] == 'append' and @fsdata[req.path])
359
+ @fsdata[req.path] += req.body
360
+ res.status = 200
361
+ res['Location'] = 'http://localhost:14000' + req.path
362
+ res.content_type = CONTENT_TYPE_JSON
363
+ when req.query['op'] == 'append'
364
+ res.status = 404
365
+ res.content_type = CONTENT_TYPE_JSON
366
+ res.body = sprintf RES_FORMAT_NOT_FOUND, req.path
367
+ when (req.request_method == 'GET' and @fsdata[req.path]) # maybe GET
368
+ res.status = 200
369
+ res.content_type = 'application/octet-stream'
370
+ res.body = @fsdata[req.path]
371
+ else
372
+ res.status = 404
373
+ res.content_type = CONTENT_TYPE_JSON
374
+ res.body = sprintf RES_FORMAT_NOT_FOUND_GET, req.path
375
+ end
376
+ }
377
+ srv.start
378
+ ensure
379
+ srv.shutdown
380
+ end
381
+ end
382
+
383
+ # to wait completion of dummy server.start()
384
+ require 'thread'
385
+ cv = ConditionVariable.new
386
+ watcher = Thread.new {
387
+ connected = false
388
+ while not connected
389
+ begin
390
+ get_content('localhost', 14000, '/', {'Cookie' => VALID_COOKIE_STRING})
391
+ connected = true
392
+ rescue Errno::ECONNREFUSED
393
+ sleep 0.1
394
+ rescue StandardError => e
395
+ p e
396
+ sleep 0.1
397
+ end
398
+ end
399
+ cv.signal
400
+ }
401
+ mutex = Mutex.new
402
+ mutex.synchronize {
403
+ cv.wait(mutex)
404
+ }
405
+ end
406
+
407
+ def test_dummy_server
408
+ d = create_driver
409
+ authheader = {'Cookie' => VALID_COOKIE_STRING}
410
+ client = Net::HTTP.start(d.instance.hoop_server.split(':')[0], d.instance.hoop_server.split(':')[1])
411
+ assert_equal '401', client.request_get('/').code
412
+ assert_equal '200', client.request_get('/?user.name=hoopuser').code
413
+ assert_equal '200', client.request_get('/', authheader).code
414
+
415
+ # /logs/from/fluentd
416
+ path1 = '/logs/from/fluentd/hoge001/moge-access-log'
417
+ path1_line1 = "1111111111111111111111111111111\n"
418
+ path1_line2 = "2222222222222222222222222222222222222222222222222\n"
419
+ assert_equal '404', client.request_put(path1 + '?op=append', path1_line1, authheader).code
420
+ assert_equal '201', client.request_post(path1 + '?op=create&overwrite=false', path1_line1, authheader).code
421
+ assert_equal path1_line1, client.request_get(path1, authheader).body
422
+ assert_equal '200', client.request_put(path1 + '?op=append', path1_line2, authheader).code
423
+ assert_equal path1_line1 + path1_line2, client.request_get(path1, authheader).body
424
+
425
+ path2 = '/logs/from/fluentd/hoge002/moge-access-log'
426
+ path2_line1 = "XXXXX___1111111111111111111111111111111\n"
427
+ path2_line2 = "YYYYY___2222222222222222222222222222222222222222222222222\n"
428
+ assert_equal '404', client.request_put(path2 + '?op=append', path2_line1, authheader).code
429
+ assert_equal '201', client.request_post(path2 + '?op=create&overwrite=false', path2_line1, authheader).code
430
+ assert_equal '500', client.request_post(path2 + '?op=create&overwrite=false', path2_line1, authheader).code
431
+ assert_equal path2_line1, client.request_get(path2, authheader).body
432
+ assert_equal '200', client.request_put(path2 + '?op=append', path2_line2, authheader).code
433
+ assert_equal path2_line1 + path2_line2, client.request_get(path2, authheader).body
434
+ assert_equal path2_line1 + path2_line2, get_content('localhost', 14000, path2, authheader)
435
+ end
436
+
437
+ def teardown
438
+ @dummy_server_thread.kill
439
+ @dummy_server_thread.join
440
+ end
441
+ end