Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to filter testsuite roots #84225

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

nordic-piks
Copy link
Collaborator

@nordic-piks nordic-piks commented Jan 20, 2025

This PR contains 2 changes: for twister and test_plan (the one used at CI for test scope selection).

For twister, it adds a new parameter --testsuite-exclude-path which can be used to exclude the test suite path from
discovering tests (base on --testsuite-root).
So you can use --testsuite-root tests --testsuite-exclude-path "*tests/kernel*" --testsuite-exclude-path "*tests/lib*" to run all tests except those in the tests/kernel and tests/lib paths.
This can be useful to limit the number of executed tests (e.g. if it is known that nothing related to these tests has changed).

For test_plan, an option is added to include the relationship between test suite paths and modified files in the test scope selection process. The new way works almost the same as filtering by tags, but it filters by test suite paths. The relationship to the modified files is the same i.e. if the PR does not modify the specified files/paths, the test suite path is removed from execution.

Test suite path based filtering has several advantages:

  • There is no need to tag every test. Most of the tests are not tagged, so they cannot be easily excluded (which limits the ability to filter on Zephyr and downstream (forked Zephyr repositories)).
  • Test suite path-based approach is easily extensible - just one file change. It can be easily overwritten downstream with custom configuration.
  • Tag-based filtering approach may result in unintentionally skipped tests if multiple tags are added to the test and only one of them is filtered out by test_plan.

The downside may be that if you add a new test and its path is already listed in excludes, it will not be automatically executed. The opposite is true for tags, if the new test does not have one, it will not be filtered out.

Tag-based filtering and test suite path filtering can be used together or separately.

The scripts/ci/testsuite_excludes.yaml has example content (but valid), I plan to extend it for all tests and samples (not at this PR). If wanted, I can share that dependency list so it can be used for zephyr CI.

This PR does not affect test scope selection used currently at zephyr CI! (new filtering is not enabled there).

@nordic-piks nordic-piks force-pushed the allow_to_filter_testsuite_roots branch 2 times, most recently from c1ef16f to 6700fd7 Compare January 20, 2025 10:05
@nordic-piks nordic-piks marked this pull request as ready for review January 20, 2025 10:56
@nordic-piks nordic-piks requested a review from PerMac January 20, 2025 10:56
@nordic-piks nordic-piks requested a review from golowanow January 20, 2025 10:56
@zephyrbot zephyrbot added the area: Twister Twister label Jan 20, 2025
hakehuang
hakehuang previously approved these changes Jan 21, 2025
hakehuang
hakehuang previously approved these changes Jan 22, 2025
gchwier
gchwier previously approved these changes Jan 22, 2025
Copy link
Member

@nashif nashif left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excluding tests by path is not as clean as you think, using tags, even if flawed in some areas is much more granular and accurate. The goal was to move to more granular and test identifier based filtering, which is more accurate. Initial step was done in the maintainer file:

- kernel
and there some work in progress to move to this model and drop tag based filtering in test plan generation.

First commit in this PR can be considered, but changes to test_plan IMO need some more thought and coordination.

@nashif
Copy link
Member

nashif commented Jan 22, 2025

  • There is no need to tag every test. Most of the tests are not tagged, so they cannot be easily excluded (which limits the ability to filter on Zephyr and downstream (forked Zephyr repositories)).

what tests are not tagged? AFAIK tagging is almost everywhere, we have too much tagging if you ask me.

  • Tag-based filtering approach may result in unintentionally skipped tests if multiple tags are added to the test and only one of them is filtered out by test_plan.

same applies for path based filtering, there is no easy way to match a code change to the tests related to this code. You are making an assumption that the test tree structure is complete and accurate but that is not the case, same issue with tagging.

@nordic-piks
Copy link
Collaborator Author

Excluding tests by path is not as clean as you think, using tags, even if flawed in some areas is much more granular and accurate. The goal was to move to more granular and test identifier based filtering, which is more accurate. Initial step was done in the maintainer file:

- kernel

and there some work in progress to move to this model and drop tag based filtering in test plan generation.
First commit in this PR can be considered, but changes to test_plan IMO need some more thought and coordination.

IMHO, test path filtering gives more freedom how to set scope and dependencies.
Maybe my example was not good in case of granularity as I added very general rules:

"*tests/kernel*":
  files:
    - kernel/
    - arch/
    - tests/kernel/

"*tests/posix*":
  files:
    - lib/posix/
    - tests/posix

To get more granularity you can write more specific paths and dependencies - which can be similar to the style of MAINTAINERS.yml:

"*tests/drivers/adc*":
 files:
   - drivers/adc/
   - tests/drivers/adc/

"*tests/drivers/audio*":
 files:
   - drivers/audio/
   - tests/drivers/audio/

This is similar if you want to use tags in granular way.

I wrote about freedom as if you for some reason want to have more general approach, you can do like this (nordic example):

"*tests/drivers/*":
  files:
    - modules/hal/nordic/
    - tests/drivers/
    - zephyr/drivers/

This is harder to do that with tags.

Thank you for that MAINTAINERS.yml mention, that will give me more inspiration about dependencies.

and there some work in progress to move to this model and drop tag based filtering in test plan generation.

Do you have some PR or proposal? Just wanted to have a look how it is designed.

First commit in this PR can be considered, but changes to test_plan IMO need some more thought and coordination.

Regarding changes in test_plan, I intentionally made it optional, there is no test path filtering enable by default or in the zephyr CI. My idea was if someone want to use that kind of filtering, it will provide its own configuration file.
Please accept this new option.

As I look more on MAINTAINERS.yml I see that there is a way to connect tests (by test suite name?):

  tests:
    - libraries.cmsis_dsp

and files:

  files:
    - modules/cmsis-dsp/
    - tests/benchmarks/cmsis_dsp/
    - tests/lib/cmsis_dsp/

Can test_plan already parse that or is there work to do so?
As I look at this, this will also solve my problem.

Still I would vote for my PR so that rules can be adjusted in the downstream.

@nordic-piks
Copy link
Collaborator Author

  • There is no need to tag every test. Most of the tests are not tagged, so they cannot be easily excluded (which limits the ability to filter on Zephyr and downstream (forked Zephyr repositories)).

what tests are not tagged? AFAIK tagging is almost everywhere, we have too much tagging if you ask me.

Indeed, I was wrong regarding tags, sorry for that.

  • Tag-based filtering approach may result in unintentionally skipped tests if multiple tags are added to the test and only one of them is filtered out by test_plan.

same applies for path based filtering, there is no easy way to match a code change to the tests related to this code. You are making an assumption that the test tree structure is complete and accurate but that is not the case, same issue with tagging.

I am aware that with hardcoding dependencies I take a risk that they will be not accurate. But with benefit of having much faster CI I can accept that risk and act accordingly when regression happens.
However I do my best to make those dependencies. My approach is to generate dependencies for each test and then gather them into groups (originally it was tags, now I want to have specific test paths).
To generate dependencies I run all tests but in shorter way (example with nordic platforms, but I do also --integration separately):

./zephyr/scripts/twister -T zephyr/tests/ -T zephyr/sample --platform native_sim --platform nrf52840dk/nrf52840 --platform nrf54l15dk/nrf54l15/cpuapp --cmake-only

--cmake-only is the option which makes this process faster.

This will create the whole output structure and at each test folder there will be file compile_commands.json which list all the .c files used for compilation (+ include paths - there is whole compiler invocation).
I do parse those files and merge it (semi-automatically) into dependencies list.

[
{
  "directory": "twister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general",
  "command": "/usr/bin/gcc -DKERNEL -DK_HEAP_MEM_POOL_SIZE=0 -DTC_RUNID=14b6fde4ee52ed5d300299f930d3bcc5 -D__ZEPHYR__=1 -Itwister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general/zephyr/include/generated/zephyr -Izephyr/include -Itwister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general/zephyr/include/generated -Izephyr/soc/native/inf_clock -Izephyr/boards/native/native_sim -Izephyr/scripts/native_simulator/common/src/include -Izephyr/scripts/native_simulator/native/src/include -Izephyr/subsys/testsuite/include -Izephyr/subsys/testsuite/coverage -Izephyr/subsys/testsuite/ztest/include -Izephyr/subsys/bluetooth -Inrf/include -Inrf/tests/include -Imodules/crypto/tinycrypt/lib/include -Ifind-my/include -Os -DNDEBUG -fno-strict-aliasing -Werror -Os -imacros twister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general/zephyr/include/generated/zephyr/autoconf.h -fno-common -g -gdwarf-4 -fdiagnostics-color=always -Wall -Wformat -Wformat-security -Wno-format-zero-length -Wdouble-promotion -Wno-pointer-sign -Wpointer-arith -Wexpansion-to-defined -Wno-unused-but-set-variable -Werror=implicit-int -fno-pic -fno-pie -fno-asynchronous-unwind-tables -fno-reorder-functions --param=min-pagesize=0 -fno-defer-pop -fmacro-prefix-map=zephyr/tests/bluetooth/bluetooth=CMAKE_SOURCE_DIR -fmacro-prefix-map=zephyr=ZEPHYR_BASE -ffunction-sections -fdata-sections -m32 -msse2 -mfpmath=sse -fvisibility=hidden -fno-freestanding -std=c11 -o CMakeFiles/app.dir/src/bluetooth.c.obj -c zephyr/tests/bluetooth/bluetooth/src/bluetooth.c",
  "file": "zephyr/tests/bluetooth/bluetooth/src/bluetooth.c"
},
{
  "directory": "twister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general",
  "command": "/usr/bin/gcc -DKERNEL -DK_HEAP_MEM_POOL_SIZE=0 -DTC_RUNID=14b6fde4ee52ed5d300299f930d3bcc5 -D__ZEPHYR__=1 -Izephyr/kernel/include -Izephyr/arch/posix/include -Itwister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general/zephyr/include/generated/zephyr -Izephyr/include -Itwister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general/zephyr/include/generated -Izephyr/soc/native/inf_clock -Izephyr/boards/native/native_sim -Izephyr/scripts/native_simulator/common/src/include -Izephyr/scripts/native_simulator/native/src/include -Izephyr/subsys/testsuite/include -Izephyr/subsys/testsuite/coverage -Izephyr/subsys/testsuite/ztest/include -Izephyr/subsys/bluetooth -Inrf/include -Inrf/tests/include -Imodules/crypto/tinycrypt/lib/include -Ifind-my/include -Os -DNDEBUG -fno-strict-aliasing -Werror -Os -imacros twister-build/native_sim/tests/bluetooth/bluetooth/bluetooth.general/zephyr/include/generated/zephyr/autoconf.h -fno-common -g -gdwarf-4 -fdiagnostics-color=always -Wall -Wformat -Wformat-security -Wno-format-zero-length -Wdouble-promotion -Wno-pointer-sign -Wpointer-arith -Wexpansion-to-defined -Wno-unused-but-set-variable -Werror=implicit-int -fno-pic -fno-pie -fno-asynchronous-unwind-tables -fno-reorder-functions --param=min-pagesize=0 -fno-defer-pop -fmacro-prefix-map=zephyr/tests/bluetooth/bluetooth=CMAKE_SOURCE_DIR -fmacro-prefix-map=zephyr=ZEPHYR_BASE -ffunction-sections -fdata-sections -m32 -msse2 -mfpmath=sse -fvisibility=hidden -fno-freestanding -std=c11 -o zephyr/CMakeFiles/zephyr.dir/lib/heap/heap.c.obj -c zephyr/lib/heap/heap.c",
  "file": "zephyr/lib/heap/heap.c"
}
]

@nordic-piks nordic-piks requested a review from nashif January 23, 2025 07:05
Copy link
Member

@PerMac PerMac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM and works as described, just a minor nit to fix

@@ -443,6 +464,9 @@ def parse_args():
"the file need to correspond to the test scenarios names as in "
"corresponding tests .yaml files. These scenarios "
"will be skipped with quarantine as the reason.")
parser.add_argument('--testsuite-excludes-def',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe consider changing this name to something more direct, e.g. --testsuite-excludes-file? it took me some time to figure out what this variable is responsible for from the code and only reading its description sorted it out.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed, thanks :)

Allow to exclude specific paths from testsuite roots.
It takes testsuite roots and filter out one which matches
provided pattern, accepting Unix shell-style wildcards.

Signed-off-by: Piotr Kosycarz <[email protected]>
Allow to filter out testsuites base on changed files.
This is allow for similar way of excluding tests as for tags,
however now there will be possible to specify paths
for testsuites that should be excluded if certain files were not changed.

Signed-off-by: Piotr Kosycarz <[email protected]>
@nordic-piks nordic-piks dismissed stale reviews from gchwier and hakehuang via 4612909 January 24, 2025 13:22
@nordic-piks nordic-piks force-pushed the allow_to_filter_testsuite_roots branch from ab20aa5 to 4612909 Compare January 24, 2025 13:22
@nordic-piks nordic-piks requested a review from PerMac January 24, 2025 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants