xref: /unit/test/test_upstreams_rr.py (revision 1445)
11396Szelenkov@nginx.comimport os
21396Szelenkov@nginx.comimport re
31396Szelenkov@nginx.comimport unittest
41396Szelenkov@nginx.comfrom unit.applications.lang.python import TestApplicationPython
51396Szelenkov@nginx.com
61396Szelenkov@nginx.com
71396Szelenkov@nginx.comclass TestUpstreamsRR(TestApplicationPython):
81396Szelenkov@nginx.com    prerequisites = {'modules': ['python']}
91396Szelenkov@nginx.com
101396Szelenkov@nginx.com    def setUp(self):
111396Szelenkov@nginx.com        super().setUp()
121396Szelenkov@nginx.com
131396Szelenkov@nginx.com        self.assertIn(
141396Szelenkov@nginx.com            'success',
151396Szelenkov@nginx.com            self.conf(
161396Szelenkov@nginx.com                {
171396Szelenkov@nginx.com                    "listeners": {
181396Szelenkov@nginx.com                        "*:7080": {"pass": "upstreams/one"},
191396Szelenkov@nginx.com                        "*:7090": {"pass": "upstreams/two"},
20*1445Szelenkov@nginx.com                        "*:7081": {"pass": "routes/one"},
21*1445Szelenkov@nginx.com                        "*:7082": {"pass": "routes/two"},
22*1445Szelenkov@nginx.com                        "*:7083": {"pass": "routes/three"},
231396Szelenkov@nginx.com                    },
241396Szelenkov@nginx.com                    "upstreams": {
251396Szelenkov@nginx.com                        "one": {
261396Szelenkov@nginx.com                            "servers": {
271396Szelenkov@nginx.com                                "127.0.0.1:7081": {},
281396Szelenkov@nginx.com                                "127.0.0.1:7082": {},
291396Szelenkov@nginx.com                            },
301396Szelenkov@nginx.com                        },
311396Szelenkov@nginx.com                        "two": {
321396Szelenkov@nginx.com                            "servers": {
331396Szelenkov@nginx.com                                "127.0.0.1:7081": {},
341396Szelenkov@nginx.com                                "127.0.0.1:7082": {},
351396Szelenkov@nginx.com                            },
361396Szelenkov@nginx.com                        },
371396Szelenkov@nginx.com                    },
38*1445Szelenkov@nginx.com                    "routes": {
39*1445Szelenkov@nginx.com                        "one": [{"action": {"return": 200}}],
40*1445Szelenkov@nginx.com                        "two": [{"action": {"return": 201}}],
41*1445Szelenkov@nginx.com                        "three": [{"action": {"return": 202}}],
421396Szelenkov@nginx.com                    },
43*1445Szelenkov@nginx.com                    "applications": {},
441396Szelenkov@nginx.com                },
451396Szelenkov@nginx.com            ),
461396Szelenkov@nginx.com            'upstreams initial configuration',
471396Szelenkov@nginx.com        )
481396Szelenkov@nginx.com
491396Szelenkov@nginx.com        self.cpu_count = os.cpu_count()
501396Szelenkov@nginx.com
511396Szelenkov@nginx.com    def get_resps(self, req=100, port=7080):
521396Szelenkov@nginx.com        resps = [0]
53*1445Szelenkov@nginx.com
541396Szelenkov@nginx.com        for _ in range(req):
55*1445Szelenkov@nginx.com            status = self.get(port=port)['status']
56*1445Szelenkov@nginx.com            if 200 > status or status > 209:
57*1445Szelenkov@nginx.com                continue
581396Szelenkov@nginx.com
59*1445Szelenkov@nginx.com            ups = status % 10
60*1445Szelenkov@nginx.com            if ups > len(resps) - 1:
61*1445Szelenkov@nginx.com                resps.extend([0] * (ups - len(resps) + 1))
621396Szelenkov@nginx.com
63*1445Szelenkov@nginx.com            resps[ups] += 1
641396Szelenkov@nginx.com
651396Szelenkov@nginx.com        return resps
661396Szelenkov@nginx.com
671396Szelenkov@nginx.com    def get_resps_sc(self, req=100, port=7080):
681396Szelenkov@nginx.com        to_send = b"""GET / HTTP/1.1
691396Szelenkov@nginx.comHost: localhost
701396Szelenkov@nginx.com
711396Szelenkov@nginx.com""" * (
721396Szelenkov@nginx.com            req - 1
731396Szelenkov@nginx.com        )
741396Szelenkov@nginx.com
751396Szelenkov@nginx.com        to_send += b"""GET / HTTP/1.1
761396Szelenkov@nginx.comHost: localhost
771396Szelenkov@nginx.comConnection: close
781396Szelenkov@nginx.com
791396Szelenkov@nginx.com"""
801396Szelenkov@nginx.com
811396Szelenkov@nginx.com        resp = self.http(to_send, raw_resp=True, raw=True, port=port)
82*1445Szelenkov@nginx.com        status = re.findall(r'HTTP\/\d\.\d\s(\d\d\d)', resp)
83*1445Szelenkov@nginx.com        status = list(filter(lambda x: x[:2] == '20', status))
84*1445Szelenkov@nginx.com        ups = list(map(lambda x: int(x[-1]), status))
851396Szelenkov@nginx.com
86*1445Szelenkov@nginx.com        resps = [0] * (max(ups) + 1)
871396Szelenkov@nginx.com        for i in range(len(ups)):
88*1445Szelenkov@nginx.com            resps[ups[i]] += 1
891396Szelenkov@nginx.com
901396Szelenkov@nginx.com        return resps
911396Szelenkov@nginx.com
921396Szelenkov@nginx.com    def test_upstreams_rr_no_weight(self):
931396Szelenkov@nginx.com        resps = self.get_resps()
94*1445Szelenkov@nginx.com        self.assertEqual(sum(resps), 100, 'no weight sum')
951396Szelenkov@nginx.com        self.assertLessEqual(
961396Szelenkov@nginx.com            abs(resps[0] - resps[1]), self.cpu_count, 'no weight'
971396Szelenkov@nginx.com        )
981396Szelenkov@nginx.com
991396Szelenkov@nginx.com        self.assertIn(
1001396Szelenkov@nginx.com            'success',
1011396Szelenkov@nginx.com            self.conf_delete('upstreams/one/servers/127.0.0.1:7081'),
1021396Szelenkov@nginx.com            'no weight server remove',
1031396Szelenkov@nginx.com        )
1041396Szelenkov@nginx.com
1051396Szelenkov@nginx.com        resps = self.get_resps(req=50)
1061396Szelenkov@nginx.com        self.assertEqual(resps[1], 50, 'no weight 2')
1071396Szelenkov@nginx.com
1081396Szelenkov@nginx.com        self.assertIn(
1091396Szelenkov@nginx.com            'success',
1101396Szelenkov@nginx.com            self.conf({}, 'upstreams/one/servers/127.0.0.1:7081'),
1111396Szelenkov@nginx.com            'no weight server revert',
1121396Szelenkov@nginx.com        )
1131396Szelenkov@nginx.com
1141396Szelenkov@nginx.com        resps = self.get_resps()
115*1445Szelenkov@nginx.com        self.assertEqual(sum(resps), 100, 'no weight 3 sum')
1161396Szelenkov@nginx.com        self.assertLessEqual(
1171396Szelenkov@nginx.com            abs(resps[0] - resps[1]), self.cpu_count, 'no weight 3'
1181396Szelenkov@nginx.com        )
1191396Szelenkov@nginx.com
1201396Szelenkov@nginx.com        self.assertIn(
1211396Szelenkov@nginx.com            'success',
1221396Szelenkov@nginx.com            self.conf({}, 'upstreams/one/servers/127.0.0.1:7083'),
1231396Szelenkov@nginx.com            'no weight server new',
1241396Szelenkov@nginx.com        )
1251396Szelenkov@nginx.com
1261396Szelenkov@nginx.com        resps = self.get_resps()
127*1445Szelenkov@nginx.com        self.assertEqual(sum(resps), 100, 'no weight 4 sum')
1281396Szelenkov@nginx.com        self.assertLessEqual(
1291396Szelenkov@nginx.com            max(resps) - min(resps), self.cpu_count, 'no weight 4'
1301396Szelenkov@nginx.com        )
1311396Szelenkov@nginx.com
1321396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
1331396Szelenkov@nginx.com        self.assertEqual(resps[0], 10, 'no weight 4 0')
1341396Szelenkov@nginx.com        self.assertEqual(resps[1], 10, 'no weight 4 1')
1351396Szelenkov@nginx.com        self.assertEqual(resps[2], 10, 'no weight 4 2')
1361396Szelenkov@nginx.com
1371396Szelenkov@nginx.com    def test_upstreams_rr_weight(self):
1381396Szelenkov@nginx.com        self.assertIn(
1391396Szelenkov@nginx.com            'success',
1401396Szelenkov@nginx.com            self.conf({"weight": 3}, 'upstreams/one/servers/127.0.0.1:7081'),
1411396Szelenkov@nginx.com            'configure weight',
1421396Szelenkov@nginx.com        )
1431396Szelenkov@nginx.com
1441396Szelenkov@nginx.com        resps = self.get_resps_sc()
1451396Szelenkov@nginx.com        self.assertEqual(resps[0], 75, 'weight 3 0')
1461396Szelenkov@nginx.com        self.assertEqual(resps[1], 25, 'weight 3 1')
1471396Szelenkov@nginx.com
1481396Szelenkov@nginx.com        self.assertIn(
1491396Szelenkov@nginx.com            'success',
1501396Szelenkov@nginx.com            self.conf_delete('upstreams/one/servers/127.0.0.1:7081/weight'),
1511396Szelenkov@nginx.com            'configure weight remove',
1521396Szelenkov@nginx.com        )
1531396Szelenkov@nginx.com        resps = self.get_resps_sc(req=10)
1541396Szelenkov@nginx.com        self.assertEqual(resps[0], 5, 'weight 0 0')
1551396Szelenkov@nginx.com        self.assertEqual(resps[1], 5, 'weight 0 1')
1561396Szelenkov@nginx.com
1571396Szelenkov@nginx.com        self.assertIn(
1581396Szelenkov@nginx.com            'success',
1591396Szelenkov@nginx.com            self.conf('1', 'upstreams/one/servers/127.0.0.1:7081/weight'),
1601396Szelenkov@nginx.com            'configure weight 1',
1611396Szelenkov@nginx.com        )
1621396Szelenkov@nginx.com
1631396Szelenkov@nginx.com        resps = self.get_resps_sc()
1641396Szelenkov@nginx.com        self.assertEqual(resps[0], 50, 'weight 1 0')
1651396Szelenkov@nginx.com        self.assertEqual(resps[1], 50, 'weight 1 1')
1661396Szelenkov@nginx.com
1671396Szelenkov@nginx.com        self.assertIn(
1681396Szelenkov@nginx.com            'success',
1691396Szelenkov@nginx.com            self.conf(
1701396Szelenkov@nginx.com                {
1711396Szelenkov@nginx.com                    "127.0.0.1:7081": {"weight": 3},
1721396Szelenkov@nginx.com                    "127.0.0.1:7083": {"weight": 2},
1731396Szelenkov@nginx.com                },
1741396Szelenkov@nginx.com                'upstreams/one/servers',
1751396Szelenkov@nginx.com            ),
1761396Szelenkov@nginx.com            'configure weight 2',
1771396Szelenkov@nginx.com        )
1781396Szelenkov@nginx.com
1791396Szelenkov@nginx.com        resps = self.get_resps_sc()
1801396Szelenkov@nginx.com        self.assertEqual(resps[0], 60, 'weight 2 0')
1811396Szelenkov@nginx.com        self.assertEqual(resps[2], 40, 'weight 2 1')
1821396Szelenkov@nginx.com
1831441Szelenkov@nginx.com    def test_upstreams_rr_weight_rational(self):
1841441Szelenkov@nginx.com        def set_weights(w1, w2):
1851441Szelenkov@nginx.com            self.assertIn(
1861441Szelenkov@nginx.com                'success',
1871441Szelenkov@nginx.com                self.conf(
1881441Szelenkov@nginx.com                    {
1891441Szelenkov@nginx.com                        "127.0.0.1:7081": {"weight": w1},
1901441Szelenkov@nginx.com                        "127.0.0.1:7082": {"weight": w2},
1911441Szelenkov@nginx.com                    },
1921441Szelenkov@nginx.com                    'upstreams/one/servers',
1931441Szelenkov@nginx.com                ),
1941441Szelenkov@nginx.com                'configure weights',
1951441Szelenkov@nginx.com            )
1961441Szelenkov@nginx.com
1971441Szelenkov@nginx.com        def check_reqs(w1, w2, reqs=10):
1981441Szelenkov@nginx.com            resps = self.get_resps_sc(req=reqs)
1991441Szelenkov@nginx.com            self.assertEqual(resps[0], reqs * w1 / (w1 + w2), 'weight 1')
2001441Szelenkov@nginx.com            self.assertEqual(resps[1], reqs * w2 / (w1 + w2), 'weight 2')
2011441Szelenkov@nginx.com
2021441Szelenkov@nginx.com        def check_weights(w1, w2):
2031441Szelenkov@nginx.com            set_weights(w1, w2)
2041441Szelenkov@nginx.com            check_reqs(w1, w2)
2051441Szelenkov@nginx.com
2061441Szelenkov@nginx.com        check_weights(0, 1)
2071441Szelenkov@nginx.com        check_weights(0, 999999.0123456)
2081441Szelenkov@nginx.com        check_weights(1, 9)
2091441Szelenkov@nginx.com        check_weights(100000, 900000)
2101441Szelenkov@nginx.com        check_weights(1, .25)
2111441Szelenkov@nginx.com        check_weights(1, 0.25)
2121441Szelenkov@nginx.com        check_weights(0.2, .8)
2131441Szelenkov@nginx.com        check_weights(1, 1.5)
2141441Szelenkov@nginx.com        check_weights(1e-3, 1E-3)
2151441Szelenkov@nginx.com        check_weights(1e-20, 1e-20)
2161441Szelenkov@nginx.com        check_weights(1e4, 1e4)
2171441Szelenkov@nginx.com        check_weights(1000000, 1000000)
2181441Szelenkov@nginx.com
2191441Szelenkov@nginx.com        set_weights(0.25, 0.25)
2201441Szelenkov@nginx.com        self.assertIn(
2211441Szelenkov@nginx.com            'success',
2221441Szelenkov@nginx.com            self.conf_delete('upstreams/one/servers/127.0.0.1:7081/weight'),
2231441Szelenkov@nginx.com            'delete weight',
2241441Szelenkov@nginx.com        )
2251441Szelenkov@nginx.com        check_reqs(1, 0.25)
2261441Szelenkov@nginx.com
2271441Szelenkov@nginx.com        self.assertIn(
2281441Szelenkov@nginx.com            'success',
2291441Szelenkov@nginx.com            self.conf(
2301441Szelenkov@nginx.com                {
2311441Szelenkov@nginx.com                    "127.0.0.1:7081": {"weight": 0.1},
2321441Szelenkov@nginx.com                    "127.0.0.1:7082": {"weight": 1},
2331441Szelenkov@nginx.com                    "127.0.0.1:7083": {"weight": 0.9},
2341441Szelenkov@nginx.com                },
2351441Szelenkov@nginx.com                'upstreams/one/servers',
2361441Szelenkov@nginx.com            ),
2371441Szelenkov@nginx.com            'configure weights',
2381441Szelenkov@nginx.com        )
2391441Szelenkov@nginx.com        resps = self.get_resps_sc(req=20)
2401441Szelenkov@nginx.com        self.assertEqual(resps[0], 1, 'weight 3 1')
2411441Szelenkov@nginx.com        self.assertEqual(resps[1], 10, 'weight 3 2')
2421441Szelenkov@nginx.com        self.assertEqual(resps[2], 9, 'weight 3 3')
2431441Szelenkov@nginx.com
2441396Szelenkov@nginx.com    def test_upstreams_rr_independent(self):
2451396Szelenkov@nginx.com        def sum_resps(*args):
2461396Szelenkov@nginx.com            sum = [0] * len(args[0])
2471396Szelenkov@nginx.com            for arg in args:
2481396Szelenkov@nginx.com                sum = [x + y for x, y in zip(sum, arg)]
2491396Szelenkov@nginx.com
2501396Szelenkov@nginx.com            return sum
2511396Szelenkov@nginx.com
2521396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30, port=7090)
2531396Szelenkov@nginx.com        self.assertEqual(resps[0], 15, 'dep two before 0')
2541396Szelenkov@nginx.com        self.assertEqual(resps[1], 15, 'dep two before 1')
2551396Szelenkov@nginx.com
2561396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
2571396Szelenkov@nginx.com        self.assertEqual(resps[0], 15, 'dep one before 0')
2581396Szelenkov@nginx.com        self.assertEqual(resps[1], 15, 'dep one before 1')
2591396Szelenkov@nginx.com
2601396Szelenkov@nginx.com        self.assertIn(
2611396Szelenkov@nginx.com            'success',
2621396Szelenkov@nginx.com            self.conf('2', 'upstreams/two/servers/127.0.0.1:7081/weight'),
2631396Szelenkov@nginx.com            'configure dep weight',
2641396Szelenkov@nginx.com        )
2651396Szelenkov@nginx.com
2661396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30, port=7090)
2671396Szelenkov@nginx.com        self.assertEqual(resps[0], 20, 'dep two 0')
2681396Szelenkov@nginx.com        self.assertEqual(resps[1], 10, 'dep two 1')
2691396Szelenkov@nginx.com
2701396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
2711396Szelenkov@nginx.com        self.assertEqual(resps[0], 15, 'dep one 0')
2721396Szelenkov@nginx.com        self.assertEqual(resps[1], 15, 'dep one 1')
2731396Szelenkov@nginx.com
2741396Szelenkov@nginx.com        self.assertIn(
2751396Szelenkov@nginx.com            'success',
2761396Szelenkov@nginx.com            self.conf('1', 'upstreams/two/servers/127.0.0.1:7081/weight'),
2771396Szelenkov@nginx.com            'configure dep weight 1',
2781396Szelenkov@nginx.com        )
2791396Szelenkov@nginx.com
2801396Szelenkov@nginx.com        r_one, r_two = [0, 0], [0, 0]
2811396Szelenkov@nginx.com        for _ in range(10):
2821396Szelenkov@nginx.com            r_one = sum_resps(r_one, self.get_resps(req=10))
2831396Szelenkov@nginx.com            r_two = sum_resps(r_two, self.get_resps(req=10, port=7090))
2841396Szelenkov@nginx.com
285*1445Szelenkov@nginx.com
286*1445Szelenkov@nginx.com        self.assertEqual(sum(r_one), 100, 'dep one mix sum')
2871396Szelenkov@nginx.com        self.assertLessEqual(
2881396Szelenkov@nginx.com            abs(r_one[0] - r_one[1]), self.cpu_count, 'dep one mix'
2891396Szelenkov@nginx.com        )
290*1445Szelenkov@nginx.com        self.assertEqual(sum(r_two), 100, 'dep two mix sum')
2911396Szelenkov@nginx.com        self.assertLessEqual(
2921396Szelenkov@nginx.com            abs(r_two[0] - r_two[1]), self.cpu_count, 'dep two mix'
2931396Szelenkov@nginx.com        )
2941396Szelenkov@nginx.com
2951396Szelenkov@nginx.com    def test_upstreams_rr_delay(self):
296*1445Szelenkov@nginx.com        self.assertIn(
297*1445Szelenkov@nginx.com            'success',
298*1445Szelenkov@nginx.com            self.conf(
299*1445Szelenkov@nginx.com                {
300*1445Szelenkov@nginx.com                    "listeners": {
301*1445Szelenkov@nginx.com                        "*:7080": {"pass": "upstreams/one"},
302*1445Szelenkov@nginx.com                        "*:7081": {"pass": "routes"},
303*1445Szelenkov@nginx.com                        "*:7082": {"pass": "routes"},
304*1445Szelenkov@nginx.com                    },
305*1445Szelenkov@nginx.com                    "upstreams": {
306*1445Szelenkov@nginx.com                        "one": {
307*1445Szelenkov@nginx.com                            "servers": {
308*1445Szelenkov@nginx.com                                "127.0.0.1:7081": {},
309*1445Szelenkov@nginx.com                                "127.0.0.1:7082": {},
310*1445Szelenkov@nginx.com                            },
311*1445Szelenkov@nginx.com                        },
312*1445Szelenkov@nginx.com                    },
313*1445Szelenkov@nginx.com                    "routes": [
314*1445Szelenkov@nginx.com                        {
315*1445Szelenkov@nginx.com                            "match": {"destination": "*:7081"},
316*1445Szelenkov@nginx.com                            "action": {"pass": "applications/delayed"},
317*1445Szelenkov@nginx.com                        },
318*1445Szelenkov@nginx.com                        {
319*1445Szelenkov@nginx.com                            "match": {"destination": "*:7082"},
320*1445Szelenkov@nginx.com                            "action": {"return": 201},
321*1445Szelenkov@nginx.com                        },
322*1445Szelenkov@nginx.com                    ],
323*1445Szelenkov@nginx.com                    "applications": {
324*1445Szelenkov@nginx.com                        "delayed": {
325*1445Szelenkov@nginx.com                            "type": "python",
326*1445Szelenkov@nginx.com                            "processes": {"spare": 0},
327*1445Szelenkov@nginx.com                            "path": self.current_dir + "/python/delayed",
328*1445Szelenkov@nginx.com                            "working_directory": self.current_dir
329*1445Szelenkov@nginx.com                            + "/python/delayed",
330*1445Szelenkov@nginx.com                            "module": "wsgi",
331*1445Szelenkov@nginx.com                        }
332*1445Szelenkov@nginx.com                    },
333*1445Szelenkov@nginx.com                },
334*1445Szelenkov@nginx.com            ),
335*1445Szelenkov@nginx.com            'upstreams initial configuration',
336*1445Szelenkov@nginx.com        )
3371396Szelenkov@nginx.com
3381396Szelenkov@nginx.com        req = 50
3391396Szelenkov@nginx.com
3401396Szelenkov@nginx.com        socks = []
3411396Szelenkov@nginx.com        for i in range(req):
342*1445Szelenkov@nginx.com            delay = 1 if i % 5 == 0 else 0
3431396Szelenkov@nginx.com            _, sock = self.get(
344*1445Szelenkov@nginx.com                headers={
345*1445Szelenkov@nginx.com                    'Host': 'localhost',
346*1445Szelenkov@nginx.com                    'Content-Length': '0',
347*1445Szelenkov@nginx.com                    'X-Delay': str(delay),
348*1445Szelenkov@nginx.com                    'Connection': 'close',
349*1445Szelenkov@nginx.com                },
3501396Szelenkov@nginx.com                start=True,
3511396Szelenkov@nginx.com                no_recv=True,
3521396Szelenkov@nginx.com            )
3531396Szelenkov@nginx.com            socks.append(sock)
3541396Szelenkov@nginx.com
3551396Szelenkov@nginx.com        resps = [0, 0]
3561396Szelenkov@nginx.com        for i in range(req):
3571396Szelenkov@nginx.com            resp = self.recvall(socks[i]).decode()
3581396Szelenkov@nginx.com            socks[i].close()
3591396Szelenkov@nginx.com
360*1445Szelenkov@nginx.com            m = re.search('HTTP/1.1 20(\d)', resp)
361*1445Szelenkov@nginx.com            self.assertIsNotNone(m, 'status')
3621396Szelenkov@nginx.com            resps[int(m.group(1))] += 1
3631396Szelenkov@nginx.com
364*1445Szelenkov@nginx.com        self.assertEqual(sum(resps), req, 'delay sum')
365*1445Szelenkov@nginx.com        self.assertLessEqual(abs(resps[0] - resps[1]), self.cpu_count, 'delay')
3661396Szelenkov@nginx.com
3671396Szelenkov@nginx.com    def test_upstreams_rr_active_req(self):
3681396Szelenkov@nginx.com        conns = 5
3691396Szelenkov@nginx.com        socks = []
3701396Szelenkov@nginx.com        socks2 = []
3711396Szelenkov@nginx.com
3721396Szelenkov@nginx.com        for _ in range(conns):
3731396Szelenkov@nginx.com            _, sock = self.get(start=True, no_recv=True)
3741396Szelenkov@nginx.com            socks.append(sock)
3751396Szelenkov@nginx.com
3761396Szelenkov@nginx.com            _, sock2 = self.http(
3771396Szelenkov@nginx.com                b"""POST / HTTP/1.1
3781396Szelenkov@nginx.comHost: localhost
3791396Szelenkov@nginx.comContent-Length: 10
3801396Szelenkov@nginx.comConnection: close
3811396Szelenkov@nginx.com
3821396Szelenkov@nginx.com""",
3831396Szelenkov@nginx.com                start=True,
3841396Szelenkov@nginx.com                no_recv=True,
3851396Szelenkov@nginx.com                raw=True,
3861396Szelenkov@nginx.com            )
3871396Szelenkov@nginx.com            socks2.append(sock2)
3881396Szelenkov@nginx.com
3891396Szelenkov@nginx.com        # Send one more request and read response to make sure that previous
3901396Szelenkov@nginx.com        # requests had enough time to reach server.
3911396Szelenkov@nginx.com
392*1445Szelenkov@nginx.com        self.assertEqual(self.get()['body'], '')
3931396Szelenkov@nginx.com
3941396Szelenkov@nginx.com        self.assertIn(
3951396Szelenkov@nginx.com            'success',
3961396Szelenkov@nginx.com            self.conf(
3971396Szelenkov@nginx.com                {"127.0.0.1:7083": {"weight": 2}}, 'upstreams/one/servers',
3981396Szelenkov@nginx.com            ),
3991396Szelenkov@nginx.com            'active req new server',
4001396Szelenkov@nginx.com        )
4011396Szelenkov@nginx.com        self.assertIn(
4021396Szelenkov@nginx.com            'success',
4031396Szelenkov@nginx.com            self.conf_delete('upstreams/one/servers/127.0.0.1:7083'),
4041396Szelenkov@nginx.com            'active req server remove',
4051396Szelenkov@nginx.com        )
4061396Szelenkov@nginx.com        self.assertIn(
4071396Szelenkov@nginx.com            'success', self.conf_delete('listeners/*:7080'), 'delete listener'
4081396Szelenkov@nginx.com        )
4091396Szelenkov@nginx.com        self.assertIn(
4101396Szelenkov@nginx.com            'success',
4111396Szelenkov@nginx.com            self.conf_delete('upstreams/one'),
4121396Szelenkov@nginx.com            'active req upstream remove',
4131396Szelenkov@nginx.com        )
4141396Szelenkov@nginx.com
4151396Szelenkov@nginx.com        for i in range(conns):
416*1445Szelenkov@nginx.com            self.assertEqual(
417*1445Szelenkov@nginx.com                self.http(b'', sock=socks[i], raw=True)['body'],
418*1445Szelenkov@nginx.com                '',
419*1445Szelenkov@nginx.com                'active req GET',
420*1445Szelenkov@nginx.com            )
4211396Szelenkov@nginx.com
422*1445Szelenkov@nginx.com            self.assertEqual(
423*1445Szelenkov@nginx.com                self.http(b"""0123456789""", sock=socks2[i], raw=True)['body'],
424*1445Szelenkov@nginx.com                '',
425*1445Szelenkov@nginx.com                'active req POST',
426*1445Szelenkov@nginx.com            )
4271396Szelenkov@nginx.com
4281396Szelenkov@nginx.com    def test_upstreams_rr_bad_server(self):
4291396Szelenkov@nginx.com        self.assertIn(
4301396Szelenkov@nginx.com            'success',
4311396Szelenkov@nginx.com            self.conf({"weight": 1}, 'upstreams/one/servers/127.0.0.1:7084'),
4321396Szelenkov@nginx.com            'configure bad server',
4331396Szelenkov@nginx.com        )
4341396Szelenkov@nginx.com
4351396Szelenkov@nginx.com        resps = self.get_resps_sc(req=30)
4361396Szelenkov@nginx.com        self.assertEqual(resps[0], 10, 'bad server 0')
4371396Szelenkov@nginx.com        self.assertEqual(resps[1], 10, 'bad server 1')
4381396Szelenkov@nginx.com        self.assertEqual(sum(resps), 20, 'bad server sum')
4391396Szelenkov@nginx.com
4401396Szelenkov@nginx.com    def test_upstreams_rr_pipeline(self):
4411396Szelenkov@nginx.com        resps = self.get_resps_sc()
4421396Szelenkov@nginx.com
4431396Szelenkov@nginx.com        self.assertEqual(resps[0], 50, 'pipeline 0')
4441396Szelenkov@nginx.com        self.assertEqual(resps[1], 50, 'pipeline 1')
4451396Szelenkov@nginx.com
4461396Szelenkov@nginx.com    def test_upstreams_rr_post(self):
4471396Szelenkov@nginx.com        resps = [0, 0]
4481396Szelenkov@nginx.com        for _ in range(50):
449*1445Szelenkov@nginx.com            resps[self.get()['status'] % 10] += 1
450*1445Szelenkov@nginx.com            resps[self.post(body='0123456789')['status'] % 10] += 1
4511396Szelenkov@nginx.com
452*1445Szelenkov@nginx.com        self.assertEqual(sum(resps), 100, 'post sum')
453*1445Szelenkov@nginx.com        self.assertLessEqual(abs(resps[0] - resps[1]), self.cpu_count, 'post')
4541396Szelenkov@nginx.com
4551396Szelenkov@nginx.com    def test_upstreams_rr_unix(self):
4561396Szelenkov@nginx.com        addr_0 = self.testdir + '/sock_0'
4571396Szelenkov@nginx.com        addr_1 = self.testdir + '/sock_1'
4581396Szelenkov@nginx.com
4591396Szelenkov@nginx.com        self.assertIn(
4601396Szelenkov@nginx.com            'success',
4611396Szelenkov@nginx.com            self.conf(
4621396Szelenkov@nginx.com                {
4631396Szelenkov@nginx.com                    "*:7080": {"pass": "upstreams/one"},
464*1445Szelenkov@nginx.com                    "unix:" + addr_0: {"pass": "routes/one"},
465*1445Szelenkov@nginx.com                    "unix:" + addr_1: {"pass": "routes/two"},
4661396Szelenkov@nginx.com                },
4671396Szelenkov@nginx.com                'listeners',
4681396Szelenkov@nginx.com            ),
4691396Szelenkov@nginx.com            'configure listeners unix',
4701396Szelenkov@nginx.com        )
4711396Szelenkov@nginx.com
4721396Szelenkov@nginx.com        self.assertIn(
4731396Szelenkov@nginx.com            'success',
4741396Szelenkov@nginx.com            self.conf(
475*1445Szelenkov@nginx.com                {"unix:" + addr_0: {}, "unix:" + addr_1: {}},
4761396Szelenkov@nginx.com                'upstreams/one/servers',
4771396Szelenkov@nginx.com            ),
4781396Szelenkov@nginx.com            'configure servers unix',
4791396Szelenkov@nginx.com        )
4801396Szelenkov@nginx.com
4811396Szelenkov@nginx.com        resps = self.get_resps_sc()
4821396Szelenkov@nginx.com
4831396Szelenkov@nginx.com        self.assertEqual(resps[0], 50, 'unix 0')
4841396Szelenkov@nginx.com        self.assertEqual(resps[1], 50, 'unix 1')
4851396Szelenkov@nginx.com
4861396Szelenkov@nginx.com    def test_upstreams_rr_ipv6(self):
4871396Szelenkov@nginx.com        self.assertIn(
4881396Szelenkov@nginx.com            'success',
4891396Szelenkov@nginx.com            self.conf(
4901396Szelenkov@nginx.com                {
4911396Szelenkov@nginx.com                    "*:7080": {"pass": "upstreams/one"},
492*1445Szelenkov@nginx.com                    "[::1]:7081": {"pass": "routes/one"},
493*1445Szelenkov@nginx.com                    "[::1]:7082": {"pass": "routes/two"},
4941396Szelenkov@nginx.com                },
4951396Szelenkov@nginx.com                'listeners',
4961396Szelenkov@nginx.com            ),
4971396Szelenkov@nginx.com            'configure listeners ipv6',
4981396Szelenkov@nginx.com        )
4991396Szelenkov@nginx.com
5001396Szelenkov@nginx.com        self.assertIn(
5011396Szelenkov@nginx.com            'success',
5021396Szelenkov@nginx.com            self.conf(
503*1445Szelenkov@nginx.com                {"[::1]:7081": {}, "[::1]:7082": {}}, 'upstreams/one/servers'
5041396Szelenkov@nginx.com            ),
5051396Szelenkov@nginx.com            'configure servers ipv6',
5061396Szelenkov@nginx.com        )
5071396Szelenkov@nginx.com
5081396Szelenkov@nginx.com        resps = self.get_resps_sc()
5091396Szelenkov@nginx.com
5101396Szelenkov@nginx.com        self.assertEqual(resps[0], 50, 'ipv6 0')
5111396Szelenkov@nginx.com        self.assertEqual(resps[1], 50, 'ipv6 1')
5121396Szelenkov@nginx.com
5131396Szelenkov@nginx.com    def test_upstreams_rr_servers_empty(self):
5141396Szelenkov@nginx.com        self.assertIn(
5151396Szelenkov@nginx.com            'success',
5161396Szelenkov@nginx.com            self.conf({}, 'upstreams/one/servers'),
5171396Szelenkov@nginx.com            'configure servers empty',
5181396Szelenkov@nginx.com        )
5191441Szelenkov@nginx.com        self.assertEqual(self.get()['status'], 502, 'servers empty')
5201396Szelenkov@nginx.com
5211441Szelenkov@nginx.com        self.assertIn(
5221441Szelenkov@nginx.com            'success',
5231441Szelenkov@nginx.com            self.conf(
5241441Szelenkov@nginx.com                {"127.0.0.1:7081": {"weight": 0}}, 'upstreams/one/servers'
5251441Szelenkov@nginx.com            ),
5261441Szelenkov@nginx.com            'configure servers empty one',
5271441Szelenkov@nginx.com        )
5281441Szelenkov@nginx.com        self.assertEqual(self.get()['status'], 502, 'servers empty one')
5291441Szelenkov@nginx.com        self.assertIn(
5301441Szelenkov@nginx.com            'success',
5311441Szelenkov@nginx.com            self.conf(
5321441Szelenkov@nginx.com                {
5331441Szelenkov@nginx.com                    "127.0.0.1:7081": {"weight": 0},
5341441Szelenkov@nginx.com                    "127.0.0.1:7082": {"weight": 0},
5351441Szelenkov@nginx.com                },
5361441Szelenkov@nginx.com                'upstreams/one/servers',
5371441Szelenkov@nginx.com            ),
5381441Szelenkov@nginx.com            'configure servers empty two',
5391441Szelenkov@nginx.com        )
5401441Szelenkov@nginx.com        self.assertEqual(self.get()['status'], 502, 'servers empty two')
5411396Szelenkov@nginx.com
5421396Szelenkov@nginx.com    def test_upstreams_rr_invalid(self):
5431396Szelenkov@nginx.com        self.assertIn(
5441396Szelenkov@nginx.com            'error', self.conf({}, 'upstreams'), 'upstreams empty',
5451396Szelenkov@nginx.com        )
5461396Szelenkov@nginx.com        self.assertIn(
5471396Szelenkov@nginx.com            'error', self.conf({}, 'upstreams/one'), 'named upstreams empty',
5481396Szelenkov@nginx.com        )
5491396Szelenkov@nginx.com        self.assertIn(
5501396Szelenkov@nginx.com            'error',
5511396Szelenkov@nginx.com            self.conf({}, 'upstreams/one/servers/127.0.0.1'),
5521396Szelenkov@nginx.com            'invalid address',
5531396Szelenkov@nginx.com        )
5541396Szelenkov@nginx.com        self.assertIn(
5551396Szelenkov@nginx.com            'error',
5561396Szelenkov@nginx.com            self.conf({}, 'upstreams/one/servers/127.0.0.1:7081/blah'),
5571396Szelenkov@nginx.com            'invalid server option',
5581396Szelenkov@nginx.com        )
5591441Szelenkov@nginx.com
5601441Szelenkov@nginx.com        def check_weight(w):
5611441Szelenkov@nginx.com            self.assertIn(
5621441Szelenkov@nginx.com                'error',
5631441Szelenkov@nginx.com                self.conf(w, 'upstreams/one/servers/127.0.0.1:7081/weight'),
5641441Szelenkov@nginx.com                'invalid weight option',
5651441Szelenkov@nginx.com            )
5661441Szelenkov@nginx.com        check_weight({})
5671441Szelenkov@nginx.com        check_weight('-1')
5681441Szelenkov@nginx.com        check_weight('1.')
5691441Szelenkov@nginx.com        check_weight('1.1.')
5701441Szelenkov@nginx.com        check_weight('.')
5711441Szelenkov@nginx.com        check_weight('.01234567890123')
5721441Szelenkov@nginx.com        check_weight('1000001')
5731441Szelenkov@nginx.com        check_weight('2e6')
5741396Szelenkov@nginx.com
5751396Szelenkov@nginx.com
5761396Szelenkov@nginx.comif __name__ == '__main__':
5771396Szelenkov@nginx.com    TestUpstreamsRR.main()
578