Skip to content

Commit 92017cc

Browse files
polybassagpotter2
authored andcommitted
Add automotive tests to unit test configurations [Ready for merge] (#2233)
* add automotive tests to unit test configurations * try to fix ccp.uts and gm.uts * improve automotive unit tests cleanup * fix ccp.uts timeout check * fix obd scanner.uts
1 parent 99424ea commit 92017cc

File tree

12 files changed

+186
-42
lines changed

12 files changed

+186
-42
lines changed

test/configs/bsd.utsc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
22
"testfiles": [
33
"test/*.uts",
4+
"test/contrib/automotive/*.uts",
5+
"test/contrib/automotive/obd/*.uts",
6+
"test/contrib/automotive/gm/*.uts",
7+
"test/contrib/automotive/bmw/*.uts",
48
"test/contrib/*.uts"
59
],
610
"remove_testfiles": [

test/configs/linux.utsc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
"testfiles": [
33
"test/*.uts",
44
"test/contrib/*.uts",
5+
"test/contrib/automotive/*.uts",
6+
"test/contrib/automotive/obd/*.uts",
7+
"test/contrib/automotive/gm/*.uts",
8+
"test/contrib/automotive/bmw/*.uts",
59
"test/tools/*.uts",
610
"test/tls/tests_tls_netaccess.uts"
711
],

test/configs/solaris.utsc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
22
"testfiles": [
33
"test/*.uts",
4+
"test/contrib/automotive/*.uts",
5+
"test/contrib/automotive/obd/*.uts",
6+
"test/contrib/automotive/gm/*.uts",
7+
"test/contrib/automotive/bmw/*.uts",
48
"test/contrib/*.uts"
59
],
610
"remove_testfiles": [

test/configs/windows.utsc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
"testfiles": [
33
"test\\*.uts",
44
"test\\tls\\tests_tls_netaccess.uts",
5+
"test\\contrib\\automotive\\obd\\*.uts",
6+
"test\\contrib\\automotive\\gm\\*.uts",
7+
"test\\contrib\\automotive\\bmw\\*.uts",
8+
"test\\contrib\\automotive\\*.uts",
59
"test\\contrib\\*.uts"
610
],
711
"remove_testfiles": [

test/configs/windows2.utsc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
22
"testfiles": [
33
"*.uts",
4+
"test\\contrib\\automotive\\obd\\*.uts",
5+
"test\\contrib\\automotive\\gm\\*.uts",
6+
"test\\contrib\\automotive\\bmw\\*.uts",
7+
"test\\contrib\\automotive\\*.uts",
48
"tls\\tests_tls_netaccess.uts",
59
"contrib\\*.uts"
610
],

test/contrib/automotive/ccp.uts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
= Load module
1212

1313
load_contrib("automotive.ccp")
14+
from scapy.contrib.automotive.ccp import CONNECT, DISCONNECT
1415

1516
= Build CRO CONNECT
1617

@@ -887,7 +888,7 @@ load_contrib("cansocket")
887888
iface0 = "vcan0"
888889

889890
= Initialize a virtual CAN interface
890-
~ needs_root linux conf
891+
~ needs_root linux conf vcan_socket
891892
if 0 != call("cansend %s 000#" % iface0, shell=True):
892893
# vcan0 is not enabled
893894
if 0 != call("sudo modprobe vcan", shell=True):
@@ -903,7 +904,7 @@ if 0 != call("cansend %s 000#" % iface0, shell=True):
903904
print("CAN should work now")
904905

905906
= CAN Socket sr1 with dto.ansers(cro) == True
906-
~ needs_root linux
907+
~ needs_root linux vcan_socket
907908

908909
sock1 = CANSocket(iface=can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000), basecls=CCP)
909910
sock2 = CANSocket(iface=can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000))
@@ -936,7 +937,7 @@ sock2.close()
936937

937938

938939
= CAN Socket sr1 with dto.ansers(cro) == False
939-
~ needs_root linux
940+
~ needs_root linux vcan_socket
940941

941942
sock1 = CANSocket(iface=can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000), basecls=CCP)
942943
sock2 = CANSocket(iface=can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000))
@@ -956,6 +957,9 @@ time.sleep(0.1)
956957
gotTimeout = False
957958
try:
958959
dto = sock1.sr1(CCP(identifier=0x700)/CRO(ctr=0x54)/PROGRAM_6(data=b"\x10\x11\x12\x10\x11\x12"), timeout=1)
960+
print(dto)
961+
if dto is None:
962+
gotTimeout = True
959963
except CANSocketTimeoutElapsed as e:
960964
gotTimeout = True
961965

@@ -966,7 +970,7 @@ sock1.close()
966970
sock2.close()
967971

968972
= CAN Socket sr1 with error code
969-
~ needs_root linux
973+
~ needs_root linux vcan_socket
970974

971975
sock1 = CANSocket(iface=can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000), basecls=CCP)
972976
sock2 = CANSocket(iface=can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000))
@@ -995,4 +999,11 @@ assert dto.MTA0_extension == 0xff
995999
assert dto.MTA0_address == 0xffffffff
9961000

9971001
sock1.close()
998-
sock2.close()
1002+
sock2.close()
1003+
1004+
+ Cleanup
1005+
= Delete vcan interfaces
1006+
~ needs_root linux vcan_socket
1007+
1008+
if 0 != call("sudo ip link delete %s" % iface0, shell=True):
1009+
raise Exception("%s could not be deleted" % iface0)

test/contrib/automotive/gm/gmlan.uts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ x.load == b'\x00\x0c\xaa\xbb'
2424
x.service == 0x52
2525

2626
= Craft VIN Packet
27-
x = GMLAN(b'\x5a\x90'+ raw("WOOOJBF35W1042000"))
27+
x = GMLAN(b'\x5a\x90'+ raw(b"WOOOJBF35W1042000"))
2828
x.load == b'WOOOJBF35W1042000'
2929
x.dataIdentifier == 0x90
3030

test/contrib/automotive/obd/scanner.uts

Lines changed: 114 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,118 @@
11
% Regression tests for obd_scan
2-
~ python3_only
2+
~ vcan_socket needs_root linux
33

44
# More information at http://www.secdev.org/projects/UTscapy/
55

6+
+ Configuration
7+
~ conf
68

7-
############
8-
############
9-
+ Load general modules
10-
= Load contribution layer
9+
= Imports
10+
load_layer("can")
11+
import six, subprocess
12+
from subprocess import call
13+
14+
15+
= Definition of constants, utility functions and mock classes
16+
iface0 = "vcan0"
17+
iface1 = "vcan1"
18+
19+
# function to exit when the can-isotp kernel module is not available
20+
ISOTP_KERNEL_MODULE_AVAILABLE = False
21+
def exit_if_no_isotp_module():
22+
if not ISOTP_KERNEL_MODULE_AVAILABLE:
23+
err = "TEST SKIPPED: can-isotp not available"
24+
subprocess.call("printf \"%s\r\n\" > /dev/stderr" % err, shell=True)
25+
warning("Can't test ISOTP native socket because kernel module is not loaded")
26+
exit(0)
27+
28+
29+
= Initialize a virtual CAN interface
30+
if 0 != call("cansend %s 000#" % iface0, shell=True):
31+
# vcan0 is not enabled
32+
if 0 != call("sudo modprobe vcan", shell=True):
33+
raise Exception("modprobe vcan failed")
34+
if 0 != call("sudo ip link add name %s type vcan" % iface0, shell=True):
35+
print("add %s failed: Maybe it was already up?" % iface0)
36+
if 0 != call("sudo ip link set dev %s up" % iface0, shell=True):
37+
raise Exception("could not bring up %s" % iface0)
38+
39+
if 0 != call("cansend %s 000#" % iface0, shell=True):
40+
raise Exception("cansend doesn't work")
41+
42+
if 0 != call("cansend %s 000#" % iface1, shell=True):
43+
# vcan1 is not enabled
44+
if 0 != call("sudo modprobe vcan", shell=True):
45+
raise Exception("modprobe vcan failed")
46+
if 0 != call("sudo ip link add name %s type vcan" % iface1, shell=True):
47+
print("add %s failed: Maybe it was already up?" % iface1)
48+
if 0 != call("sudo ip link set dev %s up" % iface1, shell=True):
49+
raise Exception("could not bring up %s" % iface1)
50+
51+
if 0 != call("cansend %s 000#" % iface1, shell=True):
52+
raise Exception("cansend doesn't work")
53+
54+
print("CAN should work now")
1155

12-
load_contrib('automotive.obd.obd')
1356

14-
+ Configuration of CAN virtual sockets
15-
~ conf command linux
57+
if six.PY3:
58+
from scapy.contrib.cansocket_native import *
59+
else:
60+
from scapy.contrib.cansocket_python_can import *
1661

17-
= Load module
1862

19-
conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': True}
20-
load_contrib('isotp')
63+
if "python_can" in CANSocket.__module__:
64+
import can as python_can
65+
new_can_socket = lambda iface: CANSocket(iface=python_can.interface.Bus(bustype='socketcan', channel=iface, bitrate=250000))
66+
new_can_socket0 = lambda: CANSocket(iface=python_can.interface.Bus(bustype='socketcan', channel=iface0, bitrate=250000), timeout=0.01)
67+
new_can_socket1 = lambda: CANSocket(iface=python_can.interface.Bus(bustype='socketcan', channel=iface1, bitrate=250000), timeout=0.01)
68+
can_socket_string = "-i socketcan -c %s -b 250000" % iface0
69+
else:
70+
new_can_socket = lambda iface: CANSocket(iface)
71+
new_can_socket0 = lambda: CANSocket(iface0)
72+
new_can_socket1 = lambda: CANSocket(iface1)
73+
can_socket_string = "-c %s" % iface0
2174

22-
= Load os
75+
# utility function for draining a can interface, asserting that no packets are there
76+
def drain_bus(iface=iface0, assert_empty=True):
77+
s = new_can_socket(iface)
78+
pkts = s.sniff(timeout=0.1)
79+
if assert_empty:
80+
assert len(pkts) == 0
81+
s.close()
2382

24-
import os
83+
print("CAN sockets should work now")
2584

26-
= Setup vcan0
27-
~ needs_root
2885

29-
bashCommand = "/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'"
30-
0 == os.system(bashCommand)
86+
= Verify that a CAN socket can be created and closed
87+
s = new_can_socket(iface0)
88+
s.close()
89+
90+
91+
= Check if can-isotp and can-utils are installed on this system
92+
p = subprocess.Popen('lsmod | grep "^can_isotp"', stdout=subprocess.PIPE, shell=True)
93+
if p.wait() == 0:
94+
if b"can_isotp" in p.stdout.read():
95+
p = subprocess.Popen("isotpsend -s1 -d0 %s" % iface0, stdin=subprocess.PIPE, shell=True)
96+
p.stdin.write(b"01")
97+
p.stdin.close()
98+
r = p.wait()
99+
if r == 0:
100+
ISOTP_KERNEL_MODULE_AVAILABLE = True
101+
102+
103+
+ Syntax check
104+
105+
= Import isotp
106+
conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}
107+
load_contrib("isotp")
108+
109+
110+
############
111+
############
112+
+ Load general modules
113+
= Load contribution layer
114+
115+
load_contrib('automotive.obd.obd')
31116

32117
+ Load OBD_scan
33118
= imports
@@ -61,10 +146,6 @@ s3_queue.put(s3)
61146
+ Simulate scanner
62147
~ linux needs_root
63148

64-
= Create socket
65-
66-
socket = ISOTPSocket("vcan0", 0x7e0, 0x7e8, basecls=OBD, padding=True)
67-
68149
= Create responder
69150
# Ensures the responder is running before sending the first request
70151
ready = Event()
@@ -82,34 +163,32 @@ class MockResponder(Thread):
82163
resp = s3_queue.get()
83164
sock.send(resp)
84165
def run(self):
85-
with ISOTPSocket("vcan0", 0x7e8, 0x7e0, basecls=OBD, padding=True) as sock:
166+
with ISOTPSocket(new_can_socket(iface0), 0x7e8, 0x7e0, basecls=OBD, padding=True) as sock:
86167
ready.set()
87168
while not self._stopped.is_set() or not (s1_queue.empty() and s3_queue.empty()):
88-
sniff(opened_socket=sock,
89-
timeout=0.2,
90-
store=False,
91-
prn=lambda p: self.process_request(p, sock))
169+
sniff(opened_socket=sock, timeout=0.2, store=False, prn=lambda p: self.process_request(p, sock))
92170
def stop(self):
93171
self._stopped.set()
94172

95173
responder = MockResponder()
96174
responder.start()
97175

98176
= Get ids
99-
all_ids_set = set(range(1, 256))
100-
supported_ids = _supported_id_numbers(socket, 0.1, OBD_S01, 'pid', False)
101-
unsupported_ids = all_ids_set - supported_ids
177+
with ISOTPSocket(new_can_socket(iface0), 0x7e0, 0x7e8, basecls=OBD, padding=True) as socket:
178+
all_ids_set = set(range(1, 256))
179+
supported_ids = _supported_id_numbers(socket, 0.1, OBD_S01, 'pid', False)
180+
unsupported_ids = all_ids_set - supported_ids
102181

103182
= Run scanner
104183
# timeout to avoid a deadlock if the test which sets this event fails
105-
ready.wait(timeout=5)
106-
data = obd_scan(socket, 0.1, True, True, False)
107-
dtc = data[0]
108-
supported = data[1]
109-
unsupported = data[2]
184+
with ISOTPSocket(new_can_socket(iface0), 0x7e0, 0x7e8, basecls=OBD, padding=True) as socket:
185+
ready.wait(timeout=5)
186+
data = obd_scan(socket, 0.1, True, True, False)
187+
dtc = data[0]
188+
supported = data[1]
189+
unsupported = data[2]
110190

111191
= Cleanup
112-
socket.close()
113192
responder.stop()
114193
if 0 != call("sudo ip link delete vcan0", shell=True):
115194
raise Exception("vcan0 could not be deleted")

test/contrib/cansocket_native.uts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,4 +757,13 @@ sock0.close()
757757
sock1.close()
758758

759759
threadSender.join()
760-
threadBridge.join()
760+
threadBridge.join()
761+
762+
= Delete vcan interfaces
763+
~ needs_root linux vcan_socket
764+
765+
if 0 != call("sudo ip link delete %s" % "vcan0", shell=True):
766+
raise Exception("%s could not be deleted" % "vcan0")
767+
768+
if 0 != call("sudo ip link delete %s" % "vcan1", shell=True):
769+
raise Exception("%s could not be deleted" % "vcan1")

test/contrib/cansocket_python_can.uts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,3 +776,11 @@ len(packetsVCan1) == 5
776776
sock0.close()
777777
sock1.close()
778778

779+
= Delete vcan interfaces
780+
~ needs_root linux vcan_socket
781+
782+
if 0 != call("sudo ip link delete %s" % "vcan0", shell=True):
783+
raise Exception("%s could not be deleted" % "vcan0")
784+
785+
if 0 != call("sudo ip link delete %s" % "vcan1", shell=True):
786+
raise Exception("%s could not be deleted" % "vcan1")

0 commit comments

Comments
 (0)