xref: /unit/test/test_access_log.py (revision 1029:687f7cc7aae2)
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