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