xref: /unit/test/test_node_application.py (revision 2642:d92e92c69c5d)
1import re
2
3import pytest
4
5from unit.applications.lang.node import ApplicationNode
6from unit.utils import waitforfiles
7
8prerequisites = {'modules': {'node': 'all'}}
9
10client = ApplicationNode()
11
12
13def assert_basic_application():
14    resp = client.get()
15    assert resp['headers']['Content-Type'] == 'text/plain', 'basic header'
16    assert resp['body'] == 'Hello World\n', 'basic body'
17
18
19def test_node_application_basic():
20    client.load('basic')
21
22    assert_basic_application()
23
24def test_node_application_options(wait_for_record):
25    client.load('options')
26
27    assert_basic_application()
28    assert wait_for_record(r'constructor was called with unsupported') is not None
29
30
31def test_node_application_loader_unit_http():
32    client.load('loader/unit_http')
33
34    assert_basic_application()
35
36
37def test_node_application_loader_transitive_dependency():
38    client.load('loader/transitive_dependency')
39
40    assert_basic_application()
41
42
43def test_node_application_seq():
44    client.load('basic')
45
46    assert client.get()['status'] == 200, 'seq'
47    assert client.get()['status'] == 200, 'seq 2'
48
49
50def test_node_application_variables(date_to_sec_epoch, sec_epoch):
51    client.load('variables')
52
53    body = 'Test body string.'
54
55    resp = client.post(
56        headers={
57            'Host': 'localhost',
58            'Content-Type': 'text/html',
59            'Custom-Header': 'blah',
60            'Connection': 'close',
61        },
62        body=body,
63    )
64
65    assert resp['status'] == 200, 'status'
66    headers = resp['headers']
67    header_server = headers.pop('Server')
68    assert re.search(r'Unit/[\d\.]+', header_server), 'server header'
69
70    date = headers.pop('Date')
71    assert date[-4:] == ' GMT', 'date header timezone'
72    assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
73
74    raw_headers = headers.pop('Request-Raw-Headers')
75    assert re.search(
76        r'^(?:Host|localhost|Content-Type|'
77        r'text\/html|Custom-Header|blah|Content-Length|17|Connection|'
78        r'close|,)+$',
79        raw_headers,
80    ), 'raw headers'
81
82    assert headers == {
83        'Connection': 'close',
84        'Content-Length': str(len(body)),
85        'Content-Type': 'text/html',
86        'Request-Method': 'POST',
87        'Request-Uri': '/',
88        'Http-Host': 'localhost',
89        'Server-Protocol': '1.1',
90        'Custom-Header': 'blah',
91    }, 'headers'
92    assert resp['body'] == body, 'body'
93
94
95def test_node_application_get_variables():
96    client.load('get_variables')
97
98    resp = client.get(url='/?var1=val1&var2=&var3')
99    assert resp['headers']['X-Var-1'] == 'val1', 'GET variables'
100    assert resp['headers']['X-Var-2'] == '', 'GET variables 2'
101    assert resp['headers']['X-Var-3'] == '', 'GET variables 3'
102
103
104def test_node_application_post_variables():
105    client.load('post_variables')
106
107    resp = client.post(
108        headers={
109            'Content-Type': 'application/x-www-form-urlencoded',
110            'Host': 'localhost',
111            'Connection': 'close',
112        },
113        body='var1=val1&var2=&var3',
114    )
115
116    assert resp['headers']['X-Var-1'] == 'val1', 'POST variables'
117    assert resp['headers']['X-Var-2'] == '', 'POST variables 2'
118    assert resp['headers']['X-Var-3'] == '', 'POST variables 3'
119
120
121def test_node_application_404():
122    client.load('404')
123
124    resp = client.get()
125
126    assert resp['status'] == 404, '404 status'
127    assert re.search(r'<title>404 Not Found</title>', resp['body']), '404 body'
128
129
130def test_node_keepalive_body():
131    client.load('mirror')
132
133    assert client.get()['status'] == 200, 'init'
134
135    body = '0123456789' * 500
136    (resp, sock) = client.post(
137        headers={
138            'Host': 'localhost',
139            'Connection': 'keep-alive',
140        },
141        start=True,
142        body=body,
143        read_timeout=1,
144    )
145
146    assert resp['body'] == '0123456789' * 500, 'keep-alive 1'
147
148    body = '0123456789'
149    resp = client.post(sock=sock, body=body)
150
151    assert resp['body'] == body, 'keep-alive 2'
152
153
154def test_node_application_write_buffer():
155    client.load('write_buffer')
156
157    assert client.get()['body'] == 'buffer', 'write buffer'
158
159
160def test_node_application_write_array():
161    client.load('write_array')
162
163    assert client.get()['body'] == 'array', 'write array'
164
165
166def test_node_application_write_callback(temp_dir):
167    client.load('write_callback')
168
169    assert client.get()['body'] == 'helloworld', 'write callback order'
170    assert waitforfiles(f'{temp_dir}/node/callback'), 'write callback'
171
172
173def test_node_application_write_before_write_head():
174    client.load('write_before_write_head')
175
176    assert client.get()['status'] == 200, 'write before writeHead'
177
178
179def test_node_application_double_end():
180    client.load('double_end')
181
182    assert client.get()['status'] == 200, 'double end'
183    assert client.get()['status'] == 200, 'double end 2'
184
185
186def test_node_application_write_return():
187    client.load('write_return')
188
189    assert client.get()['body'] == 'bodytrue', 'write return'
190
191
192def test_node_application_remove_header():
193    client.load('remove_header')
194
195    resp = client.get(
196        headers={
197            'Host': 'localhost',
198            'X-Remove': 'X-Header',
199            'Connection': 'close',
200        }
201    )
202    assert resp['headers']['Was-Header'] == 'true', 'was header'
203    assert resp['headers']['Has-Header'] == 'false', 'has header'
204    assert not ('X-Header' in resp['headers']), 'remove header'
205
206
207def test_node_application_remove_header_nonexisting():
208    client.load('remove_header')
209
210    assert (
211        client.get(
212            headers={
213                'Host': 'localhost',
214                'X-Remove': 'blah',
215                'Connection': 'close',
216            }
217        )['headers']['Has-Header']
218        == 'true'
219    ), 'remove header nonexisting'
220
221
222def test_node_application_update_header():
223    client.load('update_header')
224
225    assert client.get()['headers']['X-Header'] == 'new', 'update header'
226
227
228def test_node_application_set_header_array():
229    client.load('set_header_array')
230
231    assert client.get()['headers']['Set-Cookie'] == [
232        'tc=one,two,three',
233        'tc=four,five,six',
234    ], 'set header array'
235
236
237@pytest.mark.skip('not yet')
238def test_node_application_status_message():
239    client.load('status_message')
240
241    assert re.search(r'200 blah', client.get(raw_resp=True)), 'status message'
242
243
244def test_node_application_get_header_type():
245    client.load('get_header_type')
246
247    assert client.get()['headers']['X-Type'] == 'number', 'get header type'
248
249
250def test_node_application_header_name_case():
251    client.load('header_name_case')
252
253    headers = client.get()['headers']
254
255    assert headers['X-HEADER'] == '3', 'header value'
256    assert 'X-Header' not in headers, 'insensitive'
257    assert 'X-header' not in headers, 'insensitive 2'
258
259
260def test_node_application_promise_handler_write_after_end():
261    client.load('promise_handler')
262
263    assert (
264        client.post(
265            headers={
266                'Host': 'localhost',
267                'Content-Type': 'text/html',
268                'X-Write-Call': '1',
269                'Connection': 'close',
270            },
271            body='callback',
272        )['status']
273        == 200
274    ), 'promise handler request write after end'
275
276
277def test_node_application_promise_end(temp_dir):
278    client.load('promise_end')
279
280    assert (
281        client.post(
282            headers={
283                'Host': 'localhost',
284                'Content-Type': 'text/html',
285                'Connection': 'close',
286            },
287            body='end',
288        )['status']
289        == 200
290    ), 'promise end request'
291    assert waitforfiles(f'{temp_dir}/node/callback'), 'promise end'
292
293
294@pytest.mark.skip('not yet')
295def test_node_application_header_name_valid():
296    client.load('header_name_valid')
297
298    assert 'status' not in client.get(), 'header name valid'
299
300
301def test_node_application_header_value_object():
302    client.load('header_value_object')
303
304    assert 'X-Header' in client.get()['headers'], 'header value object'
305
306
307def test_node_application_get_header_names():
308    client.load('get_header_names')
309
310    assert client.get()['headers']['X-Names'] == [
311        'date',
312        'x-header',
313    ], 'get header names'
314
315
316def test_node_application_flush_headers():
317    client.load('flush_headers')
318
319    assert client.get()['headers']['X-Header'] == 'blah'
320
321
322def test_node_application_has_header():
323    client.load('has_header')
324
325    assert (
326        client.get(
327            headers={
328                'Host': 'localhost',
329                'X-Header': 'length',
330                'Connection': 'close',
331            }
332        )['headers']['X-Has-Header']
333        == 'false'
334    ), 'has header length'
335
336    assert (
337        client.get(
338            headers={
339                'Host': 'localhost',
340                'X-Header': 'Date',
341                'Connection': 'close',
342            }
343        )['headers']['X-Has-Header']
344        == 'false'
345    ), 'has header date'
346
347
348def test_node_application_write_multiple():
349    client.load('write_multiple')
350
351    assert client.get()['body'] == 'writewrite2end', 'write multiple'
352