Commit Graph

41 Commits

Author SHA1 Message Date
Martino Ferrari 28d149f536 fix(e2e): assert real FORCE/TRACE/BREAK acks in the debug scenario
The final whole-branch review found runDebugScript only checked
mc.IsConnected() after sending FORCE/TRACE/BREAK/UNFORCE -- a liveness
check that would PASS even if DebugService silently no-op'd every command
(e.g. a signal-name/wire-format bug), undercutting the design's stated
rationale for this scenario ("catching wire-format/serialization bugs the
in-process suite cannot"). This mirrors the tautology already fixed for
the tcplogger scenario in an earlier task, but had not been applied here.

Added waitForAck(), which polls the sink's recorded "text_line" events for
DebugServiceBase::HandleCommand's real "OK <TOKEN> <count>\n" reply and
requires count > 0 -- HandleCommand prints this for every one of
FORCE/UNFORCE/TRACE/BREAK regardless of enable/disable direction, and
count is always "number of signals actually matched", so count==0 means
the signal path was never resolved. Verified with a real negative control
(temporarily pointing all commands at a nonexistent signal name): the
scenario now correctly FAILs, then reverted and reconfirmed PASS against
the real signal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-02 00:03:47 +02:00
Martino Ferrari 9a39cf923a fix(e2e): isolate coverage-pass WORK dir; filter chain-only e2e report section
The final whole-branch review (post Task 10) found two real cross-task
integration bugs:

- run_e2e.sh's coverage-instrumented scenario re-run only rebound OUT_DIR
  in its subshell, not WORK. proc_perf.py/plots.py write perf_*.json and
  wave_*.png into WORK, so every --cpp-coverage run (the default) silently
  clobbered the primary pass's perf/waveform data with the instrumented
  re-run's numbers before report_build.py read them -- defeating the
  "uncontaminated performance metrics" goal of the coverage-double-run
  design. Fixed by rebinding WORK the same way OUT_DIR already was.

- report_build.py's build_e2e() iterated all results["scenarios"] with no
  kind filter, so the direct/recorder/debug/tcplogger scenarios (already
  covered by their own dedicated report sections since Task 8) also leaked
  into the chain-only Scenarios/Performance sections and headline e2e
  pass/fail count as degenerate rows. Fixed by filtering to kind=="chain".

Verified end-to-end with a full ./run_e2e.sh run: coverage pass now writes
to /tmp/chain_e2e/coverage_pass/ (confirmed via log), and report_data.json's
e2e section now reports 51 (chain-only) scenarios instead of all 56.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 23:59:54 +02:00
Martino Ferrari 07b6b4898a fix(e2e): rebuild test binaries when restoring non-instrumented build
The post-coverage restore step ran `make clean` (which also wipes
Test/GTest, Test/Integration and Test/Components/*) but only rebuilt
`core apps`, leaving MainGTest.ex/IntegrationTests.ex deleted after
every --cpp-coverage run instead of restored to their plain (non-gcov)
form.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 22:55:48 +02:00
Martino Ferrari 03c7a95e9b docs: fix stale run_combined_test.sh comment in combined_test.cfg
Minor follow-up from Task 9's retirement review.
2026-07-01 22:08:21 +02:00
Martino Ferrari 45dcb9a71f docs: fix remaining dangling references to retired run_e2e_test.sh
README.md and Docs/StreamHub-Developer.md still pointed at the deleted
run_e2e_test.sh / Test/E2E/streamhub Go client after their removal in the
previous commit; repoint at Test/E2E/suite/run_e2e.sh.
2026-07-01 22:05:29 +02:00
Martino Ferrari 4286ea4539 chore(e2e): retire streamhub/datasources/recorder standalone scripts superseded by run_e2e.sh 2026-07-01 22:04:08 +02:00
Martino Ferrari 8337d678be feat(e2e): render direct/recorder/debug/tcplogger/stress sections in the unified report
Extends report_build.py with build_by_kind() (per-scenario-kind pass/fail
rollup) and a ported build_stress()/stress_headline()/stress_plots() (scaling
curves per stress axis), wires both into the headline KPIs, regression
tracking, and report_data.json. E2E_Report.typ renders the four new
per-kind tables plus a Stress Tests section (per-axis case tables + scaling
plots, gracefully degrading to placeholders when a kind/stress data is
absent). run_e2e.sh now passes --stress-results so the report actually
receives real stress data instead of silently omitting it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 21:57:11 +02:00
Martino Ferrari b65ac06ce2 feat(e2e): instrument-first coverage flow with double-run + new skip flags; port stress multi-fragment sizing 2026-07-01 21:07:03 +02:00
Martino Ferrari 83d0a060fe feat(e2e): add debug/tcplogger E2E scenario kinds using debugclient
Adds a trimmed debug_e2e.cfg (DebugService on 8080/8081, TcpLogger on
9090) and two new scenarios (s55_debug_force_trace_break, kind=debug;
s56_tcplogger_delivery, kind=tcplogger) reusing it, with matching
run_e2e.sh scenario-list/dispatch wiring and debugclient build steps.

Also fixes a real bug found while wiring s56: debugclient's tcplogger
check was tautological (it matched MarteController's own local
"CMD"-level echo of the outgoing command, which contains the same text
as the triggered event, instead of a line actually delivered over the
real TCPLogger TCP socket) and its trigger command (an invalid FORCE)
never reaches DebugServiceBase's REPORT_ERROR at all. Switched the
trigger to a MSG-to-missing-destination command (which does call
REPORT_ERROR) and the match to require the real log text
("not found in ORD"), recorded only after a connect-settle baseline —
verified with a positive run (real Warning-level TCPLogger line
received) and a negative control (LogPort=0 disables TcpLogger and the
scenario correctly FAILs).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 19:36:47 +02:00
Martino Ferrari efb4ea48fb feat(e2e): add debugclient Go tool for DebugService/TCPLogger E2E scenarios
Standalone headless client that drives a running MARTeApp.ex's
DebugService (TCP 8080 commands, UDP 8081 trace) and TCPLogger (TCP
9090) via marte2debugger/controller's NewHeadlessMarteController, for
the upcoming Test/E2E/suite "debug"/"tcplogger" scenario kinds. Scripts
FORCE/TRACE/BREAK for -mode debug, and triggers+waits for a TCPLogger
log event for -mode tcplogger; reports PASS/FAIL as
result_<scenario>.json/status_<scenario>.txt in -out.
2026-07-01 19:18:34 +02:00
Martino Ferrari f0f83110a4 fix(debugger): extract MarteController into an importable controller package
Client/debugger was entirely package main, which Go forbids importing from
another module ("is a program, not an importable package") -- discovered
while wiring the new debugclient E2E tool against NewHeadlessMarteController.
Move martecontrol.go and its test into a new marte2debugger/controller
subpackage (package controller) and update Client/debugger/main.go to call
controller.NewMarteController/controller.DangerousCommandsEnabled. No
behavioral change to the browser-facing server.
2026-07-01 19:18:08 +02:00
Martino Ferrari 269b2c4d97 refactor(debugger): extract MarteController sink so it can run headless
Add a sink func(v any) field so MarteController's event stream can be
routed somewhere other than the browser WebSocket hub. NewMarteController
now sets sink to broadcast through the hub as before; a new
NewHeadlessMarteController(sink) constructor builds an instance with
hub == nil for the upcoming debugclient E2E tool. Direct m.hub.* calls
(SetSourceState/UpdateConfigForSource/PushDataForSource) are now guarded
with nil checks so a headless controller doesn't panic.
2026-07-01 19:12:41 +02:00
Martino Ferrari 1d78b45963 feat(e2e): dispatch direct/recorder scenario kinds in run_e2e.sh
Extends the scenario-list builder and main loop to actually execute
s52_direct_unicast/s53_direct_multicast (self-contained single-MARTeApp
FileReader->UDPStreamer->UDPStreamerClient->FileWriter round trip) and
s54_recorder (StreamHub BinaryRecorder round trip, ported from
run_recorder_e2e.sh) alongside the existing chain scenarios, and tags
each results.json record with its scenario kind.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 19:06:30 +02:00
Martino Ferrari ef58553c63 feat(e2e): add kind discriminator + direct/recorder scenario definitions 2026-07-01 18:51:18 +02:00
Martino Ferrari 69e52af20b refactor(e2e): rename Test/E2E/chain -> Test/E2E/suite, run_chain_e2e.sh -> run_e2e.sh 2026-07-01 18:42:33 +02:00
Martino Ferrari 1fcc4e4e6d fix(streamhub-test): unblock make test by fixing BoundsCheckTest C++98 build and registering both orphaned GTest files 2026-07-01 18:34:16 +02:00
Martino Ferrari 462b05b71a docs(testing): implementation plan for unified test/E2E/reporting/coverage pipeline
Plan derived from the approved 2026-07-01 design spec; covers scenario
kind unification (chain/direct/recorder/debug/tcplogger), instrument-first
double-run coverage, and DebugService/TCPLogger E2E via debugclient.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 18:29:29 +02:00
Martino Ferrari dcaa466736 docs(testing): design for unified test/E2E/reporting/coverage pipeline
Consolidates the fragmented chain/stress/streamhub/datasources/recorder
E2E suites, unit-test collection, and coverage into one entry point and
one report, adds new DebugService/TCPLogger E2E coverage, and fixes the
Test/Applications/StreamHub build break blocking `make test`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-01 18:14:09 +02:00
Martino Ferrari 0bea41f866 Implemented better testing and fixed skipepd frames 2026-07-01 16:39:34 +02:00
Martino Ferrari 7a326c5d78 test(gtest): wire DebugServiceGTest into the shared MainGTest binary
Add DebugServiceGTest.cpp (TraceRingBuffer, DebugSignalInfo, BreakOp
regression coverage for the HI-4/HI-9 fixes) to Test/GTest's OBJSX so it
builds and runs as part of ./Build/x86-linux/GTest/MainGTest.ex alongside
the rest of the unit suite. 17/17 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 09:34:20 +02:00
Martino Ferrari 036dd4a656 docs(e2e-stress): implementation plan for stress suite report integration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 09:11:19 +02:00
Martino Ferrari 4702d0a217 Implemented qt port + e2e 2026-06-26 09:11:10 +02:00
Martino Ferrari 0d7d8f396b docs(e2e-stress): design for stress suite report integration
Track the existing (untracked) stress matrix, extend the signal-size axis
into the multi-fragment regime now that the UDPSClient reassembly cap is
1 MiB, and wire stress results into the E2E PDF report via an opt-in
--stress flag (table + per-axis scaling curves + regression vs prior run).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 09:05:21 +02:00
Martino Ferrari f256a4def5 test(e2e-chain): orchestrator + end-to-end fixes (Task 7)
Full-chain orchestrator (run_chain_e2e.sh) now runs the starter set green
(3 pass). Fixes found bringing the chain up end-to-end:

- client: gorilla/websocket cannot survive a read deadline (next ReadMessage
  panics "repeated read on failed connection"); replace the poll-with-deadline
  loop with a background reader goroutine + mutex-guarded state.
- orchestrator: guard env.sh's unbound LD_LIBRARY_PATH under set -u.
- scenarios/gen_data: centralize NUM_ROWS/ROW_DT and enforce sine freq to be a
  multiple of the buffer fundamental (LOOP_HZ=5 Hz) so the looped FileReader
  buffer is a seamless waveform; align starter freqs (5/5/10 Hz).
- gen_cfg: FileReader allows exactly one consuming Function, so route tapped
  (oracle=fed/both) sources through the DDB (ReaderGAM->DDB, then StreamGAM and
  TapGAM both read DDB) instead of a second FileReader consumer.
- validate_waveform: fidelity gates correctness (bit-exact / within one quant
  level); sine shape becomes a gross frequency-sanity gate (corr>=0.5) plus a
  tracked corr/nRMSE quality metric, since per-sample wall-clock calibration
  (Phase-A) and FULL_ARRAY packed timestamps (Phase-A4) are still pending.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 13:11:35 +02:00
Martino Ferrari d4fa84d482 test(e2e-chain): report plot generation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 09:07:13 +02:00
Martino Ferrari d35a78778e test(e2e-chain): per-effect waveform validator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 09:05:56 +02:00
Martino Ferrari aa6679f1a7 test(e2e-chain): Go mock client (record + zoom/window/trigger)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 09:04:04 +02:00
Martino Ferrari f146fc1016 test(e2e-chain): MARTe + StreamHub config generator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 09:01:20 +02:00
Martino Ferrari 10dec4c5d2 test(e2e-chain): deterministic typed/shaped data generator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 08:58:49 +02:00
Martino Ferrari 0ab49078cc test(e2e-chain): scenario model + starter scenarios
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 08:56:57 +02:00
Martino Ferrari f46b2dfb14 test(streamhub): add binary recorder E2E scenario
End-to-end test streaming three float32 signals via a MARTe2 UDPStreamer
app into a standalone StreamHub with the recorder enabled, then validating
the recorded FileWriter-compatible .bin against the streamed input with
validate_binary.py. All recorded rows are byte-identical to input rows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 01:20:16 +02:00
Martino Ferrari 8664b24e82 chore(streamhub): add disabled +Recorder block to run_streamhub.sh demo cfg
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 01:13:54 +02:00
Martino Ferrari 19e649aa38 feat(streamhub): parse +Recorder config and add recorder WS commands
Parse the optional +Recorder block in Initialise (Enabled/AutoStart/
Directory/MaxFileMB/KeepFiles/StagingMB/FlushIntervalSec/MinDiskFreeMB/
Signals, MB->bytes), apply it to each session before Start (static and
dynamic sources). Drive recorder disk I/O from the push loop via
RecorderFlushTick, and add recStart/recStop/recInfo WS commands plus a
recStatus broadcast/snapshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 01:13:23 +02:00
Martino Ferrari 93fc11c88f feat(streamhub): wire BinaryRecorder into UDPSourceSession
Each session owns a BinaryRecorder. The receive thread configures the
recorder layout at CONFIG time and captures each data packet; the push
thread performs all file I/O via RecorderFlushTick. WS subset overrides
are adopted through an epoch-deferred handoff mirroring the trigger path.
Arm/disarm/flush/info are exposed for StreamHub-level control.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 01:10:27 +02:00
Martino Ferrari 0ae35d11ff feat(streamhub): BinaryRecorder core (header, encode, rows, flush, rotation)
Add a FileWriter-compatible per-source binary recorder: native-type encode
and TypeDescriptor mapping, FileWriter header serialization, subset/quantized/
ACCUMULATE row serialization, and push-thread double-buffer flush with size-cap
rotation, keep-N pruning, fdatasync cadence, disk-free and staging-overflow
guards. Covered by 12 GTests; full suite (83) green.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 01:05:32 +02:00
Martino Ferrari e3b458ed94 Add implementation plan for StreamHub binary recorder
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 00:52:54 +02:00
Martino Ferrari 0412c20edd Implemented client datasource 2026-06-25 00:45:45 +02:00
Martino Ferrari dca4872976 Add design spec for StreamHub binary recorder
Lossless packet-decode capture to FileWriter-compatible per-source binary
files with size-capped rotation, config + WS control, and double-buffered
flush on the push thread (Approach C).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-25 00:45:25 +02:00
Martino Ferrari dd7dd22cb0 Implemented history writer 2026-06-14 14:09:51 +02:00
Martino Ferrari f25bd7f08e Implemented new C++ logic 2026-06-12 15:25:13 +02:00
Martino Ferrari 617b5bd712 Initial release 2026-05-29 13:29:59 +02:00