Skip to content

Commit 305d4e6

Browse files
authored
Red Panda: add separate CAN FD test to CI (commaai#807)
* initial simple test * linter * ...
1 parent de296d0 commit 305d4e6

File tree

3 files changed

+125
-5
lines changed

3 files changed

+125
-5
lines changed

Jenkinsfile

+17-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ pipeline {
3030
}
3131
}
3232
}
33+
stage('CANFD tests') {
34+
steps {
35+
lock(resource: "pedal", inversePrecedence: true, quantity: 1) {
36+
timeout(time: 10, unit: 'MINUTES') {
37+
script {
38+
sh "docker run --rm --privileged \
39+
--volume /dev/bus/usb:/dev/bus/usb \
40+
--volume /var/run/dbus:/var/run/dbus \
41+
--net host \
42+
${env.DOCKER_IMAGE_TAG} \
43+
bash -c 'cd /tmp/panda && ./board/build_all.sh && JUNGLE=058010800f51363038363036 H7_PANDAS_EXCLUDE=\"080021000c51303136383232\" python ./tests/canfd/test_ci_canfd.py'"
44+
}
45+
}
46+
}
47+
}
48+
}
3349
stage('HITL tests') {
3450
steps {
3551
lock(resource: "pandas", inversePrecedence: true, quantity: 1) {
@@ -40,7 +56,7 @@ pipeline {
4056
--volume /var/run/dbus:/var/run/dbus \
4157
--net host \
4258
${env.DOCKER_IMAGE_TAG} \
43-
bash -c 'cd /tmp/panda && ./board/build_all.sh && PANDAS_JUNGLE=23002d000851393038373731 ./tests/automated/test.sh'"
59+
bash -c 'cd /tmp/panda && ./board/build_all.sh && PANDAS_JUNGLE=23002d000851393038373731 PANDAS_EXCLUDE=\"1d0002000c51303136383232 2f002e000c51303136383232\" ./tests/automated/test.sh'"
4460
}
4561
}
4662
}

tests/automated/helpers.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
GPS_HW_TYPES = [Panda.HW_TYPE_GREY_PANDA, Panda.HW_TYPE_BLACK_PANDA, Panda.HW_TYPE_UNO]
2020
PEDAL_SERIAL = 'none'
2121
JUNGLE_SERIAL = os.getenv("PANDAS_JUNGLE")
22+
PANDAS_EXCLUDE = []
23+
if os.getenv("PANDAS_EXCLUDE"):
24+
PANDAS_EXCLUDE = os.getenv("PANDAS_EXCLUDE").strip().split(" ")
2225

2326
# Enable fault debug
2427
faulthandler.enable(all_threads=False)
@@ -34,10 +37,11 @@ def init_panda_serials():
3437
panda_jungle.set_panda_power(True)
3538
time.sleep(5)
3639
for serial in Panda.list():
37-
p = Panda(serial=serial)
38-
_panda_serials.append((serial, p.get_type()))
39-
p.close()
40-
print('Found', str(len(_panda_serials)), 'pandas')
40+
if serial not in PANDAS_EXCLUDE:
41+
p = Panda(serial=serial)
42+
_panda_serials.append((serial, p.get_type()))
43+
p.close()
44+
print(f"Found {len(_panda_serials)} pandas")
4145
init_panda_serials()
4246

4347
# Panda providers

tests/canfd/test_ci_canfd.py

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import os
2+
import time
3+
import random
4+
import _thread
5+
from collections import defaultdict
6+
from panda import Panda
7+
from panda_jungle import PandaJungle # pylint: disable=import-error
8+
9+
H7_HW_TYPES = [Panda.HW_TYPE_RED_PANDA]
10+
JUNGLE_SERIAL = os.getenv("JUNGLE")
11+
H7_PANDAS_EXCLUDE = [] # type: ignore
12+
if os.getenv("H7_PANDAS_EXCLUDE"):
13+
H7_PANDAS_EXCLUDE = os.getenv("H7_PANDAS_EXCLUDE").strip().split(" ") # type: ignore
14+
15+
#TODO: REMOVE, temporary list of CAN FD lengths, one in panda python lib MUST be used
16+
DLC_TO_LEN = [0,1,2,3,4,5,6,7,8, 12, 16, 20, 24, 32, 48]
17+
18+
_panda_serials = []
19+
20+
def start_heartbeat_thread(p):
21+
def heartbeat_thread(p):
22+
while True:
23+
try:
24+
p.send_heartbeat()
25+
time.sleep(.5)
26+
except Exception:
27+
break
28+
_thread.start_new_thread(heartbeat_thread, (p,))
29+
30+
def panda_init(serial):
31+
p = Panda(serial=serial)
32+
assert p.recover(timeout=30)
33+
start_heartbeat_thread(p)
34+
for bus in range(3):
35+
p.set_can_speed_kbps(bus, 500)
36+
p.set_can_data_speed_kbps(bus, 2000)
37+
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
38+
p.set_power_save(False)
39+
return p
40+
41+
if JUNGLE_SERIAL:
42+
panda_jungle = PandaJungle(JUNGLE_SERIAL)
43+
panda_jungle.set_panda_power(False)
44+
time.sleep(2)
45+
panda_jungle.set_panda_power(True)
46+
time.sleep(4)
47+
#panda_jungle.set_can_enable(0, False)
48+
#panda_jungle.set_can_enable(1, False)
49+
#panda_jungle.set_can_enable(2, False)
50+
51+
for serial in Panda.list():
52+
if serial not in H7_PANDAS_EXCLUDE:
53+
p = Panda(serial=serial)
54+
if p.get_type() in H7_HW_TYPES:
55+
_panda_serials.append(serial)
56+
p.close()
57+
58+
if len(_panda_serials) < 2:
59+
print("Minimum two H7 type pandas should be connected.")
60+
assert False
61+
62+
63+
def canfd_test(p_send, p_recv):
64+
for _ in range(500):
65+
sent_msgs = defaultdict(set)
66+
to_send = []
67+
for _ in range(200):
68+
bus = random.randrange(3)
69+
for dlc in range(len(DLC_TO_LEN)):
70+
address = random.randrange(1, 1<<29)
71+
data = bytes([random.getrandbits(8) for _ in range(DLC_TO_LEN[dlc])])
72+
to_send.append([address, 0, data, bus])
73+
sent_msgs[bus].add((address, data))
74+
75+
p_send.can_send_many(to_send, timeout=0)
76+
77+
while True:
78+
incoming = p_recv.can_recv()
79+
if not incoming:
80+
break
81+
for msg in incoming:
82+
address, _, data, bus = msg
83+
k = (address, bytes(data))
84+
assert k in sent_msgs[bus], f"message {k} was never sent on bus {bus}"
85+
sent_msgs[bus].discard(k)
86+
87+
for bus in range(3):
88+
assert not len(sent_msgs[bus]), f"loop : bus {bus} missing {len(sent_msgs[bus])} messages"
89+
90+
# Set back to silent mode
91+
p_send.set_safety_mode(Panda.SAFETY_SILENT)
92+
p_recv.set_safety_mode(Panda.SAFETY_SILENT)
93+
p_send.set_power_save(True)
94+
p_recv.set_power_save(True)
95+
print("Got all messages intact")
96+
97+
98+
p_send = panda_init(_panda_serials[0])
99+
p_recv = panda_init(_panda_serials[1])
100+
canfd_test(p_send, p_recv)

0 commit comments

Comments
 (0)