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