def test_normal_empty(self, device_value): if device_value is None: pytest.skip("device option is null") for tc_target in [device_value, "--device {}".format(device_value)]: delete_all_rules(tc_target) runner = SubprocessRunner(" ".join([Tc.Command.TCSHOW, tc_target])) expected = ("{" + '"{:s}"'.format(device_value) + ": {" + """ "outgoing": { }, "incoming": { } } }""") print(runner.command_str) runner.run() print_test_result(expected=expected, actual=runner.stdout, error=runner.stderr) assert runner.returncode == 0 assert json.loads(runner.stdout) == json.loads(expected) # smoe test for --color option runner = SubprocessRunner(" ".join( [Tc.Command.TCSHOW, tc_target, "--color"])) assert runner.run() == 0, runner.stderr
def test_dst_net_uniform_latency(self, device_option, dst_host_option, transmitter, pingparser, shaping_algo, delay): if device_option is None: pytest.skip("device option is null") if typepy.is_null_string(dst_host_option): pytest.skip("destination host is null") for tc_target in [device_option, "--device {}".format(device_option)]: delete_all_rules(tc_target) transmitter.destination = dst_host_option # w/o latency tc --- ping_result = transmitter.ping() assert ping_result.returncode == 0 without_tc_rtt_avg = pingparser.parse(ping_result).rtt_avg # w/ latency tc --- runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "--delay {}ms".format(delay), "--shaping-algo {:s}".format(shaping_algo), ])) ping_result = transmitter.ping() assert ping_result.returncode == 0 with_tc_rtt_avg = pingparser.parse(ping_result).rtt_avg # assertion --- rtt_diff = with_tc_rtt_avg - without_tc_rtt_avg assert rtt_diff > (delay * ASSERT_MARGIN) # finalize --- delete_all_rules(device_option)
def test_dst_net_packet_duplicate(self, device_option, dst_host_option, transmitter, pingparser, option, value): if typepy.is_null_string(dst_host_option): pytest.skip("destination host is null") for tc_target in [device_option, "--device {}".format(device_option)]: delete_all_rules(tc_target) transmitter.destination = dst_host_option # w/o packet duplicate tc --- ping_result = transmitter.ping() assert ping_result.returncode == 0 without_tc_duplicate_rate = pingparser.parse( ping_result).packet_duplicate_rate # w/ packet duplicate tc --- runner_helper(" ".join( [Tc.Command.TCSET, tc_target, "{:s} {}".format(option, value)])) ping_result = transmitter.ping() assert ping_result.returncode == 0 with_tc_duplicate_rate = pingparser.parse( ping_result).packet_duplicate_rate # assertion --- duplicate_rate_diff = with_tc_duplicate_rate - without_tc_duplicate_rate assert duplicate_rate_diff > (convert_rate_to_f(value) * ASSERT_MARGIN) # finalize --- delete_all_rules(tc_target)
def test_dst_net_packet_loss(self, device_option, dst_host_option, transmitter, pingparser, option, value): if typepy.is_null_string(dst_host_option): pytest.skip("destination host is null") for tc_target in [device_option, "--device {}".format(device_option)]: delete_all_rules(tc_target) transmitter.destination = dst_host_option # w/o traffic shaping --- ping_result = transmitter.ping() assert ping_result.returncode == 0 without_tc_loss_rate = pingparser.parse( ping_result).packet_loss_rate # w/ traffic shaping --- runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "{:s} {:f}".format(option, value) ])) ping_result = transmitter.ping() assert ping_result.returncode == 0 with_tc_loss_rate = pingparser.parse(ping_result).packet_loss_rate # check packet loss rate --- loss_diff = with_tc_loss_rate - without_tc_loss_rate assert loss_diff > (value * ASSERT_MARGIN) # finalize --- delete_all_rules(tc_target)
def test_smoke_multiple(self, device_value): if device_value is None: pytest.skip("device is null") for device_option in [device_value, "--device {}".format(device_value)]: delete_all_rules(device_option) runner_helper( " ".join( [ Tc.Command.TCSET, device_option, "--delay 100ms --rate 50Kbps --network 192.168.1.2 --change", ] ) ) runner_helper( " ".join( [ Tc.Command.TCSET, device_option, "--delay 100ms --rate 50Kbps --network 192.168.1.3 --change", ] ) ) delete_all_rules(device_option)
def test_smoke(self, tmpdir, device_value, overwrite): if device_value is None: pytest.skip("device option is null") p = tmpdir.join("tcconfig.json") config = make_config(device_value) print("[config]\n{}\n".format(config)) p.write(config) for device_option in [device_value]: delete_all_rules(device_value) command = " ".join( [Tc.Command.TCSET, "--import-setting", str(p), overwrite]) SubprocessRunner(command).run() parser = TcShapingRuleParser( device=device_value, ip_version=4, logger=NullLogger(), tc_command_output=None, is_parse_filter_id=False, ) result = parser.get_tc_parameter() print_test_result(expected=config, actual=result) assert result == json.loads(config) delete_all_rules(device_value)
def test_config_file_smoke(self, tmpdir, device_value, overwrite): if device_value is None: pytest.skip("device option is null") p = tmpdir.join("tcconfig.json") config = ( "{" + '"{:s}"'.format(device_value) + ": {" + """ "outgoing": { "dst-network=192.168.0.10/32, dst-port=8080, protocol=ip": { "delay": "10.0ms", "loss": "0.01%", "rate": "250Kbps", "delay-distro": "2.0ms" }, "src-port=1234, protocol=ip": { "delay": "50.0ms", "rate": "1Gbps" } }, "incoming": { "dst-network=192.168.10.0/24, protocol=ip": { "corrupt": "0.02%", "rate": "1500Kbps" } } } } """ ) print("[config]\n{}\n".format(config)) p.write(config) for device_option in [device_value, "--device {}".format(device_value)]: delete_all_rules(device_value) command = " ".join([Tc.Command.TCSET, "--import-setting", str(p), overwrite]) SubprocessRunner(command).run() parser = TcShapingRuleParser( device=device_value, ip_version=4, logger=NullLogger(), tc_command_output=None, is_parse_filter_id=False, ) result = parser.get_tc_parameter() print_test_result(expected=config, actual=result) assert result == json.loads(config) delete_all_rules(device_value)
def test_src_net_uniform_latency( self, device_option, local_host_option, dst_host_option, transmitter, pingparser, shaping_algo, delay, ): if device_option is None: pytest.skip("device option is null") if typepy.is_null_string(local_host_option): pytest.skip("local host is null") if typepy.is_null_string(dst_host_option): pytest.skip("destination host is null") for tc_target in [device_option, "--device {}".format(device_option)]: delete_all_rules(tc_target) transmitter.destination = dst_host_option # w/o latency tc --- without_tc_rtt_avg = pingparser.parse( transmitter.ping().stdout).rtt_avg # w/o latency tc (exclude network) --- assert (SubprocessRunner(" ".join([ Tc.Command.TCSET, tc_target, "--direction {:s}".format(TrafficDirection.INCOMING), "--exclude-dst-network {:s}".format(local_host_option), "--exclude-src-network {:s}".format(dst_host_option), "--delay {:d}ms".format(delay), "--shaping-algo {:s}".format(shaping_algo), ])).run() == 0) exclude_tc_rtt_avg = pingparser.parse( transmitter.ping().stdout).rtt_avg # assertion --- rtt_diff = exclude_tc_rtt_avg - without_tc_rtt_avg print("w/o tc rtt: {} ms".format(without_tc_rtt_avg)) print("exclude tc rtt: {} ms".format(exclude_tc_rtt_avg)) assert rtt_diff < (delay / 10) # finalize --- delete_all_rules(tc_target)
def test_abnormal(self, monkeypatch, device_option, rate): if device_option is None: pytest.skip("device option is null") for tc_target in [device_option]: monkeypatch.setattr("tcconfig._network._read_iface_speed", lambda x: "1") runner = SubprocessRunner(" ".join( [Tc.Command.TCSET, tc_target, "--rate", rate, "--overwrite"])) assert runner.run() != 0, (runner.command_str, runner.returncode, runner.stderr) # finalize --- delete_all_rules(tc_target)
def test_network( self, device_option, dst_host_option, dst_host_ex_option, transmitter, pingparser, shaping_algo, ): if device_option is None: pytest.skip("device option is null") if any([ typepy.is_null_string(dst_host_option), typepy.is_null_string(dst_host_ex_option) ]): pytest.skip("destination host is null") for tc_target in [device_option, "--device {}".format(device_option)]: delete_all_rules(tc_target) delay = 100 # tc to specific network --- command_list = [ Tc.Command.TCSET, tc_target, "--delay {:d}ms".format(delay), "--dst-network {:s}".format(dst_host_ex_option), "--shaping-algo {:s}".format(shaping_algo), ] assert SubprocessRunner(" ".join(command_list)).run() == 0 # w/o tc network --- transmitter.destination = dst_host_option without_tc_rtt_avg = pingparser.parse( transmitter.ping().stdout).rtt_avg # w/ tc network --- transmitter.destination = dst_host_ex_option with_tc_rtt_avg = pingparser.parse( transmitter.ping().stdout).rtt_avg # assertion --- rtt_diff = with_tc_rtt_avg - without_tc_rtt_avg assert rtt_diff > (delay * ASSERT_MARGIN) # finalize --- delete_all_rules(tc_target)
def test_smoke( self, device_value, rate, delay, delay_distro, loss, corrupt, direction, network, port, overwrite, # is_enable_iptables ): if device_value is None: pytest.skip("device is empty") if is_invalid_param(rate, delay, loss, corrupt): pytest.skip("skip null parameters") for device_option in [ device_value, "--device {}".format(device_value) ]: delete_all_rules(device_value) command = " ".join([ Tc.Command.TCSET, device_option, rate, delay, delay_distro, loss, corrupt, direction, network, port, overwrite, # is_enable_iptables, ]) print("command: {}".format(command)) tcset_proc = SubprocessRunner(command) assert tcset_proc.run() == 0, tcset_proc.stderr delete_all_rules(device_value)
def test_dst_net_latency_distro(self, device_option, dst_host_option, transmitter, pingparser, delay, delay_distro): if typepy.is_null_string(dst_host_option): pytest.skip("destination host is null") for tc_target in [device_option, "--device {}".format(device_option)]: delete_all_rules(tc_target) transmitter.destination = dst_host_option # w/o latency tc --- ping_result = transmitter.ping() assert ping_result.returncode == 0 ping_stats = pingparser.parse(ping_result) without_tc_rtt_avg = ping_stats.rtt_avg without_tc_rtt_mdev = ping_stats.rtt_mdev # w/ latency tc --- runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "--delay", "{:d}ms".format(delay), "--delay-distro", "{:d}ms".format(delay_distro), ])) ping_result = transmitter.ping() assert ping_result.returncode == 0 ping_stats = pingparser.parse(ping_result) with_tc_rtt_avg = ping_stats.rtt_avg with_tc_rtt_mdev = ping_stats.rtt_mdev # assertion --- rtt_diff = with_tc_rtt_avg - without_tc_rtt_avg assert rtt_diff > (delay * ASSERT_MARGIN) rtt_diff = with_tc_rtt_mdev - without_tc_rtt_mdev assert rtt_diff > (delay_distro * ASSERT_MARGIN) # finalize --- delete_all_rules(tc_target)
def test_dst_net_exclude_dst_network(self, device_option, dst_host_option, transmitter, pingparser): if device_option is None: pytest.skip("device option is null") if typepy.is_null_string(dst_host_option): pytest.skip("destination host is null") delay = 100 for tc_target in [device_option]: delete_all_rules(tc_target) transmitter.destination = dst_host_option # w/ latency tc --- runner_helper([ Tc.Command.TCSET, tc_target, "--delay", "{:d}ms".format(delay) ]) ping_result = transmitter.ping() assert ping_result.returncode == 0 with_tc_rtt_avg = pingparser.parse(ping_result).rtt_avg # exclude certain network --- runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "--exclude-dst-network {:s}/24".format( ".".join(dst_host_option.split(".")[:3] + ["0"])), "--delay {:d}ms".format(delay), "--overwrite", ])) without_tc_rtt_avg = pingparser.parse(transmitter.ping()).rtt_avg # assertion --- rtt_diff = with_tc_rtt_avg - without_tc_rtt_avg assert rtt_diff > (delay * ASSERT_MARGIN) # finalize --- delete_all_rules(tc_target)
def test_normal(self, device_value): if device_value is None: pytest.skip("device option is null") delete_all_rules(device_value) tc = TrafficControl( device=device_value, shaping_algorithm="htb", direction=TrafficDirection.INCOMING, netem_param=NetemParameter( device=device_value, bandwidth_rate="200kbps", packet_loss_rate=0, packet_duplicate_rate=0, corruption_rate=0, reordering_rate=0, ), src_network="192.168.3.188", dst_port=5201, ) assert tc.set_shaping_rule() == 0 tc = TrafficControl( device=device_value, shaping_algorithm="htb", direction=TrafficDirection.OUTGOING, netem_param=NetemParameter( device=device_value, bandwidth_rate="1000000kbps", packet_loss_rate=0, packet_duplicate_rate=0, corruption_rate=0, reordering_rate=0, ), dst_network="192.168.3.188", ) assert tc.set_shaping_rule() == 0 result = tcconfig.parser.shaping_rule.TcShapingRuleParser( device=device_value, ip_version=4, logger=NullLogger(), tc_command_output=None, is_parse_filter_id=False, ).get_tc_parameter() expected = json.loads( """\ { "enp0s3": { "outgoing": { "dst-network=192.168.3.188/32, protocol=ip": { "rate": "1Gbps" } }, "incoming": { "src-network=192.168.3.188/32, dst-port=5201, protocol=ip": { "rate": "200Kbps" } } } } """ ) print_test_result(expected=expected, actual=result) assert result == expected
def test_normal_ipv4(self, device_value): if device_value is None: pytest.skip("device option is null") for tc_target in [device_value, "--device {}".format(device_value)]: runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "--delay", "10", "--delay-distro", "2", "--loss", "0.01", "--duplicate", "0.5", "--reorder", "0.2", "--rate", "0.25Kbps", "--network", "192.168.0.10", "--port", "8080", "--overwrite", ])) runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "--delay", "1", "--loss", "1", "--rate", "100Mbit/s", "--network", "192.168.1.0/24", "--add", ])) runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "--delay", "10", "--delay-distro", "2", "--rate", "500Kbit/s", "--direction", "incoming", ])) runner_helper(" ".join([ Tc.Command.TCSET, tc_target, "--delay", "1", "--loss", "0.02", "--duplicate", "0.5", "--reorder", "0.2", "--rate", "0.1Mbit/s", "--network", "192.168.11.0/24", "--port", "80", "--direction", "incoming", "--add", ])) runner = SubprocessRunner(" ".join([Tc.Command.TCSHOW, tc_target])) expected = ("{" + '"{:s}"'.format(device_value) + ": {" + """ "outgoing": { "dst-network=192.168.0.10/32, dst-port=8080, protocol=ip": { "filter_id": "800::800", "delay": "10.0ms", "loss": "0.01%", "duplicate": "0.5%", "reorder": "0.2%", "rate": "248bps", "delay-distro": "2.0ms" }, "dst-network=192.168.1.0/24, protocol=ip": { "filter_id": "800::801", "delay": "1.0ms", "loss": "1%", "rate": "100Mbps" } }, "incoming": { "dst-network=192.168.11.0/24, dst-port=80, protocol=ip": { "filter_id": "800::801", "delay": "1.0ms", "loss": "0.02%", "duplicate": "0.5%", "reorder": "0.2%", "rate": "100Kbps" }, "protocol=ip": { "filter_id": "800::800", "delay": "10.0ms", "delay-distro": "2.0ms", "rate": "500Kbps" } } } }""") runner.run() print_test_result(expected=expected, actual=runner.stdout, error=runner.stderr) assert json.loads(runner.stdout) == json.loads(expected) # smoe test for --color option runner = SubprocessRunner(" ".join( [Tc.Command.TCSHOW, tc_target, "--color"])) assert runner.run() == 0, runner.stderr delete_all_rules(tc_target)
def test_normal(self, device_value): if device_value is None: pytest.skip("device is null") for device_option in [device_value, "--device {}".format(device_value)]: runner_helper( " ".join( [ Tc.Command.TCSET, device_option, "--delay 100ms --rate 50Kbps --network 192.168.1.2 --overwrite", ] ) ) runner_helper( " ".join( [ Tc.Command.TCSET, device_option, "--delay 200.0ms", "--delay-distro 20", "--rate 100Kbps", "--loss 0.01%", "--duplicate 5%", "--reorder 2%", "--network 192.168.1.3", "--add", ] ) ) runner = SubprocessRunner("{:s} {:s}".format(Tc.Command.TCSHOW, device_option)) expected = ( "{" + '"{:s}"'.format(device_value) + ": {" + """ "outgoing": { "dst-network=192.168.1.2/32, protocol=ip": { "filter_id": "800::800", "delay": "100.0ms", "rate": "50Kbps" }, "dst-network=192.168.1.3/32, protocol=ip": { "filter_id": "800::801", "delay": "200.0ms", "loss": "0.01%", "duplicate": "5%", "delay-distro": "20.0ms", "rate": "100Kbps", "reorder": "2%" } }, "incoming": {} } }""" ) runner.run() print_test_result(expected=expected, actual=runner.stdout, error=runner.stderr) assert json.loads(runner.stdout) == json.loads(expected) runner_helper( " ".join( [ Tc.Command.TCSET, device_option, "--delay 300ms", "--delay-distro 30", "--rate 200Kbps", "--loss 0.02%", "--duplicate 5.5%", "--reorder 0.2%", "--network 192.168.1.3", "--change", ] ) ) runner = SubprocessRunner("{:s} {:s}".format(Tc.Command.TCSHOW, device_option)) expected = ( "{" + '"{:s}"'.format(device_value) + ": {" + """ "outgoing": { "dst-network=192.168.1.2/32, protocol=ip": { "filter_id": "800::800", "delay": "100.0ms", "rate": "50Kbps" }, "dst-network=192.168.1.3/32, protocol=ip": { "filter_id": "800::801", "delay": "300.0ms", "loss": "0.02%", "duplicate": "5.5%", "delay-distro": "30.0ms", "rate": "200Kbps", "reorder": "0.2%" } }, "incoming": {} } }""" ) runner.run() print_test_result(expected=expected, actual=runner.stdout, error=runner.stderr) assert json.loads(runner.stdout) == json.loads(expected) # finalize --- delete_all_rules(device_option)