xref: /unit/test/test_configuration.py (revision 1971:3410f9d2a662)
11902Szelenkov@nginx.comimport socket
21902Szelenkov@nginx.com
31596Szelenkov@nginx.comimport pytest
41019Szelenkov@nginx.comfrom unit.control import TestControl
5484Szelenkov@nginx.com
61017Szelenkov@nginx.com
71019Szelenkov@nginx.comclass TestConfiguration(TestControl):
81467Szelenkov@nginx.com    prerequisites = {'modules': {'python': 'any'}}
9484Szelenkov@nginx.com
10*1913Szelenkov@nginx.com    def try_addr(self, addr):
11*1913Szelenkov@nginx.com        return self.conf(
12*1913Szelenkov@nginx.com            {
13*1913Szelenkov@nginx.com                "listeners": {addr: {"pass": "routes"}},
14*1913Szelenkov@nginx.com                "routes": [{"action": {"return": 200}}],
15*1913Szelenkov@nginx.com                "applications": {},
16*1913Szelenkov@nginx.com            }
17*1913Szelenkov@nginx.com        )
18*1913Szelenkov@nginx.com
19719Szelenkov@nginx.com    def test_json_empty(self):
201596Szelenkov@nginx.com        assert 'error' in self.conf(''), 'empty'
21719Szelenkov@nginx.com
22495Szelenkov@nginx.com    def test_json_leading_zero(self):
231596Szelenkov@nginx.com        assert 'error' in self.conf('00'), 'leading zero'
24484Szelenkov@nginx.com
25495Szelenkov@nginx.com    def test_json_unicode(self):
261596Szelenkov@nginx.com        assert 'success' in self.conf(
271635Szelenkov@nginx.com            u"""
28495Szelenkov@nginx.com            {
29495Szelenkov@nginx.com                "ap\u0070": {
30495Szelenkov@nginx.com                    "type": "\u0070ython",
31507Smax.romanov@nginx.com                    "processes": { "spare": 0 },
32495Szelenkov@nginx.com                    "path": "\u002Fapp",
33495Szelenkov@nginx.com                    "module": "wsgi"
34495Szelenkov@nginx.com                }
35495Szelenkov@nginx.com            }
361017Szelenkov@nginx.com            """,
371596Szelenkov@nginx.com            'applications',
381596Szelenkov@nginx.com        ), 'unicode'
39484Szelenkov@nginx.com
401596Szelenkov@nginx.com        assert self.conf_get('applications') == {
411596Szelenkov@nginx.com            "app": {
421596Szelenkov@nginx.com                "type": "python",
431596Szelenkov@nginx.com                "processes": {"spare": 0},
441596Szelenkov@nginx.com                "path": "/app",
451596Szelenkov@nginx.com                "module": "wsgi",
461596Szelenkov@nginx.com            }
471596Szelenkov@nginx.com        }, 'unicode get'
481596Szelenkov@nginx.com
491596Szelenkov@nginx.com    def test_json_unicode_2(self):
501596Szelenkov@nginx.com        assert 'success' in self.conf(
511017Szelenkov@nginx.com            {
521596Szelenkov@nginx.com                "приложение": {
531017Szelenkov@nginx.com                    "type": "python",
541017Szelenkov@nginx.com                    "processes": {"spare": 0},
551017Szelenkov@nginx.com                    "path": "/app",
561017Szelenkov@nginx.com                    "module": "wsgi",
571017Szelenkov@nginx.com                }
581017Szelenkov@nginx.com            },
591596Szelenkov@nginx.com            'applications',
601596Szelenkov@nginx.com        ), 'unicode 2'
61555Szelenkov@nginx.com
621596Szelenkov@nginx.com        assert 'приложение' in self.conf_get('applications'), 'unicode 2 get'
63555Szelenkov@nginx.com
64495Szelenkov@nginx.com    def test_json_unicode_number(self):
651635Szelenkov@nginx.com        assert 'success' in self.conf(
661635Szelenkov@nginx.com            u"""
67495Szelenkov@nginx.com            {
68495Szelenkov@nginx.com                "app": {
69495Szelenkov@nginx.com                    "type": "python",
70507Smax.romanov@nginx.com                    "processes": { "spare": \u0030 },
71495Szelenkov@nginx.com                    "path": "/app",
72495Szelenkov@nginx.com                    "module": "wsgi"
73495Szelenkov@nginx.com                }
74495Szelenkov@nginx.com            }
751017Szelenkov@nginx.com            """,
761596Szelenkov@nginx.com            'applications',
771596Szelenkov@nginx.com        ), 'unicode number'
78495Szelenkov@nginx.com
791426Szelenkov@nginx.com    def test_json_utf8_bom(self):
801596Szelenkov@nginx.com        assert 'success' in self.conf(
811596Szelenkov@nginx.com            b"""\xEF\xBB\xBF
821426Szelenkov@nginx.com            {
831426Szelenkov@nginx.com                "app": {
841426Szelenkov@nginx.com                    "type": "python",
851426Szelenkov@nginx.com                    "processes": {"spare": 0},
861426Szelenkov@nginx.com                    "path": "/app",
871426Szelenkov@nginx.com                    "module": "wsgi"
881426Szelenkov@nginx.com                }
891426Szelenkov@nginx.com            }
901426Szelenkov@nginx.com            """,
911596Szelenkov@nginx.com            'applications',
921596Szelenkov@nginx.com        ), 'UTF-8 BOM'
931426Szelenkov@nginx.com
941427Szelenkov@nginx.com    def test_json_comment_single_line(self):
951596Szelenkov@nginx.com        assert 'success' in self.conf(
961596Szelenkov@nginx.com            b"""
971427Szelenkov@nginx.com            // this is bridge
981427Szelenkov@nginx.com            {
991427Szelenkov@nginx.com                "//app": {
1001427Szelenkov@nginx.com                    "type": "python", // end line
1011427Szelenkov@nginx.com                    "processes": {"spare": 0},
1021427Szelenkov@nginx.com                    // inside of block
1031427Szelenkov@nginx.com                    "path": "/app",
1041427Szelenkov@nginx.com                    "module": "wsgi"
1051427Szelenkov@nginx.com                }
1061427Szelenkov@nginx.com                // double //
1071427Szelenkov@nginx.com            }
1081427Szelenkov@nginx.com            // end of json \xEF\t
1091427Szelenkov@nginx.com            """,
1101596Szelenkov@nginx.com            'applications',
1111596Szelenkov@nginx.com        ), 'single line comments'
1121427Szelenkov@nginx.com
1131427Szelenkov@nginx.com    def test_json_comment_multi_line(self):
1141596Szelenkov@nginx.com        assert 'success' in self.conf(
1151596Szelenkov@nginx.com            b"""
1161427Szelenkov@nginx.com            /* this is bridge */
1171427Szelenkov@nginx.com            {
1181427Szelenkov@nginx.com                "/*app": {
1191427Szelenkov@nginx.com                /**
1201427Szelenkov@nginx.com                 * multiple lines
1211427Szelenkov@nginx.com                 **/
1221427Szelenkov@nginx.com                    "type": "python",
1231427Szelenkov@nginx.com                    "processes": /* inline */ {"spare": 0},
1241427Szelenkov@nginx.com                    "path": "/app",
1251427Szelenkov@nginx.com                    "module": "wsgi"
1261427Szelenkov@nginx.com                    /*
1271427Szelenkov@nginx.com                    // end of block */
1281427Szelenkov@nginx.com                }
1291427Szelenkov@nginx.com                /* blah * / blah /* blah */
1301427Szelenkov@nginx.com            }
1311427Szelenkov@nginx.com            /* end of json \xEF\t\b */
1321427Szelenkov@nginx.com            """,
1331596Szelenkov@nginx.com            'applications',
1341596Szelenkov@nginx.com        ), 'multi line comments'
1351427Szelenkov@nginx.com
1361427Szelenkov@nginx.com    def test_json_comment_invalid(self):
1371596Szelenkov@nginx.com        assert 'error' in self.conf(b'/{}', 'applications'), 'slash'
1381596Szelenkov@nginx.com        assert 'error' in self.conf(b'//{}', 'applications'), 'comment'
1391596Szelenkov@nginx.com        assert 'error' in self.conf(b'{} /', 'applications'), 'slash end'
1401596Szelenkov@nginx.com        assert 'error' in self.conf(b'/*{}', 'applications'), 'slash star'
1411596Szelenkov@nginx.com        assert 'error' in self.conf(b'{} /*', 'applications'), 'slash star end'
1421427Szelenkov@nginx.com
143495Szelenkov@nginx.com    def test_applications_open_brace(self):
1441596Szelenkov@nginx.com        assert 'error' in self.conf('{', 'applications'), 'open brace'
145495Szelenkov@nginx.com
146495Szelenkov@nginx.com    def test_applications_string(self):
1471596Szelenkov@nginx.com        assert 'error' in self.conf('"{}"', 'applications'), 'string'
148495Szelenkov@nginx.com
1491596Szelenkov@nginx.com    @pytest.mark.skip('not yet, unsafe')
150495Szelenkov@nginx.com    def test_applications_type_only(self):
1511596Szelenkov@nginx.com        assert 'error' in self.conf(
1521596Szelenkov@nginx.com            {"app": {"type": "python"}}, 'applications'
1531596Szelenkov@nginx.com        ), 'type only'
154484Szelenkov@nginx.com
155495Szelenkov@nginx.com    def test_applications_miss_quote(self):
1561596Szelenkov@nginx.com        assert 'error' in self.conf(
1571596Szelenkov@nginx.com            """
158484Szelenkov@nginx.com            {
159484Szelenkov@nginx.com                app": {
160484Szelenkov@nginx.com                    "type": "python",
161507Smax.romanov@nginx.com                    "processes": { "spare": 0 },
162484Szelenkov@nginx.com                    "path": "/app",
163484Szelenkov@nginx.com                    "module": "wsgi"
164484Szelenkov@nginx.com                }
165484Szelenkov@nginx.com            }
1661017Szelenkov@nginx.com            """,
1671596Szelenkov@nginx.com            'applications',
1681596Szelenkov@nginx.com        ), 'miss quote'
169484Szelenkov@nginx.com
170495Szelenkov@nginx.com    def test_applications_miss_colon(self):
1711596Szelenkov@nginx.com        assert 'error' in self.conf(
1721596Szelenkov@nginx.com            """
173484Szelenkov@nginx.com            {
174484Szelenkov@nginx.com                "app" {
175484Szelenkov@nginx.com                    "type": "python",
176507Smax.romanov@nginx.com                    "processes": { "spare": 0 },
177484Szelenkov@nginx.com                    "path": "/app",
178484Szelenkov@nginx.com                    "module": "wsgi"
179484Szelenkov@nginx.com                }
180484Szelenkov@nginx.com            }
1811017Szelenkov@nginx.com            """,
1821596Szelenkov@nginx.com            'applications',
1831596Szelenkov@nginx.com        ), 'miss colon'
184484Szelenkov@nginx.com
185495Szelenkov@nginx.com    def test_applications_miss_comma(self):
1861596Szelenkov@nginx.com        assert 'error' in self.conf(
1871596Szelenkov@nginx.com            """
188484Szelenkov@nginx.com            {
189484Szelenkov@nginx.com                "app": {
190484Szelenkov@nginx.com                    "type": "python"
191507Smax.romanov@nginx.com                    "processes": { "spare": 0 },
192484Szelenkov@nginx.com                    "path": "/app",
193484Szelenkov@nginx.com                    "module": "wsgi"
194484Szelenkov@nginx.com                }
195484Szelenkov@nginx.com            }
1961017Szelenkov@nginx.com            """,
1971596Szelenkov@nginx.com            'applications',
1981596Szelenkov@nginx.com        ), 'miss comma'
199484Szelenkov@nginx.com
200495Szelenkov@nginx.com    def test_applications_skip_spaces(self):
2011596Szelenkov@nginx.com        assert 'success' in self.conf(
2021596Szelenkov@nginx.com            b'{ \n\r\t}', 'applications'
2031596Szelenkov@nginx.com        ), 'skip spaces'
204484Szelenkov@nginx.com
205495Szelenkov@nginx.com    def test_applications_relative_path(self):
2061596Szelenkov@nginx.com        assert 'success' in self.conf(
2071596Szelenkov@nginx.com            {
2081596Szelenkov@nginx.com                "app": {
2091596Szelenkov@nginx.com                    "type": "python",
2101596Szelenkov@nginx.com                    "processes": {"spare": 0},
2111596Szelenkov@nginx.com                    "path": "../app",
2121596Szelenkov@nginx.com                    "module": "wsgi",
2131596Szelenkov@nginx.com                }
2141596Szelenkov@nginx.com            },
2151596Szelenkov@nginx.com            'applications',
2161596Szelenkov@nginx.com        ), 'relative path'
2171596Szelenkov@nginx.com
2181596Szelenkov@nginx.com    @pytest.mark.skip('not yet, unsafe')
2191596Szelenkov@nginx.com    def test_listeners_empty(self):
2201596Szelenkov@nginx.com        assert 'error' in self.conf(
2211596Szelenkov@nginx.com            {"*:7080": {}}, 'listeners'
2221596Szelenkov@nginx.com        ), 'listener empty'
2231596Szelenkov@nginx.com
2241596Szelenkov@nginx.com    def test_listeners_no_app(self):
2251596Szelenkov@nginx.com        assert 'error' in self.conf(
2261596Szelenkov@nginx.com            {"*:7080": {"pass": "applications/app"}}, 'listeners'
2271596Szelenkov@nginx.com        ), 'listeners no app'
2281596Szelenkov@nginx.com
229*1913Szelenkov@nginx.com    def test_listeners_addr(self):
230*1913Szelenkov@nginx.com        assert 'success' in self.try_addr("*:7080"), 'wildcard'
231*1913Szelenkov@nginx.com        assert 'success' in self.try_addr("127.0.0.1:7081"), 'explicit'
232*1913Szelenkov@nginx.com        assert 'success' in self.try_addr("[::1]:7082"), 'explicit ipv6'
233495Szelenkov@nginx.com
234*1913Szelenkov@nginx.com    def test_listeners_addr_error(self):
235*1913Szelenkov@nginx.com        assert 'error' in self.try_addr("127.0.0.1"), 'no port'
236484Szelenkov@nginx.com
237*1913Szelenkov@nginx.com    def test_listeners_addr_error_2(self, skip_alert):
238*1913Szelenkov@nginx.com        skip_alert(r'bind.*failed', r'failed to apply new conf')
239*1913Szelenkov@nginx.com
240*1913Szelenkov@nginx.com        assert 'error' in self.try_addr(
241*1913Szelenkov@nginx.com            "[f607:7403:1e4b:6c66:33b2:843f:2517:da27]:7080"
242*1913Szelenkov@nginx.com        )
243495Szelenkov@nginx.com
2441871Szelenkov@nginx.com    def test_listeners_port_release(self):
2451871Szelenkov@nginx.com        for i in range(10):
2461871Szelenkov@nginx.com            fail = False
2471871Szelenkov@nginx.com            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
2481871Szelenkov@nginx.com                s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2491871Szelenkov@nginx.com
2501871Szelenkov@nginx.com                self.conf(
2511871Szelenkov@nginx.com                    {
2521871Szelenkov@nginx.com                        "listeners": {"127.0.0.1:7080": {"pass": "routes"}},
2531871Szelenkov@nginx.com                        "routes": [],
2541871Szelenkov@nginx.com                    }
2551871Szelenkov@nginx.com                )
2561871Szelenkov@nginx.com
2571871Szelenkov@nginx.com                resp = self.conf({"listeners": {}, "applications": {}})
2581871Szelenkov@nginx.com
2591871Szelenkov@nginx.com                try:
2601871Szelenkov@nginx.com                    s.bind(('127.0.0.1', 7080))
2611871Szelenkov@nginx.com                    s.listen()
2621871Szelenkov@nginx.com
2631871Szelenkov@nginx.com                except OSError:
2641871Szelenkov@nginx.com                    fail = True
2651871Szelenkov@nginx.com
2661871Szelenkov@nginx.com                if fail:
2671871Szelenkov@nginx.com                    pytest.fail('cannot bind or listen to the address')
2681871Szelenkov@nginx.com
2691871Szelenkov@nginx.com                assert 'success' in resp, 'port release'
2701871Szelenkov@nginx.com
271917Szelenkov@nginx.com    def test_json_application_name_large(self):
272917Szelenkov@nginx.com        name = "X" * 1024 * 1024
273917Szelenkov@nginx.com
2741596Szelenkov@nginx.com        assert 'success' in self.conf(
2751596Szelenkov@nginx.com            {
2761596Szelenkov@nginx.com                "listeners": {"*:7080": {"pass": "applications/" + name}},
2771596Szelenkov@nginx.com                "applications": {
2781596Szelenkov@nginx.com                    name: {
2791596Szelenkov@nginx.com                        "type": "python",
2801596Szelenkov@nginx.com                        "processes": {"spare": 0},
2811596Szelenkov@nginx.com                        "path": "/app",
2821596Szelenkov@nginx.com                        "module": "wsgi",
2831596Szelenkov@nginx.com                    }
2841596Szelenkov@nginx.com                },
2851596Szelenkov@nginx.com            }
2861017Szelenkov@nginx.com        )
287917Szelenkov@nginx.com
2881596Szelenkov@nginx.com    @pytest.mark.skip('not yet')
289917Szelenkov@nginx.com    def test_json_application_many(self):
290946Szelenkov@nginx.com        apps = 999
291917Szelenkov@nginx.com
292917Szelenkov@nginx.com        conf = {
2931017Szelenkov@nginx.com            "applications": {
2941017Szelenkov@nginx.com                "app-"
2951017Szelenkov@nginx.com                + str(a): {
296917Szelenkov@nginx.com                    "type": "python",
2971017Szelenkov@nginx.com                    "processes": {"spare": 0},
298917Szelenkov@nginx.com                    "path": "/app",
2991017Szelenkov@nginx.com                    "module": "wsgi",
3001017Szelenkov@nginx.com                }
3011017Szelenkov@nginx.com                for a in range(apps)
302917Szelenkov@nginx.com            },
303917Szelenkov@nginx.com            "listeners": {
3041041Svbart@nginx.com                "*:" + str(7000 + a): {"pass": "applications/app-" + str(a)}
3051017Szelenkov@nginx.com                for a in range(apps)
3061017Szelenkov@nginx.com            },
307917Szelenkov@nginx.com        }
308917Szelenkov@nginx.com
3091596Szelenkov@nginx.com        assert 'success' in self.conf(conf)
310917Szelenkov@nginx.com
3111006Smax.romanov@nginx.com    def test_json_application_many2(self):
3121006Smax.romanov@nginx.com        conf = {
3131017Szelenkov@nginx.com            "applications": {
3141017Szelenkov@nginx.com                "app-"
3151017Szelenkov@nginx.com                + str(a): {
3161006Smax.romanov@nginx.com                    "type": "python",
3171017Szelenkov@nginx.com                    "processes": {"spare": 0},
3181006Smax.romanov@nginx.com                    "path": "/app",
3191017Szelenkov@nginx.com                    "module": "wsgi",
3201017Szelenkov@nginx.com                }
3211551Smax.romanov@nginx.com                # Larger number of applications can cause test fail with default
3221551Smax.romanov@nginx.com                # open files limit due to the lack of file descriptors.
3231551Smax.romanov@nginx.com                for a in range(100)
3241006Smax.romanov@nginx.com            },
3251232Szelenkov@nginx.com            "listeners": {"*:7080": {"pass": "applications/app-1"}},
3261006Smax.romanov@nginx.com        }
3271006Smax.romanov@nginx.com
3281596Szelenkov@nginx.com        assert 'success' in self.conf(conf)
3291006Smax.romanov@nginx.com
3301736Szelenkov@nginx.com    def test_unprivileged_user_error(self, is_su, skip_alert):
3311596Szelenkov@nginx.com        skip_alert(r'cannot set user "root"', r'failed to apply new conf')
3321596Szelenkov@nginx.com        if is_su:
3331596Szelenkov@nginx.com            pytest.skip('unprivileged tests')
3341569St.nateldemoura@f5.com
3351596Szelenkov@nginx.com        assert 'error' in self.conf(
3361596Szelenkov@nginx.com            {
3371596Szelenkov@nginx.com                "app": {
3381596Szelenkov@nginx.com                    "type": "external",
3391596Szelenkov@nginx.com                    "processes": 1,
3401596Szelenkov@nginx.com                    "executable": "/app",
3411596Szelenkov@nginx.com                    "user": "root",
3421596Szelenkov@nginx.com                }
3431596Szelenkov@nginx.com            },
3441596Szelenkov@nginx.com            'applications',
3451596Szelenkov@nginx.com        ), 'setting user'
346