|
| 1 | +"""Tests for software-only platform handling in TR-RTE. |
| 2 | +
|
| 3 | +Spec note: trace-spec added `software-only` as a valid `runtime.platform` |
| 4 | +value for development and CI use. It carries no hardware attestation evidence |
| 5 | +and is therefore only acceptable at Level 0. Level 1+ must reject it with a |
| 6 | +clear message that names the reason (development-mode, not hardware-attested) |
| 7 | +rather than the generic "unknown platform" error. |
| 8 | +
|
| 9 | +Covers: |
| 10 | +- software-only at Level 0 passes TR-RTE-001 |
| 11 | +- software-only at Level 1 fails TR-RTE-001 with a message mentioning "development-mode" |
| 12 | +- software-only at Level 2 fails TR-RTE-001 with a message mentioning "development-mode" |
| 13 | +- software-only is accepted by the JSON Schema (schema enum coverage) |
| 14 | +""" |
| 15 | + |
| 16 | +from __future__ import annotations |
| 17 | + |
| 18 | +import copy |
| 19 | + |
| 20 | +import jsonschema |
| 21 | +import pytest |
| 22 | + |
| 23 | +from trace_tests.modules import tr_rte |
| 24 | +from trace_tests.result import Status |
| 25 | + |
| 26 | +_SOFTWARE_ONLY_TRACE = { |
| 27 | + "runtime": { |
| 28 | + "platform": "software-only", |
| 29 | + "measurement": "sha256:" + "a" * 64, |
| 30 | + } |
| 31 | +} |
| 32 | + |
| 33 | + |
| 34 | +@pytest.mark.parametrize("level", [1, 2]) |
| 35 | +def test_software_only_fails_at_level(level): |
| 36 | + """software-only must fail TR-RTE-001 at Level 1 and Level 2.""" |
| 37 | + findings = tr_rte.check(_SOFTWARE_ONLY_TRACE, level=level) |
| 38 | + platform_findings = [f for f in findings if f.code == "TR-RTE-001"] |
| 39 | + assert platform_findings, "TR-RTE-001 finding expected" |
| 40 | + assert all(f.failed() for f in platform_findings), ( |
| 41 | + f"software-only must fail TR-RTE-001 at Level {level}; got {platform_findings}" |
| 42 | + ) |
| 43 | + |
| 44 | + |
| 45 | +@pytest.mark.parametrize("level", [1, 2]) |
| 46 | +def test_software_only_failure_mentions_development_mode(level): |
| 47 | + """Failure message for software-only must mention 'development-mode', not 'unknown'.""" |
| 48 | + findings = tr_rte.check(_SOFTWARE_ONLY_TRACE, level=level) |
| 49 | + fail_findings = [f for f in findings if f.code == "TR-RTE-001" and f.failed()] |
| 50 | + assert fail_findings, f"Expected TR-RTE-001 FAIL at Level {level}" |
| 51 | + messages = " ".join(f.message.lower() for f in fail_findings) |
| 52 | + assert "development-mode" in messages, ( |
| 53 | + f"TR-RTE-001 failure at Level {level} must mention 'development-mode'; " |
| 54 | + f"got: {[f.message for f in fail_findings]}" |
| 55 | + ) |
| 56 | + assert "unknown" not in messages, ( |
| 57 | + f"TR-RTE-001 failure at Level {level} must not say 'unknown platform'; " |
| 58 | + f"got: {[f.message for f in fail_findings]}" |
| 59 | + ) |
| 60 | + |
| 61 | + |
| 62 | +def test_software_only_passes_at_level0(): |
| 63 | + """software-only must pass TR-RTE-001 at Level 0.""" |
| 64 | + findings = tr_rte.check(_SOFTWARE_ONLY_TRACE, level=0) |
| 65 | + platform_findings = [f for f in findings if f.code == "TR-RTE-001"] |
| 66 | + assert platform_findings, "TR-RTE-001 finding expected" |
| 67 | + assert all(f.passed() for f in platform_findings), ( |
| 68 | + f"software-only must pass TR-RTE-001 at Level 0; got {platform_findings}" |
| 69 | + ) |
| 70 | + |
| 71 | + |
| 72 | +def test_software_only_default_level_passes(): |
| 73 | + """check() with no level argument defaults to Level 0 and passes software-only.""" |
| 74 | + findings = tr_rte.check(_SOFTWARE_ONLY_TRACE) |
| 75 | + platform_findings = [f for f in findings if f.code == "TR-RTE-001"] |
| 76 | + assert platform_findings, "TR-RTE-001 finding expected" |
| 77 | + assert all(f.passed() for f in platform_findings), ( |
| 78 | + f"software-only must pass TR-RTE-001 at default level; got {platform_findings}" |
| 79 | + ) |
| 80 | + |
| 81 | + |
| 82 | +def test_software_only_accepted_by_schema(schema, valid_level0): |
| 83 | + """software-only must be a valid enum value in the JSON Schema.""" |
| 84 | + record = copy.deepcopy(valid_level0) |
| 85 | + record["runtime"]["platform"] = "software-only" |
| 86 | + # Must not raise |
| 87 | + jsonschema.validate(record, schema) |
0 commit comments