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