Skip to content

Coverage test sys.settrace & improve coverage #17538

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

jepler
Copy link
Contributor

@jepler jepler commented Jun 20, 2025

Summary

I noticed that py/profile.c was not covered at all according to codecov, due to the fact it was never enabled in the unix port.

I enabled it, and then added a new test to cover some previously un-covered lines.

Testing

I ran the tests locally and reviewed the coverage of profile.c.

Note: I suspect one or more Windows x64 builds will fail due to improved coverage in this PR, exposing a latent problem.

I wrote a rambling post in the discussions area about passing qstrs to mp_printf. The TL;DR explanation is, there appears to be undefined behavior that occurs when a "small qstr" (uint16_t) argument such as type->name is printed via the %q format specifier, which retrieves a ssize_t value. The specific behavior I saw with x64 msvc on godbolt looked like it would trigger on one specific format string in the core, the repr of frame objects. That's what spurred me to ensure that this code was covered.

If the failure does occur, I'll try to write it up properly as an issue.

@jepler jepler force-pushed the profile-coverage branch from 74fe1d6 to feb117d Compare June 20, 2025 18:33
Copy link

github-actions bot commented Jun 20, 2025

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO_W
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

@jepler jepler force-pushed the profile-coverage branch from feb117d to 986acd2 Compare June 20, 2025 18:57
@jepler
Copy link
Contributor Author

jepler commented Jun 20, 2025

While there are some other errors going on that also leave me scratching my head, the "expected error" happens on Windows CI, specifically "build-vs (x64, Debug, dev, 2017)".

Run python run-tests.py --print-failures
--- D:/a/micropython/micropython/tests/results\misc_sys_settrace_cov.py.exp	2025-06-20 18:41:30.413152600 +0000
+++ D:/a/micropython/micropython/tests/results\misc_sys_settrace_cov.py.out	2025-06-20 18:41:30.413152600 +0000
@@ -1,2 +1,2 @@
-FRAME <frame at 0x\[0-9a-f\]\+, file 'misc/sys_settrace_repr\.py', line \\d\+, code f>
-LASTI \\d\+
+FRAME <frame at 0xe06df4a0, file 'D:/a/micropython/micropython/tests/misc/sys_settrace_cov.py', line 20, code Assertion failed: *q < pool->len, file d:\a\micropython\micropython\py\qstr.c, line 198
+CRASH
\ No newline at end of file

FAILURE D:/a/micropython/micropython/tests/results\misc_sys_settrace_cov.py

@jepler
Copy link
Contributor Author

jepler commented Jun 20, 2025

I can't come up with any good theory as to what's making those unix builds fail. It's also a surprise that it's only ONE of the msvc x64 builds.

@Josverl
Copy link
Contributor

Josverl commented Jun 20, 2025

While working on extending sys.settrace() with additional capabilities I also noticed that the debug builds are not tested across ports. I first noticed Errors first popping up when building an ESP32 locally.

Is there a way to determine coverage locally?

Copy link

codecov bot commented Jun 21, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.23%. Comparing base (09541b7) to head (ec1036f).
Report is 20 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #17538      +/-   ##
==========================================
- Coverage   98.56%   98.23%   -0.34%     
==========================================
  Files         169      171       +2     
  Lines       21950    22142     +192     
==========================================
+ Hits        21636    21751     +115     
- Misses        314      391      +77     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jepler
Copy link
Contributor Author

jepler commented Jun 21, 2025

Yes, you can go through the steps of the unix coverage build locally. In ports/unix, make VARIANT=coverage test_gcov. The build output will finish with a summary of coverage, and a large number of ".gcov" files will be written.

gcov files show coverage on a line by line basis, with "#####" indicating no coverage of the line, "-" indicating no coverage possible, and a number indicating the number of times the line was covered. The format is described in man gcov.

@jepler
Copy link
Contributor Author

jepler commented Jun 21, 2025

The nanbox build were failing like this:

-FRAME <frame at 0x\[0-9a-f\]\+, file '\.\*/sys_settrace_cov.py', line \\d\+, code f>
+FRAME <frame at 0xf4d622e0, file 'misc/sys_settrace_cov.py', line 16, code >

The reason is that a mp_uint_t is passed in to a %d format specifier. But in nanbox, sizeof(mp_uint_t) > sizeof(int), so again there's the UB problem that arises when the promoted argument type does not match the va_arg type.

@jepler jepler force-pushed the profile-coverage branch from e10831b to 74279e3 Compare June 21, 2025 08:13
@jepler
Copy link
Contributor Author

jepler commented Jun 21, 2025

This PR is now read only because it decreases the overall coverage percentage. In reality, it adds coverage to 21751 previously not covered lines.

jepler added 6 commits June 22, 2025 08:11
This side-steps the problem where the output does not match when the
host python version is 3.12.x (as it is on unix ci today).

Signed-off-by: Jeff Epler <[email protected]>
If the fields added for MICROPY_PY_SYS_SETTRACE are not
initialized properly, their value in a thread is
indeterminate. In particular, if the callback is not NULL,
it will be invoked as a function.

Signed-off-by: Jeff Epler <[email protected]>
When MICROPY_PY_SYS_SETTRACE was enabled, a crash was seen in
the qemu_mips build. It seems likely that this was due to these
added fields not being initialized.

Signed-off-by: Jeff Epler <[email protected]>
The argument corresponding to a `%q` specifier must be of type
`qstr`, not a narrower type like `int16_t`. Not ensuring this
caused an assertion error on one Windows x64 build.

The argument corresponding to a `%d` specifier must be of type
`int`, not a potentially-wider type like `mp_uint_t`. Not ensuring
this prevented the function name from being printed on the
unix nanbox build.

Signed-off-by: Jeff Epler <[email protected]>
@jepler jepler force-pushed the profile-coverage branch from 74279e3 to ec1036f Compare June 22, 2025 06:13
@jepler
Copy link
Contributor Author

jepler commented Jun 22, 2025

I've updated the PR so that settrace is only enabled in the coverage build, not the standard build or other variants.

we should consider whether this makes the standard+settrace CI build redundant. I can remove that if desired. the standard+stackless+settrace CI job is probably still useful.

@dpgeorge
Copy link
Member

dpgeorge commented Jul 1, 2025

I've updated the PR so that settrace is only enabled in the coverage build, not the standard build or other variants.

Yes, that's a good idea. As mentioned, it really decreases performance.

OTOH, it's important to get coverage of the settrace code, so enabling it on the coverage build makes sense.

we should consider whether this makes the standard+settrace CI build redundant. I can remove that if desired. the standard+stackless+settrace CI job is probably still useful.

Yes, we can now simplify those CI jobs.

These settrace jobs were added in 0b85b5b . Maybe we can replace those two with just a test for stackless mode? Or at least just remove the standard+settrace CI and keep standard+stackless+settrace (as you suggest).

@Josverl
Copy link
Contributor

Josverl commented Jul 1, 2025

wrt the work on micropython-lib/python-ecosys/debugpy I have been contemplating a few changes as well

  • moving the misc/sys_settrace*.* tests to their own folder: tests/sys_settrace
  • there I have been updating and adding tests to cover the new functionality @andrewleech and I have been working on

That makes it simpler to run that subset during development.

  • debug variant ?
    Also if you have guidance how to test the combination of a sys,settrace firmware together with micropython-lib/python-ecosys/debugpy that would be appreciated. Creating a separate 'settrace/debug' variant seems the simplest approach to me.

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.

4 participants