xref: /unit/test/test_upstreams_rr.py (revision 1730)
11396Szelenkov@nginx.comimport os
21396Szelenkov@nginx.comimport re
31477Szelenkov@nginx.com
41396Szelenkov@nginx.comfrom unit.applications.lang.python import TestApplicationPython
5*1730Szelenkov@nginx.comfrom unit.option import option
61396Szelenkov@nginx.com
71396Szelenkov@nginx.com
81396Szelenkov@nginx.comclass TestUpstreamsRR(TestApplicationPython):
91467Szelenkov@nginx.com    prerequisites = {'modules': {'python': 'any'}}
101396Szelenkov@nginx.com
111596Szelenkov@nginx.com    def setup_method(self):
121596Szelenkov@nginx.com        assert 'success' in self.conf(
131596Szelenkov@nginx.com            {
141596Szelenkov@nginx.com                "listeners": {
151596Szelenkov@nginx.com                    "*:7080": {"pass": "upstreams/one"},
161596Szelenkov@nginx.com                    "*:7090": {"pass": "upstreams/two"},
171596Szelenkov@nginx.com                    "*:7081": {"pass": "routes/one"},
181596Szelenkov@nginx.com                    "*:7082": {"pass": "routes/two"},
191596Szelenkov@nginx.com                    "*:7083": {"pass": "routes/three"},
201596Szelenkov@nginx.com                },
211596Szelenkov@nginx.com                "upstreams": {
221596Szelenkov@nginx.com                    "one": {
231596Szelenkov@nginx.com                        "servers": {
241596Szelenkov@nginx.com                            "127.0.0.1:7081": {},
251596Szelenkov@nginx.com                            "127.0.0.1:7082": {},
261396Szelenkov@nginx.com                        },
271396Szelenkov@nginx.com                    },
281596Szelenkov@nginx.com                    "two": {
291596Szelenkov@nginx.com                        "servers": {
301596Szelenkov@nginx.com                            "127.0.0.1:7081": {},
311596Szelenkov@nginx.com                            "127.0.0.1:7082": {},
321596Szelenkov@nginx.com                        },
331396Szelenkov@nginx.com                    },
341396Szelenkov@nginx.com                },
351596Szelenkov@nginx.com                "routes": {
361596Szelenkov@nginx.com                    "one": [{"action": {"return": 200}}],
371596Szelenkov@nginx.com                    "two": [{"action": {"return": 201}}],
381596Szelenkov@nginx.com                    "three": [{"action": {"return": 202}}],
391596Szelenkov@nginx.com                },
401596Szelenkov@nginx.com                "applications": {},
411596Szelenkov@nginx.com            },
421596Szelenkov@nginx.com        ), 'upstreams initial configuration'
431396Szelenkov@nginx.com
441396Szelenkov@nginx.com        self.cpu_count = os.cpu_count()
451396Szelenkov@nginx.com
461396Szelenkov@nginx.com    def get_resps(self, req=100, port=7080):
471396Szelenkov@nginx.com        resps = [0]
481445Szelenkov@nginx.com
491396Szelenkov@nginx.com        for _ in range(req):
501445Szelenkov@nginx.com            status = self.get(port=port)['status']
511445Szelenkov@nginx.com            if 200 > status or status > 209:
521445Szelenkov@nginx.com                continue
531396Szelenkov@nginx.com
541445Szelenkov@nginx.com            ups = status % 10
551445Szelenkov@nginx.com            if ups > len(resps) - 1:
561445Szelenkov@nginx.com                resps.extend([0] * (ups - len(resps) + 1))
571396Szelenkov@nginx.com
581445Szelenkov@nginx.com            resps[ups] += 1
591396Szelenkov@nginx.com
601396Szelenkov@nginx.com        return resps
611396Szelenkov@nginx.com
621396Szelenkov@nginx.com    def get_resps_sc(self, req=100, port=7080):
631396Szelenkov@nginx.com        to_send = b"""GET / HTTP/1.1
641396Szelenkov@nginx.comHost: localhost
651396Szelenkov@nginx.com
661396Szelenkov@nginx.com""" * (
671396Szelenkov@nginx.com            req - 1
681396Szelenkov@nginx.com        )
691396Szelenkov@nginx.com
701396Szelenkov@nginx.com        to_send += b"""GET / HTTP/1.1
711396Szelenkov@nginx.comHost: localhost
721396Szelenkov@nginx.comConnection: close
731396Szelenkov@nginx.com
741396Szelenkov@nginx.com"""
751396Szelenkov@nginx.com
761396Szelenkov@nginx.com        resp = self.http(to_send, raw_resp=True, raw=True, port=port)
771445Szelenkov@nginx.com        status = re.findall(r'HTTP\/\d\.\d\s(\d\d\d)', resp)
781445Szelenkov@nginx.com        status = list(filter(lambda x: x[:2] == '20', status))
791445Szelenkov@nginx.com        ups = list(map(lambda x: int(x[-1]), status))
801396Szelenkov@nginx.com
811445Szelenkov@nginx.com        resps = [0] * (max(ups) + 1)
821396Szelenkov@nginx.com        for i in range(len(ups)):
831445Szelenkov@nginx.com            resps[ups[i]] += 1
841396Szelenkov@nginx.com
851396Szelenkov@nginx.com        return resps
861396Szelenkov@nginx.com
871396Szelenkov@nginx.com    def test_upstreams_rr_no_weight(self):
881396Szelenkov@nginx.com        resps = self.get_resps()
891596Szelenkov@nginx.com        assert sum(resps) == 100, 'no weight sum'
901596Szelenkov@nginx.com        assert abs(resps[0] - resps[1]) <= self.cpu_count, 'no weight'
911396Szelenkov@nginx.com
921596Szelenkov@nginx.com        assert 'success' in self.conf_delete(
931596Szelenkov@nginx.com            'upstreams/one/servers/127.0.0.1:7081'
941596Szelenkov@nginx.com        ), 'no weight server remove'
951396Szelenkov@nginx.com
961396Szelenkov@nginx.com        resps = self.get_resps(req=50)
971596Szelenkov@nginx.com        assert resps[1] == 50, 'no weight 2'
981396Szelenkov@nginx.com
991596Szelenkov@nginx.com        assert 'success' in self.conf(
1001596Szelenkov@nginx.com            {}, 'upstreams/one/servers/127.0.0.1:7081'
1011596Szelenkov@nginx.com        ), 'no weight server revert'
1021396Szelenkov@nginx.com
1031396Szelenkov@nginx.com        resps = self.get_resps()
1041596Szelenkov@nginx.com        assert sum(resps) == 100, 'no weight 3 sum'
1051596Szelenkov@nginx.com        assert abs(resps[0] - resps[1]) <= self.cpu_count, 'no weight 3'
1061396Szelenkov@nginx.com
1071596Szelenkov@nginx.com        assert 'success' in self.conf(
1081596Szelenkov@nginx.com            {}, 'upstreams/one/servers/127.0.0.1:7083'
1091596Szelenkov@nginx.com        ), 'no weight server new'
1101396Szelenkov@nginx.com
1111396Szelenkov@nginx.com        resps = self.get_resps()
1121596Szelenkov@nginx.com        assert sum(resps) == 100, 'no weight 4 sum'
1131596Szelenkov@nginx.com        assert max(resps) - min(resps) <= self.cpu_count, 'no weight 4'
1141396Szelenkov@nginx.com
1151396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
1161596Szelenkov@nginx.com        assert resps[0] == 10, 'no weight 4 0'
1171596Szelenkov@nginx.com        assert resps[1] == 10, 'no weight 4 1'
1181596Szelenkov@nginx.com        assert resps[2] == 10, 'no weight 4 2'
1191396Szelenkov@nginx.com
1201396Szelenkov@nginx.com    def test_upstreams_rr_weight(self):
1211596Szelenkov@nginx.com        assert 'success' in self.conf(
1221596Szelenkov@nginx.com            {"weight": 3}, 'upstreams/one/servers/127.0.0.1:7081'
1231596Szelenkov@nginx.com        ), 'configure weight'
1241396Szelenkov@nginx.com
1251396Szelenkov@nginx.com        resps = self.get_resps_sc()
1261596Szelenkov@nginx.com        assert resps[0] == 75, 'weight 3 0'
1271596Szelenkov@nginx.com        assert resps[1] == 25, 'weight 3 1'
1281396Szelenkov@nginx.com
1291596Szelenkov@nginx.com        assert 'success' in self.conf_delete(
1301596Szelenkov@nginx.com            'upstreams/one/servers/127.0.0.1:7081/weight'
1311596Szelenkov@nginx.com        ), 'configure weight remove'
1321396Szelenkov@nginx.com        resps = self.get_resps_sc(req=10)
1331596Szelenkov@nginx.com        assert resps[0] == 5, 'weight 0 0'
1341596Szelenkov@nginx.com        assert resps[1] == 5, 'weight 0 1'
1351396Szelenkov@nginx.com
1361596Szelenkov@nginx.com        assert 'success' in self.conf(
1371596Szelenkov@nginx.com            '1', 'upstreams/one/servers/127.0.0.1:7081/weight'
1381596Szelenkov@nginx.com        ), 'configure weight 1'
1391396Szelenkov@nginx.com
1401396Szelenkov@nginx.com        resps = self.get_resps_sc()
1411596Szelenkov@nginx.com        assert resps[0] == 50, 'weight 1 0'
1421596Szelenkov@nginx.com        assert resps[1] == 50, 'weight 1 1'
1431396Szelenkov@nginx.com
1441596Szelenkov@nginx.com        assert 'success' in self.conf(
1451596Szelenkov@nginx.com            {
1461596Szelenkov@nginx.com                "127.0.0.1:7081": {"weight": 3},
1471596Szelenkov@nginx.com                "127.0.0.1:7083": {"weight": 2},
1481596Szelenkov@nginx.com            },
1491596Szelenkov@nginx.com            'upstreams/one/servers',
1501596Szelenkov@nginx.com        ), 'configure weight 2'
1511396Szelenkov@nginx.com
1521396Szelenkov@nginx.com        resps = self.get_resps_sc()
1531596Szelenkov@nginx.com        assert resps[0] == 60, 'weight 2 0'
1541596Szelenkov@nginx.com        assert resps[2] == 40, 'weight 2 1'
1551396Szelenkov@nginx.com
1561441Szelenkov@nginx.com    def test_upstreams_rr_weight_rational(self):
1571441Szelenkov@nginx.com        def set_weights(w1, w2):
1581596Szelenkov@nginx.com            assert 'success' in self.conf(
1591596Szelenkov@nginx.com                {
1601596Szelenkov@nginx.com                    "127.0.0.1:7081": {"weight": w1},
1611596Szelenkov@nginx.com                    "127.0.0.1:7082": {"weight": w2},
1621596Szelenkov@nginx.com                },
1631596Szelenkov@nginx.com                'upstreams/one/servers',
1641596Szelenkov@nginx.com            ), 'configure weights'
1651441Szelenkov@nginx.com
1661441Szelenkov@nginx.com        def check_reqs(w1, w2, reqs=10):
1671441Szelenkov@nginx.com            resps = self.get_resps_sc(req=reqs)
1681596Szelenkov@nginx.com            assert resps[0] == reqs * w1 / (w1 + w2), 'weight 1'
1691596Szelenkov@nginx.com            assert resps[1] == reqs * w2 / (w1 + w2), 'weight 2'
1701441Szelenkov@nginx.com
1711441Szelenkov@nginx.com        def check_weights(w1, w2):
1721441Szelenkov@nginx.com            set_weights(w1, w2)
1731441Szelenkov@nginx.com            check_reqs(w1, w2)
1741441Szelenkov@nginx.com
1751441Szelenkov@nginx.com        check_weights(0, 1)
1761441Szelenkov@nginx.com        check_weights(0, 999999.0123456)
1771441Szelenkov@nginx.com        check_weights(1, 9)
1781441Szelenkov@nginx.com        check_weights(100000, 900000)
1791596Szelenkov@nginx.com        check_weights(1, 0.25)
1801441Szelenkov@nginx.com        check_weights(1, 0.25)
1811596Szelenkov@nginx.com        check_weights(0.2, 0.8)
1821441Szelenkov@nginx.com        check_weights(1, 1.5)
1831596Szelenkov@nginx.com        check_weights(1e-3, 1e-3)
1841441Szelenkov@nginx.com        check_weights(1e-20, 1e-20)
1851441Szelenkov@nginx.com        check_weights(1e4, 1e4)
1861441Szelenkov@nginx.com        check_weights(1000000, 1000000)
1871441Szelenkov@nginx.com
1881441Szelenkov@nginx.com        set_weights(0.25, 0.25)
1891596Szelenkov@nginx.com        assert 'success' in self.conf_delete(
1901596Szelenkov@nginx.com            'upstreams/one/servers/127.0.0.1:7081/weight'
1911596Szelenkov@nginx.com        ), 'delete weight'
1921441Szelenkov@nginx.com        check_reqs(1, 0.25)
1931441Szelenkov@nginx.com
1941596Szelenkov@nginx.com        assert 'success' in self.conf(
1951596Szelenkov@nginx.com            {
1961596Szelenkov@nginx.com                "127.0.0.1:7081": {"weight": 0.1},
1971596Szelenkov@nginx.com                "127.0.0.1:7082": {"weight": 1},
1981596Szelenkov@nginx.com                "127.0.0.1:7083": {"weight": 0.9},
1991596Szelenkov@nginx.com            },
2001596Szelenkov@nginx.com            'upstreams/one/servers',
2011596Szelenkov@nginx.com        ), 'configure weights'
2021441Szelenkov@nginx.com        resps = self.get_resps_sc(req=20)
2031596Szelenkov@nginx.com        assert resps[0] == 1, 'weight 3 1'
2041596Szelenkov@nginx.com        assert resps[1] == 10, 'weight 3 2'
2051596Szelenkov@nginx.com        assert resps[2] == 9, 'weight 3 3'
2061441Szelenkov@nginx.com
2071396Szelenkov@nginx.com    def test_upstreams_rr_independent(self):
2081396Szelenkov@nginx.com        def sum_resps(*args):
2091396Szelenkov@nginx.com            sum = [0] * len(args[0])
2101396Szelenkov@nginx.com            for arg in args:
2111396Szelenkov@nginx.com                sum = [x + y for x, y in zip(sum, arg)]
2121396Szelenkov@nginx.com
2131396Szelenkov@nginx.com            return sum
2141396Szelenkov@nginx.com
2151396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30, port=7090)
2161596Szelenkov@nginx.com        assert resps[0] == 15, 'dep two before 0'
2171596Szelenkov@nginx.com        assert resps[1] == 15, 'dep two before 1'
2181396Szelenkov@nginx.com
2191396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
2201596Szelenkov@nginx.com        assert resps[0] == 15, 'dep one before 0'
2211596Szelenkov@nginx.com        assert resps[1] == 15, 'dep one before 1'
2221396Szelenkov@nginx.com
2231596Szelenkov@nginx.com        assert 'success' in self.conf(
2241596Szelenkov@nginx.com            '2', 'upstreams/two/servers/127.0.0.1:7081/weight'
2251596Szelenkov@nginx.com        ), 'configure dep weight'
2261396Szelenkov@nginx.com
2271396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30, port=7090)
2281596Szelenkov@nginx.com        assert resps[0] == 20, 'dep two 0'
2291596Szelenkov@nginx.com        assert resps[1] == 10, 'dep two 1'
2301396Szelenkov@nginx.com
2311396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
2321596Szelenkov@nginx.com        assert resps[0] == 15, 'dep one 0'
2331596Szelenkov@nginx.com        assert resps[1] == 15, 'dep one 1'
2341396Szelenkov@nginx.com
2351596Szelenkov@nginx.com        assert 'success' in self.conf(
2361596Szelenkov@nginx.com            '1', 'upstreams/two/servers/127.0.0.1:7081/weight'
2371596Szelenkov@nginx.com        ), 'configure dep weight 1'
2381396Szelenkov@nginx.com
2391396Szelenkov@nginx.com        r_one, r_two = [0, 0], [0, 0]
2401396Szelenkov@nginx.com        for _ in range(10):
2411396Szelenkov@nginx.com            r_one = sum_resps(r_one, self.get_resps(req=10))
2421396Szelenkov@nginx.com            r_two = sum_resps(r_two, self.get_resps(req=10, port=7090))
2431396Szelenkov@nginx.com
2441596Szelenkov@nginx.com        assert sum(r_one) == 100, 'dep one mix sum'
2451596Szelenkov@nginx.com        assert abs(r_one[0] - r_one[1]) <= self.cpu_count, 'dep one mix'
2461596Szelenkov@nginx.com        assert sum(r_two) == 100, 'dep two mix sum'
2471596Szelenkov@nginx.com        assert abs(r_two[0] - r_two[1]) <= self.cpu_count, 'dep two mix'
2481396Szelenkov@nginx.com
2491396Szelenkov@nginx.com    def test_upstreams_rr_delay(self):
2501596Szelenkov@nginx.com        assert 'success' in self.conf(
2511596Szelenkov@nginx.com            {
2521596Szelenkov@nginx.com                "listeners": {
2531596Szelenkov@nginx.com                    "*:7080": {"pass": "upstreams/one"},
2541596Szelenkov@nginx.com                    "*:7081": {"pass": "routes"},
2551596Szelenkov@nginx.com                    "*:7082": {"pass": "routes"},
2561596Szelenkov@nginx.com                },
2571596Szelenkov@nginx.com                "upstreams": {
2581596Szelenkov@nginx.com                    "one": {
2591596Szelenkov@nginx.com                        "servers": {
2601596Szelenkov@nginx.com                            "127.0.0.1:7081": {},
2611596Szelenkov@nginx.com                            "127.0.0.1:7082": {},
2621445Szelenkov@nginx.com                        },
2631445Szelenkov@nginx.com                    },
2641596Szelenkov@nginx.com                },
2651596Szelenkov@nginx.com                "routes": [
2661596Szelenkov@nginx.com                    {
2671596Szelenkov@nginx.com                        "match": {"destination": "*:7081"},
2681596Szelenkov@nginx.com                        "action": {"pass": "applications/delayed"},
2691596Szelenkov@nginx.com                    },
2701596Szelenkov@nginx.com                    {
2711596Szelenkov@nginx.com                        "match": {"destination": "*:7082"},
2721596Szelenkov@nginx.com                        "action": {"return": 201},
2731445Szelenkov@nginx.com                    },
2741596Szelenkov@nginx.com                ],
2751596Szelenkov@nginx.com                "applications": {
2761596Szelenkov@nginx.com                    "delayed": {
2771596Szelenkov@nginx.com                        "type": "python",
2781596Szelenkov@nginx.com                        "processes": {"spare": 0},
2791596Szelenkov@nginx.com                        "path": option.test_dir + "/python/delayed",
2801596Szelenkov@nginx.com                        "working_directory": option.test_dir
2811596Szelenkov@nginx.com                        + "/python/delayed",
2821596Szelenkov@nginx.com                        "module": "wsgi",
2831596Szelenkov@nginx.com                    }
2841445Szelenkov@nginx.com                },
2851596Szelenkov@nginx.com            },
2861596Szelenkov@nginx.com        ), 'upstreams initial configuration'
2871396Szelenkov@nginx.com
2881396Szelenkov@nginx.com        req = 50
2891396Szelenkov@nginx.com
2901396Szelenkov@nginx.com        socks = []
2911396Szelenkov@nginx.com        for i in range(req):
2921445Szelenkov@nginx.com            delay = 1 if i % 5 == 0 else 0
2931396Szelenkov@nginx.com            _, sock = self.get(
2941445Szelenkov@nginx.com                headers={
2951445Szelenkov@nginx.com                    'Host': 'localhost',
2961445Szelenkov@nginx.com                    'Content-Length': '0',
2971445Szelenkov@nginx.com                    'X-Delay': str(delay),
2981445Szelenkov@nginx.com                    'Connection': 'close',
2991445Szelenkov@nginx.com                },
3001396Szelenkov@nginx.com                start=True,
3011396Szelenkov@nginx.com                no_recv=True,
3021396Szelenkov@nginx.com            )
3031396Szelenkov@nginx.com            socks.append(sock)
3041396Szelenkov@nginx.com
3051396Szelenkov@nginx.com        resps = [0, 0]
3061396Szelenkov@nginx.com        for i in range(req):
3071396Szelenkov@nginx.com            resp = self.recvall(socks[i]).decode()
3081396Szelenkov@nginx.com            socks[i].close()
3091396Szelenkov@nginx.com
3101596Szelenkov@nginx.com            m = re.search(r'HTTP/1.1 20(\d)', resp)
3111596Szelenkov@nginx.com            assert m is not None, 'status'
3121396Szelenkov@nginx.com            resps[int(m.group(1))] += 1
3131396Szelenkov@nginx.com
3141596Szelenkov@nginx.com        assert sum(resps) == req, 'delay sum'
3151596Szelenkov@nginx.com        assert abs(resps[0] - resps[1]) <= self.cpu_count, 'delay'
3161396Szelenkov@nginx.com
3171396Szelenkov@nginx.com    def test_upstreams_rr_active_req(self):
3181396Szelenkov@nginx.com        conns = 5
3191396Szelenkov@nginx.com        socks = []
3201396Szelenkov@nginx.com        socks2 = []
3211396Szelenkov@nginx.com
3221396Szelenkov@nginx.com        for _ in range(conns):
3231396Szelenkov@nginx.com            _, sock = self.get(start=True, no_recv=True)
3241396Szelenkov@nginx.com            socks.append(sock)
3251396Szelenkov@nginx.com
3261396Szelenkov@nginx.com            _, sock2 = self.http(
3271396Szelenkov@nginx.com                b"""POST / HTTP/1.1
3281396Szelenkov@nginx.comHost: localhost
3291396Szelenkov@nginx.comContent-Length: 10
3301396Szelenkov@nginx.comConnection: close
3311396Szelenkov@nginx.com
3321396Szelenkov@nginx.com""",
3331396Szelenkov@nginx.com                start=True,
3341396Szelenkov@nginx.com                no_recv=True,
3351396Szelenkov@nginx.com                raw=True,
3361396Szelenkov@nginx.com            )
3371396Szelenkov@nginx.com            socks2.append(sock2)
3381396Szelenkov@nginx.com
3391396Szelenkov@nginx.com        # Send one more request and read response to make sure that previous
3401396Szelenkov@nginx.com        # requests had enough time to reach server.
3411396Szelenkov@nginx.com
3421596Szelenkov@nginx.com        assert self.get()['body'] == ''
3431396Szelenkov@nginx.com
3441596Szelenkov@nginx.com        assert 'success' in self.conf(
3451596Szelenkov@nginx.com            {"127.0.0.1:7083": {"weight": 2}}, 'upstreams/one/servers',
3461596Szelenkov@nginx.com        ), 'active req new server'
3471596Szelenkov@nginx.com        assert 'success' in self.conf_delete(
3481596Szelenkov@nginx.com            'upstreams/one/servers/127.0.0.1:7083'
3491596Szelenkov@nginx.com        ), 'active req server remove'
3501596Szelenkov@nginx.com        assert 'success' in self.conf_delete(
3511596Szelenkov@nginx.com            'listeners/*:7080'
3521596Szelenkov@nginx.com        ), 'delete listener'
3531596Szelenkov@nginx.com        assert 'success' in self.conf_delete(
3541596Szelenkov@nginx.com            'upstreams/one'
3551596Szelenkov@nginx.com        ), 'active req upstream remove'
3561396Szelenkov@nginx.com
3571396Szelenkov@nginx.com        for i in range(conns):
3581596Szelenkov@nginx.com            assert (
3591596Szelenkov@nginx.com                self.http(b'', sock=socks[i], raw=True)['body'] == ''
3601596Szelenkov@nginx.com            ), 'active req GET'
3611396Szelenkov@nginx.com
3621596Szelenkov@nginx.com            assert (
3631596Szelenkov@nginx.com                self.http(b"""0123456789""", sock=socks2[i], raw=True)['body']
3641596Szelenkov@nginx.com                == ''
3651596Szelenkov@nginx.com            ), 'active req POST'
3661396Szelenkov@nginx.com
3671396Szelenkov@nginx.com    def test_upstreams_rr_bad_server(self):
3681596Szelenkov@nginx.com        assert 'success' in self.conf(
3691596Szelenkov@nginx.com            {"weight": 1}, 'upstreams/one/servers/127.0.0.1:7084'
3701596Szelenkov@nginx.com        ), 'configure bad server'
3711396Szelenkov@nginx.com
3721396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
3731596Szelenkov@nginx.com        assert resps[0] == 10, 'bad server 0'
3741596Szelenkov@nginx.com        assert resps[1] == 10, 'bad server 1'
3751596Szelenkov@nginx.com        assert sum(resps) == 20, 'bad server sum'
3761396Szelenkov@nginx.com
3771396Szelenkov@nginx.com    def test_upstreams_rr_pipeline(self):
3781396Szelenkov@nginx.com        resps = self.get_resps_sc()
3791396Szelenkov@nginx.com
3801596Szelenkov@nginx.com        assert resps[0] == 50, 'pipeline 0'
3811596Szelenkov@nginx.com        assert resps[1] == 50, 'pipeline 1'
3821396Szelenkov@nginx.com
3831396Szelenkov@nginx.com    def test_upstreams_rr_post(self):
3841396Szelenkov@nginx.com        resps = [0, 0]
3851396Szelenkov@nginx.com        for _ in range(50):
3861445Szelenkov@nginx.com            resps[self.get()['status'] % 10] += 1
3871445Szelenkov@nginx.com            resps[self.post(body='0123456789')['status'] % 10] += 1
3881396Szelenkov@nginx.com
3891596Szelenkov@nginx.com        assert sum(resps) == 100, 'post sum'
3901596Szelenkov@nginx.com        assert abs(resps[0] - resps[1]) <= self.cpu_count, 'post'
3911396Szelenkov@nginx.com
3921654Szelenkov@nginx.com    def test_upstreams_rr_unix(self, temp_dir):
3931654Szelenkov@nginx.com        addr_0 = temp_dir + '/sock_0'
3941654Szelenkov@nginx.com        addr_1 = temp_dir + '/sock_1'
3951396Szelenkov@nginx.com
3961596Szelenkov@nginx.com        assert 'success' in self.conf(
3971596Szelenkov@nginx.com            {
3981596Szelenkov@nginx.com                "*:7080": {"pass": "upstreams/one"},
3991596Szelenkov@nginx.com                "unix:" + addr_0: {"pass": "routes/one"},
4001596Szelenkov@nginx.com                "unix:" + addr_1: {"pass": "routes/two"},
4011596Szelenkov@nginx.com            },
4021596Szelenkov@nginx.com            'listeners',
4031596Szelenkov@nginx.com        ), 'configure listeners unix'
4041396Szelenkov@nginx.com
4051596Szelenkov@nginx.com        assert 'success' in self.conf(
4061596Szelenkov@nginx.com            {"unix:" + addr_0: {}, "unix:" + addr_1: {}},
4071596Szelenkov@nginx.com            'upstreams/one/servers',
4081596Szelenkov@nginx.com        ), 'configure servers unix'
4091396Szelenkov@nginx.com
4101396Szelenkov@nginx.com        resps = self.get_resps_sc()
4111396Szelenkov@nginx.com
4121596Szelenkov@nginx.com        assert resps[0] == 50, 'unix 0'
4131596Szelenkov@nginx.com        assert resps[1] == 50, 'unix 1'
4141396Szelenkov@nginx.com
4151396Szelenkov@nginx.com    def test_upstreams_rr_ipv6(self):
4161596Szelenkov@nginx.com        assert 'success' in self.conf(
4171596Szelenkov@nginx.com            {
4181596Szelenkov@nginx.com                "*:7080": {"pass": "upstreams/one"},
4191596Szelenkov@nginx.com                "[::1]:7081": {"pass": "routes/one"},
4201596Szelenkov@nginx.com                "[::1]:7082": {"pass": "routes/two"},
4211596Szelenkov@nginx.com            },
4221596Szelenkov@nginx.com            'listeners',
4231596Szelenkov@nginx.com        ), 'configure listeners ipv6'
4241396Szelenkov@nginx.com
4251596Szelenkov@nginx.com        assert 'success' in self.conf(
4261596Szelenkov@nginx.com            {"[::1]:7081": {}, "[::1]:7082": {}}, 'upstreams/one/servers'
4271596Szelenkov@nginx.com        ), 'configure servers ipv6'
4281396Szelenkov@nginx.com
4291396Szelenkov@nginx.com        resps = self.get_resps_sc()
4301396Szelenkov@nginx.com
4311596Szelenkov@nginx.com        assert resps[0] == 50, 'ipv6 0'
4321596Szelenkov@nginx.com        assert resps[1] == 50, 'ipv6 1'
4331396Szelenkov@nginx.com
4341396Szelenkov@nginx.com    def test_upstreams_rr_servers_empty(self):
4351596Szelenkov@nginx.com        assert 'success' in self.conf(
4361596Szelenkov@nginx.com            {}, 'upstreams/one/servers'
4371596Szelenkov@nginx.com        ), 'configure servers empty'
4381596Szelenkov@nginx.com        assert self.get()['status'] == 502, 'servers empty'
4391396Szelenkov@nginx.com
4401596Szelenkov@nginx.com        assert 'success' in self.conf(
4411596Szelenkov@nginx.com            {"127.0.0.1:7081": {"weight": 0}}, 'upstreams/one/servers'
4421596Szelenkov@nginx.com        ), 'configure servers empty one'
4431596Szelenkov@nginx.com        assert self.get()['status'] == 502, 'servers empty one'
4441596Szelenkov@nginx.com        assert 'success' in self.conf(
4451596Szelenkov@nginx.com            {
4461596Szelenkov@nginx.com                "127.0.0.1:7081": {"weight": 0},
4471596Szelenkov@nginx.com                "127.0.0.1:7082": {"weight": 0},
4481596Szelenkov@nginx.com            },
4491596Szelenkov@nginx.com            'upstreams/one/servers',
4501596Szelenkov@nginx.com        ), 'configure servers empty two'
4511596Szelenkov@nginx.com        assert self.get()['status'] == 502, 'servers empty two'
4521396Szelenkov@nginx.com
4531396Szelenkov@nginx.com    def test_upstreams_rr_invalid(self):
4541596Szelenkov@nginx.com        assert 'error' in self.conf({}, 'upstreams'), 'upstreams empty'
4551596Szelenkov@nginx.com        assert 'error' in self.conf(
4561596Szelenkov@nginx.com            {}, 'upstreams/one'
4571596Szelenkov@nginx.com        ), 'named upstreams empty'
4581596Szelenkov@nginx.com        assert 'error' in self.conf(
4591596Szelenkov@nginx.com            {}, 'upstreams/one/servers/127.0.0.1'
4601596Szelenkov@nginx.com        ), 'invalid address'
4611596Szelenkov@nginx.com        assert 'error' in self.conf(
4621596Szelenkov@nginx.com            {}, 'upstreams/one/servers/127.0.0.1:7081/blah'
4631596Szelenkov@nginx.com        ), 'invalid server option'
4641441Szelenkov@nginx.com
4651441Szelenkov@nginx.com        def check_weight(w):
4661596Szelenkov@nginx.com            assert 'error' in self.conf(
4671596Szelenkov@nginx.com                w, 'upstreams/one/servers/127.0.0.1:7081/weight'
4681596Szelenkov@nginx.com            ), 'invalid weight option'
4691596Szelenkov@nginx.com
4701441Szelenkov@nginx.com        check_weight({})
4711441Szelenkov@nginx.com        check_weight('-1')
4721441Szelenkov@nginx.com        check_weight('1.')
4731441Szelenkov@nginx.com        check_weight('1.1.')
4741441Szelenkov@nginx.com        check_weight('.')
4751441Szelenkov@nginx.com        check_weight('.01234567890123')
4761441Szelenkov@nginx.com        check_weight('1000001')
4771441Szelenkov@nginx.com        check_weight('2e6')
478