xref: /unit/test/test_settings.py (revision 2073:bc6ad31ce286)
1import re
2import socket
3import time
4
5import pytest
6from unit.applications.lang.python import TestApplicationPython
7from unit.utils import sysctl
8
9
10class TestSettings(TestApplicationPython):
11    prerequisites = {'modules': {'python': 'any'}}
12
13    def test_settings_header_read_timeout(self):
14        self.load('empty')
15
16        def req():
17            (resp, sock) = self.http(
18                b"""GET / HTTP/1.1
19""",
20                start=True,
21                read_timeout=1,
22                raw=True,
23            )
24
25            time.sleep(3)
26
27            return self.http(
28                b"""Host: localhost
29Connection: close
30
31    """,
32                sock=sock,
33                raw=True,
34            )
35
36        assert 'success' in self.conf(
37            {'http': {'header_read_timeout': 2}}, 'settings'
38        )
39        assert req()['status'] == 408, 'status header read timeout'
40
41        assert 'success' in self.conf(
42            {'http': {'header_read_timeout': 7}}, 'settings'
43        )
44        assert req()['status'] == 200, 'status header read timeout 2'
45
46    def test_settings_header_read_timeout_update(self):
47        self.load('empty')
48
49        assert 'success' in self.conf(
50            {'http': {'header_read_timeout': 4}}, 'settings'
51        )
52
53        (resp, sock) = self.http(
54            b"""GET / HTTP/1.1
55""",
56            start=True,
57            raw=True,
58            no_recv=True,
59        )
60
61        time.sleep(2)
62
63        (resp, sock) = self.http(
64            b"""Host: localhost
65""",
66            start=True,
67            sock=sock,
68            raw=True,
69            no_recv=True,
70        )
71
72        time.sleep(2)
73
74        (resp, sock) = self.http(
75            b"""X-Blah: blah
76""",
77            start=True,
78            sock=sock,
79            read_timeout=1,
80            raw=True,
81        )
82
83        if len(resp) != 0:
84            sock.close()
85
86        else:
87            time.sleep(2)
88
89            resp = self.http(
90                b"""Connection: close
91
92""",
93                sock=sock,
94                raw=True,
95            )
96
97        assert resp['status'] == 408, 'status header read timeout update'
98
99    def test_settings_body_read_timeout(self):
100        self.load('empty')
101
102        def req():
103            (resp, sock) = self.http(
104                b"""POST / HTTP/1.1
105Host: localhost
106Content-Length: 10
107Connection: close
108
109""",
110                start=True,
111                raw_resp=True,
112                read_timeout=1,
113                raw=True,
114            )
115
116            time.sleep(3)
117
118            return self.http(b"""0123456789""", sock=sock, raw=True)
119
120        assert 'success' in self.conf(
121            {'http': {'body_read_timeout': 2}}, 'settings'
122        )
123        assert req()['status'] == 408, 'status body read timeout'
124
125        assert 'success' in self.conf(
126            {'http': {'body_read_timeout': 7}}, 'settings'
127        )
128        assert req()['status'] == 200, 'status body read timeout 2'
129
130    def test_settings_body_read_timeout_update(self):
131        self.load('empty')
132
133        assert 'success' in self.conf(
134            {'http': {'body_read_timeout': 4}}, 'settings'
135        )
136
137        (resp, sock) = self.http(
138            b"""POST / HTTP/1.1
139Host: localhost
140Content-Length: 10
141Connection: close
142
143""",
144            start=True,
145            read_timeout=1,
146            raw=True,
147        )
148
149        time.sleep(2)
150
151        (resp, sock) = self.http(
152            b"""012""", start=True, sock=sock, read_timeout=1, raw=True
153        )
154
155        time.sleep(2)
156
157        (resp, sock) = self.http(
158            b"""345""", start=True, sock=sock, read_timeout=1, raw=True
159        )
160
161        time.sleep(2)
162
163        resp = self.http(b"""6789""", sock=sock, raw=True)
164
165        assert resp['status'] == 200, 'status body read timeout update'
166
167    def test_settings_send_timeout(self, temp_dir):
168        self.load('body_generate')
169
170        def req(addr, data_len):
171            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
172            sock.connect(addr)
173
174            req = (
175                """GET / HTTP/1.1
176Host: localhost
177X-Length: %d
178Connection: close
179
180"""
181                % data_len
182            )
183
184            sock.sendall(req.encode())
185
186            data = sock.recv(16).decode()
187
188            time.sleep(3)
189
190            data += self.recvall(sock).decode()
191
192            sock.close()
193
194            return data
195
196        sysctl_out = sysctl()
197        values = re.findall(
198            r'net.core.[rw]mem_(?:max|default).*?(\d+)', sysctl_out
199        )
200        values = [int(v) for v in values]
201
202        data_len = 1048576 if len(values) == 0 else 10 * max(values)
203
204        addr = temp_dir + '/sock'
205
206        assert 'success' in self.conf(
207            {"unix:" + addr: {'application': 'body_generate'}}, 'listeners'
208        )
209
210        assert 'success' in self.conf({'http': {'send_timeout': 1}}, 'settings')
211
212        data = req(addr, data_len)
213        assert re.search(r'200 OK', data), 'send timeout status'
214        assert len(data) < data_len, 'send timeout data '
215
216        self.conf({'http': {'send_timeout': 7}}, 'settings')
217
218        data = req(addr, data_len)
219        assert re.search(r'200 OK', data), 'send timeout status  2'
220        assert len(data) > data_len, 'send timeout data 2'
221
222    def test_settings_idle_timeout(self):
223        self.load('empty')
224
225        def req():
226            (resp, sock) = self.get(
227                headers={'Host': 'localhost', 'Connection': 'keep-alive'},
228                start=True,
229                read_timeout=1,
230            )
231
232            time.sleep(3)
233
234            return self.get(sock=sock)
235
236        assert self.get()['status'] == 200, 'init'
237
238        assert 'success' in self.conf({'http': {'idle_timeout': 2}}, 'settings')
239        assert req()['status'] == 408, 'status idle timeout'
240
241        assert 'success' in self.conf({'http': {'idle_timeout': 7}}, 'settings')
242        assert req()['status'] == 200, 'status idle timeout 2'
243
244    def test_settings_idle_timeout_2(self):
245        self.load('empty')
246
247        def req():
248            _, sock = self.http(b'', start=True, raw=True, no_recv=True)
249
250            time.sleep(3)
251
252            return self.get(sock=sock)
253
254        assert self.get()['status'] == 200, 'init'
255
256        assert 'success' in self.conf({'http': {'idle_timeout': 1}}, 'settings')
257        assert req()['status'] == 408, 'status idle timeout'
258
259        assert 'success' in self.conf({'http': {'idle_timeout': 7}}, 'settings')
260        assert req()['status'] == 200, 'status idle timeout 2'
261
262    def test_settings_max_body_size(self):
263        self.load('empty')
264
265        assert 'success' in self.conf(
266            {'http': {'max_body_size': 5}}, 'settings'
267        )
268
269        assert self.post(body='01234')['status'] == 200, 'status size'
270        assert self.post(body='012345')['status'] == 413, 'status size max'
271
272    def test_settings_max_body_size_large(self):
273        self.load('mirror')
274
275        assert 'success' in self.conf(
276            {'http': {'max_body_size': 32 * 1024 * 1024}}, 'settings'
277        )
278
279        body = '0123456789abcdef' * 4 * 64 * 1024
280        resp = self.post(body=body, read_buffer_size=1024 * 1024)
281        assert resp['status'] == 200, 'status size 4'
282        assert resp['body'] == body, 'status body 4'
283
284        body = '0123456789abcdef' * 8 * 64 * 1024
285        resp = self.post(body=body, read_buffer_size=1024 * 1024)
286        assert resp['status'] == 200, 'status size 8'
287        assert resp['body'] == body, 'status body 8'
288
289        body = '0123456789abcdef' * 16 * 64 * 1024
290        resp = self.post(body=body, read_buffer_size=1024 * 1024)
291        assert resp['status'] == 200, 'status size 16'
292        assert resp['body'] == body, 'status body 16'
293
294        body = '0123456789abcdef' * 32 * 64 * 1024
295        resp = self.post(body=body, read_buffer_size=1024 * 1024)
296        assert resp['status'] == 200, 'status size 32'
297        assert resp['body'] == body, 'status body 32'
298
299    @pytest.mark.skip('not yet')
300    def test_settings_negative_value(self):
301        assert 'error' in self.conf(
302            {'http': {'max_body_size': -1}}, 'settings'
303        ), 'settings negative value'
304
305    def test_settings_body_buffer_size(self):
306        self.load('mirror')
307
308        assert 'success' in self.conf(
309            {
310                'http': {
311                    'max_body_size': 64 * 1024 * 1024,
312                    'body_buffer_size': 32 * 1024 * 1024,
313                }
314            },
315            'settings',
316        )
317
318        body = '0123456789abcdef'
319        resp = self.post(body=body)
320        assert bool(resp), 'response from application'
321        assert resp['status'] == 200, 'status'
322        assert resp['body'] == body, 'body'
323
324        body = '0123456789abcdef' * 1024 * 1024
325        resp = self.post(body=body, read_buffer_size=1024 * 1024)
326        assert bool(resp), 'response from application 2'
327        assert resp['status'] == 200, 'status 2'
328        assert resp['body'] == body, 'body 2'
329
330        body = '0123456789abcdef' * 2 * 1024 * 1024
331        resp = self.post(body=body, read_buffer_size=1024 * 1024)
332        assert bool(resp), 'response from application 3'
333        assert resp['status'] == 200, 'status 3'
334        assert resp['body'] == body, 'body 3'
335
336        body = '0123456789abcdef' * 3 * 1024 * 1024
337        resp = self.post(body=body, read_buffer_size=1024 * 1024)
338        assert bool(resp), 'response from application 4'
339        assert resp['status'] == 200, 'status 4'
340        assert resp['body'] == body, 'body 4'
341