File: test_cli.py

package info (click to toggle)
2ping 4.5-1.2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 492 kB
  • sloc: python: 3,304; makefile: 44; sh: 4
file content (177 lines) | stat: -rw-r--r-- 6,159 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import locale
import logging
import pytest
import unittest
import unittest.mock

from . import _test_module_init
from twoping import args, cli, utils


class TestCLI(unittest.TestCase):
    bind_addresses = ["127.0.0.1"]
    port = None
    logger = None
    class_args = None

    def setUp(self):
        self.logger = logging.getLogger()
        self.logger.level = logging.DEBUG

    def _client(self, test_flags=None, test_positionals=None, test_stats=True, pairs=1):
        if self.port is None:
            port = -1
        else:
            port = self.port

        flag_args = ["--debug"]
        if self.class_args is not None:
            flag_args += self.class_args
        if test_flags is not None:
            flag_args += test_flags

        positional_args = []
        if test_positionals is not None:
            positional_args += test_positionals

        if "--loopback" not in flag_args:
            flag_args += ["--listen", "--port={}".format(port)]
            for bind_address in self.bind_addresses:
                flag_args.append("--interface-address={}".format(bind_address))
                positional_args.append(bind_address)
        if ("--adaptive" not in flag_args) and ("--flood" not in flag_args):
            flag_args.append("--count=1")
        if not ("--count=1" in flag_args):
            flag_args.append("--interval=5")
        all_args = ["2ping"] + flag_args + positional_args
        self.logger.info("Passed arguments: {}".format(all_args))

        p = cli.TwoPing(args.parse_args(all_args))
        self.logger.info("Parsed arguments: {}".format(p.args))
        self.assertEqual(p.run(), 0)

        for sock_class in p.sock_classes:
            self.assertTrue(sock_class.closed)

        self.assertEqual(len(p.sock_classes), (pairs * 2))
        client_sock_classes = [
            sock_class for sock_class in p.sock_classes if sock_class.is_client
        ]
        self.assertEqual(len(client_sock_classes), pairs)
        sock_class = client_sock_classes[0]

        if not test_stats:
            return sock_class

        self.assertEqual(sock_class.errors_received, 0)
        self.assertEqual(sock_class.lost_inbound, 0)
        self.assertEqual(sock_class.lost_outbound, 0)
        if p.args.count:
            self.assertEqual(sock_class.pings_transmitted, p.args.count)
            self.assertEqual(sock_class.pings_received, p.args.count)
        else:
            self.assertGreaterEqual(
                sock_class.pings_received / sock_class.pings_transmitted, 0.99
            )

        return sock_class

    def test_3way(self):
        sock_class = self._client([])
        self.assertEqual(sock_class.packets_transmitted, 2)
        self.assertEqual(sock_class.packets_received, 1)

    def test_3way_no(self):
        sock_class = self._client(["--no-3way"])
        self.assertEqual(sock_class.packets_transmitted, 1)
        self.assertEqual(sock_class.packets_received, 1)

    @pytest.mark.slow
    def test_adaptive(self):
        sock_class = self._client(["--adaptive", "--deadline=3"])
        self.assertGreaterEqual(sock_class.pings_transmitted, 100)

    @unittest.skipIf(isinstance(utils.AES, ImportError), "Crypto module required")
    def test_encrypt(self):
        self._client(
            ["--encrypt-method=hkdf-aes256-cbc", "--encrypt=S49HVbnJd3fBdDzdMVVw"]
        )

    @pytest.mark.slow
    def test_flood(self):
        sock_class = self._client(["--flood", "--deadline=3"])
        self.assertGreaterEqual(sock_class.pings_transmitted, 100)

    def test_hmac_crc32(self):
        self._client(["--auth-digest=hmac-crc32", "--auth=mc82kJwtXFlhqQSCKptQ"])

    def test_hmac_md5(self):
        self._client(["--auth-digest=hmac-md5", "--auth=rBgRpBfRbF4DkwFQXncz"])

    def test_hmac_sha1(self):
        self._client(["--auth-digest=hmac-sha1", "--auth=qnzTCJHnZXdrxRZ8JjQw"])

    def test_hmac_sha256(self):
        self._client(["--auth-digest=hmac-sha256", "--auth=cc8G2Ssbq4WZRq7H7d5L"])

    def test_hmac_sha512(self):
        self._client(["--auth-digest=hmac-sha512", "--auth=sjk3kqzcSV3XfHJWNstn"])

    def test_invalid_hostname(self):
        with self.assertRaises(OSError):
            self._client([], ["xGkKWDDMnZxCD4XchMnK."])

    def test_monotonic_clock(self):
        self._client(["--send-monotonic-clock"])

    def test_notice(self):
        self._client(["--notice=Notice text"])

    @unittest.skipUnless(
        (locale.getlocale()[1] == "UTF-8"), "UTF-8 environment required"
    )
    def test_notice_utf8(self):
        self._client(["--notice=UTF-8 \u2603"])

    @pytest.mark.slow
    def test_packet_loss(self):
        # There is a small but non-zero chance that packet loss will prevent
        # any investigation replies from getting back to the client sock
        # between the 10 and 15 second mark, causing a test failure.
        # There's an even more minisculely small chance no simulated losses
        # will occur within the test period.
        sock_class = self._client(
            ["--flood", "--deadline=15", "--packet-loss=25"], test_stats=False
        )
        self.assertGreaterEqual(sock_class.pings_transmitted, 100)
        self.assertEqual(sock_class.errors_received, 0)
        self.assertGreater(sock_class.lost_inbound, 0)
        self.assertGreater(sock_class.lost_outbound, 0)

    def test_random(self):
        self._client(["--send-random=32"])

    def test_time(self):
        self._client(["--send-time"])

    def test_module_init(self):
        self.assertTrue(_test_module_init(cli))


class TestCLIInet(TestCLI):
    def test_srv_addresses(self):
        self.bind_addresses = []
        with unittest.mock.patch(
            "twoping.cli.TwoPing.get_srv_hosts", return_value=[("127.0.0.1", -1)]
        ):
            self._client(
                ["--interface-address=127.0.0.1", "--srv"], ["pssPCPkc3XlMTDZhclPV."]
            )


@unittest.skipUnless(hasattr(cli.socket, "AF_UNIX"), "UNIX environment required")
class TestCLILoopback(TestCLI):
    class_args = ["--loopback"]

    def test_loopback_pairs(self):
        self._client(["--loopback-pairs=3"], pairs=3)