1import pytest 2import time 3 4from unit.applications.lang.python import TestApplicationPython 5 6 7class TestAccessLog(TestApplicationPython): 8 prerequisites = {'modules': {'python': 'any'}} 9 10 def load(self, script): 11 super().load(script) 12 13 assert 'success' in self.conf( 14 '"' + self.temp_dir + '/access.log"', 'access_log' 15 ), 'access_log configure' 16 17 def wait_for_record(self, pattern, name='access.log'): 18 return super().wait_for_record(pattern, name) 19 20 def test_access_log_keepalive(self): 21 self.load('mirror') 22 23 assert self.get()['status'] == 200, 'init' 24 25 (resp, sock) = self.post( 26 headers={ 27 'Host': 'localhost', 28 'Connection': 'keep-alive', 29 'Content-Type': 'text/html', 30 }, 31 start=True, 32 body='01234', 33 read_timeout=1, 34 ) 35 36 assert ( 37 self.wait_for_record(r'"POST / HTTP/1.1" 200 5') is not None 38 ), 'keepalive 1' 39 40 resp = self.post( 41 headers={ 42 'Host': 'localhost', 43 'Connection': 'close', 44 'Content-Type': 'text/html', 45 }, 46 sock=sock, 47 body='0123456789', 48 ) 49 50 self.stop() 51 52 assert ( 53 self.wait_for_record(r'"POST / HTTP/1.1" 200 10') is not None 54 ), 'keepalive 2' 55 56 def test_access_log_pipeline(self): 57 self.load('empty') 58 59 self.http( 60 b"""GET / HTTP/1.1 61Host: localhost 62Referer: Referer-1 63 64GET / HTTP/1.1 65Host: localhost 66Referer: Referer-2 67 68GET / HTTP/1.1 69Host: localhost 70Referer: Referer-3 71Connection: close 72 73""", 74 raw_resp=True, 75 raw=True, 76 ) 77 78 self.stop() 79 80 assert ( 81 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"') 82 is not None 83 ), 'pipeline 1' 84 assert ( 85 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-2" "-"') 86 is not None 87 ), 'pipeline 2' 88 assert ( 89 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-3" "-"') 90 is not None 91 ), 'pipeline 3' 92 93 def test_access_log_ipv6(self): 94 self.load('empty') 95 96 self.conf({"[::1]:7080": {"pass": "applications/empty"}}, 'listeners') 97 98 self.get(sock_type='ipv6') 99 100 self.stop() 101 102 assert ( 103 self.wait_for_record( 104 r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' 105 ) 106 is not None 107 ), 'ipv6' 108 109 def test_access_log_unix(self): 110 self.load('empty') 111 112 addr = self.temp_dir + '/sock' 113 114 self.conf( 115 {"unix:" + addr: {"pass": "applications/empty"}}, 'listeners' 116 ) 117 118 self.get(sock_type='unix', addr=addr) 119 120 self.stop() 121 122 assert ( 123 self.wait_for_record( 124 r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' 125 ) 126 is not None 127 ), 'unix' 128 129 def test_access_log_referer(self): 130 self.load('empty') 131 132 self.get( 133 headers={ 134 'Host': 'localhost', 135 'Referer': 'referer-value', 136 'Connection': 'close', 137 } 138 ) 139 140 self.stop() 141 142 assert ( 143 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "referer-value" "-"') 144 is not None 145 ), 'referer' 146 147 def test_access_log_user_agent(self): 148 self.load('empty') 149 150 self.get( 151 headers={ 152 'Host': 'localhost', 153 'User-Agent': 'user-agent-value', 154 'Connection': 'close', 155 } 156 ) 157 158 self.stop() 159 160 assert ( 161 self.wait_for_record( 162 r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"' 163 ) 164 is not None 165 ), 'user agent' 166 167 def test_access_log_http10(self): 168 self.load('empty') 169 170 self.get(http_10=True) 171 172 self.stop() 173 174 assert ( 175 self.wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"') is not None 176 ), 'http 1.0' 177 178 def test_access_log_partial(self): 179 self.load('empty') 180 181 assert self.post()['status'] == 200, 'init' 182 183 resp = self.http(b"""GE""", raw=True, read_timeout=1) 184 185 time.sleep(1) 186 187 self.stop() 188 189 assert ( 190 self.wait_for_record(r'"GE" 400 0 "-" "-"') is not None 191 ), 'partial' 192 193 def test_access_log_partial_2(self): 194 self.load('empty') 195 196 assert self.post()['status'] == 200, 'init' 197 198 self.http(b"""GET /\n""", raw=True) 199 200 self.stop() 201 202 assert ( 203 self.wait_for_record(r'"GET /" 400 \d+ "-" "-"') is not None 204 ), 'partial 2' 205 206 def test_access_log_partial_3(self): 207 self.load('empty') 208 209 assert self.post()['status'] == 200, 'init' 210 211 resp = self.http(b"""GET / HTTP/1.1""", raw=True, read_timeout=1) 212 213 time.sleep(1) 214 215 self.stop() 216 217 assert ( 218 self.wait_for_record(r'"GET /" 400 0 "-" "-"') is not None 219 ), 'partial 3' 220 221 def test_access_log_partial_4(self): 222 self.load('empty') 223 224 assert self.post()['status'] == 200, 'init' 225 226 resp = self.http(b"""GET / HTTP/1.1\n""", raw=True, read_timeout=1) 227 228 time.sleep(1) 229 230 self.stop() 231 232 assert ( 233 self.wait_for_record(r'"GET / HTTP/1.1" 400 0 "-" "-"') is not None 234 ), 'partial 4' 235 236 @pytest.mark.skip('not yet') 237 def test_access_log_partial_5(self): 238 self.load('empty') 239 240 assert self.post()['status'] == 200, 'init' 241 242 self.get(headers={'Connection': 'close'}) 243 244 self.stop() 245 246 assert ( 247 self.wait_for_record(r'"GET / HTTP/1.1" 400 \d+ "-" "-"') 248 is not None 249 ), 'partial 5' 250 251 def test_access_log_get_parameters(self): 252 self.load('empty') 253 254 self.get(url='/?blah&var=val') 255 256 self.stop() 257 258 assert ( 259 self.wait_for_record( 260 r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"' 261 ) 262 is not None 263 ), 'get parameters' 264 265 def test_access_log_delete(self): 266 self.load('empty') 267 268 self.conf_delete('access_log') 269 270 self.get(url='/delete') 271 272 self.stop() 273 274 assert self.search_in_log(r'/delete', 'access.log') is None, 'delete' 275 276 def test_access_log_change(self): 277 self.load('empty') 278 279 self.get() 280 281 self.conf('"' + self.temp_dir + '/new.log"', 'access_log') 282 283 self.get() 284 285 self.stop() 286 287 assert ( 288 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log') 289 is not None 290 ), 'change' 291