Skip to content

Commit c697a25

Browse files
committed
test(report): respect Bitcoin-only feature boundaries
1 parent e79c6b8 commit c697a25

2 files changed

Lines changed: 63 additions & 3 deletions

File tree

scripts/generate-test-report.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,6 +3243,13 @@ def screenshot_filter(fw_version):
32433243
'test_msg_solana_lut_attestation': '7.15.0',
32443244
}
32453245

3246+
# These modules are mandatory only on the multi-chain product. Their handlers
3247+
# are intentionally absent from KK_BITCOIN_ONLY, so a capability-gated skip is
3248+
# evidence of the product boundary there, not missing release coverage.
3249+
FULL_FEATURE_ONLY_MUST_RUN_MODULES = {
3250+
'test_msg_solana_lut_attestation',
3251+
}
3252+
32463253
def screenshot_audit(fw_version, screenshot_root, junit_path=None):
32473254
"""Which SECTIONS tests DECLARED screens but captured none?
32483255
@@ -3283,7 +3290,7 @@ def screenshot_audit(fw_version, screenshot_root, junit_path=None):
32833290
return (len(missing) == 0, missing)
32843291

32853292

3286-
def validate_junit(fw_version, results):
3293+
def validate_junit(fw_version, results, variant='full'):
32873294
"""Check SECTIONS tests against JUnit results. Returns (passed, failed_list).
32883295
32893296
A test is considered failed if it appears in SECTIONS for this firmware version
@@ -3299,7 +3306,12 @@ def validate_junit(fw_version, results):
32993306
status = _lookup(results, mod, meth)
33003307
if status in ('fail', 'error'):
33013308
failures.append((tid, mod, meth, status))
3302-
elif status == 'skip' and ver_ge(fw_version, MUST_RUN_MODULES.get(mod, '99.0.0')):
3309+
must_run = not (
3310+
variant == 'bitcoin-only' and
3311+
mod in FULL_FEATURE_ONLY_MUST_RUN_MODULES
3312+
)
3313+
if (status == 'skip' and must_run and
3314+
ver_ge(fw_version, MUST_RUN_MODULES.get(mod, '99.0.0'))):
33033315
failures.append((tid, mod, meth, 'skipped-but-required'))
33043316
elif not status:
33053317
failures.append((tid, mod, meth, 'missing'))
@@ -3320,6 +3332,9 @@ def main():
33203332
help='Print pytest -k expression for tests needing screenshots, then exit')
33213333
p.add_argument('--validate-junit', action='store_true',
33223334
help='Validate JUnit results against SECTIONS, exit non-zero on failures')
3335+
p.add_argument('--variant', choices=('full', 'bitcoin-only'),
3336+
default=os.environ.get('KK_FIRMWARE_VARIANT', 'full'),
3337+
help='Product variant whose required report coverage is validated')
33233338
args = p.parse_args()
33243339

33253340
fw = args.fw_version
@@ -3347,7 +3362,7 @@ def main():
33473362
print('ERROR: --validate-junit requires --junit=<path>', file=sys.stderr)
33483363
sys.exit(2)
33493364
results = parse_junit(args.junit)
3350-
ok, failures = validate_junit(fw, results)
3365+
ok, failures = validate_junit(fw, results, args.variant)
33513366
if ok:
33523367
print(f'SECTIONS validation passed: all tests for fw {fw} are pass or skip')
33533368
sys.exit(0)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import importlib.util
2+
import os
3+
import unittest
4+
5+
6+
REPORT_SCRIPT = os.path.join(
7+
os.path.dirname(__file__), '..', 'scripts', 'generate-test-report.py')
8+
SPEC = importlib.util.spec_from_file_location('generate_test_report',
9+
REPORT_SCRIPT)
10+
REPORT = importlib.util.module_from_spec(SPEC)
11+
SPEC.loader.exec_module(REPORT)
12+
13+
14+
def catalog_results_with_solana_lut_skipped():
15+
results = {}
16+
for _, _, min_fw, _, _, tests in REPORT.SECTIONS:
17+
if not REPORT.ver_ge('7.15.0', min_fw):
18+
continue
19+
for _, module, method, _, _, _ in tests:
20+
results['%s::%s' % (module, method)] = 'pass'
21+
for key in list(results):
22+
if key.startswith('test_msg_solana_lut_attestation::'):
23+
results[key] = 'skip'
24+
return results
25+
26+
27+
class TestReportVariantValidation(unittest.TestCase):
28+
29+
def test_full_product_requires_solana_lut_coverage(self):
30+
ok, failures = REPORT.validate_junit(
31+
'7.15.0', catalog_results_with_solana_lut_skipped(), 'full')
32+
self.assertFalse(ok)
33+
self.assertEqual(4, len(failures))
34+
self.assertTrue(all(item[3] == 'skipped-but-required'
35+
for item in failures))
36+
37+
def test_bitcoin_only_accepts_absent_solana_lut_handlers(self):
38+
result = REPORT.validate_junit(
39+
'7.15.0', catalog_results_with_solana_lut_skipped(),
40+
'bitcoin-only')
41+
self.assertEqual((True, []), result)
42+
43+
44+
if __name__ == '__main__':
45+
unittest.main()

0 commit comments

Comments
 (0)