1import re 2 3import pytest 4from unit.applications.lang.node import TestApplicationNode 5from unit.utils import waitforfiles 6 7 8class TestNodeApplication(TestApplicationNode): 9 prerequisites = {'modules': {'node': 'all'}} 10 11 def test_node_application_basic(self): 12 self.load('basic') 13 14 resp = self.get() 15 assert resp['headers']['Content-Type'] == 'text/plain', 'basic header' 16 assert resp['body'] == 'Hello World\n', 'basic body' 17 18 def test_node_application_seq(self): 19 self.load('basic') 20 21 assert self.get()['status'] == 200, 'seq' 22 assert self.get()['status'] == 200, 'seq 2' 23 24 def test_node_application_variables(self): 25 self.load('variables') 26 27 body = 'Test body string.' 28 29 resp = self.post( 30 headers={ 31 'Host': 'localhost', 32 'Content-Type': 'text/html', 33 'Custom-Header': 'blah', 34 'Connection': 'close', 35 }, 36 body=body, 37 ) 38 39 assert resp['status'] == 200, 'status' 40 headers = resp['headers'] 41 header_server = headers.pop('Server') 42 assert re.search(r'Unit/[\d\.]+', header_server), 'server header' 43 44 date = headers.pop('Date') 45 assert date[-4:] == ' GMT', 'date header timezone' 46 assert ( 47 abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 48 ), 'date header' 49 50 raw_headers = headers.pop('Request-Raw-Headers') 51 assert re.search( 52 r'^(?:Host|localhost|Content-Type|' 53 r'text\/html|Custom-Header|blah|Content-Length|17|Connection|' 54 r'close|,)+$', 55 raw_headers, 56 ), 'raw headers' 57 58 assert headers == { 59 'Connection': 'close', 60 'Content-Length': str(len(body)), 61 'Content-Type': 'text/html', 62 'Request-Method': 'POST', 63 'Request-Uri': '/', 64 'Http-Host': 'localhost', 65 'Server-Protocol': 'HTTP/1.1', 66 'Custom-Header': 'blah', 67 }, 'headers' 68 assert resp['body'] == body, 'body' 69 70 def test_node_application_get_variables(self): 71 self.load('get_variables') 72 73 resp = self.get(url='/?var1=val1&var2=&var3') 74 assert resp['headers']['X-Var-1'] == 'val1', 'GET variables' 75 assert resp['headers']['X-Var-2'] == '', 'GET variables 2' 76 assert resp['headers']['X-Var-3'] == '', 'GET variables 3' 77 78 def test_node_application_post_variables(self): 79 self.load('post_variables') 80 81 resp = self.post( 82 headers={ 83 'Content-Type': 'application/x-www-form-urlencoded', 84 'Host': 'localhost', 85 'Connection': 'close', 86 }, 87 body='var1=val1&var2=&var3', 88 ) 89 90 assert resp['headers']['X-Var-1'] == 'val1', 'POST variables' 91 assert resp['headers']['X-Var-2'] == '', 'POST variables 2' 92 assert resp['headers']['X-Var-3'] == '', 'POST variables 3' 93 94 def test_node_application_404(self): 95 self.load('404') 96 97 resp = self.get() 98 99 assert resp['status'] == 404, '404 status' 100 assert re.search( 101 r'<title>404 Not Found</title>', resp['body'] 102 ), '404 body' 103 104 def test_node_keepalive_body(self): 105 self.load('mirror') 106 107 assert self.get()['status'] == 200, 'init' 108 109 body = '0123456789' * 500 110 (resp, sock) = self.post( 111 headers={ 112 'Host': 'localhost', 113 'Connection': 'keep-alive', 114 'Content-Type': 'text/html', 115 }, 116 start=True, 117 body=body, 118 read_timeout=1, 119 ) 120 121 assert resp['body'] == '0123456789' * 500, 'keep-alive 1' 122 123 body = '0123456789' 124 resp = self.post( 125 headers={ 126 'Host': 'localhost', 127 'Connection': 'close', 128 'Content-Type': 'text/html', 129 }, 130 sock=sock, 131 body=body, 132 ) 133 134 assert resp['body'] == body, 'keep-alive 2' 135 136 def test_node_application_write_buffer(self): 137 self.load('write_buffer') 138 139 assert self.get()['body'] == 'buffer', 'write buffer' 140 141 def test_node_application_write_callback(self, temp_dir): 142 self.load('write_callback') 143 144 assert self.get()['body'] == 'helloworld', 'write callback order' 145 assert waitforfiles(temp_dir + '/node/callback'), 'write callback' 146 147 def test_node_application_write_before_write_head(self): 148 self.load('write_before_write_head') 149 150 assert self.get()['status'] == 200, 'write before writeHead' 151 152 def test_node_application_double_end(self): 153 self.load('double_end') 154 155 assert self.get()['status'] == 200, 'double end' 156 assert self.get()['status'] == 200, 'double end 2' 157 158 def test_node_application_write_return(self): 159 self.load('write_return') 160 161 assert self.get()['body'] == 'bodytrue', 'write return' 162 163 def test_node_application_remove_header(self): 164 self.load('remove_header') 165 166 resp = self.get( 167 headers={ 168 'Host': 'localhost', 169 'X-Remove': 'X-Header', 170 'Connection': 'close', 171 } 172 ) 173 assert resp['headers']['Was-Header'] == 'true', 'was header' 174 assert resp['headers']['Has-Header'] == 'false', 'has header' 175 assert not ('X-Header' in resp['headers']), 'remove header' 176 177 def test_node_application_remove_header_nonexisting(self): 178 self.load('remove_header') 179 180 assert ( 181 self.get( 182 headers={ 183 'Host': 'localhost', 184 'X-Remove': 'blah', 185 'Connection': 'close', 186 } 187 )['headers']['Has-Header'] 188 == 'true' 189 ), 'remove header nonexisting' 190 191 def test_node_application_update_header(self): 192 self.load('update_header') 193 194 assert self.get()['headers']['X-Header'] == 'new', 'update header' 195 196 def test_node_application_set_header_array(self): 197 self.load('set_header_array') 198 199 assert self.get()['headers']['Set-Cookie'] == [ 200 'tc=one,two,three', 201 'tc=four,five,six', 202 ], 'set header array' 203 204 @pytest.mark.skip('not yet') 205 def test_node_application_status_message(self): 206 self.load('status_message') 207 208 assert re.search(r'200 blah', self.get(raw_resp=True)), 'status message' 209 210 def test_node_application_get_header_type(self): 211 self.load('get_header_type') 212 213 assert self.get()['headers']['X-Type'] == 'number', 'get header type' 214 215 def test_node_application_header_name_case(self): 216 self.load('header_name_case') 217 218 headers = self.get()['headers'] 219 220 assert headers['X-HEADER'] == '3', 'header value' 221 assert 'X-Header' not in headers, 'insensitive' 222 assert 'X-header' not in headers, 'insensitive 2' 223 224 def test_node_application_promise_handler_write_after_end(self): 225 self.load('promise_handler') 226 227 assert ( 228 self.post( 229 headers={ 230 'Host': 'localhost', 231 'Content-Type': 'text/html', 232 'X-Write-Call': '1', 233 'Connection': 'close', 234 }, 235 body='callback', 236 )['status'] 237 == 200 238 ), 'promise handler request write after end' 239 240 def test_node_application_promise_end(self, temp_dir): 241 self.load('promise_end') 242 243 assert ( 244 self.post( 245 headers={ 246 'Host': 'localhost', 247 'Content-Type': 'text/html', 248 'Connection': 'close', 249 }, 250 body='end', 251 )['status'] 252 == 200 253 ), 'promise end request' 254 assert waitforfiles(temp_dir + '/node/callback'), 'promise end' 255 256 @pytest.mark.skip('not yet') 257 def test_node_application_header_name_valid(self): 258 self.load('header_name_valid') 259 260 assert 'status' not in self.get(), 'header name valid' 261 262 def test_node_application_header_value_object(self): 263 self.load('header_value_object') 264 265 assert 'X-Header' in self.get()['headers'], 'header value object' 266 267 def test_node_application_get_header_names(self): 268 self.load('get_header_names') 269 270 assert self.get()['headers']['X-Names'] == [ 271 'date', 272 'x-header', 273 ], 'get header names' 274 275 def test_node_application_has_header(self): 276 self.load('has_header') 277 278 assert ( 279 self.get( 280 headers={ 281 'Host': 'localhost', 282 'X-Header': 'length', 283 'Connection': 'close', 284 } 285 )['headers']['X-Has-Header'] 286 == 'false' 287 ), 'has header length' 288 289 assert ( 290 self.get( 291 headers={ 292 'Host': 'localhost', 293 'X-Header': 'Date', 294 'Connection': 'close', 295 } 296 )['headers']['X-Has-Header'] 297 == 'false' 298 ), 'has header date' 299 300 def test_node_application_write_multiple(self): 301 self.load('write_multiple') 302 303 assert self.get()['body'] == 'writewrite2end', 'write multiple' 304