1import os 2import re 3import time 4from subprocess import call 5from unit.applications.lang.python import TestApplicationPython 6 7 8class TestAccessLog(TestApplicationPython): 9 prerequisites = ['python'] 10 11 def load(self, script): 12 super().load(script) 13 14 self.conf('"' + self.testdir + '/access.log"', 'access_log') 15 16 def wait_for_record(self, pattern, name='access.log'): 17 return super().wait_for_record(pattern, name) 18 19 def test_access_log_keepalive(self): 20 self.load('mirror') 21 22 self.assertEqual(self.get()['status'], 200, 'init') 23 24 (resp, sock) = self.post( 25 headers={ 26 'Host': 'localhost', 27 'Connection': 'keep-alive', 28 'Content-Type': 'text/html', 29 }, 30 start=True, 31 body='01234', 32 read_timeout=1, 33 ) 34 35 self.assertIsNotNone( 36 self.wait_for_record(r'"POST / HTTP/1.1" 200 5'), 'keepalive 1' 37 ) 38 39 resp = self.post( 40 headers={ 41 'Host': 'localhost', 42 'Connection': 'close', 43 'Content-Type': 'text/html', 44 }, 45 sock=sock, 46 body='0123456789', 47 ) 48 49 self.stop() 50 51 self.assertIsNotNone( 52 self.wait_for_record(r'"POST / HTTP/1.1" 200 10'), 'keepalive 2' 53 ) 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 self.stop() 78 79 self.assertIsNotNone( 80 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"'), 81 'pipeline 1', 82 ) 83 self.assertIsNotNone( 84 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-2" "-"'), 85 'pipeline 2', 86 ) 87 self.assertIsNotNone( 88 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-3" "-"'), 89 'pipeline 3', 90 ) 91 92 def test_access_log_ipv6(self): 93 self.load('empty') 94 95 self.conf({"[::1]:7080": {"application": "empty"}}, 'listeners') 96 97 self.get(sock_type='ipv6') 98 99 self.stop() 100 101 self.assertIsNotNone( 102 self.wait_for_record( 103 r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' 104 ), 105 'ipv6', 106 ) 107 108 def test_access_log_unix(self): 109 self.load('empty') 110 111 addr = self.testdir + '/sock' 112 113 self.conf({"unix:" + addr: {"application": "empty"}}, 'listeners') 114 115 self.get(sock_type='unix', addr=addr) 116 117 self.stop() 118 119 self.assertIsNotNone( 120 self.wait_for_record( 121 r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' 122 ), 123 'unix', 124 ) 125 126 def test_access_log_referer(self): 127 self.load('empty') 128 129 self.get( 130 headers={ 131 'Host': 'localhost', 132 'Referer': 'referer-value', 133 'Connection': 'close', 134 } 135 ) 136 137 self.stop() 138 139 self.assertIsNotNone( 140 self.wait_for_record( 141 r'"GET / HTTP/1.1" 200 0 "referer-value" "-"' 142 ), 143 'referer', 144 ) 145 146 def test_access_log_user_agent(self): 147 self.load('empty') 148 149 self.get( 150 headers={ 151 'Host': 'localhost', 152 'User-Agent': 'user-agent-value', 153 'Connection': 'close', 154 } 155 ) 156 157 self.stop() 158 159 self.assertIsNotNone( 160 self.wait_for_record( 161 r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"' 162 ), 163 'user agent', 164 ) 165 166 def test_access_log_http10(self): 167 self.load('empty') 168 169 self.get(http_10=True) 170 171 self.stop() 172 173 self.assertIsNotNone( 174 self.wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"'), 'http 1.0' 175 ) 176 177 def test_access_log_partial(self): 178 self.load('empty') 179 180 self.http(b"""GE""", raw=True, no_recv=True) 181 182 self.stop() 183 184 self.assertIsNotNone( 185 self.wait_for_record(r'"GE" 400 0 "-" "-"'), 'partial' 186 ) 187 188 def test_access_log_partial_2(self): 189 self.load('empty') 190 191 self.http(b"""GET /\n""", raw=True, no_recv=True) 192 193 self.stop() 194 195 self.assertIsNotNone( 196 self.wait_for_record(r'"GET /" 400 \d+ "-" "-"'), 'partial 2' 197 ) 198 199 def test_access_log_partial_3(self): 200 self.load('empty') 201 202 self.http(b"""GET / HTTP/1.1""", raw=True, no_recv=True) 203 204 self.stop() 205 206 self.assertIsNotNone( 207 self.wait_for_record(r'"GET /" 400 0 "-" "-"'), 'partial 3' 208 ) 209 210 def test_access_log_partial_4(self): 211 self.load('empty') 212 213 resp = self.http(b"""GET / HTTP/1.1\n""", raw=True, no_recv=True) 214 215 self.stop() 216 217 self.assertIsNotNone( 218 self.wait_for_record(r'"GET / HTTP/1.1" 400 0 "-" "-"'), 219 'partial 4', 220 ) 221 222 def test_access_log_partial_5(self): 223 self.load('empty') 224 225 self.assertEqual(self.post()['status'], 200, 'init') 226 227 self.http(b"""GET / HTTP/1.1\n\n""", raw=True, read_timeout=1) 228 229 self.stop() 230 231 self.assertIsNotNone( 232 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"'), 233 'partial 5', 234 ) 235 236 def test_access_log_get_parameters(self): 237 self.load('empty') 238 239 self.get(url='/?blah&var=val') 240 241 self.stop() 242 243 self.assertIsNotNone( 244 self.wait_for_record( 245 r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"' 246 ), 247 'get parameters', 248 ) 249 250 def test_access_log_delete(self): 251 self.load('empty') 252 253 self.conf_delete('access_log') 254 255 self.get(url='/delete') 256 257 self.stop() 258 259 self.assertIsNone( 260 self.search_in_log(r'/delete', 'access.log'), 'delete' 261 ) 262 263 def test_access_log_change(self): 264 self.load('empty') 265 266 self.get() 267 268 self.conf('"' + self.testdir + '/new.log"', 'access_log') 269 270 self.get() 271 272 self.stop() 273 274 self.assertIsNotNone( 275 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log'), 276 'change', 277 ) 278 279 def test_access_log_reopen(self): 280 self.load('empty') 281 282 log_path = self.testdir + '/access.log' 283 284 self.assertTrue(self.waitforfiles(log_path), 'open') 285 286 log_path_new = self.testdir + '/new.log' 287 288 os.rename(log_path, log_path_new) 289 290 self.get() 291 292 self.assertIsNotNone( 293 self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log'), 294 'rename new', 295 ) 296 self.assertFalse(os.path.isfile(log_path), 'rename old') 297 298 with open(self.testdir + '/unit.pid', 'r') as f: 299 pid = f.read().rstrip() 300 301 call(['kill', '-s', 'USR1', pid]) 302 303 self.assertTrue(self.waitforfiles(log_path), 'reopen') 304 305 self.get(url='/usr1') 306 307 self.assertIsNotNone( 308 self.wait_for_record(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"'), 309 'reopen 2', 310 ) 311 self.assertIsNone( 312 self.search_in_log(r'/usr1', 'new.log'), 'rename new 2' 313 ) 314 315 316if __name__ == '__main__': 317 TestAccessLog.main() 318