Skip to main content

Smoke Test Report

FieldValue
Document IDSTR-OCSA-001
Version1.0
StatusFinal — Phase 1
Date2026-09-12
Test leadSQM Engineering
ResultPASS — 138/138 automated assertions, 13/13 manual verifications

This report is the authoritative definition of test case IDs (TC-01 … TC-58, MV-01 … MV-13). The "Verified by" column in the requirements specification points at these IDs.

1. Test objectives​

  1. Verify that the domain engine produces correct, deterministic verdicts on representative license expressions and a realistic SBOM.
  2. Verify that the web dashboard renders every view without runtime errors.
  3. Verify that the CLI and MCP interfaces operate correctly and that the CI gate returns the right exit codes.
  4. Verify that the animated architecture walkthrough loads, reveals every element it is supposed to, and responds correctly to its playback controls.
  5. Record every defect found and its resolution.

2. Scope​

In scopeOut of scope
License expression evaluationVisual design review
SBOM parsing and graph constructionCross-browser compatibility (Chromium only)
Copyleft classification and propagationLoad testing beyond ~1 000 nodes
Finding generation (8 rules)Legal correctness of the tier table
SBOM quality checks (12)Real supplier SBOMs (not yet available)
Milestone diffAccessibility audit
Report / NOTICE / inquiry rendering
Dashboard rendering and filtering
CLI commands and exit codes
MCP protocol and tool dispatch
Static build and MIME types
Architecture walkthrough: scene rendering, timeline, controls

3. Test environment​

ItemValue
OSWindows (win32)
RuntimeNode.js v22.22.2
Browser engine (UI tests)jsdom 30.0.1
UI test invocationJSDOM_ENTRY=… node tools/ui-smoke-test.mjs
Engine test invocationnode tools/smoke-test.mjs
Animation test invocationJSDOM_ENTRY=… node tools/animation-smoke-test.mjs
Test datasamples/sample-ivisystem.spdx.json (4.2.0), samples/sample-ivisystem-4.1.0.spdx.json
Test data profile42 components, 45 relationships, 1 root

4. Test strategy​

LevelApproachAutomation
UnitLicense expression evaluation against known-answer casesAutomated (12)
ComponentParsing, classification, propagation, findings, scoring on a fixture SBOMAutomated (12)
ComponentMilestone diff against a 4.1.0 / 4.2.0 pairAutomated (7)
ComponentReport / NOTICE renderingAutomated (4)
IntegrationDashboard rendering in jsdom; filters; detail panel; diff cardAutomated (23)
SystemCLI commands, exit codes, MCP protocolManual, scripted (13)
Builddist/ contents and MIME types over HTTPManual, scripted

Test data design. The 4.2.0 fixture deliberately contains the failure modes that matter: an AGPL component statically linked into a proprietary telematics agent, LGPL components statically linked without declared relinking, a NOASSERTION component, a custom LicenseRef- whose extracted text mentions the GPL, and CDDL/EPL components that conflict with GPL in the same subtree. The 4.1.0 fixture is derived from it with four controlled differences so every diff path has a known expected result.

5. Test cases and results​

A — License expression evaluation (automated)​

IDInputExpectedActualResult
TC-01GPL-2.0-onlyCRITICALCRITICALPASS
TC-02GPL-2.0-or-later WITH u-boot-exception-2.0HIGHHIGHPASS
TC-03GPL-3.0-only WITH GCC-exception-3.1HIGHHIGHPASS
TC-04GPL-2.0-only WITH Linux-syscall-noteCRITICALCRITICALPASS
TC-05LGPL-2.1-or-later OR GPL-2.0-or-laterHIGHHIGHPASS
TC-06GPL-2.0-or-later AND LGPL-2.1-or-laterCRITICALCRITICALPASS
TC-07MITLOWLOWPASS
TC-08Apache-2.0LOWLOWPASS
TC-09AGPL-3.0-onlyCRITICALCRITICALPASS
TC-10NOASSERTIONUNKNOWNUNKNOWNPASS
TC-11LicenseRef-FooUNKNOWNUNKNOWNPASS
TC-12(MIT OR Apache-2.0) AND GPL-2.0-onlyCRITICALCRITICALPASS

TC-02/03 verify that linking exceptions relax copyleft; TC-04 verifies that an exception with no relaxation effect (Linux-syscall-note) does not downgrade the verdict.

B — SBOM model and risk analysis (automated)​

IDObjectiveExpectedActualResult
TC-13All packages parsed42 components42PASS
TC-14Root identifiedSPDXRef-Pkg-IVI-HMI-Applicationas expectedPASS
TC-15LGPL statically linked raises LIC-009Finding presentpresent (Qt)PASS
TC-16Unresolved license raises LIC-003Finding presentpresent (legacy-codec)PASS
TC-17Custom license text raises LIC-004Finding presentpresent (vendor-camera-sdk)PASS
TC-18Multi-licensing raises LIC-007Finding presentpresent (ffmpeg)PASS
TC-19Incompatibility raises LIC-005Finding presentpresentPASS
TC-20Propagation raises LIC-006Finding presentpresent (6 sources)PASS
TC-21AGPL classified CRITICALeclipse-mosquitto-client = CRITICALCRITICALPASS
TC-22Taint reaches the parenttelematics-agent tainted by AGPL clienttaintedPASS
TC-23Quality checks present12 checks12PASS
TC-24Risk score in range0 < score ≤ 10061PASS

Observed output for the fixture: score 61 (band HIGH), SBOM quality 50 % (6/12), findings CRITICAL 13 / HIGH 30 / MEDIUM 8 = 51 total.

C — Milestone diff 4.1.0 → 4.2.0 (automated)​

IDObjectiveExpectedActualResult
TC-25Added component detectedeclipse-mosquitto-clientdetectedPASS
TC-26Removed component detectedgpsddetectedPASS
TC-27License change detectedOpenSSL → Apache-2.0detectedPASS
TC-28Escalation flaggedlegacy-codec MIT → NOASSERTIONflagged escalatedPASS
TC-29Regression to unresolved detectedlegacy-codecdetectedPASS
TC-30Version bump detectedQt 6.5.2 → 6.5.3detectedPASS
TC-31New critical findings counted> 02PASS

D — Report generation (automated)​

IDObjectiveExpectedActualResult
TC-32Compliance report contains verdictRisk score nn/100presentPASS
TC-33Report contains obligation checklistsection presentpresentPASS
TC-34Report contains source-offer sectionsection presentpresentPASS
TC-35NOTICE file contains attributionsNOTICES AND ATTRIBUTIONSpresentPASS

E — Dashboard in jsdom (automated)​

IDObjectiveExpectedActualResult
TC-36No runtime errors0 errors0PASS
TC-37Dashboard becomes visible#dashboard shownshownPASS
TC-38Landing zone hidden#dropzone hiddenhiddenPASS
TC-39Header shows document identitycontains document nameIVI-Cockpit-SW-4.2.0 … 42 componentsPASS
TC-40KPI strip renders6 cards6PASS
TC-41Risk score displayednumeric61PASS
TC-42License distribution renders> 5 bars14PASS
TC-43Quality table renders12 rows12PASS
TC-44Findings render> 10 rows51PASS
TC-45Critical badge rendered≥ 11+PASS
TC-46Inventory renders42 rows42PASS
TC-47Graph SVG createdelement existsexistsPASS
TC-48Graph nodes drawn> 20 circles85PASS
TC-49Graph edges drawn> 20 lines45PASS
TC-50Graph statistics labelnn nodes / nn edges42 nodes / 45 edgesPASS
TC-51Tier filter narrows inventory0 < rows < 426PASS
TC-52Detail panel opensclass openopensPASS
TC-53Detail shows licenseEffective licensepresentPASS
TC-54Diff card rendersMilestone diffpresentPASS
TC-55Diff shows new componenteclipse-mosquitto-clientpresentPASS
TC-56Diff shows removed componentgpsdpresentPASS
TC-57Diff shows license changeOpenSSLpresentPASS
TC-58Diff verdict severityCRITICALCRITICALPASS

F — CLI and MCP (manual, scripted)​

IDCommand / actionExpectedActualResult
MV-01cli.mjs analyze … --format jsonValid JSON with score, findings, componentsProducedPASS
MV-02cli.mjs analyze … --format csv43 lines (header + 42)43PASS
MV-03cli.mjs analyze … --format mdMarkdown reportProducedPASS
MV-04cli.mjs report … --ecu … --milestone …Report with metadata tableProducedPASS
MV-05cli.mjs notice …NOTICE with per-component blocksProducedPASS
MV-06cli.mjs inquiry … --supplier …Numbered items with response blanksProducedPASS
MV-07cli.mjs diff <old> <new>Markdown diff with all sectionsProducedPASS
MV-08cli.mjs gate <file> (strict)Exit 1 + reasonsExit 1, 3 reasonsPASS
MV-09cli.mjs gate … --max-critical 99 --max-high 99 --allow-unresolvedExit 0Exit 0PASS
MV-10MCP initializeprotocolVersion + capabilities + serverInfoReturnedPASS
MV-11MCP tools/list9 tools with JSON Schemas9PASS
MV-12MCP tools/call × 4Correct payloadsCorrectPASS
MV-13build:static + HTTP servedist/ 281 KB; 200 + correct MIMEVerifiedPASS

G — Architecture walkthrough in jsdom (automated)​

Suite: tools/animation-smoke-test.mjs. Loads the walkthrough HTML into jsdom, jumps to every scene, fires every timeline step, and asserts nothing throws and nothing is left in a hidden state. Where a group is shown, each row is emitted once per scene — which is why 40 IDs cover 80 assertions.

IDObjectiveExpectedActualResult
A-01 … A-06Load: 0 runtime errors, 8 scenes, sidebar populated, SVG present, caption, clockall matchall matchPASS
A-07 … A-14Per-scene rendering (8 scenes × 5)4040PASS
A-15 … A-22Per-scene timeline (8 scenes × 2)1616PASS
A-23 … A-35Controls: play/pause, Next, Prev, Restart, speed, arrow keys1313PASS
A-36 … A-37Progress bar grows; scene auto-advancesadvances0 → 11.4 %; advancedPASS
A-38 … A-40Every scene has a title, text and positive duration; no errors33PASS

Total: 80 assertions, 80 passed, 0 failed.

The "nothing stranded hidden" checks are the valuable ones. The walkthrough reveals elements by adding a CSS class, so a typo in a selector or a missing data-n attribute produces a scene that looks fine in code review but is missing half its content on screen. Asserting that every element which starts hidden ends up visible catches that class of defect automatically. It found BUG-18, BUG-19 and BUG-21.

6. Execution summary​

SuiteCasesPassedFailedPass rate
A — License expressions12120100 %
B — Model and analysis12120100 %
C — Milestone diff770100 %
D — Report generation440100 %
E — Dashboard (jsdom)23230100 %
G — Architecture walkthrough (jsdom)80800100 %
Automated total1381380100 %
F — CLI / MCP / build (manual)13130100 %
Grand total1511510100 %

Exit codes: engine suite 0, UI suite 0, animation suite 0.

7. Bug register​

All defects were found during development and verification. All are closed.

IDSeverityComponentDescriptionRoot causeResolution
BUG-01Highlicense-db.jsUNKNOWN licenses reported as HIGHHIGH and UNKNOWN both had the same rank, so a rank lookup matched HIGH firstUNKNOWN given a fractional rank; ranks are now unique
BUG-02Highlicense-db.jsGPL-2.0+ WITH u-boot-exception-2.0 classified UNKNOWN instead of HIGHThe relaxation ladder contained UNKNOWN, so CRITICAL relaxed onto itLadder restricted to LOW, MEDIUM, HIGH, CRITICAL
BUG-03Criticallicense-db.jsSecond and later lookups of a license returned no rank → NaN → UNKNOWN verdictThe classification cache stored the object before rank was computedRank computed before caching
BUG-04Highlicense-db.jsLIC-003 never fired for NOASSERTIONThe early-return object omitted unresolved: trueField added
BUG-05Mediumrisk-engine.js30+ spurious HIGH findings — LIC-003 fired for every LicenseRef-Proprietary refs with extracted text treated as unknown-unknownsA ref with extracted text is resolved for copyleft purposes; tier stays UNKNOWN
BUG-06Mediumrisk-engine.js22 identical propagation findings for one AGPL componentFindings emitted per intermediate hopEmitted only when the target is a distributed-unit root; ancestors still tainted
BUG-07Mediumcli.mjs--allow-unresolved had no effect; the gate could never passBoolean flag read with the value-flag helper, which consumes the next argvDedicated has() helper
BUG-08Mediumrisk-engine.jsRisk score saturated at 100 on every realistic SBOMRaw weighted finding count × 4Density-normalised formula
BUG-09Highindex.html / app.jsrenderDiff crashed: "Cannot set properties of null"The diff-card container was missing from the markupContainer added
BUG-10Lowui-smoke-test.mjsDiff assertions failed — the diff was emptyThe fetch stub returned the same document for both URLsStub made URL-aware
BUG-11Lowspdx.jslicenseDeclared extraction incorrectOperator-precedence bug in a ternarySimplified
BUG-12Lowgraph.jsAnimation loop never terminated, burning CPUNo settle conditionMotion threshold stops the loop; interaction wakes it
BUG-13Mediumrisk-engine.jsAncestor paths could be malformed or miss entriesFragile index arithmetic in path constructionRewritten as a cycle-safe BFS
BUG-14Lowgraph.jsSyntax error in an assignmentTypo during editingCorrected; caught by node --check
BUG-15Lowspdx.jspurl extraction used an incorrect reduceOver-engineered parsingSimplified to a reference-type check
BUG-16Lowapp.jsHeader showed only the filename, not the SBOM document nameMissing field in the header stringHeader now shows name, filename, SPDX version and component count
BUG-17Lowrisk-engine.jsAll LIC-006 findings had identical titlesTitle omitted the source componentTitle now names the source
BUG-18Mediumwalkthrough HTMLTimed reveals appeared immediately — the closing panel of every scene was on screen from frame oneElements carried both the auto-reveal marker and a timeline stepMarker removed from step-controlled elements
BUG-19Mediumwalkthrough HTMLIn the propagation scene one connector was invisible and the other never hiddenFirst path had the hidden class but no marker; second had a typo classBoth corrected
BUG-20Lowwalkthrough HTMLAll four output connector lines drawn on top of each otherPath data multiplied the index term by zeroEach line elbows to its own box centre
BUG-21Lowwalkthrough HTMLLegend panel never appearedThe step built the rows but never revealed the parent groupStep now reveals the group first

Defect distribution​

SeverityCountComponentCount
Critical1license-db.js4
High4risk-engine.js4
Medium7spdx.js2
Low9graph.js2
Total21app.js / index.html2
walkthrough HTML4
tests / other tools3

BUG-03 is the notable one: silent and order-dependent — a license evaluated correctly on first use and incorrectly once cached. It was caught only because the suite evaluates GPL-2.0-only twice with different modifiers. Known-answer repetition is what surfaced it.

8. Coverage analysis​

AreaCovered byStatus
Expression grammar (AND/OR/WITH/parens)TC-01 … TC-12Covered
Linking exceptions (relaxing and non-relaxing)TC-02, TC-03, TC-04Covered
Classification of unknown / custom referencesTC-10, TC-11, TC-17Covered
All 8 finding rulesTC-15 … TC-20, TC-22Covered except LIC-008 by assertion (observed in output only)
Propagation and taintTC-20, TC-22Covered
ScoringTC-24Covered (range check only — no golden value)
Quality checksTC-23Covered (count only)
Diff — all categoriesTC-25 … TC-31Covered
Report / NOTICETC-32 … TC-35Covered
UI rendering and filteringTC-36 … TC-58Covered
CLI and MCPMV-01 … MV-12Covered (manual)
Build and MIME typesMV-13Covered (manual)

Coverage gaps (honest assessment)​

GapRiskRecommendation
LIC-008 (missing copyright) is not assertedLowAdd an assertion in the next cycle
Scoring has no golden-value testMediumPin expected scores for both fixtures
LIC-001 not asserted directlyLowAssert explicitly
Graph is tested structurally, not visuallyMediumOne manual visual check per release
No negative tests for malformed SPDX beyond the missing-packages caseMediumAdd fixtures: cyclic relationships, missing relationships, empty document
No cross-browser testingMediumManual check in Firefox/Edge before wide rollout
CLI/MCP are manualMediumAutomate MV-01 … MV-12

9. Residual risk​

IDRiskSeverityMitigation
RR-01Tier table not legally ratified — all verdicts are engineering triageHighM-8; legal workshop
RR-02No real supplier SBOM tested; fixtures are syntheticMediumFirst live run must be compared against manual review
RR-03Compatibility conflicts may over-report without a process-boundary mapMediumDocumented; request boundary maps
RR-04Single browser engine testedMediumManual cross-browser check
RR-05No persistence, so historical re-analysis requires the original filesLowPhase 2 (P2-01)

10. Conclusion and recommendations​

The Phase 1 prototype passes all automated assertions and all manual verifications, with 21 defects found and closed. The build is reproducible (dist/ 281 KB) and serves correctly over HTTP.

:::danger A green suite is not validation of correctness It validates that the implementation matches the current rules. The rules themselves need legal ratification (M-8). Until then every CRITICAL/HIGH finding requires counsel. :::

Recommendations before operational use:

  1. Do not treat the green suite as validation of correctness. It validates that the implementation matches the current rules, not that the rules are right.
  2. Automate the manual cases. MV-01 … MV-12 are scripted but not asserted; promoting them prevents regression in the CLI and MCP surfaces.
  3. Add golden-value tests for the score so a formula change is visible.
  4. Add negative fixtures — cyclic relationships, missing relationships, empty document.
  5. Run against one real supplier SBOM and compare with the manual review to calibrate the false-positive rate before rollout.

11. Appendix A — reproduction​

cd oss-compliance-analyzer

# Automated engine suite (35 assertions, no dependencies)
node tools/smoke-test.mjs

# Automated UI suite (23 assertions, needs jsdom)
npm i -D jsdom
node tools/ui-smoke-test.mjs

# Automated animation suite (80 assertions, needs jsdom)
node tools/animation-smoke-test.mjs

# Manual CLI / MCP checks
node tools/cli.mjs gate samples/sample-ivisystem.spdx.json
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| node tools/mcp-server.mjs

# Build verification
npm run build:static && (cd dist && python -m http.server 8080)

12. Appendix B — engine suite output (excerpt)​

PASS evaluate("GPL-2.0-only") => CRITICAL - got CRITICAL
PASS evaluate("GPL-2.0-or-later WITH u-boot-exception-2.0") => HIGH - got HIGH
PASS evaluate("GPL-2.0-only WITH Linux-syscall-note") => CRITICAL - got CRITICAL
PASS evaluate("(MIT OR Apache-2.0) AND GPL-2.0-only") => CRITICAL - got CRITICAL

Document: IVI-Cockpit-SW-4.2.0 (SPDX SPDX-2.3)
Components: 42, relationships: 45, roots: SPDXRef-Pkg-IVI-HMI-Application
Risk score: 61 (HIGH) SBOM quality: 50%
Findings: CRITICAL=13 HIGH=30 MEDIUM=8

Top findings:
[CRITICAL] LIC-006 Strong copyleft from "busybox" propagates into "IVI-HMI-Application"
[CRITICAL] LIC-006 Strong copyleft from "linux-kernel" propagates into "IVI-HMI-Application"
[CRITICAL] LIC-006 Strong copyleft from "eclipse-mosquitto-client" propagates into "IVI-HMI-Application"
[CRITICAL] LIC-004 Custom license text on vendor-camera-sdk shows copyleft indicators
[CRITICAL] LIC-001 Strong copyleft component: busybox

Diff 4.1.0 -> 4.2.0: 2 new critical finding(s) (risk +3)

ALL CHECKS PASSED