% Regression tests for isotpscanner
~ vcan_socket needs_root linux not_pypy automotive_comm scanner


+ Configuration
~ conf

= Imports
with open(scapy_path("test/contrib/automotive/interface_mockup.py")) as f:
    exec(f.read())

ISOTPSocket = ISOTPSoftSocket

from unittest.mock import patch

+ Usage tests

= Test wrong usage

result = subprocess.Popen([sys.executable, "scapy/tools/automotive/isotpscanner.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

std_out, std_err = result.communicate()
if result.returncode:
    print(std_out)
    print(std_err)

assert result.returncode != 0

expected_output = plain_str(b'usage:')
assert expected_output in plain_str(std_err)


= Test show help

result = subprocess.Popen([sys.executable, "scapy/tools/automotive/isotpscanner.py", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
std_out, _ = result.communicate()
expected_output = plain_str(b'Scan for open ISOTP-Sockets.')

assert result.wait() == 0
assert expected_output in plain_str(std_out)


= Test Python2 call

result = subprocess.Popen([sys.executable, "scapy/tools/automotive/isotpscanner.py", "-i", "socketcan", "-c", iface0, "-s", "0x600", "-e", "0x600", "-v", "-n", "0", "-t", "0"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
returncode = result.wait()
expected_output = plain_str(b'Start scan')
std_out, std_err = result.communicate()

assert returncode == 0
assert expected_output in plain_str(std_out)

= Test Python2 call with one python-can arg

result = subprocess.Popen([sys.executable, "scapy/tools/automotive/isotpscanner.py", "-i", "socketcan", "-c", iface0, "-a", "bitrate=500000", "-s", "0x600", "-e", "0x600", "-v", "-n", "0", "-t", "0"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
returncode = result.wait()
expected_output = plain_str(b'Start scan')
std_out, std_err = result.communicate()

assert returncode == 0
assert expected_output in plain_str(std_out)


= Test Python2 call with multiple python-can args

result = subprocess.Popen([sys.executable, "scapy/tools/automotive/isotpscanner.py", "-i", "socketcan", "-c", iface0, "-a", "bitrate=500000 receive_own_messages=True", "-s", "0x600", "-e", "0x600", "-v", "-n", "0", "-t", "0"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
returncode = result.wait()
expected_output = plain_str(b'Start scan')
std_out, std_err = result.communicate()

assert returncode == 0
assert expected_output in plain_str(std_out)

= Test Python2 call with multiple python-can args 2

result = subprocess.Popen([sys.executable, "scapy/tools/automotive/isotpscanner.py", "-i", "socketcan", "-c", iface0, "--python-can_args", "bitrate=500000 receive_own_messages=True", "-s", "0x600", "-e", "0x600", "-v", "-n", "0", "-t", "0"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
returncode = result.wait()
expected_output = plain_str(b'Start scan')
std_out, std_err = result.communicate()

assert returncode == 0
assert expected_output in plain_str(std_out)


+ Scan tests

= Test standard scan

exit_if_no_isotp_module()

drain_bus(iface0)

recv_result = subprocess.Popen(("isotprecv -s 700 -d 600 -l " + iface0).split())
result = subprocess.Popen([sys.executable, "scapy/tools/automotive/isotpscanner.py"] + can_socket_string_list + ["-s", "0x600", "-e", "0x600"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
returncode1 = result.wait()
std_out1, std_err1 = result.communicate()
recv_result.terminate()

print(std_out1)
print(std_err1)

assert returncode1 == 0

expected_output = [b'0x600', b'0x700']
for out in expected_output:
    assert plain_str(out) in plain_str(std_out1)


= Test extended scan

def isotp_scan(sock,  # type: SuperSocket
               scan_range=range(0x7ff + 1),  # type: Iterable[int]
               extended_addressing=False,  # type: bool
               extended_scan_range=range(0x100),  # type: Iterable[int]
               noise_listen_time=2,  # type: int
               sniff_time=0.1,  # type: float
               output_format=None,  # type: Optional[str]
               can_interface=None,  # type: Optional[str]
               extended_can_id=False,  # type: bool
               verbose=False  # type: bool
               ):
    # type: (...) -> Union[str, List[SuperSocket]]
    assert sock is not None
    assert 0x601 in scan_range
    assert 0x602 not in scan_range
    assert extended_addressing == True
    assert 0 in extended_scan_range
    assert 0xff in extended_scan_range
    assert output_format == "text"
    assert verbose == False
    assert extended_can_id == False
    assert "vcan0" in can_interface
    return "Success"

testargs = ["scapy/tools/automotive/isotpscanner.py"] + can_socket_string_list + ["-s", "0x601", "-e", "0x601", "-x"]
with patch.object(sys, "argv", testargs), patch.object(scapy.contrib.isotp, "isotp_scan", isotp_scan):
    from scapy.tools.automotive.isotpscanner import main
    main()


= Test scan with piso flag

def isotp_scan(sock,  # type: SuperSocket
               scan_range=range(0x7ff + 1),  # type: Iterable[int]
               extended_addressing=False,  # type: bool
               extended_scan_range=range(0x100),  # type: Iterable[int]
               noise_listen_time=2,  # type: int
               sniff_time=0.1,  # type: float
               output_format=None,  # type: Optional[str]
               can_interface=None,  # type: Optional[str]
               extended_can_id=False,  # type: bool
               verbose=False  # type: bool
               ):
    # type: (...) -> Union[str, List[SuperSocket]]
    assert sock is not None
    assert 0x601 in scan_range
    assert 0x602 not in scan_range
    assert extended_addressing == True
    assert 0 in extended_scan_range
    assert 0xff in extended_scan_range
    assert output_format == "code"
    assert verbose == False
    assert extended_can_id == False
    assert "vcan0" in can_interface
    return "Success"

testargs = ["scapy/tools/automotive/isotpscanner.py"] + can_socket_string_list + ["-s", "0x601", "-e", "0x601", "-x", "-C"]
with patch.object(sys, "argv", testargs), patch.object(scapy.contrib.isotp, "isotp_scan", isotp_scan):
    from scapy.tools.automotive.isotpscanner import main
    main()


+ Cleanup

= Delete vcan interfaces

assert cleanup_interfaces()
