mirror of
https://github.com/infiniteCable2/panda.git
synced 2026-04-06 14:13:59 +08:00
run all tests in test.sh (#2364)
This commit is contained in:
21
.github/workflows/test.yaml
vendored
21
.github/workflows/test.yaml
vendored
@@ -54,24 +54,3 @@ jobs:
|
|||||||
run: uv pip install --system .
|
run: uv pip install --system .
|
||||||
- name: Verify importing panda
|
- name: Verify importing panda
|
||||||
run: python -c "from panda import Panda"
|
run: python -c "from panda import Panda"
|
||||||
|
|
||||||
|
|
||||||
misra_linter:
|
|
||||||
name: MISRA C:2012 Linter
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 10
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: ./setup.sh
|
|
||||||
- name: Run MISRA C:2012 analysis
|
|
||||||
run: ${{ env.RUN }} "cd tests/misra && ./test_misra.sh"
|
|
||||||
|
|
||||||
misra_mutation:
|
|
||||||
name: MISRA C:2012 Mutation
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 10
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: ./setup.sh
|
|
||||||
- name: MISRA mutation tests
|
|
||||||
run: ${{ env.RUN }} "cd tests/misra && pytest test_mutation.py"
|
|
||||||
|
|||||||
@@ -27,11 +27,10 @@ dev = [
|
|||||||
"cffi",
|
"cffi",
|
||||||
"flaky",
|
"flaky",
|
||||||
"pytest",
|
"pytest",
|
||||||
|
"pytest-xdist",
|
||||||
"pytest-mock",
|
"pytest-mock",
|
||||||
"pytest-timeout",
|
"pytest-timeout",
|
||||||
"pytest-randomly",
|
|
||||||
"ruff",
|
"ruff",
|
||||||
"mypy",
|
|
||||||
"setuptools",
|
"setuptools",
|
||||||
"gcc-arm-none-eabi @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=gcc-arm-none-eabi",
|
"gcc-arm-none-eabi @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=gcc-arm-none-eabi",
|
||||||
"cppcheck @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=cppcheck",
|
"cppcheck @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=cppcheck",
|
||||||
@@ -53,18 +52,6 @@ packages = [
|
|||||||
[tool.setuptools.package-dir]
|
[tool.setuptools.package-dir]
|
||||||
panda = "."
|
panda = "."
|
||||||
|
|
||||||
[tool.mypy]
|
|
||||||
# third-party packages
|
|
||||||
ignore_missing_imports = true
|
|
||||||
|
|
||||||
# helpful warnings
|
|
||||||
warn_redundant_casts = true
|
|
||||||
warn_unreachable = true
|
|
||||||
warn_unused_ignores = true
|
|
||||||
|
|
||||||
# restrict dynamic typing
|
|
||||||
warn_return_any = true
|
|
||||||
|
|
||||||
# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml
|
# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 160
|
line-length = 160
|
||||||
@@ -79,7 +66,7 @@ flake8-implicit-str-concat.allow-multiline=false
|
|||||||
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
|
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
addopts = "-Werror --strict-config --strict-markers --durations=10 --ignore-glob='*.sh' --ignore=tests/misra --ignore=tests/som --ignore=tests/hitl"
|
addopts = "-Werror --strict-config --strict-markers --maxprocesses=8 -nauto --durations=10 --ignore-glob='*.sh' --ignore=tests/som --ignore=tests/hitl"
|
||||||
python_files = "test_*.py"
|
python_files = "test_*.py"
|
||||||
testpaths = [
|
testpaths = [
|
||||||
"tests/"
|
"tests/"
|
||||||
|
|||||||
10
test.sh
10
test.sh
@@ -10,12 +10,6 @@ source ./setup.sh
|
|||||||
# *** build ***
|
# *** build ***
|
||||||
scons
|
scons
|
||||||
|
|
||||||
# *** lint ***
|
# *** lint + test ***
|
||||||
ruff check .
|
ruff check .
|
||||||
mypy python/
|
pytest
|
||||||
|
|
||||||
|
|
||||||
# *** test ***
|
|
||||||
|
|
||||||
# TODO: make randomly work
|
|
||||||
pytest --randomly-dont-reorganize tests/
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import random
|
|||||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||||
ROOT = os.path.join(HERE, "../../")
|
ROOT = os.path.join(HERE, "../../")
|
||||||
|
|
||||||
|
# skip mutating these paths
|
||||||
IGNORED_PATHS = (
|
IGNORED_PATHS = (
|
||||||
'board/obj',
|
'board/obj',
|
||||||
'board/jungle',
|
'board/jungle',
|
||||||
@@ -53,14 +54,16 @@ patterns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
all_files = glob.glob('board/**', root_dir=ROOT, recursive=True)
|
all_files = glob.glob('board/**', root_dir=ROOT, recursive=True)
|
||||||
files = [f for f in all_files if f.endswith(('.c', '.h')) and not f.startswith(IGNORED_PATHS)]
|
files = sorted(f for f in all_files if f.endswith(('.c', '.h')) and not f.startswith(IGNORED_PATHS))
|
||||||
assert len(files) > 50, all(d in files for d in ('board/main.c', 'board/stm32h7/llfdcan.h'))
|
assert len(files) > 50, all(d in files for d in ('board/main.c', 'board/stm32h7/llfdcan.h'))
|
||||||
|
|
||||||
|
# fixed seed so every xdist worker collects the same test params
|
||||||
|
rng = random.Random(len(files))
|
||||||
for p in patterns:
|
for p in patterns:
|
||||||
mutations.append((random.choice(files), p, True))
|
mutations.append((rng.choice(files), p, True))
|
||||||
|
|
||||||
# TODO: remove sampling once test_misra.sh is faster
|
# sample to keep CI fast, but always include the no-mutation case
|
||||||
mutations = random.sample(mutations, 2)
|
mutations = [mutations[0]] + rng.sample(mutations[1:], min(2, len(mutations) - 1))
|
||||||
|
|
||||||
@pytest.mark.parametrize("fn, patch, should_fail", mutations)
|
@pytest.mark.parametrize("fn, patch, should_fail", mutations)
|
||||||
def test_misra_mutation(fn, patch, should_fail):
|
def test_misra_mutation(fn, patch, should_fail):
|
||||||
@@ -69,8 +72,16 @@ def test_misra_mutation(fn, patch, should_fail):
|
|||||||
|
|
||||||
# apply patch
|
# apply patch
|
||||||
if fn is not None:
|
if fn is not None:
|
||||||
r = os.system(f"cd {tmp}/panda && sed -i '{patch}' {fn}")
|
fpath = os.path.join(tmp, "panda", fn)
|
||||||
assert r == 0
|
with open(fpath) as f:
|
||||||
|
content = f.read()
|
||||||
|
if patch.startswith("s/"):
|
||||||
|
old, new = patch[2:].rsplit("/g", 1)[0].split("/", 1)
|
||||||
|
content = content.replace(old, new)
|
||||||
|
elif patch.startswith("$a "):
|
||||||
|
content += patch[3:].replace(r"\n", "\n")
|
||||||
|
with open(fpath, "w") as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
# run test
|
# run test
|
||||||
r = subprocess.run("SKIP_TABLES_DIFF=1 panda/tests/misra/test_misra.sh", cwd=tmp, shell=True)
|
r = subprocess.run("SKIP_TABLES_DIFF=1 panda/tests/misra/test_misra.sh", cwd=tmp, shell=True)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ def random_can_messages(n, bus=None):
|
|||||||
|
|
||||||
class TestPandaComms(unittest.TestCase):
|
class TestPandaComms(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
lpp.set_safety_hooks(CarParams.SafetyModel.allOutput, 0)
|
||||||
lpp.comms_can_reset()
|
lpp.comms_can_reset()
|
||||||
|
|
||||||
def test_tx_queues(self):
|
def test_tx_queues(self):
|
||||||
@@ -102,8 +103,6 @@ class TestPandaComms(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
def test_can_send_usb(self):
|
def test_can_send_usb(self):
|
||||||
lpp.set_safety_hooks(CarParams.SafetyModel.allOutput, 0)
|
|
||||||
|
|
||||||
for bus in range(3):
|
for bus in range(3):
|
||||||
with self.subTest(bus=bus):
|
with self.subTest(bus=bus):
|
||||||
for _ in range(100):
|
for _ in range(100):
|
||||||
|
|||||||
Reference in New Issue
Block a user