Skip to content

Commit 792473b

Browse files
authored
Merge pull request #3 from runtimed/detailed-conformance-reports
Add detailed conformance reports with actionable insights
2 parents 6d6110f + 05d5fd9 commit 792473b

7 files changed

Lines changed: 273 additions & 71 deletions

File tree

.github/workflows/conformance.yml

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595
pattern: report-*
9696
merge-multiple: true
9797

98-
- name: Generate matrix summary
98+
- name: Generate detailed report
9999
run: |
100100
{
101101
echo "## Kernel Conformance Matrix"
@@ -119,6 +119,79 @@ jobs:
119119
echo "| $kernel | $tier1/$tier1_total | $tier2/$tier2_total | $tier3/$tier3_total | $tier4/$tier4_total | $total/$total_tests |"
120120
fi
121121
done
122+
123+
echo ""
124+
echo "---"
125+
echo ""
126+
127+
# Detailed failure breakdown per kernel
128+
for report in reports/*-report.json; do
129+
if [ -f "$report" ]; then
130+
kernel=$(basename "$report" -report.json)
131+
impl=$(jq -r '.implementation // "unknown"' "$report" 2>/dev/null)
132+
lang=$(jq -r '.language // "unknown"' "$report" 2>/dev/null)
133+
protocol=$(jq -r '.protocol_version // "unknown"' "$report" 2>/dev/null)
134+
135+
failures=$(jq '[.results[] | select(.result.status != "pass" and .result.status != "unsupported")] | length' "$report" 2>/dev/null || echo "0")
136+
skipped=$(jq '[.results[] | select(.result.status == "unsupported")] | length' "$report" 2>/dev/null || echo "0")
137+
138+
if [ "$failures" != "0" ] || [ "$skipped" != "0" ]; then
139+
echo "<details>"
140+
echo "<summary><strong>$kernel</strong> ($impl) - $failures failures, $skipped skipped</summary>"
141+
echo ""
142+
echo "**Language:** $lang | **Protocol:** $protocol"
143+
echo ""
144+
145+
if [ "$failures" != "0" ]; then
146+
echo "#### Failures"
147+
echo ""
148+
echo "| Test | Message Type | Likely Source | Reason |"
149+
echo "|------|--------------|---------------|--------|"
150+
jq -r '.results[] | select(.result.status == "fail" or .result.status == "timeout") | "| \(.name) | `\(.message_type)` | \(.result.kind // "unknown") | \(.result.reason // "timeout") |"' "$report" 2>/dev/null
151+
echo ""
152+
fi
153+
154+
if [ "$skipped" != "0" ]; then
155+
echo "#### Skipped (Not Implemented)"
156+
echo ""
157+
jq -r '.results[] | select(.result.status == "unsupported") | "- **\(.name)**: \(.description)"' "$report" 2>/dev/null
158+
echo ""
159+
fi
160+
161+
echo "</details>"
162+
echo ""
163+
fi
164+
fi
165+
done
166+
167+
# Cross-kernel comparison for failing tests
168+
echo "---"
169+
echo ""
170+
echo "### Test Results by Message Type"
171+
echo ""
172+
echo "| Test | Message Type |$(for r in reports/*-report.json; do kernel=$(basename "$r" -report.json); echo -n " $kernel |"; done)"
173+
echo "|------|--------------|$(for r in reports/*-report.json; do echo -n "--------|"; done)"
174+
175+
# Get all unique test names
176+
all_tests=$(jq -r '.results[].name' reports/*-report.json 2>/dev/null | sort -u)
177+
for test in $all_tests; do
178+
msg_type=$(jq -r --arg t "$test" '.results[] | select(.name == $t) | .message_type' reports/*-report.json 2>/dev/null | head -1)
179+
echo -n "| $test | \`$msg_type\` |"
180+
for report in reports/*-report.json; do
181+
if [ -f "$report" ]; then
182+
status=$(jq -r --arg t "$test" '.results[] | select(.name == $t) | .result.status' "$report" 2>/dev/null)
183+
case "$status" in
184+
pass) echo -n " ✅ |" ;;
185+
fail) echo -n " ❌ |" ;;
186+
unsupported) echo -n " ⏭️ |" ;;
187+
timeout) echo -n " ⏱️ |" ;;
188+
partial_pass) echo -n " ⚠️ |" ;;
189+
*) echo -n " - |" ;;
190+
esac
191+
fi
192+
done
193+
echo ""
194+
done
122195
} | tee -a $GITHUB_STEP_SUMMARY > summary.md
123196
124197
- name: Comment on PR

Cargo.lock

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/harness.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,10 @@ impl KernelUnderTest {
332332
pub struct ConformanceTest {
333333
pub name: &'static str,
334334
pub category: TestCategory,
335+
/// Human-readable description of what this test validates
336+
pub description: &'static str,
337+
/// The primary protocol message type being tested (e.g., "kernel_info_request")
338+
pub message_type: &'static str,
335339
pub run: fn(&mut KernelUnderTest) -> std::pin::Pin<Box<dyn std::future::Future<Output = TestResult> + Send + '_>>,
336340
}
337341

@@ -369,6 +373,8 @@ pub async fn run_conformance_suite(
369373
results.push(TestRecord {
370374
name: test.name.to_string(),
371375
category: test.category,
376+
description: test.description.to_string(),
377+
message_type: test.message_type.to_string(),
372378
result,
373379
duration: test_start.elapsed(),
374380
});

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ pub use harness::{run_conformance_suite, ConformanceTest, KernelUnderTest};
2929
pub use report::{render_json, render_markdown, render_matrix_json, render_matrix_markdown, render_terminal};
3030
pub use snippets::LanguageSnippets;
3131
pub use tests::all_tests;
32-
pub use types::{ConformanceMatrix, KernelReport, TestCategory, TestRecord, TestResult};
32+
pub use types::{ConformanceMatrix, FailureKind, KernelReport, TestCategory, TestRecord, TestResult};

src/report.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@ pub fn render_terminal(report: &KernelReport) -> String {
4949
emoji, symbol, record.name, record.duration
5050
));
5151

52-
// Show failure reason
53-
if let TestResult::Fail { reason } = &record.result {
52+
// Show failure reason and hint
53+
if let TestResult::Fail { reason, kind } = &record.result {
5454
output.push_str(&format!(" Reason: {}\n", reason));
55+
if let Some(k) = kind {
56+
output.push_str(&format!(" Likely source: {} | {}\n", k.likely_source(), k.actionable_hint()));
57+
}
5558
}
5659
if let TestResult::PartialPass { score, notes } = &record.result {
5760
output.push_str(&format!(" Score: {:.0}% - {}\n", score * 100.0, notes));
@@ -113,7 +116,7 @@ pub fn render_markdown(report: &KernelReport) -> String {
113116
for record in &report.results {
114117
let result_str = match &record.result {
115118
TestResult::Pass => "PASS".to_string(),
116-
TestResult::Fail { reason } => format!("FAIL: {}", truncate(reason, 30)),
119+
TestResult::Fail { reason, .. } => format!("FAIL: {}", truncate(reason, 30)),
117120
TestResult::Unsupported => "SKIP".to_string(),
118121
TestResult::Timeout => "TIMEOUT".to_string(),
119122
TestResult::PartialPass { score, .. } => format!("PARTIAL ({:.0}%)", score * 100.0),

0 commit comments

Comments
 (0)