1*1283Szelenkov@nginx.comimport re 2899Szelenkov@nginx.comimport time 3484Szelenkov@nginx.comimport unittest 41019Szelenkov@nginx.comfrom unit.applications.lang.python import TestApplicationPython 5484Szelenkov@nginx.com 61017Szelenkov@nginx.com 71019Szelenkov@nginx.comclass TestPythonApplication(TestApplicationPython): 81165Szelenkov@nginx.com prerequisites = {'modules': ['python']} 9484Szelenkov@nginx.com 10*1283Szelenkov@nginx.com def findall(self, pattern): 11*1283Szelenkov@nginx.com with open(self.testdir + '/unit.log', 'r', errors='ignore') as f: 12*1283Szelenkov@nginx.com return re.findall(pattern, f.read()) 13*1283Szelenkov@nginx.com 14552Szelenkov@nginx.com def test_python_application_variables(self): 15552Szelenkov@nginx.com self.load('variables') 16484Szelenkov@nginx.com 17484Szelenkov@nginx.com body = 'Test body string.' 18484Szelenkov@nginx.com 191017Szelenkov@nginx.com resp = self.post( 201017Szelenkov@nginx.com headers={ 211017Szelenkov@nginx.com 'Host': 'localhost', 221017Szelenkov@nginx.com 'Content-Type': 'text/html', 231017Szelenkov@nginx.com 'Custom-Header': 'blah', 241017Szelenkov@nginx.com 'Connection': 'close', 251017Szelenkov@nginx.com }, 261017Szelenkov@nginx.com body=body, 271017Szelenkov@nginx.com ) 28484Szelenkov@nginx.com 29505Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'status') 30505Szelenkov@nginx.com headers = resp['headers'] 31674Szelenkov@nginx.com header_server = headers.pop('Server') 32674Szelenkov@nginx.com self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') 331017Szelenkov@nginx.com self.assertEqual( 341017Szelenkov@nginx.com headers.pop('Server-Software'), 351017Szelenkov@nginx.com header_server, 361017Szelenkov@nginx.com 'server software header', 371017Szelenkov@nginx.com ) 38599Szelenkov@nginx.com 39599Szelenkov@nginx.com date = headers.pop('Date') 40599Szelenkov@nginx.com self.assertEqual(date[-4:], ' GMT', 'date header timezone') 411017Szelenkov@nginx.com self.assertLess( 421017Szelenkov@nginx.com abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 431017Szelenkov@nginx.com 5, 441017Szelenkov@nginx.com 'date header', 451017Szelenkov@nginx.com ) 46599Szelenkov@nginx.com 471017Szelenkov@nginx.com self.assertDictEqual( 481017Szelenkov@nginx.com headers, 491017Szelenkov@nginx.com { 501017Szelenkov@nginx.com 'Connection': 'close', 511017Szelenkov@nginx.com 'Content-Length': str(len(body)), 521017Szelenkov@nginx.com 'Content-Type': 'text/html', 531017Szelenkov@nginx.com 'Request-Method': 'POST', 541017Szelenkov@nginx.com 'Request-Uri': '/', 551017Szelenkov@nginx.com 'Http-Host': 'localhost', 561017Szelenkov@nginx.com 'Server-Protocol': 'HTTP/1.1', 571017Szelenkov@nginx.com 'Custom-Header': 'blah', 581017Szelenkov@nginx.com 'Wsgi-Version': '(1, 0)', 591017Szelenkov@nginx.com 'Wsgi-Url-Scheme': 'http', 601017Szelenkov@nginx.com 'Wsgi-Multithread': 'False', 611017Szelenkov@nginx.com 'Wsgi-Multiprocess': 'True', 621017Szelenkov@nginx.com 'Wsgi-Run-Once': 'False', 631017Szelenkov@nginx.com }, 641017Szelenkov@nginx.com 'headers', 651017Szelenkov@nginx.com ) 66505Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'body') 67484Szelenkov@nginx.com 68497Szelenkov@nginx.com def test_python_application_query_string(self): 69552Szelenkov@nginx.com self.load('query_string') 70497Szelenkov@nginx.com 71505Szelenkov@nginx.com resp = self.get(url='/?var1=val1&var2=val2') 72497Szelenkov@nginx.com 731017Szelenkov@nginx.com self.assertEqual( 741017Szelenkov@nginx.com resp['headers']['Query-String'], 751017Szelenkov@nginx.com 'var1=val1&var2=val2', 761017Szelenkov@nginx.com 'Query-String header', 771017Szelenkov@nginx.com ) 78497Szelenkov@nginx.com 791171Svbart@nginx.com def test_python_application_query_string_space(self): 801171Svbart@nginx.com self.load('query_string') 811171Svbart@nginx.com 821171Svbart@nginx.com resp = self.get(url='/ ?var1=val1&var2=val2') 831171Svbart@nginx.com self.assertEqual( 841171Svbart@nginx.com resp['headers']['Query-String'], 851171Svbart@nginx.com 'var1=val1&var2=val2', 861171Svbart@nginx.com 'Query-String space', 871171Svbart@nginx.com ) 881171Svbart@nginx.com 891171Svbart@nginx.com resp = self.get(url='/ %20?var1=val1&var2=val2') 901171Svbart@nginx.com self.assertEqual( 911171Svbart@nginx.com resp['headers']['Query-String'], 921171Svbart@nginx.com 'var1=val1&var2=val2', 931171Svbart@nginx.com 'Query-String space 2', 941171Svbart@nginx.com ) 951171Svbart@nginx.com 961171Svbart@nginx.com resp = self.get(url='/ %20 ?var1=val1&var2=val2') 971171Svbart@nginx.com self.assertEqual( 981171Svbart@nginx.com resp['headers']['Query-String'], 991171Svbart@nginx.com 'var1=val1&var2=val2', 1001171Svbart@nginx.com 'Query-String space 3', 1011171Svbart@nginx.com ) 1021171Svbart@nginx.com 1031171Svbart@nginx.com resp = self.get(url='/blah %20 blah? var1= val1 & var2=val2') 1041171Svbart@nginx.com self.assertEqual( 1051171Svbart@nginx.com resp['headers']['Query-String'], 1061171Svbart@nginx.com ' var1= val1 & var2=val2', 1071171Svbart@nginx.com 'Query-String space 4', 1081171Svbart@nginx.com ) 1091171Svbart@nginx.com 110894Szelenkov@nginx.com def test_python_application_query_string_empty(self): 111894Szelenkov@nginx.com self.load('query_string') 112894Szelenkov@nginx.com 113894Szelenkov@nginx.com resp = self.get(url='/?') 114894Szelenkov@nginx.com 115894Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'query string empty status') 1161017Szelenkov@nginx.com self.assertEqual( 1171017Szelenkov@nginx.com resp['headers']['Query-String'], '', 'query string empty' 1181017Szelenkov@nginx.com ) 119894Szelenkov@nginx.com 120894Szelenkov@nginx.com def test_python_application_query_string_absent(self): 121894Szelenkov@nginx.com self.load('query_string') 122894Szelenkov@nginx.com 123894Szelenkov@nginx.com resp = self.get() 124894Szelenkov@nginx.com 125894Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'query string absent status') 1261017Szelenkov@nginx.com self.assertEqual( 1271017Szelenkov@nginx.com resp['headers']['Query-String'], '', 'query string absent' 1281017Szelenkov@nginx.com ) 129894Szelenkov@nginx.com 1301064Szelenkov@nginx.com @unittest.skip('not yet') 131495Szelenkov@nginx.com def test_python_application_server_port(self): 132552Szelenkov@nginx.com self.load('server_port') 133495Szelenkov@nginx.com 1341017Szelenkov@nginx.com self.assertEqual( 1351017Szelenkov@nginx.com self.get()['headers']['Server-Port'], '7080', 'Server-Port header' 1361017Szelenkov@nginx.com ) 137484Szelenkov@nginx.com 1381250Szelenkov@nginx.com @unittest.skip('not yet') 1391250Szelenkov@nginx.com def test_python_application_working_directory_invalid(self): 1401250Szelenkov@nginx.com self.load('empty') 1411250Szelenkov@nginx.com 1421250Szelenkov@nginx.com self.assertIn( 1431250Szelenkov@nginx.com 'success', 1441250Szelenkov@nginx.com self.conf('"/blah"', 'applications/empty/working_directory'), 1451250Szelenkov@nginx.com 'configure invalid working_directory', 1461250Szelenkov@nginx.com ) 1471250Szelenkov@nginx.com 1481250Szelenkov@nginx.com self.assertEqual(self.get()['status'], 500, 'status') 1491250Szelenkov@nginx.com 150496Szelenkov@nginx.com def test_python_application_204_transfer_encoding(self): 151552Szelenkov@nginx.com self.load('204_no_content') 152496Szelenkov@nginx.com 1531017Szelenkov@nginx.com self.assertNotIn( 1541017Szelenkov@nginx.com 'Transfer-Encoding', 1551017Szelenkov@nginx.com self.get()['headers'], 1561017Szelenkov@nginx.com '204 header transfer encoding', 1571017Szelenkov@nginx.com ) 158484Szelenkov@nginx.com 159602Szelenkov@nginx.com def test_python_application_ctx_iter_atexit(self): 160602Szelenkov@nginx.com self.load('ctx_iter_atexit') 161602Szelenkov@nginx.com 1621017Szelenkov@nginx.com resp = self.post( 1631017Szelenkov@nginx.com headers={ 1641017Szelenkov@nginx.com 'Host': 'localhost', 1651017Szelenkov@nginx.com 'Connection': 'close', 1661017Szelenkov@nginx.com 'Content-Type': 'text/html', 1671017Szelenkov@nginx.com }, 1681017Szelenkov@nginx.com body='0123456789', 1691017Szelenkov@nginx.com ) 170602Szelenkov@nginx.com 171602Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'ctx iter status') 172602Szelenkov@nginx.com self.assertEqual(resp['body'], '0123456789', 'ctx iter body') 173602Szelenkov@nginx.com 1741017Szelenkov@nginx.com self.conf({"listeners": {}, "applications": {}}) 175602Szelenkov@nginx.com 176602Szelenkov@nginx.com self.stop() 177602Szelenkov@nginx.com 1781017Szelenkov@nginx.com self.assertIsNotNone( 1791028Szelenkov@nginx.com self.wait_for_record(r'RuntimeError'), 'ctx iter atexit' 1801017Szelenkov@nginx.com ) 181602Szelenkov@nginx.com 182603Szelenkov@nginx.com def test_python_keepalive_body(self): 183603Szelenkov@nginx.com self.load('mirror') 184603Szelenkov@nginx.com 1851029Szelenkov@nginx.com self.assertEqual(self.get()['status'], 200, 'init') 1861029Szelenkov@nginx.com 1871017Szelenkov@nginx.com (resp, sock) = self.post( 1881017Szelenkov@nginx.com headers={ 1891017Szelenkov@nginx.com 'Host': 'localhost', 1901017Szelenkov@nginx.com 'Connection': 'keep-alive', 1911017Szelenkov@nginx.com 'Content-Type': 'text/html', 1921017Szelenkov@nginx.com }, 1931017Szelenkov@nginx.com start=True, 1941017Szelenkov@nginx.com body='0123456789' * 500, 1951029Szelenkov@nginx.com read_timeout=1, 1961017Szelenkov@nginx.com ) 197603Szelenkov@nginx.com 198603Szelenkov@nginx.com self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1') 199603Szelenkov@nginx.com 2001017Szelenkov@nginx.com resp = self.post( 2011017Szelenkov@nginx.com headers={ 2021017Szelenkov@nginx.com 'Host': 'localhost', 2031017Szelenkov@nginx.com 'Connection': 'close', 2041017Szelenkov@nginx.com 'Content-Type': 'text/html', 2051017Szelenkov@nginx.com }, 2061017Szelenkov@nginx.com sock=sock, 2071017Szelenkov@nginx.com body='0123456789', 2081017Szelenkov@nginx.com ) 209603Szelenkov@nginx.com 210603Szelenkov@nginx.com self.assertEqual(resp['body'], '0123456789', 'keep-alive 2') 211603Szelenkov@nginx.com 212684Szelenkov@nginx.com def test_python_keepalive_reconfigure(self): 2131017Szelenkov@nginx.com self.skip_alerts.extend( 2141017Szelenkov@nginx.com [ 2151017Szelenkov@nginx.com r'pthread_mutex.+failed', 2161017Szelenkov@nginx.com r'failed to apply', 2171017Szelenkov@nginx.com r'process \d+ exited on signal', 2181017Szelenkov@nginx.com ] 2191017Szelenkov@nginx.com ) 220684Szelenkov@nginx.com self.load('mirror') 221684Szelenkov@nginx.com 2221029Szelenkov@nginx.com self.assertEqual(self.get()['status'], 200, 'init') 2231029Szelenkov@nginx.com 224684Szelenkov@nginx.com body = '0123456789' 225684Szelenkov@nginx.com conns = 3 226684Szelenkov@nginx.com socks = [] 227684Szelenkov@nginx.com 228684Szelenkov@nginx.com for i in range(conns): 2291017Szelenkov@nginx.com (resp, sock) = self.post( 2301017Szelenkov@nginx.com headers={ 2311017Szelenkov@nginx.com 'Host': 'localhost', 2321017Szelenkov@nginx.com 'Connection': 'keep-alive', 2331017Szelenkov@nginx.com 'Content-Type': 'text/html', 2341017Szelenkov@nginx.com }, 2351017Szelenkov@nginx.com start=True, 2361017Szelenkov@nginx.com body=body, 2371029Szelenkov@nginx.com read_timeout=1, 2381017Szelenkov@nginx.com ) 239684Szelenkov@nginx.com 240684Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'keep-alive open') 2411017Szelenkov@nginx.com self.assertIn( 2421017Szelenkov@nginx.com 'success', 2431026Szelenkov@nginx.com self.conf(str(i + 1), 'applications/mirror/processes'), 2441017Szelenkov@nginx.com 'reconfigure', 2451017Szelenkov@nginx.com ) 246684Szelenkov@nginx.com 247684Szelenkov@nginx.com socks.append(sock) 248684Szelenkov@nginx.com 249684Szelenkov@nginx.com for i in range(conns): 2501017Szelenkov@nginx.com (resp, sock) = self.post( 2511017Szelenkov@nginx.com headers={ 2521017Szelenkov@nginx.com 'Host': 'localhost', 2531017Szelenkov@nginx.com 'Connection': 'keep-alive', 2541017Szelenkov@nginx.com 'Content-Type': 'text/html', 2551017Szelenkov@nginx.com }, 2561017Szelenkov@nginx.com start=True, 2571017Szelenkov@nginx.com sock=socks[i], 2581017Szelenkov@nginx.com body=body, 2591029Szelenkov@nginx.com read_timeout=1, 2601017Szelenkov@nginx.com ) 261684Szelenkov@nginx.com 262684Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'keep-alive request') 2631017Szelenkov@nginx.com self.assertIn( 2641017Szelenkov@nginx.com 'success', 2651026Szelenkov@nginx.com self.conf(str(i + 1), 'applications/mirror/processes'), 2661017Szelenkov@nginx.com 'reconfigure 2', 2671017Szelenkov@nginx.com ) 268684Szelenkov@nginx.com 269684Szelenkov@nginx.com for i in range(conns): 2701017Szelenkov@nginx.com resp = self.post( 2711017Szelenkov@nginx.com headers={ 2721017Szelenkov@nginx.com 'Host': 'localhost', 2731017Szelenkov@nginx.com 'Connection': 'close', 2741017Szelenkov@nginx.com 'Content-Type': 'text/html', 2751017Szelenkov@nginx.com }, 2761017Szelenkov@nginx.com sock=socks[i], 2771017Szelenkov@nginx.com body=body, 2781017Szelenkov@nginx.com ) 279684Szelenkov@nginx.com 280684Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'keep-alive close') 2811017Szelenkov@nginx.com self.assertIn( 2821017Szelenkov@nginx.com 'success', 2831026Szelenkov@nginx.com self.conf(str(i + 1), 'applications/mirror/processes'), 2841017Szelenkov@nginx.com 'reconfigure 3', 2851017Szelenkov@nginx.com ) 286684Szelenkov@nginx.com 287750Szelenkov@nginx.com def test_python_keepalive_reconfigure_2(self): 288750Szelenkov@nginx.com self.load('mirror') 289750Szelenkov@nginx.com 2901029Szelenkov@nginx.com self.assertEqual(self.get()['status'], 200, 'init') 2911029Szelenkov@nginx.com 292750Szelenkov@nginx.com body = '0123456789' 293750Szelenkov@nginx.com 2941017Szelenkov@nginx.com (resp, sock) = self.post( 2951017Szelenkov@nginx.com headers={ 2961017Szelenkov@nginx.com 'Host': 'localhost', 2971017Szelenkov@nginx.com 'Connection': 'keep-alive', 2981017Szelenkov@nginx.com 'Content-Type': 'text/html', 2991017Szelenkov@nginx.com }, 3001017Szelenkov@nginx.com start=True, 3011017Szelenkov@nginx.com body=body, 3021029Szelenkov@nginx.com read_timeout=1, 3031017Szelenkov@nginx.com ) 304750Szelenkov@nginx.com 305750Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'reconfigure 2 keep-alive 1') 306750Szelenkov@nginx.com 307750Szelenkov@nginx.com self.load('empty') 308750Szelenkov@nginx.com 3091029Szelenkov@nginx.com self.assertEqual(self.get()['status'], 200, 'init') 3101029Szelenkov@nginx.com 3111017Szelenkov@nginx.com (resp, sock) = self.post( 3121017Szelenkov@nginx.com headers={ 3131017Szelenkov@nginx.com 'Host': 'localhost', 3141017Szelenkov@nginx.com 'Connection': 'close', 3151017Szelenkov@nginx.com 'Content-Type': 'text/html', 3161017Szelenkov@nginx.com }, 3171017Szelenkov@nginx.com start=True, 3181017Szelenkov@nginx.com sock=sock, 3191017Szelenkov@nginx.com body=body, 3201017Szelenkov@nginx.com ) 321750Szelenkov@nginx.com 322750Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'reconfigure 2 keep-alive 2') 323750Szelenkov@nginx.com self.assertEqual(resp['body'], '', 'reconfigure 2 keep-alive 2 body') 324750Szelenkov@nginx.com 3251017Szelenkov@nginx.com self.assertIn( 3261017Szelenkov@nginx.com 'success', 3271017Szelenkov@nginx.com self.conf({"listeners": {}, "applications": {}}), 3281017Szelenkov@nginx.com 'reconfigure 2 clear configuration', 3291017Szelenkov@nginx.com ) 330750Szelenkov@nginx.com 331750Szelenkov@nginx.com resp = self.get(sock=sock) 332750Szelenkov@nginx.com 333750Szelenkov@nginx.com self.assertEqual(resp, {}, 'reconfigure 2 keep-alive 3') 334750Szelenkov@nginx.com 335750Szelenkov@nginx.com def test_python_keepalive_reconfigure_3(self): 336750Szelenkov@nginx.com self.load('empty') 337750Szelenkov@nginx.com 3381029Szelenkov@nginx.com self.assertEqual(self.get()['status'], 200, 'init') 3391029Szelenkov@nginx.com 3401017Szelenkov@nginx.com (resp, sock) = self.http( 3411017Szelenkov@nginx.com b"""GET / HTTP/1.1 3421017Szelenkov@nginx.com""", 3431017Szelenkov@nginx.com start=True, 3441017Szelenkov@nginx.com raw=True, 3451043Szelenkov@nginx.com read_timeout=5, 3461017Szelenkov@nginx.com ) 347750Szelenkov@nginx.com 3481017Szelenkov@nginx.com self.assertIn( 3491017Szelenkov@nginx.com 'success', 3501017Szelenkov@nginx.com self.conf({"listeners": {}, "applications": {}}), 3511017Szelenkov@nginx.com 'reconfigure 3 clear configuration', 3521017Szelenkov@nginx.com ) 353750Szelenkov@nginx.com 3541017Szelenkov@nginx.com resp = self.http( 3551017Szelenkov@nginx.com b"""Host: localhost 356750Szelenkov@nginx.comConnection: close 357750Szelenkov@nginx.com 3581017Szelenkov@nginx.com""", 3591017Szelenkov@nginx.com sock=sock, 3601017Szelenkov@nginx.com raw=True, 3611017Szelenkov@nginx.com ) 362750Szelenkov@nginx.com 363750Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'reconfigure 3') 364750Szelenkov@nginx.com 365603Szelenkov@nginx.com def test_python_atexit(self): 366603Szelenkov@nginx.com self.load('atexit') 367603Szelenkov@nginx.com 368603Szelenkov@nginx.com self.get() 369603Szelenkov@nginx.com 3701017Szelenkov@nginx.com self.conf({"listeners": {}, "applications": {}}) 371603Szelenkov@nginx.com 372603Szelenkov@nginx.com self.stop() 373603Szelenkov@nginx.com 3741028Szelenkov@nginx.com self.assertIsNotNone( 3751028Szelenkov@nginx.com self.wait_for_record(r'At exit called\.'), 'atexit' 3761028Szelenkov@nginx.com ) 377603Szelenkov@nginx.com 3781064Szelenkov@nginx.com @unittest.skip('not yet') 379603Szelenkov@nginx.com def test_python_application_start_response_exit(self): 380603Szelenkov@nginx.com self.load('start_response_exit') 381603Szelenkov@nginx.com 382603Szelenkov@nginx.com self.assertEqual(self.get()['status'], 500, 'start response exit') 383603Szelenkov@nginx.com 3841064Szelenkov@nginx.com @unittest.skip('not yet') 385603Szelenkov@nginx.com def test_python_application_input_iter(self): 386603Szelenkov@nginx.com self.load('input_iter') 387603Szelenkov@nginx.com 388603Szelenkov@nginx.com body = '0123456789' 389603Szelenkov@nginx.com 390603Szelenkov@nginx.com self.assertEqual(self.post(body=body)['body'], body, 'input iter') 391603Szelenkov@nginx.com 392603Szelenkov@nginx.com def test_python_application_input_read_length(self): 393603Szelenkov@nginx.com self.load('input_read_length') 394603Szelenkov@nginx.com 395603Szelenkov@nginx.com body = '0123456789' 396603Szelenkov@nginx.com 3971017Szelenkov@nginx.com resp = self.post( 3981017Szelenkov@nginx.com headers={ 3991017Szelenkov@nginx.com 'Host': 'localhost', 4001017Szelenkov@nginx.com 'Input-Length': '5', 4011017Szelenkov@nginx.com 'Connection': 'close', 4021017Szelenkov@nginx.com }, 4031017Szelenkov@nginx.com body=body, 4041017Szelenkov@nginx.com ) 405603Szelenkov@nginx.com 406603Szelenkov@nginx.com self.assertEqual(resp['body'], body[:5], 'input read length lt body') 407603Szelenkov@nginx.com 4081017Szelenkov@nginx.com resp = self.post( 4091017Szelenkov@nginx.com headers={ 4101017Szelenkov@nginx.com 'Host': 'localhost', 4111017Szelenkov@nginx.com 'Input-Length': '15', 4121017Szelenkov@nginx.com 'Connection': 'close', 4131017Szelenkov@nginx.com }, 4141017Szelenkov@nginx.com body=body, 4151017Szelenkov@nginx.com ) 416603Szelenkov@nginx.com 417603Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'input read length gt body') 418603Szelenkov@nginx.com 4191017Szelenkov@nginx.com resp = self.post( 4201017Szelenkov@nginx.com headers={ 4211017Szelenkov@nginx.com 'Host': 'localhost', 4221017Szelenkov@nginx.com 'Input-Length': '0', 4231017Szelenkov@nginx.com 'Connection': 'close', 4241017Szelenkov@nginx.com }, 4251017Szelenkov@nginx.com body=body, 4261017Szelenkov@nginx.com ) 427603Szelenkov@nginx.com 428603Szelenkov@nginx.com self.assertEqual(resp['body'], '', 'input read length zero') 429603Szelenkov@nginx.com 4301017Szelenkov@nginx.com resp = self.post( 4311017Szelenkov@nginx.com headers={ 4321017Szelenkov@nginx.com 'Host': 'localhost', 4331017Szelenkov@nginx.com 'Input-Length': '-1', 4341017Szelenkov@nginx.com 'Connection': 'close', 4351017Szelenkov@nginx.com }, 4361017Szelenkov@nginx.com body=body, 4371017Szelenkov@nginx.com ) 438603Szelenkov@nginx.com 439603Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'input read length negative') 440603Szelenkov@nginx.com 4411064Szelenkov@nginx.com @unittest.skip('not yet') 442603Szelenkov@nginx.com def test_python_application_errors_write(self): 443603Szelenkov@nginx.com self.load('errors_write') 444603Szelenkov@nginx.com 445603Szelenkov@nginx.com self.get() 446603Szelenkov@nginx.com 447603Szelenkov@nginx.com self.stop() 448603Szelenkov@nginx.com 449603Szelenkov@nginx.com self.assertIsNotNone( 4501028Szelenkov@nginx.com self.wait_for_record(r'\[error\].+Error in application\.'), 4511017Szelenkov@nginx.com 'errors write', 4521017Szelenkov@nginx.com ) 453603Szelenkov@nginx.com 454603Szelenkov@nginx.com def test_python_application_body_array(self): 455603Szelenkov@nginx.com self.load('body_array') 456603Szelenkov@nginx.com 457603Szelenkov@nginx.com self.assertEqual(self.get()['body'], '0123456789', 'body array') 458603Szelenkov@nginx.com 459603Szelenkov@nginx.com def test_python_application_body_io(self): 460603Szelenkov@nginx.com self.load('body_io') 461603Szelenkov@nginx.com 462603Szelenkov@nginx.com self.assertEqual(self.get()['body'], '0123456789', 'body io') 463603Szelenkov@nginx.com 464603Szelenkov@nginx.com def test_python_application_body_io_file(self): 465603Szelenkov@nginx.com self.load('body_io_file') 466603Szelenkov@nginx.com 467603Szelenkov@nginx.com self.assertEqual(self.get()['body'], 'body\n', 'body io file') 468603Szelenkov@nginx.com 4691064Szelenkov@nginx.com @unittest.skip('not yet') 470603Szelenkov@nginx.com def test_python_application_syntax_error(self): 471603Szelenkov@nginx.com self.skip_alerts.append(r'Python failed to import module "wsgi"') 472603Szelenkov@nginx.com self.load('syntax_error') 473603Szelenkov@nginx.com 474603Szelenkov@nginx.com self.assertEqual(self.get()['status'], 500, 'syntax error') 475603Szelenkov@nginx.com 476603Szelenkov@nginx.com def test_python_application_close(self): 477603Szelenkov@nginx.com self.load('close') 478603Szelenkov@nginx.com 479603Szelenkov@nginx.com self.get() 480603Szelenkov@nginx.com 481603Szelenkov@nginx.com self.stop() 482603Szelenkov@nginx.com 4831028Szelenkov@nginx.com self.assertIsNotNone(self.wait_for_record(r'Close called\.'), 'close') 484603Szelenkov@nginx.com 485603Szelenkov@nginx.com def test_python_application_close_error(self): 486603Szelenkov@nginx.com self.load('close_error') 487603Szelenkov@nginx.com 488603Szelenkov@nginx.com self.get() 489603Szelenkov@nginx.com 490603Szelenkov@nginx.com self.stop() 491603Szelenkov@nginx.com 4921017Szelenkov@nginx.com self.assertIsNotNone( 4931028Szelenkov@nginx.com self.wait_for_record(r'Close called\.'), 'close error' 4941017Szelenkov@nginx.com ) 495603Szelenkov@nginx.com 496617Szelenkov@nginx.com def test_python_application_not_iterable(self): 497617Szelenkov@nginx.com self.load('not_iterable') 498617Szelenkov@nginx.com 499665Szelenkov@nginx.com self.get() 500617Szelenkov@nginx.com 501617Szelenkov@nginx.com self.stop() 502617Szelenkov@nginx.com 5031017Szelenkov@nginx.com self.assertIsNotNone( 5041028Szelenkov@nginx.com self.wait_for_record( 5051017Szelenkov@nginx.com r'\[error\].+the application returned not an iterable object' 5061017Szelenkov@nginx.com ), 5071017Szelenkov@nginx.com 'not iterable', 5081017Szelenkov@nginx.com ) 509617Szelenkov@nginx.com 510664Szelenkov@nginx.com def test_python_application_write(self): 511664Szelenkov@nginx.com self.load('write') 512664Szelenkov@nginx.com 513664Szelenkov@nginx.com self.assertEqual(self.get()['body'], '0123456789', 'write') 514664Szelenkov@nginx.com 5151261Szelenkov@nginx.com def test_python_application_threading(self): 5161261Szelenkov@nginx.com """wait_for_record() timeouts after 5s while every thread works at 5171261Szelenkov@nginx.com least 3s. So without releasing GIL test should fail. 5181261Szelenkov@nginx.com """ 5191261Szelenkov@nginx.com 5201261Szelenkov@nginx.com self.load('threading') 5211261Szelenkov@nginx.com 5221261Szelenkov@nginx.com for _ in range(10): 5231261Szelenkov@nginx.com self.get(no_recv=True) 5241261Szelenkov@nginx.com 5251261Szelenkov@nginx.com self.assertIsNotNone( 5261261Szelenkov@nginx.com self.wait_for_record(r'\(5\) Thread: 100'), 'last thread finished' 5271261Szelenkov@nginx.com ) 5281017Szelenkov@nginx.com 529*1283Szelenkov@nginx.com def test_python_application_iter_exception(self): 530*1283Szelenkov@nginx.com self.load('iter_exception') 531*1283Szelenkov@nginx.com 532*1283Szelenkov@nginx.com # Default request doesn't lead to the exception. 533*1283Szelenkov@nginx.com 534*1283Szelenkov@nginx.com resp = self.get( 535*1283Szelenkov@nginx.com headers={ 536*1283Szelenkov@nginx.com 'Host': 'localhost', 537*1283Szelenkov@nginx.com 'X-Skip': '9', 538*1283Szelenkov@nginx.com 'X-Chunked': '1', 539*1283Szelenkov@nginx.com 'Connection': 'close', 540*1283Szelenkov@nginx.com } 541*1283Szelenkov@nginx.com ) 542*1283Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'status') 543*1283Szelenkov@nginx.com self.assertEqual(resp['body'][-5:], '0\r\n\r\n', 'body') 544*1283Szelenkov@nginx.com 545*1283Szelenkov@nginx.com # Exception before start_response(). 546*1283Szelenkov@nginx.com 547*1283Szelenkov@nginx.com self.assertEqual(self.get()['status'], 503, 'error') 548*1283Szelenkov@nginx.com 549*1283Szelenkov@nginx.com self.assertIsNotNone(self.wait_for_record(r'Traceback'), 'traceback') 550*1283Szelenkov@nginx.com self.assertIsNotNone( 551*1283Szelenkov@nginx.com self.wait_for_record(r'raise Exception\(\'first exception\'\)'), 552*1283Szelenkov@nginx.com 'first exception raise', 553*1283Szelenkov@nginx.com ) 554*1283Szelenkov@nginx.com self.assertEqual( 555*1283Szelenkov@nginx.com len(self.findall(r'Traceback')), 1, 'traceback count 1' 556*1283Szelenkov@nginx.com ) 557*1283Szelenkov@nginx.com 558*1283Szelenkov@nginx.com # Exception after start_response(), before first write(). 559*1283Szelenkov@nginx.com 560*1283Szelenkov@nginx.com self.assertEqual( 561*1283Szelenkov@nginx.com self.get( 562*1283Szelenkov@nginx.com headers={ 563*1283Szelenkov@nginx.com 'Host': 'localhost', 564*1283Szelenkov@nginx.com 'X-Skip': '1', 565*1283Szelenkov@nginx.com 'Connection': 'close', 566*1283Szelenkov@nginx.com } 567*1283Szelenkov@nginx.com )['status'], 568*1283Szelenkov@nginx.com 503, 569*1283Szelenkov@nginx.com 'error 2', 570*1283Szelenkov@nginx.com ) 571*1283Szelenkov@nginx.com 572*1283Szelenkov@nginx.com self.assertIsNotNone( 573*1283Szelenkov@nginx.com self.wait_for_record(r'raise Exception\(\'second exception\'\)'), 574*1283Szelenkov@nginx.com 'exception raise second', 575*1283Szelenkov@nginx.com ) 576*1283Szelenkov@nginx.com self.assertEqual( 577*1283Szelenkov@nginx.com len(self.findall(r'Traceback')), 2, 'traceback count 2' 578*1283Szelenkov@nginx.com ) 579*1283Szelenkov@nginx.com 580*1283Szelenkov@nginx.com # Exception after first write(), before first __next__(). 581*1283Szelenkov@nginx.com 582*1283Szelenkov@nginx.com _, sock = self.get( 583*1283Szelenkov@nginx.com headers={ 584*1283Szelenkov@nginx.com 'Host': 'localhost', 585*1283Szelenkov@nginx.com 'X-Skip': '2', 586*1283Szelenkov@nginx.com 'Connection': 'keep-alive', 587*1283Szelenkov@nginx.com }, 588*1283Szelenkov@nginx.com start=True, 589*1283Szelenkov@nginx.com ) 590*1283Szelenkov@nginx.com 591*1283Szelenkov@nginx.com self.assertIsNotNone( 592*1283Szelenkov@nginx.com self.wait_for_record(r'raise Exception\(\'third exception\'\)'), 593*1283Szelenkov@nginx.com 'exception raise third', 594*1283Szelenkov@nginx.com ) 595*1283Szelenkov@nginx.com self.assertEqual( 596*1283Szelenkov@nginx.com len(self.findall(r'Traceback')), 3, 'traceback count 3' 597*1283Szelenkov@nginx.com ) 598*1283Szelenkov@nginx.com 599*1283Szelenkov@nginx.com self.assertDictEqual(self.get(sock=sock), {}, 'closed connection') 600*1283Szelenkov@nginx.com 601*1283Szelenkov@nginx.com # Exception after first write(), before first __next__(), 602*1283Szelenkov@nginx.com # chunked (incomplete body). 603*1283Szelenkov@nginx.com 604*1283Szelenkov@nginx.com resp = self.get( 605*1283Szelenkov@nginx.com headers={ 606*1283Szelenkov@nginx.com 'Host': 'localhost', 607*1283Szelenkov@nginx.com 'X-Skip': '2', 608*1283Szelenkov@nginx.com 'X-Chunked': '1', 609*1283Szelenkov@nginx.com 'Connection': 'close', 610*1283Szelenkov@nginx.com } 611*1283Szelenkov@nginx.com ) 612*1283Szelenkov@nginx.com if 'body' in resp: 613*1283Szelenkov@nginx.com self.assertNotEqual( 614*1283Szelenkov@nginx.com resp['body'][-5:], '0\r\n\r\n', 'incomplete body' 615*1283Szelenkov@nginx.com ) 616*1283Szelenkov@nginx.com self.assertEqual( 617*1283Szelenkov@nginx.com len(self.findall(r'Traceback')), 4, 'traceback count 4' 618*1283Szelenkov@nginx.com ) 619*1283Szelenkov@nginx.com 620*1283Szelenkov@nginx.com # Exception in __next__(). 621*1283Szelenkov@nginx.com 622*1283Szelenkov@nginx.com _, sock = self.get( 623*1283Szelenkov@nginx.com headers={ 624*1283Szelenkov@nginx.com 'Host': 'localhost', 625*1283Szelenkov@nginx.com 'X-Skip': '3', 626*1283Szelenkov@nginx.com 'Connection': 'keep-alive', 627*1283Szelenkov@nginx.com }, 628*1283Szelenkov@nginx.com start=True, 629*1283Szelenkov@nginx.com ) 630*1283Szelenkov@nginx.com 631*1283Szelenkov@nginx.com self.assertIsNotNone( 632*1283Szelenkov@nginx.com self.wait_for_record(r'raise Exception\(\'next exception\'\)'), 633*1283Szelenkov@nginx.com 'exception raise next', 634*1283Szelenkov@nginx.com ) 635*1283Szelenkov@nginx.com self.assertEqual( 636*1283Szelenkov@nginx.com len(self.findall(r'Traceback')), 5, 'traceback count 5' 637*1283Szelenkov@nginx.com ) 638*1283Szelenkov@nginx.com 639*1283Szelenkov@nginx.com self.assertDictEqual(self.get(sock=sock), {}, 'closed connection 2') 640*1283Szelenkov@nginx.com 641*1283Szelenkov@nginx.com # Exception in __next__(), chunked (incomplete body). 642*1283Szelenkov@nginx.com 643*1283Szelenkov@nginx.com resp = self.get( 644*1283Szelenkov@nginx.com headers={ 645*1283Szelenkov@nginx.com 'Host': 'localhost', 646*1283Szelenkov@nginx.com 'X-Skip': '3', 647*1283Szelenkov@nginx.com 'X-Chunked': '1', 648*1283Szelenkov@nginx.com 'Connection': 'close', 649*1283Szelenkov@nginx.com } 650*1283Szelenkov@nginx.com ) 651*1283Szelenkov@nginx.com if 'body' in resp: 652*1283Szelenkov@nginx.com self.assertNotEqual( 653*1283Szelenkov@nginx.com resp['body'][-5:], '0\r\n\r\n', 'incomplete body 2' 654*1283Szelenkov@nginx.com ) 655*1283Szelenkov@nginx.com self.assertEqual( 656*1283Szelenkov@nginx.com len(self.findall(r'Traceback')), 6, 'traceback count 6' 657*1283Szelenkov@nginx.com ) 658*1283Szelenkov@nginx.com 659*1283Szelenkov@nginx.com # Exception before start_response() and in close(). 660*1283Szelenkov@nginx.com 661*1283Szelenkov@nginx.com self.assertEqual( 662*1283Szelenkov@nginx.com self.get( 663*1283Szelenkov@nginx.com headers={ 664*1283Szelenkov@nginx.com 'Host': 'localhost', 665*1283Szelenkov@nginx.com 'X-Not-Skip-Close': '1', 666*1283Szelenkov@nginx.com 'Connection': 'close', 667*1283Szelenkov@nginx.com } 668*1283Szelenkov@nginx.com )['status'], 669*1283Szelenkov@nginx.com 503, 670*1283Szelenkov@nginx.com 'error', 671*1283Szelenkov@nginx.com ) 672*1283Szelenkov@nginx.com 673*1283Szelenkov@nginx.com self.assertIsNotNone( 674*1283Szelenkov@nginx.com self.wait_for_record(r'raise Exception\(\'close exception\'\)'), 675*1283Szelenkov@nginx.com 'exception raise close', 676*1283Szelenkov@nginx.com ) 677*1283Szelenkov@nginx.com self.assertEqual( 678*1283Szelenkov@nginx.com len(self.findall(r'Traceback')), 8, 'traceback count 8' 679*1283Szelenkov@nginx.com ) 680*1283Szelenkov@nginx.com 681484Szelenkov@nginx.comif __name__ == '__main__': 6821019Szelenkov@nginx.com TestPythonApplication.main() 683