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