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