xref: /unit/test/test_java_application.py (revision 2073:bc6ad31ce286)
1import io
2import os
3import re
4import time
5
6from unit.applications.lang.java import TestApplicationJava
7from unit.option import option
8from unit.utils import public_dir
9
10
11class TestJavaApplication(TestApplicationJava):
12    prerequisites = {'modules': {'java': 'all'}}
13
14    def test_java_conf_error(self, temp_dir, skip_alert):
15        skip_alert(
16            r'realpath.*failed',
17            r'failed to apply new conf',
18            r'application setup failed',
19        )
20        assert 'error' in self.conf(
21            {
22                "listeners": {"*:7080": {"pass": "applications/app"}},
23                "applications": {
24                    "app": {
25                        "type": self.get_application_type(),
26                        "processes": 1,
27                        "working_directory": option.test_dir + "/java/empty",
28                        "webapp": temp_dir + "/java",
29                        "unit_jars": temp_dir + "/no_such_dir",
30                    }
31                },
32            }
33        ), 'conf error'
34
35    def test_java_war(self, temp_dir):
36        self.load('empty_war')
37
38        assert 'success' in self.conf(
39            '"' + temp_dir + '/java/empty.war"',
40            '/config/applications/empty_war/webapp',
41        ), 'configure war'
42
43        assert self.get()['status'] == 200, 'war'
44
45    def test_java_application_cookies(self):
46        self.load('cookies')
47
48        headers = self.get(
49            headers={
50                'Cookie': 'var1=val1; var2=val2',
51                'Host': 'localhost',
52                'Connection': 'close',
53            }
54        )['headers']
55
56        assert headers['X-Cookie-1'] == 'val1', 'cookie 1'
57        assert headers['X-Cookie-2'] == 'val2', 'cookie 2'
58
59    def test_java_application_filter(self):
60        self.load('filter')
61
62        headers = self.get()['headers']
63
64        assert headers['X-Filter-Before'] == '1', 'filter before'
65        assert headers['X-Filter-After'] == '1', 'filter after'
66
67        assert (
68            self.get(url='/test')['headers']['X-Filter-After'] == '0'
69        ), 'filter after 2'
70
71    def test_java_application_get_variables(self):
72        self.load('get_params')
73
74        headers = self.get(url='/?var1=val1&var2=&var4=val4&var4=foo')[
75            'headers'
76        ]
77
78        assert headers['X-Var-1'] == 'val1', 'GET variables'
79        assert headers['X-Var-2'] == 'true', 'GET variables 2'
80        assert headers['X-Var-3'] == 'false', 'GET variables 3'
81
82        assert (
83            headers['X-Param-Names'] == 'var4 var2 var1 '
84        ), 'getParameterNames'
85        assert headers['X-Param-Values'] == 'val4 foo ', 'getParameterValues'
86        assert (
87            headers['X-Param-Map'] == 'var2= var1=val1 var4=val4,foo '
88        ), 'getParameterMap'
89
90    def test_java_application_post_variables(self):
91        self.load('post_params')
92
93        headers = self.post(
94            headers={
95                'Content-Type': 'application/x-www-form-urlencoded',
96                'Host': 'localhost',
97                'Connection': 'close',
98            },
99            body='var1=val1&var2=',
100        )['headers']
101
102        assert headers['X-Var-1'] == 'val1', 'POST variables'
103        assert headers['X-Var-2'] == 'true', 'POST variables 2'
104        assert headers['X-Var-3'] == 'false', 'POST variables 3'
105
106    def test_java_application_session(self):
107        self.load('session')
108
109        headers = self.get(url='/?var1=val1')['headers']
110        session_id = headers['X-Session-Id']
111
112        assert headers['X-Var-1'] == 'null', 'variable empty'
113        assert headers['X-Session-New'] == 'true', 'session create'
114
115        headers = self.get(
116            headers={
117                'Host': 'localhost',
118                'Cookie': 'JSESSIONID=' + session_id,
119                'Connection': 'close',
120            },
121            url='/?var1=val2',
122        )['headers']
123
124        assert headers['X-Var-1'] == 'val1', 'variable'
125        assert headers['X-Session-New'] == 'false', 'session resume'
126        assert session_id == headers['X-Session-Id'], 'session same id'
127
128    def test_java_application_session_active(self):
129        self.load('session_inactive')
130
131        resp = self.get(
132            headers={
133                'X-Interval': '4',
134                'Host': 'localhost',
135                'Connection': 'close',
136            }
137        )
138        session_id = resp['headers']['X-Session-Id']
139
140        assert resp['status'] == 200, 'session init'
141        assert resp['headers']['X-Session-Interval'] == '4', 'session interval'
142        assert (
143            abs(
144                self.date_to_sec_epoch(
145                    resp['headers']['X-Session-Last-Access-Time']
146                )
147                - self.sec_epoch()
148            )
149            < 5
150        ), 'session last access time'
151
152        time.sleep(1)
153
154        resp = self.get(
155            headers={
156                'Host': 'localhost',
157                'Cookie': 'JSESSIONID=' + session_id,
158                'Connection': 'close',
159            }
160        )
161
162        assert resp['headers']['X-Session-Id'] == session_id, 'session active'
163
164        session_id = resp['headers']['X-Session-Id']
165
166        time.sleep(1)
167
168        resp = self.get(
169            headers={
170                'Host': 'localhost',
171                'Cookie': 'JSESSIONID=' + session_id,
172                'Connection': 'close',
173            }
174        )
175
176        assert resp['headers']['X-Session-Id'] == session_id, 'session active 2'
177
178        time.sleep(2)
179
180        resp = self.get(
181            headers={
182                'Host': 'localhost',
183                'Cookie': 'JSESSIONID=' + session_id,
184                'Connection': 'close',
185            }
186        )
187
188        assert resp['headers']['X-Session-Id'] == session_id, 'session active 3'
189
190    def test_java_application_session_inactive(self):
191        self.load('session_inactive')
192
193        resp = self.get(
194            headers={
195                'X-Interval': '1',
196                'Host': 'localhost',
197                'Connection': 'close',
198            }
199        )
200        session_id = resp['headers']['X-Session-Id']
201
202        time.sleep(3)
203
204        resp = self.get(
205            headers={
206                'Host': 'localhost',
207                'Cookie': 'JSESSIONID=' + session_id,
208                'Connection': 'close',
209            }
210        )
211
212        assert resp['headers']['X-Session-Id'] != session_id, 'session inactive'
213
214    def test_java_application_session_invalidate(self):
215        self.load('session_invalidate')
216
217        resp = self.get()
218        session_id = resp['headers']['X-Session-Id']
219
220        resp = self.get(
221            headers={
222                'Host': 'localhost',
223                'Cookie': 'JSESSIONID=' + session_id,
224                'Connection': 'close',
225            }
226        )
227
228        assert (
229            resp['headers']['X-Session-Id'] != session_id
230        ), 'session invalidate'
231
232    def test_java_application_session_listeners(self):
233        self.load('session_listeners')
234
235        headers = self.get(url='/test?var1=val1')['headers']
236        session_id = headers['X-Session-Id']
237
238        assert headers['X-Session-Created'] == session_id, 'session create'
239        assert headers['X-Attr-Added'] == 'var1=val1', 'attribute add'
240
241        headers = self.get(
242            headers={
243                'Host': 'localhost',
244                'Cookie': 'JSESSIONID=' + session_id,
245                'Connection': 'close',
246            },
247            url='/?var1=val2',
248        )['headers']
249
250        assert session_id == headers['X-Session-Id'], 'session same id'
251        assert headers['X-Attr-Replaced'] == 'var1=val1', 'attribute replace'
252
253        headers = self.get(
254            headers={
255                'Host': 'localhost',
256                'Cookie': 'JSESSIONID=' + session_id,
257                'Connection': 'close',
258            },
259            url='/',
260        )['headers']
261
262        assert session_id == headers['X-Session-Id'], 'session same id'
263        assert headers['X-Attr-Removed'] == 'var1=val2', 'attribute remove'
264
265    def test_java_application_jsp(self):
266        self.load('jsp')
267
268        headers = self.get(url='/index.jsp')['headers']
269
270        assert headers['X-Unit-JSP'] == 'ok', 'JSP Ok header'
271
272    def test_java_application_url_pattern(self):
273        self.load('url_pattern')
274
275        headers = self.get(url='/foo/bar/index.html')['headers']
276
277        assert headers['X-Id'] == 'servlet1', '#1 Servlet1 request'
278        assert (
279            headers['X-Request-URI'] == '/foo/bar/index.html'
280        ), '#1 request URI'
281        assert headers['X-Servlet-Path'] == '/foo/bar', '#1 servlet path'
282        assert headers['X-Path-Info'] == '/index.html', '#1 path info'
283
284        headers = self.get(url='/foo/bar/index.bop')['headers']
285
286        assert headers['X-Id'] == 'servlet1', '#2 Servlet1 request'
287        assert (
288            headers['X-Request-URI'] == '/foo/bar/index.bop'
289        ), '#2 request URI'
290        assert headers['X-Servlet-Path'] == '/foo/bar', '#2 servlet path'
291        assert headers['X-Path-Info'] == '/index.bop', '#2 path info'
292
293        headers = self.get(url='/baz')['headers']
294
295        assert headers['X-Id'] == 'servlet2', '#3 Servlet2 request'
296        assert headers['X-Request-URI'] == '/baz', '#3 request URI'
297        assert headers['X-Servlet-Path'] == '/baz', '#3 servlet path'
298        assert headers['X-Path-Info'] == 'null', '#3 path info'
299
300        headers = self.get(url='/baz/index.html')['headers']
301
302        assert headers['X-Id'] == 'servlet2', '#4 Servlet2 request'
303        assert headers['X-Request-URI'] == '/baz/index.html', '#4 request URI'
304        assert headers['X-Servlet-Path'] == '/baz', '#4 servlet path'
305        assert headers['X-Path-Info'] == '/index.html', '#4 path info'
306
307        headers = self.get(url='/catalog')['headers']
308
309        assert headers['X-Id'] == 'servlet3', '#5 Servlet3 request'
310        assert headers['X-Request-URI'] == '/catalog', '#5 request URI'
311        assert headers['X-Servlet-Path'] == '/catalog', '#5 servlet path'
312        assert headers['X-Path-Info'] == 'null', '#5 path info'
313
314        headers = self.get(url='/catalog/index.html')['headers']
315
316        assert headers['X-Id'] == 'default', '#6 default request'
317        assert (
318            headers['X-Request-URI'] == '/catalog/index.html'
319        ), '#6 request URI'
320        assert (
321            headers['X-Servlet-Path'] == '/catalog/index.html'
322        ), '#6 servlet path'
323        assert headers['X-Path-Info'] == 'null', '#6 path info'
324
325        headers = self.get(url='/catalog/racecar.bop')['headers']
326
327        assert headers['X-Id'] == 'servlet4', '#7 servlet4 request'
328        assert (
329            headers['X-Request-URI'] == '/catalog/racecar.bop'
330        ), '#7 request URI'
331        assert (
332            headers['X-Servlet-Path'] == '/catalog/racecar.bop'
333        ), '#7 servlet path'
334        assert headers['X-Path-Info'] == 'null', '#7 path info'
335
336        headers = self.get(url='/index.bop')['headers']
337
338        assert headers['X-Id'] == 'servlet4', '#8 servlet4 request'
339        assert headers['X-Request-URI'] == '/index.bop', '#8 request URI'
340        assert headers['X-Servlet-Path'] == '/index.bop', '#8 servlet path'
341        assert headers['X-Path-Info'] == 'null', '#8 path info'
342
343        headers = self.get(url='/foo/baz')['headers']
344
345        assert headers['X-Id'] == 'servlet0', '#9 servlet0 request'
346        assert headers['X-Request-URI'] == '/foo/baz', '#9 request URI'
347        assert headers['X-Servlet-Path'] == '/foo', '#9 servlet path'
348        assert headers['X-Path-Info'] == '/baz', '#9 path info'
349
350        headers = self.get()['headers']
351
352        assert headers['X-Id'] == 'default', '#10 default request'
353        assert headers['X-Request-URI'] == '/', '#10 request URI'
354        assert headers['X-Servlet-Path'] == '/', '#10 servlet path'
355        assert headers['X-Path-Info'] == 'null', '#10 path info'
356
357        headers = self.get(url='/index.bop/')['headers']
358
359        assert headers['X-Id'] == 'default', '#11 default request'
360        assert headers['X-Request-URI'] == '/index.bop/', '#11 request URI'
361        assert headers['X-Servlet-Path'] == '/index.bop/', '#11 servlet path'
362        assert headers['X-Path-Info'] == 'null', '#11 path info'
363
364    def test_java_application_header(self):
365        self.load('header')
366
367        headers = self.get()['headers']
368
369        assert headers['X-Set-Utf8-Value'] == '????', 'set Utf8 header value'
370        assert headers['X-Set-Utf8-Name-???'] == 'x', 'set Utf8 header name'
371        assert headers['X-Add-Utf8-Value'] == '????', 'add Utf8 header value'
372        assert headers['X-Add-Utf8-Name-???'] == 'y', 'add Utf8 header name'
373        assert headers['X-Add-Test'] == 'v1', 'add null header'
374        assert ('X-Set-Test1' in headers) == False, 'set null header'
375        assert headers['X-Set-Test2'] == '', 'set empty header'
376
377    def test_java_application_content_type(self):
378        self.load('content_type')
379
380        headers = self.get(url='/1')['headers']
381
382        assert (
383            headers['Content-Type'] == 'text/plain;charset=utf-8'
384        ), '#1 Content-Type header'
385        assert (
386            headers['X-Content-Type'] == 'text/plain;charset=utf-8'
387        ), '#1 response Content-Type'
388        assert headers['X-Character-Encoding'] == 'utf-8', '#1 response charset'
389
390        headers = self.get(url='/2')['headers']
391
392        assert (
393            headers['Content-Type'] == 'text/plain;charset=iso-8859-1'
394        ), '#2 Content-Type header'
395        assert (
396            headers['X-Content-Type'] == 'text/plain;charset=iso-8859-1'
397        ), '#2 response Content-Type'
398        assert (
399            headers['X-Character-Encoding'] == 'iso-8859-1'
400        ), '#2 response charset'
401
402        headers = self.get(url='/3')['headers']
403
404        assert (
405            headers['Content-Type'] == 'text/plain;charset=windows-1251'
406        ), '#3 Content-Type header'
407        assert (
408            headers['X-Content-Type'] == 'text/plain;charset=windows-1251'
409        ), '#3 response Content-Type'
410        assert (
411            headers['X-Character-Encoding'] == 'windows-1251'
412        ), '#3 response charset'
413
414        headers = self.get(url='/4')['headers']
415
416        assert (
417            headers['Content-Type'] == 'text/plain;charset=windows-1251'
418        ), '#4 Content-Type header'
419        assert (
420            headers['X-Content-Type'] == 'text/plain;charset=windows-1251'
421        ), '#4 response Content-Type'
422        assert (
423            headers['X-Character-Encoding'] == 'windows-1251'
424        ), '#4 response charset'
425
426        headers = self.get(url='/5')['headers']
427
428        assert (
429            headers['Content-Type'] == 'text/plain;charset=iso-8859-1'
430        ), '#5 Content-Type header'
431        assert (
432            headers['X-Content-Type'] == 'text/plain;charset=iso-8859-1'
433        ), '#5 response Content-Type'
434        assert (
435            headers['X-Character-Encoding'] == 'iso-8859-1'
436        ), '#5 response charset'
437
438        headers = self.get(url='/6')['headers']
439
440        assert ('Content-Type' in headers) == False, '#6 no Content-Type header'
441        assert (
442            'X-Content-Type' in headers
443        ) == False, '#6 no response Content-Type'
444        assert headers['X-Character-Encoding'] == 'utf-8', '#6 response charset'
445
446        headers = self.get(url='/7')['headers']
447
448        assert (
449            headers['Content-Type'] == 'text/plain;charset=utf-8'
450        ), '#7 Content-Type header'
451        assert (
452            headers['X-Content-Type'] == 'text/plain;charset=utf-8'
453        ), '#7 response Content-Type'
454        assert headers['X-Character-Encoding'] == 'utf-8', '#7 response charset'
455
456        headers = self.get(url='/8')['headers']
457
458        assert (
459            headers['Content-Type'] == 'text/html;charset=utf-8'
460        ), '#8 Content-Type header'
461        assert (
462            headers['X-Content-Type'] == 'text/html;charset=utf-8'
463        ), '#8 response Content-Type'
464        assert headers['X-Character-Encoding'] == 'utf-8', '#8 response charset'
465
466    def test_java_application_welcome_files(self):
467        self.load('welcome_files')
468
469        headers = self.get()['headers']
470
471        resp = self.get(url='/dir1')
472
473        assert resp['status'] == 302, 'dir redirect expected'
474
475        resp = self.get(url='/dir1/')
476
477        assert ('This is index.txt.' in resp['body']) == True, 'dir1 index body'
478        assert resp['headers']['X-TXT-Filter'] == '1', 'TXT Filter header'
479
480        headers = self.get(url='/dir2/')['headers']
481
482        assert headers['X-Unit-JSP'] == 'ok', 'JSP Ok header'
483        assert headers['X-JSP-Filter'] == '1', 'JSP Filter header'
484
485        headers = self.get(url='/dir3/')['headers']
486
487        assert (
488            headers['X-App-Servlet'] == '1'
489        ), 'URL pattern overrides welcome file'
490
491        headers = self.get(url='/dir4/')['headers']
492
493        assert (
494            'X-App-Servlet' in headers
495        ) == False, 'Static welcome file served first'
496
497        headers = self.get(url='/dir5/')['headers']
498
499        assert (
500            headers['X-App-Servlet'] == '1'
501        ), 'Servlet for welcome file served when no static file found'
502
503    def test_java_application_request_listeners(self):
504        self.load('request_listeners')
505
506        headers = self.get(url='/test1')['headers']
507
508        assert (
509            headers['X-Request-Initialized'] == '/test1'
510        ), 'request initialized event'
511        assert headers['X-Request-Destroyed'] == '', 'request destroyed event'
512        assert headers['X-Attr-Added'] == '', 'attribute added event'
513        assert headers['X-Attr-Removed'] == '', 'attribute removed event'
514        assert headers['X-Attr-Replaced'] == '', 'attribute replaced event'
515
516        headers = self.get(url='/test2?var1=1')['headers']
517
518        assert (
519            headers['X-Request-Initialized'] == '/test2'
520        ), 'request initialized event'
521        assert (
522            headers['X-Request-Destroyed'] == '/test1'
523        ), 'request destroyed event'
524        assert headers['X-Attr-Added'] == 'var=1;', 'attribute added event'
525        assert headers['X-Attr-Removed'] == 'var=1;', 'attribute removed event'
526        assert headers['X-Attr-Replaced'] == '', 'attribute replaced event'
527
528        headers = self.get(url='/test3?var1=1&var2=2')['headers']
529
530        assert (
531            headers['X-Request-Initialized'] == '/test3'
532        ), 'request initialized event'
533        assert (
534            headers['X-Request-Destroyed'] == '/test2'
535        ), 'request destroyed event'
536        assert headers['X-Attr-Added'] == 'var=1;', 'attribute added event'
537        assert headers['X-Attr-Removed'] == 'var=2;', 'attribute removed event'
538        assert (
539            headers['X-Attr-Replaced'] == 'var=1;'
540        ), 'attribute replaced event'
541
542        headers = self.get(url='/test4?var1=1&var2=2&var3=3')['headers']
543
544        assert (
545            headers['X-Request-Initialized'] == '/test4'
546        ), 'request initialized event'
547        assert (
548            headers['X-Request-Destroyed'] == '/test3'
549        ), 'request destroyed event'
550        assert headers['X-Attr-Added'] == 'var=1;', 'attribute added event'
551        assert headers['X-Attr-Removed'] == '', 'attribute removed event'
552        assert (
553            headers['X-Attr-Replaced'] == 'var=1;var=2;'
554        ), 'attribute replaced event'
555
556    def test_java_application_request_uri_forward(self):
557        self.load('forward')
558
559        resp = self.get(
560            url='/fwd?uri=%2Fdata%2Ftest%3Furi%3Dnew_uri%26a%3D2%26b%3D3&a=1&c=4'
561        )
562        headers = resp['headers']
563
564        assert (
565            headers['X-REQUEST-Id'] == 'fwd'
566        ), 'initial request servlet mapping'
567        assert (
568            headers['X-Forward-To'] == '/data/test?uri=new_uri&a=2&b=3'
569        ), 'forwarding triggered'
570        assert (
571            headers['X-REQUEST-Param-uri'] == '/data/test?uri=new_uri&a=2&b=3'
572        ), 'original uri parameter'
573        assert headers['X-REQUEST-Param-a'] == '1', 'original a parameter'
574        assert headers['X-REQUEST-Param-c'] == '4', 'original c parameter'
575
576        assert (
577            headers['X-FORWARD-Id'] == 'data'
578        ), 'forward request servlet mapping'
579        assert (
580            headers['X-FORWARD-Request-URI'] == '/data/test'
581        ), 'forward request uri'
582        assert (
583            headers['X-FORWARD-Servlet-Path'] == '/data'
584        ), 'forward request servlet path'
585        assert (
586            headers['X-FORWARD-Path-Info'] == '/test'
587        ), 'forward request path info'
588        assert (
589            headers['X-FORWARD-Query-String'] == 'uri=new_uri&a=2&b=3'
590        ), 'forward request query string'
591        assert (
592            headers['X-FORWARD-Param-uri']
593            == 'new_uri,/data/test?uri=new_uri&a=2&b=3'
594        ), 'forward uri parameter'
595        assert headers['X-FORWARD-Param-a'] == '2,1', 'forward a parameter'
596        assert headers['X-FORWARD-Param-b'] == '3', 'forward b parameter'
597        assert headers['X-FORWARD-Param-c'] == '4', 'forward c parameter'
598
599        assert (
600            headers['X-javax.servlet.forward.request_uri'] == '/fwd'
601        ), 'original request uri'
602        assert (
603            headers['X-javax.servlet.forward.context_path'] == ''
604        ), 'original request context path'
605        assert (
606            headers['X-javax.servlet.forward.servlet_path'] == '/fwd'
607        ), 'original request servlet path'
608        assert (
609            headers['X-javax.servlet.forward.path_info'] == 'null'
610        ), 'original request path info'
611        assert (
612            headers['X-javax.servlet.forward.query_string']
613            == 'uri=%2Fdata%2Ftest%3Furi%3Dnew_uri%26a%3D2%26b%3D3&a=1&c=4'
614        ), 'original request query'
615
616        assert (
617            'Before forwarding' in resp['body']
618        ) == False, 'discarded data added before forward() call'
619        assert (
620            'X-After-Forwarding' in headers
621        ) == False, 'cannot add headers after forward() call'
622        assert (
623            'After forwarding' in resp['body']
624        ) == False, 'cannot add data after forward() call'
625
626    def test_java_application_named_dispatcher_forward(self):
627        self.load('forward')
628
629        resp = self.get(url='/fwd?disp=name&uri=data')
630        headers = resp['headers']
631
632        assert (
633            headers['X-REQUEST-Id'] == 'fwd'
634        ), 'initial request servlet mapping'
635        assert headers['X-Forward-To'] == 'data', 'forwarding triggered'
636
637        assert (
638            headers['X-FORWARD-Id'] == 'data'
639        ), 'forward request servlet mapping'
640        assert headers['X-FORWARD-Request-URI'] == '/fwd', 'forward request uri'
641        assert (
642            headers['X-FORWARD-Servlet-Path'] == '/fwd'
643        ), 'forward request servlet path'
644        assert (
645            headers['X-FORWARD-Path-Info'] == 'null'
646        ), 'forward request path info'
647        assert (
648            headers['X-FORWARD-Query-String'] == 'disp=name&uri=data'
649        ), 'forward request query string'
650
651        assert (
652            headers['X-javax.servlet.forward.request_uri'] == 'null'
653        ), 'original request uri'
654        assert (
655            headers['X-javax.servlet.forward.context_path'] == 'null'
656        ), 'original request context path'
657        assert (
658            headers['X-javax.servlet.forward.servlet_path'] == 'null'
659        ), 'original request servlet path'
660        assert (
661            headers['X-javax.servlet.forward.path_info'] == 'null'
662        ), 'original request path info'
663        assert (
664            headers['X-javax.servlet.forward.query_string'] == 'null'
665        ), 'original request query'
666
667        assert (
668            'Before forwarding' in resp['body']
669        ) == False, 'discarded data added before forward() call'
670        assert (
671            'X-After-Forwarding' in headers
672        ) == False, 'cannot add headers after forward() call'
673        assert (
674            'After forwarding' in resp['body']
675        ) == False, 'cannot add data after forward() call'
676
677    def test_java_application_request_uri_include(self):
678        self.load('include')
679
680        resp = self.get(url='/inc?uri=/data/test')
681        headers = resp['headers']
682        body = resp['body']
683
684        assert (
685            headers['X-REQUEST-Id'] == 'inc'
686        ), 'initial request servlet mapping'
687        assert headers['X-Include'] == '/data/test', 'including triggered'
688
689        assert (
690            'X-INCLUDE-Id' in headers
691        ) == False, 'unable to add headers in include request'
692
693        assert (
694            'javax.servlet.include.request_uri:  /data/test' in body
695        ) == True, 'include request uri'
696        # assert (
697        #    'javax.servlet.include.context_path: ' in body
698        # ) == True, 'include request context path'
699        assert (
700            'javax.servlet.include.servlet_path: /data' in body
701        ) == True, 'include request servlet path'
702        assert (
703            'javax.servlet.include.path_info:    /test' in body
704        ) == True, 'include request path info'
705        assert (
706            'javax.servlet.include.query_string: null' in body
707        ) == True, 'include request query'
708
709        assert (
710            'Before include' in body
711        ) == True, 'preserve data added before include() call'
712        assert (
713            headers['X-After-Include'] == 'you-should-see-this'
714        ), 'add headers after include() call'
715        assert (
716            'After include' in body
717        ) == True, 'add data after include() call'
718
719    def test_java_application_named_dispatcher_include(self):
720        self.load('include')
721
722        resp = self.get(url='/inc?disp=name&uri=data')
723        headers = resp['headers']
724        body = resp['body']
725
726        assert (
727            headers['X-REQUEST-Id'] == 'inc'
728        ), 'initial request servlet mapping'
729        assert headers['X-Include'] == 'data', 'including triggered'
730
731        assert (
732            'X-INCLUDE-Id' in headers
733        ) == False, 'unable to add headers in include request'
734
735        assert (
736            'javax.servlet.include.request_uri:  null' in body
737        ) == True, 'include request uri'
738        # assert (
739        #    'javax.servlet.include.context_path: null' in body
740        # ) == True, 'include request context path'
741        assert (
742            'javax.servlet.include.servlet_path: null' in body
743        ) == True, 'include request servlet path'
744        assert (
745            'javax.servlet.include.path_info:    null' in body
746        ) == True, 'include request path info'
747        assert (
748            'javax.servlet.include.query_string: null' in body
749        ) == True, 'include request query'
750
751        assert (
752            'Before include' in body
753        ) == True, 'preserve data added before include() call'
754        assert (
755            headers['X-After-Include'] == 'you-should-see-this'
756        ), 'add headers after include() call'
757        assert (
758            'After include' in body
759        ) == True, 'add data after include() call'
760
761    def test_java_application_path_translation(self):
762        self.load('path_translation')
763
764        headers = self.get(url='/pt/test?path=/')['headers']
765
766        assert headers['X-Servlet-Path'] == '/pt', 'matched servlet path'
767        assert headers['X-Path-Info'] == '/test', 'the rest of the path'
768        assert (
769            headers['X-Path-Translated']
770            == headers['X-Real-Path'] + headers['X-Path-Info']
771        ), 'translated path is the app root + path info'
772        assert (
773            headers['X-Resource-Paths'].endswith('/WEB-INF/, /index.html]')
774            == True
775        ), 'app root directory content'
776        assert (
777            headers['X-Resource-As-Stream'] == 'null'
778        ), 'no resource stream for root path'
779
780        headers = self.get(url='/test?path=/none')['headers']
781
782        assert headers['X-Servlet-Path'] == '/test', 'matched whole path'
783        assert (
784            headers['X-Path-Info'] == 'null'
785        ), 'the rest of the path is null, whole path matched'
786        assert (
787            headers['X-Path-Translated'] == 'null'
788        ), 'translated path is null because path info is null'
789        assert (
790            headers['X-Real-Path'].endswith('/none') == True
791        ), 'read path is not null'
792        assert headers['X-Resource-Paths'] == 'null', 'no resource found'
793        assert headers['X-Resource-As-Stream'] == 'null', 'no resource stream'
794
795    def test_java_application_query_string(self):
796        self.load('query_string')
797
798        assert (
799            self.get(url='/?a=b')['headers']['X-Query-String'] == 'a=b'
800        ), 'query string'
801
802    def test_java_application_query_empty(self):
803        self.load('query_string')
804
805        assert (
806            self.get(url='/?')['headers']['X-Query-String'] == ''
807        ), 'query string empty'
808
809    def test_java_application_query_absent(self):
810        self.load('query_string')
811
812        assert (
813            self.get()['headers']['X-Query-String'] == 'null'
814        ), 'query string absent'
815
816    def test_java_application_empty(self):
817        self.load('empty')
818
819        assert self.get()['status'] == 200, 'empty'
820
821    def test_java_application_keepalive_body(self):
822        self.load('mirror')
823
824        assert self.post()['status'] == 200, 'init'
825
826        body = '0123456789' * 500
827        (resp, sock) = self.post(
828            headers={
829                'Connection': 'keep-alive',
830                'Content-Type': 'text/html',
831                'Host': 'localhost',
832            },
833            start=True,
834            body=body,
835            read_timeout=1,
836        )
837
838        assert resp['body'] == body, 'keep-alive 1'
839
840        body = '0123456789'
841        resp = self.post(
842            headers={
843                'Connection': 'close',
844                'Content-Type': 'text/html',
845                'Host': 'localhost',
846            },
847            sock=sock,
848            body=body,
849        )
850
851        assert resp['body'] == body, 'keep-alive 2'
852
853    def test_java_application_http_10(self):
854        self.load('empty')
855
856        assert self.get(http_10=True)['status'] == 200, 'HTTP 1.0'
857
858    def test_java_application_no_method(self):
859        self.load('empty')
860
861        assert self.post()['status'] == 405, 'no method'
862
863    def test_java_application_get_header(self):
864        self.load('get_header')
865
866        assert (
867            self.get(
868                headers={
869                    'X-Header': 'blah',
870                    'Content-Type': 'text/html',
871                    'Host': 'localhost',
872                    'Connection': 'close',
873                }
874            )['headers']['X-Reply']
875            == 'blah'
876        ), 'get header'
877
878    def test_java_application_get_header_empty(self):
879        self.load('get_header')
880
881        assert 'X-Reply' not in self.get()['headers'], 'get header empty'
882
883    def test_java_application_get_headers(self):
884        self.load('get_headers')
885
886        headers = self.get(
887            headers={
888                'X-Header': ['blah', 'blah'],
889                'Content-Type': 'text/html',
890                'Host': 'localhost',
891                'Connection': 'close',
892            }
893        )['headers']
894
895        assert headers['X-Reply-0'] == 'blah', 'get headers'
896        assert headers['X-Reply-1'] == 'blah', 'get headers 2'
897
898    def test_java_application_get_headers_empty(self):
899        self.load('get_headers')
900
901        assert 'X-Reply-0' not in self.get()['headers'], 'get headers empty'
902
903    def test_java_application_get_header_names(self):
904        self.load('get_header_names')
905
906        headers = self.get()['headers']
907
908        assert re.search(
909            r'(?:Host|Connection)', headers['X-Reply-0']
910        ), 'get header names'
911        assert re.search(
912            r'(?:Host|Connection)', headers['X-Reply-1']
913        ), 'get header names 2'
914        assert (
915            headers['X-Reply-0'] != headers['X-Reply-1']
916        ), 'get header names not equal'
917
918    def test_java_application_header_int(self):
919        self.load('header_int')
920
921        headers = self.get(
922            headers={
923                'X-Header': '2',
924                'Content-Type': 'text/html',
925                'Host': 'localhost',
926                'Connection': 'close',
927            }
928        )['headers']
929
930        assert headers['X-Set-Int'] == '1', 'set int header'
931        assert headers['X-Get-Int'] == '2', 'get int header'
932
933    def test_java_application_header_date(self):
934        self.load('header_date')
935
936        date = 'Fri, 15 Mar 2019 14:45:34 GMT'
937
938        headers = self.get(
939            headers={
940                'X-Header': date,
941                'Content-Type': 'text/html',
942                'Host': 'localhost',
943                'Connection': 'close',
944            }
945        )['headers']
946
947        assert (
948            headers['X-Set-Date'] == 'Thu, 01 Jan 1970 00:00:01 GMT'
949        ), 'set date header'
950        assert headers['X-Get-Date'] == date, 'get date header'
951
952    def test_java_application_multipart(self, temp_dir):
953        self.load('multipart')
954
955        reldst = '/uploads'
956        fulldst = temp_dir + reldst
957        os.mkdir(fulldst)
958        public_dir(fulldst)
959
960        fields = {
961            'file': {
962                'filename': 'sample.txt',
963                'type': 'text/plain',
964                'data': io.StringIO('Data from sample file'),
965            },
966            'destination': fulldst,
967            'upload': 'Upload',
968        }
969
970        encoded, content_type = self.multipart_encode(fields)
971
972        preamble = 'Preamble. Should be ignored.'
973        epilogue = 'Epilogue. Should be ignored.'
974        body = "%s\r\n%s\r\n%s" % (preamble, encoded.decode(), epilogue)
975
976        resp = self.post(
977            headers={
978                'Content-Type': content_type,
979                'Host': 'localhost',
980                'Connection': 'close',
981            },
982            body=body,
983        )
984
985        assert resp['status'] == 200, 'multipart status'
986        assert re.search(r'sample\.txt created', resp['body']), 'multipart body'
987        assert (
988            self.search_in_log(
989                r'^Data from sample file$', name=reldst + '/sample.txt'
990            )
991            is not None
992        ), 'file created'
993
994    def test_java_application_threads(self):
995        self.load('threads')
996
997        assert 'success' in self.conf(
998            '4', 'applications/threads/threads'
999        ), 'configure 4 threads'
1000
1001        socks = []
1002
1003        for i in range(4):
1004            (_, sock) = self.get(
1005                headers={
1006                    'Host': 'localhost',
1007                    'X-Delay': '2',
1008                    'Connection': 'close',
1009                },
1010                no_recv=True,
1011                start=True,
1012            )
1013
1014            socks.append(sock)
1015
1016            time.sleep(0.25)  # required to avoid greedy request reading
1017
1018        threads = set()
1019
1020        for sock in socks:
1021            resp = self.recvall(sock).decode('utf-8')
1022
1023            self.log_in(resp)
1024
1025            resp = self._resp_to_dict(resp)
1026
1027            assert resp['status'] == 200, 'status'
1028
1029            threads.add(resp['headers']['X-Thread'])
1030
1031            sock.close()
1032
1033        assert len(socks) == len(threads), 'threads differs'
1034