test_configuration.py (1569:250605931a20) test_configuration.py (1596:b7e2d4d92624)
1import unittest
1import pytest
2
3from unit.control import TestControl
2
3from unit.control import TestControl
4from conftest import skip_alert
4
5
6class TestConfiguration(TestControl):
7 prerequisites = {'modules': {'python': 'any'}}
8
9 def test_json_empty(self):
5
6
7class TestConfiguration(TestControl):
8 prerequisites = {'modules': {'python': 'any'}}
9
10 def test_json_empty(self):
10 self.assertIn('error', self.conf(''), 'empty')
11 assert 'error' in self.conf(''), 'empty'
11
12 def test_json_leading_zero(self):
12
13 def test_json_leading_zero(self):
13 self.assertIn('error', self.conf('00'), 'leading zero')
14 assert 'error' in self.conf('00'), 'leading zero'
14
15 def test_json_unicode(self):
15
16 def test_json_unicode(self):
16 self.assertIn(
17 'success',
18 self.conf(
19 b"""
17 assert 'success' in self.conf(
18 b"""
20 {
21 "ap\u0070": {
22 "type": "\u0070ython",
23 "processes": { "spare": 0 },
24 "path": "\u002Fapp",
25 "module": "wsgi"
26 }
27 }
28 """,
19 {
20 "ap\u0070": {
21 "type": "\u0070ython",
22 "processes": { "spare": 0 },
23 "path": "\u002Fapp",
24 "module": "wsgi"
25 }
26 }
27 """,
29 'applications',
30 ),
31 'unicode',
32 )
28 'applications',
29 ), 'unicode'
33
30
34 self.assertDictEqual(
35 self.conf_get('applications'),
31 assert self.conf_get('applications') == {
32 "app": {
33 "type": "python",
34 "processes": {"spare": 0},
35 "path": "/app",
36 "module": "wsgi",
37 }
38 }, 'unicode get'
39
40 def test_json_unicode_2(self):
41 assert 'success' in self.conf(
36 {
42 {
37 "app": {
43 "приложение": {
38 "type": "python",
39 "processes": {"spare": 0},
40 "path": "/app",
41 "module": "wsgi",
42 }
43 },
44 "type": "python",
45 "processes": {"spare": 0},
46 "path": "/app",
47 "module": "wsgi",
48 }
49 },
44 'unicode get',
45 )
50 'applications',
51 ), 'unicode 2'
46
52
47 def test_json_unicode_2(self):
48 self.assertIn(
49 'success',
50 self.conf(
51 {
52 "приложение": {
53 "type": "python",
54 "processes": {"spare": 0},
55 "path": "/app",
56 "module": "wsgi",
57 }
58 },
59 'applications',
60 ),
61 'unicode 2',
62 )
53 assert 'приложение' in self.conf_get('applications'), 'unicode 2 get'
63
54
64 self.assertIn(
65 'приложение', self.conf_get('applications'), 'unicode 2 get'
66 )
67
68 def test_json_unicode_number(self):
55 def test_json_unicode_number(self):
69 self.assertIn(
70 'error',
71 self.conf(
72 b"""
56 assert 'error' in self.conf(
57 b"""
73 {
74 "app": {
75 "type": "python",
76 "processes": { "spare": \u0030 },
77 "path": "/app",
78 "module": "wsgi"
79 }
80 }
81 """,
58 {
59 "app": {
60 "type": "python",
61 "processes": { "spare": \u0030 },
62 "path": "/app",
63 "module": "wsgi"
64 }
65 }
66 """,
82 'applications',
83 ),
84 'unicode number',
85 )
67 'applications',
68 ), 'unicode number'
86
87 def test_json_utf8_bom(self):
69
70 def test_json_utf8_bom(self):
88 self.assertIn(
89 'success',
90 self.conf(
91 b"""\xEF\xBB\xBF
71 assert 'success' in self.conf(
72 b"""\xEF\xBB\xBF
92 {
93 "app": {
94 "type": "python",
95 "processes": {"spare": 0},
96 "path": "/app",
97 "module": "wsgi"
98 }
99 }
100 """,
73 {
74 "app": {
75 "type": "python",
76 "processes": {"spare": 0},
77 "path": "/app",
78 "module": "wsgi"
79 }
80 }
81 """,
101 'applications',
102 ),
103 'UTF-8 BOM',
104 )
82 'applications',
83 ), 'UTF-8 BOM'
105
106 def test_json_comment_single_line(self):
84
85 def test_json_comment_single_line(self):
107 self.assertIn(
108 'success',
109 self.conf(
110 b"""
86 assert 'success' in self.conf(
87 b"""
111 // this is bridge
112 {
113 "//app": {
114 "type": "python", // end line
115 "processes": {"spare": 0},
116 // inside of block
117 "path": "/app",
118 "module": "wsgi"
119 }
120 // double //
121 }
122 // end of json \xEF\t
123 """,
88 // this is bridge
89 {
90 "//app": {
91 "type": "python", // end line
92 "processes": {"spare": 0},
93 // inside of block
94 "path": "/app",
95 "module": "wsgi"
96 }
97 // double //
98 }
99 // end of json \xEF\t
100 """,
124 'applications',
125 ),
126 'single line comments',
127 )
101 'applications',
102 ), 'single line comments'
128
129 def test_json_comment_multi_line(self):
103
104 def test_json_comment_multi_line(self):
130 self.assertIn(
131 'success',
132 self.conf(
133 b"""
105 assert 'success' in self.conf(
106 b"""
134 /* this is bridge */
135 {
136 "/*app": {
137 /**
138 * multiple lines
139 **/
140 "type": "python",
141 "processes": /* inline */ {"spare": 0},
142 "path": "/app",
143 "module": "wsgi"
144 /*
145 // end of block */
146 }
147 /* blah * / blah /* blah */
148 }
149 /* end of json \xEF\t\b */
150 """,
107 /* this is bridge */
108 {
109 "/*app": {
110 /**
111 * multiple lines
112 **/
113 "type": "python",
114 "processes": /* inline */ {"spare": 0},
115 "path": "/app",
116 "module": "wsgi"
117 /*
118 // end of block */
119 }
120 /* blah * / blah /* blah */
121 }
122 /* end of json \xEF\t\b */
123 """,
151 'applications',
152 ),
153 'multi line comments',
154 )
124 'applications',
125 ), 'multi line comments'
155
156 def test_json_comment_invalid(self):
126
127 def test_json_comment_invalid(self):
157 self.assertIn('error', self.conf(b'/{}', 'applications'), 'slash')
158 self.assertIn('error', self.conf(b'//{}', 'applications'), 'comment')
159 self.assertIn('error', self.conf(b'{} /', 'applications'), 'slash end')
160 self.assertIn(
161 'error', self.conf(b'/*{}', 'applications'), 'slash star'
162 )
163 self.assertIn(
164 'error', self.conf(b'{} /*', 'applications'), 'slash star end'
165 )
128 assert 'error' in self.conf(b'/{}', 'applications'), 'slash'
129 assert 'error' in self.conf(b'//{}', 'applications'), 'comment'
130 assert 'error' in self.conf(b'{} /', 'applications'), 'slash end'
131 assert 'error' in self.conf(b'/*{}', 'applications'), 'slash star'
132 assert 'error' in self.conf(b'{} /*', 'applications'), 'slash star end'
166
167 def test_applications_open_brace(self):
133
134 def test_applications_open_brace(self):
168 self.assertIn('error', self.conf('{', 'applications'), 'open brace')
135 assert 'error' in self.conf('{', 'applications'), 'open brace'
169
170 def test_applications_string(self):
136
137 def test_applications_string(self):
171 self.assertIn('error', self.conf('"{}"', 'applications'), 'string')
138 assert 'error' in self.conf('"{}"', 'applications'), 'string'
172
139
173 @unittest.skip('not yet, unsafe')
140 @pytest.mark.skip('not yet, unsafe')
174 def test_applications_type_only(self):
141 def test_applications_type_only(self):
175 self.assertIn(
176 'error',
177 self.conf({"app": {"type": "python"}}, 'applications'),
178 'type only',
179 )
142 assert 'error' in self.conf(
143 {"app": {"type": "python"}}, 'applications'
144 ), 'type only'
180
181 def test_applications_miss_quote(self):
145
146 def test_applications_miss_quote(self):
182 self.assertIn(
183 'error',
184 self.conf(
185 """
147 assert 'error' in self.conf(
148 """
186 {
187 app": {
188 "type": "python",
189 "processes": { "spare": 0 },
190 "path": "/app",
191 "module": "wsgi"
192 }
193 }
194 """,
149 {
150 app": {
151 "type": "python",
152 "processes": { "spare": 0 },
153 "path": "/app",
154 "module": "wsgi"
155 }
156 }
157 """,
195 'applications',
196 ),
197 'miss quote',
198 )
158 'applications',
159 ), 'miss quote'
199
200 def test_applications_miss_colon(self):
160
161 def test_applications_miss_colon(self):
201 self.assertIn(
202 'error',
203 self.conf(
204 """
162 assert 'error' in self.conf(
163 """
205 {
206 "app" {
207 "type": "python",
208 "processes": { "spare": 0 },
209 "path": "/app",
210 "module": "wsgi"
211 }
212 }
213 """,
164 {
165 "app" {
166 "type": "python",
167 "processes": { "spare": 0 },
168 "path": "/app",
169 "module": "wsgi"
170 }
171 }
172 """,
214 'applications',
215 ),
216 'miss colon',
217 )
173 'applications',
174 ), 'miss colon'
218
219 def test_applications_miss_comma(self):
175
176 def test_applications_miss_comma(self):
220 self.assertIn(
221 'error',
222 self.conf(
223 """
177 assert 'error' in self.conf(
178 """
224 {
225 "app": {
226 "type": "python"
227 "processes": { "spare": 0 },
228 "path": "/app",
229 "module": "wsgi"
230 }
231 }
232 """,
179 {
180 "app": {
181 "type": "python"
182 "processes": { "spare": 0 },
183 "path": "/app",
184 "module": "wsgi"
185 }
186 }
187 """,
233 'applications',
234 ),
235 'miss comma',
236 )
188 'applications',
189 ), 'miss comma'
237
238 def test_applications_skip_spaces(self):
190
191 def test_applications_skip_spaces(self):
239 self.assertIn(
240 'success', self.conf(b'{ \n\r\t}', 'applications'), 'skip spaces'
241 )
192 assert 'success' in self.conf(
193 b'{ \n\r\t}', 'applications'
194 ), 'skip spaces'
242
243 def test_applications_relative_path(self):
195
196 def test_applications_relative_path(self):
244 self.assertIn(
245 'success',
246 self.conf(
247 {
197 assert 'success' in self.conf(
198 {
199 "app": {
200 "type": "python",
201 "processes": {"spare": 0},
202 "path": "../app",
203 "module": "wsgi",
204 }
205 },
206 'applications',
207 ), 'relative path'
208
209 @pytest.mark.skip('not yet, unsafe')
210 def test_listeners_empty(self):
211 assert 'error' in self.conf(
212 {"*:7080": {}}, 'listeners'
213 ), 'listener empty'
214
215 def test_listeners_no_app(self):
216 assert 'error' in self.conf(
217 {"*:7080": {"pass": "applications/app"}}, 'listeners'
218 ), 'listeners no app'
219
220 def test_listeners_wildcard(self):
221 assert 'success' in self.conf(
222 {
223 "listeners": {"*:7080": {"pass": "applications/app"}},
224 "applications": {
248 "app": {
249 "type": "python",
250 "processes": {"spare": 0},
225 "app": {
226 "type": "python",
227 "processes": {"spare": 0},
251 "path": "../app",
228 "path": "/app",
252 "module": "wsgi",
253 }
254 },
229 "module": "wsgi",
230 }
231 },
255 'applications',
256 ),
257 'relative path',
258 )
232 }
233 ), 'listeners wildcard'
259
234
260 @unittest.skip('not yet, unsafe')
261 def test_listeners_empty(self):
262 self.assertIn(
263 'error', self.conf({"*:7080": {}}, 'listeners'), 'listener empty'
264 )
265
266 def test_listeners_no_app(self):
267 self.assertIn(
268 'error',
269 self.conf({"*:7080": {"pass": "applications/app"}}, 'listeners'),
270 'listeners no app',
271 )
272
273 def test_listeners_wildcard(self):
274 self.assertIn(
275 'success',
276 self.conf(
277 {
278 "listeners": {"*:7080": {"pass": "applications/app"}},
279 "applications": {
280 "app": {
281 "type": "python",
282 "processes": {"spare": 0},
283 "path": "/app",
284 "module": "wsgi",
285 }
286 },
287 }
288 ),
289 'listeners wildcard',
290 )
291
292 def test_listeners_explicit(self):
235 def test_listeners_explicit(self):
293 self.assertIn(
294 'success',
295 self.conf(
296 {
297 "listeners": {"127.0.0.1:7080": {"pass": "applications/app"}},
298 "applications": {
299 "app": {
300 "type": "python",
301 "processes": {"spare": 0},
302 "path": "/app",
303 "module": "wsgi",
304 }
305 },
306 }
307 ),
308 'explicit',
309 )
236 assert 'success' in self.conf(
237 {
238 "listeners": {"127.0.0.1:7080": {"pass": "applications/app"}},
239 "applications": {
240 "app": {
241 "type": "python",
242 "processes": {"spare": 0},
243 "path": "/app",
244 "module": "wsgi",
245 }
246 },
247 }
248 ), 'explicit'
310
311 def test_listeners_explicit_ipv6(self):
249
250 def test_listeners_explicit_ipv6(self):
312 self.assertIn(
313 'success',
314 self.conf(
315 {
316 "listeners": {"[::1]:7080": {"pass": "applications/app"}},
317 "applications": {
318 "app": {
319 "type": "python",
320 "processes": {"spare": 0},
321 "path": "/app",
322 "module": "wsgi",
323 }
324 },
325 }
326 ),
327 'explicit ipv6',
328 )
251 assert 'success' in self.conf(
252 {
253 "listeners": {"[::1]:7080": {"pass": "applications/app"}},
254 "applications": {
255 "app": {
256 "type": "python",
257 "processes": {"spare": 0},
258 "path": "/app",
259 "module": "wsgi",
260 }
261 },
262 }
263 ), 'explicit ipv6'
329
264
330 @unittest.skip('not yet, unsafe')
265 @pytest.mark.skip('not yet, unsafe')
331 def test_listeners_no_port(self):
266 def test_listeners_no_port(self):
332 self.assertIn(
333 'error',
334 self.conf(
335 {
336 "listeners": {"127.0.0.1": {"pass": "applications/app"}},
337 "applications": {
338 "app": {
339 "type": "python",
340 "processes": {"spare": 0},
341 "path": "/app",
342 "module": "wsgi",
343 }
344 },
345 }
346 ),
347 'no port',
348 )
267 assert 'error' in self.conf(
268 {
269 "listeners": {"127.0.0.1": {"pass": "applications/app"}},
270 "applications": {
271 "app": {
272 "type": "python",
273 "processes": {"spare": 0},
274 "path": "/app",
275 "module": "wsgi",
276 }
277 },
278 }
279 ), 'no port'
349
350 def test_json_application_name_large(self):
351 name = "X" * 1024 * 1024
352
280
281 def test_json_application_name_large(self):
282 name = "X" * 1024 * 1024
283
353 self.assertIn(
354 'success',
355 self.conf(
356 {
357 "listeners": {"*:7080": {"pass": "applications/" + name}},
358 "applications": {
359 name: {
360 "type": "python",
361 "processes": {"spare": 0},
362 "path": "/app",
363 "module": "wsgi",
364 }
365 },
366 }
367 ),
284 assert 'success' in self.conf(
285 {
286 "listeners": {"*:7080": {"pass": "applications/" + name}},
287 "applications": {
288 name: {
289 "type": "python",
290 "processes": {"spare": 0},
291 "path": "/app",
292 "module": "wsgi",
293 }
294 },
295 }
368 )
369
296 )
297
370 @unittest.skip('not yet')
298 @pytest.mark.skip('not yet')
371 def test_json_application_many(self):
372 apps = 999
373
374 conf = {
375 "applications": {
376 "app-"
377 + str(a): {
378 "type": "python",

--- 4 unchanged lines hidden (view full) ---

383 for a in range(apps)
384 },
385 "listeners": {
386 "*:" + str(7000 + a): {"pass": "applications/app-" + str(a)}
387 for a in range(apps)
388 },
389 }
390
299 def test_json_application_many(self):
300 apps = 999
301
302 conf = {
303 "applications": {
304 "app-"
305 + str(a): {
306 "type": "python",

--- 4 unchanged lines hidden (view full) ---

311 for a in range(apps)
312 },
313 "listeners": {
314 "*:" + str(7000 + a): {"pass": "applications/app-" + str(a)}
315 for a in range(apps)
316 },
317 }
318
391 self.assertIn('success', self.conf(conf))
319 assert 'success' in self.conf(conf)
392
393 def test_json_application_many2(self):
394 conf = {
395 "applications": {
396 "app-"
397 + str(a): {
398 "type": "python",
399 "processes": {"spare": 0},
400 "path": "/app",
401 "module": "wsgi",
402 }
403 # Larger number of applications can cause test fail with default
404 # open files limit due to the lack of file descriptors.
405 for a in range(100)
406 },
407 "listeners": {"*:7080": {"pass": "applications/app-1"}},
408 }
409
320
321 def test_json_application_many2(self):
322 conf = {
323 "applications": {
324 "app-"
325 + str(a): {
326 "type": "python",
327 "processes": {"spare": 0},
328 "path": "/app",
329 "module": "wsgi",
330 }
331 # Larger number of applications can cause test fail with default
332 # open files limit due to the lack of file descriptors.
333 for a in range(100)
334 },
335 "listeners": {"*:7080": {"pass": "applications/app-1"}},
336 }
337
410 self.assertIn('success', self.conf(conf))
338 assert 'success' in self.conf(conf)
411
339
412 def test_unprivileged_user_error(self):
413 self.skip_alerts.extend(
414 [
415 r'cannot set user "root"',
416 r'failed to apply new conf',
417 ]
418 )
419 if self.is_su:
420 print('unprivileged tests, skip this')
421 raise unittest.SkipTest()
340 def test_unprivileged_user_error(self, is_su):
341 skip_alert(r'cannot set user "root"', r'failed to apply new conf')
342 if is_su:
343 pytest.skip('unprivileged tests')
422
344
423 self.assertIn(
424 'error',
425 self.conf(
426 {
427 "app": {
428 "type": "external",
429 "processes": 1,
430 "executable": "/app",
431 "user": "root",
432 }
433 },
434 'applications',
435 ),
436 'setting user',
437 )
438
439
440if __name__ == '__main__':
441 TestConfiguration.main()
345 assert 'error' in self.conf(
346 {
347 "app": {
348 "type": "external",
349 "processes": 1,
350 "executable": "/app",
351 "user": "root",
352 }
353 },
354 'applications',
355 ), 'setting user'