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