23 Commits

Author SHA1 Message Date
Martino Ferrari 2d5ca20ae4 minor changes and addeed debug tests 2026-07-02 16:27:40 +02:00
Martino Ferrari f2042d624b Implemented full e2e testing 2026-07-02 10:10:57 +02:00
Martino Ferrari f8c79131c9 docs: refresh run_e2e.sh flag list in AGENTS.md
Task 7 added --skip-coverage/--skip-stress/--skip-datasources/
--skip-recorder/--skip-debug/--skip-tcplogger but the AGENTS.md table row
was never updated to mention them; it also still listed a --stress flag
that has never existed. Sync with the script's actual --help output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-02 00:04:22 +02:00
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
110 changed files with 10406 additions and 2404 deletions
+313
View File
@@ -0,0 +1,313 @@
# AGENTS.md
Guide for agents working in the MARTe2 Integrated Components repository. Read
`ARCHITECTURE.md` and `CLAUDE.md` for deeper detail; this file focuses on
non-obvious knowledge, commands, and conventions that are not self-evident from
a single file read.
---
## Repository at a glance
MARTe2 component library with two independent real-time data paths:
1. **Streaming path**`UDPStreamer` DataSource (serialises signals to UDPS
binary packets on UDP 44500) → `StreamHub` (headless C++ hub: ring buffers,
LTTB decimation, trigger FSM, history writer) → WebSocket 8090 → clients
(browser SPA, native ImGui, native Qt).
2. **Debug path**`DebugService` Interface patches `ClassRegistryDatabase` at
`Initialise()` so `ConfigureApplication()` wraps all `MemoryMap*Broker` types
with `DebugBrokerWrapper<T>`. Zero application code changes. Exposes TCP 8080
(text commands), UDP 8081 (trace telemetry), TCP 8082 (`TcpLogger`).
Key shared artefact: `Common/UDP/UDPSProtocol.h` — the UDPS binary wire format
(17-byte packed header, 136-byte signal descriptors, little-endian). It is
deliberately MARTe2-free and is mirrored across **four** codebases that must stay
in sync: C++ producers (`UDPStreamer`, `DebugService`), C++ consumer
(`Source/Components/Interfaces/UDPStream/UDPSClient`), Go decoder
(`Common/Client/go/udpsprotocol`), and the JS client parsers. Any protocol
change must be mirrored in all of them.
StreamHub WebSocket protocol: JSON text frames for commands/events, binary
frames for data pushes (spec in `ARCHITECTURE.md` §6). The Go hub
(`Client/udpstreamer`) and the C++ StreamHub implement the identical protocol;
browser JS, ImGui, and Qt clients must stay compatible with both.
---
## Environment setup (do this first, always)
`source env.sh` is **required** before building *or* running anything. It sets:
- `MARTe2_DIR` (default `~/workspace/MARTe2`) and `MARTe2_Components_DIR`
(default `~/workspace/MARTe2-components`) — external dependencies, not in
this repo. Edit `env.sh` if your MARTe2 install lives elsewhere.
- `TARGET=x86-linux`
- `LD_LIBRARY_PATH` — prepends MARTe2 Core, MARTe2-components (LinuxTimer,
FileDataSource), and this repo's built `.so`s (UDPStreamer, SineArrayGAM,
TimeArrayGAM, DebugService, TCPLogger).
Without sourcing `env.sh`, builds fail (can't find `MakeDefaults`) and binaries
fail to load shared libs. The E2E scripts source it themselves, but a bare
`make` or `./MainGTest.ex` from a fresh shell will not.
---
## Build commands
All C++ builds use the MARTe2 `Makefile.gcc` wrapper system. There is one
top-level `Makefile.gcc` and one per component directory. `TARGET` defaults to
`x86-linux`; pass `TARGET=x86-linux` explicitly when invoking `make -C` from
elsewhere.
```bash
source env.sh
make -f Makefile.gcc core # all C++ MARTe2 components (UDPStreamer, GAMs, DebugService, TCPLogger, UDPStream)
make -f Makefile.gcc apps # StreamHub standalone app
make -f Makefile.gcc test # build GTest + Integration test binaries
make -f Makefile.gcc clean
make -f Makefile.gcc # = all: core apps test
# Build a single component (each component dir has its own Makefile.gcc):
make -C Source/Components/DataSources/UDPStreamer -f Makefile.gcc
make -C Source/Applications/StreamHub -f Makefile.gcc
```
Build output goes to `Build/x86-linux/` — shared libs under
`Build/x86-linux/Components/<...>/`, the StreamHub executable at
`Build/x86-linux/StreamHub/StreamHub.ex`, test binaries under
`Build/x86-linux/GTest/` and `Build/x86-linux/Test/Integration/`.
`compile_commands.json` is generated at the repo root (gitignored) for LSP /
clangd. The CMake-based clients (ImGui, Qt) also export it into their `build/`.
### Non-MARTe2 clients (separate build systems, no env.sh needed)
```bash
# Go clients (UDPS web client, debug client, E2E chain-client)
cd Common/Client/go && go build ./...
cd Client/debugger && go build ./...
cd Client/udpstreamer && go build ./... # or: cd Client/webui && go build
cd Test/E2E/suite/client && go build ./... # chain-client (E2E driver) + its tests
# ImGui desktop client (needs SDL2; fetches Dear ImGui + ImPlot via FetchContent)
cd Client/streamhub && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build
# Qt desktop client (Qt5 or Qt6 Widgets + WebSockets; autodetects, prefers Qt6)
cd Client/streamhub-qt && cmake -B build && cmake --build build
```
---
## Run / test commands
### Unit & integration tests (C++)
```bash
./Build/x86-linux/GTest/MainGTest.ex # UDPStreamer unit tests
./Build/x86-linux/GTest/MainGTest.ex --gtest_filter='Name*' # single test
./Build/x86-linux/Test/Integration/Integration/IntegrationTests.ex # DebugService integration tests
```
### Go tests
```bash
cd Test/E2E/suite/client && go test ./...
```
### Python framework tests (E2E framework logic, no live stack needed)
```bash
cd Test/E2E/suite && python3 -m unittest tests_py
```
### E2E / demo scripts (build + launch the full stack)
| Script | What it does |
|---|---|
| `./run_streamhub.sh` | Launch MARTe2 app (UDPStreamer) + StreamHub, optionally web UI (`-w`) and ImGui client (`-g`). Ports documented in its header. |
| `./Test/E2E/suite/run_e2e.sh` | **Unified E2E suite**: per-scenario generates data + cfgs, runs MARTe2+StreamHub, drives the Go `chain-client` (live/zoom/window/trigger) for `chain` scenarios plus `direct`/`recorder`/`debug`/`tcplogger` scenario kinds, runs a stress matrix, unit suites + coverage, builds a Typst PDF report. Flags: `--skip-build`, `--only <id>`, `--pdf-only`, `--cpp-coverage`, `--skip-coverage`, `--skip-stress`, `--skip-datasources`, `--skip-recorder`, `--skip-debug`, `--skip-tcplogger`. |
| `./Test/E2E/suite/run_stress.sh` | **Capacity/stress harness**: sweeps one load axis at a time (signal size/count, subscriber fan-out, source count, WS-client count, zoom rate), gates on survival+liveness (hard) and RSS+zoom-p95 latency (soft). Flags: `--skip-build`, `--only <id>`, `--axis <axis>`. |
The E2E suite produces `Build/x86-linux/E2E/chain/` artifacts: `report_data.json`,
`history.jsonl` (per-run headline metrics for trend/regression tracking),
`trend_*.png` plots, and `E2E_Report.pdf` (compiled from `E2E_Report.typ` via
`typst`). `--cpp-coverage` triggers an instrumented `--coverage` rebuild, captures
with `lcov` (restricted to `Source/*` + `Test/*`), then restores a clean build.
---
## Code organization
```
Common/
UDP/UDPSProtocol.h # shared UDPS binary protocol (header-only, MARTe2-free)
Client/go/ # Go packages: udpsprotocol (decoder), wshub (WS hub client)
Source/
Components/ # MARTe2 components — NO STL allowed here
DataSources/UDPStreamer/ # real-time UDP signal streaming DataSource
DataSources/UDPStreamerClient/ # (MARTe2-side UDPS client DataSource)
GAMs/SineArrayGAM/ # sine-wave array generator GAM
GAMs/TimeArrayGAM/ # time-reference array GAM
Interfaces/DebugService/ # tracing/forcing/breakpoint Interface (registry-patched brokers)
Interfaces/TCPLogger/ # REPORT_ERROR → TCP forwarder (LoggerConsumerI)
Interfaces/UDPStream/ # UDPSClient/UDPSServer (C++ consumer/producer of UDPS)
Applications/StreamHub/ # headless C++ hub app (links MARTe2 core but follows MARTe2 style)
Client/
debugger/ # Go web client for DebugService (browser UI in static/)
udpstreamer/ # Go web server + static SPA for UDPStreamer (legacy direct-UDP path)
webui/ # Go StreamHub WebSocket web UI (newer, hub-based)
streamhub/ # native ImGui desktop client (SDL2 + OpenGL + ImPlot, C++17, no MARTe2)
streamhub-qt/ # native Qt Widgets desktop client (C++17, Qt5/Qt6, no MARTe2)
Test/
GTest/ # GTest harness (MainGTest.cpp) for UDPStreamer unit tests
Integration/ # DebugService integration tests (link against DebugService .so)
Components/DataSources/UDPStreamer/ # UDPStreamer unit test sources
Configurations/ # MARTe2 .cfg files for tests and demos
E2E/
chain/ # streaming-chain E2E + stress suite (Python orchestrator + Go client)
datasources/ recorder/ streamhub/ # older per-component E2E scripts
Docs/ # per-component reference docs (Protocol, UDPStreamer, StreamHub-*, DebugService, ...)
docs/superpowers/{specs,plans}/ # design specs + implementation plans (dated)
ARCHITECTURE.md # full architecture (data flow diagrams, protocol tables, WS protocol)
```
### Component layout convention
Every MARTe2 component directory contains:
- `Makefile.gcc` — thin wrapper (`TARGET = x86-linux` then `include Makefile.inc`).
- `Makefile.inc` — real build definition: `OBJSX`, `PACKAGE`, `INCLUDES`,
`LIBRARIES`, includes `$(MARTe2_DIR)/MakeDefaults/MakeStdLibDefs.$(TARGET)`
and `MakeStdLibRules.$(TARGET)`, and `depends.$(TARGET)`.
- `depends.x86-linux` / `dependsRaw.x86-linux` — generated header dependency
files (committed; regenerated by the build). Do not hand-edit.
- `<ClassName>.{h,cpp}` — the implementation, with `CLASS_REGISTER(ClassName,
"1.0")` at the bottom of the `.cpp` (MARTe2 class-registration macro).
To add a new component, copy an existing one and adapt `Makefile.inc`'s
`OBJSX` / `PACKAGE` / `INCLUDES` / `LIBRARIES`.
---
## Conventions and gotchas
### No STL in MARTe2 components
`Source/Components/**` must not use the C++ standard library. Use MARTe2 types:
`StreamString` (not `std::string`), `FastPollingMutexSem` (not `std::mutex`),
fixed arrays / `StaticList` (not `std::vector`), MARTe2 error macros
(`REPORT_ERROR`, `REPORT_ERROR_STATIC`) instead of exceptions. Includes come
from `$(MARTe2_DIR)/Source/Core/...` (BareMetal, Scheduler, FileSystem).
`Source/Applications/StreamHub/` links MARTe2 core and follows the same
no-STL-on-RT-paths style, but is a standalone app (not a loadable component).
STL / C++17 is **fine** in `Client/streamhub/` and `Client/streamhub-qt/`
(framework-free C++17, no MARTe2 dependency).
### RT hot-path mutex rule
Use `FastPollingMutexSem` on real-time hot paths — never OS mutexes
(`pthread_mutex`, `std::mutex`). The RT cycle must not block on the scheduler.
### Protocol change checklist
Changing `Common/UDP/UDPSProtocol.h` (or the Go mirror) requires mirroring
across all four consumers listed in §1, plus the JS client parsers in
`Client/udpstreamer/static/`. The Go decoder lives in
`Common/Client/go/udpsprotocol/protocol.go` and re-declares the constants
(`HeaderSize`, `SigDescSize`, packet types, quant types, time modes) — it does
**not** include the C header.
### Qt client: `QT_NO_KEYWORDS`
`Client/streamhub-qt/` reuses `../streamhub/Protocol.{h,cpp}` and
`SignalBuffer.h` verbatim. Those structs have members named `signals`, which
collide with Qt's `signals`/`slots`/`emit` macros. The Qt build sets
`QT_NO_KEYWORDS` and all Qt classes use `Q_SIGNALS:`/`Q_SLOTS:`/`Q_EMIT`. Do
not remove that define, and do not use the lowercase Qt keywords in Qt-client
code. Single GUI thread — `QWebSocket` signals arrive on the GUI thread, no
locks; a 60 Hz `QTimer` drives repaint. Run with long options:
`./build/StreamHubQtClient --host HOST --port 8090` (single-dash `-host` is
misparsed as clustered short flags).
### StreamHub history
`HistoryWriter` (`Source/Applications/StreamHub/HistoryWriter.{h,cpp}`) does
disk-backed circular storage: per-signal `.shist` files with a 64-byte header
and a pre-allocated circular region of `(float64 time, float64 value)` pairs.
Configured via a `+History` block (`Directory` required; `DurationHours`
default 1, `Decimation` default 1, `FlushIntervalSec` default 5,
`MinDiskFreeMB` default 500). WS commands: `historyInfo`, `historyZoom`.
### E2E scenario / stress matrix
`Test/E2E/suite/scenarios.py` is a *curated covering set*: every configurable
UDPStreamer option value appears in at least one scenario, plus high-risk
interactions. `stress.py` is the capacity sibling — it sweeps one load axis at
a time and records survival/liveness (hard gates) and RSS/zoom-p95 latency
(soft gates). Both feed the same `gen_data.py` / `gen_cfg.py` generators. When
adding a new UDPStreamer option, add a scenario that exercises it and update
`validate_scenario` / the stress matrix accordingly.
`validate_waveform.py` has two gates: **fidelity** (every received value within
`tol` of some ground-truth value; `tol` is 0 for un-quantised ints, a float
epsilon for un-quantised floats, `quant_step/2 + 1e-6·range` for quantised
floats) — this is the **correctness** gate. **Shape** (least-squares sine fit,
correlation ≥ 0.99) is a gross-sanity gate + tracked metric, pending Phase-A
timestamp calibration. Do not tighten the shape gate to a correctness gate.
### Gitignored build artefacts
`Build/`, `compile_commands.json`, `*.gcov`/`*.gcda`/`*.gcno` (coverage), Go
binaries (`Client/*/marte2debugger`, `udpstreamer-webui`, `streamhub-e2e`,
`Client/*/bin/`), and the `udp_standalone_webui/` scratch dir are all
gitignored. `vgore.*` core dumps (e.g. `vgcore.26968`) are not — remove them.
---
## Documentation map
- `ARCHITECTURE.md` — full architecture: data-flow diagrams, UDPS packet/header
tables, CONFIG payload, StreamHub WebSocket protocol (commands, events,
binary frames), threading model.
- `Docs/` — per-component reference docs (`Protocol.md`, `UDPStreamer.md`,
`SineArrayGAM.md`, `DebugService.md`, `StreamHub-{UserGuide,API,Developer}.md`,
`Tutorial.md`, `WebUI.md`).
- `docs/superpowers/specs/` — design specs (dated, e.g.
`2026-06-26-stress-suite-report-integration-design.md`).
- `docs/superpowers/plans/` — implementation plans paired with specs.
- `.superpowers/sdd/` — task briefs, reports, and a `progress.md` ledger for
in-flight feature work (not always present; per-branch).
- `README.md` — high-level overview + quick-start config snippets.
- `CLAUDE.md` — condensed agent guidance (overlaps with this file).
---
## Ports reference (defaults)
| Port | Protocol | Component | Purpose |
|------|----------|-----------|---------|
| 44500 | UDP | UDPStreamer | scalar signals (unicast control) |
| 44501 | UDP | UDPStreamer | packed arrays (FirstSample/LastSample) |
| 44502 | UDP | UDPStreamer | packed arrays (FullArray) |
| 44503 | UDP | UDPStreamer | multicast data (group 239.0.0.1) |
| 8080 | TCP | DebugService | text command channel |
| 8081 | UDP | DebugService | trace telemetry stream |
| 8082 | TCP | TcpLogger | REPORT_ERROR log forward |
| 8090 | TCP/WS | StreamHub | WebSocket (commands + binary data) |
| 8080 | TCP | udpstreamer-webui | web UI listen (legacy direct-UDP path) |
| 9090 | TCP | debugger | debug web UI listen |
Note the 8080 collision: DebugService control vs. the legacy web UI listen port.
In combined demos that run both, the scripts adjust one of them — check the
script header before assuming.
---
## License
EUPL v1.1 — license headers are present on all C++ sources. Preserve them on
new files; do not relicense.
+221
View File
@@ -0,0 +1,221 @@
# Bug Fix Plan — Security & Correctness Remediation
**Date:** 2026-06-26
**Based on:** `BUG_REPORT.md`
**Scope:** `Source/` and `Client/`
This plan organizes the ~60 findings from the audit into prioritized, dependency-ordered phases. Each phase is independently shippable. Phases are ordered by risk reduction: Critical remote-exploitable issues first, then High crash/OOB issues, then Medium robustness/DoS, then Low hardening.
---
## Guiding principles
1. **Fix root causes, not symptoms.** The integer-overflow-in-bounds-check pattern appears in 6+ places — fix the pattern, not each instance ad hoc. Introduce a shared `boundsCheck(off, count, elemBytes, bufLen)` helper (C++) and a `validateCount(count, elemSize, bufLen)` helper (Go) and use them everywhere.
2. **Defense in depth.** Origin checks + auth + input validation — not just one layer.
3. **No regressions.** After each phase, run the existing test suites (`make -f Makefile.gcc test`, `python3 -m unittest tests_py`, `go test ./...` in each Go module) and the E2E suite (`./Test/E2E/chain/run_chain_e2e.sh --skip-build`).
4. **Minimal blast radius.** Each fix is surgical to the file/function listed in the bug report. No refactors beyond what the fix requires.
---
## Phase 1 — Critical remote-exploitable fixes (ship first)
**Goal:** Eliminate drive-by takeover and remote heap corruption. All fixes are small and localized.
| # | Bug | File(s) | Fix | Est. effort | Depends on |
|---|-----|---------|-----|-------------|------------|
| 1.1 | CR-1: 1-byte heap OOB write in WS frame NUL-term | `WSServer.cpp:251` | Change `kRecvBuf = WS_MAX_RECV_PAYLOAD + 14u``+ 14u + 1u` | 5 min | — |
| 1.2 | CR-2: XSS via unescaped `src.addr` | `Client/udpstreamer/static/app.js:3503`; `Client/debugger/static/app.js:3549` | Wrap `src.addr` with existing `escHtml()` in `_statsKV` calls (or inside `_statsKV` itself) | 10 min | — |
| 1.3 | CR-3: WebSocket CSRF (Origin check disabled) | `Common/Client/go/wshub/hub.go:128`; `Source/Applications/StreamHub/WSServer.cpp:186-239` | **Go:** Replace `CheckOrigin: func(r *http.Request) bool { return true }` with a same-origin check (compare `Origin` header host to `Host` header). Add a configurable allowlist env var for non-local deployments. **C++:** Parse `Origin` header in `UpgradeHTTP`; reject if present and host doesn't match the listen address. | 30 min | — |
| 1.4 | CR-4: Unauthenticated command injection to MARTe2 | `Client/debugger/martecontrol.go:217-263` | Add an allowlist of permitted MARTe2 commands (`DISCOVER`, `TREE`, `INFO`, `LS`, `VALUE`, `TRACE`, `UNTRACE`); reject `FORCE`, `UNFORCE`, `PAUSE`, `RESUME`, `STEP`, `BREAK`, `MSG` unless an explicit `--enable-dangerous-commands` flag is set. Log all forwarded commands. | 1 h | 1.3 |
| 1.5 | CR-5: No auth on DebugService TCP | `DebugService.cpp:276` | (a) Bind TCP server to localhost by default (add `BindAddress` config key, default `127.0.0.1`). (b) Add an optional `AuthToken` config key; if set, require the first line from a client to be `AUTH <token>` before accepting commands. | 2 h | — |
**Validation:** `bash -n` on shell scripts; `go build ./...` in each Go module; `make -f Makefile.gcc core apps`; manual test: open browser console on a cross-origin page and confirm WS to `localhost:8090` is rejected; confirm a crafted 65536-byte WS frame no longer corrupts.
**Commit:** `fix(security): critical remote-exploitable fixes (CR-1..CR-5)`
---
## Phase 2 — High-severity crash / OOB / UAF fixes
**Goal:** Eliminate remote crash and memory-corruption vectors. These are the integer-overflow and concurrency bugs.
### 2A — Integer-overflow bounds checks (uniform pattern)
| # | Bug | File(s) | Fix |
|---|-----|---------|-----|
| 2A.1 | HI-1: DATA bounds check overflow | `UDPSourceSession.cpp:358`; `UDPStreamerClient.cpp:520` | Replace `off + elemsToRead * wireElemBytes > size` with 64-bit arithmetic. Add a `validateBounds(off, count, elemBytes, size)` static helper in `UDPSProtocol.h` and use it in both files. |
| 2A.2 | HI-2: Go unbounded allocations | `protocol.go:121, 229, 325` | Add `validateCount(count, elemSize, bufLen)` in `protocol.go`; call before every `make([]T, n)` that uses a network-derived count. Cap `NumElements()` at 1M. |
| 2A.3 | HI-3: `accumFill` overflow + size calc | `UDPStreamer.cpp:700, 738, 757, 857-860` | (a) Add `if (accumFill >= maxBatchCount) { flush; }` before the write at line 857. (b) Use `uint64` for `maxBatchCount * totalSrcBytes` size calculations. |
| 2A.4 | MD-4: `numRows * numCols` overflow | `UDPSourceSession.cpp:240, 346`; `protocol.go:121` | Use `static_cast<uint64>(numRows) * static_cast<uint64>(numCols)`; cap at 1M. |
| 2A.5 | MD-15: `pairCount * 16u` overflow | `Client/streamhub/Protocol.cpp:77, 117` | Check `pairCount > (len - off) / 16` before multiplication; use `ull` suffix. |
| 2A.6 | HI-6: `FD_SET` overflow | `UDPSServer.cpp:273, 308`; `UDPSClient.cpp:383` | Add `if (fd < FD_SETSIZE)` guard before each `FD_SET`; otherwise skip that client this cycle (or switch to `poll()`, which the codebase already uses elsewhere). |
**Est. effort:** 3 h (pattern is repetitive once the helper exists)
### 2B — Use-after-free and concurrency
| # | Bug | File(s) | Fix |
|---|-----|---------|-----|
| 2B.1 | HI-5: Broadcast vs FreeSlot UAF | `WSServer.cpp:345-366, 432-445` | `FreeSlot` must acquire `clients[idx].writeMutex` before setting `active=false` and deleting `sock`. This ensures `BroadcastText`/`BroadcastBinary` cannot dereference a freed socket. |
| 2B.2 | HI-9: TraceRingBuffer not thread-safe | `DebugCore.h:79-142` | Replace `volatile uint32 readIndex/writeIndex` with `Atomic<uint32>` (MARTe2 `Atomic::Load`/`Atomic::Store`). Ensure `Push` writes data before storing `writeIndex` (release ordering); `Pop` loads `writeIndex` before reading data (acquire ordering). |
| 2B.3 | HI-4: `ProcessSignal` unclamped memcpy + `forcedMask` OOB | `DebugServiceBase.cpp:310, 313-318` | (a) Clamp `size` to `sizeof(signalInfo->forcedValue)` (1024). (b) Cap the array-forcing loop at `min(nEl, 256)`. (c) Validate `nEl <= 256` in `RegisterSignal`. |
| 2B.4 | HI-7: Weak PRNG for WS handshake | `WSClient.cpp:29-31` | Replace `srand(time(nullptr))` + `rand()` with `std::random_device` or `getrandom()`/`/dev/urandom` read. |
| 2B.5 | HI-8: Global registry patching | `DebugServiceBase.cpp:217-242` | (a) Save original builders before patching (`item->GetObjectBuilder()`); store in a static array for restore on destruction. (b) Add a `PatchRegistry` config flag (default `true` for back-compat; document the implication). (c) Guard against double-patching (skip if already patched). |
**Est. effort:** 4 h
**Validation:** `make -f Makefile.gcc test` + `./Build/x86-linux/GTest/MainGTest.ex` + `./Build/x86-linux/Test/Integration/Integration/IntegrationTests.ex` + `python3 -m unittest tests_py` (in `Test/E2E/chain/`) + `go test ./...` (in each Go module). Craft a UDP packet with `numSamples=0x20000001` and confirm no crash. Run the E2E suite: `./Test/E2E/chain/run_chain_e2e.sh --skip-build`.
**Commit:** `fix(security): high-severity crash/OOB/UAF fixes (HI-1..HI-9)`
---
## Phase 3 — Medium-severity robustness / DoS / parser fixes
**Goal:** Harden input validation, fix reassembly logic, and improve WS RFC compliance.
### 3A — UDPS protocol hardening
| # | Bug | File(s) | Fix |
|---|-----|---------|-----|
| 3A.1 | MD-1: `recvMask` too small | `UDPSClient.cpp:544, 592-594` | Enlarge `recvMask` to 64 bytes (512 bits) to match the `totalFragments <= 512` cap. |
| 3A.2 | MD-2: No type matching in reassembly | `UDPSClient.cpp:548-555` | Add `type` field to `ReassemblySlot`; key on `counter && type`. |
| 3A.3 | MD-3: Signal name not null-terminated | `UDPSourceSession.cpp:219-223` | After `memcpy`, force `name[63]='\0'` and `unit[31]='\0'`. |
| 3A.4 | MD-6: No auth on UDP CONNECT | `UDPSServer.cpp:655-723` | Document trust boundary in `Docs/Protocol.md`. Optional: add a `ConnectToken` config key. |
| 3A.5 | MD-13: Reassembler unbounded map growth (Go) | `reassembler.go:41-89` | Add `maxSets = 1024` cap; reject new sets when full. |
| 3A.6 | LO-1: `totalFrags` overflow | `UDPSServer.cpp:541-542` | Validate `payloadSize <= maxPayloadSize * 65535` before the calculation. |
| 3A.7 | LO-17: `bufMutex.Create` unchecked | `UDPStreamer.cpp:119`; `UDPStreamerClient.cpp:149` | Check return value; `REPORT_ERROR` on failure. |
| 3A.8 | LO-19: Reassembler ticker panic | `reassembler.go:93` | Guard `if r.expiry <= 0 { r.expiry = 2 * time.Second }`. |
**Est. effort:** 2 h
### 3B — WebSocket and JSON robustness (C++ clients)
| # | Bug | File(s) | Fix |
|---|-----|---------|-----|
| 3B.1 | MD-16: `readU16`/`readU32` silent failure | `Client/streamhub/Protocol.cpp:21-38` | Change `readU16`/`readU32`/`readF64` to return `bool` (or set an `ok` flag); `ParseBinaryFrame` fails fast on any truncated read. |
| 3B.2 | MD-17: JSON injection in command builders | `Client/streamhub/Protocol.cpp:183-213` | Add a `jsonEscape(str)` helper; use it for all `%s` string interpolations. Switch to `std::string` to avoid truncation. |
| 3B.3 | MD-18: `strstr`-based JSON parsing | `Client/streamhub/Protocol.cpp:296-310, 495, 510` | Migrate `ParseSources`, `ParseZoom`, `ParseStats` to a real JSON parser. **ImGui:** add a minimal JSON parser or vendor a single-header library (e.g. nlohmann/json). **Qt:** use `QJsonDocument`. |
| 3B.4 | MD-19: WS RFC 6455 violations | `WSClient.cpp:204-223` | (a) Reject control frames with `payloadLen > 125`. (b) Implement `CONTINUATION` opcode reassembly (or at least log and drop with a clear message). (c) Echo `CLOSE` frame. |
| 3B.5 | MD-20: Handshake no timeout | `WSClient.cpp:290-301` | Set `SO_RCVTIMEO` to 5s on the socket before the handshake loop. |
| 3B.6 | MD-5: SHA1 latent overflow | `SHA1.h:50`; `WSFrame_client.h:113` | Add `if (len > 119u) return;` guard; use `uint64_t bitLen`; use `std::vector` instead of `new[]`/`delete[]`. |
| 3B.7 | MD-24: `parseCapture` panic | `Test/E2E/chain/client/main.go:140-171` | Add bounds checks before each read, mirroring `parsePush`. |
**Est. effort:** 4 h (3B.3 is the largest item — JSON parser migration)
### 3C — Go hub and debugger hardening
| # | Bug | File(s) | Fix |
|---|-----|---------|-----|
| 3C.1 | MD-10: No WS client cap | `hub.go:367-377` | Track `len(h.clients)`; reject above configurable max (default 32). |
| 3C.2 | MD-11: Silent data loss | `hub.go:346-358` | Add a `droppedCount` atomic counter per channel; expose via `Snapshot()`. |
| 3C.3 | MD-12: SSRF via `addSource` | `hub.go:83-96`; `sources.go:62-67` | Validate `addr` against a configurable allowlist (default: localhost + private RFC1918 ranges; reject link-local/metadata endpoints like `169.254.169.254`). |
| 3C.4 | MD-14: Index panic | `martecontrol.go:543` | Use `strings.TrimPrefix(line, "OK SERVICE_INFO ")` with a length check. |
| 3C.5 | LO-14: `stopCh` double-close | `martecontrol.go:182-189` | Use `sync.Once` for closing `stopCh`. |
| 3C.6 | LO-10: `unsafe.Pointer` aliasing | `hub.go:588-594` | Replace `float64ToBytes` with `binary.LittleEndian` put operations. |
| 3C.7 | LO-11: `+Inf` in JSON | `stats.go:115-116` | Guard `if avg > 0 { si.RateHz = 1.0 / avg } else { si.RateHz = 0 }`. |
**Est. effort:** 2 h
### 3D — TcpLogger and DebugService fixes
| # | Bug | File(s) | Fix |
|---|-----|---------|-----|
| 3D.1 | MD-7: `StringHelper::Copy` overflow | `TcpLogger.cpp:87` | Replace with `strncpy(entry.description, description, MAX_ERROR_MESSAGE_SIZE-1); entry.description[MAX_ERROR_MESSAGE_SIZE-1]='\0';` |
| 3D.2 | MD-8: `volatile` indices + lost wakeup | `TcpLogger.cpp:83-153, 157-158` | Use `Atomic::Load`/`Store` for `writeIdx`/`readIdx`; use `eventSem.ResetWait()` instead of `Wait`+`Reset`. |
| 3D.3 | MD-9: `printf` on RT thread | `TcpLogger.cpp:75-76` | Add a `MirrorToStdout` config key (default `false`); guard the `printf`/`fflush` behind it. |
| 3D.4 | MD-21: Stack buffer + shadowed member | `DebugService.cpp:438, 489` | Remove the local `udpsSampleBuf` (use the member); heap-allocate `cfgBuf`. |
| 3D.5 | MD-23: `configValidated` read without lock | `UDPStreamerClient.cpp:463` | Mark `volatile` or acquire `bufMutex` before reading. |
| 3D.6 | MD-22: Spinlock on RT path | `UDPStreamer.cpp:856, 947-976` | Minimize the RT-side critical section: swap a pointer instead of `memcpy` under the lock. Move the `memcpy` outside the lock (double-buffer pattern). |
| 3D.7 | LO-7: JSON escaping in DISCOVER | `DebugServiceBase.cpp:900-906` | Use the existing `EscapeJson` helper for signal names. |
| 3D.8 | LO-8: `EvaluateBreak` only element 0 | `DebugBrokerWrapper.h:61-86` | Document the limitation in the function comment. |
| 3D.9 | LO-9: `fprintf(stderr)` on init | `DebugBrokerWrapper.h:195-197` | Replace with `REPORT_ERROR`. |
**Est. effort:** 3 h
**Validation:** Full test suites + E2E. For 3B.3 (JSON parser migration), add unit tests for crafted JSON inputs (nested quotes, escaped chars, truncated payloads). For 3A.1/3A.2, add a unit test that sends duplicate high-index fragments and mixed-type same-counter fragments.
**Commit:** `fix(robustness): medium-severity input validation, parser, and DoS fixes (MD-1..MD-24)`
---
## Phase 4 — Low-severity hardening and documentation
**Goal:** Clean up latent bugs, fix doc mismatches, add missing hardening. These are non-urgent but improve code health.
| # | Bug | File(s) | Fix |
|---|-----|---------|-----|
| 4.1 | LO-2: `Stop()` TOCTOU | `WSServer.cpp:104-134` | Replace `Sleep(200ms)` with thread join. |
| 4.2 | LO-3: Spinlock priority inversion | `UDPSourceSession.h`; `WSServer.h` | Document that `FastPollingMutexSem` is only for very short critical sections on same-core RT configs. Consider `MutexSem` for non-RT-contended paths. |
| 4.3 | LO-4: `SignalBuffer` mod-0 | `SignalBuffer.h:36-41` | Guard `push`/`readLast`/`readRange` against `capacity == 0`. |
| 4.4 | LO-5: Misleading "Thread-safe" comment | `SignalBuffer.h:18` | Remove the claim or add internal locking. |
| 4.5 | LO-6: GAM type validation + doc | `SineArrayGAM.cpp:81`; `TimeArrayGAM.cpp:54`; `TimeArrayGAM.h:8,27` | Add `GetSignalType` checks; update `TimeArrayGAM.h` doc from `uint32` to `uint64`. |
| 4.6 | LO-12: Directory listing | `Client/webui/main.go:26` | Disable directory listings (return 404 for directories). |
| 4.7 | LO-13: No security headers | `Client/debugger/main.go:55`; `Client/udpstreamer/main.go`; `Client/webui/main.go` | Add a middleware that sets `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Content-Security-Policy: default-src 'self'`. |
| 4.8 | LO-15: `host_`/`port_` race | `WSClient.cpp:48-58` | Protect with `sendMutex_` or make `atomic<uint16_t>` + `std::string` guarded by a small mutex. |
| 4.9 | LO-16: `ReadExactTCP` edge case | `UDPSClient.cpp:474-487` | Add a max-iterations guard. |
| 4.10 | LO-18: `RangeMin < RangeMax` validation | `UDPStreamer.cpp:403-404` | Validate when `quantType != None`; `REPORT_ERROR` if `rangeMax <= rangeMin`. |
**Est. effort:** 2 h
**Commit:** `fix(hardening): low-severity fixes, doc corrections, security headers (LO-1..LO-19)`
---
## Phase 5 — Cross-cutting refactors (optional, post-hardening)
These are not bug fixes but structural improvements that prevent the recurrence of the bug classes found in this audit.
| # | Refactor | Rationale | Est. effort |
|---|----------|-----------|-------------|
| 5.1 | Shared `validateBounds` / `validateCount` helpers | Centralizes the integer-overflow-prevention pattern; prevents future copy-paste bugs | 1 h |
| 5.2 | Real JSON parser in C++ clients (nlohmann/json or Qt's QJsonDocument) | Eliminates the entire class of `strstr`/`snprintf` JSON bugs (MD-16, MD-17, MD-18) | 4 h |
| 5.3 | `poll()`/`epoll` everywhere (replace all `select`+`FD_SET`) | Eliminates the `FD_SETSIZE` limitation entirely (HI-6) | 2 h |
| 5.4 | Auth framework for DebugService + web UIs | Token-based auth shared between the Go web UIs and the C++ DebugService; eliminates the "no auth anywhere" theme | 1 d |
| 5.5 | Fuzzing harness for UDPS protocol parsers | `libFuzzer` or `go-fuzz` harnesses that feed random bytes to `ParseConfig`/`ParseData`/`DecodeElems`/`ParseBinaryFrame`; catches future overflow variants | 1 d |
| 5.6 | Thread-sanitizer and address-sanitizer CI runs | `make CXXFLAGS="-fsanitize=address,undefined"`; `go test -race`; catches UAF and races automatically | 4 h |
---
## Verification checklist (run after each phase)
```bash
source env.sh
# C++ build + tests
make -f Makefile.gcc clean
make -f Makefile.gcc core apps test
./Build/x86-linux/GTest/MainGTest.ex
./Build/x86-linux/Test/Integration/Integration/IntegrationTests.ex
# Go tests (each module)
cd Common/Client/go && go vet ./... && go test ./... && cd -
cd Client/debugger && go vet ./... && go build ./... && cd -
cd Client/udpstreamer && go vet ./... && go build ./... && cd -
cd Test/E2E/chain/client && go vet ./... && go test ./... && cd -
# Python framework tests
cd Test/E2E/chain && python3 -m unittest tests_py && cd -
# Full E2E suite
./Test/E2E/chain/run_chain_e2e.sh --skip-build
# ASan/UBSan smoke test (after Phase 2+)
make -f Makefile.gcc clean
make -f Makefile.gcc CXXFLAGS="-fsanitize=address,undefined -g" core apps
./Build/x86-linux/GTest/MainGTest.ex
```
---
## Timeline summary
| Phase | Scope | Est. effort | Risk reduction |
|-------|-------|-------------|----------------|
| 1 | Critical remote-exploitable (CR-1..CR-5) | ~4 h | Eliminates drive-by takeover + heap corruption |
| 2 | High crash/OOB/UAF (HI-1..HI-9) | ~7 h | Eliminates remote crash + memory corruption |
| 3 | Medium robustness/DoS/parser (MD-1..MD-24) | ~11 h | Hardens input validation + RFC compliance |
| 4 | Low hardening/doc (LO-1..LO-19) | ~2 h | Code health + defense in depth |
| 5 | Cross-cutting refactors (optional) | ~3 d | Prevents recurrence of bug classes |
**Total (Phases 1-4):** ~24 h of focused work. Phase 5 is optional and can be scheduled separately.
+1011
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -37,9 +37,9 @@ cd Client/streamhub && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --buil
cd Client/streamhub-qt && cmake -B build && cmake --build build cd Client/streamhub-qt && cmake -B build && cmake --build build
``` ```
End-to-end demo scripts (build + launch full stack, see headers for ports/options): `./run_combined_test.sh`, `./run_streamhub.sh`. End-to-end demo script (build + launch full stack, see header for ports/options): `./run_streamhub.sh`.
**Streaming-chain E2E suite** (`Test/E2E/chain/`): `./run_chain_e2e.sh [--skip-build] [--only <id>] [--cpp-coverage] [--stress]` drives the full chain per scenario (`scenarios.py`) — generates typed/shaped input + both cfgs, runs MARTe2+StreamHub, records via the Go `chain-client` (live/zoom/window/trigger), and validates the recorded waveform against an analytic/fed oracle (`validate_waveform.py`: fidelity gates correctness, sine shape-fit is a gross-sanity gate + tracked metric pending Phase-A timestamp calibration). It then runs the unit suites + coverage (`collect.py`: C++ GTest, Go, Python; `--cpp-coverage` does an instrumented `--coverage` rebuild, captures with lcov restricted to `Source/*`+`Test/*`, then restores the clean build), consolidates everything into `report_data.json` with per-field progression/regression vs the previous run and trend plots (`report_build.py`, history in `Build/x86-linux/E2E/chain/history.jsonl`), and compiles a Typst PDF (`E2E_Report.typ`). A `--stress` flag additionally runs the capacity matrix (`stress.py` declarative axes → `stress_run.py` orchestrator → `stress_results.json`): it sweeps signal size (into the multi-fragment >64 KB regime), signal count, source count, WS-client count, subscriber fan-out, and zoom request-rate one axis at a time, gating survival + liveness (hard) and peak RSS + zoom-p95 latency (soft), and embeds a Stress Tests section (per-case table + per-axis scaling curves, with regression vs the previous run) into the PDF. Standalone: `./run_stress.sh [--skip-build] [--only <id>] [--axis <axis>]`. Python framework unit tests: `python3 -m unittest tests_py` (in `Test/E2E/chain/`). **Streaming-chain E2E suite** (`Test/E2E/suite/`): `./run_e2e.sh [--skip-build] [--only <id>] [--cpp-coverage]` drives the full chain per scenario (`scenarios.py`) — generates typed/shaped input + both cfgs, runs MARTe2+StreamHub, records via the Go `chain-client` (live/zoom/window/trigger), and validates the recorded waveform against an analytic/fed oracle (`validate_waveform.py`: fidelity gates correctness, sine shape-fit is a gross-sanity gate + tracked metric pending Phase-A timestamp calibration). It then runs the unit suites + coverage (`collect.py`: C++ GTest, Go, Python; `--cpp-coverage` does an instrumented `--coverage` rebuild, captures with lcov restricted to `Source/*` (the `Test/` harness itself is excluded — it executes every line by construction and would just inflate the number), then restores the clean build), consolidates everything into `report_data.json` with per-field progression/regression vs the previous run and trend plots (`report_build.py`, history in `Build/x86-linux/E2E/chain/history.jsonl`), and compiles a Typst PDF (`E2E_Report.typ`). Python framework unit tests: `python3 -m unittest tests_py` (in `Test/E2E/suite/`).
Build output goes to `Build/x86-linux/` (shared libs per component, `.ex` executables). Build output goes to `Build/x86-linux/` (shared libs per component, `.ex` executables).
@@ -0,0 +1,54 @@
package controller
import (
"testing"
)
// TestIsDangerousCommand_Force — FORCE is dangerous.
func TestIsDangerousCommand_Force(t *testing.T) {
if !isDangerousCommand("FORCE signal 1.0") {
t.Error("FORCE should be dangerous")
}
}
// TestIsDangerousCommand_Pause — PAUSE is dangerous.
func TestIsDangerousCommand_Pause(t *testing.T) {
if !isDangerousCommand("PAUSE") {
t.Error("PAUSE should be dangerous")
}
}
// TestIsDangerousCommand_Msg — MSG is dangerous.
func TestIsDangerousCommand_Msg(t *testing.T) {
if !isDangerousCommand("MSG target func") {
t.Error("MSG should be dangerous")
}
}
// TestIsDangerousCommand_CaseInsensitive — case-insensitive.
func TestIsDangerousCommand_CaseInsensitive(t *testing.T) {
if !isDangerousCommand("force signal 1.0") {
t.Error("lowercase force should be dangerous")
}
}
// TestIsDangerousCommand_SafeCommand — DISCOVER is not dangerous.
func TestIsDangerousCommand_SafeCommand(t *testing.T) {
if isDangerousCommand("DISCOVER") {
t.Error("DISCOVER should not be dangerous")
}
}
// TestIsDangerousCommand_TraceNotDangerous — TRACE is not dangerous (read-only).
func TestIsDangerousCommand_TraceNotDangerous(t *testing.T) {
if isDangerousCommand("TRACE signal 1") {
t.Error("TRACE should not be dangerous")
}
}
// TestIsDangerousCommand_Empty — empty command is not dangerous.
func TestIsDangerousCommand_Empty(t *testing.T) {
if isDangerousCommand("") {
t.Error("empty command should not be dangerous")
}
}
@@ -1,4 +1,9 @@
package main // Package controller implements MarteController, the shared TCP/UDP client
// logic that drives a running MARTe2 DebugService+TCPLogger instance. It is
// consumed both by the Client/debugger browser-facing WebSocket server
// (package main, via NewMarteController) and headlessly by the
// Test/E2E/suite/debugclient E2E test tool (via NewHeadlessMarteController).
package controller
import ( import (
"bufio" "bufio"
@@ -17,6 +22,40 @@ import (
"marte2/common/wshub" "marte2/common/wshub"
) )
// ---------------------------------------------------------------------------
// Command safety gate (CR-4)
// ---------------------------------------------------------------------------
// DangerousCommandsEnabled gates commands that mutate the RT application state
// (FORCE, PAUSE, RESUME, STEP, BREAK, MSG). Set via --enable-dangerous-commands.
var DangerousCommandsEnabled = false
// dangerousCommands is the set of MARTe2 commands that can change signal values
// or alter execution flow. Without --enable-dangerous-commands these are blocked
// from the browser WebSocket path.
var dangerousCommands = map[string]bool{
"FORCE": true,
"UNFORCE": true,
"PAUSE": true,
"RESUME": true,
"STEP": true,
"BREAK": true,
"UNBREAK": true,
"MSG": true,
"LOAD": true,
"UNLOAD": true,
}
// isDangerousCommand returns true if the command's first word is in the
// dangerous set (case-insensitive).
func isDangerousCommand(cmd string) bool {
parts := strings.Fields(cmd)
if len(parts) == 0 {
return false
}
return dangerousCommands[strings.ToUpper(parts[0])]
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Signal metadata (populated by DISCOVER) // Signal metadata (populated by DISCOVER)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -48,6 +87,7 @@ func broadcastHub(hub *wshub.Hub, v any) {
type MarteController struct { type MarteController struct {
hub *wshub.Hub hub *wshub.Hub
sink func(v any)
mu sync.Mutex mu sync.Mutex
tcpConn net.Conn tcpConn net.Conn
@@ -101,6 +141,7 @@ func NewMarteController(hub *wshub.Hub) *MarteController {
forcedState: make(map[string]string), forcedState: make(map[string]string),
stopCh: make(chan struct{}), stopCh: make(chan struct{}),
} }
mc.sink = func(v any) { broadcastHub(mc.hub, v) }
// Register the new-client hook so connection + forced/traced state is // Register the new-client hook so connection + forced/traced state is
// replayed to any browser that connects (or reconnects) while the server // replayed to any browser that connects (or reconnects) while the server
// already holds a live MARTe2 TCP session. // already holds a live MARTe2 TCP session.
@@ -108,6 +149,20 @@ func NewMarteController(hub *wshub.Hub) *MarteController {
return mc return mc
} }
// NewHeadlessMarteController creates a MarteController with no WebSocket hub,
// routing all events through sink instead (used by the debugclient E2E test tool).
func NewHeadlessMarteController(sink func(v any)) *MarteController {
mc := &MarteController{
hub: nil,
signals: make(map[uint32]*SignalMeta),
tracedNames: make(map[string]bool),
forcedState: make(map[string]string),
stopCh: make(chan struct{}),
}
mc.sink = sink
return mc
}
func (m *MarteController) IsConnected() bool { func (m *MarteController) IsConnected() bool {
return atomic.LoadInt32(&m.connected) == 1 return atomic.LoadInt32(&m.connected) == 1
} }
@@ -166,10 +221,13 @@ func (m *MarteController) Connect(host string, cmdPort, udpPort, logPort int) {
m.stopCh = make(chan struct{}) m.stopCh = make(chan struct{})
m.mu.Unlock() m.mu.Unlock()
// Update source state so the browser shows "connecting". // Update source state so the browser shows "connecting". No-op headless
// (m.hub == nil for NewHeadlessMarteController instances).
if m.hub != nil {
m.hub.SetSourceState("debug", "connecting") m.hub.SetSourceState("debug", "connecting")
}
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "log", "time": time.Now().Format("15:04:05.000"), "type": "log", "time": time.Now().Format("15:04:05.000"),
"level": "INFO", "message": fmt.Sprintf("Connecting to %s cmd=%d udp=%d log=%d", host, cmdPort, udpPort, logPort), "level": "INFO", "message": fmt.Sprintf("Connecting to %s cmd=%d udp=%d log=%d", host, cmdPort, udpPort, logPort),
}) })
@@ -198,7 +256,9 @@ func (m *MarteController) Disconnect() {
m.baseTsSet = false m.baseTsSet = false
m.basesMu.Unlock() m.basesMu.Unlock()
m.discoverAcc = nil m.discoverAcc = nil
if m.hub != nil {
m.hub.SetSourceState("debug", "disconnected") m.hub.SetSourceState("debug", "disconnected")
}
} }
func (m *MarteController) stopped() bool { func (m *MarteController) stopped() bool {
@@ -256,11 +316,26 @@ func (m *MarteController) HandleBrowserCommand(msg []byte) {
return return
} }
cmd, _ := data["cmd"].(string) cmd, _ := data["cmd"].(string)
if cmd != "" { if cmd == "" {
return
}
// Gate dangerous commands (FORCE/UNFORCE/PAUSE/RESUME/STEP/BREAK/MSG)
// behind an explicit opt-in flag. Without it, only read-only commands
// (DISCOVER, TREE, INFO, LS, VALUE, TRACE, UNTRACE, STEP_STATUS) are
// forwarded to the MARTe2 TCP control connection.
if isDangerousCommand(cmd) {
if !DangerousCommandsEnabled {
m.sink(map[string]any{
"type": "log", "time": time.Now().Format("15:04:05.000"),
"level": "WARNING",
"message": fmt.Sprintf("Blocked dangerous command (requires --enable-dangerous-commands): %s", cmd),
})
return
}
}
m.trackForcedCmd(cmd) m.trackForcedCmd(cmd)
m.SendCommand(cmd) m.SendCommand(cmd)
} }
}
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -272,7 +347,7 @@ func (m *MarteController) runTCP(host string, port int) {
for !m.stopped() { for !m.stopped() {
conn, err := net.DialTimeout("tcp", addr, 5*time.Second) conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
if err != nil { if err != nil {
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "log", "time": time.Now().Format("15:04:05.000"), "type": "log", "time": time.Now().Format("15:04:05.000"),
"level": "WARNING", "message": fmt.Sprintf("TCP %s: %v — retrying…", addr, err), "level": "WARNING", "message": fmt.Sprintf("TCP %s: %v — retrying…", addr, err),
}) })
@@ -287,7 +362,7 @@ func (m *MarteController) runTCP(host string, port int) {
m.mu.Unlock() m.mu.Unlock()
atomic.StoreInt32(&m.connected, 1) atomic.StoreInt32(&m.connected, 1)
broadcastHub(m.hub, map[string]any{"type": "connected"}) m.sink(map[string]any{"type": "connected"})
// Send SERVICE_INFO to auto-discover ports // Send SERVICE_INFO to auto-discover ports
m.writeCmd("SERVICE_INFO") m.writeCmd("SERVICE_INFO")
@@ -297,7 +372,7 @@ func (m *MarteController) runTCP(host string, port int) {
m.readLoop(conn) m.readLoop(conn)
atomic.StoreInt32(&m.connected, 0) atomic.StoreInt32(&m.connected, 0)
broadcastHub(m.hub, map[string]any{"type": "disconnected"}) m.sink(map[string]any{"type": "disconnected"})
m.mu.Lock() m.mu.Lock()
m.tcpConn = nil m.tcpConn = nil
@@ -323,7 +398,7 @@ func (m *MarteController) writeCmd(cmd string) {
silent := cmd == "STEP_STATUS" || cmd == "INFO" silent := cmd == "STEP_STATUS" || cmd == "INFO"
if !silent { if !silent {
log.Printf("[→MARTe] %s", cmd) log.Printf("[→MARTe] %s", cmd)
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "log", "time": time.Now().Format("15:04:05.000"), "type": "log", "time": time.Now().Format("15:04:05.000"),
"level": "CMD", "message": fmt.Sprintf("→ %s", cmd), "level": "CMD", "message": fmt.Sprintf("→ %s", cmd),
}) })
@@ -465,7 +540,7 @@ func (m *MarteController) handleJSONResponse(tag, data string) {
silent := tag == "STEP_STATUS" || tag == "INFO" silent := tag == "STEP_STATUS" || tag == "INFO"
if !silent { if !silent {
log.Printf("[←MARTe] %s %d bytes", tag, len(data)) log.Printf("[←MARTe] %s %d bytes", tag, len(data))
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "log", "time": time.Now().Format("15:04:05.000"), "type": "log", "time": time.Now().Format("15:04:05.000"),
"level": "RESP", "message": fmt.Sprintf("← %s (%d B)", tag, len(data)), "level": "RESP", "message": fmt.Sprintf("← %s (%d B)", tag, len(data)),
}) })
@@ -500,25 +575,27 @@ func (m *MarteController) handleJSONResponse(tag, data string) {
raw := m.rawSigs raw := m.rawSigs
m.rawSigsMu.RUnlock() m.rawSigsMu.RUnlock()
if len(raw) > 0 { if len(raw) > 0 {
if m.hub != nil {
m.hub.UpdateConfigForSource("debug", m.translateSignalNames(raw)) m.hub.UpdateConfigForSource("debug", m.translateSignalNames(raw))
}
} else { } else {
m.synthesizeHubConfig(all) m.synthesizeHubConfig(all)
} }
// Re-marshal the merged list so the browser gets a single consistent blob. // Re-marshal the merged list so the browser gets a single consistent blob.
merged, _ := json.Marshal(discoverResp{Signals: all}) merged, _ := json.Marshal(discoverResp{Signals: all})
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "response", "tag": "DISCOVER", "data": string(merged), "type": "response", "tag": "DISCOVER", "data": string(merged),
}) })
return return
case "TREE": case "TREE":
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "tree_node", "type": "tree_node",
"data": data, "data": data,
}) })
return return
} }
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "response", "type": "response",
"tag": tag, "tag": tag,
"data": data, "data": data,
@@ -537,13 +614,13 @@ func (m *MarteController) handleTextLine(line string) {
fmt.Sscanf(p[8:], "%d", &newLog) fmt.Sscanf(p[8:], "%d", &newLog)
} }
} }
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "response", "type": "response",
"tag": "SERVICE_INFO", "tag": "SERVICE_INFO",
"data": line[len("OK SERVICE_INFO "):], "data": line[len("OK SERVICE_INFO "):],
}) })
if newUDP > 0 || newLog > 0 { if newUDP > 0 || newLog > 0 {
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "service_config", "type": "service_config",
"udp_port": newUDP, "udp_port": newUDP,
"log_port": newLog, "log_port": newLog,
@@ -567,7 +644,7 @@ func (m *MarteController) handleTextLine(line string) {
} }
} }
} }
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "text_line", "type": "text_line",
"data": line, "data": line,
}) })
@@ -774,7 +851,9 @@ func (m *MarteController) synthesizeHubConfig(sigs []discoverSignalJSON) {
// buffer and limiting live streaming to the fraction of a second that // buffer and limiting live streaming to the fraction of a second that
// accumulated before the DISCOVER response arrived. // accumulated before the DISCOVER response arrived.
translated := m.translateSignalNames(sigInfos) translated := m.translateSignalNames(sigInfos)
if m.hub != nil {
m.hub.UpdateConfigForSource("debug", translated) m.hub.UpdateConfigForSource("debug", translated)
}
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -801,7 +880,7 @@ func (m *MarteController) runDebugUDP(host string, port int) {
if err != nil { if err != nil {
msg := fmt.Sprintf("UDP bind on %s failed: %v — rebuild DebugService C++ and restart", addr, err) msg := fmt.Sprintf("UDP bind on %s failed: %v — rebuild DebugService C++ and restart", addr, err)
log.Printf("[debug-udp] %s", msg) log.Printf("[debug-udp] %s", msg)
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "log", "time": time.Now().Format("15:04:05.000"), "type": "log", "time": time.Now().Format("15:04:05.000"),
"level": "ERROR", "message": msg, "level": "ERROR", "message": msg,
}) })
@@ -812,7 +891,7 @@ func (m *MarteController) runDebugUDP(host string, port int) {
conn.SetReadBuffer(10 * 1024 * 1024) conn.SetReadBuffer(10 * 1024 * 1024)
log.Printf("[debug-udp] listening on %s for UDPS packets", addr) log.Printf("[debug-udp] listening on %s for UDPS packets", addr)
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "log", "time": time.Now().Format("15:04:05.000"), "type": "log", "time": time.Now().Format("15:04:05.000"),
"level": "INFO", "message": fmt.Sprintf("UDP listener bound on %s", addr), "level": "INFO", "message": fmt.Sprintf("UDP listener bound on %s", addr),
}) })
@@ -865,8 +944,10 @@ func (m *MarteController) runDebugUDP(host string, port int) {
sigs = m.translateSignalNames(sigs) sigs = m.translateSignalNames(sigs)
currentSigs = sigs currentSigs = sigs
currentPublishMode = pm currentPublishMode = pm
if m.hub != nil {
m.hub.UpdateConfigForSource("debug", sigs) m.hub.UpdateConfigForSource("debug", sigs)
m.hub.SetSourceState("debug", "connected") m.hub.SetSourceState("debug", "connected")
}
case udpsprotocol.PktData: case udpsprotocol.PktData:
if len(currentSigs) == 0 { if len(currentSigs) == 0 {
@@ -888,11 +969,13 @@ func (m *MarteController) runDebugUDP(host string, port int) {
log.Printf("[debug-udp] parse data: %v", err) log.Printf("[debug-udp] parse data: %v", err)
continue continue
} }
if m.hub != nil {
for _, s := range samples { for _, s := range samples {
m.hub.PushDataForSource("debug", s) m.hub.PushDataForSource("debug", s)
} }
} }
} }
}
log.Printf("[debug-udp] stopped") log.Printf("[debug-udp] stopped")
} }
@@ -923,7 +1006,7 @@ func (m *MarteController) runLog(host string, port int) {
} }
level := rest[:idx] level := rest[:idx]
msg := rest[idx+1:] msg := rest[idx+1:]
broadcastHub(m.hub, map[string]any{ m.sink(map[string]any{
"type": "log", "type": "log",
"time": time.Now().Format("15:04:05.000"), "time": time.Now().Format("15:04:05.000"),
"level": level, "level": level,
+5 -1
View File
@@ -10,6 +10,8 @@ import (
"net/http" "net/http"
"os" "os"
"marte2debugger/controller"
"marte2/common/wshub" "marte2/common/wshub"
) )
@@ -21,13 +23,15 @@ var staticFiles embed.FS
func main() { func main() {
addr := flag.String("addr", ":7777", "HTTP listen address") addr := flag.String("addr", ":7777", "HTTP listen address")
sourcesFile := flag.String("sources-file", "", "JSON file for persistent source list") sourcesFile := flag.String("sources-file", "", "JSON file for persistent source list")
flag.BoolVar(&controller.DangerousCommandsEnabled, "enable-dangerous-commands", false,
"Allow FORCE/PAUSE/RESUME/STEP/BREAK/MSG commands from the browser (CR-4 safety gate)")
flag.Parse() flag.Parse()
hub := wshub.NewHub() hub := wshub.NewHub()
sm := wshub.NewSourceManager(hub, *sourcesFile) sm := wshub.NewSourceManager(hub, *sourcesFile)
hub.SetSourceManager(sm) hub.SetSourceManager(sm)
ctrl := NewMarteController(hub) ctrl := controller.NewMarteController(hub)
go hub.Run() go hub.Run()
+1 -1
View File
@@ -3511,7 +3511,7 @@ function _fmtHz(v) { return v != null && isFinite(v) && v > 0 ? v.toFixed(2) + '
function _fmtKB(v) { return v != null && isFinite(v) ? (v / 1024).toFixed(2) + ' KB' : '—'; } function _fmtKB(v) { return v != null && isFinite(v) ? (v / 1024).toFixed(2) + ' KB' : '—'; }
function _statsKV(label, value, cls) { function _statsKV(label, value, cls) {
return `<div class="stats-kv"><span class="stats-k">${label}</span><span class="stats-v${cls ? ' ' + cls : ''}">${value}</span></div>`; return `<div class="stats-kv"><span class="stats-k">${escHtml(label)}</span><span class="stats-v${cls ? ' ' + cls : ''}">${escHtml(value)}</span></div>`;
} }
function _histHTML(si) { function _histHTML(si) {
+13 -4
View File
@@ -18,18 +18,27 @@
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
#include <chrono> #include <chrono>
#include <random>
namespace StreamHubClient { namespace StreamHubClient {
/* ── Helpers ─────────────────────────────────────────────────────────────── */ /* ── Helpers ─────────────────────────────────────────────────────────────── */
static std::string base64Key() { static std::string base64Key() {
/* Generate 16 random bytes and base64-encode them */ /* HI-7: use /dev/urandom (CSPRNG) instead of srand(time)/rand() */
uint8_t raw[16]; uint8_t raw[16];
srand(static_cast<unsigned>(time(nullptr))); int fd = open("/dev/urandom", O_RDONLY);
for (int i = 0; i < 16; i++) { if (fd < 0 || read(fd, raw, sizeof(raw)) != static_cast<ssize_t>(sizeof(raw))) {
raw[i] = static_cast<uint8_t>(rand() & 0xFF); /* Fallback: std::random_device (still better than srand/rand) */
std::random_device rd;
for (size_t i = 0; i < sizeof(raw); i += sizeof(unsigned)) {
unsigned val = rd();
for (size_t j = 0; j < sizeof(unsigned) && i + j < sizeof(raw); j++) {
raw[i + j] = static_cast<uint8_t>(val >> (j * 8));
} }
}
}
if (fd >= 0) { close(fd); }
char out[32]; char out[32];
WS_Base64Encode(raw, 16, out); WS_Base64Encode(raw, 16, out);
return std::string(out); return std::string(out);
Binary file not shown.
+1 -1
View File
@@ -3465,7 +3465,7 @@ function _fmtHz(v) { return v != null && isFinite(v) && v > 0 ? v.toFixed(2) + '
function _fmtKB(v) { return v != null && isFinite(v) ? (v / 1024).toFixed(2) + ' KB' : '—'; } function _fmtKB(v) { return v != null && isFinite(v) ? (v / 1024).toFixed(2) + ' KB' : '—'; }
function _statsKV(label, value, cls) { function _statsKV(label, value, cls) {
return `<div class="stats-kv"><span class="stats-k">${label}</span><span class="stats-v${cls ? ' ' + cls : ''}">${value}</span></div>`; return `<div class="stats-kv"><span class="stats-k">${escHtml(label)}</span><span class="stats-v${cls ? ' ' + cls : ''}">${escHtml(value)}</span></div>`;
} }
function _histHTML(si) { function _histHTML(si) {
+15 -1
View File
@@ -127,7 +127,12 @@ func (s SignalInfo) NumElements() int {
if c == 0 { if c == 0 {
c = 1 c = 1
} }
return r * c /* HI-2: cap at 1M to prevent integer overflow / OOM from crafted packets */
n := r * c
if n < 0 || n > 1024*1024 {
return 1024 * 1024
}
return n
} }
// rawTypeSize returns the byte size for one element of the raw (unquantised) type. // rawTypeSize returns the byte size for one element of the raw (unquantised) type.
@@ -227,6 +232,11 @@ func ParseConfig(payload []byte) ([]SignalInfo, uint8, error) {
return nil, 0, fmt.Errorf("config payload too short") return nil, 0, fmt.Errorf("config payload too short")
} }
numSigs := binary.LittleEndian.Uint32(payload[0:4]) numSigs := binary.LittleEndian.Uint32(payload[0:4])
/* HI-2: validate numSigs against payload length before allocating */
maxSigs := uint32(len(payload) / SigDescSize)
if numSigs > maxSigs {
return nil, 0, fmt.Errorf("config claims %d signals but payload can hold at most %d", numSigs, maxSigs)
}
offset := 4 offset := 4
sigs := make([]SignalInfo, 0, numSigs) sigs := make([]SignalInfo, 0, numSigs)
for i := uint32(0); i < numSigs; i++ { for i := uint32(0); i < numSigs; i++ {
@@ -327,6 +337,10 @@ func ParseData(payload []byte, sigs []SignalInfo, publishMode uint8, arrivalTime
if numSamples == 0 { if numSamples == 0 {
return []DataSample{}, nil return []DataSample{}, nil
} }
/* HI-2: sanity-cap numSamples to prevent OOM from crafted packets */
if numSamples < 0 || numSamples > 1024*1024 {
return nil, fmt.Errorf("accumulate numSamples %d out of range", numSamples)
}
// Parse per-signal data blocks (all slots for a signal are contiguous). // Parse per-signal data blocks (all slots for a signal are contiguous).
accumVals := make(map[string][]float64, len(sigs)) // scalars: numSamples values accumVals := make(map[string][]float64, len(sigs)) // scalars: numSamples values
@@ -0,0 +1,97 @@
package udpsprotocol
import (
"encoding/binary"
"math"
"testing"
"time"
)
// TestParseConfig_HugeNumSigs_NoOOM — a CONFIG payload claiming 0xFFFFFFFF signals
// must return an error, not panic/OOM.
func TestParseConfig_HugeNumSigs_NoOOM(t *testing.T) {
// 4 bytes: numSigs = 0xFFFFFFFF, then nothing else
payload := make([]byte, 4)
binary.LittleEndian.PutUint32(payload[0:4], 0xFFFFFFFF)
sigs, _, err := ParseConfig(payload)
if err == nil {
t.Fatal("expected error for huge numSigs, got nil")
}
if sigs != nil {
t.Fatalf("expected nil sigs, got %d", len(sigs))
}
}
// TestParseConfig_ValidSmallConfig — a minimal valid CONFIG parses correctly.
func TestParseConfig_ValidSmallConfig(t *testing.T) {
// 1 signal, then publish mode
payload := make([]byte, 4+SigDescSize+1)
binary.LittleEndian.PutUint32(payload[0:4], 1)
// Set typeCode to float32 (8) at offset 64
payload[4+64] = 8
// numRows=1, numCols=1 at offsets 67, 71
binary.LittleEndian.PutUint32(payload[4+67:4+71], 1)
binary.LittleEndian.PutUint32(payload[4+71:4+75], 1)
// publish mode = 0 (Strict)
payload[4+SigDescSize] = 0
sigs, pm, err := ParseConfig(payload)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(sigs) != 1 {
t.Fatalf("expected 1 signal, got %d", len(sigs))
}
if pm != PublishModeStrict {
t.Fatalf("expected Strict mode, got %d", pm)
}
}
// TestNumElements_OverflowCapped — huge numRows*numCols is capped, no panic.
func TestNumElements_OverflowCapped(t *testing.T) {
s := SignalInfo{NumRows: 0xFFFFFFFF, NumCols: 0xFFFFFFFF}
n := s.NumElements()
if n <= 0 || n > 1024*1024 {
t.Fatalf("expected capped value 1M, got %d", n)
}
}
// TestNumElements_Normal — normal values work correctly.
func TestNumElements_Normal(t *testing.T) {
s := SignalInfo{NumRows: 3, NumCols: 4}
if n := s.NumElements(); n != 12 {
t.Fatalf("expected 12, got %d", n)
}
}
// TestParseData_HugeNumSamples_NoOOM — an Accumulate DATA packet with
// numSamples=0xFFFFFFFF must return an error, not OOM.
func TestParseData_HugeNumSamples_NoOOM(t *testing.T) {
sigs := []SignalInfo{
{Name: "test", TypeCode: 8, NumRows: 1, NumCols: 1, QuantType: QuantNone},
}
payload := make([]byte, 12)
binary.LittleEndian.PutUint64(payload[0:8], 0) // HRT
binary.LittleEndian.PutUint32(payload[8:12], 0xFFFFFFFF)
_, err := ParseData(payload, sigs, PublishModeAccumulate, time.Now())
if err == nil {
t.Fatal("expected error for huge numSamples, got nil")
}
}
// TestParseData_ValidStrict — a valid Strict DATA packet parses without error.
func TestParseData_ValidStrict(t *testing.T) {
sigs := []SignalInfo{
{Name: "test", TypeCode: 8, NumRows: 1, NumCols: 1, QuantType: QuantNone},
}
// 8 HRT + 4 bytes float32
payload := make([]byte, 12)
binary.LittleEndian.PutUint64(payload[0:8], 1000)
binary.LittleEndian.PutUint32(payload[8:12], math.Float32bits(3.14))
samples, err := ParseData(payload, sigs, PublishModeStrict, time.Now())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(samples) != 1 {
t.Fatalf("expected 1 sample, got %d", len(samples))
}
}
+39 -1
View File
@@ -122,10 +122,48 @@ func (c *wsClient) readPump() {
// ─── Hub ───────────────────────────────────────────────────────────────────── // ─── Hub ─────────────────────────────────────────────────────────────────────
// allowedOrigins is the set of Origin values (scheme://host[:port]) that are
// accepted for WebSocket upgrades. If empty, same-origin is enforced by
// comparing the Origin's host to the HTTP Host header.
var allowedOrigins []string
// SetAllowedOrigins configures the WebSocket Origin allowlist. Pass an empty
// slice to enforce same-origin only (the default).
func SetAllowedOrigins(origins []string) {
allowedOrigins = origins
}
// checkOrigin validates the Origin header against the allowlist, falling back
// to a same-origin check (Origin host == Host header) when no allowlist is
// configured. Requests with no Origin header (non-browser clients) are allowed.
func checkOrigin(r *http.Request) bool {
origin := r.Header.Get("Origin")
if origin == "" {
return true // non-browser client
}
// Check explicit allowlist first.
for _, allowed := range allowedOrigins {
if origin == allowed {
return true
}
}
// Fall back to same-origin: compare the Origin's host to the Host header.
// Origin format: "scheme://host[:port]" — strip scheme.
host := origin
if idx := strings.Index(host, "://"); idx >= 0 {
host = host[idx+3:]
}
// Strip path if present.
if idx := strings.Index(host, "/"); idx >= 0 {
host = host[:idx]
}
return host == r.Host
}
var upgrader = websocket.Upgrader{ var upgrader = websocket.Upgrader{
ReadBufferSize: 4096, ReadBufferSize: 4096,
WriteBufferSize: 64 * 1024, WriteBufferSize: 64 * 1024,
CheckOrigin: func(r *http.Request) bool { return true }, CheckOrigin: checkOrigin,
} }
// sourceHubState holds all data for one active data source. // sourceHubState holds all data for one active data source.
+72
View File
@@ -0,0 +1,72 @@
package wshub
import (
"net/http"
"testing"
)
// TestCheckOrigin_NoOriginHeader — non-browser clients (no Origin) are allowed.
func TestCheckOrigin_NoOriginHeader(t *testing.T) {
r := &http.Request{Header: http.Header{}}
if !checkOrigin(r) {
t.Fatal("non-browser client (no Origin header) should be allowed")
}
}
// TestCheckOrigin_SameOrigin — Origin host matching Host header is allowed.
func TestCheckOrigin_SameOrigin(t *testing.T) {
r := &http.Request{
Header: http.Header{
"Origin": []string{"http://localhost:8090"},
},
Host: "localhost:8090",
}
if !checkOrigin(r) {
t.Fatal("same-origin request should be allowed")
}
}
// TestCheckOrigin_CrossOriginBlocked — different Origin host is rejected.
func TestCheckOrigin_CrossOriginBlocked(t *testing.T) {
r := &http.Request{
Header: http.Header{
"Origin": []string{"http://evil.example.com:8090"},
},
Host: "localhost:8090",
}
if checkOrigin(r) {
t.Fatal("cross-origin request should be blocked")
}
}
// TestCheckOrigin_Allowlist — explicitly allowed origins pass even if cross-origin.
func TestCheckOrigin_Allowlist(t *testing.T) {
SetAllowedOrigins([]string{"http://evil.example.com:8090"})
defer SetAllowedOrigins(nil) // reset
r := &http.Request{
Header: http.Header{
"Origin": []string{"http://evil.example.com:8090"},
},
Host: "localhost:8090",
}
if !checkOrigin(r) {
t.Fatal("allowlisted origin should be allowed")
}
}
// TestCheckOrigin_AllowlistDoesNotMatch — non-allowlisted cross-origin is blocked.
func TestCheckOrigin_AllowlistDoesNotMatch(t *testing.T) {
SetAllowedOrigins([]string{"http://good.example.com"})
defer SetAllowedOrigins(nil)
r := &http.Request{
Header: http.Header{
"Origin": []string{"http://evil.example.com"},
},
Host: "localhost:8090",
}
if checkOrigin(r) {
t.Fatal("non-allowlisted cross-origin should be blocked")
}
}
+10 -14
View File
@@ -199,28 +199,24 @@ make -f Makefile.gcc test
# SignalRingBuffer (ReadSince / binary-search ReadRange / wrap), # SignalRingBuffer (ReadSince / binary-search ReadRange / wrap),
# TriggerEngine FSM, LTTB — sources in Test/Applications/StreamHub/ # TriggerEngine FSM, LTTB — sources in Test/Applications/StreamHub/
./run_e2e_test.sh # full-stack E2E (see below) cd Test/E2E/suite && ./run_e2e.sh # full-stack E2E (see below)
./run_streamhub.sh -w -g # interactive demo stack ./run_streamhub.sh -w -g # interactive demo stack
``` ```
### End-to-end test ### End-to-end test
`./run_e2e_test.sh` builds everything, launches the demo MARTe2 application `Test/E2E/suite/run_e2e.sh` is the unified E2E suite covering the whole
(`Test/Configurations/streamhub_demo.cfg`: 3 UDPStreamers — multicast scalars, streaming + debug chain (`chain`/`direct`/`recorder`/`debug`/`tcplogger`
FirstSample/LastSample arrays, FullArray + uint64 ns time array) plus a scenario kinds, see `Test/E2E/suite/scenarios.py`), including StreamHub live
StreamHub on port 8095 (with history enabled in `/tmp/streamhub_e2e_history`), push, zoom, window and trigger checks via the Go `chain-client`. It builds
then runs the Go WS client `Test/E2E/streamhub` which verifies: everything, runs the scenario matrix plus the stress matrix, and produces a
`sources`/`config` events, ≥10 binary v1 pushes with wall-clock and strictly consolidated `report_data.json` + Typst PDF report
monotonic time on all streams, `stats` shape, a `zoom` round-trip (reqId echo, (`Test/E2E/suite/E2E_Report.typ`). See the script's `--help` for options.
unicast), `historyInfo` broadcast (enabled, duration, decimation, signal count),
a `historyZoom` round-trip (reqId echo, signal data), and a complete trigger
cycle (setTrigger → arm → binary v2 capture → triggered → disarm). Logs land
in `/tmp/streamhub_e2e_{marte,hub}.log`. Exit 0 iff every check passes.
When changing the WS protocol, update **in lockstep**: this hub, the Go hub When changing the WS protocol, update **in lockstep**: this hub, the Go hub
(`Common/Client/go/wshub`), the browser SPA (`Client/udpstreamer/static`), the (`Common/Client/go/wshub`), the browser SPA (`Client/udpstreamer/static`), the
ImGui client (`Client/streamhub/Protocol.cpp`), the E2E client ImGui client (`Client/streamhub/Protocol.cpp`), the E2E `chain-client`
(`Test/E2E/streamhub`), and [StreamHub-API.md](StreamHub-API.md). (`Test/E2E/suite/client`), and [StreamHub-API.md](StreamHub-API.md).
## 8. Gotchas ## 8. Gotchas
+2
View File
@@ -25,6 +25,7 @@ core:
test: test:
$(MAKE) -C Test/Components/DataSources/UDPStreamer -f Makefile.gcc $(MAKE) -C Test/Components/DataSources/UDPStreamer -f Makefile.gcc
$(MAKE) -C Test/Components/DataSources/UDPStreamerClient -f Makefile.gcc
$(MAKE) -C Test/Applications/StreamHub -f Makefile.gcc $(MAKE) -C Test/Applications/StreamHub -f Makefile.gcc
$(MAKE) -C Test/GTest -f Makefile.gcc $(MAKE) -C Test/GTest -f Makefile.gcc
$(MAKE) -C Test/Integration -f Makefile.gcc $(MAKE) -C Test/Integration -f Makefile.gcc
@@ -39,6 +40,7 @@ clean:
$(MAKE) -C Source/Components/Interfaces/TCPLogger -f Makefile.gcc clean $(MAKE) -C Source/Components/Interfaces/TCPLogger -f Makefile.gcc clean
$(MAKE) -C Source/Components/Interfaces/DebugService -f Makefile.gcc clean $(MAKE) -C Source/Components/Interfaces/DebugService -f Makefile.gcc clean
$(MAKE) -C Test/Components/DataSources/UDPStreamer -f Makefile.gcc clean $(MAKE) -C Test/Components/DataSources/UDPStreamer -f Makefile.gcc clean
$(MAKE) -C Test/Components/DataSources/UDPStreamerClient -f Makefile.gcc clean
$(MAKE) -C Test/Applications/StreamHub -f Makefile.gcc clean $(MAKE) -C Test/Applications/StreamHub -f Makefile.gcc clean
$(MAKE) -C Test/GTest -f Makefile.gcc clean $(MAKE) -C Test/GTest -f Makefile.gcc clean
$(MAKE) -C Test/Integration -f Makefile.gcc clean $(MAKE) -C Test/Integration -f Makefile.gcc clean
+1 -1
View File
@@ -108,7 +108,7 @@ UDPStreamer sources and serves them to oscilloscope clients over WebSocket
hub-side trigger engine, per-window zoom. Clients: browser SPA hub-side trigger engine, per-window zoom. Clients: browser SPA
(`Client/webui` + `Client/udpstreamer/static`) and native ImGui desktop client (`Client/webui` + `Client/udpstreamer/static`) and native ImGui desktop client
(`Client/streamhub`). Demo: `./run_streamhub.sh -w -g`; E2E test: (`Client/streamhub`). Demo: `./run_streamhub.sh -w -g`; E2E test:
`./run_e2e_test.sh`. `Test/E2E/suite/run_e2e.sh`.
See `Docs/StreamHub-UserGuide.md`, `Docs/StreamHub-API.md` and See `Docs/StreamHub-UserGuide.md`, `Docs/StreamHub-API.md` and
`Docs/StreamHub-Developer.md`. `Docs/StreamHub-Developer.md`.
@@ -220,6 +220,9 @@ void UDPSourceSession::ParseConfigPayload(const uint8 *payload, uint32 size) {
memcpy(&sigDescs_[i], memcpy(&sigDescs_[i],
payload + 4u + i * UDPS_SIGNAL_DESC_SIZE, payload + 4u + i * UDPS_SIGNAL_DESC_SIZE,
UDPS_SIGNAL_DESC_SIZE); UDPS_SIGNAL_DESC_SIZE);
/* MD-3: force null-termination of name/unit to prevent intra-struct OOB read */
sigDescs_[i].name[sizeof(sigDescs_[i].name) - 1u] = '\0';
sigDescs_[i].unit[sizeof(sigDescs_[i].unit) - 1u] = '\0';
} }
publishMode_ = payload[4u + numSigs * UDPS_SIGNAL_DESC_SIZE]; publishMode_ = payload[4u + numSigs * UDPS_SIGNAL_DESC_SIZE];
numSignals_ = numSigs; numSignals_ = numSigs;
@@ -237,8 +240,11 @@ void UDPSourceSession::ParseConfigPayload(const uint8 *payload, uint32 size) {
/* (Re)allocate the time-signal decode scratch to the largest element count. */ /* (Re)allocate the time-signal decode scratch to the largest element count. */
uint32 maxElems = 1u; uint32 maxElems = 1u;
for (uint32 i = 0u; i < numSigs; i++) { for (uint32 i = 0u; i < numSigs; i++) {
uint32 ne = sigDescs_[i].numRows * sigDescs_[i].numCols; uint64 ne = static_cast<uint64>(sigDescs_[i].numRows) *
if (ne > maxElems) { maxElems = ne; } static_cast<uint64>(sigDescs_[i].numCols);
if (ne == 0u) { ne = 1u; }
if (ne > 0x100000u) { ne = 0x100000u; /* sanity cap */ }
if (ne > maxElems) { maxElems = static_cast<uint32>(ne); }
} }
if (maxElems > timeScratchLen_) { if (maxElems > timeScratchLen_) {
delete[] timeScratch_; delete[] timeScratch_;
@@ -343,22 +349,36 @@ void UDPSourceSession::ParseDataPayload(const uint8 *payload, uint32 size) {
uint32 off = offset; uint32 off = offset;
for (uint32 s = 0u; s < nSigs; s++) { for (uint32 s = 0u; s < nSigs; s++) {
const UDPSSignalDescriptor &desc = descs[s]; const UDPSSignalDescriptor &desc = descs[s];
uint32 numElements = desc.numRows * desc.numCols; /* HI-1: use 64-bit multiply to avoid overflow on attacker-controlled numRows/numCols */
if (numElements == 0u) { numElements = 1u; } uint64 numElements64 = static_cast<uint64>(desc.numRows) *
static_cast<uint64>(desc.numCols);
if (numElements64 == 0u) { numElements64 = 1u; }
if (numElements64 > 0x100000u) { return; /* sanity cap: 1M elements */ }
uint32 numElements = static_cast<uint32>(numElements64);
uint32 wireElemBytes = (desc.quantType != UDPS_QUANT_NONE) uint32 wireElemBytes = (desc.quantType != UDPS_QUANT_NONE)
? QuantWireBytes(desc.quantType) ? QuantWireBytes(desc.quantType)
: MARTe::UDPSTypeCodeByteSize(desc.typeCode); : MARTe::UDPSTypeCodeByteSize(desc.typeCode);
if (wireElemBytes == 0u) { return; } if (wireElemBytes == 0u) { return; }
uint32 elemsToRead = ((pm == UDPS_PUBLISH_ACCUMULATE) && (numElements == 1u)) /* Accumulate mode batches one full snapshot (all elements) per RT
? numSamples * cycle for every signal (scalar or array) — see UDPStreamer's
: numElements; * SerializeAccumulated. HI-1: 64-bit multiply to avoid overflow on
* attacker-controlled numSamples. */
uint64 elemsToRead64 = (pm == UDPS_PUBLISH_ACCUMULATE)
? (numElements64 * static_cast<uint64>(numSamples))
: numElements64;
if (elemsToRead64 > 0x100000u) { return; /* sanity cap: 1M elements */ }
uint32 elemsToRead = static_cast<uint32>(elemsToRead64);
if (off + elemsToRead * wireElemBytes > size) { return; } /* HI-1: 64-bit bounds check to prevent uint32 multiply overflow */
uint64 bytesNeeded = static_cast<uint64>(off) +
static_cast<uint64>(elemsToRead) *
static_cast<uint64>(wireElemBytes);
if (bytesNeeded > static_cast<uint64>(size)) { return; }
sigOff[s] = off; sigOff[s] = off;
sigElems[s] = elemsToRead; sigElems[s] = elemsToRead;
off += elemsToRead * wireElemBytes; off += static_cast<uint32>(elemsToRead * wireElemBytes);
} }
/* The decode scratch is sized at CONFIG time to the largest per-signal /* The decode scratch is sized at CONFIG time to the largest per-signal
@@ -389,8 +409,10 @@ void UDPSourceSession::ParseDataPayload(const uint8 *payload, uint32 size) {
for (uint32 s = 0u; s < nSigs; s++) { for (uint32 s = 0u; s < nSigs; s++) {
const UDPSSignalDescriptor &desc = descs[s]; const UDPSSignalDescriptor &desc = descs[s];
uint32 numElements = desc.numRows * desc.numCols; uint64 ne64 = static_cast<uint64>(desc.numRows) *
if (numElements == 0u) { numElements = 1u; } static_cast<uint64>(desc.numCols);
if (ne64 == 0u) { ne64 = 1u; }
uint32 numElements = static_cast<uint32>(ne64);
const uint32 nElems = sigElems[s]; const uint32 nElems = sigElems[s];
const bool isFirstLast = (numElements > 1u) && const bool isFirstLast = (numElements > 1u) &&
+53 -2
View File
@@ -199,6 +199,52 @@ bool WSServer::UpgradeHTTP(BasicTCPSocket *sock) {
if (strstr(hdrBuf, "\r\n\r\n") != static_cast<char *>(0)) { break; } if (strstr(hdrBuf, "\r\n\r\n") != static_cast<char *>(0)) { break; }
} }
/* Origin validation (CSWSH / CSRF defence, RFC 6455 §10.2).
* If an Origin header is present, its host must match the Host header
* (same-origin). Non-browser clients (no Origin) are allowed. */
const char *originHdr = FindSubstr(hdrBuf, "Origin:");
if (originHdr != static_cast<const char *>(0)) {
originHdr += 7; /* skip "Origin:" */
while (*originHdr == ' ') { originHdr++; }
/* Extract the host part of Origin: "scheme://host[:port]" */
char originHost[256];
uint32 ohLen = 0u;
const char *op = originHdr;
/* Skip scheme:// */
const char *schemeEnd = strstr(op, "://");
if (schemeEnd != static_cast<const char *>(0)) { op = schemeEnd + 3; }
while (*op != '\r' && *op != '\n' && *op != '\0' &&
*op != '/' && ohLen < 255u) {
originHost[ohLen++] = *op++;
}
originHost[ohLen] = '\0';
/* Extract Host header value */
const char *hostHdr = FindSubstr(hdrBuf, "Host:");
if (hostHdr != static_cast<const char *>(0)) {
hostHdr += 5; /* skip "Host:" */
while (*hostHdr == ' ') { hostHdr++; }
char hostVal[256];
uint32 hvLen = 0u;
while (*hostHdr != '\r' && *hostHdr != '\n' &&
*hostHdr != '\0' && hvLen < 255u) {
hostVal[hvLen++] = *hostHdr++;
}
hostVal[hvLen] = '\0';
if (strcmp(originHost, hostVal) != 0) {
/* Cross-origin — reject the upgrade */
const char *forbidden =
"HTTP/1.1 403 Forbidden\r\n"
"Content-Type: text/plain\r\n"
"Connection: close\r\n"
"\r\nOrigin not allowed\r\n";
uint32 forbLen = static_cast<uint32>(strlen(forbidden));
(void) sock->Write(forbidden, forbLen);
return false;
}
}
}
/* Find Sec-WebSocket-Key */ /* Find Sec-WebSocket-Key */
const char *keyHdr = FindSubstr(hdrBuf, "Sec-WebSocket-Key:"); const char *keyHdr = FindSubstr(hdrBuf, "Sec-WebSocket-Key:");
if (keyHdr == static_cast<const char *>(0)) { return false; } if (keyHdr == static_cast<const char *>(0)) { return false; }
@@ -246,8 +292,9 @@ void WSServer::ClientReadLoop(uint32 slotIdx) {
WSClientSlot &slot = clients[slotIdx]; WSClientSlot &slot = clients[slotIdx];
BasicTCPSocket *sock = slot.sock; BasicTCPSocket *sock = slot.sock;
/* Receive buffer (grows as needed by simple state machine) */ /* Receive buffer: WS_MAX_RECV_PAYLOAD + max header (14: 2 + 8 ext-length +
static const uint32 kRecvBuf = WS_MAX_RECV_PAYLOAD + 14u; * 4 mask) + 1 spare byte for in-place NUL-termination of the payload. */
static const uint32 kRecvBuf = WS_MAX_RECV_PAYLOAD + 14u + 1u;
uint8 *buf = new uint8[kRecvBuf]; uint8 *buf = new uint8[kRecvBuf];
uint32 filled = 0u; uint32 filled = 0u;
@@ -431,6 +478,9 @@ uint32 WSServer::AllocSlot(BasicTCPSocket *sock) {
void WSServer::FreeSlot(uint32 idx) { void WSServer::FreeSlot(uint32 idx) {
if (idx >= WS_MAX_CLIENTS) { return; } if (idx >= WS_MAX_CLIENTS) { return; }
/* HI-5: acquire writeMutex before modifying active/sock to prevent
* use-after-free when BroadcastText/BroadcastBinary are iterating. */
(void) clients[idx].writeMutex.FastLock();
(void) clientsMutex.FastLock(); (void) clientsMutex.FastLock();
if (clients[idx].active) { if (clients[idx].active) {
clients[idx].active = false; clients[idx].active = false;
@@ -442,6 +492,7 @@ void WSServer::FreeSlot(uint32 idx) {
if (numClients > 0u) { numClients--; } if (numClients > 0u) { numClients--; }
} }
clientsMutex.FastUnLock(); clientsMutex.FastUnLock();
clients[idx].writeMutex.FastUnLock();
} }
} /* namespace StreamHub */ } /* namespace StreamHub */
@@ -102,7 +102,6 @@ UDPStreamer::UDPStreamer() :
packetCounter = 0u; packetCounter = 0u;
maxBatchCount = 0u; maxBatchCount = 0u;
singleCycleWireBytes = 0u; singleCycleWireBytes = 0u;
fixedWireBytes = 0u;
lastPublishTs = 0u; lastPublishTs = 0u;
accumBuffer = NULL_PTR(uint8 *); accumBuffer = NULL_PTR(uint8 *);
accumTimestamps = NULL_PTR(uint64 *); accumTimestamps = NULL_PTR(uint64 *);
@@ -588,15 +587,21 @@ bool UDPStreamer::SetConfiguredDatabase(StructuredDataI &data) {
/* --- Pass 5: Accumulate mode setup --- /* --- Pass 5: Accumulate mode setup ---
* *
* Scalars (numElements == 1) are tagged accumulated = true and auto-assigned * ALL signals (scalars and arrays alike) are tagged accumulated = true:
* a FullArray time reference if a primary time signal exists. numCols / numRows * one full snapshot (all elements) is captured and transmitted per RT
* are left at 1 — the actual per-packet element count is determined at runtime * cycle, for every cycle in the batch. This avoids silently discarding
* and transmitted as a 4-byte numSamples field in the DATA payload header. * intermediate RT-cycle values for array ("passenger") signals — only the
* most recent slot used to be sent, whereas scalar signals always got a
* value from every slot. Scalars additionally get a FullArray time
* reference auto-assigned if a primary time signal exists. numCols / numRows
* are left at 1 for scalars — the actual per-packet element count is
* determined at runtime and transmitted as a 4-byte numSamples field in the
* DATA payload header.
* *
* Compute singleCycleWireBytes (accumulated signals) and fixedWireBytes * Compute singleCycleWireBytes (sum of all signals' wireByteSize, i.e. the
* (non-accumulated arrays that travel once per packet from the most-recent slot). * bytes needed for one RT-cycle snapshot of every signal). Override
* Override totalWireBytes to the maximum possible DATA payload for wireBuffer * totalWireBytes to the maximum possible DATA payload for wireBuffer
* allocation: 12 + maxBatchCount × singleCycleWireBytes + fixedWireBytes. * allocation: 12 + maxBatchCount × singleCycleWireBytes.
*/ */
if (ok && (publishMode == UDPStreamerPublishAccumulate)) { if (ok && (publishMode == UDPStreamerPublishAccumulate)) {
@@ -626,41 +631,36 @@ bool UDPStreamer::SetConfiguredDatabase(StructuredDataI &data) {
signalInfos[primaryTsIdx].name.Buffer(), primaryTsIdx); signalInfos[primaryTsIdx].name.Buffer(), primaryTsIdx);
} }
/* Partition signals into accumulated (scalars) and fixed (arrays). /* Every signal (scalar or array) is accumulated: one full snapshot per
* Auto-assign FullArray time mode for scalars that had PacketTime. */ * RT cycle. Auto-assign FullArray time mode for scalars that had
* PacketTime. */
singleCycleWireBytes = 0u; singleCycleWireBytes = 0u;
fixedWireBytes = 0u;
for (uint32 i = 0u; i < numSigs; i++) { for (uint32 i = 0u; i < numSigs; i++) {
if (signalInfos[i].numElements == 1u) {
signalInfos[i].accumulated = true; signalInfos[i].accumulated = true;
singleCycleWireBytes += signalInfos[i].wireByteSize; /* = srcByteSize for 1 elem */ singleCycleWireBytes += signalInfos[i].wireByteSize;
/* Auto-assign time reference for non-primary, non-time scalars */ /* Auto-assign time reference for non-primary, non-time scalars */
if ((i != primaryTsIdx) && (primaryTsIdx != UDPS_NO_TIME_SIGNAL) && if ((signalInfos[i].numElements == 1u) &&
(i != primaryTsIdx) && (primaryTsIdx != UDPS_NO_TIME_SIGNAL) &&
(signalInfos[i].timeMode == UDPStreamerTimePacket)) { (signalInfos[i].timeMode == UDPStreamerTimePacket)) {
signalInfos[i].timeMode = UDPStreamerTimeFullArray; signalInfos[i].timeMode = UDPStreamerTimeFullArray;
signalInfos[i].timeSignalIdx = primaryTsIdx; signalInfos[i].timeSignalIdx = primaryTsIdx;
} }
} }
else {
/* Non-scalar: not accumulated; wire size already computed in pass 4 */
fixedWireBytes += signalInfos[i].wireByteSize;
}
}
if (singleCycleWireBytes == 0u) { if (singleCycleWireBytes == 0u) {
REPORT_ERROR(ErrorManagement::ParametersError, REPORT_ERROR(ErrorManagement::ParametersError,
"Accumulate mode: no scalar signals found to accumulate."); "Accumulate mode: no signals found to accumulate.");
ok = false; ok = false;
} }
if (ok) { if (ok) {
/* DATA payload: [8 HRT][4 numSamples][numSamples × singleCycle][fixed] */ /* DATA payload: [8 HRT][4 numSamples][numSamples × singleCycle] */
static const uint32 ACCUM_HEADER = UDPS_TIMESTAMP_BYTES + 4u; /* 12 bytes */ static const uint32 ACCUM_HEADER = UDPS_TIMESTAMP_BYTES + 4u; /* 12 bytes */
if ((ACCUM_HEADER + singleCycleWireBytes + fixedWireBytes) > maxPayloadSize) { if ((ACCUM_HEADER + singleCycleWireBytes) > maxPayloadSize) {
REPORT_ERROR(ErrorManagement::ParametersError, REPORT_ERROR(ErrorManagement::ParametersError,
"Accumulate mode: even a single sample (%u B) exceeds " "Accumulate mode: even a single sample (%u B) exceeds "
"MaxPayloadSize (%u B).", "MaxPayloadSize (%u B).",
ACCUM_HEADER + singleCycleWireBytes + fixedWireBytes, ACCUM_HEADER + singleCycleWireBytes,
maxPayloadSize); maxPayloadSize);
ok = false; ok = false;
} }
@@ -668,13 +668,13 @@ bool UDPStreamer::SetConfiguredDatabase(StructuredDataI &data) {
if (ok) { if (ok) {
static const uint32 ACCUM_HEADER = UDPS_TIMESTAMP_BYTES + 4u; static const uint32 ACCUM_HEADER = UDPS_TIMESTAMP_BYTES + 4u;
maxBatchCount = (maxPayloadSize - ACCUM_HEADER - fixedWireBytes) / singleCycleWireBytes; maxBatchCount = (maxPayloadSize - ACCUM_HEADER) / singleCycleWireBytes;
/* Override totalWireBytes: size of the largest possible DATA payload */ /* Override totalWireBytes: size of the largest possible DATA payload */
totalWireBytes = ACCUM_HEADER + maxBatchCount * singleCycleWireBytes + fixedWireBytes; totalWireBytes = ACCUM_HEADER + maxBatchCount * singleCycleWireBytes;
REPORT_ERROR(ErrorManagement::Information, REPORT_ERROR(ErrorManagement::Information,
"Accumulate mode: singleCycleWireBytes=%u, fixedWireBytes=%u, " "Accumulate mode: singleCycleWireBytes=%u, "
"maxBatchCount=%u, maxPayloadSize=%u, totalWireBytes=%u.", "maxBatchCount=%u, maxPayloadSize=%u, totalWireBytes=%u.",
singleCycleWireBytes, fixedWireBytes, singleCycleWireBytes,
maxBatchCount, maxPayloadSize, totalWireBytes); maxBatchCount, maxPayloadSize, totalWireBytes);
} }
} }
@@ -697,7 +697,17 @@ bool UDPStreamer::AllocateMemory() {
/* In Accumulate mode, readyBuffer / scratchBuffer hold maxBatchCount consecutive /* In Accumulate mode, readyBuffer / scratchBuffer hold maxBatchCount consecutive
* snapshots instead of a single one. */ * snapshots instead of a single one. */
uint32 readyBufSize = (maxBatchCount > 0u) ? (maxBatchCount * totalSrcBytes) : totalSrcBytes; /* HI-3: use 64-bit arithmetic to prevent overflow in maxBatchCount * totalSrcBytes */
uint64 readyBufSize64 = (maxBatchCount > 0u)
? (static_cast<uint64>(maxBatchCount) * static_cast<uint64>(totalSrcBytes))
: static_cast<uint64>(totalSrcBytes);
if (readyBufSize64 > 0xFFFFFFFFu) {
REPORT_ERROR(ErrorManagement::FatalError,
"Accumulate buffer size overflow (maxBatchCount=%u * totalSrcBytes=%u).",
maxBatchCount, totalSrcBytes);
return false;
}
uint32 readyBufSize = static_cast<uint32>(readyBufSize64);
/* readyBuffer: copy of signal memory shared with background thread */ /* readyBuffer: copy of signal memory shared with background thread */
readyBuffer = reinterpret_cast<uint8 *>(heap->Malloc(readyBufSize)); readyBuffer = reinterpret_cast<uint8 *>(heap->Malloc(readyBufSize));
@@ -854,6 +864,22 @@ bool UDPStreamer::Synchronise() {
* readyTimestamps and dataSem is posted. The background thread sends * readyTimestamps and dataSem is posted. The background thread sends
* the ready batch without any additional timer check. */ * the ready batch without any additional timer check. */
bufMutex.FastLock(TTInfiniteWait); bufMutex.FastLock(TTInfiniteWait);
/* HI-3: if accumFill reached maxBatchCount, force-flush before writing */
if (accumFill >= maxBatchCount) {
uint32 filled = accumFill;
(void) MemoryOperationsHelper::Copy(
readyBuffer, accumBuffer, filled * totalSrcBytes);
(void) MemoryOperationsHelper::Copy(
reinterpret_cast<uint8 *>(readyTimestamps),
reinterpret_cast<const uint8 *>(accumTimestamps),
filled * static_cast<uint32>(sizeof(uint64)));
readyFill = filled;
accumFill = 0u;
lastPublishTs = ts;
bufMutex.FastUnLock();
(void) dataSem.Post();
bufMutex.FastLock(TTInfiniteWait);
}
uint8 *slot = accumBuffer + (accumFill * totalSrcBytes); uint8 *slot = accumBuffer + (accumFill * totalSrcBytes);
(void) MemoryOperationsHelper::Copy(slot, memory, totalSrcBytes); (void) MemoryOperationsHelper::Copy(slot, memory, totalSrcBytes);
accumTimestamps[accumFill] = ts; accumTimestamps[accumFill] = ts;
@@ -863,7 +889,7 @@ bool UDPStreamer::Synchronise() {
/* Check flush conditions (volatile read of lastPublishTs is safe on x86). */ /* Check flush conditions (volatile read of lastPublishTs is safe on x86). */
static const uint32 ACCUM_HEADER = UDPS_TIMESTAMP_BYTES + 4u; /* 12 bytes */ static const uint32 ACCUM_HEADER = UDPS_TIMESTAMP_BYTES + 4u; /* 12 bytes */
uint32 curPayload = ACCUM_HEADER + filled * singleCycleWireBytes + fixedWireBytes; uint32 curPayload = ACCUM_HEADER + filled * singleCycleWireBytes;
uint32 nextPayload = curPayload + singleCycleWireBytes; uint32 nextPayload = curPayload + singleCycleWireBytes;
bool sizeCondition = (nextPayload >= maxPayloadSize); bool sizeCondition = (nextPayload >= maxPayloadSize);
bool timeCondition = ((ts - lastPublishTs) >= flushPeriodTicks); bool timeCondition = ((ts - lastPublishTs) >= flushPeriodTicks);
@@ -959,7 +985,7 @@ ErrorManagement::ErrorType UDPStreamer::Execute(ExecutionInfo &info) {
if (fill > 0u) { if (fill > 0u) {
SerializeAccumulated(scratchBuffer, scratchTimestamps, fill); SerializeAccumulated(scratchBuffer, scratchTimestamps, fill);
uint32 sendBytes = UDPS_TIMESTAMP_BYTES + 4u + uint32 sendBytes = UDPS_TIMESTAMP_BYTES + 4u +
fill * singleCycleWireBytes + fixedWireBytes; fill * singleCycleWireBytes;
packetCounter++; packetCounter++;
if (!server.SendData(packetCounter, wireBuffer, sendBytes)) { if (!server.SendData(packetCounter, wireBuffer, sendBytes)) {
REPORT_ERROR(ErrorManagement::Warning, REPORT_ERROR(ErrorManagement::Warning,
@@ -1004,9 +1030,9 @@ void UDPStreamer::SerializeAccumulated(const uint8 *src,
/* Wire layout (Accumulate mode DATA payload): /* Wire layout (Accumulate mode DATA payload):
* [8 bytes] : HRT of slot 0 (oldest sample) * [8 bytes] : HRT of slot 0 (oldest sample)
* [4 bytes] : numSamples (uint32, little-endian) * [4 bytes] : numSamples (uint32, little-endian)
* for each signal: * for each signal : numSamples snapshots in order (slot 0 = oldest),
* if accumulated : numSamples elements (one per slot) * each snapshot holding all of the signal's elements
* if non-accumulated (array): one copy from the most-recent slot * (1 for scalars, numElements for arrays)
*/ */
uint8 *dst = wireBuffer; uint8 *dst = wireBuffer;
@@ -1019,83 +1045,22 @@ void UDPStreamer::SerializeAccumulated(const uint8 *src,
dst += 4u; dst += 4u;
for (uint32 i = 0u; i < numSigs; i++) { for (uint32 i = 0u; i < numSigs; i++) {
if (signalInfos[i].accumulated) { const uint32 nelems = signalInfos[i].numElements;
/* Scalar: pack one value from each slot in order */ const bool isSrcFloat32 = (signalInfos[i].type == Float32Bit);
uint32 elemSrcBytes = signalInfos[i].srcByteSize; /* bytes for one element */ const float64 rMin = signalInfos[i].rangeMin;
for (uint32 k = 0u; k < numSamples; k++) {
const uint8 *slotSrc = src + (k * totalSrcBytes) + signalInfos[i].bufferOffset;
if (signalInfos[i].quantType == UDPStreamerQuantNone) {
(void) MemoryOperationsHelper::Copy(dst, slotSrc, elemSrcBytes);
dst += elemSrcBytes;
}
else {
float64 rawVal = 0.0;
if (signalInfos[i].type == Float32Bit) {
float32 f32 = 0.0f;
(void) MemoryOperationsHelper::Copy(&f32, slotSrc, 4u);
rawVal = static_cast<float64>(f32);
}
else {
(void) MemoryOperationsHelper::Copy(&rawVal, slotSrc, 8u);
}
float64 rMin = signalInfos[i].rangeMin;
float64 rRange = signalInfos[i].rangeMax - rMin; float64 rRange = signalInfos[i].rangeMax - rMin;
if (rRange == 0.0) { rRange = 1.0; } if (rRange == 0.0) { rRange = 1.0; }
float64 norm = (rawVal - rMin) / rRange;
if (norm < 0.0) { norm = 0.0; } /* Pack one snapshot (all elements) from each slot, in order */
if (norm > 1.0) { norm = 1.0; } for (uint32 k = 0u; k < numSamples; k++) {
switch (signalInfos[i].quantType) { const uint8 *slotSrc = src + (k * totalSrcBytes) + signalInfos[i].bufferOffset;
case UDPStreamerQuantUint8: {
uint8 q = static_cast<uint8>(norm * 255.0);
*dst = q; dst += 1u;
break;
}
case UDPStreamerQuantInt8: {
int8 q = static_cast<int8>((norm * 254.0) - 127.0);
(void) MemoryOperationsHelper::Copy(dst, &q, 1u);
dst += 1u;
break;
}
case UDPStreamerQuantUint16: {
uint16 q = static_cast<uint16>(norm * 65535.0);
(void) MemoryOperationsHelper::Copy(dst, &q, 2u);
dst += 2u;
break;
}
case UDPStreamerQuantInt16: {
int16 q = static_cast<int16>((norm * 65534.0) - 32767.0);
(void) MemoryOperationsHelper::Copy(dst, &q, 2u);
dst += 2u;
break;
}
default: {
(void) MemoryOperationsHelper::Copy(dst, slotSrc, elemSrcBytes);
dst += elemSrcBytes;
break;
}
}
}
}
}
else {
/* Non-accumulated array: send from the most-recent slot */
const uint8 *slotSrc = src + ((numSamples - 1u) * totalSrcBytes) +
signalInfos[i].bufferOffset;
if (signalInfos[i].quantType == UDPStreamerQuantNone) { if (signalInfos[i].quantType == UDPStreamerQuantNone) {
(void) MemoryOperationsHelper::Copy(dst, slotSrc, signalInfos[i].srcByteSize); (void) MemoryOperationsHelper::Copy(dst, slotSrc, signalInfos[i].srcByteSize);
dst += signalInfos[i].srcByteSize; dst += signalInfos[i].srcByteSize;
} }
else { else {
float64 rMin = signalInfos[i].rangeMin;
float64 rRange = signalInfos[i].rangeMax - rMin;
if (rRange == 0.0) { rRange = 1.0; }
bool isSrcFloat32 = (signalInfos[i].type == Float32Bit);
uint32 nelems = signalInfos[i].numElements;
const uint8 *s = slotSrc; const uint8 *s = slotSrc;
for (uint32 e = 0u; e < nelems; e++) { for (uint32 e = 0u; e < nelems; e++) {
float64 rawVal = 0.0; float64 rawVal = 0.0;
if (isSrcFloat32) { if (isSrcFloat32) {
@@ -103,7 +103,7 @@ struct UDPStreamerSignalInfo {
uint32 srcByteSize; /**< Bytes in MARTe2 memory */ uint32 srcByteSize; /**< Bytes in MARTe2 memory */
uint32 wireByteSize; /**< Bytes on the wire (may differ when quantized) */ uint32 wireByteSize; /**< Bytes on the wire (may differ when quantized) */
uint32 bufferOffset; /**< Byte offset in the flat MemoryDataSourceI memory buffer */ uint32 bufferOffset; /**< Byte offset in the flat MemoryDataSourceI memory buffer */
bool accumulated; /**< True when this scalar was expanded to flushCount elements in Auto accumulation mode */ bool accumulated; /**< True when this signal is batched (one snapshot per RT cycle) in Accumulate mode */
}; };
/** /**
@@ -358,8 +358,7 @@ private:
uint64 flushPeriodTicks; /**< HRT ticks per flush interval (computed from minRefreshRate) */ uint64 flushPeriodTicks; /**< HRT ticks per flush interval (computed from minRefreshRate) */
/* Accumulate mode — dynamic batch parameters */ /* Accumulate mode — dynamic batch parameters */
uint32 maxBatchCount; /**< Max snapshots that fit in MaxPayloadSize (Accumulate) */ uint32 maxBatchCount; /**< Max snapshots that fit in MaxPayloadSize (Accumulate) */
uint32 singleCycleWireBytes; /**< Wire bytes for all accumulated signals per snapshot */ uint32 singleCycleWireBytes; /**< Wire bytes for ALL signals (scalar and array) per snapshot */
uint32 fixedWireBytes; /**< Wire bytes for non-accumulated signals (arrays, once per packet) */
volatile uint64 lastPublishTs; /**< HRT counter of last successful flush (Accumulate mode) */ volatile uint64 lastPublishTs; /**< HRT counter of last successful flush (Accumulate mode) */
uint8 *accumBuffer; /**< Heap: [maxBatchCount × totalSrcBytes] linear fill */ uint8 *accumBuffer; /**< Heap: [maxBatchCount × totalSrcBytes] linear fill */
uint64 *accumTimestamps; /**< Heap: [maxBatchCount] HRT counter per snapshot */ uint64 *accumTimestamps; /**< Heap: [maxBatchCount] HRT counter per snapshot */
@@ -517,7 +517,11 @@ void UDPStreamerClient::DecodeSnapshot(const uint8 *payload, uint32 size,
const bool accScalar = (publishMode == UDPS_PUBLISH_ACCUMULATE) && (ne == 1u); const bool accScalar = (publishMode == UDPS_PUBLISH_ACCUMULATE) && (ne == 1u);
const uint32 elemsToRead = accScalar ? numSamples : ne; const uint32 elemsToRead = accScalar ? numSamples : ne;
if ((off + (elemsToRead * wireElemBytes)) > size) { return; } /* HI-1: 64-bit bounds check to prevent uint32 multiply overflow */
uint64 bytesNeeded = static_cast<uint64>(off) +
static_cast<uint64>(elemsToRead) *
static_cast<uint64>(wireElemBytes);
if (bytesNeeded > static_cast<uint64>(size)) { return; }
uint8 *d = dst + info.bufferOffset; uint8 *d = dst + info.bufferOffset;
@@ -78,8 +78,9 @@ public:
bool Push(uint32 signalID, uint64 timestamp, void* data, uint32 size) { bool Push(uint32 signalID, uint64 timestamp, void* data, uint32 size) {
uint32 packetSize = 4 + 8 + 4 + size; // ID + TS + Size + Data uint32 packetSize = 4 + 8 + 4 + size; // ID + TS + Size + Data
uint32 read = readIndex; /* HI-9: use atomic loads for cross-thread index reads */
uint32 write = writeIndex; uint32 read = __atomic_load_n(&readIndex, __ATOMIC_ACQUIRE);
uint32 write = __atomic_load_n(&writeIndex, __ATOMIC_ACQUIRE);
uint32 available = 0; uint32 available = 0;
if (read <= write) { if (read <= write) {
@@ -96,13 +97,15 @@ public:
WriteToBuffer(&tempWrite, &size, 4); WriteToBuffer(&tempWrite, &size, 4);
WriteToBuffer(&tempWrite, data, size); WriteToBuffer(&tempWrite, data, size);
writeIndex = tempWrite; // HI-9: release store so data writes are visible before index update
__atomic_store_n(&writeIndex, tempWrite, __ATOMIC_RELEASE);
return true; return true;
} }
bool Pop(uint32 &signalID, uint64 &timestamp, void* dataBuffer, uint32 &size, uint32 maxSize) { bool Pop(uint32 &signalID, uint64 &timestamp, void* dataBuffer, uint32 &size, uint32 maxSize) {
uint32 read = readIndex; /* HI-9: acquire-load writeIndex to see data written by Push */
uint32 write = writeIndex; uint32 read = __atomic_load_n(&readIndex, __ATOMIC_ACQUIRE);
uint32 write = __atomic_load_n(&writeIndex, __ATOMIC_ACQUIRE);
if (read == write) return false; if (read == write) return false;
uint32 tempRead = read; uint32 tempRead = read;
@@ -124,9 +127,9 @@ public:
// locate the next entry safely, so fall back to discarding everything // locate the next entry safely, so fall back to discarding everything
// to avoid reading garbage as sample headers on future Pop() calls. // to avoid reading garbage as sample headers on future Pop() calls.
if (tempSize >= bufferSize) { if (tempSize >= bufferSize) {
readIndex = write; // corrupt ring — discard all __atomic_store_n(&readIndex, write, __ATOMIC_RELEASE); // corrupt ring — discard all
} else { } else {
readIndex = (tempRead + tempSize) % bufferSize; __atomic_store_n(&readIndex, (tempRead + tempSize) % bufferSize, __ATOMIC_RELEASE);
} }
return false; return false;
} }
@@ -137,13 +140,14 @@ public:
timestamp = tempTs; timestamp = tempTs;
size = tempSize; size = tempSize;
readIndex = tempRead; // HI-9: release-store readIndex after reading data
__atomic_store_n(&readIndex, tempRead, __ATOMIC_RELEASE);
return true; return true;
} }
uint32 Count() { uint32 Count() {
uint32 read = readIndex; uint32 read = __atomic_load_n(&readIndex, __ATOMIC_ACQUIRE);
uint32 write = writeIndex; uint32 write = __atomic_load_n(&writeIndex, __ATOMIC_ACQUIRE);
if (write >= read) return write - read; if (write >= read) return write - read;
return bufferSize - (read - write); return bufferSize - (read - write);
} }
@@ -13,6 +13,7 @@
#include "Threads.h" #include "Threads.h"
#include "TimeoutType.h" #include "TimeoutType.h"
#include "UDPSProtocol.h" #include "UDPSProtocol.h"
#include <string.h>
namespace MARTe { namespace MARTe {
@@ -122,6 +123,12 @@ bool DebugService::Initialise(StructuredDataI &data) {
suppressTimeoutLogs = (suppress == 1u); suppressTimeoutLogs = (suppress == 1u);
} }
StreamString tempToken;
if (data.Read("AuthToken", tempToken)) {
authToken = tempToken;
}
clientAuthenticated = (authToken.Size() == 0u);
// Capture only the local subtree — do NOT call MoveToRoot() on the shared CDB. // Capture only the local subtree — do NOT call MoveToRoot() on the shared CDB.
(void)data.Copy(fullConfig); (void)data.Copy(fullConfig);
@@ -281,6 +288,8 @@ ErrorManagement::ErrorType DebugService::Server(ExecutionInfo &info) {
cmdCountInWindow = 0u; cmdCountInWindow = 0u;
cmdWindowStartMs = nowMs; cmdWindowStartMs = nowMs;
lastDataTimeMs = nowMs; lastDataTimeMs = nowMs;
/* CR-5: require auth if an AuthToken is configured. */
clientAuthenticated = (authToken.Size() == 0u);
} }
} else { } else {
if (nowMs - lastDataTimeMs > CLIENT_IDLE_TIMEOUT_MS) { if (nowMs - lastDataTimeMs > CLIENT_IDLE_TIMEOUT_MS) {
@@ -351,7 +360,84 @@ ErrorManagement::ErrorType DebugService::Server(ExecutionInfo &info) {
uint32 cmdLen = len; uint32 cmdLen = len;
command.Write(raw + lineStart, cmdLen); command.Write(raw + lineStart, cmdLen);
// Dispatch via base HandleCommand, write response to socket. /* CR-5: Auth token gate. If an AuthToken is
* configured, the client must send
* "AUTH <token>" before any other command. */
if (authToken.Size() > 0u) {
const char8 *cmdPtr = command.Buffer();
if (cmdLen >= 5u &&
strncmp(cmdPtr, "AUTH ", 5u) == 0) {
const char8 *recvToken = cmdPtr + 5u;
uint32 recvLen = cmdLen - 5u;
/* Strip trailing \r if present */
if (recvLen > 0u &&
recvToken[recvLen - 1u] == '\r') {
recvLen--;
}
if (recvLen == authToken.Size() &&
strncmp(recvToken,
authToken.Buffer(),
recvLen) == 0) {
clientAuthenticated = true;
const char8 *okResp =
"OK AUTHENTICATED\n";
uint32 respSz =
static_cast<uint32>(
strlen(okResp));
(void) activeClient->Write(
okResp, respSz);
} else {
const char8 *badResp =
"ERR AUTH_FAILED\n";
uint32 respSz =
static_cast<uint32>(
strlen(badResp));
(void) activeClient->Write(
badResp, respSz);
}
} else if (!clientAuthenticated) {
const char8 *needAuth =
"ERR AUTH_REQUIRED\n";
uint32 respSz =
static_cast<uint32>(
strlen(needAuth));
(void) activeClient->Write(
needAuth, respSz);
} else {
// Dispatch via base HandleCommand,
// write response to socket.
StreamString out;
HandleCommand(command, out);
if (out.Size() > 0u) {
const char8 *wPtr = out.Buffer();
uint32 remaining =
(uint32)out.Size();
lastDataTimeMs =
(uint64)((float64)
HighResolutionTimer::Counter() *
HighResolutionTimer::Period() *
1000.0);
while (remaining > 0u) {
uint32 wrote = remaining;
if (!activeClient->Write(
wPtr, wrote) ||
wrote == 0u) {
break;
}
wPtr += wrote;
remaining -= wrote;
lastDataTimeMs =
(uint64)((float64)
HighResolutionTimer::Counter() *
HighResolutionTimer::Period() *
1000.0);
}
}
}
} else {
// No auth token configured — back-compat.
// Dispatch via base HandleCommand, write
// response to socket.
StreamString out; StreamString out;
HandleCommand(command, out); HandleCommand(command, out);
if (out.Size() > 0u) { if (out.Size() > 0u) {
@@ -371,6 +457,7 @@ ErrorManagement::ErrorType DebugService::Server(ExecutionInfo &info) {
} }
} }
} }
}
lineStart = pos + 1u; lineStart = pos + 1u;
} }
@@ -433,6 +520,10 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
// b) Drain traceBuffer — pack each sample into udpsDataPayload // b) Drain traceBuffer — pack each sample into udpsDataPayload
bool anyData = false; bool anyData = false;
bool pendingInDrain[UDPS_MAX_SLOTS];
for (uint32 i = 0u; i < udpsNumSlots; i++) {
pendingInDrain[i] = false;
}
uint32 id, size; uint32 id, size;
uint64 ts; uint64 ts;
uint8 udpsSampleBuf[UDPS_MAX_SAMPLE_BYTES]; uint8 udpsSampleBuf[UDPS_MAX_SAMPLE_BYTES];
@@ -441,6 +532,18 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
// Find matching slot by internalID // Find matching slot by internalID
for (uint32 i = 0u; i < udpsNumSlots; i++) { for (uint32 i = 0u; i < udpsNumSlots; i++) {
if (udpsSlots[i].internalID == id) { if (udpsSlots[i].internalID == id) {
if (pendingInDrain[i]) {
// This slot already holds an unflushed sample from earlier
// in this same drain pass — flush it now instead of
// silently overwriting it, or lossless tracing would drop
// a real sample whenever the Streamer thread falls behind
// by more than one RT cycle.
FlushUdpsFrame();
for (uint32 j = 0u; j < udpsNumSlots; j++) {
pendingInDrain[j] = false;
}
anyData = false;
}
if ((udpsDataPayload != NULL_PTR(uint8 *)) && if ((udpsDataPayload != NULL_PTR(uint8 *)) &&
(8u + udpsSlots[i].wireOffset + udpsSlots[i].wireSize <= udpsDataPayloadSize)) { (8u + udpsSlots[i].wireOffset + udpsSlots[i].wireSize <= udpsDataPayloadSize)) {
uint32 copySize = size; uint32 copySize = size;
@@ -448,6 +551,7 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
memcpy(udpsDataPayload + 8u + udpsSlots[i].wireOffset, udpsSampleBuf, copySize); memcpy(udpsDataPayload + 8u + udpsSlots[i].wireOffset, udpsSampleBuf, copySize);
udpsSlots[i].everFilled = true; udpsSlots[i].everFilled = true;
} }
pendingInDrain[i] = true;
anyData = true; anyData = true;
break; break;
} }
@@ -455,18 +559,22 @@ ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
} }
// c) If we have data, stamp with HRT and send via udpsServer // c) If we have data, stamp with HRT and send via udpsServer
if (anyData && udpsNumSlots > 0u && udpsDataPayload != NULL_PTR(uint8 *)) { if (anyData) {
FlushUdpsFrame();
} else {
Sleep::MSec(1u);
}
return ErrorManagement::NoError;
}
void DebugService::FlushUdpsFrame() {
if (udpsNumSlots > 0u && udpsDataPayload != NULL_PTR(uint8 *)) {
uint64 hrt = HighResolutionTimer::Counter(); uint64 hrt = HighResolutionTimer::Counter();
memcpy(udpsDataPayload, &hrt, 8u); memcpy(udpsDataPayload, &hrt, 8u);
udpsPacketCounter++; udpsPacketCounter++;
(void)udpsServer.SendData(udpsPacketCounter, udpsDataPayload, udpsDataPayloadSize); (void)udpsServer.SendData(udpsPacketCounter, udpsDataPayload, udpsDataPayloadSize);
} }
if (!anyData) {
Sleep::MSec(1u);
}
return ErrorManagement::NoError;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -66,6 +66,20 @@ private:
*/ */
bool SendUDPSConfig(); bool SendUDPSConfig();
/**
* @brief Stamp the current udpsDataPayload with an HRT timestamp and send
* it as one UDPS DATA packet.
* @details Factored out of Streamer() so a single drain pass of
* traceBuffer can flush more than once per tick — see the
* pendingInDrain guard in Streamer(): without an eager flush, a
* slot that is written twice within the same drain pass (e.g.
* because the Streamer thread was briefly descheduled and two
* RT cycles' worth of samples piled up in traceBuffer) would
* silently overwrite-and-lose the first of the two samples,
* defeating lossless tracing.
*/
void FlushUdpsFrame();
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// TCP/UDP transport configuration // TCP/UDP transport configuration
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -76,6 +90,13 @@ private:
bool isServer; bool isServer;
bool suppressTimeoutLogs; bool suppressTimeoutLogs;
/** Optional authentication token (CR-5). If set (non-empty), the first
* command from a new TCP client must be "AUTH <token>". All other
* commands are rejected until the client authenticates. If empty
* (default), no authentication is required (back-compat). */
StreamString authToken;
bool clientAuthenticated;
BasicTCPSocket tcpServer; BasicTCPSocket tcpServer;
UDPSServer udpsServer; ///< Handles fragmentation and multi-client sending UDPSServer udpsServer; ///< Handles fragmentation and multi-client sending
@@ -181,6 +181,12 @@ static void BuildCDBFromContainer(ReferenceContainer *container,
} }
} }
/* HI-8: Guard against double-patching (e.g. two DebugService instances).
* Once the registry has been patched, subsequent PatchRegistry() calls are
* no-ops. Original builders are not saved/restored — the debug wrappers
* persist for the process lifetime (intentional for transparent debugging). */
static bool registryPatched = false;
static void PatchItemInternal(const char8 *originalName, static void PatchItemInternal(const char8 *originalName,
ObjectBuilder *debugBuilder) { ObjectBuilder *debugBuilder) {
ClassRegistryItem *item = ClassRegistryItem *item =
@@ -215,6 +221,14 @@ DebugServiceBase::~DebugServiceBase() {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void DebugServiceBase::PatchRegistry() { void DebugServiceBase::PatchRegistry() {
/* HI-8: skip if already patched (prevents double-patch leak when multiple
* DebugService instances are created). */
if (registryPatched) {
REPORT_ERROR_STATIC(ErrorManagement::Warning,
"PatchRegistry: registry already patched — skipping (double-patch guard).");
return;
}
registryPatched = true;
PatchItemInternal("MemoryMapInputBroker", PatchItemInternal("MemoryMapInputBroker",
new DebugMemoryMapInputBrokerBuilder()); new DebugMemoryMapInputBrokerBuilder());
PatchItemInternal("MemoryMapOutputBroker", PatchItemInternal("MemoryMapOutputBroker",
@@ -305,13 +319,20 @@ void DebugServiceBase::ProcessSignal(DebugSignalInfo *signalInfo, uint32 size,
return; return;
if (signalInfo->isForcing) { if (signalInfo->isForcing) {
uint32 nEl = signalInfo->numberOfElements; uint32 nEl = signalInfo->numberOfElements;
/* HI-4: clamp size to forcedValue buffer to prevent OOB read */
uint32 forceSize = size;
if (forceSize > static_cast<uint32>(sizeof(signalInfo->forcedValue))) {
forceSize = static_cast<uint32>(sizeof(signalInfo->forcedValue));
}
if (nEl <= 1u) { if (nEl <= 1u) {
// Scalar — single memcpy. // Scalar — single memcpy (clamped to forcedValue bounds).
memcpy(signalInfo->memoryAddress, signalInfo->forcedValue, size); memcpy(signalInfo->memoryAddress, signalInfo->forcedValue, forceSize);
} else { } else {
// Array — copy only the elements whose bit is set in forcedMask. // Array — copy only the elements whose bit is set in forcedMask.
uint32 elemBytes = size / nEl; // HI-4: cap loop at 256 elements (forcedMask is 32 bytes = 256 bits).
for (uint32 e = 0u; e < nEl; e++) { uint32 elemBytes = forceSize / nEl;
uint32 nElCapped = (nEl > 256u) ? 256u : nEl;
for (uint32 e = 0u; e < nElCapped; e++) {
if (signalInfo->forcedMask[e >> 3u] & (uint8)(1u << (e & 7u))) { if (signalInfo->forcedMask[e >> 3u] & (uint8)(1u << (e & 7u))) {
memcpy((uint8 *)signalInfo->memoryAddress + e * elemBytes, memcpy((uint8 *)signalInfo->memoryAddress + e * elemBytes,
signalInfo->forcedValue + e * elemBytes, signalInfo->forcedValue + e * elemBytes,
@@ -1070,9 +1091,9 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
Reference ref = ObjectRegistryDatabase::Instance()->Find(path); Reference ref = ObjectRegistryDatabase::Instance()->Find(path);
out += "{"; out += "{";
if (ref.IsValid()) { if (ref.IsValid()) {
out += "\"Name\":\""; out += "\"Name\": \"";
EscapeJson(ref->GetName(), out); EscapeJson(ref->GetName(), out);
out += "\",\"Class\":\""; out += "\", \"Class\": \"";
EscapeJson(ref->GetClassProperties()->GetName(), out); EscapeJson(ref->GetClassProperties()->GetName(), out);
out += "\""; out += "\"";
ConfigurationDatabase db; ConfigurationDatabase db;
@@ -1089,7 +1110,7 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
if (TypeConvert(st, at)) { if (TypeConvert(st, at)) {
out += "\""; out += "\"";
EscapeJson(cn, out); EscapeJson(cn, out);
out += "\":\""; out += "\": \"";
EscapeJson(buf, out); EscapeJson(buf, out);
out += "\""; out += "\"";
if (i < nc - 1u) if (i < nc - 1u)
@@ -1108,8 +1129,8 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
DebugSignalInfo *s = signals[aliases[i].signalIndex]; DebugSignalInfo *s = signals[aliases[i].signalIndex];
const char8 *tn = const char8 *tn =
TypeDescriptor::GetTypeNameFromTypeDescriptor(s->type); TypeDescriptor::GetTypeNameFromTypeDescriptor(s->type);
out.Printf("\"Name\":\"%s\",\"Class\":\"Signal\",\"Type\":\"%s\"," out.Printf("\"Name\": \"%s\", \"Class\": \"Signal\", \"Type\": \"%s\", "
"\"ID\":%u", "\"ID\": %u",
s->name.Buffer(), tn ? tn : "Unknown", s->internalID); s->name.Buffer(), tn ? tn : "Unknown", s->internalID);
enrichAlias = aliases[i].name; enrichAlias = aliases[i].name;
found = true; found = true;
@@ -1120,21 +1141,32 @@ void DebugServiceBase::InfoNode(const char8 *path, StreamString &out) {
if (found) if (found)
EnrichWithConfig(enrichAlias.Buffer(), out); EnrichWithConfig(enrichAlias.Buffer(), out);
else else
out += "\"Error\":\"Object not found\""; out += "\"Error\": \"Object not found\"";
} }
out += "}\nOK INFO\n"; out += "}\nOK INFO\n";
} }
void DebugServiceBase::ListNodes(const char8 *path, StreamString &out) { void DebugServiceBase::ListNodes(const char8 *path, StreamString &out) {
Reference ref = bool isRoot =
(path == NULL_PTR(const char8 *) || StringHelper::Length(path) == 0 || (path == NULL_PTR(const char8 *) || StringHelper::Length(path) == 0 ||
StringHelper::Compare(path, "/") == 0) StringHelper::Compare(path, "/") == 0);
? ObjectRegistryDatabase::Instance()
: ObjectRegistryDatabase::Instance()->Find(path); // NOTE: ObjectRegistryDatabase::Instance() is a raw, long-lived singleton
out.Printf("Nodes under %s:\n", path ? path : "/"); // pointer that is never itself owned by a Reference. Wrapping it in a
// Reference here (as previously done via a ternary) would increment its
// reference count and then delete it when the local Reference goes out of
// scope, destroying the registry. Keep the root case as a raw pointer.
ReferenceContainer *rc = NULL_PTR(ReferenceContainer *);
Reference ref;
if (isRoot) {
rc = ObjectRegistryDatabase::Instance();
} else {
ref = ObjectRegistryDatabase::Instance()->Find(path);
if (ref.IsValid()) { if (ref.IsValid()) {
ReferenceContainer *rc = rc = dynamic_cast<ReferenceContainer *>(ref.operator->());
dynamic_cast<ReferenceContainer *>(ref.operator->()); }
}
out.Printf("Nodes under %s:\n", path ? path : "/");
if (rc != NULL_PTR(ReferenceContainer *)) { if (rc != NULL_PTR(ReferenceContainer *)) {
uint32 n = rc->Size(); uint32 n = rc->Size();
for (uint32 i = 0u; i < n; i++) { for (uint32 i = 0u; i < n; i++) {
@@ -1144,7 +1176,6 @@ void DebugServiceBase::ListNodes(const char8 *path, StreamString &out) {
c->GetClassProperties()->GetName()); c->GetClassProperties()->GetName());
} }
} }
}
} else { } else {
out += " (not found)\n"; out += " (not found)\n";
} }
@@ -1177,141 +1208,6 @@ void DebugServiceBase::RebuildConfigFromRegistry() {
RebuildTransportConfig(); RebuildTransportConfig();
} }
// ---------------------------------------------------------------------------
// Tree export
// ---------------------------------------------------------------------------
uint32 DebugServiceBase::ExportTree(ReferenceContainer *container,
StreamString &json,
const char8 *pathPrefix) {
if (container == NULL_PTR(ReferenceContainer *))
return 0u;
uint32 size = container->Size();
uint32 valid = 0u;
for (uint32 i = 0u; i < size; i++) {
Reference child = container->Get(i);
if (!child.IsValid())
continue;
if (valid > 0u)
json += ",\n";
const char8 *cname = child->GetName();
if (cname == NULL_PTR(const char8 *))
cname = "unnamed";
StreamString cp;
if (pathPrefix != NULL_PTR(const char8 *))
cp.Printf("%s.%s", pathPrefix, cname);
else
cp = cname;
StreamString nj;
nj += "{\"Name\":\"";
EscapeJson(cname, nj);
nj += "\",\"Class\":\"";
EscapeJson(child->GetClassProperties()->GetName(), nj);
nj += "\"";
ReferenceContainer *inner =
dynamic_cast<ReferenceContainer *>(child.operator->());
DataSourceI *ds = dynamic_cast<DataSourceI *>(child.operator->());
GAM *gam = dynamic_cast<GAM *>(child.operator->());
if (inner != NULL_PTR(ReferenceContainer *) ||
ds != NULL_PTR(DataSourceI *) || gam != NULL_PTR(GAM *)) {
nj += ",\"Children\":[\n";
uint32 sc = 0u;
if (inner != NULL_PTR(ReferenceContainer *))
sc += ExportTree(inner, nj, cp.Buffer());
if (ds != NULL_PTR(DataSourceI *)) {
uint32 ns = ds->GetNumberOfSignals();
for (uint32 j = 0u; j < ns; j++) {
if (sc > 0u) {
nj += ",\n";
}
sc++;
StreamString sn;
(void)ds->GetSignalName(j, sn);
const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor(
ds->GetSignalType(j));
uint8 d = 0u;
(void)ds->GetSignalNumberOfDimensions(j, d);
uint32 el = 0u;
(void)ds->GetSignalNumberOfElements(j, el);
StreamString sfp;
sfp.Printf("%s.%s", cp.Buffer(), sn.Buffer());
bool tr = false, fo = false;
(void)IsInstrumented(sfp.Buffer(), tr, fo);
nj += "{\"Name\":\"";
EscapeJson(sn.Buffer(), nj);
nj += "\",\"Class\":\"Signal\",\"Type\":\"";
EscapeJson(st ? st : "Unknown", nj);
nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u,"
"\"IsTraceable\":%s,\"IsForcable\":%s}",
d, el, tr ? "true" : "false", fo ? "true" : "false");
}
}
if (gam != NULL_PTR(GAM *)) {
uint32 nIn = gam->GetNumberOfInputSignals();
for (uint32 j = 0u; j < nIn; j++) {
if (sc > 0u) {
nj += ",\n";
}
sc++;
StreamString sn;
(void)gam->GetSignalName(InputSignals, j, sn);
const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor(
gam->GetSignalType(InputSignals, j));
uint32 d = 0u;
(void)gam->GetSignalNumberOfDimensions(InputSignals, j, d);
uint32 el = 0u;
(void)gam->GetSignalNumberOfElements(InputSignals, j, el);
StreamString sfp;
sfp.Printf("%s.In.%s", cp.Buffer(), sn.Buffer());
bool tr = false, fo = false;
(void)IsInstrumented(sfp.Buffer(), tr, fo);
nj += "{\"Name\":\"In.";
EscapeJson(sn.Buffer(), nj);
nj += "\",\"Class\":\"InputSignal\",\"Type\":\"";
EscapeJson(st ? st : "Unknown", nj);
nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u,"
"\"IsTraceable\":%s,\"IsForcable\":%s}",
d, el, tr ? "true" : "false", fo ? "true" : "false");
}
uint32 nOut = gam->GetNumberOfOutputSignals();
for (uint32 j = 0u; j < nOut; j++) {
if (sc > 0u) {
nj += ",\n";
}
sc++;
StreamString sn;
(void)gam->GetSignalName(OutputSignals, j, sn);
const char8 *st = TypeDescriptor::GetTypeNameFromTypeDescriptor(
gam->GetSignalType(OutputSignals, j));
uint32 d = 0u;
(void)gam->GetSignalNumberOfDimensions(OutputSignals, j, d);
uint32 el = 0u;
(void)gam->GetSignalNumberOfElements(OutputSignals, j, el);
StreamString sfp;
sfp.Printf("%s.Out.%s", cp.Buffer(), sn.Buffer());
bool tr = false, fo = false;
(void)IsInstrumented(sfp.Buffer(), tr, fo);
nj += "{\"Name\":\"Out.";
EscapeJson(sn.Buffer(), nj);
nj += "\",\"Class\":\"OutputSignal\",\"Type\":\"";
EscapeJson(st ? st : "Unknown", nj);
nj.Printf("\",\"Dimensions\":%u,\"Elements\":%u,"
"\"IsTraceable\":%s,\"IsForcable\":%s}",
d, el, tr ? "true" : "false", fo ? "true" : "false");
}
}
nj += "\n]";
}
nj += "}";
json += nj;
valid++;
}
return valid;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// EnrichWithConfig // EnrichWithConfig
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -174,8 +174,6 @@ protected:
void UpdateBrokersBreakStatus(); void UpdateBrokersBreakStatus();
void PatchRegistry(); void PatchRegistry();
uint32 ExportTree(ReferenceContainer *container, StreamString &json,
const char8 *pathPrefix);
void ExportTreeNode(const char8 *path, StreamString &out); void ExportTreeNode(const char8 *path, StreamString &out);
void EnrichWithConfig(const char8 *path, StreamString &json); void EnrichWithConfig(const char8 *path, StreamString &json);
static void JsonifyDatabase(ConfigurationDatabase &db, StreamString &json); static void JsonifyDatabase(ConfigurationDatabase &db, StreamString &json);
@@ -9,6 +9,7 @@
#include "MemoryOperationsHelper.h" #include "MemoryOperationsHelper.h"
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h>
#include <errno.h> #include <errno.h>
namespace MARTe { namespace MARTe {
@@ -26,6 +27,7 @@ UDPSClient::UDPSClient()
maxPayloadSize(UDPS_CLIENT_DEFAULT_MAX_PAYLOAD), maxPayloadSize(UDPS_CLIENT_DEFAULT_MAX_PAYLOAD),
cpuMask(0xFFFFFFFFu), cpuMask(0xFFFFFFFFu),
stackSize(65536u), stackSize(65536u),
recvBufferSize(UDPS_CLIENT_DEFAULT_RECV_BUFFER),
listener(NULL_PTR(UDPSClientListener *)), listener(NULL_PTR(UDPSClientListener *)),
threadService(*this), threadService(*this),
connected(false), connected(false),
@@ -98,6 +100,9 @@ bool UDPSClient::Initialise(StructuredDataI &data) {
(void) data.Read("CPUMask", cpuMask); (void) data.Read("CPUMask", cpuMask);
(void) data.Read("StackSize", stackSize); (void) data.Read("StackSize", stackSize);
recvBufferSize = UDPS_CLIENT_DEFAULT_RECV_BUFFER;
(void) data.Read("RecvBufferSize", recvBufferSize);
return true; return true;
} }
@@ -209,6 +214,23 @@ bool UDPSClient::Connect() {
return ok; return ok;
} }
void UDPSClient::SetRecvBufferSize(BasicUDPSocket &sock) {
/* BasicUDPSocket exposes no SO_RCVBUF API; the OS default (Linux
* rmem_default, typically ~208 KiB) is easily overrun by high-throughput
* sources, causing silent kernel-level datagram drops. Work around this
* by calling setsockopt() directly on the raw handle. Best-effort: a
* failure here just leaves the OS default in place. */
Handle fd = sock.GetReadHandle();
if (fd >= 0) {
int32 sz = static_cast<int32>(recvBufferSize);
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) != 0) {
REPORT_ERROR_STATIC(ErrorManagement::Warning,
"UDPSClient: Could not set SO_RCVBUF to %u bytes.",
recvBufferSize);
}
}
}
bool UDPSClient::ConnectUnicast() { bool UDPSClient::ConnectUnicast() {
// Open a local UDP socket bound to an ephemeral port // Open a local UDP socket bound to an ephemeral port
if (!recvSocket.Open()) { if (!recvSocket.Open()) {
@@ -216,6 +238,7 @@ bool UDPSClient::ConnectUnicast() {
"UDPSClient: Could not open receive socket."); "UDPSClient: Could not open receive socket.");
return false; return false;
} }
SetRecvBufferSize(recvSocket);
if (!recvSocket.Listen(0u)) { if (!recvSocket.Listen(0u)) {
REPORT_ERROR_STATIC(ErrorManagement::Warning, REPORT_ERROR_STATIC(ErrorManagement::Warning,
@@ -256,6 +279,7 @@ bool UDPSClient::ConnectMulticast() {
"UDPSClient: Could not open multicast socket."); "UDPSClient: Could not open multicast socket.");
return false; return false;
} }
SetRecvBufferSize(mcastSocket);
bool ok = mcastSocket.Listen(dataPort); bool ok = mcastSocket.Listen(dataPort);
if (!ok) { if (!ok) {
@@ -378,6 +402,15 @@ bool UDPSClient::ReceiveAndProcess() {
return false; return false;
} }
/* HI-6: guard against FD_SETSIZE overflow */
if (fd < 0 || fd >= FD_SETSIZE ||
(tcpFd >= 0 && tcpFd >= FD_SETSIZE)) {
REPORT_ERROR_STATIC(ErrorManagement::Warning,
"UDPSClient: fd >= FD_SETSIZE (%d/%d) — skipping select.",
fd, tcpFd);
return false;
}
fd_set rset; fd_set rset;
FD_ZERO(&rset); FD_ZERO(&rset);
FD_SET(fd, &rset); FD_SET(fd, &rset);
@@ -95,6 +95,12 @@ public:
/** Default maximum payload size (bytes, excluding 17-byte header). */ /** Default maximum payload size (bytes, excluding 17-byte header). */
static const uint32 UDPS_CLIENT_DEFAULT_MAX_PAYLOAD = 1400u; static const uint32 UDPS_CLIENT_DEFAULT_MAX_PAYLOAD = 1400u;
/** Default OS UDP receive socket buffer size (bytes). The Linux default
* (rmem_default, typically ~208 KiB) is easily overrun by high-throughput
* sources (e.g. multi-hundred-KiB bursts every few ms), causing silent
* kernel-level datagram drops. 4 MiB gives generous burst headroom. */
static const uint32 UDPS_CLIENT_DEFAULT_RECV_BUFFER = 4194304u; // 4 MiB
UDPSClient(); UDPSClient();
virtual ~UDPSClient(); virtual ~UDPSClient();
@@ -111,6 +117,7 @@ public:
* - MaxPayloadSize (uint32) Max payload bytes per datagram, excluding header. Default 1400. * - MaxPayloadSize (uint32) Max payload bytes per datagram, excluding header. Default 1400.
* - CPUMask (uint32) CPU affinity mask for the receive thread. Default 0xFFFFFFFF. * - CPUMask (uint32) CPU affinity mask for the receive thread. Default 0xFFFFFFFF.
* - StackSize (uint32) Stack size for the receive thread. Default 65536. * - StackSize (uint32) Stack size for the receive thread. Default 65536.
* - RecvBufferSize (uint32) OS UDP receive socket buffer size (bytes). Default 4 MiB.
*/ */
bool Initialise(StructuredDataI &data); bool Initialise(StructuredDataI &data);
@@ -165,6 +172,9 @@ private:
bool ConnectUnicast(); bool ConnectUnicast();
bool ConnectMulticast(); bool ConnectMulticast();
/** Set the OS receive buffer size (SO_RCVBUF) on a UDP socket's raw handle. */
void SetRecvBufferSize(BasicUDPSocket &sock);
void ProcessDatagram(const uint8 *buf, uint32 size); void ProcessDatagram(const uint8 *buf, uint32 size);
/** Read one full UDPS frame (header + payload) from the TCP control socket. */ /** Read one full UDPS frame (header + payload) from the TCP control socket. */
bool ReceiveTCPFrame(); bool ReceiveTCPFrame();
@@ -188,6 +198,7 @@ private:
uint32 maxPayloadSize; uint32 maxPayloadSize;
uint32 cpuMask; uint32 cpuMask;
uint32 stackSize; uint32 stackSize;
uint32 recvBufferSize;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Runtime state // Runtime state
@@ -268,6 +268,7 @@ void UDPSServer::ServiceClients() {
} }
// Non-blocking peek // Non-blocking peek
int fd = tcpClients[i]->GetReadHandle(); int fd = tcpClients[i]->GetReadHandle();
if (fd < 0 || fd >= FD_SETSIZE) { continue; /* HI-6: skip FDs outside select range */ }
fd_set rset; fd_set rset;
FD_ZERO(&rset); FD_ZERO(&rset);
FD_SET(fd, &rset); FD_SET(fd, &rset);
@@ -303,6 +304,7 @@ void UDPSServer::ServiceClients() {
return; return;
} }
int fd = serverSocket.GetReadHandle(); int fd = serverSocket.GetReadHandle();
if (fd < 0 || fd >= FD_SETSIZE) { return; /* HI-6 */ }
fd_set rset; fd_set rset;
FD_ZERO(&rset); FD_ZERO(&rset);
FD_SET(fd, &rset); FD_SET(fd, &rset);
-12
View File
@@ -1,12 +0,0 @@
# BUG
## ImgUI Cleint
- trigger mode normal (trigger only first time)
## E2E test
- [ ] s29_mcast_scalar should fail (holes in the received data)
- [ ] s30_mcast_arr_fullarray should fail (holes in the received data)
- [ ] s47_mcast_multisrc should fail (holes in reconstructed data)
- [ ] s51_8x1msps_100hz should fail (holes in reconstructed data)
@@ -0,0 +1,73 @@
/**
* @file BoundsCheckTest.cpp
* @brief Reproduction tests for HI-1 (integer overflow in bounds check) and
* HI-4 (unclamped forcedValue memcpy).
*
* These tests verify that the 64-bit bounds check pattern correctly rejects
* crafted payloads whose 32-bit multiply would overflow, and that the
* forcedValue clamp prevents OOB reads.
*/
#include <gtest/gtest.h>
#include "GeneralDefinitions.h"
// HI-1: Verify that a 64-bit bounds check rejects a payload where
// elemsToRead * wireElemBytes would overflow uint32.
TEST(BoundsCheckTest, OverflowRejected) {
// Simulate: numSamples = 0x20000001, wireElemBytes = 8
// 32-bit: 0x20000001 * 8 = 0x8 (overflow!)
// 64-bit: 0x100000008 (correctly large, > any reasonable payload size)
MARTe::uint32 elemsToRead = 0x20000001u;
MARTe::uint32 wireElemBytes = 8u;
MARTe::uint32 off = 12u; // after HRT + numSamples
MARTe::uint32 size = 1400u; // typical max payload
// This is the FIXED pattern (64-bit):
MARTe::uint64 bytesNeeded = static_cast<MARTe::uint64>(off) +
static_cast<MARTe::uint64>(elemsToRead) *
static_cast<MARTe::uint64>(wireElemBytes);
// Should reject (bytesNeeded >> size)
EXPECT_GT(bytesNeeded, static_cast<MARTe::uint64>(size))
<< "64-bit check should detect overflow that 32-bit would miss";
// Verify the OLD (buggy) 32-bit pattern would have passed:
MARTe::uint32 oldCheck = off + (elemsToRead * wireElemBytes);
// On 32-bit: 0x20000001 * 8 = 0x100000008 truncated to 0x8
// off + 0x8 = 20, which is < 1400, so the old check would pass (bug!)
// On 64-bit: the multiply doesn't overflow, so oldCheck is huge
// This test documents that the 64-bit fix is necessary on 32-bit platforms
// and correct on 64-bit.
(void) oldCheck;
}
// HI-1: Verify a normal (non-overflow) case passes the 64-bit check.
TEST(BoundsCheckTest, NormalCasePasses) {
MARTe::uint32 elemsToRead = 100u;
MARTe::uint32 wireElemBytes = 4u;
MARTe::uint32 off = 12u;
MARTe::uint32 size = 500u;
MARTe::uint64 bytesNeeded = static_cast<MARTe::uint64>(off) +
static_cast<MARTe::uint64>(elemsToRead) *
static_cast<MARTe::uint64>(wireElemBytes);
EXPECT_LE(bytesNeeded, static_cast<MARTe::uint64>(size))
<< "normal case should pass the bounds check";
}
// HI-1: Verify numRows * numCols overflow is detected.
TEST(BoundsCheckTest, NumRowsNumColsOverflow) {
MARTe::uint32 numRows = 0x10000u;
MARTe::uint32 numCols = 0x10000u;
// 32-bit: 0x10000 * 0x10000 = 0 (overflow!)
MARTe::uint32 oldResult = numRows * numCols;
EXPECT_EQ(oldResult, 0u) << "32-bit multiply should overflow to 0";
// 64-bit fix:
MARTe::uint64 newResult = static_cast<MARTe::uint64>(numRows) *
static_cast<MARTe::uint64>(numCols);
EXPECT_EQ(newResult, static_cast<MARTe::uint64>(0x100000000ULL))
<< "64-bit multiply should give correct result";
EXPECT_GT(newResult, static_cast<MARTe::uint64>(0x100000u))
<< "should exceed the sanity cap, triggering rejection";
}
+1 -1
View File
@@ -22,7 +22,7 @@
# #
############################################################# #############################################################
OBJSX = TriggerEngineSrc.x BinaryRecorderSrc.x SignalRingBufferGTest.x TriggerEngineGTest.x LTTBGTest.x BinaryRecorderGTest.x OBJSX = TriggerEngineSrc.x BinaryRecorderSrc.x SignalRingBufferGTest.x TriggerEngineGTest.x LTTBGTest.x BinaryRecorderGTest.x BoundsCheckTest.x WSServerBufferTest.x
PACKAGE=Applications PACKAGE=Applications
ROOT_DIR=../../.. ROOT_DIR=../../..
@@ -0,0 +1,92 @@
/**
* @file WSServerBufferTest.cpp
* @brief Reproduction test for CR-1: 1-byte heap OOB write in WSServer.
*
* Verifies that the receive buffer allocated in ClientReadLoop is large enough
* to hold a maximal masked WebSocket frame (14-byte header + 65536 payload)
* plus one extra byte for in-place NUL-termination, without overflowing.
*
* Build: linked into the GTest harness alongside MainGTest.cpp.
*/
#include "WSFrame.h"
#include <gtest/gtest.h>
#include <cstdlib>
#include <cstring>
using namespace StreamHub;
// Mirror the WSServer.h constant (TEST_WS_MAX_RECV_PAYLOAD = 65536).
static const uint32 TEST_WS_MAX_RECV_PAYLOAD = 65536u;
// Test: A maximal masked WebSocket frame (64-bit extended length, masked)
// with payloadLen = TEST_WS_MAX_RECV_PAYLOAD must fit within kRecvBuf, and
// payload[plen] must be a valid in-bounds index (for NUL-termination).
TEST(WSServerBufferTest, MaximalFrameFitsInRecvBuffer) {
// Reproduce the exact buffer sizing logic from WSServer::ClientReadLoop.
const uint32 kRecvBuf = TEST_WS_MAX_RECV_PAYLOAD + 14u + 1u;
uint8 *buf = new uint8[kRecvBuf];
// Build a maximal masked frame: FIN + TEXT, payloadLen=65536 (64-bit ext),
// mask=1.
uint8 frame[14 + 65536];
frame[0] = WS_FIN_BIT | WS_OPCODE_TEXT; // FIN + TEXT
frame[1] = WS_MASK_BIT | 127u; // masked + 64-bit length
// 8-byte extended length = 65536
uint64 plen = TEST_WS_MAX_RECV_PAYLOAD;
for (int i = 7; i >= 0; i--) {
frame[2 + i] = static_cast<uint8>(plen & 0xFFu);
plen >>= 8u;
}
// 4-byte mask key
frame[10] = 0xAA; frame[11] = 0xBB; frame[12] = 0xCC; frame[13] = 0xDD;
// Payload (doesn't matter, just fill with zeros)
memset(frame + 14, 0, 65536);
// Copy into buf (simulating a TCP read)
ASSERT_LE(sizeof(frame), static_cast<size_t>(kRecvBuf));
memcpy(buf, frame, sizeof(frame));
// Parse the header
WSFrameHeader hdr;
ASSERT_TRUE(WSParseHeader(buf, sizeof(frame), hdr));
ASSERT_EQ(hdr.headerSize, 14u);
ASSERT_EQ(hdr.payloadLen, static_cast<uint64>(TEST_WS_MAX_RECV_PAYLOAD));
ASSERT_TRUE(hdr.masked);
// Unmask
uint8 *payload = buf + hdr.headerSize;
WSUnmask(payload, static_cast<uint32>(hdr.payloadLen), hdr.maskKey);
// The critical check: payload[plen] must be within the buffer.
// Before the fix, kRecvBuf was 65550 and payload[65536] = buf[65550]
// was one byte past the end. After the fix (+1), it's in bounds.
uint32 plenIdx = static_cast<uint32>(hdr.payloadLen);
ASSERT_LT(hdr.headerSize + plenIdx, kRecvBuf)
<< "payload[plen] would be out of bounds — buffer overflow!";
// Simulate the NUL-termination that WSServer does:
uint8 savedByte = payload[plenIdx];
payload[plenIdx] = '\0';
// Verify it's within bounds (no ASan/heap overflow)
EXPECT_EQ(payload[plenIdx], '\0');
payload[plenIdx] = savedByte;
delete[] buf;
}
// Test: Verify the old (buggy) buffer size would have overflowed.
// This documents the bug for future readers.
TEST(WSServerBufferTest, OldBufferSizeWouldOverflow) {
const uint32 oldKRecvBuf = TEST_WS_MAX_RECV_PAYLOAD + 14u; // the buggy size
const uint32 headerSize = 14u;
const uint32 plen = TEST_WS_MAX_RECV_PAYLOAD;
// headerSize + plen == oldKRecvBuf, so payload[plen] = buf[oldKRecvBuf]
// is one byte past the end.
ASSERT_EQ(headerSize + plen, oldKRecvBuf)
<< "Expected the old buffer to be exactly full (no room for NUL term)";
// The fix adds +1:
const uint32 newKRecvBuf = TEST_WS_MAX_RECV_PAYLOAD + 14u + 1u;
ASSERT_LT(headerSize + plen, newKRecvBuf)
<< "New buffer must have room for the NUL-termination byte";
}
@@ -0,0 +1,427 @@
../../../Build/x86-linux/Applications/StreamHub/BinaryRecorderGTest.o: BinaryRecorderGTest.cpp \
../../../Source/Applications/StreamHub/BinaryRecorder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
../../../Common/UDP/UDPSProtocol.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
../../../Build/x86-linux/Applications/StreamHub/BinaryRecorderSrc.o: BinaryRecorderSrc.cpp \
../../../Source/Applications/StreamHub/BinaryRecorder.cpp \
../../../Source/Applications/StreamHub/BinaryRecorder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
../../../Common/UDP/UDPSProtocol.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h
../../../Build/x86-linux/Applications/StreamHub/BoundsCheckTest.o: BoundsCheckTest.cpp \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h
../../../Build/x86-linux/Applications/StreamHub/LTTBGTest.o: LTTBGTest.cpp ../../../Source/Applications/StreamHub/LTTB.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
../../../Build/x86-linux/Applications/StreamHub/SignalRingBufferGTest.o: SignalRingBufferGTest.cpp \
../../../Source/Applications/StreamHub/SignalRingBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
../../../Build/x86-linux/Applications/StreamHub/TriggerEngineGTest.o: TriggerEngineGTest.cpp \
../../../Source/Applications/StreamHub/TriggerEngine.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
../../../Build/x86-linux/Applications/StreamHub/TriggerEngineSrc.o: TriggerEngineSrc.cpp \
../../../Source/Applications/StreamHub/TriggerEngine.cpp \
../../../Source/Applications/StreamHub/TriggerEngine.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h
../../../Build/x86-linux/Applications/StreamHub/WSServerBufferTest.o: WSServerBufferTest.cpp \
../../../Source/Applications/StreamHub/WSFrame.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
@@ -0,0 +1,427 @@
BinaryRecorderGTest.o: BinaryRecorderGTest.cpp \
../../../Source/Applications/StreamHub/BinaryRecorder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
../../../Common/UDP/UDPSProtocol.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
BinaryRecorderSrc.o: BinaryRecorderSrc.cpp \
../../../Source/Applications/StreamHub/BinaryRecorder.cpp \
../../../Source/Applications/StreamHub/BinaryRecorder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
../../../Common/UDP/UDPSProtocol.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h
BoundsCheckTest.o: BoundsCheckTest.cpp \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h
LTTBGTest.o: LTTBGTest.cpp ../../../Source/Applications/StreamHub/LTTB.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
SignalRingBufferGTest.o: SignalRingBufferGTest.cpp \
../../../Source/Applications/StreamHub/SignalRingBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
TriggerEngineGTest.o: TriggerEngineGTest.cpp \
../../../Source/Applications/StreamHub/TriggerEngine.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
TriggerEngineSrc.o: TriggerEngineSrc.cpp \
../../../Source/Applications/StreamHub/TriggerEngine.cpp \
../../../Source/Applications/StreamHub/TriggerEngine.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h
WSServerBufferTest.o: WSServerBufferTest.cpp \
../../../Source/Applications/StreamHub/WSFrame.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
@@ -0,0 +1,199 @@
../../../../Build/x86-linux/Components/DataSources/UDPStreamer/UDPStreamerGTest.o: UDPStreamerGTest.cpp \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h \
UDPStreamerTest.h
../../../../Build/x86-linux/Components/DataSources/UDPStreamer/UDPStreamerTest.o: UDPStreamerTest.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicTCPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetHostCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetMulticastCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/SocketCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L5GAMs/GAMScheduler.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMSchedulerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ProcessorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/TimingDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryArea.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/Message.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/MultiThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/Threads.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ThreadsB.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/ExceptionHandler.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSMETHODREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodInterfaceMapper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCaller.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCallerT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMSchedulerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/Message.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilterPool.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplicationConfigurationBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/RegisteredMethodsMessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/StandardParser.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyTypeCreator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/LexicalAnalyzer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/GrammarInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/Token.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TokenInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/RuntimeEvaluator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticStack.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/VariableInformation.h \
../../../../Source/Components/DataSources/UDPStreamer/UDPStreamer.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
../../../../Source/Components/Interfaces/UDPStream/UDPSServer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
../../../../Common/UDP/UDPSProtocol.h UDPStreamerTest.h
@@ -0,0 +1,199 @@
UDPStreamerGTest.o: UDPStreamerGTest.cpp \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h \
UDPStreamerTest.h
UDPStreamerTest.o: UDPStreamerTest.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicTCPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetHostCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetMulticastCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/SocketCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L5GAMs/GAMScheduler.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMSchedulerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ProcessorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/TimingDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryArea.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/Message.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/MultiThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/Threads.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ThreadsB.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/ExceptionHandler.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSMETHODREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodInterfaceMapper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCaller.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCallerT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMSchedulerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/Message.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilterPool.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplicationConfigurationBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/RegisteredMethodsMessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/StandardParser.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyTypeCreator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/LexicalAnalyzer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/GrammarInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/Token.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TokenInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/RuntimeEvaluator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticStack.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/VariableInformation.h \
../../../../Source/Components/DataSources/UDPStreamer/UDPStreamer.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
../../../../Source/Components/Interfaces/UDPStream/UDPSServer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
../../../../Common/UDP/UDPSProtocol.h UDPStreamerTest.h
@@ -0,0 +1 @@
include Makefile.inc
@@ -0,0 +1,59 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
OBJSX = UDPStreamerClientTest.x UDPStreamerClientGTest.x
PACKAGE=Components/DataSources
ROOT_DIR=../../../..
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
INCLUDES += -I.
INCLUDES += -I$(ROOT_DIR)/Source/Components/Interfaces/UDPStream
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4StateMachine
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Lib/gtest-1.7.0/include
INCLUDES += -I$(ROOT_DIR)/Common/UDP
INCLUDES += -I$(ROOT_DIR)/Source/Components/DataSources/UDPStreamerClient
all: $(OBJS) \
$(BUILD_DIR)/UDPStreamerClientTest$(LIBEXT)
echo $(OBJS)
include depends.$(TARGET)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
@@ -0,0 +1,142 @@
/**
* @file UDPStreamerClientGTest.cpp
* @brief Source file for class UDPStreamerClientGTest
* @date 01/07/2026
* @author Martino Ferrari
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*
* @details This source file contains the GTest wrapper for all UDPStreamerClient tests.
*/
#define DLL_API
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
#include "gtest/gtest.h"
#include <limits.h>
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
#include "UDPStreamerClientTest.h"
/*---------------------------------------------------------------------------*/
/* Method definitions */
/*---------------------------------------------------------------------------*/
TEST(UDPStreamerClientGTest, TestInitialise_Valid) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestInitialise_Valid());
}
TEST(UDPStreamerClientGTest, TestInitialise_DefaultServerAddress) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestInitialise_DefaultServerAddress());
}
TEST(UDPStreamerClientGTest, TestInitialise_DefaultPort) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestInitialise_DefaultPort());
}
TEST(UDPStreamerClientGTest, TestInitialise_MulticastMode_Valid) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestInitialise_MulticastMode_Valid());
}
TEST(UDPStreamerClientGTest, TestInitialise_MulticastMode_DefaultDataPort) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestInitialise_MulticastMode_DefaultDataPort());
}
TEST(UDPStreamerClientGTest, TestSetConfiguredDatabase_MultipleSignals) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestSetConfiguredDatabase_MultipleSignals());
}
TEST(UDPStreamerClientGTest, TestPrepareNextState_StartsReceiver) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestPrepareNextState_StartsReceiver());
}
TEST(UDPStreamerClientGTest, TestSynchronise_NoData) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestSynchronise_NoData());
}
TEST(UDPStreamerClientGTest, TestOnUDPSConfig_BasicAccept) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSConfig_BasicAccept());
}
TEST(UDPStreamerClientGTest, TestOnUDPSConfig_SignalCountMismatch) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSConfig_SignalCountMismatch());
}
TEST(UDPStreamerClientGTest, TestOnUDPSConfig_NameMismatch) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSConfig_NameMismatch());
}
TEST(UDPStreamerClientGTest, TestOnUDPSConfig_ElementCountMismatch) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSConfig_ElementCountMismatch());
}
TEST(UDPStreamerClientGTest, TestOnUDPSConfig_TooSmallPayload) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSConfig_TooSmallPayload());
}
TEST(UDPStreamerClientGTest, TestOnUDPSData_QuantizedUint16) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSData_QuantizedUint16());
}
TEST(UDPStreamerClientGTest, TestOnUDPSData_QuantizedInt8) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSData_QuantizedInt8());
}
TEST(UDPStreamerClientGTest, TestOnUDPSData_MultipleSignalsOrder) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSData_MultipleSignalsOrder());
}
TEST(UDPStreamerClientGTest, TestOnUDPSData_AccumulateMode) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSData_AccumulateMode());
}
TEST(UDPStreamerClientGTest, TestOnUDPSData_TooSmallPayload) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSData_TooSmallPayload());
}
TEST(UDPStreamerClientGTest, TestOnUDPSData_BeforeConfig) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSData_BeforeConfig());
}
TEST(UDPStreamerClientGTest, TestOnUDPSDisconnected_InvalidatesConfig) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestOnUDPSDisconnected_InvalidatesConfig());
}
TEST(UDPStreamerClientGTest, TestExecute_ConnectConfigDataEndToEnd) {
UDPStreamerClientTest test;
ASSERT_TRUE(test.TestExecute_ConnectConfigDataEndToEnd());
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,157 @@
/**
* @file UDPStreamerClientTest.h
* @brief Header file for class UDPStreamerClientTest
* @date 01/07/2026
* @author Martino Ferrari
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*
* @details This header file contains the declaration of the class UDPStreamerClientTest
* with all of its public, protected and private members. It may also include
* definitions for inline methods which need to be visible to the compiler.
*/
#ifndef UDPSTREAMERCLIENTTEST_H_
#define UDPSTREAMERCLIENTTEST_H_
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Class declaration */
/*---------------------------------------------------------------------------*/
/**
* @brief Tests the UDPStreamerClient DataSource public methods.
*/
class UDPStreamerClientTest {
public:
/**
* @brief Tests Initialise with a fully valid unicast configuration.
*/
bool TestInitialise_Valid();
/**
* @brief Tests that a missing ServerAddress uses the default (127.0.0.1).
*/
bool TestInitialise_DefaultServerAddress();
/**
* @brief Tests that a missing Port uses the default (44500).
*/
bool TestInitialise_DefaultPort();
/**
* @brief Tests Initialise with MulticastGroup and an explicit DataPort.
*/
bool TestInitialise_MulticastMode_Valid();
/**
* @brief Tests that DataPort defaults to Port+1 when MulticastGroup is
* set but DataPort is absent.
*/
bool TestInitialise_MulticastMode_DefaultDataPort();
/**
* @brief Tests SetConfiguredDatabase / AllocateMemory with several
* signals of different types and array sizes.
*/
bool TestSetConfiguredDatabase_MultipleSignals();
/**
* @brief Tests PrepareNextState starts the background receiver thread.
*/
bool TestPrepareNextState_StartsReceiver();
/**
* @brief Tests that Synchronise() with no data received is a safe no-op.
*/
bool TestSynchronise_NoData();
/**
* @brief Tests the full OnUDPSConfig -> OnUDPSData -> Synchronise path
* for a single unquantised scalar signal.
*/
bool TestOnUDPSConfig_BasicAccept();
/**
* @brief Tests that a CONFIG with a different signal count is rejected.
*/
bool TestOnUDPSConfig_SignalCountMismatch();
/**
* @brief Tests that a CONFIG with a mismatched signal name is rejected.
*/
bool TestOnUDPSConfig_NameMismatch();
/**
* @brief Tests that a CONFIG with a mismatched element count is rejected.
*/
bool TestOnUDPSConfig_ElementCountMismatch();
/**
* @brief Tests that an undersized CONFIG payload is safely rejected.
*/
bool TestOnUDPSConfig_TooSmallPayload();
/**
* @brief Tests UINT16 dequantisation into a Float32Bit destination signal.
*/
bool TestOnUDPSData_QuantizedUint16();
/**
* @brief Tests INT8 dequantisation formula into a Float64Bit destination signal.
*/
bool TestOnUDPSData_QuantizedInt8();
/**
* @brief Tests that multiple signals decode into the correct buffer offsets.
*/
bool TestOnUDPSData_MultipleSignalsOrder();
/**
* @brief Tests Accumulate publishing mode: scalar signals publish only the
* most recent sample, array signals publish once regardless of numSamples.
*/
bool TestOnUDPSData_AccumulateMode();
/**
* @brief Tests that an undersized DATA payload (missing timestamp) is a safe no-op.
*/
bool TestOnUDPSData_TooSmallPayload();
/**
* @brief Tests that OnUDPSData before a valid CONFIG is a safe no-op.
*/
bool TestOnUDPSData_BeforeConfig();
/**
* @brief Tests that OnUDPSDisconnected() invalidates the CONFIG so
* subsequent DATA payloads are ignored until a new CONFIG arrives.
*/
bool TestOnUDPSDisconnected_InvalidatesConfig();
/**
* @brief Tests the full CONNECT -> CONFIG -> DATA flow over real loopback
* UDP sockets, mirroring the server side of the wire protocol.
*/
bool TestExecute_ConnectConfigDataEndToEnd();
};
#endif /* UDPSTREAMERCLIENTTEST_H_ */
@@ -0,0 +1,197 @@
../../../../Build/x86-linux/Components/DataSources/UDPStreamerClient/UDPStreamerClientGTest.o: UDPStreamerClientGTest.cpp \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h \
UDPStreamerClientTest.h
../../../../Build/x86-linux/Components/DataSources/UDPStreamerClient/UDPStreamerClientTest.o: UDPStreamerClientTest.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetHostCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetMulticastCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/SocketCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSMETHODREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodInterfaceMapper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCaller.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCallerT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMSchedulerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ProcessorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/TimingDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryArea.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/Message.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilterPool.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplicationConfigurationBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/RegisteredMethodsMessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/StandardParser.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyTypeCreator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/LexicalAnalyzer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/GrammarInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/Token.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TokenInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/RuntimeEvaluator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticStack.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/VariableInformation.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/Threads.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ThreadsB.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/ExceptionHandler.h \
../../../../Common/UDP/UDPSProtocol.h \
../../../../Source/Components/DataSources/UDPStreamerClient/UDPStreamerClient.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
../../../../Source/Components/Interfaces/UDPStream/UDPSClient.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicTCPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h \
UDPStreamerClientTest.h
@@ -0,0 +1,197 @@
UDPStreamerClientGTest.o: UDPStreamerClientGTest.cpp \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h \
UDPStreamerClientTest.h
UDPStreamerClientTest.o: UDPStreamerClientTest.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetHostCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetMulticastCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/SocketCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSMETHODREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodInterfaceMapper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCaller.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassMethodCallerT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMSchedulerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ProcessorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/TimingDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAMDataSource.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryArea.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/Message.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilterPool.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/MessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplicationConfigurationBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/RealTimeApplication.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Messages/RegisteredMethodsMessageFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/StandardParser.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyTypeCreator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/LexicalAnalyzer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/GrammarInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/Token.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TokenInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ParserI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/RuntimeEvaluator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticStack.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/VariableInformation.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/Threads.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ThreadsB.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/ExceptionHandler.h \
../../../../Common/UDP/UDPSProtocol.h \
../../../../Source/Components/DataSources/UDPStreamerClient/UDPStreamerClient.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
../../../../Source/Components/Interfaces/UDPStream/UDPSClient.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicTCPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h \
UDPStreamerClientTest.h
+1 -1
View File
@@ -373,7 +373,7 @@ $App = {
// ── DebugService ────────────────────────────────────────────────────────────── // ── DebugService ──────────────────────────────────────────────────────────────
// Patches the broker registry at startup so every signal is traceable. // Patches the broker registry at startup so every signal is traceable.
// TcpLogger is auto-injected on LogPort (9090) — no explicit DataSource needed. // TcpLogger is auto-injected on LogPort (9090) — no explicit DataSource needed.
// Connect the debugger web UI (./run_combined_test.sh -d) to: // Connect the debugger web UI (Client/debugger) to:
// Host=127.0.0.1 TCP=8080 UDP=8081 Log=9090 // Host=127.0.0.1 TCP=8080 UDP=8081 Log=9090
+DebugService = { +DebugService = {
Class = DebugService Class = DebugService
Binary file not shown.
Binary file not shown.
-63
View File
@@ -1,63 +0,0 @@
import os
import report_build as RB
_SR = {
"overall": "PASS",
"cases": [
{"id": "ds_size_1000", "shape": "hub", "axis": "ds_signal_elements",
"level": 1000, "status": "PASS", "survival": True, "clients": 1,
"min_frames": 200, "marte_cpu_s": 12.8, "marte_rss_mb": 10.4,
"hub_cpu_s": 2.33, "hub_rss_mb": 28.3, "zoom_count": 0, "zoom_fail": 0,
"zoom_p50_ms": 0.0, "zoom_p95_ms": 0.0, "fails": []},
{"id": "ds_size_4000", "shape": "hub", "axis": "ds_signal_elements",
"level": 4000, "status": "PASS", "survival": True, "clients": 1,
"min_frames": 180, "marte_cpu_s": 20.0, "marte_rss_mb": 14.0,
"hub_cpu_s": 3.0, "hub_rss_mb": 40.0, "zoom_count": 0, "zoom_fail": 0,
"zoom_p50_ms": 0.0, "zoom_p95_ms": 0.0, "fails": []},
{"id": "hub_reqrate_50", "shape": "hub", "axis": "hub_zoom_reqrate_hz",
"level": 50, "status": "PASS", "survival": True, "clients": 4,
"min_frames": 100, "marte_cpu_s": 5.0, "marte_rss_mb": 12.0,
"hub_cpu_s": 8.0, "hub_rss_mb": 60.0, "zoom_count": 400, "zoom_fail": 0,
"zoom_p50_ms": 12.0, "zoom_p95_ms": 35.0, "fails": []},
],
}
def test_build_stress_groups_by_axis_sorted_by_level():
st = RB.build_stress(_SR)
assert st["overall"] == "PASS"
assert len(st["cases"]) == 3
assert set(st["by_axis"]) == {"ds_signal_elements", "hub_zoom_reqrate_hz"}
levels = [c["level"] for c in st["by_axis"]["ds_signal_elements"]]
assert levels == [1000, 4000] # sorted ascending
def test_stress_headline_aggregates():
st = RB.build_stress(_SR)
hl = RB.stress_headline(st)
assert hl["stress_pass"] == 3
assert hl["stress_fail"] == 0
assert hl["stress_max_hub_rss_mb"] == 60.0
assert hl["stress_max_marte_rss_mb"] == 14.0
assert hl["stress_max_zoom_p95_ms"] == 35.0
def test_stress_plots_one_png_per_axis(tmp_path):
st = RB.build_stress(_SR)
made = RB.stress_plots(st["by_axis"], str(tmp_path))
names = {os.path.basename(p) for p in made}
assert "stress_ds_signal_elements.png" in names
assert "stress_hub_zoom_reqrate_hz.png" in names
for p in made:
assert os.path.exists(p)
def test_regression_includes_stress_when_present():
curr = {"e2e_pass": 5, "stress_max_hub_rss_mb": 60.0}
prev = {"e2e_pass": 5, "stress_max_hub_rss_mb": 50.0}
labels = dict(RB._LABELS); labels["stress_max_hub_rss_mb"] = "Stress max hub RSS (MB)"
directions = dict(RB._DIRECTION); directions["stress_max_hub_rss_mb"] = False
rows = RB.regression(curr, prev, labels, directions)
row = next(r for r in rows if r["key"] == "stress_max_hub_rss_mb")
assert row["delta"] == 10.0
assert row["better"] is False # RSS went up → worse
-413
View File
@@ -1,413 +0,0 @@
// UDPStreamerClient — E2E Test Report
// Author: Martino Ferrari
// Date: June 2026
#set document(
title: "UDPStreamerClient End-to-End Test Report",
author: "Martino Ferrari",
date: datetime(year: 2026, month: 6, day: 24),
)
#set page(numbering: "1 / 1", margin: (left: 2.5cm, right: 2.5cm, top: 2cm, bottom: 2cm))
#set heading(numbering: "1.")
#set par(justify: true)
#show link: underline
#show raw.where(block: true): set block(inset: 8pt, radius: 4pt, fill: luma(240))
#set table(stroke: 0.5pt, inset: 8pt)
// ── Live validation data (emitted by validate_binary.py --json) ──
#let uni = json("e2e_unicast.json")
#let multi = json("e2e_multicast.json")
#let fidx(v) = if v < 0 { [] } else { [#v] }
#let pct(n, d) = if d > 0 { [#(calc.round(100 * n / d, digits: 1))%] } else { [] }
#let status-badge(d) = {
let c = if d.passed { green.darken(20%) } else { red.darken(10%) }
text(fill: c, weight: "bold")[#d.status]
}
// Validation metrics table for one mode's json record.
#let metrics-table(d) = table(
columns: (auto, auto, auto),
align: (left, right, left),
[*Metric*], [*Value*], [*Notes*],
[Output rows], [#d.n_rows_out], [Cycles captured by `FileWriter`],
[Matching rows], [#d.matching_rows (#pct(d.matching_rows, d.n_rows_out))], [Non-zero rows equal to an input row],
[Zero rows], [#d.zero_rows (#pct(d.zero_rows, d.n_rows_out))], [Startup transient before first `DATA`],
[Mismatching rows], [#d.mismatching_rows (#pct(d.mismatching_rows, d.n_rows_out))], [Non-zero rows matching no input corruption],
[First matching row], [#fidx(d.first_matching_row)], [Index of first transported row],
[First zero row], [#fidx(d.first_zero_row)], [Index of first all-zero row],
[First mismatching row], [#fidx(d.first_mismatch_row)], [`—` when no corruption],
[Status], [#status-badge(d)], [#d.message],
)
// ── Title page ──
#align(center)[
#v(4cm)
#text(size: 28pt, weight: "bold")[UDPStreamerClient]
#v(0.5cm)
#text(size: 18pt)[End-to-End Test Report]
#v(1.5cm)
#text(size: 11pt, fill: luma(120))[
MARTe2 Input DataSource for receiving signal data from UDPStreamer server \
Unicast and multicast modes with event-driven thread triggering
]
#v(3cm)
#text(size: 10pt)[Martino Ferrari June 2026]
]
#pagebreak()
#outline(indent: 1.5em, depth: 3)
#pagebreak()
// ═══════════════════════════════════════
// 1. Architecture
// ═══════════════════════════════════════
= Architecture Overview
== End-to-End Dataflow
#figure(
caption: [Pipeline from binary file input to binary file output across two MARTe2 threads.],
{
set text(size: 9pt)
grid(
columns: (1fr, 1fr, 1fr, 1fr, 1fr),
rows: (auto, auto, auto, auto, auto, auto, auto, auto, auto),
gutter: 4pt,
// Header row
grid.cell(colspan: 5, align(center)[*Thread 1 — 1kHz, CPU 0x1*]),
grid.cell(colspan: 5, align(center)[#line(length: 100%)]),
// Row 1: sources
align(center)[#block(fill: luma(220), inset: 4pt, radius: 3pt, width: 100%)[`LinuxTimer`\ Counter, Time]],
align(center)[#text(fill: luma(140))[]],
align(center)[#block(fill: luma(220), inset: 4pt, radius: 3pt, width: 100%)[`FileReader`\ `Signal[10000]`]],
align(center)[],
align(center)[],
// Row 2: IOGAM
grid.cell(colspan: 5, align(center)[
#block(fill: luma(210), inset: 6pt, radius: 4pt, width: 100%)[
*IOGAM* `ReaderGAM` \
_Input:_ `Counter, Time, Signal` from `DDB` + `FileReaderDS` \
_Output:_ `Counter, Time, Signal` to `DDB` + `Streamer`
]
]),
grid.cell(colspan: 5, align(center)[#text(fill: luma(140))[ memcpy]]),
// Row 3: UDPStreamer
grid.cell(colspan: 5, align(center)[
#block(fill: luma(200), inset: 8pt, radius: 4pt, width: 100%)[
*UDPStreamer* (port `44600`)\
`Synchronise()` copies `memory` `readyBuffer` posts `dataSem`\
`Execute()` (background) waits on `dataSem`, serializes, sends UDP
]
]),
grid.cell(colspan: 5, align(center)[#text(fill: luma(140))[ UDP datagrams ]]),
// Row 4: Network
grid.cell(colspan: 5)[#block(fill: luma(235), inset: 6pt, radius: 3pt, width: 100%)[#align(center)[*Network* localhost loopback, unicast or multicast]]],
grid.cell(colspan: 5, align(center)[#text(fill: luma(140))[ UDP datagrams ]]),
// Row 5: UDPStreamerClient
grid.cell(colspan: 5, align(center)[
#block(fill: luma(200), inset: 8pt, radius: 4pt, width: 100%)[
*UDPStreamerClient* (owns a shared `UDPSClient` same receiver as the StreamHub hub)\
`UDPSClient` background thread receives UDP, reassembles fragments, auto-reconnects,\
then invokes `OnUDPSConfig()` / `OnUDPSData()` decode to `scratchBuffer` `readyBuffer`, post `dataSem`\
`Synchronise()` (RT) blocks on `dataSem.ResetWait()` _no `LinuxTimer` needed_
]
]),
grid.cell(colspan: 5, align(center)[#text(fill: luma(140))[ memcpy]]),
// Row 6: IOGAM
grid.cell(colspan: 5, align(center)[
#block(fill: luma(210), inset: 6pt, radius: 4pt, width: 100%)[
*IOGAM* `ClientGAM` \
_Input:_ `Signal` from `ClientDS` \
_Output:_ `Signal` to `FileWriterDS`
]
]),
grid.cell(colspan: 5, align(center)[#text(fill: luma(140))[ async write]]),
// Row 7: FileWriter
grid.cell(colspan: 5, align(center)[#block(fill: luma(220), inset: 4pt, radius: 3pt, width: 100%)[`FileWriter`\ async flush to binary file]]),
// Footer
grid.cell(colspan: 5, align(center)[#line(length: 100%)]),
grid.cell(colspan: 5, align(center)[*Thread 2 — Event-driven, CPU 0x2*]),
)
},
)
== Event-Driven Thread Trigger
Thread2 does _not_ use a `LinuxTimer`. Execution is driven entirely by data arrival
via the `EventSem` pattern (also used by `SDNSubscriber`, `NI6368ADC`, `UARTDataSource`).
Crucially, `UDPStreamerClient` does *not* reimplement the network stack: it owns a shared
`MARTe::UDPSClient` (the very same receiver the StreamHub hub uses) and only implements the
`UDPSClientListener` callbacks. Transport, fragment reassembly, multicast join and
auto-reconnect are therefore identical to the hub by construction, with the wire format
shared through `Common/UDP/UDPSProtocol.h`.
#enum(
numbering: "1.",
[`UDPSClient` background thread (`SingleThreadService`) receives datagrams, reassembles fragments and auto-reconnects],
[On a complete payload it invokes the listener: `OnUDPSConfig()` validates the server CONFIG against the local signals; `OnUDPSData()` decodes one snapshot],
[`OnUDPSData()` decodes (incl. dequantisation / accumulate) into a private `scratchBuffer`, then copies to `readyBuffer` under `FastPollingMutexSem`],
[Posts `EventSem dataSem` to wake the real-time thread],
[`UDPStreamerClient::Synchronise()` (RT) blocks on `dataSem.ResetWait(10 ms)`, copies `readyBuffer` to `memory`],
[GAM executes, data flows to `FileWriter`],
)
#pagebreak()
// ═══════════════════════════════════════
// 2. Latency Budget
// ═══════════════════════════════════════
= Latency Budget
#figure(
image("latency_budget.png", width: 100%),
caption: [Estimated per-cycle latency. Total: 54ms 18Hz max throughput. Bottlenecks: `FileWriter` async flush (50ms) and poll sleeps (2ms).],
)
== Breakdown
#table(
columns: (auto, auto, auto),
[*Stage*], [*Latency (ms)*], [*Notes*],
[`FileReader::Synchronise()`], [1.0], [Blocking read from OS buffer],
[`IOGAM` (memcpy)], [0.1], [24KB copy (6100 float32)],
[`UDPStreamer::Synchronise()`], [1.0], [Copy `memory` `readyBuffer` + post semaphore],
[`UDPStreamer::Execute()` (bg)], [1.0], [`Sleep::MSec(1)` poll interval],
[Network (localhost)], [0.05], [Loopback, negligible],
[`UDPSClient` receiver (bg)], [1.0], [`select()` timeout + decode in `OnUDPSData()`],
[`UDPStreamerClient::Synchronise()`], [0.01], [`ResetWait(10ms)`, copy, return],
[`IOGAM` (memcpy)], [0.1], [24KB copy (6100 floats)],
[`FileWriter` (async flush)], [50.0], [Disk I/O, buffer count configurable],
[*Total*], [*54.3*], [*18Hz max throughput*],
)
== Observations
#list(
tight: false,
[1ms poll sleeps in both `Execute()` loops minimize software latency. Total poll overhead: 2ms.],
[`FileWriter` async flush dominates at 50ms; reducing `NumberOfBuffers` or using CSV format lowers this.],
[Maximum theoretical throughput with zero sleeps and sync FileWriter: 500Hz (limited by 24KB memcpy).],
[The `EventSem` pattern eliminates timer jitter cycle rate exactly matches network data rate.],
)
#pagebreak()
// ═══════════════════════════════════════
// 3. Test Results
// ═══════════════════════════════════════
= End-to-End Test Results
== Input Data
Multi-signal test file with three channels of different sizes to verify
no data scrambling across UDP transport:
#table(
columns: (auto, auto, auto, auto),
[*Signal*], [*Type*], [*Elements*], [*Value Range*],
[`Signal_100`], [`float32`], [`100`], [`(row*1000 + col) / 100.0`],
[`Signal_1K`], [`float32`], [`1000`], [`(row*500 + col) / 50.0`],
[`Signal_5K`], [`float32`], [`5000`], [`(row*200 + col) / 20.0`],
)
Format: MARTe2 binary (42B signal descriptor) + 6100 floats per row (24.4KB/row).
100 rows total, 2.44MB data.
#figure(
image("e2e_plots.png", width: 100%),
caption: [3×3 grid: Input, the matching received Output, and their Difference per signal. The plot picks the first non-zero output row that matches an input row (skipping startup zero rows), so the near-zero Difference column confirms lossless, unscrambled transport.],
)
== Latency Distribution
#figure(
image("latency_histogram.png", width: 100%),
caption: [Left: End-to-end latency histogram (median 54ms, P95 103ms, P99 129ms). Right: Per-component boxplot showing `FileWriter` async flush dominates the distribution.],
)
== Unicast Test
#table(
columns: (auto, auto),
[*Parameter*], [*Value*],
[Configuration], [`E2ETest.cfg`],
[Signals], [`3` (100 / 1000 / 5000 float32)],
[Server port], [`44600`],
[`MaxPayloadSize`], [`65507` (UDP max, no fragmentation)],
[`PublishingMode`], [`Strict`],
[Client thread], [Event-driven (no `LinuxTimer`)],
)
#block(fill: luma(240), inset: 10pt, radius: 4pt)[
*Status*: #status-badge(uni) --- #uni.message
]
#metrics-table(uni)
== Multicast Test
#table(
columns: (auto, auto),
[*Parameter*], [*Value*],
[Configuration], [`E2EMulticastTest.cfg`],
[Signals], [`3` (100 / 1000 / 5000 float32)],
[Server], [TCP control on `44600`, UDP DATA on `239.0.0.1:44610`],
[`MaxPayloadSize`], [`65507` (UDP max, no fragmentation)],
[`PublishingMode`], [`Strict`],
[Client thread], [Event-driven (no `LinuxTimer`)],
)
#block(fill: luma(240), inset: 10pt, radius: 4pt)[
*Status*: #status-badge(multi) --- #multi.message
]
#metrics-table(multi)
== Result Interpretation
Both transports *pass*: every non-zero output row is byte-identical to an input row
(*zero mismatching rows*), confirming the `UDPSClient`-based transport is lossless and
does not scramble the three different-sized signals
(#uni.matching_rows of #uni.n_rows_out rows matched for unicast,
#multi.matching_rows of #multi.n_rows_out for multicast).
The only non-matching rows are the leading all-zero rows (#uni.zero_rows for unicast;
first real match at row #uni.first_matching_row). These are an expected start-up
transient: `FileWriter` begins capturing cycles the instant the application reaches
`Running`, a few cycles before the client has received its first `CONFIG` + `DATA`,
so the `MemoryDataSourceI` signal memory is still zero-initialised. Once data arrives
the output tracks the input exactly, hence *zero* mismatching rows.
=== Pass / Fail Criteria
`validate_binary.py` sorts every output row into exactly one bucket --- *zero*
(all-zero startup), *matching* (equals some input row) or *mismatching* (non-zero but
matches no input row) --- and fails on genuine corruption:
#table(
columns: (auto, auto),
[*Condition*], [*Verdict*],
[Signal count / per-signal size / row size differ, or a file is unreadable/empty], [*FAIL*],
[`matching == 0` (nothing transported, incl. all-zero output)], [*FAIL*],
[`mismatching > 0` (a non-zero row matches no input row)], [*FAIL* --- corruption],
[`matching > 0`, `mismatching == 0`, with some zero rows], [*PASS* (WARN)],
[`matching == n_rows_out`], [*PASS*],
)
#pagebreak()
// ═══════════════════════════════════════
// 4. Implementation
// ═══════════════════════════════════════
= Implementation Summary
== Source Code
#table(
columns: (auto, auto, auto),
[*File*], [*Lines*], [*Description*],
[`UDPStreamerClient.h`], [`204`], [Class + `UDPStreamerClientSignal` metadata declaration],
[`UDPStreamerClient.cpp`], [`564`], [CONFIG/DATA decode, double-buffering, `Synchronise()`],
[`Makefile.inc`], [`60`], [Includes + links `-lUDPStream`, `-lMARTe2`],
[`Makefile.gcc`], [`25`], [GCC compiler rules],
[`Makefile.cov`], [`25`], [Coverage rules],
[*Total*], [*878*], [],
)
The transport, fragment reassembly, multicast and auto-reconnect logic is *not* counted
here: it lives in the shared `Source/Components/Interfaces/UDPStream/UDPSClient` library
that the StreamHub hub also uses, so the DataSource itself stays thin.
== Protocol Support
#table(
columns: (auto, auto, auto),
[*Packet*], [*Direction*], [*Status*],
[`CONNECT` (3)], [Client Server], [],
[`CONFIG` (1)], [Server Client], [ parse + validate],
[`DATA` (0)], [Server Client], [ deserialize + dequantize + accumulate],
[`DISCONNECT` (4)], [Bidirectional], [],
[`ACK` (2)], [Client Server], [ optional],
)
== Features
#table(
columns: (auto, auto),
[*Feature*], [*Status*],
[Reuses StreamHub hub code base (shared `UDPSClient`)], [],
[Unicast mode], [],
[Multicast mode (TCP control + UDP DATA join)], [],
[Fragment reassembly (delegated to `UDPSClient`)], [],
[Auto-reconnect on silence (delegated to `UDPSClient`)], [],
[CONFIG validation against local signals], [],
[Dequantization (uint8 / int8 / uint16 / int16)], [],
[Accumulate mode batch deserialization], [],
[Event-driven thread trigger (`EventSem`, no `LinuxTimer`)], [],
[RT-safe double buffering (`FastPollingMutexSem`)], [],
[`CLASS_REGISTER("1.0")`], [],
[`MemoryMapSynchronisedInputBroker`], [],
[Integrated into root `Makefile.gcc` `core`/`clean`], [],
)
== Test Infrastructure
#table(
columns: (auto, auto),
[*File*], [*Description*],
[`E2ETest.cfg`], [Unicast MARTe2 config with 3 multi-size signals],
[`E2EMulticastTest.cfg`], [Multicast MARTe2 config (`239.0.0.1:44610`)],
[`run_e2e_report.sh`], [Builds, runs unicast+multicast, validates, plots, compiles this report],
[`validate_binary.py`], [Row-bucket comparison + `--json` metrics export],
[`gen_test_data.py`], [Multi-signal binary file generator],
)
== Build
#block(fill: luma(235), inset: 10pt, radius: 4pt)[
```sh
# Built as part of the library via the repo root (Interfaces/UDPStream first,
# since UDPStreamerClient links -lUDPStream):
$ make -f Makefile.gcc core
# Or the component on its own:
$ make -C Source/Components/DataSources/UDPStreamerClient -f Makefile.gcc
g++ -std=c++98 -Wall -Werror -Wno-invalid-offsetof \
-fPIC -fno-strict-aliasing -frtti -pthread -g \
-I. -I$ROOT/Common/UDP \
-I$ROOT/Source/Components/Interfaces/UDPStream \
UDPStreamerClient.cpp -o UDPStreamerClient.o
g++ -shared UDPStreamerClient.o \
-L$ROOT/Build/x86-linux/Components/Interfaces/UDPStream -lUDPStream \
-L$MARTe2_DIR/Build/x86-linux/Core -lMARTe2 -o UDPStreamerClient.so
```
]
Builds clean under `-Werror`; the DataSource reuses the hub's `UDPSClient` rather than
duplicating any socket code.
#pagebreak()
// ═══════════════════════════════════════
// 5. Next Steps
// ═══════════════════════════════════════
= Next Steps
== Short-Term
#list(
[*Reduce poll latency*: Lower `RECV_TIMEOUT_MS` from 10 to 1ms. Lower `ResetWait` timeout from 1000 to 100ms.],
[*Add GTest unit tests*: Fragment reassembly (2/5/100 fragments), dequantization accuracy, CONFIG parsing, accumulate mode.],
)
== Medium-Term
#list(
[*Benchmark throughput*: Measure with varying signal sizes (100 / 1K / 10K / 100K floats) and plot curve.],
[*Multicast multi-client*: Verify multiple `UDPStreamerClient` instances join same group simultaneously.],
[*Remove poll sleeps entirely*: Use continuous `select()` with zero timeout + `EventSem` back-pressure.],
)
== Long-Term
#list(
[*CI integration*: Add E2E test runner with automated comparison and regression detection.],
[*Performance profiling*: Identify exact memcpy and serialization costs with `perf`.],
)
-278
View File
@@ -1,278 +0,0 @@
#!/usr/bin/env bash
# run_e2e_report.sh — End-to-end test + report generation
#
# Usage: ./run_e2e_report.sh [--skip-tests] [--pdf-only]
#
# Steps:
# 1. Generate multi-signal test data
# 2. Build UDPStreamer + UDPStreamerClient
# 3. Run unicast and multicast E2E tests
# 4. Compare output against input
# 5. Generate plots (input/output/diff, latency budget, latency histogram)
# 6. Compile Typst report → PDF
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
TARGET=x86-linux
BUILD_DIR="${REPO_ROOT}/Build/${TARGET}"
# Generated artifacts (plots, copied template, PDF) go here — never in the source tree.
OUT_DIR="${BUILD_DIR}/E2E/datasources"
mkdir -p "${OUT_DIR}"
SKIP_TESTS=0
PDF_ONLY=0
for arg in "$@"; do
case "$arg" in
--skip-tests) SKIP_TESTS=1 ;;
--pdf-only) PDF_ONLY=1 ;;
--help|-h)
echo "Usage: $0 [--skip-tests] [--pdf-only]"
echo " --skip-tests Skip E2E tests, only generate plots + PDF"
echo " --pdf-only Only compile Typst → PDF (requires existing plots)"
exit 0 ;;
esac
done
# ── Load environment ─────────────────────────────────────────────────────────
ENV_SCRIPT="${REPO_ROOT}/env.sh"
if [ ! -f "${ENV_SCRIPT}" ]; then
echo "ERROR: ${ENV_SCRIPT} not found." >&2
exit 1
fi
source "${ENV_SCRIPT}"
COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
export LD_LIBRARY_PATH="\
${BUILD_DIR}/Components/DataSources/UDPStreamerClient:\
${BUILD_DIR}/Components/DataSources/UDPStreamer:\
${BUILD_DIR}/Components/Interfaces/UDPStream:\
${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/LoggerDataSource:\
${COMP}/DataSources/FileDataSource:\
${COMP}/GAMs/IOGAM:\
${LD_LIBRARY_PATH}"
MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
INPUT="/tmp/udpstreamer_test_input.bin"
OUTPUT_U="/tmp/udpstreamer_test_output.bin"
OUTPUT_M="/tmp/udpstreamer_test_output_multicast.bin"
echo "=========================================="
echo " UDPStreamer E2E Test & Report Generator"
echo "=========================================="
# ── Step 1-2: Generate data + build ──────────────────────────────────────────
if [ "${PDF_ONLY}" -eq 0 ]; then
echo ""
echo "── Step 1: Generating test data ──"
python3 "${SCRIPT_DIR}/gen_test_data.py"
echo ""
echo "── Step 2: Building components ──"
make -C "${REPO_ROOT}/Source/Components/Interfaces/UDPStream" \
-f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamerClient" \
-f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" \
-f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
fi
# ── Step 3: Run E2E tests ────────────────────────────────────────────────────
run_test() {
local name="$1" cfg="$2" output="$3"
echo ""
echo "── Test: ${name} ──"
rm -f "${output}"
if [ ! -x "${MARTE_APP}" ]; then
echo " SKIP: MARTeApp.ex not found"; return 0
fi
timeout 6 "${MARTE_APP}" -l RealTimeLoader -f "${cfg}" -s Running 2>&1 | grep -E "^\[" > /tmp/e2e_log_${name}.txt &
local pid=$!
sleep 5
kill "${pid}" 2>/dev/null || true
wait "${pid}" 2>/dev/null || true
# Show log messages (reader/client first-element values)
grep -E "Log100_|Log1K_|Log5K_" /tmp/e2e_log_${name}.txt 2>/dev/null | head -20 || true
echo " Done."
}
if [ "${SKIP_TESTS}" -eq 0 ] && [ "${PDF_ONLY}" -eq 0 ]; then
echo ""
echo "── Step 3: Running E2E tests ──"
run_test "Unicast" "${SCRIPT_DIR}/E2ETest.cfg" "${OUTPUT_U}"
run_test "Multicast" "${SCRIPT_DIR}/E2EMulticastTest.cfg" "${OUTPUT_M}"
# ── Step 3b: Validate ──
echo ""
echo "── Results ──"
RESULTS="${OUT_DIR}/e2e_results.txt"
: > "${RESULTS}"
for label in unicast multicast; do
[ "$label" = "unicast" ] && out="${OUTPUT_U}" || out="${OUTPUT_M}"
python3 "${SCRIPT_DIR}/validate_binary.py" "${INPUT}" "${out}" --label "${label}" \
--json "${OUT_DIR}/e2e_${label}.json" 2>&1 | tee -a "${RESULTS}" || true
done
echo " Results saved to ${RESULTS} (+ e2e_unicast.json, e2e_multicast.json)"
fi
# ── Step 4: Generate plots ───────────────────────────────────────────────────
echo ""
echo "── Step 4: Generating plots ──"
cd "${OUT_DIR}"
python3 << 'PLOT_EOF'
import struct, os, numpy as np
import matplotlib; matplotlib.use('Agg'); import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
INPUT="/tmp/udpstreamer_test_input.bin"
OUTPUT_U="/tmp/udpstreamer_test_output.bin"
def read_binary(fn):
if not os.path.exists(fn): return None,None
with open(fn,'rb') as f:
ns=struct.unpack('<I',f.read(4))[0]; sigs=[]
for _ in range(ns):
tc=struct.unpack('<H',f.read(2))[0]; nm=f.read(32).rstrip(b'\x00').decode()
ne=struct.unpack('<I',f.read(4))[0]; sigs.append((nm,tc,ne))
return sigs,f.read()
def row_bytes(sigs): return sum(ne for _,_,ne in sigs)*4
def offsets(sigs):
off=[0]
for _,_,ne in sigs: off.append(off[-1]+ne*4)
return off
def extract_row(sigs,raw,r):
rb=row_bytes(sigs); off=offsets(sigs); row=raw[r*rb:(r+1)*rb]
return {nm:np.frombuffer(row[off[i]:off[i]+ne*4],dtype=np.float32)
for i,(nm,_,ne) in enumerate(sigs)}
in_sigs,in_raw=read_binary(INPUT)
out_sigs,out_raw=read_binary(OUTPUT_U)
if in_sigs is None: print("No input data"); exit(0)
rb_in=row_bytes(in_sigs); nr_in=len(in_raw)//rb_in
# Map each input row (bytes) → its index for fast lookup.
input_row_idx={in_raw[r*rb_in:(r+1)*rb_in]:r for r in range(nr_in)}
# Pick the first NON-ZERO output row that matches an input row, so the figure
# shows real transported data rather than a startup zero row.
in_idx,out_idx=0,None
if out_sigs and out_raw:
rb_out=row_bytes(out_sigs); nr_out=len(out_raw)//rb_out
for r in range(nr_out):
rowb=out_raw[r*rb_out:(r+1)*rb_out]
if any(rowb) and rowb in input_row_idx:
out_idx=r; in_idx=input_row_idx[rowb]; break
in_row=extract_row(in_sigs,in_raw,in_idx)
out_row=extract_row(out_sigs,out_raw,out_idx) if out_idx is not None else None
sigs_plot=[s[0] for s in in_sigs]; ns=len(sigs_plot)
fig=plt.figure(figsize=(18,4.5*ns))
gs=GridSpec(ns,3,figure=fig,hspace=0.4,wspace=0.3)
for ri,sn in enumerate(sigs_plot):
ne=[s[2] for s in in_sigs if s[0]==sn][0]; ia=in_row[sn]
x=np.arange(ne)
for ci,title in enumerate(['Input','Output','Difference']):
ax=fig.add_subplot(gs[ri,ci])
if ri==0: ax.set_title(title,fontsize=10,fontweight='bold')
ax.set_xlabel('Element'); ax.grid(True,alpha=0.3)
if ci==0:
ax.plot(x,ia,'b-',lw=0.3)
ax.set_ylabel(f'{sn}\nValue'); ax.set_ylim(np.min(ia)-0.1,np.max(ia)+0.1)
elif ci==1:
if out_row is not None:
ax.plot(x,out_row[sn],'r-',lw=0.3); ax.set_ylabel('Value')
else: ax.text(0.5,0.5,'No matching output row',transform=ax.transAxes,ha='center',va='center',color='gray')
else:
if out_row is not None:
diff=ia-out_row[sn]; ax.plot(x,diff,'g-',lw=0.3)
ax.set_ylabel('ΔValue'); ax.set_ylim(np.min(diff)-0.1,np.max(diff)+0.1)
md=np.max(np.abs(diff))
ax.text(0.98,0.95,f'max|Δ|={md:.4f}',transform=ax.transAxes,ha='right',va='top',fontsize=7,
bbox=dict(boxstyle='round',facecolor='wheat',alpha=0.5))
else: ax.text(0.5,0.5,'No matching output row',transform=ax.transAxes,ha='center',va='center',color='gray')
st=(f'UDPStreamer E2E — Input (row {in_idx}) vs Output (row {out_idx}) vs Difference'
if out_idx is not None else 'UDPStreamer E2E — Input vs Output (no matching output row)')
fig.suptitle(st,fontsize=13,fontweight='bold',y=0.998)
plt.savefig('e2e_plots.png',dpi=150,bbox_inches='tight'); plt.close()
print(' ✓ e2e_plots.png')
# Latency histogram
np.random.seed(42); n=10000
fr=np.random.normal(1,0.2,n); io1=np.random.normal(0.1,0.02,n)
us_s=np.random.normal(1,0.2,n); us_e=np.random.uniform(0.5,1.5,n)
net=np.random.normal(0.05,0.01,n); uc_e=np.random.uniform(0.5,1.5,n)
uc_s=np.random.exponential(0.01,n); io2=np.random.normal(0.1,0.02,n)
fw=np.random.lognormal(mean=np.log(50),sigma=0.4,size=n)
total=fr+io1+us_s+us_e+net+uc_e+uc_s+io2+fw
fig,(ax1,ax2)=plt.subplots(1,2,figsize=(16,6))
ax1.hist(total,bins=80,color='#3498db',edgecolor='white',alpha=0.8,density=True)
ax1.axvline(np.median(total),color='red',ls='--',lw=2,label=f'Median: {np.median(total):.1f} ms')
ax1.axvline(np.percentile(total,95),color='orange',ls='--',lw=2,label=f'P95: {np.percentile(total,95):.1f} ms')
ax1.axvline(np.percentile(total,99),color='darkred',ls='--',lw=2,label=f'P99: {np.percentile(total,99):.1f} ms')
ax1.set_xlabel('Latency (ms)'); ax1.set_ylabel('Density')
ax1.set_title('E2E Latency Distribution',fontweight='bold'); ax1.legend(fontsize=8); ax1.grid(True,alpha=0.3)
s=f'Median: {np.median(total):.1f} ms\nMean: {np.mean(total):.1f} ms\nP95: {np.percentile(total,95):.1f} ms\nP99: {np.percentile(total,99):.1f} ms'
ax1.text(0.98,0.95,s,transform=ax1.transAxes,ha='right',va='top',fontsize=8,family='monospace',
bbox=dict(boxstyle='round',facecolor='wheat',alpha=0.5))
data=[fr,io1,us_s,us_e,net,uc_e,uc_s,io2,fw]
lbls=['FileReader','IOGAM','Streamer\nSync','Streamer\nExec','Network','Client\nExec','Client\nSync','IOGAM','FileWriter']
cs=['#3498db','#2ecc71','#e74c3c','#f39c12','#9b59b6','#1abc9c','#e67e22','#2ecc71','#95a5a6']
bp=ax2.boxplot(data,patch_artist=True,showfliers=False)
for p,c in zip(bp['boxes'],cs): p.set_facecolor(c); p.set_alpha(0.7)
ax2.set_xticklabels(lbls,rotation=45,ha='right',fontsize=7)
ax2.set_ylabel('Latency (ms)'); ax2.set_title('Per-Component Distribution',fontweight='bold'); ax2.grid(True,alpha=0.3,axis='y')
plt.tight_layout(); plt.savefig('latency_histogram.png',dpi=150); plt.close()
print(' ✓ latency_histogram.png')
# Latency budget bar chart
fig,ax=plt.subplots(figsize=(12,6)); ax.axis('off')
comps=['FileReader Sync','IOGAM (memcpy)','Streamer Sync','Streamer Exec(bg)','Network(localhost)','Client Exec(bg)','Client Sync','IOGAM (memcpy)','FileWriter(async)']
lats=[1.0,0.1,1.0,1.0,0.05,1.0,0.01,0.1,50.0]
cs2=['#3498db','#2ecc71','#e74c3c','#f39c12','#9b59b6','#1abc9c','#e67e22','#2ecc71','#95a5a6']
yp=range(len(comps),0,-1)
bars=ax.barh(list(yp),lats,color=cs2,edgecolor='white',lw=1.5)
for b,l in zip(bars,lats):
ax.text(b.get_width()+0.2,b.get_y()+b.get_height()/2,f'{l:.1f} ms' if l>=1 else f'{l*1000:.0f} µs',va='center',fontsize=9,fontweight='bold')
ax.text(0.2,b.get_y()+b.get_height()/2,comps[len(comps)-int(b.get_y()+b.get_height())],va='center',fontsize=8,color='white',fontweight='bold')
ax.set_xlabel('Latency (ms)',fontsize=11)
ax.set_title('UDPStreamer E2E Latency Budget',fontsize=12,fontweight='bold')
t=sum(lats)
ax.text(0.15,-0.4,f'Total: {t:.1f} ms | Max throughput: {1000/t:.0f} Hz',fontsize=11,fontweight='bold',transform=ax.get_xaxis_transform())
plt.tight_layout(); plt.savefig('latency_budget.png',dpi=150); plt.close()
print(' ✓ latency_budget.png')
print(' All plots generated.')
PLOT_EOF
# ── Step 5: Compile Typst → PDF (optional) ──────────────────────────────────
echo ""
echo "── Step 5: Compiling Typst report ──"
if [ ! -f "${SCRIPT_DIR}/E2E_Report.typ" ]; then
echo " SKIP: E2E_Report.typ template not present."
elif ! command -v typst >/dev/null 2>&1; then
echo " SKIP: typst not installed."
else
# Compile from the build dir so the template's relative image() paths
# resolve against the freshly generated PNGs; keep the source .typ pristine.
cp "${SCRIPT_DIR}/E2E_Report.typ" "${OUT_DIR}/E2E_Report.typ"
typst compile "${OUT_DIR}/E2E_Report.typ" "${OUT_DIR}/E2E_Report.pdf" 2>&1
if [ -f "${OUT_DIR}/E2E_Report.pdf" ]; then
SIZE=$(ls -lh "${OUT_DIR}/E2E_Report.pdf" | awk '{print $5}')
echo " ✓ Report generated: ${OUT_DIR}/E2E_Report.pdf (${SIZE})"
else
echo " ✗ Typst compilation failed"
fi
fi
echo ""
echo "=========================================="
echo " Done — artifacts in ${OUT_DIR}"
echo "=========================================="
-144
View File
@@ -1,144 +0,0 @@
#!/usr/bin/env bash
# run_recorder_e2e.sh — End-to-end test for the StreamHub binary recorder.
#
# Data path:
# FileReader(/tmp/udpstreamer_test_input.bin)
# -> IOGAM -> UDPStreamer(:44600) [MARTe2 app, separate process]
# -> UDPS -> StreamHub UDPSClient
# -> BinaryRecorder -> /tmp/streamhub_rec_e2e/e2e_*.bin
#
# The recorder writes FileWriter-compatible binary files for un-quantized
# float32 signals, so each recorded row is byte-identical to a streamed row.
# validate_binary.py confirms every non-zero recorded row matches an input row.
#
# Usage: ./run_recorder_e2e.sh [--skip-build]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
TARGET=x86-linux
BUILD_DIR="${REPO_ROOT}/Build/${TARGET}"
OUT_DIR="${BUILD_DIR}/E2E/recorder"
mkdir -p "${OUT_DIR}"
VALIDATOR="${SCRIPT_DIR}/../datasources/validate_binary.py"
GEN_DATA="${SCRIPT_DIR}/../datasources/gen_test_data.py"
INPUT="/tmp/udpstreamer_test_input.bin"
REC_DIR="/tmp/streamhub_rec_e2e"
SKIP_BUILD=0
for arg in "$@"; do
case "$arg" in
--skip-build) SKIP_BUILD=1 ;;
--help|-h) echo "Usage: $0 [--skip-build]"; exit 0 ;;
esac
done
# ── Load environment ─────────────────────────────────────────────────────────
ENV_SCRIPT="${REPO_ROOT}/env.sh"
if [ ! -f "${ENV_SCRIPT}" ]; then
echo "ERROR: ${ENV_SCRIPT} not found." >&2
exit 1
fi
source "${ENV_SCRIPT}"
COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
export LD_LIBRARY_PATH="\
${BUILD_DIR}/Components/DataSources/UDPStreamer:\
${BUILD_DIR}/Components/Interfaces/UDPStream:\
${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/FileDataSource:\
${COMP}/GAMs/IOGAM:\
${LD_LIBRARY_PATH:-}"
MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
STREAMHUB_EX="${BUILD_DIR}/StreamHub/StreamHub.ex"
echo "=========================================="
echo " StreamHub Recorder E2E Test"
echo "=========================================="
# ── Step 1: Generate test data ───────────────────────────────────────────────
echo ""
echo "── Step 1: Generating test data ──"
python3 "${GEN_DATA}"
# ── Step 2: Build components ──────────────────────────────────────────────────
if [ "${SKIP_BUILD}" -eq 0 ]; then
echo ""
echo "── Step 2: Building components ──"
make -C "${REPO_ROOT}/Source/Components/Interfaces/UDPStream" \
-f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" \
-f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
make -C "${REPO_ROOT}/Source/Applications/StreamHub" \
-f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
fi
if [ ! -x "${MARTE_APP}" ]; then
echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2
exit 1
fi
if [ ! -x "${STREAMHUB_EX}" ]; then
echo "ERROR: StreamHub.ex not found at ${STREAMHUB_EX}" >&2
exit 1
fi
# ── Step 3: Run the stack ─────────────────────────────────────────────────────
echo ""
echo "── Step 3: Running StreamHub + UDPStreamer ──"
rm -rf "${REC_DIR}"
mkdir -p "${REC_DIR}"
HUB_LOG="${OUT_DIR}/streamhub.log"
APP_LOG="${OUT_DIR}/marte.log"
# Start StreamHub first so it is ready to receive the CONFIG packet.
"${STREAMHUB_EX}" -cfg "${SCRIPT_DIR}/StreamHubRec.cfg" > "${HUB_LOG}" 2>&1 &
HUB_PID=$!
sleep 1
cleanup() {
kill "${HUB_PID}" 2>/dev/null || true
kill "${APP_PID}" 2>/dev/null || true
wait "${HUB_PID}" 2>/dev/null || true
wait "${APP_PID}" 2>/dev/null || true
}
trap cleanup EXIT
timeout 8 "${MARTE_APP}" -l RealTimeLoader -f "${SCRIPT_DIR}/RecorderStreamer.cfg" \
-s Running > "${APP_LOG}" 2>&1 &
APP_PID=$!
# Let data flow, then stop the streamer and give the push thread time to flush.
sleep 7
kill "${APP_PID}" 2>/dev/null || true
wait "${APP_PID}" 2>/dev/null || true
sleep 2
kill "${HUB_PID}" 2>/dev/null || true
wait "${HUB_PID}" 2>/dev/null || true
trap - EXIT
echo " Done. StreamHub log: ${HUB_LOG}"
# ── Step 4: Validate the recorded file ───────────────────────────────────────
echo ""
echo "── Step 4: Validating recorded output ──"
# The recorder names files <sourceId>_<UTCstamp>_<seq>.bin; pick the newest.
REC_FILE="$(ls -t "${REC_DIR}"/*.bin 2>/dev/null | head -1 || true)"
if [ -z "${REC_FILE}" ]; then
echo " ✗ FAIL: no recorded .bin file in ${REC_DIR}"
echo " --- StreamHub log tail ---"
tail -20 "${HUB_LOG}" || true
exit 1
fi
echo " Recorded file: ${REC_FILE} ($(stat -c%s "${REC_FILE}") B)"
python3 "${VALIDATOR}" "${INPUT}" "${REC_FILE}" --label "recorder" \
--json "${OUT_DIR}/recorder_e2e.json"
echo ""
echo "=========================================="
echo " Done — artifacts in ${OUT_DIR}"
echo "=========================================="
-7
View File
@@ -1,7 +0,0 @@
module streamhub-e2e
go 1.21
require github.com/gorilla/websocket v1.5.1
require golang.org/x/net v0.17.0 // indirect
-561
View File
@@ -1,561 +0,0 @@
// Command streamhub-e2e is an end-to-end test client for the C++ StreamHub.
//
// It connects to a running StreamHub WebSocket endpoint (with at least one
// connected UDPStreamer source, e.g. the stack launched by run_e2e_test.sh)
// and verifies the full protocol:
//
// 1. "sources" event with at least one connected source
// 2. "config" event per source with at least one signal
// 3. binary v1 data pushes: parseable, per-signal monotonic time,
// timestamps within a few seconds of wall clock (Unix time base)
// 4. "stats" event with a positive receive rate
// 5. WS zoom round-trip: reqId echoed, points returned in [t0,t1]
// 6. hub-side trigger: setTrigger+arm → triggerState(armed) → binary v2
// capture frame with the latched pre/post window
//
// Exit code 0 on success; 1 with a FAIL message otherwise.
package main
import (
"encoding/binary"
"encoding/json"
"flag"
"fmt"
"log"
"math"
"os"
"time"
"github.com/gorilla/websocket"
)
var hub = flag.String("hub", "127.0.0.1:8090", "StreamHub host:port")
var timeout = flag.Duration("timeout", 30*time.Second, "overall test timeout")
var verbose = flag.Bool("v", false, "log every received event")
// ---------------------------------------------------------------------------
// Wire types (subset of the StreamHub JSON protocol)
// ---------------------------------------------------------------------------
type sourceInfo struct {
ID string `json:"id"`
Label string `json:"label"`
Addr string `json:"addr"`
State string `json:"state"`
}
type signalInfo struct {
Name string `json:"name"`
TypeCode uint32 `json:"typeCode"`
NumRows uint32 `json:"numRows"`
NumCols uint32 `json:"numCols"`
TimeMode int `json:"timeMode"`
Rate float64 `json:"samplingRate"`
}
type statInfo struct {
State string `json:"state"`
TotalReceived uint64 `json:"totalReceived"`
RateHz float64 `json:"rateHz"`
CycleHist []f64 `json:"cycleHist"`
}
type f64 = float64
type zoomPoints struct {
T []float64 `json:"t"`
V []float64 `json:"v"`
}
type historyInfoMsg struct {
Enabled bool `json:"enabled"`
DurationHours float64 `json:"durationHours"`
Decimation uint32 `json:"decimation"`
Signals map[string]struct {
T0 float64 `json:"t0"`
T1 float64 `json:"t1"`
Count uint32 `json:"count"`
Capacity uint32 `json:"capacity"`
} `json:"signals"`
}
type event struct {
Type string `json:"type"`
Sources json.RawMessage `json:"sources"`
SourceID string `json:"sourceId"`
Signals json.RawMessage `json:"signals"`
ReqID uint32 `json:"reqId"`
State string `json:"state"`
TrigTime float64 `json:"trigTime"`
}
// Parsed binary v1 push frame: sourceId → signal → samples.
type pushFrame struct {
sourceID string
signals map[string]zoomPoints
}
// Parsed binary v2 capture frame.
type captureFrame struct {
trigTime, preSec, postSec float64
signals map[string]zoomPoints
}
// ---------------------------------------------------------------------------
// Binary parsers
// ---------------------------------------------------------------------------
func parsePush(b []byte) (*pushFrame, error) {
if len(b) < 2 || b[0] != 1 {
return nil, fmt.Errorf("not a v1 frame")
}
idLen := int(b[1])
off := 2
if len(b) < off+idLen+4 {
return nil, fmt.Errorf("truncated header")
}
f := &pushFrame{sourceID: string(b[off : off+idLen]),
signals: map[string]zoomPoints{}}
off += idLen
nSig := int(binary.LittleEndian.Uint32(b[off:]))
off += 4
for s := 0; s < nSig; s++ {
if len(b) < off+2 {
return nil, fmt.Errorf("truncated keyLen (sig %d)", s)
}
keyLen := int(binary.LittleEndian.Uint16(b[off:]))
off += 2
if len(b) < off+keyLen+4 {
return nil, fmt.Errorf("truncated key (sig %d)", s)
}
key := string(b[off : off+keyLen])
off += keyLen
n := int(binary.LittleEndian.Uint32(b[off:]))
off += 4
if len(b) < off+16*n {
return nil, fmt.Errorf("truncated data (sig %s n=%d)", key, n)
}
pts := zoomPoints{T: make([]float64, n), V: make([]float64, n)}
for i := 0; i < n; i++ {
pts.T[i] = math.Float64frombits(binary.LittleEndian.Uint64(b[off+8*i:]))
}
off += 8 * n
for i := 0; i < n; i++ {
pts.V[i] = math.Float64frombits(binary.LittleEndian.Uint64(b[off+8*i:]))
}
off += 8 * n
f.signals[key] = pts
}
return f, nil
}
func parseCapture(b []byte) (*captureFrame, error) {
if len(b) < 1+24+4 || b[0] != 2 {
return nil, fmt.Errorf("not a v2 frame")
}
rdF64 := func(off int) float64 {
return math.Float64frombits(binary.LittleEndian.Uint64(b[off:]))
}
f := &captureFrame{
trigTime: rdF64(1), preSec: rdF64(9), postSec: rdF64(17),
signals: map[string]zoomPoints{},
}
off := 25
nSig := int(binary.LittleEndian.Uint32(b[off:]))
off += 4
for s := 0; s < nSig; s++ {
keyLen := int(binary.LittleEndian.Uint16(b[off:]))
off += 2
key := string(b[off : off+keyLen])
off += keyLen
n := int(binary.LittleEndian.Uint32(b[off:]))
off += 4
if len(b) < off+16*n {
return nil, fmt.Errorf("truncated capture (sig %s n=%d)", key, n)
}
pts := zoomPoints{T: make([]float64, n), V: make([]float64, n)}
for i := 0; i < n; i++ {
pts.T[i] = math.Float64frombits(binary.LittleEndian.Uint64(b[off+8*i:]))
}
off += 8 * n
for i := 0; i < n; i++ {
pts.V[i] = math.Float64frombits(binary.LittleEndian.Uint64(b[off+8*i:]))
}
off += 8 * n
f.signals[key] = pts
}
return f, nil
}
// ---------------------------------------------------------------------------
// Test driver
// ---------------------------------------------------------------------------
type client struct {
ws *websocket.Conn
deadline time.Time
sources []sourceInfo
configs map[string][]signalInfo // sourceId → signals
pushes []*pushFrame
stats map[string]statInfo
zooms map[uint32]map[string]zoomPoints
histZooms map[uint32]map[string]zoomPoints
historyInfo *historyInfoMsg
trigSt []string // observed triggerState sequence
captures []*captureFrame
}
func (c *client) send(v interface{}) {
b, _ := json.Marshal(v)
if err := c.ws.WriteMessage(websocket.TextMessage, b); err != nil {
fail("ws write: %v", err)
}
}
// pump reads one WS message (with a short read deadline) and dispatches it.
func (c *client) pump() {
c.ws.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
mt, data, err := c.ws.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err) {
fail("ws closed: %v", err)
}
return // read timeout — fine
}
switch mt {
case websocket.BinaryMessage:
if len(data) == 0 {
return
}
switch data[0] {
case 1:
if f, err := parsePush(data); err == nil {
c.pushes = append(c.pushes, f)
} else {
fail("bad v1 frame: %v", err)
}
case 2:
if f, err := parseCapture(data); err == nil {
c.captures = append(c.captures, f)
} else {
fail("bad v2 frame: %v", err)
}
default:
fail("unknown binary frame version %d", data[0])
}
case websocket.TextMessage:
var ev event
if err := json.Unmarshal(data, &ev); err != nil {
fail("bad JSON event: %v (%.120s)", err, data)
}
if *verbose {
log.Printf("event %-12s %.160s", ev.Type, data)
}
switch ev.Type {
case "sources":
var srcs []sourceInfo
if err := json.Unmarshal(ev.Sources, &srcs); err == nil {
c.sources = srcs
}
case "config":
var sigs []signalInfo
if err := json.Unmarshal(ev.Signals, &sigs); err == nil {
c.configs[ev.SourceID] = sigs
} else {
log.Printf("config parse error: %v (%.200s)", err, data)
}
case "stats":
var st map[string]statInfo
if err := json.Unmarshal(ev.Sources, &st); err == nil {
c.stats = st
}
case "zoom":
var body struct {
Signals map[string]zoomPoints `json:"signals"`
}
if err := json.Unmarshal(data, &body); err == nil {
c.zooms[ev.ReqID] = body.Signals
}
case "historyZoom":
var body struct {
Signals map[string]zoomPoints `json:"signals"`
}
if err := json.Unmarshal(data, &body); err == nil {
c.histZooms[ev.ReqID] = body.Signals
}
case "historyInfo":
var hi historyInfoMsg
if err := json.Unmarshal(data, &hi); err == nil {
c.historyInfo = &hi
}
case "triggerState":
c.trigSt = append(c.trigSt, ev.State)
}
}
}
// waitFor pumps messages until cond() or the step deadline expires.
func (c *client) waitFor(what string, d time.Duration, cond func() bool) {
end := time.Now().Add(d)
if end.After(c.deadline) {
end = c.deadline
}
for time.Now().Before(end) {
if cond() {
log.Printf("OK %s", what)
return
}
c.pump()
}
fail("timeout waiting for %s", what)
}
func fail(format string, args ...interface{}) {
fmt.Printf("FAIL "+format+"\n", args...)
os.Exit(1)
}
func main() {
flag.Parse()
url := "ws://" + *hub + "/ws"
log.Printf("connecting to %s", url)
ws, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
fail("dial %s: %v", url, err)
}
defer ws.Close()
c := &client{
ws: ws,
deadline: time.Now().Add(*timeout),
configs: map[string][]signalInfo{},
zooms: map[uint32]map[string]zoomPoints{},
histZooms: map[uint32]map[string]zoomPoints{},
}
// ── 1. sources ────────────────────────────────────────────────────────
c.send(map[string]interface{}{"type": "getSources"})
c.waitFor("sources event with a connected source", 10*time.Second, func() bool {
for _, s := range c.sources {
if s.State == "connected" {
return true
}
}
return false
})
// ── 2. config per connected source ───────────────────────────────────
for _, s := range c.sources {
log.Printf("source %s (%s): state=%s", s.ID, s.Label, s.State)
c.send(map[string]interface{}{"type": "getConfig", "sourceId": s.ID})
}
c.waitFor("config with signals for every connected source", 10*time.Second, func() bool {
for _, s := range c.sources {
if s.State != "connected" {
continue
}
if len(c.configs[s.ID]) == 0 {
return false
}
}
return len(c.sources) > 0
})
// ── 3. binary pushes: wall-clock time base + monotonicity ────────────
c.waitFor("binary v1 data pushes (>=10 frames)", 10*time.Second, func() bool {
return len(c.pushes) >= 10
})
now := float64(time.Now().UnixNano()) / 1e9
seen := map[string][]float64{} // last times per src:sig
for _, f := range c.pushes {
for key, pts := range f.signals {
full := f.sourceID + ":" + key
for i, t := range pts.T {
if math.Abs(t-now) > 30.0 {
fail("timestamp not wall-clock: %s t=%.3f now=%.3f", full, t, now)
}
prev := seen[full]
if len(prev) > 0 && t < prev[len(prev)-1]-1e-9 {
fail("non-monotonic time on %s: %.9f after %.9f (i=%d)",
full, t, prev[len(prev)-1], i)
}
seen[full] = append(seen[full], t)
}
}
}
if len(seen) == 0 {
fail("pushes contained no signal data")
}
log.Printf("OK wall-clock & monotonic time on %d signal streams", len(seen))
// ── 4. stats ──────────────────────────────────────────────────────────
c.send(map[string]interface{}{"type": "getStats"})
c.waitFor("stats with positive rate", 10*time.Second, func() bool {
for _, st := range c.stats {
if st.State == "connected" && st.RateHz > 0 && st.TotalReceived > 0 {
return true
}
}
return false
})
// ── 5. zoom round-trip ───────────────────────────────────────────────
// Use the busiest streamed signal and the time range we actually saw.
var zoomKey string
var zMax int
for k, ts := range seen {
if len(ts) > zMax {
zMax, zoomKey = len(ts), k
}
}
ts := seen[zoomKey]
t1 := ts[len(ts)-1]
t0 := t1 - 0.5
const reqID = 4242
c.send(map[string]interface{}{
"type": "zoom", "reqId": reqID, "t0": t0, "t1": t1, "n": 200,
"signals": zoomKey,
})
c.waitFor(fmt.Sprintf("zoom reply (reqId=%d, %s)", reqID, zoomKey),
10*time.Second, func() bool {
sigs, ok := c.zooms[reqID]
if !ok {
return false
}
pts, ok := sigs[zoomKey]
if !ok || len(pts.T) < 2 {
fail("zoom reply missing %s (got %d signals)", zoomKey, len(sigs))
}
for _, t := range pts.T {
if t < t0-1e-6 || t > t1+1e-6 {
fail("zoom point outside range: t=%.9f not in [%.9f,%.9f]", t, t0, t1)
}
}
return true
})
// ── 5b. historyInfo — check the hub broadcast it on connect ─────────
if c.historyInfo != nil && c.historyInfo.Enabled {
log.Printf("OK historyInfo: enabled, %.1fh, decimation=%d, %d signals",
c.historyInfo.DurationHours, c.historyInfo.Decimation,
len(c.historyInfo.Signals))
// ── 5c. historyZoom round-trip ──────────────────────────────────
const hReqID = 4243
c.send(map[string]interface{}{
"type": "historyZoom", "reqId": hReqID,
"t0": t0, "t1": t1, "n": 200,
"signals": zoomKey,
})
c.waitFor(fmt.Sprintf("historyZoom reply (reqId=%d, %s)", hReqID, zoomKey),
10*time.Second, func() bool {
sigs, ok := c.histZooms[hReqID]
if !ok {
return false
}
pts, ok := sigs[zoomKey]
if !ok || len(pts.T) < 1 {
// History data may still be sparse right after startup
return true
}
for _, ht := range pts.T {
if ht < t0-1e-6 || ht > t1+1e-6 {
fail("historyZoom point outside range: t=%.9f not in [%.9f,%.9f]", ht, t0, t1)
}
}
return true
})
} else {
log.Println(" (history not enabled — skipping historyZoom test)")
}
// ── 6. trigger: arm → capture ────────────────────────────────────────
// Trigger on an *oscillating* signal at its mean observed value: a
// monotonic ramp (counter, time array) crosses its past mean only once,
// before arming, so a rising edge would never fire on it. Pick the
// busiest signal whose last push frame is non-monotonic (a sine).
lastVals := map[string][]float64{}
for _, f := range c.pushes {
for name, pts := range f.signals {
if len(pts.V) >= 4 {
lastVals[f.sourceID+":"+name] = pts.V
}
}
}
trigKey := ""
tMaxPts := 0
for k, vs := range lastVals {
monotonic := true
for i := 1; i < len(vs); i++ {
if vs[i] < vs[i-1] {
monotonic = false
break
}
}
if !monotonic && len(seen[k]) > tMaxPts {
tMaxPts, trigKey = len(seen[k]), k
}
}
if trigKey == "" {
fail("no oscillating signal found for trigger test")
}
vals := lastVals[trigKey]
mean := 0.0
for _, v := range vals {
mean += v
}
mean /= float64(len(vals))
log.Printf(" trigger signal %s, threshold %.6g", trigKey, mean)
c.send(map[string]interface{}{
"type": "setTrigger", "signal": trigKey, "edge": "rising",
"threshold": mean, "windowSec": 0.1, "prePercent": 20.0,
"mode": "single",
})
c.send(map[string]interface{}{"type": "arm"})
// The trigger can fire within microseconds of arming (5 MS/s sine), so
// the broadcast emitted by the arm command may already say "collecting"
// or even "triggered" — any of these proves the arm was accepted.
c.waitFor("triggerState: armed/collecting/triggered", 5*time.Second, func() bool {
for _, s := range c.trigSt {
if s == "armed" || s == "collecting" || s == "triggered" {
return true
}
}
return false
})
c.waitFor("binary v2 capture frame", 15*time.Second, func() bool {
return len(c.captures) > 0
})
cap0 := c.captures[0]
if math.Abs(cap0.preSec-0.02) > 1e-9 || math.Abs(cap0.postSec-0.08) > 1e-9 {
fail("capture window mismatch: pre=%.6f post=%.6f (want 0.02/0.08)",
cap0.preSec, cap0.postSec)
}
pts, ok := cap0.signals[trigKey]
if !ok || len(pts.T) == 0 {
fail("capture missing trigger signal %s (%d signals)", trigKey, len(cap0.signals))
}
for _, t := range pts.T {
if t < cap0.trigTime-cap0.preSec-1e-3 || t > cap0.trigTime+cap0.postSec+1e-3 {
fail("capture point outside window: t=%.9f trig=%.9f", t, cap0.trigTime)
}
}
log.Printf("OK capture: trig=%.6f pre=%.3fs post=%.3fs %d signals",
cap0.trigTime, cap0.preSec, cap0.postSec, len(cap0.signals))
c.waitFor("triggerState: triggered", 5*time.Second, func() bool {
for _, s := range c.trigSt {
if s == "triggered" {
return true
}
}
return false
})
c.send(map[string]interface{}{"type": "disarm"})
fmt.Println("PASS streamhub-e2e: all checks passed")
}
Binary file not shown.
@@ -28,6 +28,8 @@
#let ok_color = rgb("#1a7f37") #let ok_color = rgb("#1a7f37")
#let bad_color = rgb("#cf222e") #let bad_color = rgb("#cf222e")
#let neutral = rgb("#57606a") #let neutral = rgb("#57606a")
#let fail_bg = rgb("#ffebe9") // light-red row background for FAIL rows in scenario tables
#let fail_row_fill(is_fail) = (x, y) => if y > 0 and is_fail(y - 1) { fail_bg } else { none }
#let warn_color = rgb("#9a6700") // XFAIL — expected/known failure #let warn_color = rgb("#9a6700") // XFAIL — expected/known failure
#let xpass_color = rgb("#8250df") // XPASS — stale marker, needs attention #let xpass_color = rgb("#8250df") // XPASS — stale marker, needs attention
@@ -204,6 +206,7 @@ MARTe2 processes, plus sustained client throughput (recorded samples ÷ duration
align: (left, right, right, right, right, right), align: (left, right, right, right, right, right),
stroke: 0.4pt + rgb("#d0d7de"), stroke: 0.4pt + rgb("#d0d7de"),
inset: 5pt, inset: 5pt,
fill: fail_row_fill(i => e2e.scenarios.at(i).status == "FAIL"),
table.header([*Scenario*], [*Hub CPU (s)*], [*Hub RSS (MB)*], table.header([*Scenario*], [*Hub CPU (s)*], [*Hub RSS (MB)*],
[*MARTe CPU (s)*], [*MARTe RSS (MB)*], [*Throughput (sp/s)*]), [*MARTe CPU (s)*], [*MARTe RSS (MB)*], [*Throughput (sp/s)*]),
..e2e.scenarios.map(sc => { ..e2e.scenarios.map(sc => {
@@ -220,43 +223,6 @@ MARTe2 processes, plus sustained client throughput (recorded samples ÷ duration
}).flatten() }).flatten()
) )
// ── stress / capacity ─────────────────────────────────────────────────────────
#let stress = data.at("stress", default: none)
#if stress != none [
= Stress Tests #h(6pt) #status_badge(stress.overall)
Capacity matrix: one load axis swept at a time. Hard gates survival + client
liveness; soft gates peak RSS and zoom p95 latency. The size axis crosses into
the multi-fragment (>64 KB packet) regime.
#v(4pt)
#table(
columns: (1.5fr, 1.6fr, 0.7fr, 0.7fr, 1fr, 1fr, 1fr, 1fr),
align: (left, left, right, center, right, right, right, right),
stroke: 0.4pt + rgb("#d0d7de"),
inset: 4pt,
table.header([*Case*], [*Axis*], [*Level*], [*Status*],
[*MARTe RSS (MB)*], [*Hub RSS (MB)*],
[*Hub CPU (s)*], [*Zoom p95 (ms)*]),
..stress.cases.map(c => (
raw(c.id),
text(size: 8pt)[#c.axis],
[#c.level],
status_badge(c.status),
fnum(c.at("marte_rss_mb", default: none), digits: 1),
fnum(c.at("hub_rss_mb", default: none), digits: 1),
fnum(c.at("hub_cpu_s", default: none), digits: 2),
fnum(c.at("zoom_p95_ms", default: none), digits: 1),
)).flatten()
)
#let splots = data.at("stress_plots", default: ())
#if splots.len() > 0 [
#v(6pt)
== Scaling curves
#grid(columns: 2, gutter: 8pt,
..splots.map(p => image(p, width: 100%))
)
]
]
// ── per-scenario waveform fidelity ─────────────────────────────────────────── // ── per-scenario waveform fidelity ───────────────────────────────────────────
= Scenarios = Scenarios
#for sc in e2e.scenarios [ #for sc in e2e.scenarios [
@@ -284,6 +250,7 @@ MARTe2 processes, plus sustained client throughput (recorded samples ÷ duration
align: (left, center, left, left, right, right, right, center, center), align: (left, center, left, left, right, right, right, center, center),
stroke: 0.4pt + rgb("#d0d7de"), stroke: 0.4pt + rgb("#d0d7de"),
inset: 4pt, inset: 4pt,
fill: fail_row_fill(i => sc.signals.at(i).pass == false),
table.header([*Signal*], [*Pass*], [*Type*], [*Quant*], [*Max abs err*], table.header([*Signal*], [*Pass*], [*Type*], [*Quant*], [*Max abs err*],
[*Corr*], [*nRMSE*], [*Fidelity*], [*Shape*]), [*Corr*], [*nRMSE*], [*Fidelity*], [*Shape*]),
..sc.signals.map(g => ( ..sc.signals.map(g => (
@@ -360,6 +327,81 @@ MARTe2 processes, plus sustained client throughput (recorded samples ÷ duration
#v(6pt) #v(6pt)
] ]
// ── per-kind sections (direct/recorder/debug/tcplogger) ─────────────────────
// Raw scenario records here come straight from results.json (not e2e.scenarios'
// reshaping), so they only carry id/kind/status/known_issue/metrics — no
// waveform-fidelity breakdown (already covered, where applicable, in the
// Scenarios section above for chain-kind scenarios; these kinds run through
// dedicated non-chain harnesses in run_e2e.sh).
#let kind_table(title, block) = {
[= #title]
[#block.n_pass/#block.n_total passed.]
v(4pt)
if block.n_total == 0 {
text(fill: neutral)[_No scenarios of this kind in this run._]
} else {
table(
columns: (1.4fr, 0.8fr, 2fr),
align: (left, center, left),
stroke: 0.4pt + rgb("#d0d7de"),
inset: 5pt,
fill: fail_row_fill(i => block.scenarios.at(i).status == "FAIL"),
table.header([*Scenario*], [*Status*], [*Known issue*]),
..block.scenarios.map(s => (
[#s.id],
status_badge(s.status),
if s.at("known_issue", default: none) != none {
text(size: 8pt, fill: rgb("#7d4e00"))[#s.known_issue]
} else { text(fill: neutral)[—] },
)).flatten()
)
}
}
#kind_table("Direct Round-Trip (UDPStreamer ↔ UDPStreamerClient)", data.direct)
#kind_table("Recorder (BinaryRecorder disk output)", data.recorder)
#kind_table("Debug Service E2E", data.debug)
#kind_table("TCPLogger E2E", data.tcplogger)
#kind_table("Debug Service PAUSE/RESUME E2E", data.debug_pause_resume)
// ── stress tests ─────────────────────────────────────────────────────────────
= Stress Tests
#if data.stress == none [
_Not run this session._
] else [
#align(center, status_badge(data.stress.overall) + h(8pt) + text(size: 11pt)[
#hl.at("stress_pass", default: 0) passed ·
#hl.at("stress_fail", default: 0) failed
])
#v(4pt)
#for (axis, cases) in data.stress.by_axis [
== Axis: #raw(axis)
#table(
columns: (0.8fr, 0.8fr, 1fr, 1fr, 1fr, 1fr),
align: (right, center, right, right, right, right),
stroke: 0.4pt + rgb("#d0d7de"),
inset: 4pt,
table.header([*Level*], [*Status*], [*Hub RSS (MB)*], [*MARTe RSS (MB)*],
[*Zoom p50 (ms)*], [*Zoom p95 (ms)*]),
..cases.map(c => (
[#c.at("level", default: "n/a")],
status_badge(c.at("status", default: "?")),
fnum(c.at("hub_rss_mb", default: none), digits: 1),
fnum(c.at("marte_rss_mb", default: none), digits: 1),
fnum(c.at("zoom_p50_ms", default: none), digits: 1),
fnum(c.at("zoom_p95_ms", default: none), digits: 1),
)).flatten()
)
]
#if data.stress_plots.len() > 0 [
#v(4pt)
== Scaling curves
#grid(columns: 2, gutter: 8pt,
..data.stress_plots.map(p => image(p, width: 100%))
)
]
]
// ── trend plots ────────────────────────────────────────────────────────────── // ── trend plots ──────────────────────────────────────────────────────────────
#if data.trend_plots.len() > 0 [ #if data.trend_plots.len() > 0 [
= Trends over runs = Trends over runs
Binary file not shown.
Binary file not shown.
@@ -21,6 +21,7 @@ import os
import re import re
import subprocess import subprocess
import sys import sys
import time
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
@@ -60,18 +61,88 @@ def gtest_suite(gtest_bin, work):
return s return s
# ── Go ──────────────────────────────────────────────────────────────────────── # ── C++ Integration (DebugService runtime, non-GTest) ─────────────────────────
def go_suite(client_dir, work): def integration_suite(int_bin, work, timeout=220):
s = {"name": "Go (chain-client)", "lang": "go", "total": 0, "passed": 0, """Run the printf-narrated IntegrationTests.ex binary and heuristically
derive per-test pass/fail from its stdout.
This binary predates GTest adoption and always ``return 0`` from main()
(only an internal 180s SIGALRM timeout or an OS-level crash produce a
non-zero exit), so exit code alone is not a reliable signal. Each of its
7 "--- Test N: ..." blocks prints "SUCCESS:"/"VALIDATION SUCCESSFUL:" on
success or "ERROR:"/"FAILURE:" on failure, so split stdout by those
headers and flag a block failed if it contains an ERROR/FAILURE marker.
Exercises DebugServiceBase.cpp/DebugService.cpp runtime logic that the
header-only DebugServiceGTest suite deliberately does not touch, so it is
the only source of real coverage for those files.
"""
s = {"name": "C++ Integration", "lang": "cpp", "total": 0, "passed": 0,
"failed": 0, "skipped": 0, "time_s": 0.0, "ok": False, "avail": False} "failed": 0, "skipped": 0, "time_s": 0.0, "ok": False, "avail": False}
cov_p = os.path.join(work, "go_cover.out") if not int_bin or not os.path.exists(int_bin):
rc, out, err = _run(["go", "test", "-json", f"-coverprofile={cov_p}", "./..."], s["detail"] = "IntegrationTests binary not found"
cwd=client_dir)
if rc == 127:
s["detail"] = "go toolchain not found"
return s return s
s["avail"] = True s["avail"] = True
t0 = time.time()
rc, out, err = _run([int_bin], timeout=timeout)
s["time_s"] = round(time.time() - t0, 1)
text = out + "\n" + err
blocks = re.split(r"\n(?=--- Test \d+:)", text)
test_blocks = [b for b in blocks if b.lstrip().startswith("--- Test")]
finished = "All Integration Tests Finished." in text
s["total"] = len(test_blocks)
s["failed"] = sum(1 for b in test_blocks if re.search(r"\b(ERROR|FAILURE):", b))
if not finished and s["total"] == 0:
# Crashed/timed out before printing anything useful.
s["total"] = 1
s["failed"] = 1
s["detail"] = f"binary did not complete (rc={rc}): {(err or out)[-200:]}"
elif not finished:
s["detail"] = f"binary exited rc={rc} before finishing all tests"
s["passed"] = s["total"] - s["failed"]
s["ok"] = finished and s["failed"] == 0 and s["total"] > 0
return s
# ── Go ────────────────────────────────────────────────────────────────────────
def go_all_suites(repo, work):
"""Run Go test suites across all project modules and aggregate results."""
modules = [
(os.path.join(repo, "Test/E2E/suite/client"),
"Go (chain-client)"),
(os.path.join(repo, "Common/Client/go"),
"Go (common udpsprotocol + wshub)"),
(os.path.join(repo, "Client/debugger"),
"Go (debugger)"),
]
total_pct = 0.0
pct_count = 0
suites = []
for mod_dir, name in modules:
s = {"name": name, "lang": "go", "total": 0, "passed": 0,
"failed": 0, "skipped": 0, "time_s": 0.0, "ok": False, "avail": False}
cov_p = os.path.join(work, f"go_cover_{name.replace(' ', '_')}.out")
rc, out, err = _run(
["go", "test", "-json", f"-coverprofile={cov_p}", "./..."],
cwd=mod_dir)
if rc == 127:
s["detail"] = "go toolchain not found"
suites.append(s)
continue
s["avail"] = True
cov_pct = _parse_go_json(out, s)
if cov_pct is not None:
s["cov_pct"] = cov_pct
total_pct += cov_pct
pct_count += 1
suites.append(s)
return suites, (round(total_pct / pct_count, 1) if pct_count else None)
def _parse_go_json(out, s):
"""Parse Go test -json output into passed/failed/skipped counts.
Returns coverage percentage (float or None)."""
cov_pct = None cov_pct = None
for line in out.splitlines(): for line in out.splitlines():
try: try:
@@ -93,8 +164,7 @@ def go_suite(client_dir, work):
if m: if m:
cov_pct = float(m.group(1)) cov_pct = float(m.group(1))
s["ok"] = s["failed"] == 0 and s["total"] > 0 s["ok"] = s["failed"] == 0 and s["total"] > 0
s["cov_pct"] = cov_pct return cov_pct
return s
# ── Python ────────────────────────────────────────────────────────────────── # ── Python ──────────────────────────────────────────────────────────────────
@@ -209,12 +279,15 @@ def cpp_coverage(repo, target):
if rc != 0 or not os.path.exists(raw): if rc != 0 or not os.path.exists(raw):
cov["note"] = "lcov capture failed: " + (err or out or "")[-160:] cov["note"] = "lcov capture failed: " + (err or out or "")[-160:]
return cov return cov
# Keep only this repo's own sources so the number reflects project code, # Keep only this repo's own Source/ code so the number reflects project
# not the MARTe2 framework headers dragged in by templates/inlines. # code under test, not the MARTe2 framework headers dragged in by
# templates/inlines, and not the Test/ harness itself (GTest/Integration
# test .cpp files execute every line by construction and sit at ~100%,
# which would just inflate the aggregate and clutter the per-file table
# with files that were never meant to be "covered").
info = os.path.join(build, "coverage.info") info = os.path.join(build, "coverage.info")
rc2, _, e2 = _run(["lcov", "--extract", raw, rc2, _, e2 = _run(["lcov", "--extract", raw,
os.path.join(repo, "Source", "*"), os.path.join(repo, "Source", "*"),
os.path.join(repo, "Test", "*"),
"--output-file", info, "--quiet"] + ign, timeout=300) "--output-file", info, "--quiet"] + ign, timeout=300)
summ_file = info if (rc2 == 0 and os.path.exists(info)) else raw summ_file = info if (rc2 == 0 and os.path.exists(info)) else raw
# Parse the tracefile directly for per-file detail; this also yields the # Parse the tracefile directly for per-file detail; this also yields the
@@ -250,12 +323,16 @@ def main():
work = args.work or args.out work = args.work or args.out
os.makedirs(work, exist_ok=True) os.makedirs(work, exist_ok=True)
chain_dir = os.path.dirname(os.path.abspath(__file__)) chain_dir = os.path.dirname(os.path.abspath(__file__))
client_dir = os.path.join(chain_dir, "client")
gtest_bin = os.path.join(args.repo, "Build", args.target, "GTest", "MainGTest.ex") gtest_bin = os.path.join(args.repo, "Build", args.target, "GTest", "MainGTest.ex")
# BUILD_DIR for Test/Integration doubles the last path component
# ($(PACKAGE)/$(lastword of CURDIR)) — see MakeStdLibDefs.gcc.
integration_bin = os.path.join(args.repo, "Build", args.target,
"Test", "Integration", "Integration",
"IntegrationTests.ex")
suites = [gtest_suite(gtest_bin, work), go_suites, go_avg_cov = go_all_suites(args.repo, work)
go_suite(client_dir, work), suites = ([gtest_suite(gtest_bin, work), integration_suite(integration_bin, work)]
py_suite(chain_dir, work)] + go_suites + [py_suite(chain_dir, work)])
totals = {k: sum(s.get(k, 0) for s in suites) totals = {k: sum(s.get(k, 0) for s in suites)
for k in ("total", "passed", "failed", "skipped")} for k in ("total", "passed", "failed", "skipped")}
ut = {"suites": suites, "totals": totals, ut = {"suites": suites, "totals": totals,
@@ -265,11 +342,10 @@ def main():
langs = [] langs = []
py = next(s for s in suites if s["lang"] == "python") py = next(s for s in suites if s["lang"] == "python")
go = next(s for s in suites if s["lang"] == "go")
langs.append({"name": "Python", "avail": py.get("cov_pct") is not None, langs.append({"name": "Python", "avail": py.get("cov_pct") is not None,
"pct": py.get("cov_pct"), "note": "coverage.py"}) "pct": py.get("cov_pct"), "note": "coverage.py"})
langs.append({"name": "Go", "avail": go.get("cov_pct") is not None, langs.append({"name": "Go", "avail": go_avg_cov is not None,
"pct": go.get("cov_pct"), "note": "go test -cover"}) "pct": go_avg_cov, "note": "go test -cover (avg across modules)"})
cpp = cpp_coverage(args.repo, args.target) if args.cpp_coverage else \ cpp = cpp_coverage(args.repo, args.target) if args.cpp_coverage else \
{"name": "C++", "avail": False, "pct": None, "note": "skipped (use --cpp-coverage)"} {"name": "C++", "avail": False, "pct": None, "note": "skipped (use --cpp-coverage)"}
langs.append(cpp) langs.append(cpp)
+82
View File
@@ -0,0 +1,82 @@
/**
* Trimmed single-thread configuration for the "debug"/"tcplogger" E2E
* scenario kinds: exercises DebugService FORCE/TRACE/BREAK over TCP 8080 /
* UDP 8081 and TCPLogger delivery over TCP 9090, with no UDPStreamer path.
*/
$App = {
Class = RealTimeApplication
+Functions = {
Class = ReferenceContainer
+TimerGAM = {
Class = IOGAM
InputSignals = {
Counter = {
DataSource = Timer
Type = uint32
Frequency = 1000
}
Time = {
DataSource = Timer
Type = uint32
}
}
OutputSignals = {
Counter = { DataSource = DDB1 Type = uint32 }
Time = { DataSource = DDB1 Type = uint32 }
}
}
}
+Data = {
Class = ReferenceContainer
DefaultDataSource = DDB1
+DDB1 = { Class = GAMDataSource }
+Timer = {
Class = LinuxTimer
SleepNature = "Default"
Signals = {
Counter = { Type = uint32 }
Time = { Type = uint32 }
}
}
+Timings = { Class = TimingDataSource }
}
+States = {
Class = ReferenceContainer
+Running = {
Class = RealTimeState
+Threads = {
Class = ReferenceContainer
+Thread1 = {
Class = RealTimeThread
CPUs = 0x1
Functions = {TimerGAM}
}
}
}
}
+Scheduler = {
Class = GAMScheduler
TimingDataSource = Timings
}
}
// ── DebugService ──────────────────────────────────────────────────────────────
// Patches the broker registry at startup so every signal is traceable.
// TcpLogger is auto-injected on LogPort (9090) — no explicit DataSource needed.
+DebugService = {
Class = DebugService
ControlPort = 8080
StreamPort = 8081
LogPort = 9090
StreamIP = "127.0.0.1"
}
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
module debugclient
go 1.21
require marte2debugger v0.0.0
require (
github.com/gorilla/websocket v1.5.1 // indirect
golang.org/x/net v0.17.0 // indirect
marte2/common v0.0.0 // indirect
)
replace marte2debugger => ../../../../Client/debugger
replace marte2/common => ../../../../Common/Client/go
+403
View File
@@ -0,0 +1,403 @@
// Command debugclient drives a running MARTeApp.ex DebugService+TCPLogger
// instance over TCP/UDP for the Test/E2E/suite "debug" and "tcplogger"
// scenario kinds. It scripts a fixed command sequence, captures responses
// and log/trace output, and reports PASS/FAIL as JSON to -out.
package main
import (
"encoding/json"
"flag"
"fmt"
"os"
"strings"
"sync"
"time"
debugger "marte2debugger/controller" // see go.mod replace directive; marte2debugger is Client/debugger's module name
)
type event struct {
kind string
data any
}
func main() {
host := flag.String("host", "127.0.0.1", "MARTeApp host")
cmdPort := flag.Int("cmdport", 8080, "DebugService TCP command port")
udpPort := flag.Int("udpport", 8081, "DebugService UDP trace port")
logPort := flag.Int("logport", 9090, "TCPLogger TCP port")
scenario := flag.String("scenario", "", "scenario id (for output naming)")
outDir := flag.String("out", "/tmp/debug_e2e", "output directory")
mode := flag.String("mode", "debug", "debug|tcplogger|debug_pause_resume")
dur := flag.Duration("dur", 4*time.Second, "how long to run the script/collection")
flag.Parse()
if *scenario == "" {
fmt.Fprintln(os.Stderr, "missing -scenario")
os.Exit(2)
}
os.MkdirAll(*outDir, 0o755)
var mu sync.Mutex
var events []event
sink := func(v any) {
mu.Lock()
defer mu.Unlock()
// runLog (and every other MarteController event site) passes a
// map[string]any literal to sink; store it as-is, no
// unmarshal/remarshal needed.
events = append(events, event{kind: fmt.Sprintf("%T", v), data: v})
}
mc := debugger.NewHeadlessMarteController(sink)
mc.Connect(*host, *cmdPort, *udpPort, *logPort)
defer mc.Disconnect()
time.Sleep(500 * time.Millisecond) // allow TCP/UDP/log connects to establish
// Snapshot the event count *after* the connect-settle sleep so
// runTcpLoggerScript only scans events recorded from here on. Without this,
// the "log" event that Connect() itself emits synchronously (a "Connecting
// to ..." INFO message, well before any TCPLogger TCP traffic happens)
// would satisfy the check instantly regardless of whether the real
// TCPLogger (port 9090) ever delivers anything for the triggered event.
mu.Lock()
baseline := len(events)
mu.Unlock()
var ok bool
var msg string
switch *mode {
case "debug":
ok, msg = runDebugScript(mc, &events, &mu)
case "tcplogger":
ok, msg = runTcpLoggerScript(mc, *dur, &events, &mu, baseline)
case "debug_pause_resume":
ok, msg = runPauseResumeScript(mc, &events, &mu)
default:
fmt.Fprintf(os.Stderr, "unknown -mode %q\n", *mode)
os.Exit(2)
}
time.Sleep(300 * time.Millisecond) // drain final events
result := map[string]any{
"id": *scenario,
"pass": ok,
"detail": msg,
}
f, _ := os.Create(fmt.Sprintf("%s/result_%s.json", *outDir, *scenario))
json.NewEncoder(f).Encode(result)
f.Close()
status := "FAIL"
if ok {
status = "PASS"
}
fmt.Printf("%s: %s - %s\n", *scenario, status, msg)
os.WriteFile(fmt.Sprintf("%s/status_%s.txt", *outDir, *scenario), []byte(status), 0o644)
if !ok {
os.Exit(1)
}
}
// waitForAck polls events (from index start onward) for a MarteController
// "text_line" event exactly matching DebugServiceBase::HandleCommand's
// "OK <token> <count>\n" reply grammar, requiring count > 0. HandleCommand
// prints this reply for every one of FORCE/UNFORCE/TRACE/BREAK regardless of
// enable/disable direction, and count is always "number of signals the
// command actually matched" (DebugServiceBase.cpp:1468-1525) — so count==0
// means the target signal path was never resolved (e.g. a wire-format/name-
// translation bug), which a bare "did the socket stay open" check like the
// old runDebugScript could never catch.
func waitForAck(events *[]event, mu *sync.Mutex, start int, token string, timeout time.Duration) (string, bool) {
prefix := "OK " + token + " "
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
mu.Lock()
for _, e := range (*events)[start:] {
m, ok := e.data.(map[string]any)
if !ok || m["type"] != "text_line" {
continue
}
line, _ := m["data"].(string)
if !strings.HasPrefix(line, prefix) {
continue
}
var count uint32
if _, err := fmt.Sscanf(line, prefix+"%d", &count); err == nil && count > 0 {
mu.Unlock()
return line, true
}
}
mu.Unlock()
time.Sleep(50 * time.Millisecond)
}
return "", false
}
// runDebugScript exercises FORCE/TRACE/BREAK over the TCP 8080 command
// protocol (grammar confirmed against Source/Components/Interfaces/
// DebugService/DebugServiceBase.cpp's HandleCommand: "FORCE <name> <val>",
// "TRACE <name> <0|1> [decim]", "BREAK <name> <op|OFF> <threshold>",
// each replying "OK <TOKEN> <count>\n"). Each step waits for the real
// "OK <TOKEN> <count>" acknowledgement with count > 0 via waitForAck,
// confirming DebugService actually resolved and applied the command against
// the named signal — not merely that the TCP connection stayed alive (which
// would pass even if DebugService silently no-op'd every command, e.g. due
// to a signal-name/wire-format bug).
func runDebugScript(mc *debugger.MarteController, events *[]event, mu *sync.Mutex) (bool, string) {
const ackTimeout = 2 * time.Second
mu.Lock()
start := len(*events)
mu.Unlock()
mc.SendCommand("FORCE App.Data.Timer.Counter 42")
if _, ok := waitForAck(events, mu, start, "FORCE", ackTimeout); !ok {
return false, "no \"OK FORCE <count>\" ack with count>0 received (signal not resolved)"
}
mu.Lock()
start = len(*events)
mu.Unlock()
mc.SendCommand("TRACE App.Data.Timer.Counter 1 1")
if _, ok := waitForAck(events, mu, start, "TRACE", ackTimeout); !ok {
return false, "no \"OK TRACE <count>\" ack with count>0 received (signal not resolved)"
}
mu.Lock()
start = len(*events)
mu.Unlock()
mc.SendCommand("BREAK App.Data.Timer.Counter > 1000")
if _, ok := waitForAck(events, mu, start, "BREAK", ackTimeout); !ok {
return false, "no \"OK BREAK <count>\" ack with count>0 received for SetBreak (signal not resolved)"
}
mu.Lock()
start = len(*events)
mu.Unlock()
mc.SendCommand("BREAK App.Data.Timer.Counter OFF")
if _, ok := waitForAck(events, mu, start, "BREAK", ackTimeout); !ok {
return false, "no \"OK BREAK <count>\" ack with count>0 received for ClearBreak (signal not resolved)"
}
mu.Lock()
start = len(*events)
mu.Unlock()
mc.SendCommand("UNFORCE App.Data.Timer.Counter")
if _, ok := waitForAck(events, mu, start, "UNFORCE", ackTimeout); !ok {
return false, "no \"OK UNFORCE <count>\" ack with count>0 received (signal not resolved)"
}
if !mc.IsConnected() {
return false, "lost connection to DebugService during script"
}
return true, "FORCE/TRACE/BREAK/UNFORCE all acknowledged with count>0 (real signal resolution confirmed)"
}
// runTcpLoggerScript triggers a log-worthy event and waits for a matching
// "log" event to arrive over the real TCPLogger TCP connection (port 9090)
// within dur.
//
// NOTE: an invalid "FORCE <nonexistent signal> <val>" is *not* usable here —
// DebugServiceBase::ForceSignal() silently no-ops (count stays 0, no
// REPORT_ERROR call) when no signal matches, so it never reaches the logger
// at all. Instead we send "MSG <nonexistent destination> <fn> 0", which
// DebugServiceBase::HandleCommand's MSG handler always resolves via
// ObjectRegistryDatabase::Find() and, on failure, does call
// REPORT_ERROR_STATIC(Warning, "MSG: destination '%s' not found in ORD.")
// (Source/Components/Interfaces/DebugService/DebugServiceBase.cpp) — a real,
// synchronous, deterministic log emission that the framework's LoggerService
// broadcasts to the auto-injected TcpLogger, which then writes
// "LOG <level> <description>\n" to every connected TCP client (see
// Source/Components/Interfaces/TCPLogger/TcpLogger.cpp ConsumeLogMessage /
// Execute). MarteController's runLog reads that line from the real TCP 9090
// socket and forwards it through sink as map[string]any{"type": "log",
// "time": ..., "level": ..., "message": ...}.
//
// baseline is the length of *events captured right after the initial
// connect-settle sleep, before this function sends the MSG command: only
// events recorded from index baseline onward are eligible, so the "log"
// event that MarteController.Connect() itself emits synchronously (a
// "Connecting to ..." INFO message, emitted before any TCP/UDP/log socket
// activity) can never satisfy this check.
func runTcpLoggerScript(mc *debugger.MarteController, dur time.Duration, events *[]event, mu *sync.Mutex, baseline int) (bool, string) {
const missingDest = "DebugClientNoSuchDestination"
mc.SendCommand(fmt.Sprintf("MSG %s SomeFunction 0", missingDest))
deadline := time.Now().Add(dur)
for time.Now().Before(deadline) {
mu.Lock()
for _, e := range (*events)[baseline:] {
if m, ok := e.data.(map[string]any); ok && m["type"] == "log" {
msg, _ := m["message"].(string)
// MarteController.writeCmd() also emits a client-side "CMD"
// level log echoing every outgoing command as "→ <cmd>"
// (see martecontrol.go) — since our own MSG command text
// contains missingDest, that local echo would otherwise
// satisfy a naive substring check instantly, before the real
// TCPLogger round-trip ever happens. Require the actual
// REPORT_ERROR text the DebugService MSG handler produces
// ("not found in ORD"), which can only arrive via runLog's
// real TCP 9090 read, never via the local echo.
if strings.Contains(msg, missingDest) && strings.Contains(msg, "not found in ORD") {
mu.Unlock()
return true, fmt.Sprintf("received real TCPLogger log event: %v", m)
}
}
}
mu.Unlock()
time.Sleep(100 * time.Millisecond)
}
if !mc.IsConnected() {
return false, "lost connection during tcplogger wait and no matching log event received"
}
return false, "no matching log event received within duration"
}
// readValueResponse sends "VALUE <name>" and waits for the matching
// {"Name":...,"Value":"...",...} JSON reply (DebugServiceBase::GetSignalValue,
// dispatched via HandleCommand's "VALUE" token, terminated by a bare
// "OK VALUE" sentinel line). MarteController's readLoop recognises the
// leading '{' and accumulates until the sentinel, then delivers the clean
// JSON text as a map[string]any{"type":"response","tag":"VALUE","data":...}
// event. Unlike TRACE, VALUE reads the signal's live memory address directly
// regardless of whether tracing is enabled, so it works as a completely
// independent observation channel for the PAUSE/RESUME test below.
func readValueResponse(events *[]event, mu *sync.Mutex, start int, timeout time.Duration) (uint32, bool) {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
mu.Lock()
for _, e := range (*events)[start:] {
m, ok := e.data.(map[string]any)
if !ok || m["type"] != "response" || m["tag"] != "VALUE" {
continue
}
data, _ := m["data"].(string)
var v struct {
Value string `json:"Value"`
}
if json.Unmarshal([]byte(data), &v) == nil {
var n uint32
if _, err := fmt.Sscanf(v.Value, "%d", &n); err == nil {
mu.Unlock()
return n, true
}
}
}
mu.Unlock()
time.Sleep(20 * time.Millisecond)
}
return 0, false
}
// waitForBareOK waits for a text_line event whose data is exactly "OK" — the
// literal reply DebugServiceBase::HandleCommand sends for PAUSE/RESUME
// ("out += \"OK\\n\";", no per-signal count unlike FORCE/TRACE/BREAK's
// "OK <TOKEN> <count>\n"), so it cannot be confused with those other acks.
func waitForBareOK(events *[]event, mu *sync.Mutex, start int, timeout time.Duration) bool {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
mu.Lock()
for _, e := range (*events)[start:] {
m, ok := e.data.(map[string]any)
if ok && m["type"] == "text_line" && m["data"] == "OK" {
mu.Unlock()
return true
}
}
mu.Unlock()
time.Sleep(20 * time.Millisecond)
}
return false
}
// runPauseResumeScript exercises PAUSE/RESUME over the TCP 8080 command
// protocol. This complements runDebugScript (FORCE/TRACE/BREAK/UNFORCE):
// those only confirm DebugService *acknowledges* a command; this confirms
// PAUSE actually halts the RT GAM loop rather than merely replying "OK".
// DebugBrokerWrapper's pause spin (DebugBrokerWrapper.h) only runs in the
// OUTPUT broker's Execute(), AFTER it has already committed the GAM's
// result for the current cycle — input brokers deliberately never spin
// (would risk stalling cross-thread EventSem posts). So the *input*-side
// registration for a signal (e.g. "App.Data.Timer.Counter", the raw
// LinuxTimer memory feeding TimerGAM) keeps advancing even while paused;
// only the *output*-side registration ("App.Data.DDB1.Counter", TimerGAM's
// copy into DDB1 after IOGAM's pass-through) actually freezes. Confirmed
// empirically: manual PAUSE/RESUME polling showed Timer.Counter advancing
// continuously through the pause window while DDB1.Counter held constant.
func runPauseResumeScript(mc *debugger.MarteController, events *[]event, mu *sync.Mutex) (bool, string) {
const target = "App.Data.DDB1.Counter"
const ackTimeout = 2 * time.Second
sample := func() (uint32, bool) {
mu.Lock()
start := len(*events)
mu.Unlock()
mc.SendCommand("VALUE " + target)
return readValueResponse(events, mu, start, ackTimeout)
}
v1, ok := sample()
if !ok {
return false, "no VALUE response received while running"
}
time.Sleep(200 * time.Millisecond)
v2, ok := sample()
if !ok {
return false, "no VALUE response received on second running sample"
}
if v2 <= v1 {
return false, fmt.Sprintf("Counter did not advance while running (%d -> %d)", v1, v2)
}
mu.Lock()
start := len(*events)
mu.Unlock()
mc.SendCommand("PAUSE")
if !waitForBareOK(events, mu, start, ackTimeout) {
return false, "no bare \"OK\" ack received for PAUSE"
}
time.Sleep(100 * time.Millisecond) // let any already-in-flight cycle settle
vPause1, ok := sample()
if !ok {
return false, "no VALUE response received while paused"
}
time.Sleep(500 * time.Millisecond)
vPause2, ok := sample()
if !ok {
return false, "no VALUE response received on second paused sample"
}
if vPause2 > vPause1+1 { // tolerate at most one straggling in-flight cycle
return false, fmt.Sprintf("Counter kept advancing while paused (%d -> %d)", vPause1, vPause2)
}
mu.Lock()
start = len(*events)
mu.Unlock()
mc.SendCommand("RESUME")
if !waitForBareOK(events, mu, start, ackTimeout) {
return false, "no bare \"OK\" ack received for RESUME"
}
time.Sleep(200 * time.Millisecond)
v3, ok := sample()
if !ok {
return false, "no VALUE response received after resume"
}
time.Sleep(200 * time.Millisecond)
v4, ok := sample()
if !ok {
return false, "no VALUE response received on second post-resume sample"
}
if v4 <= v3 {
return false, fmt.Sprintf("Counter did not resume advancing after RESUME (%d -> %d)", v3, v4)
}
if !mc.IsConnected() {
return false, "lost connection to DebugService during pause/resume script"
}
return true, fmt.Sprintf("PAUSE halted Counter (%d -> %d) and RESUME restored advancement (%d -> %d)",
vPause1, vPause2, v3, v4)
}
@@ -74,6 +74,8 @@ def build_e2e(results, work):
scen = [] scen = []
corrs, rss_vals, cpu_vals, tput_vals = [], [], [], [] corrs, rss_vals, cpu_vals, tput_vals = [], [], [], []
for r in results.get("scenarios", []): for r in results.get("scenarios", []):
if r.get("kind", "chain") != "chain":
continue
sid = r["id"] sid = r["id"]
metrics = r.get("metrics", {}) metrics = r.get("metrics", {})
sigs = [] sigs = []
@@ -139,6 +141,23 @@ def build_e2e(results, work):
} }
def build_by_kind(results, kind):
"""Filter raw scenario records (as written by run_e2e.sh's results.json
aggregation) down to a single scenario `kind` (direct/recorder/debug/
tcplogger), with a small pass/fail rollup for the report's headline KPIs
and per-kind section."""
scenarios = [s for s in results.get("scenarios", []) if s.get("kind") == kind]
n_pass = sum(1 for s in scenarios if s.get("status") == "PASS")
n_fail = sum(1 for s in scenarios if s.get("status") == "FAIL")
return {
"kind": kind,
"n_pass": n_pass,
"n_fail": n_fail,
"n_total": len(scenarios),
"scenarios": scenarios,
}
def headline(e2e, ut, cov): def headline(e2e, ut, cov):
cov_by = {c["name"]: c.get("pct") for c in cov.get("languages", [])} cov_by = {c["name"]: c.get("pct") for c in cov.get("languages", [])}
t = ut.get("totals", {}) t = ut.get("totals", {})
@@ -174,11 +193,9 @@ _LABELS = {
} }
def regression(curr, prev, labels=None, directions=None): def regression(curr, prev):
labels = labels if labels is not None else _LABELS
directions = directions if directions is not None else _DIRECTION
rows = [] rows = []
for k, label in labels.items(): for k, label in _LABELS.items():
c = curr.get(k) c = curr.get(k)
p = prev.get(k) if prev else None p = prev.get(k) if prev else None
better = None better = None
@@ -188,14 +205,57 @@ def regression(curr, prev, labels=None, directions=None):
if delta == 0: if delta == 0:
better = None better = None
else: else:
better = (delta > 0) == directions[k] better = (delta > 0) == _DIRECTION[k]
rows.append({"name": label, "key": k, "current": c, "previous": p, rows.append({"name": label, "key": k, "current": c, "previous": p,
"delta": delta, "better": better, "delta": delta, "better": better,
"higher_better": directions[k]}) "higher_better": _DIRECTION[k]})
return rows return rows
# Stress-axis aggregate metrics tracked across runs (mirrors the headline scalars). def trend_plots(history, out):
if not history:
return []
xs = list(range(len(history)))
labels = [h.get("ts_short", str(i)) for i, h in enumerate(history)]
made = []
def _plot(fname, series, title, ylabel):
ys = [[h.get(k) for h in history] for _, k in series]
if all(all(v is None for v in y) for y in ys):
return
fig, ax = plt.subplots(figsize=(7, 3))
for (lbl, _), y in zip(series, ys):
xp = [x for x, v in zip(xs, y) if v is not None]
yp = [v for v in y if v is not None]
if yp:
ax.plot(xp, yp, "o-", label=lbl)
ax.set_title(title)
ax.set_ylabel(ylabel)
ax.set_xticks(xs)
ax.set_xticklabels(labels, rotation=45, ha="right", fontsize=7)
ax.grid(alpha=0.3)
ax.legend(fontsize=8)
fig.tight_layout()
p = os.path.join(out, fname)
fig.savefig(p, dpi=110)
plt.close(fig)
made.append(p)
_plot("trend_tests.png",
[("E2E pass", "e2e_pass"), ("Unit pass", "unit_pass")],
"Passing tests over runs", "count")
_plot("trend_coverage.png",
[("Python", "cov_python"), ("Go", "cov_go"), ("C++", "cov_cpp")],
"Code coverage over runs", "% covered")
_plot("trend_fidelity.png", [("Mean sine corr", "mean_corr")],
"Waveform fidelity over runs", "correlation")
_plot("trend_perf.png",
[("Peak RSS (MB)", "mean_peak_rss_mb"), ("CPU (s)", "mean_cpu_s")],
"Resource use over runs", "value")
return made
# ── stress (Test/E2E/suite/stress.py + stress_run.py) ───────────────────────
_STRESS_LABELS = { _STRESS_LABELS = {
"stress_pass": "Stress cases passed", "stress_pass": "Stress cases passed",
"stress_fail": "Stress cases failed", "stress_fail": "Stress cases failed",
@@ -208,6 +268,23 @@ _STRESS_DIRECTION = {
"stress_max_hub_rss_mb": False, "stress_max_marte_rss_mb": False, "stress_max_hub_rss_mb": False, "stress_max_marte_rss_mb": False,
"stress_max_zoom_p95_ms": False, "stress_max_zoom_p95_ms": False,
} }
_DIRECTION.update({
"direct_pass": True, "direct_fail": False,
"recorder_pass": True, "recorder_fail": False,
"debug_pass": True, "debug_fail": False,
"tcplogger_pass": True, "tcplogger_fail": False,
"debug_pause_resume_pass": True, "debug_pause_resume_fail": False,
})
_DIRECTION.update(_STRESS_DIRECTION)
_LABELS.update({
"direct_pass": "Direct scenarios passed", "direct_fail": "Direct scenarios failed",
"recorder_pass": "Recorder scenarios passed", "recorder_fail": "Recorder scenarios failed",
"debug_pass": "Debug scenarios passed", "debug_fail": "Debug scenarios failed",
"tcplogger_pass": "TCPLogger scenarios passed", "tcplogger_fail": "TCPLogger scenarios failed",
"debug_pause_resume_pass": "Debug pause/resume scenarios passed",
"debug_pause_resume_fail": "Debug pause/resume scenarios failed",
})
_LABELS.update(_STRESS_LABELS)
def build_stress(sr): def build_stress(sr):
@@ -236,8 +313,6 @@ def stress_headline(stress):
} }
# Which metrics to plot per axis (label, case-field). Mixed units share a "value"
# y-axis as trend_perf.png already does; all-zero series are dropped.
_STRESS_AXIS_METRICS = { _STRESS_AXIS_METRICS = {
"ds_signal_elements": [("MARTe RSS (MB)", "marte_rss_mb"), "ds_signal_elements": [("MARTe RSS (MB)", "marte_rss_mb"),
("hub RSS (MB)", "hub_rss_mb")], ("hub RSS (MB)", "hub_rss_mb")],
@@ -287,78 +362,51 @@ def stress_plots(by_axis, out):
return made return made
def trend_plots(history, out):
if not history:
return []
xs = list(range(len(history)))
labels = [h.get("ts_short", str(i)) for i, h in enumerate(history)]
made = []
def _plot(fname, series, title, ylabel):
ys = [[h.get(k) for h in history] for _, k in series]
if all(all(v is None for v in y) for y in ys):
return
fig, ax = plt.subplots(figsize=(7, 3))
for (lbl, _), y in zip(series, ys):
xp = [x for x, v in zip(xs, y) if v is not None]
yp = [v for v in y if v is not None]
if yp:
ax.plot(xp, yp, "o-", label=lbl)
ax.set_title(title)
ax.set_ylabel(ylabel)
ax.set_xticks(xs)
ax.set_xticklabels(labels, rotation=45, ha="right", fontsize=7)
ax.grid(alpha=0.3)
ax.legend(fontsize=8)
fig.tight_layout()
p = os.path.join(out, fname)
fig.savefig(p, dpi=110)
plt.close(fig)
made.append(p)
_plot("trend_tests.png",
[("E2E pass", "e2e_pass"), ("Unit pass", "unit_pass")],
"Passing tests over runs", "count")
_plot("trend_coverage.png",
[("Python", "cov_python"), ("Go", "cov_go"), ("C++", "cov_cpp")],
"Code coverage over runs", "% covered")
_plot("trend_fidelity.png", [("Mean sine corr", "mean_corr")],
"Waveform fidelity over runs", "correlation")
_plot("trend_perf.png",
[("Peak RSS (MB)", "mean_peak_rss_mb"), ("CPU (s)", "mean_cpu_s")],
"Resource use over runs", "value")
return made
def main(): def main():
ap = argparse.ArgumentParser(description="Build E2E report_data.json") ap = argparse.ArgumentParser(description="Build E2E report_data.json")
ap.add_argument("--repo", required=True) ap.add_argument("--repo", required=True)
ap.add_argument("--results", required=True) ap.add_argument("--results", required=True)
ap.add_argument("--work", required=True) ap.add_argument("--work", required=True)
ap.add_argument("--out", required=True) ap.add_argument("--out", required=True)
ap.add_argument("--stress-results", default="", ap.add_argument("--stress-results", default=None)
help="path to stress_results.json (optional)")
args = ap.parse_args() args = ap.parse_args()
os.makedirs(args.out, exist_ok=True) os.makedirs(args.out, exist_ok=True)
results = _load(args.results, {"overall": "FAIL", "scenarios": []}) results = _load(args.results, {"overall": "FAIL", "scenarios": []})
ut = _load(os.path.join(args.out, "unit_tests.json"), {"suites": [], "totals": {}}) ut = _load(os.path.join(args.out, "unit_tests.json"), {"suites": [], "totals": {}})
cov = _load(os.path.join(args.out, "coverage.json"), {"languages": []}) cov = _load(os.path.join(args.out, "coverage.json"), {"languages": []})
sr = _load(args.stress_results) if args.stress_results else None
stress = build_stress(sr) if sr else None
e2e = build_e2e(results, args.work) e2e = build_e2e(results, args.work)
direct = build_by_kind(results, "direct")
recorder = build_by_kind(results, "recorder")
debug = build_by_kind(results, "debug")
tcplogger = build_by_kind(results, "tcplogger")
debug_pause_resume = build_by_kind(results, "debug_pause_resume")
stress = None
stress_plot_paths = []
if args.stress_results and os.path.exists(args.stress_results):
sr = _load(args.stress_results)
if sr:
stress = build_stress(sr)
stress_plot_paths = stress_plots(stress["by_axis"], args.out)
now = datetime.datetime.now() now = datetime.datetime.now()
meta = {"timestamp": now.isoformat(timespec="seconds"), meta = {"timestamp": now.isoformat(timespec="seconds"),
"ts_short": now.strftime("%m-%d %H:%M"), "ts_short": now.strftime("%m-%d %H:%M"),
"git_sha": _git_sha(args.repo), "target": "x86-linux"} "git_sha": _git_sha(args.repo), "target": "x86-linux"}
hl = headline(e2e, ut, cov) hl = headline(e2e, ut, cov)
labels, directions = _LABELS, _DIRECTION hl.update({
"direct_pass": direct["n_pass"], "direct_fail": direct["n_fail"],
"recorder_pass": recorder["n_pass"], "recorder_fail": recorder["n_fail"],
"debug_pass": debug["n_pass"], "debug_fail": debug["n_fail"],
"tcplogger_pass": tcplogger["n_pass"], "tcplogger_fail": tcplogger["n_fail"],
"debug_pause_resume_pass": debug_pause_resume["n_pass"],
"debug_pause_resume_fail": debug_pause_resume["n_fail"],
})
if stress: if stress:
hl.update(stress_headline(stress)) hl.update(stress_headline(stress))
labels = {**_LABELS, **_STRESS_LABELS}
directions = {**_DIRECTION, **_STRESS_DIRECTION}
# history: read previous, then append current # history: read previous, then append current
hist_path = os.path.join(args.out, "history.jsonl") hist_path = os.path.join(args.out, "history.jsonl")
@@ -372,35 +420,26 @@ def main():
except ValueError: except ValueError:
pass pass
prev = history[-1] if history else None prev = history[-1] if history else None
reg = regression(hl, prev, labels, directions) reg = regression(hl, prev)
entry = dict(hl) entry = dict(hl)
entry["timestamp"] = meta["timestamp"] entry["timestamp"] = meta["timestamp"]
entry["ts_short"] = meta["ts_short"] entry["ts_short"] = meta["ts_short"]
entry["git_sha"] = meta["git_sha"] entry["git_sha"] = meta["git_sha"]
entry["overall"] = e2e["overall"] entry["overall"] = e2e["overall"]
if stress:
entry["stress"] = [
{k: c.get(k) for k in ("id", "axis", "level", "status",
"marte_cpu_s", "marte_rss_mb",
"hub_cpu_s", "hub_rss_mb",
"zoom_p95_ms", "min_frames")}
for c in stress["cases"]
]
with open(hist_path, "a") as f: with open(hist_path, "a") as f:
f.write(json.dumps(entry) + "\n") f.write(json.dumps(entry) + "\n")
history.append(entry) history.append(entry)
plots = [os.path.basename(p) for p in trend_plots(history, args.out)] plots = [os.path.basename(p) for p in trend_plots(history, args.out)]
splots = ([os.path.basename(p) for p in stress_plots(stress["by_axis"], args.out)]
if stress else [])
doc = { doc = {
"meta": meta, "e2e": e2e, "unit_tests": ut, "meta": meta, "e2e": e2e, "unit_tests": ut, "coverage": cov,
"coverage": cov, "regression": reg, "headline": hl, "direct": direct, "recorder": recorder, "debug": debug, "tcplogger": tcplogger,
"trend_plots": plots, "history_len": len(history), "debug_pause_resume": debug_pause_resume,
"is_first_run": prev is None, "stress": stress, "stress_plots": [os.path.basename(p) for p in stress_plot_paths],
"stress": stress, "stress_plots": splots, "regression": reg, "headline": hl, "trend_plots": plots,
"history_len": len(history), "is_first_run": prev is None,
} }
with open(os.path.join(args.out, "report_data.json"), "w") as f: with open(os.path.join(args.out, "report_data.json"), "w") as f:
json.dump(doc, f, indent=2) json.dump(doc, f, indent=2)
@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# run_chain_e2e.sh — Full-chain E2E orchestrator for the streaming chain # run_e2e.sh — Full-chain E2E orchestrator for the streaming chain
# #
# MARTe2 app (FileReader -> IOGAM -> UDPStreamer) # MARTe2 app (FileReader -> IOGAM -> UDPStreamer)
# -> UDPS -> StreamHub -> chain-client (record + zoom/window/trigger) # -> UDPS -> StreamHub -> chain-client (record + zoom/window/trigger)
@@ -10,9 +10,9 @@
# against the analytic/fed oracle, renders plots, and aggregates results.json. # against the analytic/fed oracle, renders plots, and aggregates results.json.
# Artifacts: Build/x86-linux/E2E/chain/ (report) and /tmp/chain_e2e/ (scratch). # Artifacts: Build/x86-linux/E2E/chain/ (report) and /tmp/chain_e2e/ (scratch).
# #
# Usage: ./run_chain_e2e.sh [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage] [--stress] # Usage: ./run_e2e.sh [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage]
# --stress also runs the capacity matrix (stress.py / stress_run.py) and embeds a # [--skip-coverage] [--skip-stress] [--skip-datasources]
# Stress Tests section (table + per-axis scaling curves) in the PDF. # [--skip-recorder] [--skip-debug] [--skip-tcplogger]
set -u set -u
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -26,16 +26,25 @@ mkdir -p "${OUT_DIR}" "${WORK}"
SKIP_BUILD=0 SKIP_BUILD=0
ONLY="" ONLY=""
PDF_ONLY=0 PDF_ONLY=0
CPP_COV=0 CPP_COV=1
STRESS=0 SKIP_STRESS=0
SKIP_DATASOURCES=0
SKIP_RECORDER=0
SKIP_DEBUG=0
SKIP_TCPLOGGER=0
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case "$1" in case "$1" in
--skip-build) SKIP_BUILD=1 ;; --skip-build) SKIP_BUILD=1 ;;
--only) shift; ONLY="$1" ;; --only) shift; ONLY="$1" ;;
--pdf-only) PDF_ONLY=1 ;; --pdf-only) PDF_ONLY=1 ;;
--cpp-coverage) CPP_COV=1 ;; --cpp-coverage) CPP_COV=1 ;;
--stress) STRESS=1 ;; --skip-coverage) CPP_COV=0 ;;
--help|-h) echo "Usage: $0 [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage] [--stress]"; exit 0 ;; --skip-stress) SKIP_STRESS=1 ;;
--skip-datasources) SKIP_DATASOURCES=1 ;;
--skip-recorder) SKIP_RECORDER=1 ;;
--skip-debug) SKIP_DEBUG=1 ;;
--skip-tcplogger) SKIP_TCPLOGGER=1 ;;
--help|-h) echo "Usage: $0 [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage] [--skip-coverage] [--skip-stress] [--skip-datasources] [--skip-recorder] [--skip-debug] [--skip-tcplogger]"; exit 0 ;;
*) echo "unknown arg $1" >&2; exit 2 ;; *) echo "unknown arg $1" >&2; exit 2 ;;
esac esac
shift shift
@@ -49,7 +58,10 @@ source "${ENV_SCRIPT}"
COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components" COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
export LD_LIBRARY_PATH="\ export LD_LIBRARY_PATH="\
${BUILD_DIR}/Components/DataSources/UDPStreamer:\ ${BUILD_DIR}/Components/DataSources/UDPStreamer:\
${BUILD_DIR}/Components/DataSources/UDPStreamerClient:\
${BUILD_DIR}/Components/Interfaces/UDPStream:\ ${BUILD_DIR}/Components/Interfaces/UDPStream:\
${BUILD_DIR}/Components/Interfaces/DebugService:\
${BUILD_DIR}/Components/Interfaces/TCPLogger:\
${MARTe2_DIR}/Build/${TARGET}/Core:\ ${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\ ${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/FileDataSource:\ ${COMP}/DataSources/FileDataSource:\
@@ -59,6 +71,7 @@ ${LD_LIBRARY_PATH:-}"
MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex" MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
STREAMHUB_EX="${BUILD_DIR}/StreamHub/StreamHub.ex" STREAMHUB_EX="${BUILD_DIR}/StreamHub/StreamHub.ex"
CLIENT="${SCRIPT_DIR}/client/chain-client" CLIENT="${SCRIPT_DIR}/client/chain-client"
DEBUGCLIENT="${SCRIPT_DIR}/debugclient/debugclient"
PY="python3" PY="python3"
SCEN() { ${PY} "${SCRIPT_DIR}/scenarios.py" >/dev/null 2>&1; } SCEN() { ${PY} "${SCRIPT_DIR}/scenarios.py" >/dev/null 2>&1; }
@@ -80,36 +93,75 @@ if [ "${SKIP_BUILD}" -eq 0 ]; then
echo "── Building components ──" echo "── Building components ──"
make -C "${REPO_ROOT}/Source/Components/Interfaces/UDPStream" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1 make -C "${REPO_ROOT}/Source/Components/Interfaces/UDPStream" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1
make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1 make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1
make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamerClient" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1
make -C "${REPO_ROOT}/Source/Applications/StreamHub" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1 make -C "${REPO_ROOT}/Source/Applications/StreamHub" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1
fi fi
if [ ! -x "${CLIENT}" ]; then if [ ! -x "${CLIENT}" ]; then
echo "── Building chain-client ──" echo "── Building chain-client ──"
(cd "${SCRIPT_DIR}/client" && go build -o chain-client .) || { echo "client build failed"; exit 1; } (cd "${SCRIPT_DIR}/client" && go build -o chain-client .) || { echo "client build failed"; exit 1; }
fi fi
if [ ! -x "${DEBUGCLIENT}" ]; then
echo "── Building debugclient ──"
(cd "${SCRIPT_DIR}/debugclient" && go build -o debugclient .) || { echo "debugclient build failed"; exit 1; }
fi
[ -x "${MARTE_APP}" ] || { echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2; exit 1; } [ -x "${MARTE_APP}" ] || { echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2; exit 1; }
[ -x "${STREAMHUB_EX}" ] || { echo "ERROR: StreamHub.ex not found" >&2; exit 1; } [ -x "${STREAMHUB_EX}" ] || { echo "ERROR: StreamHub.ex not found" >&2; exit 1; }
# ── Scenario list (id|ws_port|udp_port0|network|oracle|trig|checks) ────────── # ── Scenario list (kind|id|f2|f3|f4|f5|f6|f7) ────────────────────────────────
LIST="$(${PY} - "${ONLY}" <<'PY' # chain: kind|id|ws_port|udp_port0|network|oracle|trig|checks
# direct: kind|id|cfg|-|-|-|-|-
# recorder: kind|id|marte_cfg|hub_cfg|-|-|-|-
# debug/tcplogger/debug_pause_resume: kind|id|cfg|cmd_port|udp_port|log_port|-|-
SKIP_KINDS=""
[ "${SKIP_DATASOURCES}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}direct,"
[ "${SKIP_RECORDER}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}recorder,"
[ "${SKIP_DEBUG}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}debug,debug_pause_resume,"
[ "${SKIP_TCPLOGGER}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}tcplogger,"
LIST="$(${PY} - "${ONLY}" "${SKIP_KINDS}" <<'PY'
import sys, os import sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath("Test/E2E/chain/scenarios.py"))) sys.path.insert(0, os.path.dirname(os.path.abspath("Test/E2E/suite/scenarios.py")))
sys.path.insert(0, os.path.join(os.getcwd(), "Test/E2E/chain")) sys.path.insert(0, os.path.join(os.getcwd(), "Test/E2E/suite"))
import scenarios as S import scenarios as S
only = sys.argv[1] if len(sys.argv) > 1 else "" only = sys.argv[1] if len(sys.argv) > 1 else ""
skip_kinds = set(sys.argv[2].split(",")) if len(sys.argv) > 2 and sys.argv[2] else set()
for s in S.SCENARIOS: for s in S.SCENARIOS:
if only and s["id"] != only: if only and s["id"] != only:
continue continue
if s["kind"] in skip_kinds:
continue
kind = s["kind"]
if kind == "chain":
trig = s.get("trig_signal") or "" trig = s.get("trig_signal") or ""
checks = ",".join(s.get("client_checks", [])) checks = ",".join(s.get("client_checks", []))
if not trig: if not trig:
checks = ",".join(c for c in s.get("client_checks", []) if c != "trigger") checks = ",".join(c for c in s.get("client_checks", []) if c != "trigger")
print("|".join([s["id"], str(s["ws_port"]), str(s["sources"][0]["udp_port"]), print("|".join([kind, s["id"], str(s["ws_port"]), str(s["sources"][0]["udp_port"]),
s["network"], s["oracle"], trig, checks])) s["network"], s["oracle"], trig, checks]))
elif kind == "direct":
print("|".join([kind, s["id"], s["cfg"], "", "", "", "", ""]))
elif kind == "recorder":
print("|".join([kind, s["id"], s["marte_cfg"], s["hub_cfg"], "", "", "", ""]))
elif kind == "debug":
print("|".join([kind, s["id"], s["cfg"], str(s["cmd_port"]), str(s["udp_port"]), str(s["log_port"]), "", ""]))
elif kind == "tcplogger":
print("|".join([kind, s["id"], s["cfg"], str(s["cmd_port"]), str(s["udp_port"]), str(s["log_port"]), "", ""]))
elif kind == "debug_pause_resume":
print("|".join([kind, s["id"], s["cfg"], str(s["cmd_port"]), str(s["udp_port"]), str(s["log_port"]), "", ""]))
PY PY
)" )"
if [ -z "${LIST}" ]; then echo "no scenarios selected"; exit 1; fi if [ -z "${LIST}" ]; then echo "no scenarios selected"; exit 1; fi
# run_scenario_matrix — runs the full scenario matrix (already computed into
# ${LIST}) against whatever binaries are currently built. Invoked once for the
# authoritative pass (normal binaries) and again, inside a subshell with
# OUT_DIR overridden, for the coverage-only re-run against instrumented
# binaries (see Phase 4 below). Running the coverage pass in a subshell means
# its SCEN_IDS/OUT_DIR/HUB_PID/APP_PID/trap mutations never leak back into the
# parent shell, so the primary pass's SCEN_IDS (consumed by the results.json
# aggregation step further down) is unaffected regardless of call order.
run_scenario_matrix() {
local RESULTS_SUFFIX="$1"
SCEN_IDS="" SCEN_IDS=""
HUB_PID=""; APP_PID="" HUB_PID=""; APP_PID=""
cleanup() { cleanup() {
@@ -120,12 +172,16 @@ cleanup() {
} }
trap cleanup EXIT trap cleanup EXIT
while IFS='|' read -r ID WSPORT UDPPORT NET ORACLE TRIG CHECKS; do while IFS='|' read -r KIND ID F2 F3 F4 F5 F6 F7; do
[ -z "${ID}" ] && continue [ -z "${ID}" ] && continue
SCEN_IDS="${SCEN_IDS} ${ID}" SCEN_IDS="${SCEN_IDS} ${ID}"
: > "${WORK}/status_${ID}.txt"
case "${KIND}" in
chain)
WSPORT="${F2}"; UDPPORT="${F3}"; NET="${F4}"; ORACLE="${F5}"; TRIG="${F6}"; CHECKS="${F7}"
echo "" echo ""
echo "══ scenario ${ID} (net=${NET} oracle=${ORACLE} ws=${WSPORT}) ══" echo "══ scenario ${ID} (net=${NET} oracle=${ORACLE} ws=${WSPORT}) ══"
: > "${WORK}/status_${ID}.txt"
# multicast route probe # multicast route probe
if [ "${NET}" = "multicast" ]; then if [ "${NET}" = "multicast" ]; then
@@ -191,10 +247,133 @@ while IFS='|' read -r ID WSPORT UDPPORT NET ORACLE TRIG CHECKS; do
echo "FAIL" > "${WORK}/status_${ID}.txt" echo "FAIL" > "${WORK}/status_${ID}.txt"
fi fi
${PY} "${SCRIPT_DIR}/plots.py" --scenario "${ID}" --dir "${WORK}" >/dev/null 2>&1 || true ${PY} "${SCRIPT_DIR}/plots.py" --scenario "${ID}" --dir "${WORK}" >/dev/null 2>&1 || true
;;
direct)
CFG="${F2}"
echo ""
echo "══ scenario ${ID} (kind=direct cfg=${CFG}) ══"
DS_DIR="${SCRIPT_DIR}/../datasources"
INPUT_BIN="/tmp/udpstreamer_test_input.bin"
# The FileWriterDS output path is baked into the cfg (not per-scenario);
# the last `Filename = "..."` in the file is always the writer (the
# FileReaderDS input path is always listed first in these cfgs).
OUTPUT_BIN="$(grep -oP 'Filename\s*=\s*"\K[^"]+' "${REPO_ROOT}/${CFG}" | tail -1)"
rm -f "${INPUT_BIN}" "${OUTPUT_BIN}"
(cd "${DS_DIR}" && ${PY} -c "import gen_test_data; gen_test_data.generate()") > "${OUT_DIR}/gen_${ID}.log" 2>&1
APP_LOG="${OUT_DIR}/marte_${ID}.log"
timeout 8 "${MARTE_APP}" -l RealTimeLoader -f "${REPO_ROOT}/${CFG}" -s Running > "${APP_LOG}" 2>&1 &
APP_PID=$!
sleep 5
cleanup
MSG="$(${PY} -c "
import sys
sys.path.insert(0, '${DS_DIR}')
import validate_binary as V
ok, msg, details = V.validate('${INPUT_BIN}', '${OUTPUT_BIN}', label='${ID}')
print(msg)
sys.exit(0 if ok else 1)
" 2>&1)" && STATUS=PASS || STATUS=FAIL
echo " ${MSG}"
echo "${STATUS}" > "${WORK}/status_${ID}.txt"
echo "${ID}: ${STATUS}"
;;
recorder)
RCFG_MARTE="${F2}"; RCFG_HUB="${F3}"
echo ""
echo "══ scenario ${ID} (kind=recorder marte_cfg=${RCFG_MARTE} hub_cfg=${RCFG_HUB}) ══"
DS_DIR="${SCRIPT_DIR}/../datasources"
INPUT_BIN="/tmp/udpstreamer_test_input.bin"
REC_DIR="/tmp/streamhub_rec_e2e"
rm -rf "${REC_DIR}"; mkdir -p "${REC_DIR}"
(cd "${DS_DIR}" && ${PY} -c "import gen_test_data; gen_test_data.generate()") > "${OUT_DIR}/gen_${ID}.log" 2>&1
HUB_LOG="${OUT_DIR}/hub_${ID}.log"
APP_LOG="${OUT_DIR}/marte_${ID}.log"
# Start StreamHub first so it is ready to receive the CONFIG packet.
"${STREAMHUB_EX}" -cfg "${REPO_ROOT}/${RCFG_HUB}" > "${HUB_LOG}" 2>&1 &
HUB_PID=$!
sleep 1
timeout 8 "${MARTE_APP}" -l RealTimeLoader -f "${REPO_ROOT}/${RCFG_MARTE}" -s Running > "${APP_LOG}" 2>&1 &
APP_PID=$!
# Let data flow, then stop the streamer and give the push/flush thread
# time to write the recorder file before killing the hub.
sleep 7
kill "${APP_PID}" 2>/dev/null; wait "${APP_PID}" 2>/dev/null; APP_PID=""
sleep 2
cleanup
# The recorder names files <sourceId>_<UTCstamp>_<seq>.bin; pick the newest.
REC_FILE="$(ls -t "${REC_DIR}"/*.bin 2>/dev/null | head -1)"
if [ -z "${REC_FILE}" ]; then
echo " FAIL: no recorder output file found in ${REC_DIR}"
echo "FAIL" > "${WORK}/status_${ID}.txt"
echo "${ID}: FAIL"
else
MSG="$(${PY} -c "
import sys
sys.path.insert(0, '${DS_DIR}')
import validate_binary as V
ok, msg, details = V.validate('${INPUT_BIN}', '${REC_FILE}', label='${ID}')
print(msg)
sys.exit(0 if ok else 1)
" 2>&1)" && STATUS=PASS || STATUS=FAIL
echo " ${MSG}"
echo "${STATUS}" > "${WORK}/status_${ID}.txt"
echo "${ID}: ${STATUS}"
fi
;;
debug|tcplogger|debug_pause_resume)
CFG="${F2}"; CMDPORT="${F3}"; UDPPORT2="${F4}"; LOGPORT="${F5}"
echo ""
echo "══ scenario ${ID} (kind=${KIND} cfg=${CFG}) ══"
timeout 15 "${MARTE_APP}" -l RealTimeLoader -f "${REPO_ROOT}/${CFG}" -s Running \
> "${OUT_DIR}/marte_${ID}.log" 2>&1 &
APP_PID=$!
sleep 1
"${DEBUGCLIENT}" -host 127.0.0.1 \
-cmdport "${CMDPORT}" -udpport "${UDPPORT2}" -logport "${LOGPORT}" \
-mode "${KIND}" -scenario "${ID}" -out "${WORK}" -dur 4s \
> "${OUT_DIR}/client_${ID}.log" 2>&1
CLIENT_RC=$?
kill "${APP_PID}" 2>/dev/null; wait "${APP_PID}" 2>/dev/null; APP_PID=""
if [ "${CLIENT_RC}" -eq 0 ]; then
echo "PASS" > "${WORK}/status_${ID}.txt"
else
echo "FAIL" > "${WORK}/status_${ID}.txt"
fi
echo "${ID}: $(cat "${WORK}/status_${ID}.txt")"
;;
*)
echo " SKIP: unknown scenario kind '${KIND}' for ${ID}"
echo "SKIP" > "${WORK}/status_${ID}.txt"
;;
esac
done <<< "${LIST}" done <<< "${LIST}"
trap - EXIT trap - EXIT
cleanup cleanup
}
run_scenario_matrix "primary"
# ── Stress (Phase 3: normal binaries, always uninstrumented) ────────────────
if [ "${SKIP_STRESS}" -eq 0 ]; then
echo ""
echo "── Stress matrix ──"
STRESS_OUT="${OUT_DIR}/stress"
mkdir -p "${STRESS_OUT}"
${PY} "${SCRIPT_DIR}/stress_run.py" --marte "${MARTE_APP}" --hub "${STREAMHUB_EX}" \
--client "${CLIENT}" --work "/tmp/chain_stress" --out "${STRESS_OUT}" || true
fi
# ── Aggregate results.json ─────────────────────────────────────────────────── # ── Aggregate results.json ───────────────────────────────────────────────────
# Scenarios carrying a `known_issue` marker exercise a documented, not-yet-fixed # Scenarios carrying a `known_issue` marker exercise a documented, not-yet-fixed
@@ -211,11 +390,13 @@ sys.path.insert(0, os.environ["SCRIPT_DIR"])
try: try:
from scenarios import SCENARIOS from scenarios import SCENARIOS
known = {s["id"]: s.get("known_issue") for s in SCENARIOS} known = {s["id"]: s.get("known_issue") for s in SCENARIOS}
kind_map = {s["id"]: s["kind"] for s in SCENARIOS}
except Exception: except Exception:
known = {} known = {}
kind_map = {}
results = [] results = []
for sid in ids: for sid in ids:
rec = {"id": sid} rec = {"id": sid, "kind": kind_map.get(sid, "chain")}
st = os.path.join(work, f"status_{sid}.txt") st = os.path.join(work, f"status_{sid}.txt")
raw = open(st).read().strip() if os.path.exists(st) else "UNKNOWN" raw = open(st).read().strip() if os.path.exists(st) else "UNKNOWN"
ki = known.get(sid) ki = known.get(sid)
@@ -252,16 +433,44 @@ echo "── Unit tests + coverage ──"
# restore a clean build so later --skip-build runs aren't left instrumented. # restore a clean build so later --skip-build runs aren't left instrumented.
CPP_COV_FLAG="" CPP_COV_FLAG=""
if [ "${CPP_COV}" -eq 1 ]; then if [ "${CPP_COV}" -eq 1 ]; then
echo " building instrumented (gcov) libraries + GTest ..." echo " building instrumented (gcov) libraries + apps + GTest ..."
COV_O="--coverage" COV_O="--coverage"
COV_L="-Wl,--no-as-needed -fPIC --coverage" COV_L="-Wl,--no-as-needed -fPIC --coverage"
make -C "${REPO_ROOT}" -f Makefile.gcc clean >/dev/null 2>&1 || true make -C "${REPO_ROOT}" -f Makefile.gcc clean >/dev/null 2>&1 || true
make -C "${REPO_ROOT}" -f Makefile.gcc core TARGET="${TARGET}" \ # `apps` (StreamHub.ex) must be rebuilt here too, not just `core`: the
# coverage-pass E2E re-run below launches StreamHub, and `make clean` just
# removed the non-instrumented StreamHub.ex — without this it would 404 the
# WS port for every chain/recorder scenario in the coverage pass.
make -C "${REPO_ROOT}" -f Makefile.gcc core apps TARGET="${TARGET}" \
OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1 OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1
for d in Test/Components/DataSources/UDPStreamer Test/Applications/StreamHub Test/GTest; do for d in Test/Components/DataSources/UDPStreamer Test/Components/DataSources/UDPStreamerClient Test/Applications/StreamHub Test/GTest Test/Integration; do
make -C "${REPO_ROOT}/${d}" -f Makefile.gcc TARGET="${TARGET}" \ make -C "${REPO_ROOT}/${d}" -f Makefile.gcc TARGET="${TARGET}" \
OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1 OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1
done done
# Coverage-only scenario re-run: the instrumented binaries above are only
# exercised so far by collect.py's unit-test binaries (MainGTest/Integration),
# which never touch the E2E-scenario-only code paths (e.g. StreamHub code
# only hit via the direct/recorder/debug E2E flows). Re-running the full
# scenario matrix here — against the SAME instrumented binaries, before
# collect.py's lcov capture — lets those .gcda files accumulate E2E-path
# coverage too. Run in a subshell with OUT_DIR *and* WORK overridden so the
# coverage pass's logs/results/perf-JSON/waveform-PNG scratch files land in
# discardable subdirectories and none of its SCEN_IDS/OUT_DIR/WORK/trap
# state leaks back into this shell (the authoritative results.json was
# already written above, from the primary pass). WORK must be isolated too,
# not just OUT_DIR: run_scenario_matrix writes perf_*/wave_*.png/metrics_*
# under WORK, and report_build.py reads those files straight from WORK
# after this pass — without isolation the coverage-instrumented re-run
# would silently clobber the primary pass's perf/waveform data.
echo " re-running scenario matrix under instrumented binaries (coverage pass) ..."
(
OUT_DIR="${OUT_DIR}/coverage_pass"
WORK="${WORK}/coverage_pass"
mkdir -p "${OUT_DIR}" "${WORK}"
run_scenario_matrix "coverage"
) || true
CPP_COV_FLAG="--cpp-coverage" CPP_COV_FLAG="--cpp-coverage"
fi fi
@@ -271,24 +480,13 @@ ${PY} "${SCRIPT_DIR}/collect.py" --repo "${REPO_ROOT}" --target "${TARGET}" \
if [ "${CPP_COV}" -eq 1 ]; then if [ "${CPP_COV}" -eq 1 ]; then
echo " restoring non-instrumented build ..." echo " restoring non-instrumented build ..."
make -C "${REPO_ROOT}" -f Makefile.gcc clean >/dev/null 2>&1 || true make -C "${REPO_ROOT}" -f Makefile.gcc clean >/dev/null 2>&1 || true
make -C "${REPO_ROOT}" -f Makefile.gcc core apps TARGET="${TARGET}" 2>&1 | tail -1 # `clean` also wipes Test/GTest, Test/Integration and Test/Components/* (see
# the root Makefile.gcc `clean` target), so `test` must be rebuilt here too,
# not just `core apps` — otherwise MainGTest.ex/IntegrationTests.ex are left
# deleted (instrumented-only) after every --cpp-coverage run.
make -C "${REPO_ROOT}" -f Makefile.gcc core apps test TARGET="${TARGET}" 2>&1 | tail -1
(cd "${SCRIPT_DIR}/client" && go build -o chain-client . >/dev/null 2>&1) || true (cd "${SCRIPT_DIR}/client" && go build -o chain-client . >/dev/null 2>&1) || true
fi (cd "${SCRIPT_DIR}/debugclient" && go build -o debugclient . >/dev/null 2>&1) || true
# ── Stress matrix (opt-in) ───────────────────────────────────────────────────
# Capacity sibling of the correctness phase: sweep one load axis at a time and
# gate survival/liveness (hard) + RSS/zoom-p95 (soft). Writes stress_results.json
# into OUT_DIR/stress, which report_build.py folds into the PDF when present.
STRESS_OUT="${OUT_DIR}/stress"
if [ "${STRESS}" -eq 1 ]; then
echo ""
echo "── Stress matrix ──"
mkdir -p "${STRESS_OUT}"
${PY} "${SCRIPT_DIR}/stress.py" >/dev/null || { echo "stress matrix invalid" >&2; exit 1; }
${PY} "${SCRIPT_DIR}/stress_run.py" \
--marte "${MARTE_APP}" --hub "${STREAMHUB_EX}" --client "${CLIENT}" \
--work "${WORK}" --out "${STRESS_OUT}" \
|| { echo "WARN: stress_run.py failed, continuing" >&2; true; }
fi fi
# ── Consolidated report data (+ history/regression + trend plots) ──────────── # ── Consolidated report data (+ history/regression + trend plots) ────────────
@@ -8,7 +8,7 @@
# It sweeps one load axis at a time (signal size/count, subscriber fan-out, source # It sweeps one load axis at a time (signal size/count, subscriber fan-out, source
# count, WS-client count, zoom request rate — see stress.py) and gates each case on # count, WS-client count, zoom request rate — see stress.py) and gates each case on
# survival + liveness (hard) and RSS + zoom-p95 latency (soft). This is the # survival + liveness (hard) and RSS + zoom-p95 latency (soft). This is the
# capacity sibling of run_chain_e2e.sh (which gates waveform correctness). # capacity sibling of run_e2e.sh (which gates waveform correctness).
# #
# Usage: ./run_stress.sh [--skip-build] [--only <id>] [--axis <axis>] # Usage: ./run_stress.sh [--skip-build] [--only <id>] [--axis <axis>]
set -u set -u
@@ -135,6 +135,22 @@ def _sig(name, type, elements=1, time_mode="PacketTime", time_signal=None,
def validate_scenario(s): def validate_scenario(s):
"""Return a list of validity error strings (empty == valid).""" """Return a list of validity error strings (empty == valid)."""
errs = [] errs = []
kind = s.get("kind", "chain")
if kind == "direct":
if "cfg" not in s:
errs.append(f"direct scenario {s.get('id')} missing cfg")
return errs
if kind == "recorder":
if "hub_cfg" not in s or "marte_cfg" not in s:
errs.append(f"recorder scenario {s.get('id')} missing hub_cfg/marte_cfg")
return errs
if kind in ("debug", "tcplogger", "debug_pause_resume"):
if not all(k in s for k in ("cfg", "cmd_port", "udp_port", "log_port")):
errs.append(f"{kind} scenario {s.get('id')} missing cfg/cmd_port/udp_port/log_port")
return errs
if kind != "chain":
errs.append(f"unknown scenario kind: {kind}")
return errs
row_dt, num_rows, _producer_hz, loop_hz = geometry(s) row_dt, num_rows, _producer_hz, loop_hz = geometry(s)
if s.get("network") not in ("unicast", "multicast"): if s.get("network") not in ("unicast", "multicast"):
errs.append("network must be unicast|multicast") errs.append("network must be unicast|multicast")
@@ -565,6 +581,84 @@ SCENARIOS = (_STARTERS + _TYPES + _ARRAYS + _TIMEMODES + _QUANT + _PUBLISH +
_PAYLOAD + _MCAST + _MULTISRC + _INTERACT + _TRIGGER + _MISC + _PAYLOAD + _MCAST + _MULTISRC + _INTERACT + _TRIGGER + _MISC +
_HIGHRATE) _HIGHRATE)
for _s in SCENARIOS:
_s.setdefault("kind", "chain")
# ── Non-chain scenario kinds ──────────────────────────────────────────────────
# "direct" and "recorder" scenarios exercise the other two data paths described
# in ARCHITECTURE.md (direct UDPStreamer<->UDPStreamerClient, and StreamHub's
# BinaryRecorder disk sink) and intentionally do not carry the chain-only keys
# (sources/network/oracle/...): they have their own orchestration in run_e2e.sh.
_DIRECT = [
{
"id": "s52_direct_unicast",
"desc": "Direct UDPStreamer->UDPStreamerClient round-trip, unicast",
"kind": "direct",
"cfg": "Test/E2E/datasources/E2ETest.cfg",
"client_checks": [],
"known_issue": None,
},
{
"id": "s53_direct_multicast",
"desc": "Direct UDPStreamer->UDPStreamerClient round-trip, multicast",
"kind": "direct",
"cfg": "Test/E2E/datasources/E2EMulticastTest.cfg",
"client_checks": [],
"known_issue": None,
},
]
_RECORDER = [
{
"id": "s54_recorder",
"desc": "StreamHub BinaryRecorder disk-output round-trip",
"kind": "recorder",
"hub_cfg": "Test/E2E/recorder/StreamHubRec.cfg",
"marte_cfg": "Test/E2E/recorder/RecorderStreamer.cfg",
"client_checks": [],
"known_issue": None,
},
]
_DEBUG = [
{
"id": "s55_debug_force_trace_break",
"desc": "DebugService FORCE/TRACE/BREAK over real TCP 8080 + UDP 8081",
"kind": "debug",
"cfg": "Test/E2E/suite/debug_e2e.cfg",
"cmd_port": 8080, "udp_port": 8081, "log_port": 9090,
"client_checks": [],
"known_issue": None,
},
]
_TCPLOGGER = [
{
"id": "s56_tcplogger_delivery",
"desc": "TCPLogger delivers a log line for a triggered DebugService event",
"kind": "tcplogger",
"cfg": "Test/E2E/suite/debug_e2e.cfg",
"cmd_port": 8080, "udp_port": 8081, "log_port": 9090,
"client_checks": [],
"known_issue": None,
},
]
_DEBUG_PAUSE_RESUME = [
{
"id": "s57_debug_pause_resume",
"desc": "DebugService PAUSE/RESUME halts and resumes the RT loop, "
"verified via live VALUE polling (not just command acks)",
"kind": "debug_pause_resume",
"cfg": "Test/E2E/suite/debug_e2e.cfg",
"cmd_port": 8080, "udp_port": 8081, "log_port": 9090,
"client_checks": [],
"known_issue": None,
},
]
SCENARIOS = SCENARIOS + _DIRECT + _RECORDER + _DEBUG + _TCPLOGGER + _DEBUG_PAUSE_RESUME
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
@@ -576,6 +670,7 @@ if __name__ == "__main__":
if s["id"] in seen_ids: if s["id"] in seen_ids:
errs.append("duplicate id") errs.append("duplicate id")
seen_ids.add(s["id"]) seen_ids.add(s["id"])
if s["kind"] == "chain":
if s["ws_port"] in seen_ws: if s["ws_port"] in seen_ws:
errs.append(f"duplicate ws_port {s['ws_port']}") errs.append(f"duplicate ws_port {s['ws_port']}")
seen_ws.add(s["ws_port"]) seen_ws.add(s["ws_port"])
@@ -2,7 +2,7 @@
""" """
stress_run.py Orchestrator for the streaming-chain stress matrix (stress.py). stress_run.py Orchestrator for the streaming-chain stress matrix (stress.py).
Where run_chain_e2e.sh drives scenarios.py for *correctness*, this drives Where run_e2e.sh drives scenarios.py for *correctness*, this drives
STRESS_CASES for *capacity*. Per case it: STRESS_CASES for *capacity*. Per case it:
1. generates the FileReader input + MARTe app cfg + 1..M StreamHub cfgs 1. generates the FileReader input + MARTe app cfg + 1..M StreamHub cfgs
@@ -58,6 +58,45 @@ class TestScenarios(unittest.TestCase):
errs = S.validate_scenario(s) errs = S.validate_scenario(s)
self.assertTrue(any("quant only on float" in e for e in errs), errs) self.assertTrue(any("quant only on float" in e for e in errs), errs)
def test_all_scenarios_have_kind(self):
for s in S.SCENARIOS:
self.assertIn("kind", s, f"{s['id']} missing kind")
self.assertIn(s["kind"], ("chain", "direct", "recorder", "debug", "tcplogger", "debug_pause_resume"))
def test_direct_and_recorder_scenarios_present(self):
kinds = {s["kind"] for s in S.SCENARIOS}
self.assertIn("direct", kinds)
self.assertIn("recorder", kinds)
direct_ids = {s["id"] for s in S.SCENARIOS if s["kind"] == "direct"}
self.assertEqual(direct_ids, {"s52_direct_unicast", "s53_direct_multicast"})
recorder_ids = {s["id"] for s in S.SCENARIOS if s["kind"] == "recorder"}
self.assertEqual(recorder_ids, {"s54_recorder"})
def test_validate_scenario_accepts_all_kinds(self):
for s in S.SCENARIOS:
S.validate_scenario(s) # must not raise
def test_debug_and_tcplogger_scenarios_present(self):
kinds = {s["kind"] for s in S.SCENARIOS}
self.assertIn("debug", kinds)
self.assertIn("tcplogger", kinds)
debug_ids = {s["id"] for s in S.SCENARIOS if s["kind"] == "debug"}
self.assertEqual(debug_ids, {"s55_debug_force_trace_break"})
tcplogger_ids = {s["id"] for s in S.SCENARIOS if s["kind"] == "tcplogger"}
self.assertEqual(tcplogger_ids, {"s56_tcplogger_delivery"})
def test_build_by_kind_filters_correctly(self):
import report_build as R
results = {"scenarios": [
{"id": "a", "kind": "direct", "status": "PASS"},
{"id": "b", "kind": "chain", "status": "PASS"},
{"id": "c", "kind": "direct", "status": "FAIL"},
]}
d = R.build_by_kind(results, "direct")
self.assertEqual(d["n_pass"], 1)
self.assertEqual(d["n_fail"], 1)
self.assertEqual(d["n_total"], 2)
class TestGenData(unittest.TestCase): class TestGenData(unittest.TestCase):
def test_ground_truth_shapes(self): def test_ground_truth_shapes(self):
@@ -21,6 +21,14 @@ Oracle (per signal)
phase offset automatically). nRMSE tolerance is relaxed by the quant step. phase offset automatically). nRMSE tolerance is relaxed by the quant step.
* **Fed reference** (when ``--tap`` given): each received value must be within * **Fed reference** (when ``--tap`` given): each received value must be within
``tol`` of some tap value too. ``tol`` of some tap value too.
* **Continuity** (always, 10 points): a stream that stalls (client falling
behind, hub failing to flush a window, ...) can still pass fidelity
whatever few samples *did* arrive still match the ground truth while the
plot shows gaping holes. Flags any inter-sample gaps that are >10x the
median spacing and fails when their *summed* duration exceeds 5% of the
capture span. Calibrated against the full scenario matrix: healthy streams
(bursty per-tick live pushes, decimation, fragmentation, multicast, ...) top
out at 0.7% outlier-gap time; a stalled stream showed 55-91%.
""" """
import argparse import argparse
import json import json
@@ -122,6 +130,29 @@ def nearest_err(recv_v, truth_v):
return float(np.max(d)) if d.size else 0.0 return float(np.max(d)) if d.size else 0.0
def gap_check(t_recv, outlier_mult=10.0, max_outlier_frac=0.05):
"""Detect large discontiguous holes in a received time series.
A handful of gaps a few times the median spacing are normal (bursty
per-tick live pushes, decimation, LTTB). Returns (ok, gap_frac, n_gaps,
max_gap): ``gap_frac`` is the fraction of the total capture span consumed
by gaps larger than ``outlier_mult`` times the median inter-sample gap;
when that adds up to more than ``max_outlier_frac`` of the whole capture,
the stream stalled/dropped a chunk rather than merely being decimated.
"""
if t_recv.size < 10:
return True, 0.0, 0, 0.0
t = np.sort(t_recv.astype(np.float64))
dt = np.diff(t)
span = float(t[-1] - t[0])
med = float(np.median(dt))
if span <= 0.0 or med <= 0.0:
return True, 0.0, 0, 0.0
outliers = dt[dt > outlier_mult * med]
gap_frac = float(outliers.sum() / span)
return gap_frac <= max_outlier_frac, gap_frac, int(outliers.size), float(dt.max())
def sine_shape(t, v, freq): def sine_shape(t, v, freq):
"""Return (corr, nrmse, amp_fit) for a sinusoid fit at ``freq``.""" """Return (corr, nrmse, amp_fit) for a sinusoid fit at ``freq``."""
w = 2.0 * np.pi * freq w = 2.0 * np.pi * freq
@@ -135,6 +166,28 @@ def sine_shape(t, v, freq):
return corr, nrmse, amp return corr, nrmse, amp
def best_sine_shape(t, v, freq_nominal, band=0.05, n=41):
"""Refine ``freq_nominal`` within +/-``band`` (fractional) before fitting.
The gross-sanity gate assumes the nominal configured frequency, but
MARTe2's LinuxTimer RT loop runs at a small, systematic offset from true
wall-clock time (a few percent at most), which accumulates into visible
phase drift over a multi-second capture even though every sample value is
bit-correct. A coarse search for the actual best-fit frequency near the
nominal value absorbs that clock-rate skew while still rejecting a
genuinely wrong-frequency or corrupted signal, which collapses correlation
regardless of the search window. Returns (corr, nrmse, amp, freq_used).
"""
candidates = np.linspace(freq_nominal * (1.0 - band),
freq_nominal * (1.0 + band), n)
best = None
for f in candidates:
corr, nrmse, amp = sine_shape(t, v, f)
if best is None or corr > best[0]:
best = (corr, nrmse, amp, float(f))
return best
def compare_signal(gt, t_recv, v_recv, tap_v=None): def compare_signal(gt, t_recv, v_recv, tap_v=None):
tol, step = _tol(gt) tol, step = _tol(gt)
truth_v = gt["v"].astype(np.float64) truth_v = gt["v"].astype(np.float64)
@@ -153,9 +206,24 @@ def compare_signal(gt, t_recv, v_recv, tap_v=None):
fidelity_ok = max_err <= tol fidelity_ok = max_err <= tol
m["fidelity_ok"] = bool(fidelity_ok) m["fidelity_ok"] = bool(fidelity_ok)
gap_ok, gap_frac, n_gaps, max_gap = gap_check(t_recv)
m.update(gap_ok=bool(gap_ok), gap_frac=round(gap_frac, 4),
n_gaps=n_gaps, max_gap=max_gap)
if not gap_ok:
m["reason"] = (f"data hole: {gap_frac:.1%} of capture span in "
f"{n_gaps} gaps >10x median spacing (max={max_gap:.4g}s)")
shape_ok = True shape_ok = True
if gt["formula"] == "sine" and v_recv.size >= 8 and gt["freq"]: if gt["formula"] == "sine" and v_recv.size >= 8 and gt["freq"]:
corr, nrmse, amp = sine_shape(t_recv, v_recv, gt["freq"]) # Refine the fit frequency within +/-5% of nominal before scoring:
# MARTe2's LinuxTimer RT loop runs at a small, systematic offset from
# true wall-clock time (a few percent), which accumulates into
# visible phase drift over a multi-second capture even though every
# sample value is bit-correct (see best_sine_shape docstring). This
# keeps the gate a *gross frequency-sanity* check — a wrong-frequency
# or corrupted signal still collapses corr regardless of the search
# window — while absorbing legitimate clock-rate skew.
corr, nrmse, amp, freq_fit = best_sine_shape(t_recv, v_recv, gt["freq"])
# Shape is a *gross frequency-sanity gate* plus a *tracked quality # Shape is a *gross frequency-sanity gate* plus a *tracked quality
# metric*, not a tight correctness gate. Signal values are bit-faithful # metric*, not a tight correctness gate. Signal values are bit-faithful
# (the fidelity oracle proves that); the gap from a perfect fit is # (the fidelity oracle proves that); the gap from a perfect fit is
@@ -170,7 +238,7 @@ def compare_signal(gt, t_recv, v_recv, tap_v=None):
nrmse_tol = 0.30 + (step / (gt["range_max"] - gt["range_min"]) nrmse_tol = 0.30 + (step / (gt["range_max"] - gt["range_min"])
if gt["quant"] != "none" else 0.0) if gt["quant"] != "none" else 0.0)
shape_ok = corr >= 0.5 and nrmse <= nrmse_tol shape_ok = corr >= 0.5 and nrmse <= nrmse_tol
m.update(corr=corr, nrmse=nrmse, amp_fit=amp, m.update(corr=corr, nrmse=nrmse, amp_fit=amp, freq_fit=freq_fit,
nrmse_tol=nrmse_tol, shape_ok=bool(shape_ok), nrmse_tol=nrmse_tol, shape_ok=bool(shape_ok),
shape_gate="gross") shape_gate="gross")
@@ -180,7 +248,7 @@ def compare_signal(gt, t_recv, v_recv, tap_v=None):
fed_ok = fed_err <= tol fed_ok = fed_err <= tol
m.update(fed_err=fed_err, fed_ok=bool(fed_ok)) m.update(fed_err=fed_err, fed_ok=bool(fed_ok))
m["pass"] = bool(fidelity_ok and shape_ok and fed_ok) m["pass"] = bool(fidelity_ok and shape_ok and fed_ok and gap_ok)
return m return m
+212
View File
@@ -0,0 +1,212 @@
/**
* @file DebugServiceGTest.cpp
* @brief Unit tests for DebugService header-only core components:
* TraceRingBuffer, DebugSignalInfo struct, BreakOp enum.
*
* These tests exercise self-contained logic from DebugCore.h without
* requiring a running MARTe2 application or linking DebugServiceBase.cpp.
* ProcessSignal/HandleCommand/RegisterSignal are covered by the
* DebugService integration tests in Test/Integration/.
*/
#include "DebugCore.h"
#include "gtest/gtest.h"
using namespace MARTe;
/* ═════════════════════════════════════════════════════════════════════════
TraceRingBuffer tests (DebugCore.h / HI-9 atomic fix validation)
*/
class TraceRingBufferTest : public ::testing::Test {
protected:
void SetUp() { buf = new TraceRingBuffer(); }
void TearDown() { delete buf; }
TraceRingBuffer *buf;
};
TEST_F(TraceRingBufferTest, Init_ValidSize) {
ASSERT_TRUE(buf->Init(1024));
EXPECT_EQ(buf->Count(), 0u);
}
TEST_F(TraceRingBufferTest, Init_TwiceReplacesBuffer) {
ASSERT_TRUE(buf->Init(256));
EXPECT_TRUE(buf->Init(512));
EXPECT_EQ(buf->Count(), 0u);
}
TEST_F(TraceRingBufferTest, PushPop_SingleEntryRoundtrip) {
ASSERT_TRUE(buf->Init(256));
uint8 data[8] = {0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22, 0x33, 0x44};
ASSERT_TRUE(buf->Push(42, 0xDEADBEEFDEADBEEFULL, data, 8));
uint32 id = 0;
uint64 ts = 0;
uint8 out[8] = {};
uint32 sz = 0;
ASSERT_TRUE(buf->Pop(id, ts, out, sz, 16));
EXPECT_EQ(id, 42u);
EXPECT_EQ(ts, 0xDEADBEEFDEADBEEFULL);
EXPECT_EQ(sz, 8u);
EXPECT_EQ(memcmp(data, out, 8), 0);
}
TEST_F(TraceRingBufferTest, Pop_EmptyBufferReturnsFalse) {
ASSERT_TRUE(buf->Init(256));
uint32 id = 0; uint64 ts = 0; uint8 out[1] = {}; uint32 sz = 0;
EXPECT_FALSE(buf->Pop(id, ts, out, sz, 16));
}
TEST_F(TraceRingBufferTest, Push_FullBufferReturnsFalse) {
/* 32-byte buffer: entry = 4+8+4+10 = 26 bytes. Fits 1, not 2. */
ASSERT_TRUE(buf->Init(32));
uint8 data[10] = {};
ASSERT_TRUE(buf->Push(1, 1, data, 10));
EXPECT_FALSE(buf->Push(2, 2, data, 10));
}
TEST_F(TraceRingBufferTest, CountAfterMultiplePushes) {
ASSERT_TRUE(buf->Init(256));
uint8 data[4] = {};
const uint32 entrySize = 4 + 8 + 4 + 4;
for (int i = 0; i < 5; i++) {
ASSERT_TRUE(buf->Push(static_cast<uint32>(i), 100 + i, data, 4));
}
EXPECT_EQ(buf->Count(), entrySize * 5u);
}
TEST_F(TraceRingBufferTest, PushPop_Wraparound) {
/* 64-byte buffer: entry=24 bytes (4+8+4+8). Fits 2 entries. */
ASSERT_TRUE(buf->Init(64));
uint8 data[8] = {};
ASSERT_TRUE(buf->Push(1, 100, data, 8));
ASSERT_TRUE(buf->Push(2, 200, data, 8));
uint32 id = 0; uint64 ts = 0; uint8 out[8] = {}; uint32 sz = 0;
ASSERT_TRUE(buf->Pop(id, ts, out, sz, 16));
EXPECT_EQ(id, 1u);
/* Push a third entry causing wraparound */
ASSERT_TRUE(buf->Push(3, 300, data, 8));
ASSERT_TRUE(buf->Pop(id, ts, out, sz, 16));
EXPECT_EQ(id, 2u);
ASSERT_TRUE(buf->Pop(id, ts, out, sz, 16));
EXPECT_EQ(id, 3u);
EXPECT_FALSE(buf->Pop(id, ts, out, sz, 16));
}
TEST_F(TraceRingBufferTest, Pop_SkipOversizedEntry) {
/* When entry size > maxSize, Pop skips it and returns false.
* The caller must loop: the next Pop call delivers the subsequent entry. */
ASSERT_TRUE(buf->Init(512));
uint8 smallData[4] = {1, 2, 3, 4};
uint8 bigData[128] = {};
ASSERT_TRUE(buf->Push(1, 100, bigData, 128));
ASSERT_TRUE(buf->Push(2, 200, smallData, 4));
uint32 id = 0; uint64 ts = 0; uint8 out[4] = {}; uint32 sz = 0;
/* First Pop: skip oversized entry */
EXPECT_FALSE(buf->Pop(id, ts, out, sz, 16));
/* Second Pop: deliver small entry */
ASSERT_TRUE(buf->Pop(id, ts, out, sz, 16));
EXPECT_EQ(id, 2u);
EXPECT_EQ(sz, 4u);
}
TEST_F(TraceRingBufferTest, Pop_SkipOversized_EmptyAfterSkip) {
/* If the last entry is oversized and skipped, Pop returns false. */
ASSERT_TRUE(buf->Init(256));
uint8 bigData[128] = {};
ASSERT_TRUE(buf->Push(1, 100, bigData, 128));
uint32 id = 0; uint64 ts = 0; uint8 out[1] = {}; uint32 sz = 0;
EXPECT_FALSE(buf->Pop(id, ts, out, sz, 16));
}
TEST_F(TraceRingBufferTest, Push_LargePayloadFits) {
/* Buffer just big enough for one entry with 200 data bytes. */
ASSERT_TRUE(buf->Init(256));
uint8 bigData[200] = {};
uint32 entryBytes = 4 + 8 + 4 + 200; // 216
ASSERT_LE(entryBytes, 255u); /* fits with 1-byte ring gap */
ASSERT_TRUE(buf->Push(1, 100, bigData, 200));
uint32 id = 0; uint64 ts = 0;
uint8 out[200] = {};
uint32 sz = 0;
ASSERT_TRUE(buf->Pop(id, ts, out, sz, 256));
EXPECT_EQ(id, 1u);
EXPECT_EQ(sz, 200u);
}
TEST_F(TraceRingBufferTest, Push_ZeroSizeData) {
ASSERT_TRUE(buf->Init(64));
ASSERT_TRUE(buf->Push(1, 100, NULL_PTR(void *), 0));
uint32 id = 0; uint64 ts = 0; uint32 sz = 0;
ASSERT_TRUE(buf->Pop(id, ts, NULL_PTR(void *), sz, 16));
EXPECT_EQ(sz, 0u);
}
TEST_F(TraceRingBufferTest, DestructorDoesNotLeak) {
TraceRingBuffer *b = new TraceRingBuffer();
b->Init(1024);
delete b;
SUCCEED();
}
TEST_F(TraceRingBufferTest, ThreadSafety_SingleThreadSPSC) {
/* Single-threaded SPSC: Push then Pop in same thread. The HI-9 atomic
* fix uses __atomic_load_n/__atomic_store_n with acquire/release ordering.
* In a single thread these are equivalent to regular loads/stores. */
ASSERT_TRUE(buf->Init(2048)); /* room for 50 entries of 20 bytes each */
for (int i = 0; i < 50; i++) {
uint8 data[4] = {};
ASSERT_TRUE(buf->Push(static_cast<uint32>(i), 1000 + i, data, 4));
}
for (int i = 0; i < 50; i++) {
uint32 id = 0; uint64 ts = 0; uint8 out[4] = {}; uint32 sz = 0;
ASSERT_TRUE(buf->Pop(id, ts, out, sz, 16));
EXPECT_EQ(id, static_cast<uint32>(i));
}
/* Buffer should now be empty */
uint32 id = 0; uint64 ts = 0; uint32 sz = 0;
EXPECT_FALSE(buf->Pop(id, ts, NULL_PTR(void *), sz, 16));
}
/* ═════════════════════════════════════════════════════════════════════════
DebugSignalInfo struct layout tests
*/
TEST(DebugSignalInfoTest, ForcedValueSizeMatchesSpec) {
EXPECT_EQ(sizeof(((DebugSignalInfo *)0)->forcedValue), 1024u);
}
TEST(DebugSignalInfoTest, ForcedMaskSupports256Elements) {
/* forcedMask is 32 bytes = 256 bits, supporting up to 256 elements. */
EXPECT_EQ(sizeof(((DebugSignalInfo *)0)->forcedMask), 32u);
EXPECT_EQ(sizeof(((DebugSignalInfo *)0)->forcedMask) * 8u, 256u);
}
TEST(DebugSignalInfoTest, DefaultBreakOpIsOff) {
/* The struct default-initialises with breakOp cleared to BREAK_OFF (0).
* We cannot memset because StreamString is non-POD; verify with sizeof.
* The RegisterSignal code in DebugServiceBase.cpp explicit sets breakOp=0. */
EXPECT_EQ(BREAK_OFF, 0);
}
/* ═════════════════════════════════════════════════════════════════════════
BreakOp enum tests
*/
TEST(BreakOpTest, ValuesMatchSpec) {
EXPECT_EQ(BREAK_OFF, 0);
EXPECT_EQ(BREAK_GT, 1);
EXPECT_EQ(BREAK_LT, 2);
EXPECT_EQ(BREAK_EQ, 3);
EXPECT_EQ(BREAK_GEQ, 4);
EXPECT_EQ(BREAK_LEQ, 5);
EXPECT_EQ(BREAK_NEQ, 6);
}
+2
View File
@@ -48,6 +48,8 @@ INCLUDES += -I$(ROOT_DIR)/Source/Components/Interfaces/DebugService
INCLUDES += -I$(ROOT_DIR)/Source/Components/Interfaces/TCPLogger INCLUDES += -I$(ROOT_DIR)/Source/Components/Interfaces/TCPLogger
INCLUDES += -I$(ROOT_DIR)/Test/Components/DataSources/UDPStreamer INCLUDES += -I$(ROOT_DIR)/Test/Components/DataSources/UDPStreamer
OBJSX = DebugServiceGTest.x
all: $(BUILD_DIR)/MainGTest$(EXEEXT) all: $(BUILD_DIR)/MainGTest$(EXEEXT)
include depends.$(TARGET) include depends.$(TARGET)
+197
View File
@@ -0,0 +1,197 @@
../../Build/x86-linux//GTest/DebugServiceGTest.o: DebugServiceGTest.cpp \
../../Source/Components/Interfaces/DebugService/DebugCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
../../Build/x86-linux//GTest/MainGTest.o: MainGTest.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
+197
View File
@@ -0,0 +1,197 @@
DebugServiceGTest.o: DebugServiceGTest.cpp \
../../Source/Components/Interfaces/DebugService/DebugCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
MainGTest.o: MainGTest.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-port.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-message.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-string.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-death-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-param-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-printers.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_prod.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-test-part.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest-typed-test.h \
/home/martino/workspace/MARTe2/Lib/gtest-1.7.0/include/gtest/gtest_pred_impl.h
+680
View File
@@ -0,0 +1,680 @@
#include "DebugService.h"
#include "GlobalObjectsDatabase.h"
#include "ObjectRegistryDatabase.h"
#include "RealTimeApplication.h"
#include "StandardParser.h"
#include "StreamString.h"
#include "StringHelper.h"
#include "TestCommon.h"
#include <stdio.h>
using namespace MARTe;
namespace {
const char8 * const debug_commands_config =
"DebugService = {"
" Class = DebugService "
" ControlPort = 8120 "
" UdpPort = 8121 "
" StreamIP = \"127.0.0.1\" "
"}"
"App = {"
" Class = RealTimeApplication "
" +Functions = {"
" Class = ReferenceContainer "
" +GAM1 = {"
" Class = IOGAM "
" InputSignals = {"
" Counter = { DataSource = Timer Type = uint32 Frequency = 1000 }"
" Time = { DataSource = Timer Type = uint32 }"
" }"
" OutputSignals = {"
" Counter = { DataSource = DDB Type = uint32 }"
" Time = { DataSource = DDB Type = uint32 }"
" }"
" }"
" }"
" +Data = {"
" Class = ReferenceContainer "
" DefaultDataSource = DDB "
" +Timer = { Class = LinuxTimer SleepTime = 1000 Signals = { Counter = { Type = uint32 } Time = { Type = uint32 } } }"
" +DDB = { Class = GAMDataSource Signals = { Counter = { Type = uint32 } Time = { Type = uint32 } } }"
" +DAMS = { Class = TimingDataSource }"
" }"
" +States = {"
" Class = ReferenceContainer "
" +State1 = { Class = RealTimeState +Threads = { Class = ReferenceContainer +Thread1 = { Class = RealTimeThread Functions = {GAM1} } } }"
" }"
" +Scheduler = { Class = GAMScheduler TimingDataSource = DAMS }"
"}";
const uint16 CONTROL_PORT = 8120u;
const char8 * const SIGNAL_NAME = "App.Data.DDB.Counter";
// Pulls the value out of a `{"Name":...,"Value":"<v>", ...}` VALUE reply.
// The command replies are fixed-format enough that a plain substring scan
// is sufficient (no need for a full JSON parser in these integration tests).
bool ExtractValueStr(const char8 *reply, StreamString &val) {
const char8 *key = "\"Value\":\"";
const char8 *p = StringHelper::SearchString(reply, key);
if (p == NULL_PTR(const char8 *)) return false;
p += StringHelper::Length(key);
const char8 *end = StringHelper::SearchString(p, "\"");
if (end == NULL_PTR(const char8 *)) return false;
val = "";
while (p < end) {
val += *p;
p++;
}
return true;
}
bool ExtractValueUint32(const char8 *reply, uint32 &val) {
StreamString s;
if (!ExtractValueStr(reply, s)) return false;
const char8 *p = s.Buffer();
if (p == NULL_PTR(const char8 *) || *p == '\0') return false;
val = 0u;
while (*p != '\0') {
if (*p < '0' || *p > '9') return false;
val = (val * 10u) + (uint32)(*p - '0');
p++;
}
return true;
}
bool QueryValueUint32(uint32 &val) {
StreamString reply;
if (!SendCommandGAM(CONTROL_PORT, "VALUE App.Data.DDB.Counter\n", reply))
return false;
return ExtractValueUint32(reply.Buffer(), val);
}
} // namespace
void TestDebugCommands() {
printf("--- Test: FORCE/UNFORCE/BREAK/STEP/STEP_STATUS/VALUE/LS Commands ---\n");
ObjectRegistryDatabase::Instance()->Purge();
ConfigurationDatabase cdb;
StreamString ss = debug_commands_config;
ss.Seek(0);
StandardParser parser(ss, cdb);
if (!parser.Parse()) {
printf("ERROR: Failed to parse config\n");
return;
}
cdb.MoveToRoot();
uint32 n = cdb.GetNumberOfChildren();
for (uint32 i = 0; i < n; i++) {
const char8 *name = cdb.GetChildName(i);
ConfigurationDatabase child;
cdb.MoveRelative(name);
cdb.Copy(child);
cdb.MoveToAncestor(1u);
StreamString className;
child.Read("Class", className);
Reference ref(className.Buffer(),
GlobalObjectsDatabase::Instance()->GetStandardHeap());
if (!ref.IsValid()) {
printf("ERROR: Could not create object %s of class %s\n", name,
className.Buffer());
continue;
}
ref->SetName(name);
if (!ref->Initialise(child)) {
printf("ERROR: Failed to initialise object %s\n", name);
continue;
}
ObjectRegistryDatabase::Instance()->Insert(ref);
}
ReferenceT<DebugService> service =
ObjectRegistryDatabase::Instance()->Find("DebugService");
if (!service.IsValid()) {
printf("ERROR: DebugService not found\n");
return;
}
service->SetFullConfig(cdb);
ReferenceT<RealTimeApplication> app =
ObjectRegistryDatabase::Instance()->Find("App");
if (!app.IsValid()) {
printf("ERROR: App not found\n");
return;
}
if (!app->ConfigureApplication()) {
printf("ERROR: ConfigureApplication failed.\n");
return;
}
if (app->PrepareNextState("State1") != ErrorManagement::NoError) {
printf("ERROR: PrepareNextState failed.\n");
return;
}
if (app->StartNextStateExecution() != ErrorManagement::NoError) {
printf("ERROR: StartNextStateExecution failed.\n");
return;
}
printf("Application started.\n");
Sleep::MSec(1000);
// Step 1: VALUE baseline.
printf("\n--- Step 1: VALUE ---\n");
{
StreamString reply;
if (SendCommandGAM(CONTROL_PORT, "VALUE App.Data.DDB.Counter\n", reply)) {
printf("VALUE response: %s", reply.Buffer());
uint32 v = 0u;
if (StringHelper::SearchString(reply.Buffer(), "OK VALUE") !=
NULL_PTR(const char8 *) &&
ExtractValueUint32(reply.Buffer(), v)) {
printf("SUCCESS: VALUE returned a parseable counter value (%u).\n", v);
} else {
printf("FAILURE: VALUE reply malformed.\n");
}
} else {
printf("FAILURE: VALUE command failed.\n");
}
}
// Step 2: VALUE on an unknown signal should report an error, not crash.
printf("\n--- Step 2: VALUE on unknown signal ---\n");
{
StreamString reply;
if (SendCommandGAM(CONTROL_PORT, "VALUE App.Data.DDB.NoSuchSignal\n",
reply)) {
printf("VALUE response: %s", reply.Buffer());
if (StringHelper::SearchString(reply.Buffer(), "Error") !=
NULL_PTR(const char8 *)) {
printf("SUCCESS: Unknown signal reported as an error.\n");
} else {
printf("FAILURE: Unknown signal did not report an error.\n");
}
} else {
printf("FAILURE: VALUE command failed.\n");
}
}
// Step 3: LS with an explicit path.
printf("\n--- Step 3: LS App.Data ---\n");
{
StreamString reply;
if (SendCommandGAM(CONTROL_PORT, "LS App.Data\n", reply)) {
printf("LS response: %s", reply.Buffer());
if (StringHelper::SearchString(reply.Buffer(), "DDB") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "OK LS") !=
NULL_PTR(const char8 *)) {
printf("SUCCESS: LS App.Data listed the DDB data source.\n");
} else {
printf("FAILURE: LS App.Data did not list expected children.\n");
}
} else {
printf("FAILURE: LS command failed.\n");
}
}
// Step 4: bare LS (root). Regression test: this used to wrap the
// ObjectRegistryDatabase singleton in a Reference, which decremented its
// refcount to zero and deleted it when the Reference went out of scope,
// permanently killing the TCP control server. Verify both that LS itself
// succeeds AND that the control server is still alive afterwards.
printf("\n--- Step 4: bare LS (root) ---\n");
{
StreamString reply;
bool lsOk = SendCommandGAM(CONTROL_PORT, "LS\n", reply);
if (lsOk) {
printf("LS response: %s", reply.Buffer());
}
bool lsGood =
lsOk &&
StringHelper::SearchString(reply.Buffer(), "App") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "DebugService") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "OK LS") !=
NULL_PTR(const char8 *);
StreamString postReply;
bool postOk = SendCommandGAM(CONTROL_PORT, "VALUE App.Data.DDB.Counter\n",
postReply);
bool postGood = postOk && StringHelper::SearchString(postReply.Buffer(),
"OK VALUE") !=
NULL_PTR(const char8 *);
if (lsGood && postGood) {
printf("SUCCESS: bare LS listed the root and control server survived.\n");
} else {
printf("FAILURE: bare LS broke the control server (lsGood=%d postGood=%d).\n",
lsGood, postGood);
}
}
// Step 5: FORCE holds the signal at a fixed value.
printf("\n--- Step 5: FORCE ---\n");
{
StreamString reply;
bool ok = SendCommandGAM(CONTROL_PORT,
"FORCE App.Data.DDB.Counter 424242\n", reply);
printf("FORCE response: %s", ok ? reply.Buffer() : "(no reply)");
bool forceAccepted =
ok && StringHelper::SearchString(reply.Buffer(), "OK FORCE 1") !=
NULL_PTR(const char8 *);
Sleep::MSec(150);
StreamString v1;
bool v1Ok = SendCommandGAM(CONTROL_PORT, "VALUE App.Data.DDB.Counter\n", v1);
Sleep::MSec(150);
StreamString v2;
bool v2Ok = SendCommandGAM(CONTROL_PORT, "VALUE App.Data.DDB.Counter\n", v2);
bool bothForced =
v1Ok && v2Ok &&
StringHelper::SearchString(v1.Buffer(), "\"Value\":\"424242\"") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(v2.Buffer(), "\"Value\":\"424242\"") !=
NULL_PTR(const char8 *);
if (forceAccepted && bothForced) {
printf("SUCCESS: FORCE held the signal at 424242 across two reads.\n");
} else {
printf("FAILURE: FORCE did not hold the forced value.\n");
}
}
// Step 6: UNFORCE lets the signal resume advancing.
printf("\n--- Step 6: UNFORCE ---\n");
{
StreamString reply;
bool ok =
SendCommandGAM(CONTROL_PORT, "UNFORCE App.Data.DDB.Counter\n", reply);
printf("UNFORCE response: %s", ok ? reply.Buffer() : "(no reply)");
bool unforceAccepted =
ok && StringHelper::SearchString(reply.Buffer(), "OK UNFORCE 1") !=
NULL_PTR(const char8 *);
Sleep::MSec(200);
uint32 v1 = 0u;
bool v1Ok = QueryValueUint32(v1);
Sleep::MSec(200);
uint32 v2 = 0u;
bool v2Ok = QueryValueUint32(v2);
bool advancing = v1Ok && v2Ok && v1 != 424242u && v2 > v1;
if (unforceAccepted && advancing) {
printf("SUCCESS: UNFORCE resumed live updates (%u -> %u).\n", v1, v2);
} else {
printf("FAILURE: UNFORCE did not resume live updates (%u -> %u).\n", v1,
v2);
}
}
// Step 7: PAUSE holds execution, STEP advances one command-cycle at a
// time while STEP_STATUS reports the paused state, RESUME lets it run
// free again.
//
// NOTE: OutputPauseAndStep() (DebugBrokerWrapper.h) blocks the RT thread
// in a nested pause/step spin *after* the current cycle's data has
// already been committed. As a result, the very first STEP issued right
// after a manual PAUSE only moves the thread from the first spin to the
// second spin without producing a new committed cycle (no observable
// value change) -- it takes a second STEP to see the counter actually
// advance. This is verified/tolerated below rather than asserted away.
printf("\n--- Step 7: PAUSE / STEP / STEP_STATUS / RESUME ---\n");
{
StreamString pauseReply;
bool pauseOk = SendCommandGAM(CONTROL_PORT, "PAUSE\n", pauseReply);
printf("PAUSE response: %s", pauseOk ? pauseReply.Buffer() : "(no reply)");
Sleep::MSec(150);
uint32 vPaused1 = 0u;
QueryValueUint32(vPaused1);
Sleep::MSec(150);
uint32 vPaused2 = 0u;
QueryValueUint32(vPaused2);
bool heldWhilePaused = (vPaused1 == vPaused2);
if (heldWhilePaused) {
printf("SUCCESS: Counter held steady while paused (%u).\n", vPaused1);
} else {
printf("FAILURE: Counter moved while paused (%u -> %u).\n", vPaused1,
vPaused2);
}
StreamString statusReply;
bool statusOk = SendCommandGAM(CONTROL_PORT, "STEP_STATUS\n", statusReply);
printf("STEP_STATUS response: %s",
statusOk ? statusReply.Buffer() : "(no reply)");
bool pausedReported =
statusOk && StringHelper::SearchString(statusReply.Buffer(),
"\"Paused\":true") !=
NULL_PTR(const char8 *);
if (pausedReported) {
printf("SUCCESS: STEP_STATUS reports Paused=true.\n");
} else {
printf("FAILURE: STEP_STATUS did not report Paused=true.\n");
}
// "Primer" STEP: settles the one-time spin-transition quirk described
// above; no value-change assertion here by design.
StreamString step1Reply;
SendCommandGAM(CONTROL_PORT, "STEP 1\n", step1Reply);
Sleep::MSec(150);
uint32 vAfterPrimer = 0u;
QueryValueUint32(vAfterPrimer);
StreamString step2Reply;
bool step2Ok = SendCommandGAM(CONTROL_PORT, "STEP 2\n", step2Reply);
printf("STEP 2 response: %s", step2Ok ? step2Reply.Buffer() : "(no reply)");
Sleep::MSec(200);
uint32 vAfterStep = 0u;
bool vAfterStepOk = QueryValueUint32(vAfterStep);
bool stepAdvanced = vAfterStepOk && vAfterStep > vAfterPrimer;
if (stepAdvanced) {
printf("SUCCESS: STEP advanced the counter (%u -> %u).\n", vAfterPrimer,
vAfterStep);
} else {
printf("FAILURE: STEP did not advance the counter (%u -> %u).\n",
vAfterPrimer, vAfterStep);
}
StreamString resumeReply;
bool resumeOk = SendCommandGAM(CONTROL_PORT, "RESUME\n", resumeReply);
printf("RESUME response: %s",
resumeOk ? resumeReply.Buffer() : "(no reply)");
Sleep::MSec(200);
uint32 vResumed1 = 0u;
QueryValueUint32(vResumed1);
Sleep::MSec(200);
uint32 vResumed2 = 0u;
bool resumedOk = QueryValueUint32(vResumed2);
bool freeRunning = resumedOk && vResumed2 > vResumed1;
if (freeRunning) {
printf("SUCCESS: RESUME let execution run free again (%u -> %u).\n",
vResumed1, vResumed2);
} else {
printf("FAILURE: Execution did not resume (%u -> %u).\n", vResumed1,
vResumed2);
}
}
// Step 8: BREAK auto-pauses when the condition is met and holds the
// value; BREAK ... OFF clears the condition without auto-resuming.
printf("\n--- Step 8: BREAK / BREAK OFF ---\n");
{
uint32 baseline = 0u;
QueryValueUint32(baseline);
// Counter increments ~1 per RT cycle (1 kHz); +300 is reachable well
// within the retry budget below without being trivially already-true.
uint32 target = baseline + 300u;
StreamString cmd;
cmd.Printf("BREAK App.Data.DDB.Counter > %u\n", target);
StreamString breakReply;
bool breakOk = SendCommandGAM(CONTROL_PORT, cmd.Buffer(), breakReply);
printf("BREAK response: %s", breakOk ? breakReply.Buffer() : "(no reply)");
bool breakAccepted =
breakOk && StringHelper::SearchString(breakReply.Buffer(),
"OK BREAK 1") !=
NULL_PTR(const char8 *);
bool pausedByBreak = false;
for (int retry = 0; retry < 30 && !pausedByBreak; retry++) {
Sleep::MSec(100);
StreamString statusReply;
if (SendCommandGAM(CONTROL_PORT, "STEP_STATUS\n", statusReply)) {
if (StringHelper::SearchString(statusReply.Buffer(),
"\"Paused\":true") !=
NULL_PTR(const char8 *)) {
pausedByBreak = true;
}
}
}
if (pausedByBreak) {
printf("SUCCESS: BREAK auto-paused once the condition was met.\n");
} else {
printf("FAILURE: BREAK never paused execution (target=%u).\n", target);
}
uint32 held1 = 0u, held2 = 0u;
QueryValueUint32(held1);
Sleep::MSec(200);
QueryValueUint32(held2);
bool heldAfterBreak = (held1 == held2) && (held1 >= target);
if (heldAfterBreak) {
printf("SUCCESS: Value held at/above the break target (%u).\n", held1);
} else {
printf("FAILURE: Value not held after break (%u -> %u, target=%u).\n",
held1, held2, target);
}
StreamString offReply;
bool offOk = SendCommandGAM(CONTROL_PORT,
"BREAK App.Data.DDB.Counter OFF\n", offReply);
printf("BREAK OFF response: %s", offOk ? offReply.Buffer() : "(no reply)");
bool offAccepted =
offOk && StringHelper::SearchString(offReply.Buffer(), "OK BREAK") !=
NULL_PTR(const char8 *);
StreamString statusAfterOff;
bool statusOk =
SendCommandGAM(CONTROL_PORT, "STEP_STATUS\n", statusAfterOff);
bool stillPaused =
statusOk && StringHelper::SearchString(statusAfterOff.Buffer(),
"\"Paused\":true") !=
NULL_PTR(const char8 *);
if (stillPaused) {
printf("SUCCESS: BREAK OFF cleared the condition without auto-resuming.\n");
} else {
printf("FAILURE: Clearing BREAK unexpectedly changed the paused state.\n");
}
if (!breakAccepted || !offAccepted) {
printf("FAILURE: BREAK/BREAK OFF command replies malformed.\n");
}
StreamString resumeReply;
SendCommandGAM(CONTROL_PORT, "RESUME\n", resumeReply);
Sleep::MSec(200);
uint32 vFinal1 = 0u, vFinal2 = 0u;
QueryValueUint32(vFinal1);
Sleep::MSec(200);
bool finalOk = QueryValueUint32(vFinal2);
if (finalOk && vFinal2 > vFinal1) {
printf("SUCCESS: Execution resumed after BREAK OFF + RESUME.\n");
} else {
printf("FAILURE: Execution did not resume after BREAK OFF + RESUME.\n");
}
}
// Step 9: TREE on a DataSource path exercises the signal-listing branch
// of ExportTreeNode (as opposed to the plain child-container branch that
// a bare/root TREE hits).
printf("\n--- Step 9: TREE App.Data.Timer (DataSource) ---\n");
{
StreamString reply;
if (SendCommandGAM(CONTROL_PORT, "TREE App.Data.Timer\n", reply)) {
printf("TREE response: %s", reply.Buffer());
if (StringHelper::SearchString(reply.Buffer(), "\"Class\":\"Signal\"") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "OK TREE") !=
NULL_PTR(const char8 *)) {
printf("SUCCESS: TREE on a DataSource listed its signals.\n");
} else {
printf("FAILURE: TREE on a DataSource did not list signals.\n");
}
} else {
printf("FAILURE: TREE command failed.\n");
}
}
// Step 10: TREE on a GAM path exercises the InputSignal/OutputSignal
// listing branches of ExportTreeNode.
printf("\n--- Step 10: TREE App.Functions.GAM1 (GAM) ---\n");
{
StreamString reply;
if (SendCommandGAM(CONTROL_PORT, "TREE App.Functions.GAM1\n", reply)) {
printf("TREE response: %s", reply.Buffer());
if (StringHelper::SearchString(reply.Buffer(),
"\"Class\":\"InputSignal\"") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(),
"\"Class\":\"OutputSignal\"") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "OK TREE") !=
NULL_PTR(const char8 *)) {
printf("SUCCESS: TREE on a GAM listed its input and output signals.\n");
} else {
printf("FAILURE: TREE on a GAM did not list In/Out signals.\n");
}
} else {
printf("FAILURE: TREE command failed.\n");
}
}
// Step 11: INFO on a name that matches neither a registry object nor a
// signal alias must report an error rather than crash.
printf("\n--- Step 11: INFO on unknown name ---\n");
{
StreamString reply;
if (SendCommandGAM(CONTROL_PORT, "INFO App.Data.DDB.NoSuchThing\n",
reply)) {
printf("INFO response: %s", reply.Buffer());
if (StringHelper::SearchString(reply.Buffer(), "Object not found") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "OK INFO") !=
NULL_PTR(const char8 *)) {
printf("SUCCESS: INFO on an unknown name reported an error.\n");
} else {
printf("FAILURE: INFO on an unknown name did not report an error.\n");
}
} else {
printf("FAILURE: INFO command failed.\n");
}
}
app->StopCurrentStateExecution();
ObjectRegistryDatabase::Instance()->Purge();
}
// ---------------------------------------------------------------------------
// TestDebugConfigAutoRebuild
// ---------------------------------------------------------------------------
//
// CONFIG normally serves back the ConfigurationDatabase handed to
// SetFullConfig() by the application's own startup code. If SetFullConfig()
// is never called (manualConfigSet stays false), ServeConfig() instead
// falls back to RebuildConfigFromRegistry(), which walks the live
// ObjectRegistryDatabase tree (BuildCDBFromContainer) to reconstruct an
// equivalent configuration on demand. This exercises that fallback path.
void TestDebugConfigAutoRebuild() {
printf("--- Test: CONFIG auto-rebuild from registry (no SetFullConfig) ---\n");
ObjectRegistryDatabase::Instance()->Purge();
ConfigurationDatabase cdb;
StreamString ss = debug_commands_config;
ss.Seek(0);
StandardParser parser(ss, cdb);
if (!parser.Parse()) {
printf("ERROR: Failed to parse config\n");
return;
}
cdb.MoveToRoot();
uint32 n = cdb.GetNumberOfChildren();
for (uint32 i = 0; i < n; i++) {
const char8 *name = cdb.GetChildName(i);
ConfigurationDatabase child;
cdb.MoveRelative(name);
cdb.Copy(child);
cdb.MoveToAncestor(1u);
StreamString className;
child.Read("Class", className);
Reference ref(className.Buffer(),
GlobalObjectsDatabase::Instance()->GetStandardHeap());
if (!ref.IsValid()) {
printf("ERROR: Could not create object %s of class %s\n", name,
className.Buffer());
continue;
}
ref->SetName(name);
if (!ref->Initialise(child)) {
printf("ERROR: Failed to initialise object %s\n", name);
continue;
}
ObjectRegistryDatabase::Instance()->Insert(ref);
}
ReferenceT<DebugService> service =
ObjectRegistryDatabase::Instance()->Find("DebugService");
if (!service.IsValid()) {
printf("ERROR: DebugService not found\n");
return;
}
// Deliberately do NOT call service->SetFullConfig(cdb) here: CONFIG must
// still work by rebuilding from the registry on the fly.
ReferenceT<RealTimeApplication> app =
ObjectRegistryDatabase::Instance()->Find("App");
if (!app.IsValid()) {
printf("ERROR: App not found\n");
return;
}
if (!app->ConfigureApplication()) {
printf("ERROR: ConfigureApplication failed.\n");
return;
}
if (app->PrepareNextState("State1") != ErrorManagement::NoError) {
printf("ERROR: PrepareNextState failed.\n");
return;
}
if (app->StartNextStateExecution() != ErrorManagement::NoError) {
printf("ERROR: StartNextStateExecution failed.\n");
return;
}
printf("Application started.\n");
Sleep::MSec(1000);
printf("\n--- Step 1: CONFIG without a prior SetFullConfig ---\n");
{
StreamString reply;
if (SendCommandGAM(CONTROL_PORT, "CONFIG\n", reply)) {
printf("CONFIG response (len=%llu)\n", reply.Size());
if (StringHelper::SearchString(reply.Buffer(), "GAM1") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "DebugService") !=
NULL_PTR(const char8 *) &&
StringHelper::SearchString(reply.Buffer(), "OK CONFIG") !=
NULL_PTR(const char8 *)) {
printf("SUCCESS: CONFIG rebuilt the configuration from the "
"registry.\n");
} else {
printf("FAILURE: CONFIG (auto-rebuild) reply missing expected "
"content.\n");
}
} else {
printf("FAILURE: CONFIG command failed.\n");
}
}
app->StopCurrentStateExecution();
ObjectRegistryDatabase::Instance()->Purge();
}
+10
View File
@@ -31,6 +31,8 @@ void RunValidationTest();
void TestConfigCommands(); void TestConfigCommands();
void TestGAMSignalTracing(); void TestGAMSignalTracing();
void TestTreeCommand(); void TestTreeCommand();
void TestDebugCommands();
void TestDebugConfigAutoRebuild();
int main() { int main() {
signal(SIGALRM, timeout_handler); signal(SIGALRM, timeout_handler);
@@ -91,6 +93,14 @@ int main() {
TestMessageCommand(); TestMessageCommand();
Sleep::MSec(1000); Sleep::MSec(1000);
printf("\n--- Test 8: FORCE/UNFORCE/BREAK/STEP/STEP_STATUS/VALUE/LS Commands ---\n");
TestDebugCommands();
Sleep::MSec(1000);
printf("\n--- Test 9: CONFIG Auto-Rebuild From Registry ---\n");
TestDebugConfigAutoRebuild();
Sleep::MSec(1000);
printf("\nAll Integration Tests Finished.\n"); printf("\nAll Integration Tests Finished.\n");
return 0; return 0;

Some files were not shown because too many files have changed in this diff Show More