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

Make easier getting coverage data for devices #63826

Merged
merged 3 commits into from
Oct 25, 2023

Conversation

nordic-piks
Copy link
Collaborator

@nordic-piks nordic-piks commented Oct 11, 2023

The idea is to enable easy coverage data gathering for tests executed on devices.
Most devices do not have coverage support enabled by default, yet they can obtain coverage for some tests.
From now coverage can be enabled like this:
./zephyr/scripts/twister -T xxx --coverage --platform nrf52840dk_nrf52840 --device-testing --device-serial /dev/ttyACM0 ----extra-args CONFIG_FORCE_COVERAGE=y

There is also possible optimization of the coverage data dump process i.e.
not using an additional buffer to collect gcda data, instead print them directly on the console.
This can be achieved by adding:
--extra-args CONFIG_COVERAGE_GCOV_HEAP_SIZE=0
This allows reduction of used RAM, thus more gcov data can fit the memory.

Regardless of used buffer size, there is another optimization added:
reduced size of data sent on console - no space between hex characters.

An error can occur when getting coverage from the console - received data may be corrupted.
In that case, report failures but continue to process valid data.
Include the status of coverage data processing in the twister return code.

EDIT:
Useful example of how to run Twister and get a sample coverage report from a device:
./zephyr/scripts/twister --ninja --inline-logs --outdir twister-build --jobs 1 -T zephyr/samples/hello_world --coverage --platform nrf52840dk_nrf52840 --coverage-tool gcovr --device-testing --device-serial /dev/ttyACM0 --extra-args CONFIG_COVERAGE_GCOV_HEAP_SIZE=0 --extra-args CONFIG_FORCE_COVERAGE=y --extra-args CONFIG_MAIN_STACK_SIZE=4096 -v -v

The result will be at twister-build/coverage/index.html

Additionally, please be sure that there is an env variable ZEPHYR_SDK_INSTALL_DIR which points to Zephyr SDK.

Comment on lines 1 to 6
# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

config SHIELD_COVERAGE_SUPPORT
def_bool $(shields_list_contains,coverage_support)
select HAS_COVERAGE_SUPPORT
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the suggestion, I did not know that possibility.
However, when I started to use snippets I found an easier way, just using KCONFIGs directly.
I will stick to that simple solution until more settings do not need to be adjusted to get coverage.

@@ -72,14 +72,6 @@ config COVERAGE_GCOV

endchoice

config COVERAGE_GCOV_HEAP_SIZE
Copy link
Collaborator

Choose a reason for hiding this comment

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

remove this feature totally may not good, as we some time expect to have coverage data dumpped by debugger, without the uart driver. maybe move this to a none-default option?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok.
The code still uses a buffer by default. I added the possibility to set the buffer size to 0, which will lead to dumping data directly to the console.
While I was thinking about your comment I found how a debugger dump can be prepared - https://www.thanassis.space/coverage.html (I did not try it but as the buffer is available, that solution should be possible)

Copy link
Collaborator

Choose a reason for hiding this comment

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

this is the way most coverage tools get coverage result back. so thanks for keep this feature

@nordic-piks nordic-piks force-pushed the coverage_for_target branch 2 times, most recently from 944bc5e to 81ffa98 Compare October 14, 2023 12:06
@nordic-piks
Copy link
Collaborator Author

I see github action (twister build) - https://github.com/zephyrproject-rtos/zephyr/actions/runs/6517518442/job/17702105148?pr=63826 - hanging after "Set up runner", with no obvious reason. How can I deal with that? Can it be simply rerun?
(I expect all CI will be green, other similar actions were green)

hakehuang
hakehuang previously approved these changes Oct 18, 2023
@nordic-piks
Copy link
Collaborator Author

During review I got question about exact command to execute testing with coverage - here there is:
./zephyr/scripts/twister --ninja --inline-logs --outdir twister-build --jobs 1 -T zephyr/samples/hello_world --coverage --platform nrf52840dk_nrf52840 --coverage-tool gcovr --device-testing --device-serial /dev/ttyACM0 --extra-args CONFIG_COVERAGE_GCOV_HEAP_SIZE=0 --extra-args CONFIG_FORCE_COVERAGE=y -v -v --extra-args CONFIG_MAIN_STACK_SIZE=4096

There result will be at twister-build/coverage/index.html

@gopiotr
Copy link
Collaborator

gopiotr commented Oct 19, 2023

During review I got question about exact command to execute testing with coverage - here there is: ./zephyr/scripts/twister --ninja --inline-logs --outdir twister-build --jobs 1 -T zephyr/samples/hello_world --coverage --platform nrf52840dk_nrf52840 --coverage-tool gcovr --device-testing --device-serial /dev/ttyACM0 --extra-args CONFIG_COVERAGE_GCOV_HEAP_SIZE=0 --extra-args CONFIG_FORCE_COVERAGE=y -v -v --extra-args CONFIG_MAIN_STACK_SIZE=4096

There result will be at twister-build/coverage/index.html

Thanks for sharing this. Please change PR description, because I believe, that most of reviewers start from reading PR description and testing basing on information from this. Another useful tip is necessity of exporting ZEPHYR_SDK_INSTALL_DIR variable with a path to Zephyr SDK. Without this Twister cannot find proper path to gcov tool and raises "not saying much" error like:

  File "/home/redbeard/zephyrproject/zephyr/scripts/pylib/twister/twisterlib/coverage.py", line 116, in generate
    ret = self._generate(outdir, coveragelog)
  File "/home/redbeard/zephyrproject/zephyr/scripts/pylib/twister/twisterlib/coverage.py", line 233, in _generate
    subprocess.call(["gcovr", "-r", self.base_dir, "--gcov-executable",
  File "/usr/lib/python3.8/subprocess.py", line 340, in call
    with Popen(*popenargs, **kwargs) as p:
  File "/usr/lib/python3.8/subprocess.py", line 858, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1639, in _execute_child
    self.pid = _posixsubprocess.fork_exec(
TypeError: expected str, bytes or os.PathLike object, not NoneType

gopiotr
gopiotr previously approved these changes Oct 19, 2023
Copy link
Collaborator

@gopiotr gopiotr left a comment

Choose a reason for hiding this comment

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

Looks good to me - I believe that this can be very useful especially for measuring coverage in driver tests. I don't want to stop or delay this feature, but I think that it could be helpful for potential users, if some information about measuring coverage on real devices will be placed in documentation here:
https://docs.zephyrproject.org/latest/develop/test/coverage.html

@nordic-piks
Copy link
Collaborator Author

During review I got question about exact command to execute testing with coverage - here there is: ./zephyr/scripts/twister --ninja --inline-logs --outdir twister-build --jobs 1 -T zephyr/samples/hello_world --coverage --platform nrf52840dk_nrf52840 --coverage-tool gcovr --device-testing --device-serial /dev/ttyACM0 --extra-args CONFIG_COVERAGE_GCOV_HEAP_SIZE=0 --extra-args CONFIG_FORCE_COVERAGE=y -v -v --extra-args CONFIG_MAIN_STACK_SIZE=4096
There result will be at twister-build/coverage/index.html

Thanks for sharing this. Please change PR description, because I believe, that most of reviewers start from reading PR description and testing basing on information from this. Another useful tip is necessity of exporting ZEPHYR_SDK_INSTALL_DIR variable with a path to Zephyr SDK. Without this Twister cannot find proper path to gcov tool and raises "not saying much" error like:

  File "/home/redbeard/zephyrproject/zephyr/scripts/pylib/twister/twisterlib/coverage.py", line 116, in generate
    ret = self._generate(outdir, coveragelog)
  File "/home/redbeard/zephyrproject/zephyr/scripts/pylib/twister/twisterlib/coverage.py", line 233, in _generate
    subprocess.call(["gcovr", "-r", self.base_dir, "--gcov-executable",
  File "/usr/lib/python3.8/subprocess.py", line 340, in call
    with Popen(*popenargs, **kwargs) as p:
  File "/usr/lib/python3.8/subprocess.py", line 858, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1639, in _execute_child
    self.pid = _posixsubprocess.fork_exec(
TypeError: expected str, bytes or os.PathLike object, not NoneType

Thanks, updated the PR description with both information.

@fabiobaltieri fabiobaltieri added this to the v3.6.0 milestone Oct 19, 2023
golowanow
golowanow previously approved these changes Oct 19, 2023

config COVERAGE_DUMP
bool "Dump coverage data on exit"
depends on COVERAGE_GCOV
help
Dump collected coverage information to console on exit.

config FORCE_COVERAGE
Copy link
Member

Choose a reason for hiding this comment

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

why do we need this if you can just set 'CONFIG_HAS_COVERAGE_SUPPORT'?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the question ;)
That was actually my first attempt, which failed as this config cannot be directly modified:
https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_HAS_COVERAGE_SUPPORT

I decided to add another config that influences HAS_COVERAGE_SUPPORT to describe my intention clearly:
force coverage data generation knowing that it is not supported by design by this platform.
I agree with the current design, that this config is a property of the platform, not an on/off feature.

Do you have suggestions on how this can be implemented differently?
There are already multiple platforms that have this property, I did not want to influence them.

Copy link
Member

Choose a reason for hiding this comment

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

ok, with FORCE_COVERAGE, HAS_COVERAGE_SUPPORT will have no meaning, so, my suggestion is to expand the help message for th is kconfig saying that there is no guarantee coverage data will be produced and that things might fail, etc.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, added more information in the help message + rebased.

When there is no buffer for gcov hex data,
dump them directly to console.
This saves RAM which can be used to hold more gcov data.

Reduce number of gcov hex data send by console -
do not send space between every two digits.

Signed-off-by: Piotr Kosycarz <piotr.kosycarz@nordicsemi.no>
When coverage is enabled, gather console logs longer
to receive gcov data which are send after test output.

Signed-off-by: Piotr Kosycarz <piotr.kosycarz@nordicsemi.no>
Do not break processing when incorrect coverage data are received.
Instead, report failures but still process valid data.

Include coverage processing status within twister retrun code.

Signed-off-by: Piotr Kosycarz <piotr.kosycarz@nordicsemi.no>
@carlescufi carlescufi merged commit 8c5a15a into zephyrproject-rtos:main Oct 25, 2023
24 checks passed
@nordic-piks nordic-piks deleted the coverage_for_target branch October 25, 2023 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Shields Shields (add-on boards) area: Testsuite Testsuite area: Twister Twister
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants