1*899Szelenkov@nginx.comimport time 2484Szelenkov@nginx.comimport unittest 3484Szelenkov@nginx.comimport unit 4484Szelenkov@nginx.com 5552Szelenkov@nginx.comclass TestUnitPythonApplication(unit.TestUnitApplicationPython): 6484Szelenkov@nginx.com 7484Szelenkov@nginx.com def setUpClass(): 8550Szelenkov@nginx.com unit.TestUnit().check_modules('python') 9484Szelenkov@nginx.com 10552Szelenkov@nginx.com def test_python_application_variables(self): 11552Szelenkov@nginx.com self.load('variables') 12484Szelenkov@nginx.com 13484Szelenkov@nginx.com body = 'Test body string.' 14484Szelenkov@nginx.com 15505Szelenkov@nginx.com resp = self.post(headers={ 16484Szelenkov@nginx.com 'Host': 'localhost', 17484Szelenkov@nginx.com 'Content-Type': 'text/html', 18484Szelenkov@nginx.com 'Custom-Header': 'blah' 19505Szelenkov@nginx.com }, body=body) 20484Szelenkov@nginx.com 21505Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'status') 22505Szelenkov@nginx.com headers = resp['headers'] 23674Szelenkov@nginx.com header_server = headers.pop('Server') 24674Szelenkov@nginx.com self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') 25674Szelenkov@nginx.com self.assertEqual(headers.pop('Server-Software'), header_server, 26674Szelenkov@nginx.com 'server software header') 27599Szelenkov@nginx.com 28599Szelenkov@nginx.com date = headers.pop('Date') 29599Szelenkov@nginx.com self.assertEqual(date[-4:], ' GMT', 'date header timezone') 30599Szelenkov@nginx.com self.assertLess(abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 5, 31599Szelenkov@nginx.com 'date header') 32599Szelenkov@nginx.com 33495Szelenkov@nginx.com self.assertDictEqual(headers, { 34495Szelenkov@nginx.com 'Content-Length': str(len(body)), 35495Szelenkov@nginx.com 'Content-Type': 'text/html', 36495Szelenkov@nginx.com 'Request-Method': 'POST', 37495Szelenkov@nginx.com 'Request-Uri': '/', 38495Szelenkov@nginx.com 'Http-Host': 'localhost', 39495Szelenkov@nginx.com 'Server-Protocol': 'HTTP/1.1', 40603Szelenkov@nginx.com 'Custom-Header': 'blah', 41603Szelenkov@nginx.com 'Wsgi-Version': '(1, 0)', 42603Szelenkov@nginx.com 'Wsgi-Url-Scheme': 'http', 43603Szelenkov@nginx.com 'Wsgi-Multithread': 'False', 44603Szelenkov@nginx.com 'Wsgi-Multiprocess': 'True', 45603Szelenkov@nginx.com 'Wsgi-Run-Once': 'False' 46495Szelenkov@nginx.com }, 'headers') 47505Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'body') 48484Szelenkov@nginx.com 49497Szelenkov@nginx.com def test_python_application_query_string(self): 50552Szelenkov@nginx.com self.load('query_string') 51497Szelenkov@nginx.com 52505Szelenkov@nginx.com resp = self.get(url='/?var1=val1&var2=val2') 53497Szelenkov@nginx.com 54513Szelenkov@nginx.com self.assertEqual(resp['headers']['Query-String'], 'var1=val1&var2=val2', 55513Szelenkov@nginx.com 'Query-String header') 56497Szelenkov@nginx.com 57894Szelenkov@nginx.com def test_python_application_query_string_empty(self): 58894Szelenkov@nginx.com self.load('query_string') 59894Szelenkov@nginx.com 60894Szelenkov@nginx.com resp = self.get(url='/?') 61894Szelenkov@nginx.com 62894Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'query string empty status') 63894Szelenkov@nginx.com self.assertEqual(resp['headers']['Query-String'], '', 64894Szelenkov@nginx.com 'query string empty') 65894Szelenkov@nginx.com 66894Szelenkov@nginx.com @unittest.expectedFailure 67894Szelenkov@nginx.com def test_python_application_query_string_absent(self): 68894Szelenkov@nginx.com self.load('query_string') 69894Szelenkov@nginx.com 70894Szelenkov@nginx.com resp = self.get() 71894Szelenkov@nginx.com 72894Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'query string absent status') 73894Szelenkov@nginx.com self.assertEqual(resp['headers']['Query-String'], '', 74894Szelenkov@nginx.com 'query string absent') 75894Szelenkov@nginx.com 76495Szelenkov@nginx.com @unittest.expectedFailure 77495Szelenkov@nginx.com def test_python_application_server_port(self): 78552Szelenkov@nginx.com self.load('server_port') 79495Szelenkov@nginx.com 80505Szelenkov@nginx.com self.assertEqual(self.get()['headers']['Server-Port'], '7080', 81495Szelenkov@nginx.com 'Server-Port header') 82484Szelenkov@nginx.com 83496Szelenkov@nginx.com def test_python_application_204_transfer_encoding(self): 84552Szelenkov@nginx.com self.load('204_no_content') 85496Szelenkov@nginx.com 86505Szelenkov@nginx.com self.assertNotIn('Transfer-Encoding', self.get()['headers'], 87496Szelenkov@nginx.com '204 header transfer encoding') 88484Szelenkov@nginx.com 89602Szelenkov@nginx.com def test_python_application_ctx_iter_atexit(self): 90602Szelenkov@nginx.com self.skip_alerts.append(r'sendmsg.+failed') 91602Szelenkov@nginx.com self.load('ctx_iter_atexit') 92602Szelenkov@nginx.com 93602Szelenkov@nginx.com resp = self.post(headers={ 94602Szelenkov@nginx.com 'Connection': 'close', 95602Szelenkov@nginx.com 'Content-Type': 'text/html', 96602Szelenkov@nginx.com 'Host': 'localhost' 97602Szelenkov@nginx.com }, body='0123456789') 98602Szelenkov@nginx.com 99602Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'ctx iter status') 100602Szelenkov@nginx.com self.assertEqual(resp['body'], '0123456789', 'ctx iter body') 101602Szelenkov@nginx.com 102602Szelenkov@nginx.com self.conf({ 103602Szelenkov@nginx.com "listeners": {}, 104602Szelenkov@nginx.com "applications": {} 105602Szelenkov@nginx.com }) 106602Szelenkov@nginx.com 107602Szelenkov@nginx.com self.stop() 108602Szelenkov@nginx.com 109*899Szelenkov@nginx.com time.sleep(0.2) 110*899Szelenkov@nginx.com 111602Szelenkov@nginx.com self.assertIsNotNone(self.search_in_log(r'RuntimeError'), 112602Szelenkov@nginx.com 'ctx iter atexit') 113602Szelenkov@nginx.com 114603Szelenkov@nginx.com def test_python_keepalive_body(self): 115603Szelenkov@nginx.com self.load('mirror') 116603Szelenkov@nginx.com 117603Szelenkov@nginx.com (resp, sock) = self.post(headers={ 118603Szelenkov@nginx.com 'Connection': 'keep-alive', 119603Szelenkov@nginx.com 'Content-Type': 'text/html', 120603Szelenkov@nginx.com 'Host': 'localhost' 121603Szelenkov@nginx.com }, start=True, body='0123456789' * 500) 122603Szelenkov@nginx.com 123603Szelenkov@nginx.com self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1') 124603Szelenkov@nginx.com 125603Szelenkov@nginx.com resp = self.post(headers={ 126603Szelenkov@nginx.com 'Connection': 'close', 127603Szelenkov@nginx.com 'Content-Type': 'text/html', 128603Szelenkov@nginx.com 'Host': 'localhost' 129603Szelenkov@nginx.com }, sock=sock, body='0123456789') 130603Szelenkov@nginx.com 131603Szelenkov@nginx.com self.assertEqual(resp['body'], '0123456789', 'keep-alive 2') 132603Szelenkov@nginx.com 133684Szelenkov@nginx.com def test_python_keepalive_reconfigure(self): 134684Szelenkov@nginx.com self.skip_alerts.extend([ 135684Szelenkov@nginx.com r'sendmsg.+failed', 136684Szelenkov@nginx.com r'recvmsg.+failed' 137684Szelenkov@nginx.com ]) 138684Szelenkov@nginx.com self.load('mirror') 139684Szelenkov@nginx.com 140684Szelenkov@nginx.com body = '0123456789' 141684Szelenkov@nginx.com conns = 3 142684Szelenkov@nginx.com socks = [] 143684Szelenkov@nginx.com 144684Szelenkov@nginx.com for i in range(conns): 145684Szelenkov@nginx.com (resp, sock) = self.post(headers={ 146684Szelenkov@nginx.com 'Connection': 'keep-alive', 147684Szelenkov@nginx.com 'Content-Type': 'text/html', 148684Szelenkov@nginx.com 'Host': 'localhost' 149684Szelenkov@nginx.com }, start=True, body=body) 150684Szelenkov@nginx.com 151684Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'keep-alive open') 152684Szelenkov@nginx.com self.assertIn('success', self.conf({ 153684Szelenkov@nginx.com "spare": i % 4, 154684Szelenkov@nginx.com "max": (i % 4) + 1 155760Szelenkov@nginx.com }, 'applications/mirror/processes'), 'reconfigure') 156684Szelenkov@nginx.com 157684Szelenkov@nginx.com socks.append(sock) 158684Szelenkov@nginx.com 159684Szelenkov@nginx.com for i in range(conns): 160684Szelenkov@nginx.com (resp, sock) = self.post(headers={ 161684Szelenkov@nginx.com 'Connection': 'keep-alive', 162684Szelenkov@nginx.com 'Content-Type': 'text/html', 163684Szelenkov@nginx.com 'Host': 'localhost' 164684Szelenkov@nginx.com }, start=True, sock=socks[i], body=body) 165684Szelenkov@nginx.com 166684Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'keep-alive request') 167684Szelenkov@nginx.com self.assertIn('success', self.conf({ 168684Szelenkov@nginx.com "spare": i % 4, 169684Szelenkov@nginx.com "max": (i % 4) + 1 170760Szelenkov@nginx.com }, 'applications/mirror/processes'), 'reconfigure 2') 171684Szelenkov@nginx.com 172684Szelenkov@nginx.com for i in range(conns): 173684Szelenkov@nginx.com resp = self.post(headers={ 174684Szelenkov@nginx.com 'Connection': 'close', 175684Szelenkov@nginx.com 'Content-Type': 'text/html', 176684Szelenkov@nginx.com 'Host': 'localhost' 177684Szelenkov@nginx.com }, sock=socks[i], body=body) 178684Szelenkov@nginx.com 179684Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'keep-alive close') 180684Szelenkov@nginx.com self.assertIn('success', self.conf({ 181684Szelenkov@nginx.com "spare": i % 4, 182684Szelenkov@nginx.com "max": (i % 4) + 1 183760Szelenkov@nginx.com }, 'applications/mirror/processes'), 'reconfigure 3') 184684Szelenkov@nginx.com 185750Szelenkov@nginx.com def test_python_keepalive_reconfigure_2(self): 186750Szelenkov@nginx.com self.skip_alerts.append(r'sendmsg.+failed') 187750Szelenkov@nginx.com self.load('mirror') 188750Szelenkov@nginx.com 189750Szelenkov@nginx.com body = '0123456789' 190750Szelenkov@nginx.com 191750Szelenkov@nginx.com (resp, sock) = self.post(headers={ 192750Szelenkov@nginx.com 'Connection': 'keep-alive', 193750Szelenkov@nginx.com 'Content-Type': 'text/html', 194750Szelenkov@nginx.com 'Host': 'localhost' 195750Szelenkov@nginx.com }, start=True, body=body) 196750Szelenkov@nginx.com 197750Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'reconfigure 2 keep-alive 1') 198750Szelenkov@nginx.com 199750Szelenkov@nginx.com self.load('empty') 200750Szelenkov@nginx.com 201750Szelenkov@nginx.com (resp, sock) = self.post(headers={ 202750Szelenkov@nginx.com 'Connection': 'close', 203750Szelenkov@nginx.com 'Content-Type': 'text/html', 204750Szelenkov@nginx.com 'Host': 'localhost' 205750Szelenkov@nginx.com }, start=True, sock=sock, body=body) 206750Szelenkov@nginx.com 207750Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'reconfigure 2 keep-alive 2') 208750Szelenkov@nginx.com self.assertEqual(resp['body'], '', 'reconfigure 2 keep-alive 2 body') 209750Szelenkov@nginx.com 210750Szelenkov@nginx.com self.assertIn('success', self.conf({ 211750Szelenkov@nginx.com "listeners": {}, 212750Szelenkov@nginx.com "applications": {} 213750Szelenkov@nginx.com }), 'reconfigure 2 clear configuration') 214750Szelenkov@nginx.com 215750Szelenkov@nginx.com resp = self.get(sock=sock) 216750Szelenkov@nginx.com 217750Szelenkov@nginx.com self.assertEqual(resp, {}, 'reconfigure 2 keep-alive 3') 218750Szelenkov@nginx.com 219750Szelenkov@nginx.com def test_python_keepalive_reconfigure_3(self): 220753Smax.romanov@nginx.com self.skip_alerts.append(r'sendmsg.+failed') 221750Szelenkov@nginx.com self.load('empty') 222750Szelenkov@nginx.com 223750Szelenkov@nginx.com (resp, sock) = self.http(b"""GET / HTTP/1.1 224750Szelenkov@nginx.com""", start=True, raw=True) 225750Szelenkov@nginx.com 226750Szelenkov@nginx.com self.assertIn('success', self.conf({ 227750Szelenkov@nginx.com "listeners": {}, 228750Szelenkov@nginx.com "applications": {} 229750Szelenkov@nginx.com }), 'reconfigure 3 clear configuration') 230750Szelenkov@nginx.com 231750Szelenkov@nginx.com resp = self.http(b"""Host: localhost 232750Szelenkov@nginx.comConnection: close 233750Szelenkov@nginx.com 234750Szelenkov@nginx.com""", sock=sock, raw=True) 235750Szelenkov@nginx.com 236750Szelenkov@nginx.com self.assertEqual(resp['status'], 200, 'reconfigure 3') 237750Szelenkov@nginx.com 238603Szelenkov@nginx.com def test_python_atexit(self): 239603Szelenkov@nginx.com self.skip_alerts.append(r'sendmsg.+failed') 240603Szelenkov@nginx.com self.load('atexit') 241603Szelenkov@nginx.com 242603Szelenkov@nginx.com self.get() 243603Szelenkov@nginx.com 244603Szelenkov@nginx.com self.conf({ 245603Szelenkov@nginx.com "listeners": {}, 246603Szelenkov@nginx.com "applications": {} 247603Szelenkov@nginx.com }) 248603Szelenkov@nginx.com 249603Szelenkov@nginx.com self.stop() 250603Szelenkov@nginx.com 251603Szelenkov@nginx.com self.assertIsNotNone(self.search_in_log(r'At exit called\.'), 'atexit') 252603Szelenkov@nginx.com 253603Szelenkov@nginx.com @unittest.expectedFailure 254603Szelenkov@nginx.com def test_python_application_start_response_exit(self): 255603Szelenkov@nginx.com self.load('start_response_exit') 256603Szelenkov@nginx.com 257603Szelenkov@nginx.com self.assertEqual(self.get()['status'], 500, 'start response exit') 258603Szelenkov@nginx.com 259603Szelenkov@nginx.com @unittest.expectedFailure 260603Szelenkov@nginx.com def test_python_application_input_iter(self): 261603Szelenkov@nginx.com self.load('input_iter') 262603Szelenkov@nginx.com 263603Szelenkov@nginx.com body = '0123456789' 264603Szelenkov@nginx.com 265603Szelenkov@nginx.com self.assertEqual(self.post(body=body)['body'], body, 'input iter') 266603Szelenkov@nginx.com 267603Szelenkov@nginx.com def test_python_application_input_read_length(self): 268603Szelenkov@nginx.com self.load('input_read_length') 269603Szelenkov@nginx.com 270603Szelenkov@nginx.com body = '0123456789' 271603Szelenkov@nginx.com 272603Szelenkov@nginx.com resp = self.post(headers={ 273603Szelenkov@nginx.com 'Host': 'localhost', 274603Szelenkov@nginx.com 'Input-Length': '5', 275603Szelenkov@nginx.com 'Connection': 'close' 276603Szelenkov@nginx.com }, body=body) 277603Szelenkov@nginx.com 278603Szelenkov@nginx.com self.assertEqual(resp['body'], body[:5], 'input read length lt body') 279603Szelenkov@nginx.com 280603Szelenkov@nginx.com resp = self.post(headers={ 281603Szelenkov@nginx.com 'Host': 'localhost', 282603Szelenkov@nginx.com 'Input-Length': '15', 283603Szelenkov@nginx.com 'Connection': 'close' 284603Szelenkov@nginx.com }, body=body) 285603Szelenkov@nginx.com 286603Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'input read length gt body') 287603Szelenkov@nginx.com 288603Szelenkov@nginx.com resp = self.post(headers={ 289603Szelenkov@nginx.com 'Host': 'localhost', 290603Szelenkov@nginx.com 'Input-Length': '0', 291603Szelenkov@nginx.com 'Connection': 'close' 292603Szelenkov@nginx.com }, body=body) 293603Szelenkov@nginx.com 294603Szelenkov@nginx.com self.assertEqual(resp['body'], '', 'input read length zero') 295603Szelenkov@nginx.com 296603Szelenkov@nginx.com resp = self.post(headers={ 297603Szelenkov@nginx.com 'Host': 'localhost', 298603Szelenkov@nginx.com 'Input-Length': '-1', 299603Szelenkov@nginx.com 'Connection': 'close' 300603Szelenkov@nginx.com }, body=body) 301603Szelenkov@nginx.com 302603Szelenkov@nginx.com self.assertEqual(resp['body'], body, 'input read length negative') 303603Szelenkov@nginx.com 304603Szelenkov@nginx.com @unittest.expectedFailure 305603Szelenkov@nginx.com def test_python_application_errors_write(self): 306603Szelenkov@nginx.com self.load('errors_write') 307603Szelenkov@nginx.com 308603Szelenkov@nginx.com self.get() 309603Szelenkov@nginx.com 310603Szelenkov@nginx.com self.stop() 311603Szelenkov@nginx.com 312603Szelenkov@nginx.com self.assertIsNotNone( 313603Szelenkov@nginx.com self.search_in_log(r'\[error\].+Error in application\.'), 314603Szelenkov@nginx.com 'errors write') 315603Szelenkov@nginx.com 316603Szelenkov@nginx.com def test_python_application_body_array(self): 317603Szelenkov@nginx.com self.load('body_array') 318603Szelenkov@nginx.com 319603Szelenkov@nginx.com self.assertEqual(self.get()['body'], '0123456789', 'body array') 320603Szelenkov@nginx.com 321603Szelenkov@nginx.com def test_python_application_body_io(self): 322603Szelenkov@nginx.com self.load('body_io') 323603Szelenkov@nginx.com 324603Szelenkov@nginx.com self.assertEqual(self.get()['body'], '0123456789', 'body io') 325603Szelenkov@nginx.com 326603Szelenkov@nginx.com def test_python_application_body_io_file(self): 327603Szelenkov@nginx.com self.load('body_io_file') 328603Szelenkov@nginx.com 329603Szelenkov@nginx.com self.assertEqual(self.get()['body'], 'body\n', 'body io file') 330603Szelenkov@nginx.com 331603Szelenkov@nginx.com @unittest.expectedFailure 332603Szelenkov@nginx.com def test_python_application_syntax_error(self): 333603Szelenkov@nginx.com self.skip_alerts.append(r'Python failed to import module "wsgi"') 334603Szelenkov@nginx.com self.load('syntax_error') 335603Szelenkov@nginx.com 336603Szelenkov@nginx.com self.assertEqual(self.get()['status'], 500, 'syntax error') 337603Szelenkov@nginx.com 338603Szelenkov@nginx.com def test_python_application_close(self): 339603Szelenkov@nginx.com self.load('close') 340603Szelenkov@nginx.com 341603Szelenkov@nginx.com self.get() 342603Szelenkov@nginx.com 343603Szelenkov@nginx.com self.stop() 344603Szelenkov@nginx.com 345603Szelenkov@nginx.com self.assertIsNotNone(self.search_in_log(r'Close called\.'), 'close') 346603Szelenkov@nginx.com 347603Szelenkov@nginx.com def test_python_application_close_error(self): 348603Szelenkov@nginx.com self.load('close_error') 349603Szelenkov@nginx.com 350603Szelenkov@nginx.com self.get() 351603Szelenkov@nginx.com 352603Szelenkov@nginx.com self.stop() 353603Szelenkov@nginx.com 354603Szelenkov@nginx.com self.assertIsNotNone(self.search_in_log(r'Close called\.'), 355603Szelenkov@nginx.com 'close error') 356603Szelenkov@nginx.com 357617Szelenkov@nginx.com def test_python_application_not_iterable(self): 358617Szelenkov@nginx.com self.load('not_iterable') 359617Szelenkov@nginx.com 360665Szelenkov@nginx.com self.get() 361617Szelenkov@nginx.com 362617Szelenkov@nginx.com self.stop() 363617Szelenkov@nginx.com 364617Szelenkov@nginx.com self.assertIsNotNone(self.search_in_log( 365617Szelenkov@nginx.com r'\[error\].+the application returned not an iterable object'), 366617Szelenkov@nginx.com 'not iterable') 367617Szelenkov@nginx.com 368664Szelenkov@nginx.com def test_python_application_write(self): 369664Szelenkov@nginx.com self.load('write') 370664Szelenkov@nginx.com 371664Szelenkov@nginx.com self.assertEqual(self.get()['body'], '0123456789', 'write') 372664Szelenkov@nginx.com 373484Szelenkov@nginx.comif __name__ == '__main__': 374853Szelenkov@nginx.com TestUnitPythonApplication.main() 375