xref: /unit/test/test_configuration.py (revision 1551:2fcbe6700258)
1import unittest
2
3from unit.control import TestControl
4
5
6class TestConfiguration(TestControl):
7    prerequisites = {'modules': {'python': 'any'}}
8
9    def test_json_empty(self):
10        self.assertIn('error', self.conf(''), 'empty')
11
12    def test_json_leading_zero(self):
13        self.assertIn('error', self.conf('00'), 'leading zero')
14
15    def test_json_unicode(self):
16        self.assertIn(
17            'success',
18            self.conf(
19                b"""
20            {
21                "ap\u0070": {
22                    "type": "\u0070ython",
23                    "processes": { "spare": 0 },
24                    "path": "\u002Fapp",
25                    "module": "wsgi"
26                }
27            }
28            """,
29                'applications',
30            ),
31            'unicode',
32        )
33
34        self.assertDictEqual(
35            self.conf_get('applications'),
36            {
37                "app": {
38                    "type": "python",
39                    "processes": {"spare": 0},
40                    "path": "/app",
41                    "module": "wsgi",
42                }
43            },
44            'unicode get',
45        )
46
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        )
63
64        self.assertIn(
65            'приложение', self.conf_get('applications'), 'unicode 2 get'
66        )
67
68    def test_json_unicode_number(self):
69        self.assertIn(
70            'error',
71            self.conf(
72                b"""
73            {
74                "app": {
75                    "type": "python",
76                    "processes": { "spare": \u0030 },
77                    "path": "/app",
78                    "module": "wsgi"
79                }
80            }
81            """,
82                'applications',
83            ),
84            'unicode number',
85        )
86
87    def test_json_utf8_bom(self):
88        self.assertIn(
89            'success',
90            self.conf(
91                b"""\xEF\xBB\xBF
92            {
93                "app": {
94                    "type": "python",
95                    "processes": {"spare": 0},
96                    "path": "/app",
97                    "module": "wsgi"
98                }
99            }
100            """,
101                'applications',
102            ),
103            'UTF-8 BOM',
104        )
105
106    def test_json_comment_single_line(self):
107        self.assertIn(
108            'success',
109            self.conf(
110                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            """,
124                'applications',
125            ),
126            'single line comments',
127        )
128
129    def test_json_comment_multi_line(self):
130        self.assertIn(
131            'success',
132            self.conf(
133                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            """,
151                'applications',
152            ),
153            'multi line comments',
154        )
155
156    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        )
166
167    def test_applications_open_brace(self):
168        self.assertIn('error', self.conf('{', 'applications'), 'open brace')
169
170    def test_applications_string(self):
171        self.assertIn('error', self.conf('"{}"', 'applications'), 'string')
172
173    @unittest.skip('not yet, unsafe')
174    def test_applications_type_only(self):
175        self.assertIn(
176            'error',
177            self.conf({"app": {"type": "python"}}, 'applications'),
178            'type only',
179        )
180
181    def test_applications_miss_quote(self):
182        self.assertIn(
183            'error',
184            self.conf(
185                """
186            {
187                app": {
188                    "type": "python",
189                    "processes": { "spare": 0 },
190                    "path": "/app",
191                    "module": "wsgi"
192                }
193            }
194            """,
195                'applications',
196            ),
197            'miss quote',
198        )
199
200    def test_applications_miss_colon(self):
201        self.assertIn(
202            'error',
203            self.conf(
204                """
205            {
206                "app" {
207                    "type": "python",
208                    "processes": { "spare": 0 },
209                    "path": "/app",
210                    "module": "wsgi"
211                }
212            }
213            """,
214                'applications',
215            ),
216            'miss colon',
217        )
218
219    def test_applications_miss_comma(self):
220        self.assertIn(
221            'error',
222            self.conf(
223                """
224            {
225                "app": {
226                    "type": "python"
227                    "processes": { "spare": 0 },
228                    "path": "/app",
229                    "module": "wsgi"
230                }
231            }
232            """,
233                'applications',
234            ),
235            'miss comma',
236        )
237
238    def test_applications_skip_spaces(self):
239        self.assertIn(
240            'success', self.conf(b'{ \n\r\t}', 'applications'), 'skip spaces'
241        )
242
243    def test_applications_relative_path(self):
244        self.assertIn(
245            'success',
246            self.conf(
247                {
248                    "app": {
249                        "type": "python",
250                        "processes": {"spare": 0},
251                        "path": "../app",
252                        "module": "wsgi",
253                    }
254                },
255                'applications',
256            ),
257            'relative path',
258        )
259
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):
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        )
310
311    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        )
329
330    @unittest.skip('not yet, unsafe')
331    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        )
349
350    def test_json_application_name_large(self):
351        name = "X" * 1024 * 1024
352
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            ),
368        )
369
370    @unittest.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",
379                    "processes": {"spare": 0},
380                    "path": "/app",
381                    "module": "wsgi",
382                }
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
391        self.assertIn('success', 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
410        self.assertIn('success', self.conf(conf))
411
412
413if __name__ == '__main__':
414    TestConfiguration.main()
415