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