Compare commits
27
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a49ab5ba25 | ||
|
|
1ddb4fe356 | ||
|
|
915a192b16 | ||
|
|
3e0a481c13 | ||
|
|
2d5ca20ae4 | ||
|
|
f2042d624b | ||
|
|
f8c79131c9 | ||
|
|
28d149f536 | ||
|
|
9a39cf923a | ||
|
|
07b6b4898a | ||
|
|
03c7a95e9b | ||
|
|
45dcb9a71f | ||
|
|
4286ea4539 | ||
|
|
8337d678be | ||
|
|
b65ac06ce2 | ||
|
|
83d0a060fe | ||
|
|
efb4ea48fb | ||
|
|
f0f83110a4 | ||
|
|
269b2c4d97 | ||
|
|
1d78b45963 | ||
|
|
ef58553c63 | ||
|
|
69e52af20b | ||
|
|
1fcc4e4e6d | ||
|
|
462b05b71a | ||
|
|
dcaa466736 | ||
|
|
0bea41f866 | ||
|
|
7a326c5d78 |
@@ -0,0 +1,241 @@
|
|||||||
|
# Repository Guidelines
|
||||||
|
|
||||||
|
Guide for AI assistants working in the MARTe2 Integrated Components repository.
|
||||||
|
Focuses on non-obvious facts: commands, conventions, cross-module contracts, and
|
||||||
|
gotchas that are not self-evident from a single file read.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
MARTe2 component library with **two independent real-time data paths** sharing
|
||||||
|
one binary wire protocol (`Common/UDP/UDPSProtocol.h`):
|
||||||
|
|
||||||
|
1. **Streaming path** — `UDPStreamer` DataSource serialises DDB signals into UDPS
|
||||||
|
binary packets on UDP → `StreamHub` (headless C++ hub: ring buffers, LTTB
|
||||||
|
decimation, trigger FSM, history writer, binary recorder) → WebSocket 8090 →
|
||||||
|
clients (browser SPA, native ImGui, native Qt).
|
||||||
|
2. **Debug path** — `DebugService` 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 (UDPS trace telemetry), TCP 8082
|
||||||
|
(`TcpLogger` log forward).
|
||||||
|
|
||||||
|
## Architecture & Data Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
[SineArrayGAM/TimeArrayGAM] → DDB → UDPStreamer (UDPS over UDP)
|
||||||
|
├─→ UDPStreamerClient (input DS back into a MARTe2 RT app, round-trip)
|
||||||
|
└─→ StreamHub: UDPSourceSession (receive thread → SignalRingBuffer)
|
||||||
|
→ push loop @30Hz: LTTB decimate temporal sigs → WS binary frames → clients
|
||||||
|
DebugService: patches broker builders at Initialise(); TCP 8080 commands,
|
||||||
|
UDP 8081 telemetry, TcpLogger 8082 (REPORT_ERROR → "LOG <LEVEL> <desc>" lines)
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Wire protocol**: `Common/UDP/UDPSProtocol.h` is the canonical spec (17-byte
|
||||||
|
packed header, magic `0x53504455` 'UDPS', 136-byte signal descriptors,
|
||||||
|
CONFIG/DATA/ACK/CONNECT/DISCONNECT packet types, quant/time/publish modes).
|
||||||
|
Deliberately MARTe2-free so Go clients reuse it. **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/protocol.go`), and JS parsers
|
||||||
|
(`Client/udpstreamer/static/`, `Client/debugger/static/`). Any protocol change
|
||||||
|
must be mirrored in all of them.
|
||||||
|
- **WS protocol** has two implementations — Go hub (`Common/Client/go/wshub`) and
|
||||||
|
C++ StreamHub — that must behave identically; every client (SPA, ImGui, Qt)
|
||||||
|
must satisfy both. JSON text frames for commands/events (`addSource`,
|
||||||
|
`removeSource`, `setTrigger`, `arm`, `zoom`, `historyZoom`, `recStart`…), binary
|
||||||
|
frames for data pushes (live v1 + trigger capture v2).
|
||||||
|
- **Threading model**: RT threads only spinlock+memcpy (`FastPollingMutexSem`);
|
||||||
|
all socket I/O, fragmentation, and reassembly lives on background
|
||||||
|
`SingleThreadService` threads. StreamHub: per-session UDPSClient receive
|
||||||
|
threads + WS accept/read threads + one push loop.
|
||||||
|
- **DebugService patching**: `PatchRegistry()` replaces the ObjectBuilder for 11
|
||||||
|
`MemoryMap*Broker` classes; runs only when `ControlPort > 0`; static guard
|
||||||
|
against double-patching; wrappers persist for process lifetime.
|
||||||
|
|
||||||
|
## Key Directories
|
||||||
|
|
||||||
|
| Path | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `Source/Components/DataSources/UDPStreamer/` | Output DataSource; UDP I/O on bg thread, RT thread only spinlock+memcpy in `Synchronise()` |
|
||||||
|
| `Source/Components/DataSources/UDPStreamerClient/` | Input DataSource (shared `UDPSClient`), double-buffered ready/scratch |
|
||||||
|
| `Source/Components/GAMs/` | `SineArrayGAM` (float32 sine, continuous phase), `TimeArrayGAM` (us-timer → per-sample timestamp array) |
|
||||||
|
| `Source/Components/Interfaces/DebugService/` | Registry patching, `DebugBrokerWrapper.h`, TCP/UDP services |
|
||||||
|
| `Source/Components/Interfaces/TCPLogger/` | `LoggerConsumerI` forwarding `REPORT_ERROR` to ≤8 TCP clients |
|
||||||
|
| `Source/Components/Interfaces/UDPStream/` | Plain-C++ helpers (not MARTe2 Objects): `UDPSClient` (auto-reconnect + fragment reassembly), `UDPSServer` (not thread-safe — owner's Execute thread only) |
|
||||||
|
| `Source/Applications/StreamHub/` | Standalone app (links MARTe2 core): `StreamHub`, `UDPSourceSession`, `WSServer`, `TriggerEngine`, `HistoryWriter`, `BinaryRecorder`, `LTTB`, `SignalRingBuffer` |
|
||||||
|
| `Common/UDP/` | Canonical wire protocol (header-only, MARTe2-free) |
|
||||||
|
| `Common/Client/go/` | Go mirror: `udpsprotocol` (decoder), `wshub` (WS hub client) |
|
||||||
|
| `Client/udpstreamer/` | Go legacy direct-UDP oscilloscope web UI (connects straight to UDPStreamer, no StreamHub) |
|
||||||
|
| `Client/webui/` | Go thin static server; SPA talks WS directly to C++ StreamHub (discovers via `GET /hub`) |
|
||||||
|
| `Client/debugger/` | Go debug web UI for DebugService |
|
||||||
|
| `Client/streamhub/` | Native ImGui+SDL2+OpenGL oscilloscope (C++17, no MARTe2) |
|
||||||
|
| `Client/streamhub-qt/` | Native Qt Widgets oscilloscope (Qt6 preferred, Qt5 fallback) |
|
||||||
|
| `Test/` | GTest, legacy Integration tests, Configurations (.cfg), E2E suite |
|
||||||
|
| `Docs/` | Per-component reference: `Protocol.md`, `UDPStreamer.md`, `StreamHub-{API,UserGuide,Developer}.md`, `DebugService.md`, `WebUI.md`, `Tutorial.md`, `E2E-Suite.md` |
|
||||||
|
|
||||||
|
## Development Commands
|
||||||
|
|
||||||
|
`source env.sh` is **mandatory** before any MARTe2 build or run (sets
|
||||||
|
`MARTe2_DIR`, `MARTe2_Components_DIR`, `TARGET=x86-linux`, `LD_LIBRARY_PATH`).
|
||||||
|
The E2E scripts source it themselves; a bare `make` from a fresh shell will not
|
||||||
|
work. `run_streamhub.sh` hard-errors if `MARTe2_DIR` is unset.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source env.sh
|
||||||
|
|
||||||
|
make -f Makefile.gcc core # 7 components (UDPStream interface FIRST, then UDPStreamer, UDPStreamerClient, GAMs, TCPLogger, DebugService)
|
||||||
|
make -f Makefile.gcc apps # StreamHub standalone app → Build/x86-linux/StreamHub/StreamHub.ex
|
||||||
|
make -f Makefile.gcc test # GTest + Integration test binaries + component test libs
|
||||||
|
make -f Makefile.gcc all # core + apps + test
|
||||||
|
make -f Makefile.gcc clean
|
||||||
|
|
||||||
|
# Single component:
|
||||||
|
make -C Source/Components/GAMs/SineArrayGAM -f Makefile.gcc
|
||||||
|
```
|
||||||
|
|
||||||
|
Build output → `Build/x86-linux/` mirroring `PACKAGE` paths (both `libX.so` and
|
||||||
|
`X.so` are produced). `compile_commands.json` (repo root, gitignored) feeds
|
||||||
|
LSP/clangd; CMake clients export their own into `Client/*/build/`.
|
||||||
|
|
||||||
|
### Non-MARTe2 clients (no env.sh needed)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd Common/Client/go && go build ./...
|
||||||
|
cd Client/debugger && go build ./...
|
||||||
|
cd Client/streamhub && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build
|
||||||
|
cd Client/streamhub-qt && cmake -B build && cmake --build build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key scripts
|
||||||
|
|
||||||
|
| Script | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `./run_streamhub.sh` | Demo stack: build + launch MARTe2 app + StreamHub, optional web (`-w`) / ImGui (`-g`) clients. Flags `-m/-c` MARTe2 dirs, `-b TARGET`, `-p WS_PORT`, `-n MAX_POINTS` (actual default 1000000, header says 10000), `-s` skip build. Generates temp hub cfg with `+History`/`+Recorder` blocks in `/tmp`. Ctrl-C kills all. |
|
||||||
|
| `./Test/E2E/suite/run_e2e.sh` | Full E2E: 57-scenario matrix + stress + unit suites + gcov coverage + Typst PDF report. Flags: `--skip-build`, `--only <id>`, `--pdf-only`, `--skip-coverage`, `--skip-stress`, `--skip-datasources`, `--skip-recorder`, `--skip-debug`, `--skip-tcplogger` |
|
||||||
|
| `./Test/E2E/suite/run_stress.sh` | Capacity harness: sweeps one load axis at a time (`--axis`), hard gates survival+liveness, soft gates RSS+zoom-p95 |
|
||||||
|
|
||||||
|
## Code Conventions & Common Patterns
|
||||||
|
|
||||||
|
- **No STL in `Source/Components/**` (and StreamHub)**: use `StreamString` (not
|
||||||
|
`std::string`), `FastPollingMutexSem`/`EventSem` (not `std::mutex`/threads),
|
||||||
|
fixed arrays / MARTe2 `Vector<T>` (not `std::vector`), `REPORT_ERROR` /
|
||||||
|
`REPORT_ERROR_STATIC` macros (no exceptions). C stdlib is fine. Heap
|
||||||
|
`new`/`delete[]` is normal. STL/C++17 is fine in `Client/streamhub/` and
|
||||||
|
`Client/streamhub-qt/`.
|
||||||
|
- **RT hot-path rule**: `FastPollingMutexSem` on real-time hot paths, never OS
|
||||||
|
mutexes; RT cycle must not block on the scheduler.
|
||||||
|
- **Class registration**: `CLASS_REGISTER_DECLARATION()` in the class `public:`
|
||||||
|
section of the header; `CLASS_REGISTER(Name, "1.0")` at the end of the `.cpp`
|
||||||
|
inside `namespace MARTe`. Every component `.cpp` ends with it.
|
||||||
|
- **EUPL v1.1 license headers** on all C++ sources and `Makefile.inc` — preserve
|
||||||
|
on new files.
|
||||||
|
- **Per-component build**: each dir has one-line `Makefile.gcc` wrapper
|
||||||
|
(`include Makefile.inc`) + `Makefile.inc` declaring `OBJSX`, `PACKAGE`,
|
||||||
|
`ROOT_DIR`, `INCLUDES` (re-declared per file, ~12 MARTe2 layer dirs),
|
||||||
|
`LIBRARIES`, including `MakeStdLibDefs.$(TARGET)` then
|
||||||
|
`MakeStdLibRules.$(TARGET)`. Generated `depends.x86-linux` (gcc -MM) is
|
||||||
|
committed but **never hand-edited** — delete to regenerate.
|
||||||
|
- **Qt client**: `QT_NO_KEYWORDS` is required (reused `Protocol.h` structs have
|
||||||
|
members named `signals`); Qt classes use `Q_SIGNALS`/`Q_SLOTS`/`Q_EMIT`. Run
|
||||||
|
with long options: `--host HOST --port 8090` (single-dash misparsed). Single
|
||||||
|
GUI thread, 60 Hz QTimer repaint.
|
||||||
|
- **StreamHub config** is *not* a MARTe2 `RealTimeApplication`: `Hub = { WSPort
|
||||||
|
MaxPoints PushRate MaxPushPoints RingTemporal RingScalar +Recorder{...}
|
||||||
|
Sources={id={Label Addr Port}} }`. `+History` keys: `Directory` (required),
|
||||||
|
`DurationHours` (1), `Decimation` (1), `FlushIntervalSec` (5),
|
||||||
|
`MinDiskFreeMB` (500). `.shist` files: 64-byte header ('SHR1') + circular
|
||||||
|
(t,v) float64 pairs.
|
||||||
|
- **UDPStreamer config**: `Port` (44500; multicast data = `DataPort`, default
|
||||||
|
`Port+1`), `MaxPayloadSize` (1400), `PublishingMode` `Strict`/`Accumulate`,
|
||||||
|
per-signal `Signals={Name={Type,Unit,NumberOfDimensions,NumberOfElements,
|
||||||
|
TimeMode}}` with `TimeMode` `PacketTime`/`FirstSample`/`LastSample`/`FullArray`;
|
||||||
|
multicast needs `MulticastGroup` + `Interface`.
|
||||||
|
|
||||||
|
## Important Files
|
||||||
|
|
||||||
|
- `env.sh` — environment; source first, always.
|
||||||
|
- `Makefile.gcc` / `Makefile.inc` (root) — build orchestration.
|
||||||
|
- `Common/UDP/UDPSProtocol.h` — canonical wire format; changing it triggers the
|
||||||
|
4-way mirror checklist above.
|
||||||
|
- `Source/Applications/StreamHub/main.cpp` — hub entry (`[-cfg file.cfg]
|
||||||
|
[-port N] [-maxPoints N]`); hub **must be heap-allocated** (~128 MB, exceeds
|
||||||
|
the 8 MB stack).
|
||||||
|
- `Test/Configurations/*.cfg` — MARTe2 app configs (`$App = { Class =
|
||||||
|
RealTimeApplication }` with `+Functions`, `+DataSources`, `+States`, `+Timings`
|
||||||
|
blocks); `streamhub_demo.cfg` and `TestApp.cfg` are good templates.
|
||||||
|
- `Test/E2E/suite/{scenarios,gen_data,gen_cfg,validate_waveform,stress}.py` —
|
||||||
|
declarative scenario matrix and generators consumed identically by the Go
|
||||||
|
chain-client and validators.
|
||||||
|
- `Client/debugger/main.go` — `-addr :7777` default, `-enable-dangerous-commands`
|
||||||
|
safety gate (CR-4) for FORCE/PAUSE/RESUME/STEP/BREAK/MSG.
|
||||||
|
|
||||||
|
## Runtime/Tooling Preferences
|
||||||
|
|
||||||
|
- **OS**: Linux x86_64 (`TARGET=x86-linux`). External deps live outside this
|
||||||
|
repo: `MARTe2_DIR` (default `~/workspace/MARTe2`) and
|
||||||
|
`MARTe2_Components_DIR` (default `~/workspace/MARTe2-components`) — edit
|
||||||
|
`env.sh` if they differ. `env.sh`'s `LD_LIBRARY_PATH` does **not** cover
|
||||||
|
UDPStreamerClient/UDPStream lib dirs.
|
||||||
|
- **C++**: MARTe2 `Makefile.gcc` wrapper system, gtest-1.7.0 for tests.
|
||||||
|
- **Go**: `go 1.21`; modules use `replace marte2/common => ../../Common/Client/go`
|
||||||
|
(`gorilla/websocket` v1.5.1). Go binaries are gitignored.
|
||||||
|
- **ImGui client**: needs SDL2; CMake FetchContent pins Dear ImGui **v1.91.8** +
|
||||||
|
ImPlot **v0.17** (`implot_items.cpp` is a slow -O3 TU, ~2 min rebuild).
|
||||||
|
- **Qt client**: Qt6 preferred, Qt5 fallback, Widgets + WebSockets, custom
|
||||||
|
QPainter plotting (no QtCharts).
|
||||||
|
- **E2E report**: `typst compile E2E_Report.typ`; Python 3 + numpy for the suite.
|
||||||
|
- Remove `vgore.*` core dumps when you see them; they are not gitignored.
|
||||||
|
|
||||||
|
## Testing & QA
|
||||||
|
|
||||||
|
Four test layers; `env.sh` + built stack required for all but the standalone
|
||||||
|
ones. Only `tests_py.py`, Go tests, and the built C++ test binaries run
|
||||||
|
standalone.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./Build/x86-linux/GTest/MainGTest.ex --gtest_filter='Name*' # C++ GTest
|
||||||
|
./Build/x86-linux/Test/Integration/Integration/IntegrationTests.ex # legacy DebugService runtime tests
|
||||||
|
cd Test/E2E/suite/client && go test ./... # Go chain-client unit tests
|
||||||
|
cd Test/E2E/suite && python3 -m unittest tests_py # framework logic, standalone
|
||||||
|
```
|
||||||
|
|
||||||
|
- **GTest**: `MainGTest.ex` currently holds only `DebugServiceGTest`
|
||||||
|
(TraceRingBuffer SPSC, DebugSignalInfo, BreakOp). Component GTests
|
||||||
|
(`UDPStreamerGTest.cpp` ~46 cases, `StreamHubTest.a`, `UDPStreamerClientTest.a`)
|
||||||
|
compile **as libraries only — no standalone executable**.
|
||||||
|
- **Legacy IntegrationTests.ex**: 9 printf-narrated DebugService runtime tests,
|
||||||
|
always returns 0; `collect.py` parses stdout blocks.
|
||||||
|
- **E2E suite** (`run_e2e.sh`): 57 curated scenarios (s01–s57) across kinds
|
||||||
|
`chain`/`direct`/`recorder`/`debug`/`debug_pause_resume`/`tcplogger`, driven
|
||||||
|
against live MARTeApp.ex + StreamHub.ex + Go chain-client. `scenarios.py` is a
|
||||||
|
curated covering set: **every configurable UDPStreamer option value appears in
|
||||||
|
≥1 scenario** — add a scenario when adding an option.
|
||||||
|
- **Oracle gates** (`validate_waveform.py`): **fidelity** (every received value
|
||||||
|
within `tol` of ground truth; 0 for un-quantised ints, float epsilon for
|
||||||
|
un-quantised floats, `quant_step/2 + 1e-6·range` for quantised) is the
|
||||||
|
**correctness gate**. **Shape** is a *gross* sanity gate + tracked metric
|
||||||
|
(`corr >= 0.5`, `nRMSE <= 0.30` relaxed by quant step, frequency searched
|
||||||
|
±5% band); a correct sinusoid yields corr ~0.82–0.98, wrong frequency
|
||||||
|
collapses to ~0.00. Do **not** tighten shape into a correctness gate —
|
||||||
|
timestamp calibration (Phase-A) is pending.
|
||||||
|
- **Stress** (`run_stress.sh`): 7 axes (signal size/count/fan-out/sources/WS
|
||||||
|
clients/zoom rate), hard gates survival+liveness, soft gates RSS+zoom-p95.
|
||||||
|
- **Coverage**: `--cpp-coverage` rebuilds with gcov, captures via `lcov`
|
||||||
|
restricted to `Source/*` + `Test/*`, then restores a clean build.
|
||||||
|
- Artifacts → `Build/x86-linux/E2E/chain/`: `results.json` (XFAIL/XPASS for
|
||||||
|
`known_issue` markers), `report_data.json`, `history.jsonl`, `trend_*.png`,
|
||||||
|
`E2E_Report.pdf`; stress → `stress/stress_results.json`.
|
||||||
|
|
||||||
|
## Ports Reference (defaults)
|
||||||
|
|
||||||
|
| Port | Protocol | Component | Purpose |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 44500 | UDP | UDPStreamer | scalar signals (unicast control + data) |
|
||||||
|
| 44501/44502 | UDP | UDPStreamer | packed arrays (FirstSample/LastSample, FullArray) |
|
||||||
|
| 44503 | UDP | UDPStreamer | multicast data (group 239.0.0.1) |
|
||||||
|
| 8080 | TCP | DebugService | text command channel (one client at a time, newline-terminated) |
|
||||||
|
| 8081 | UDP | DebugService | trace telemetry (UDPS format) |
|
||||||
|
| 8082 | TCP | TcpLogger | REPORT_ERROR log forward |
|
||||||
|
| 8090 | TCP/WS | StreamHub | WebSocket (commands + binary data) |
|
||||||
|
| 7777 | TCP | Client/debugger | debug web UI (older docs say 9090; current flag is `-addr`) |
|
||||||
|
| 8080 | TCP | Client/udpstreamer, Client/webui | web UI listen (collides with DebugService in combined demos — scripts adjust) |
|
||||||
+221
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -37,9 +37,40 @@ 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/`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./Test/E2E/suite/run_e2e.sh [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
|
||||||
|
| Flag | Effect |
|
||||||
|
|---|---|
|
||||||
|
| `--skip-build` | Skip C++ component rebuild |
|
||||||
|
| `--only <id>` | Run a single scenario by ID |
|
||||||
|
| `--pdf-only` | Just compile the Typst PDF report |
|
||||||
|
| `--cpp-coverage` | Instrumented gcov rebuild + lcov capture (on by default) |
|
||||||
|
| `--skip-coverage` | Disable the coverage pass |
|
||||||
|
| `--skip-stress` | Skip the stress matrix |
|
||||||
|
| `--skip-datasources` | Skip `direct` scenarios |
|
||||||
|
| `--skip-recorder` | Skip `recorder` scenarios |
|
||||||
|
| `--skip-debug` | Skip `debug` and `debug_pause_resume` scenarios |
|
||||||
|
| `--skip-tcplogger` | Skip `tcplogger` scenarios |
|
||||||
|
|
||||||
|
Scenario kinds (defined in `scenarios.py`):
|
||||||
|
|
||||||
|
- **chain** — full streaming pipeline: MARTe2 → UDPStreamer → StreamHub → Go `chain-client` (live/zoom/window/trigger). Validates recorded waveform against analytic/fed oracle (`validate_waveform.py`: fidelity gates correctness, sine shape-fit is a gross-sanity gate + tracked metric).
|
||||||
|
- **direct** — MARTe2 FileReader → FileWriter round-trip, validates binary output.
|
||||||
|
- **recorder** — MARTe2 → StreamHub with history recorder, validates recorded `.bin` file.
|
||||||
|
- **debug / debug_pause_resume** — DebugService scenarios via the Go `debugclient`.
|
||||||
|
- **tcplogger** — TcpLogger scenarios via the Go `debugclient`.
|
||||||
|
|
||||||
|
After scenarios, the suite runs unit tests + coverage (`collect.py`: C++ GTest, Go, Python; coverage uses lcov restricted to `Source/*` — the `Test/` harness is excluded), 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`). Artifacts go to `Build/x86-linux/E2E/chain/` (report, logs, PDF) and `/tmp/chain_e2e/` (scratch). Results are aggregated into `results.json` with XFAIL/XPASS handling for known issues.
|
||||||
|
|
||||||
|
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)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -47,7 +86,8 @@ 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.SetSourceState("debug", "connecting")
|
// (m.hub == nil for NewHeadlessMarteController instances).
|
||||||
|
if m.hub != nil {
|
||||||
|
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
|
||||||
m.hub.SetSourceState("debug", "disconnected")
|
if m.hub != nil {
|
||||||
|
m.hub.SetSourceState("debug", "disconnected")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MarteController) stopped() bool {
|
func (m *MarteController) stopped() bool {
|
||||||
@@ -256,10 +316,25 @@ func (m *MarteController) HandleBrowserCommand(msg []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
cmd, _ := data["cmd"].(string)
|
cmd, _ := data["cmd"].(string)
|
||||||
if cmd != "" {
|
if cmd == "" {
|
||||||
m.trackForcedCmd(cmd)
|
return
|
||||||
m.SendCommand(cmd)
|
|
||||||
}
|
}
|
||||||
|
// 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.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 {
|
||||||
m.hub.UpdateConfigForSource("debug", m.translateSignalNames(raw))
|
if m.hub != nil {
|
||||||
|
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)
|
||||||
m.hub.UpdateConfigForSource("debug", translated)
|
if m.hub != nil {
|
||||||
|
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
|
||||||
m.hub.UpdateConfigForSource("debug", sigs)
|
if m.hub != nil {
|
||||||
m.hub.SetSourceState("debug", "connected")
|
m.hub.UpdateConfigForSource("debug", sigs)
|
||||||
|
m.hub.SetSourceState("debug", "connected")
|
||||||
|
}
|
||||||
|
|
||||||
case udpsprotocol.PktData:
|
case udpsprotocol.PktData:
|
||||||
if len(currentSigs) == 0 {
|
if len(currentSigs) == 0 {
|
||||||
@@ -888,8 +969,10 @@ 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
|
||||||
}
|
}
|
||||||
for _, s := range samples {
|
if m.hub != nil {
|
||||||
m.hub.PushDataForSource("debug", s)
|
for _, s := range samples {
|
||||||
|
m.hub.PushDataForSource("debug", s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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.
@@ -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) {
|
||||||
|
|||||||
@@ -99,6 +99,20 @@ func BuildDisconnectPacket() []byte {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuildAckPacket returns a 17-byte ACK datagram. Unicast clients send it
|
||||||
|
// periodically as a keepalive: UDPSServer refreshes the client's last-seen
|
||||||
|
// without re-sending CONFIG (which a repeated CONNECT would trigger).
|
||||||
|
func BuildAckPacket() []byte {
|
||||||
|
return buildHeader(PacketHeader{
|
||||||
|
Magic: MagicUDPS,
|
||||||
|
Type: PktACK,
|
||||||
|
Counter: 0,
|
||||||
|
FragmentIdx: 0,
|
||||||
|
TotalFragments: 1,
|
||||||
|
PayloadBytes: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Signal descriptor (136 bytes) ───────────────────────────────────────────
|
// ─── Signal descriptor (136 bytes) ───────────────────────────────────────────
|
||||||
|
|
||||||
// SignalInfo holds the parsed metadata for one signal.
|
// SignalInfo holds the parsed metadata for one signal.
|
||||||
@@ -127,7 +141,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 +246,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 +351,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))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package wshub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"marte2/common/udpsprotocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestUDPClientSendsPeriodicKeepAliveAcks verifies that a unicast UDPClient
|
||||||
|
// re-sends ACK datagrams from the SAME socket at keepAliveInterval. The
|
||||||
|
// UDPSServer refreshes a unicast client's last-seen only on client->server
|
||||||
|
// traffic; without this keepalive it evicts the client after ClientTimeout
|
||||||
|
// (default 30 s) and the stream dies.
|
||||||
|
func TestUDPClientSendsPeriodicKeepAliveAcks(t *testing.T) {
|
||||||
|
srv, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.ParseIP("127.0.0.1")})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
c := NewUDPClient(srv.LocalAddr().String(), "ka1", NewHub(), "", 0)
|
||||||
|
c.keepAliveInterval = 150 * time.Millisecond
|
||||||
|
go c.Run()
|
||||||
|
defer c.Stop()
|
||||||
|
|
||||||
|
buf := make([]byte, 512)
|
||||||
|
|
||||||
|
// 1) CONNECT from the client's ephemeral socket.
|
||||||
|
srv.SetReadDeadline(time.Now().Add(3 * time.Second))
|
||||||
|
n, clientAddr, err := srv.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected CONNECT: %v", err)
|
||||||
|
}
|
||||||
|
hdr, err := udpsprotocol.ParseHeader(buf[:n])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parse CONNECT: %v", err)
|
||||||
|
}
|
||||||
|
if hdr.Type != udpsprotocol.PktConnect {
|
||||||
|
t.Fatalf("first packet type = %d, want CONNECT (%d)", hdr.Type, udpsprotocol.PktConnect)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Collect ACKs for ~1 s: must be periodic and from the SAME socket
|
||||||
|
// (a new ephemeral socket would be registered as a new client).
|
||||||
|
deadline := time.Now().Add(time.Second)
|
||||||
|
acks := 0
|
||||||
|
for time.Now().Before(deadline) {
|
||||||
|
srv.SetReadDeadline(deadline)
|
||||||
|
n, addr, err := srv.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
hdr, err := udpsprotocol.ParseHeader(buf[:n])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if hdr.Type != udpsprotocol.PktACK {
|
||||||
|
t.Fatalf("unexpected packet type %d from %s", hdr.Type, addr)
|
||||||
|
}
|
||||||
|
if addr.String() != clientAddr.String() {
|
||||||
|
t.Fatalf("ACK from %s, want same socket as CONNECT (%s)", addr, clientAddr)
|
||||||
|
}
|
||||||
|
acks++
|
||||||
|
}
|
||||||
|
if acks < 3 {
|
||||||
|
t.Fatalf("expected >= 3 keepalive ACKs in 1 s, got %d", acks)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -172,27 +172,34 @@ const (
|
|||||||
reconnectDelay = 2 * time.Second
|
reconnectDelay = 2 * time.Second
|
||||||
readBufSize = 65536
|
readBufSize = 65536
|
||||||
udpRcvBufSize = 8 * 1024 * 1024
|
udpRcvBufSize = 8 * 1024 * 1024
|
||||||
|
// keepAliveInterval is the unicast keepalive period. The UDPStreamer
|
||||||
|
// server evicts silent unicast clients after its ClientTimeout (default
|
||||||
|
// 30 s); an ACK from the same socket refreshes its last-seen without
|
||||||
|
// triggering a CONFIG resend (a CONNECT would).
|
||||||
|
keepAliveInterval = 15 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// UDPClient manages the connection to one MARTe2 streamer source.
|
// UDPClient manages the connection to one MARTe2 streamer source.
|
||||||
type UDPClient struct {
|
type UDPClient struct {
|
||||||
serverAddr string
|
serverAddr string
|
||||||
sourceID string
|
sourceID string
|
||||||
hub *Hub
|
hub *Hub
|
||||||
multicastGroup string
|
multicastGroup string
|
||||||
dataPort int
|
dataPort int
|
||||||
stopCh chan struct{}
|
keepAliveInterval time.Duration
|
||||||
|
stopCh chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUDPClient creates a UDPClient bound to a specific source ID.
|
// NewUDPClient creates a UDPClient bound to a specific source ID.
|
||||||
func NewUDPClient(serverAddr, sourceID string, hub *Hub, multicastGroup string, dataPort int) *UDPClient {
|
func NewUDPClient(serverAddr, sourceID string, hub *Hub, multicastGroup string, dataPort int) *UDPClient {
|
||||||
return &UDPClient{
|
return &UDPClient{
|
||||||
serverAddr: serverAddr,
|
serverAddr: serverAddr,
|
||||||
sourceID: sourceID,
|
sourceID: sourceID,
|
||||||
hub: hub,
|
hub: hub,
|
||||||
multicastGroup: multicastGroup,
|
multicastGroup: multicastGroup,
|
||||||
dataPort: dataPort,
|
dataPort: dataPort,
|
||||||
stopCh: make(chan struct{}),
|
keepAliveInterval: keepAliveInterval,
|
||||||
|
stopCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +260,20 @@ func (u *UDPClient) runSession() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Printf("[%s] udp: sent CONNECT", u.sourceID)
|
log.Printf("[%s] udp: sent CONNECT", u.sourceID)
|
||||||
|
lastData := time.Now()
|
||||||
|
lastKeepAlive := time.Now()
|
||||||
|
// sendKeepAliveIfDue sends an ACK if the keepalive interval has elapsed.
|
||||||
|
// ACK refreshes the server's last-seen without re-sending CONFIG (which a
|
||||||
|
// repeated CONNECT would trigger).
|
||||||
|
sendKeepAliveIfDue := func() error {
|
||||||
|
if u.keepAliveInterval > 0 && time.Since(lastKeepAlive) >= u.keepAliveInterval {
|
||||||
|
if _, err := conn.WriteToUDP(udpsprotocol.BuildAckPacket(), serverAddr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lastKeepAlive = time.Now()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
reassembler := udpsprotocol.NewReassembler(2 * time.Second)
|
reassembler := udpsprotocol.NewReassembler(2 * time.Second)
|
||||||
buf := make([]byte, readBufSize)
|
buf := make([]byte, readBufSize)
|
||||||
@@ -260,14 +281,34 @@ func (u *UDPClient) runSession() error {
|
|||||||
var currentPublishMode uint8
|
var currentPublishMode uint8
|
||||||
|
|
||||||
for {
|
for {
|
||||||
conn.SetReadDeadline(time.Now().Add(silenceTimeout))
|
// Wake up at least every keepalive interval so ACKs are sent even
|
||||||
|
// when the server is idle; the read deadline also doubles as the
|
||||||
|
// silence detector (no data for silenceTimeout = server gone).
|
||||||
|
wakeup := silenceTimeout
|
||||||
|
if u.keepAliveInterval > 0 && u.keepAliveInterval < wakeup {
|
||||||
|
wakeup = u.keepAliveInterval
|
||||||
|
}
|
||||||
|
conn.SetReadDeadline(time.Now().Add(wakeup))
|
||||||
|
|
||||||
n, _, err := conn.ReadFromUDP(buf)
|
n, _, err := conn.ReadFromUDP(buf)
|
||||||
arrivalTime := time.Now()
|
arrivalTime := time.Now()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if ne, ok := err.(net.Error); ok && ne.Timeout() {
|
||||||
|
if time.Since(lastData) >= silenceTimeout {
|
||||||
|
// True silence: stream is dead — Run() reconnects.
|
||||||
|
conn.WriteToUDP(udpsprotocol.BuildDisconnectPacket(), serverAddr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Short wakeup: keepalive if due, then keep waiting.
|
||||||
|
if kaErr := sendKeepAliveIfDue(); kaErr != nil {
|
||||||
|
return kaErr
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
conn.WriteToUDP(udpsprotocol.BuildDisconnectPacket(), serverAddr)
|
conn.WriteToUDP(udpsprotocol.BuildDisconnectPacket(), serverAddr)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
lastData = arrivalTime
|
||||||
|
|
||||||
if n < udpsprotocol.HeaderSize {
|
if n < udpsprotocol.HeaderSize {
|
||||||
log.Printf("[%s] udp: short datagram (%d bytes), skipping", u.sourceID, n)
|
log.Printf("[%s] udp: short datagram (%d bytes), skipping", u.sourceID, n)
|
||||||
@@ -334,6 +375,10 @@ func (u *UDPClient) runSession() error {
|
|||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if kaErr := sendKeepAliveIfDue(); kaErr != nil {
|
||||||
|
return kaErr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,282 @@
|
|||||||
|
# E2E Test Suite
|
||||||
|
|
||||||
|
The streaming-chain end-to-end suite (`Test/E2E/suite/`) validates the full data path from
|
||||||
|
MARTe2 real-time application through the UDPS wire protocol to StreamHub and client consumers.
|
||||||
|
It also covers the debug/trace path (DebugService, TCPLogger) and the direct
|
||||||
|
UDPStreamer-to-UDPStreamerClient round-trip.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The suite is driven by a single orchestrator script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source env.sh
|
||||||
|
./Test/E2E/suite/run_e2e.sh [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
For each scenario defined in `scenarios.py`, the orchestrator:
|
||||||
|
|
||||||
|
1. **Generates input data** (`gen_data.py`) — deterministic typed/shaped binary in MARTe2
|
||||||
|
FileReader format, plus a ground-truth dict for the validator.
|
||||||
|
2. **Generates configs** (`gen_cfg.py`) — MARTe2 app config (LinuxTimer + FileReader + IOGAM +
|
||||||
|
UDPStreamer) and StreamHub config, per scenario.
|
||||||
|
3. **Launches the server stack** — MARTe2 app + StreamHub (for chain/recorder scenarios) or
|
||||||
|
MARTe2 app alone (for direct/debug scenarios).
|
||||||
|
4. **Drives mock clients** — the Go `chain-client` (chain scenarios) or `debugclient`
|
||||||
|
(debug/tcplogger scenarios) connects, records data, and runs behavioural checks.
|
||||||
|
5. **Validates** (`validate_waveform.py`) — compares the recorded stream against the analytic
|
||||||
|
ground truth and/or the fed-reference tap file.
|
||||||
|
6. **Renders plots** (`plots.py`) — waveform, trigger, and zoom overlay PNGs per scenario.
|
||||||
|
7. **Runs unit tests + coverage** (`collect.py`) — C++ GTest, Go, and Python suites with
|
||||||
|
optional lcov C++ line coverage.
|
||||||
|
8. **Runs stress matrix** (`stress_run.py` / `stress.py`) — capacity sweeps (signal size,
|
||||||
|
count, fan-out, zoom rate) with survival/liveness/RSS/latency gates.
|
||||||
|
9. **Builds the report** (`report_build.py`) — consolidates everything into
|
||||||
|
`report_data.json` with regression tracking against the previous run, trend plots, and a
|
||||||
|
Typst PDF (`E2E_Report.typ`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Flags
|
||||||
|
|
||||||
|
| Flag | Effect |
|
||||||
|
| -------------------- | -------------------------------------------------------- |
|
||||||
|
| `--skip-build` | Skip C++ component rebuild |
|
||||||
|
| `--only <id>` | Run a single scenario by ID |
|
||||||
|
| `--pdf-only` | Just compile the Typst PDF report (no tests) |
|
||||||
|
| `--cpp-coverage` | Instrumented gcov rebuild + lcov capture (on by default) |
|
||||||
|
| `--skip-coverage` | Disable the coverage pass |
|
||||||
|
| `--skip-stress` | Skip the stress matrix |
|
||||||
|
| `--skip-datasources` | Skip `direct` scenarios |
|
||||||
|
| `--skip-recorder` | Skip `recorder` scenarios |
|
||||||
|
| `--skip-debug` | Skip `debug` and `debug_pause_resume` scenarios |
|
||||||
|
| `--skip-tcplogger` | Skip `tcplogger` scenarios |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Scenario Kinds
|
||||||
|
|
||||||
|
### chain
|
||||||
|
|
||||||
|
Full streaming pipeline: MARTe2 (FileReader -> IOGAM -> UDPStreamer) -> StreamHub -> Go
|
||||||
|
`chain-client`. The client records the live binary stream and runs behavioural checks
|
||||||
|
(live, zoom, window, trigger). The validator compares the recording against the analytic
|
||||||
|
ground truth (fidelity, sine shape fit, continuity) and optionally a fed-reference tap.
|
||||||
|
|
||||||
|
### direct
|
||||||
|
|
||||||
|
MARTe2 FileReader -> UDPStreamer -> UDPStreamerClient -> FileWriter round-trip. Validates that
|
||||||
|
the written binary matches the input binary (bit-exact for each signal type).
|
||||||
|
|
||||||
|
### recorder
|
||||||
|
|
||||||
|
MARTe2 -> UDPStreamer -> StreamHub with BinaryRecorder enabled. Validates the `.bin` file
|
||||||
|
written to disk by the recorder against the original input.
|
||||||
|
|
||||||
|
### debug / debug_pause_resume
|
||||||
|
|
||||||
|
DebugService scenarios exercising FORCE, TRACE, and BREAK commands over TCP (port 8080) with
|
||||||
|
trace telemetry on UDP (port 8081). The Go `debugclient` scripts a fixed command sequence and
|
||||||
|
verifies real acknowledgements. The `debug_pause_resume` variant additionally verifies that
|
||||||
|
PAUSE halts the RT loop and RESUME restarts it via live VALUE polling.
|
||||||
|
|
||||||
|
### tcplogger
|
||||||
|
|
||||||
|
TCPLogger delivery: verifies that a triggered DebugService event produces a log line on the
|
||||||
|
TCPLogger TCP port (8082/9090).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Validation Oracles
|
||||||
|
|
||||||
|
Each chain scenario specifies an `oracle` mode:
|
||||||
|
|
||||||
|
- **analytic** — ground truth is reconstructed from `gen_data.py`'s deterministic formulas
|
||||||
|
(sine, ramp, counter, time_us, time_ns). No reference file needed.
|
||||||
|
- **fed** — a second IOGAM branch in the MARTe config taps the same signals into a FileWriter
|
||||||
|
("tap file"). The validator compares recordings against this tap.
|
||||||
|
- **both** — both oracles are applied.
|
||||||
|
|
||||||
|
Per-signal checks (`validate_waveform.py`):
|
||||||
|
|
||||||
|
| Check | Description |
|
||||||
|
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| **Fidelity** | Every received value within tolerance of some ground-truth value. Tolerance is 0 for raw integers, float epsilon for raw floats, `quant_step/2 + 1e-6*range` for quantised floats. |
|
||||||
|
| **Shape** | Sine signals (>= 8 points): least-squares fit of `a*sin(wt)+b*cos(wt)+c`. Requires correlation >= 0.99 and low normalised RMSE (relaxed by quant step). |
|
||||||
|
| **Fed reference** | When `--tap` is given, each received value must also match the tap. |
|
||||||
|
| **Continuity** | Flags inter-sample gaps > 10x median spacing. Fails when summed gap duration exceeds 5% of capture span. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client Checks
|
||||||
|
|
||||||
|
The Go `chain-client` (`Test/E2E/suite/client/`) performs behavioural checks specified per
|
||||||
|
scenario in `client_checks`:
|
||||||
|
|
||||||
|
| Check | What it verifies |
|
||||||
|
| --------- | ----------------------------------------------------------------------------------------------- |
|
||||||
|
| `live` | WebSocket connection succeeds and live binary pushes arrive with monotonic timestamps. |
|
||||||
|
| `zoom` | A `zoom` WS command returns a valid binary response covering the requested time range. |
|
||||||
|
| `window` | A `window` WS command returns data within the specified time bounds. |
|
||||||
|
| `trigger` | A `trigger` WS command on the specified signal fires and returns data around the trigger point. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stress Matrix
|
||||||
|
|
||||||
|
The stress module (`stress.py` + `stress_run.py`) exercises capacity by sweeping one load axis
|
||||||
|
at a time:
|
||||||
|
|
||||||
|
| Axis | What is scaled |
|
||||||
|
| ------------------ | ------------------------------------------------------------ |
|
||||||
|
| Signal size | Bytes per packet (array element count) |
|
||||||
|
| Signal count | Number of signals per source |
|
||||||
|
| Subscriber fan-out | Number of StreamHub instances subscribing to one UDPStreamer |
|
||||||
|
| WS client count | Parallel WebSocket clients on one StreamHub |
|
||||||
|
| Zoom request rate | Concurrent zoom queries per second per client |
|
||||||
|
|
||||||
|
Gates:
|
||||||
|
|
||||||
|
- **Survival** (hard) — neither server crashed or hung.
|
||||||
|
- **Liveness** (hard) — every client received monotonic, timestamped pushes.
|
||||||
|
- **Peak RSS** (soft) — MARTe and StreamHub memory stayed under case ceilings.
|
||||||
|
- **Zoom p95 latency** (soft) — round-trip zoom query latency under load.
|
||||||
|
|
||||||
|
Results are written to `stress_results.json` with axis/level for scaling-curve plots.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifacts
|
||||||
|
|
||||||
|
| Path | Content |
|
||||||
|
| -------------------------------------------- | ------------------------------------------------------------------- |
|
||||||
|
| `Build/x86-linux/E2E/chain/results.json` | Per-scenario status (PASS/FAIL/SKIP/XFAIL/XPASS) + waveform metrics |
|
||||||
|
| `Build/x86-linux/E2E/chain/report_data.json` | Full report data including regression diffs |
|
||||||
|
| `Build/x86-linux/E2E/chain/history.jsonl` | One-line-per-run headline metrics for trend tracking |
|
||||||
|
| `Build/x86-linux/E2E/chain/trend_*.png` | Pass-rate / coverage / fidelity / memory trend plots |
|
||||||
|
| `Build/x86-linux/E2E/chain/E2E_Report.pdf` | Compiled Typst PDF report |
|
||||||
|
| `Build/x86-linux/E2E/chain/unit_tests.json` | Per-suite test results (GTest, Go, Python) |
|
||||||
|
| `Build/x86-linux/E2E/chain/coverage.json` | Per-language coverage percentages |
|
||||||
|
| `Build/x86-linux/E2E/chain/stress/` | Stress matrix results |
|
||||||
|
| `Build/x86-linux/E2E/chain/hub_<id>.log` | StreamHub stdout/stderr per scenario |
|
||||||
|
| `Build/x86-linux/E2E/chain/marte_<id>.log` | MARTe2 app stdout/stderr per scenario |
|
||||||
|
| `Build/x86-linux/E2E/chain/client_<id>.log` | Client stdout/stderr per scenario |
|
||||||
|
| `/tmp/chain_e2e/` | Scratch: input binaries, configs, recordings, metrics, plots |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## XFAIL / XPASS Handling
|
||||||
|
|
||||||
|
Scenarios may carry a `known_issue` marker (a human-readable string describing a documented,
|
||||||
|
not-yet-fixed chain gap). When present:
|
||||||
|
|
||||||
|
- A raw **FAIL** is reclassified as **XFAIL** (expected failure) — does not break the green
|
||||||
|
baseline.
|
||||||
|
- A raw **PASS** becomes **XPASS** (unexpectedly fixed) — surfaced as a failure to prompt
|
||||||
|
removal of the stale marker.
|
||||||
|
|
||||||
|
Overall status is PASS when there are no hard FAILs and no XPASSes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Framework Files
|
||||||
|
|
||||||
|
| File | Role |
|
||||||
|
| ---------------------- | --------------------------------------------------------------- |
|
||||||
|
| `run_e2e.sh` | Top-level orchestrator (build, run scenarios, coverage, report) |
|
||||||
|
| `scenarios.py` | Declarative scenario matrix + validation |
|
||||||
|
| `gen_data.py` | Deterministic input binary generator |
|
||||||
|
| `gen_cfg.py` | MARTe2 + StreamHub config generator |
|
||||||
|
| `validate_waveform.py` | Waveform comparison (fidelity, shape, continuity) |
|
||||||
|
| `plots.py` | Per-scenario PNG figure renderer |
|
||||||
|
| `collect.py` | Unit test runner + coverage collector (GTest, Go, Python, lcov) |
|
||||||
|
| `report_build.py` | Report data consolidator + trend plots + history |
|
||||||
|
| `stress.py` | Declarative stress case matrix |
|
||||||
|
| `stress_run.py` | Stress matrix orchestrator |
|
||||||
|
| `proc_perf.py` | Live-process CPU/RSS snapshot from `/proc` |
|
||||||
|
| `E2E_Report.typ` | Typst template for the PDF report |
|
||||||
|
| `tests_py.py` | Python framework unit tests (`python3 -m unittest tests_py`) |
|
||||||
|
| `client/main.go` | Go chain-client (live record + zoom/window/trigger checks) |
|
||||||
|
| `debugclient/main.go` | Go debug/tcplogger client (command scripting + verification) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Scenario Matrix
|
||||||
|
|
||||||
|
| ID | Kind | Description |
|
||||||
|
| ----------------------------- | ------------------ | ---------------------------------------------------------------------------------------- |
|
||||||
|
| `s01_scalar_uint32` | chain | Single uint32 scalar counter, Strict unicast (type fidelity) |
|
||||||
|
| `s02_array_float32_fullarray` | chain | 100-elem float32 array, FullArray time mode, uint64 ns time array |
|
||||||
|
| `s03_quant_uint16` | chain | float32 scalar quantised to uint16 over [-5,5], Strict unicast |
|
||||||
|
| `s04_int8_scalar` | chain | int8 scalar counter, type fidelity |
|
||||||
|
| `s05_uint8_scalar` | chain | uint8 scalar counter, type fidelity |
|
||||||
|
| `s06_int16_scalar` | chain | int16 scalar ramp, type fidelity |
|
||||||
|
| `s07_uint16_scalar` | chain | uint16 scalar ramp, type fidelity |
|
||||||
|
| `s08_int32_scalar` | chain | int32 scalar counter, type fidelity |
|
||||||
|
| `s09_int64_scalar` | chain | int64 scalar counter, type fidelity |
|
||||||
|
| `s10_uint64_scalar` | chain | uint64 scalar counter, type fidelity |
|
||||||
|
| `s11_float64_scalar` | chain | float64 scalar sine 5 Hz (double-precision path) |
|
||||||
|
| `s12_f32_arr8` | chain | float32 8-elem array sine 5 Hz |
|
||||||
|
| `s13_f32_arr32` | chain | float32 32-elem array sine 10 Hz |
|
||||||
|
| `s14_f64_arr64` | chain | float64 64-elem array ramp |
|
||||||
|
| `s15_i16_arr16` | chain | int16 16-elem array counter |
|
||||||
|
| `s16_f32_arr256` | chain | float32 256-elem array sine 5 Hz (large frame) |
|
||||||
|
| `s17_lastsample` | chain | float32 8-elem LastSample, uint64 ns scalar anchor |
|
||||||
|
| `s18_firstsample` | chain | float32 8-elem FirstSample, uint32 us scalar anchor |
|
||||||
|
| `s19_fullarray_f64` | chain | float64 50-elem FullArray sine 5 Hz, uint64 ns time |
|
||||||
|
| `s20_quant_uint8` | chain | float32 scalar quant uint8 [-1,1] sine 5 Hz |
|
||||||
|
| `s21_quant_int8` | chain | float32 scalar quant int8 [-10,10] sine 5 Hz |
|
||||||
|
| `s22_quant_int16` | chain | float32 scalar quant int16 [-100,100] ramp |
|
||||||
|
| `s23_quant_f64_arr` | chain | float64 16-elem quant uint16 [-2,2] sine 5 Hz |
|
||||||
|
| `s24_accumulate` | chain | float32 scalar sine 5 Hz, Accumulate @50 Hz refresh |
|
||||||
|
| `s25_decimate4` | chain | float32 scalar sine 5 Hz, Decimate ratio 4 |
|
||||||
|
| `s26_decimate10_arr` | chain | float32 8-elem counter, Decimate ratio 10 |
|
||||||
|
| `s27_frag_f64_128` | chain | float64 128-elem ramp, MaxPayload 512 (fragmented) |
|
||||||
|
| `s28_frag_f32_100` | chain | float32 100-elem sine 5 Hz, MaxPayload 256 (fragmented) |
|
||||||
|
| `s29_mcast_scalar` | chain | multicast float32 scalar sine 5 Hz |
|
||||||
|
| `s30_mcast_arr_fullarray` | chain | multicast float32 32-elem FullArray sine 5 Hz |
|
||||||
|
| `s31_two_src` | chain | two unicast sources: float32 sine + uint32 counter |
|
||||||
|
| `s32_three_src` | chain | three unicast sources: int16 ramp / float64 sine / uint8 counter |
|
||||||
|
| `s33_dec_arr_quant` | chain | Decimate 2 + 16-elem quant uint16 sine 5 Hz |
|
||||||
|
| `s34_acc_fullarray` | chain | Accumulate @100 Hz: accumulated scalar + 32-elem FullArray sine passenger |
|
||||||
|
| `s35_mcast_decimate` | chain | multicast + Decimate ratio 5, float32 scalar sine 5 Hz |
|
||||||
|
| `s36_big_frag_dec` | chain | float64 64-elem ramp, MaxPayload 256 + Decimate 4 |
|
||||||
|
| `s37_trig_ramp_i32` | chain | trigger on int32 ramp scalar |
|
||||||
|
| `s38_trig_f64_sine` | chain | trigger on float64 sine 5 Hz scalar |
|
||||||
|
| `s39_uint8_arr32` | chain | uint8 32-elem array counter (wrap fidelity) |
|
||||||
|
| `s40_int8_arr16` | chain | int8 16-elem array counter (wrap fidelity) |
|
||||||
|
| `s41_f32_unit` | chain | float32 scalar ramp with Unit=V |
|
||||||
|
| `s42_f64_counter` | chain | float64 scalar counter (large integer values) |
|
||||||
|
| `s43_fullarray_quant` | chain | float32 16-elem FullArray quant uint16 sine 5 Hz |
|
||||||
|
| `s44_window_check` | chain | float32 sine 5 Hz scalar, window time-range check |
|
||||||
|
| `s45_decimate_multisig` | chain | Decimate ratio 2 over a 2-signal source |
|
||||||
|
| `s46_accumulate_arr` | chain | Accumulate @200 Hz: accumulated scalar sine + 16-elem array passenger |
|
||||||
|
| `s47_mcast_multisrc` | chain | multicast, two sources (scalar each) |
|
||||||
|
| `s48_f64_arr_big_payload` | chain | float64 100-elem ramp, MaxPayload 65490 (single frame) |
|
||||||
|
| `s49_mixed_quant_raw` | chain | one source: quant uint8 sine + raw float32 sine |
|
||||||
|
| `s50_trig_quant` | chain | trigger on quantised uint16 sine 10 Hz |
|
||||||
|
| `s51_8x1msps_100hz` | chain | 8x float32 10k-elem arrays @1 MSps, FirstSample, 100 Hz packets (~32 MB/s) |
|
||||||
|
| `s52_direct_unicast` | direct | Direct UDPStreamer->UDPStreamerClient round-trip, unicast |
|
||||||
|
| `s53_direct_multicast` | direct | Direct UDPStreamer->UDPStreamerClient round-trip, multicast |
|
||||||
|
| `s54_recorder` | recorder | StreamHub BinaryRecorder disk-output round-trip |
|
||||||
|
| `s55_debug_force_trace_break` | debug | DebugService FORCE/TRACE/BREAK over real TCP 8080 + UDP 8081 |
|
||||||
|
| `s56_tcplogger_delivery` | tcplogger | TCPLogger delivers a log line for a triggered DebugService event |
|
||||||
|
| `s57_debug_pause_resume` | debug_pause_resume | DebugService PAUSE/RESUME halts and resumes the RT loop, verified via live VALUE polling |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Coverage Goals
|
||||||
|
|
||||||
|
The chain scenario matrix is a curated covering set: every configurable UDPStreamer option
|
||||||
|
value appears in at least one scenario:
|
||||||
|
|
||||||
|
- **All 10 MARTe2 types**: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64
|
||||||
|
- **Scalar and array shapes**: elements 1, 8, 16, 32, 50, 64, 100, 128, 256, 1000, 10000
|
||||||
|
- **All four TimeModes**: PacketTime, FullArray, FirstSample, LastSample
|
||||||
|
- **All five QuantizedTypes**: none, uint8, int8, uint16, int16
|
||||||
|
- **All three PublishingModes**: Strict, Accumulate, Decimate
|
||||||
|
- **Both network modes**: unicast and multicast
|
||||||
|
- **Fragmentation**: small MaxPayloadSize forcing multi-fragment datagrams
|
||||||
|
- **Multi-source**: 1, 2, and 3 independent UDPStreamer feeds into one StreamHub
|
||||||
|
- **High-risk interactions**: decimate+quant+array, accumulate+fullarray, multicast+decimate,
|
||||||
|
fragmentation+decimate, mixed quant+raw signals
|
||||||
+10
-14
@@ -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
|
||||||
|
|
||||||
|
|||||||
+145
-31
@@ -8,7 +8,9 @@ thread.
|
|||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
- **Zero-copy RT path** — `Synchronise()` only locks, copies signal memory, and posts a semaphore.
|
- **Zero-copy RT path** — `Synchronise()` only locks, copies signal memory, and posts a semaphore.
|
||||||
- **Single-client model** — one client at a time; a new CONNECT replaces the previous session.
|
- **Unicast and multicast** — unicast (default): single client at a time, new CONNECT replaces
|
||||||
|
the previous session. Multicast: multiple clients receive data simultaneously by joining
|
||||||
|
a multicast group; control traffic uses a TCP listener.
|
||||||
- **Packet fragmentation** — large payloads are split into ≤ `MaxPayloadSize`-byte datagrams,
|
- **Packet fragmentation** — large payloads are split into ≤ `MaxPayloadSize`-byte datagrams,
|
||||||
each with a header carrying fragment index and total count so the client can reassemble them.
|
each with a header carrying fragment index and total count so the client can reassemble them.
|
||||||
- **Signal quantization** — `float32`/`float64` signals can be linearly quantized to
|
- **Signal quantization** — `float32`/`float64` signals can be linearly quantized to
|
||||||
@@ -16,6 +18,8 @@ thread.
|
|||||||
- **Temporal arrays** — signals with `NumberOfElements > 1` can carry per-sample time
|
- **Temporal arrays** — signals with `NumberOfElements > 1` can carry per-sample time
|
||||||
metadata via `TimeMode` and `TimeSignal`, enabling high-frequency burst transmission
|
metadata via `TimeMode` and `TimeSignal`, enabling high-frequency burst transmission
|
||||||
(e.g. 1 000 samples per RT cycle at 1 MSps).
|
(e.g. 1 000 samples per RT cycle at 1 MSps).
|
||||||
|
- **Publishing modes** — `Strict` (one packet per RT cycle), `Accumulate` (batch N snapshots
|
||||||
|
then flush on size or time limit), `Decimate` (send every Nth cycle).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -26,10 +30,22 @@ thread.
|
|||||||
Class = UDPStreamer
|
Class = UDPStreamer
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
Port = 44500 // UDP port the server listens on (default: 44500)
|
Port = 44500 // UDP port (unicast) or TCP control port (multicast)
|
||||||
MaxPayloadSize = 1400 // Maximum bytes per UDP datagram (default: 1400)
|
MaxPayloadSize = 1400 // Maximum bytes per UDP datagram (default: 1400)
|
||||||
// Must be > 17 (header size). Tune for MTU.
|
// Must be > 17 (header size). Tune for MTU.
|
||||||
|
|
||||||
|
// Multicast (optional — omit for unicast mode)
|
||||||
|
MulticastGroup = "239.0.0.1" // IPv4 multicast address (224.0.0.0/4)
|
||||||
|
Interface = "eth0" // Multicast-bound interface (mandatory when MulticastGroup is set)
|
||||||
|
DataPort = 44501 // UDP port for multicast DATA (default: Port+1)
|
||||||
|
|
||||||
|
// Publishing mode (optional)
|
||||||
|
PublishingMode = "Strict" // Strict | Accumulate | Decimate
|
||||||
|
// For Accumulate mode:
|
||||||
|
MinRefreshRate = 120.0 // Flush frequency in Hz (required for Accumulate)
|
||||||
|
// For Decimate mode:
|
||||||
|
Ratio = 10 // Send 1 packet every N RT cycles (required for Decimate)
|
||||||
|
|
||||||
// Background thread (optional)
|
// Background thread (optional)
|
||||||
CPUMask = 0x2 // CPU affinity mask for the network thread
|
CPUMask = 0x2 // CPU affinity mask for the network thread
|
||||||
StackSize = 1048576 // Stack size in bytes (default: 1 MiB)
|
StackSize = 1048576 // Stack size in bytes (default: 1 MiB)
|
||||||
@@ -66,34 +82,40 @@ thread.
|
|||||||
|
|
||||||
### Top-level Parameters
|
### Top-level Parameters
|
||||||
|
|
||||||
| Parameter | Type | Default | Description |
|
| Parameter | Type | Default | Description |
|
||||||
|-----------|------|---------|-------------|
|
| ---------------- | ------ | ---------------- | --------------------------------------------------------------------------- |
|
||||||
| `Port` | uint16 | 44500 | UDP server port |
|
| `Port` | uint16 | 44500 | UDP server port (unicast) or TCP control port (multicast). Values ≤ 1024 produce a warning. |
|
||||||
| `MaxPayloadSize` | uint32 | 1400 | Max payload bytes per UDP datagram (min 18) |
|
| `MaxPayloadSize` | uint32 | 1400 | Max payload bytes per UDP datagram (min 18) |
|
||||||
| `CPUMask` | uint32 | 0 (any) | Background thread CPU affinity |
|
| `MulticastGroup` | string | *(absent)* | IPv4 multicast address (e.g. `"239.0.0.1"`). Must be in 224.0.0.0/4. Absent or empty = unicast mode. |
|
||||||
| `StackSize` | uint32 | 1 048 576 | Background thread stack size in bytes |
|
| `Interface` | string | *(absent)* | Network interface for multicast binding (e.g. `"eth0"`). **Mandatory** when `MulticastGroup` is set. |
|
||||||
|
| `DataPort` | uint16 | Port+1 | UDP port for multicast DATA datagrams. Ignored in unicast mode. |
|
||||||
|
| `PublishingMode` | string | Strict | `Strict`: send every RT cycle. `Accumulate`: batch until size/time limit. `Decimate`: send every Nth cycle. |
|
||||||
|
| `MinRefreshRate` | float64| — | Flush frequency in Hz. **Required** when `PublishingMode` = `Accumulate`. |
|
||||||
|
| `Ratio` | uint32 | — | Send 1 packet every `Ratio` RT cycles. **Required** when `PublishingMode` = `Decimate`. |
|
||||||
|
| `CPUMask` | uint32 | 0xFFFFFFFF (any) | Background thread CPU affinity bitmask |
|
||||||
|
| `StackSize` | uint32 | MARTe2 default | Background thread stack size in bytes |
|
||||||
|
|
||||||
### Per-signal Parameters
|
### Per-signal Parameters
|
||||||
|
|
||||||
| Parameter | Type | Default | Applies to |
|
| Parameter | Type | Default | Applies to |
|
||||||
|-----------|------|---------|------------|
|
| --------------- | ------- | ------------ | -------------------------------------------------------- |
|
||||||
| `Unit` | string | `""` | Any type — informational, forwarded to client in CONFIG |
|
| `Unit` | string | `""` | Any type — informational, forwarded to client in CONFIG |
|
||||||
| `RangeMin` | float64 | 0.0 | float32/float64 with `QuantizedType` |
|
| `RangeMin` | float64 | 0.0 | float32/float64 with `QuantizedType` |
|
||||||
| `RangeMax` | float64 | 1.0 | float32/float64 with `QuantizedType` |
|
| `RangeMax` | float64 | 1.0 | float32/float64 with `QuantizedType` |
|
||||||
| `QuantizedType` | string | `none` | float32/float64 only |
|
| `QuantizedType` | string | `none` | float32/float64 only |
|
||||||
| `TimeMode` | string | `PacketTime` | Signals with `NumberOfElements > 1` |
|
| `TimeMode` | string | `PacketTime` | Signals with `NumberOfElements > 1` |
|
||||||
| `TimeSignal` | string | — | Required when `TimeMode` ≠ `PacketTime` |
|
| `TimeSignal` | string | — | Required when `TimeMode` ≠ `PacketTime` |
|
||||||
| `SamplingRate` | float64 | 0.0 | Required when `TimeMode` = `FirstSample` or `LastSample` |
|
| `SamplingRate` | float64 | 0.0 | Required when `TimeMode` = `FirstSample` or `LastSample` |
|
||||||
|
|
||||||
### Quantization Types
|
### Quantization Types
|
||||||
|
|
||||||
| Value | Wire type | Bit depth | Notes |
|
| Value | Wire type | Bit depth | Notes |
|
||||||
|-------|-----------|-----------|-------|
|
| -------- | -------------- | --------- | ------------------------------------------------- |
|
||||||
| `none` | same as source | — | Raw copy, no quantization |
|
| `none` | same as source | — | Raw copy, no quantization |
|
||||||
| `uint8` | uint8 | 8-bit | Maps `[RangeMin, RangeMax]` → `[0, 255]` |
|
| `uint8` | uint8 | 8-bit | Maps `[RangeMin, RangeMax]` → `[0, 255]` |
|
||||||
| `int8` | int8 | 8-bit | Maps `[RangeMin, RangeMax]` → `[-127, 127]` |
|
| `int8` | int8 | 8-bit | Maps `[RangeMin, RangeMax]` → `[-127, 127]` |
|
||||||
| `uint16` | uint16 | 16-bit | Maps `[RangeMin, RangeMax]` → `[0, 65 535]` |
|
| `uint16` | uint16 | 16-bit | Maps `[RangeMin, RangeMax]` → `[0, 65 535]` |
|
||||||
| `int16` | int16 | 16-bit | Maps `[RangeMin, RangeMax]` → `[-32 767, 32 767]` |
|
| `int16` | int16 | 16-bit | Maps `[RangeMin, RangeMax]` → `[-32 767, 32 767]` |
|
||||||
|
|
||||||
Quantization formula (unsigned, e.g. uint16):
|
Quantization formula (unsigned, e.g. uint16):
|
||||||
|
|
||||||
@@ -104,12 +126,68 @@ wire_value = (uint16)(normalized × 65535)
|
|||||||
|
|
||||||
### Time Modes
|
### Time Modes
|
||||||
|
|
||||||
| Value | Meaning | Requirements |
|
| Value | Meaning | Requirements |
|
||||||
|-------|---------|--------------|
|
| ------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
|
||||||
| `PacketTime` | The HRT counter captured at `Synchronise()` time is used as the packet timestamp. No per-signal time metadata. | — |
|
| `PacketTime` | The HRT counter captured at `Synchronise()` time is used as the packet timestamp. No per-signal time metadata. | — |
|
||||||
| `FullArray` | `TimeSignal` carries one timestamp per element (same `NumberOfElements`). | `TimeSignal` must have the same `NumberOfElements`. |
|
| `FullArray` | `TimeSignal` carries one timestamp per element (same `NumberOfElements`). | `TimeSignal` must have the same `NumberOfElements`. |
|
||||||
| `FirstSample` | `TimeSignal` is a scalar giving the timestamp of element `[0]`. Elements `[1..N-1]` are inferred at `1/SamplingRate` intervals. | Scalar `TimeSignal`; `SamplingRate > 0`. |
|
| `FirstSample` | `TimeSignal` is a scalar giving the timestamp of element `[0]`. Elements `[1..N-1]` are inferred at `1/SamplingRate` intervals. | Scalar `TimeSignal`; `SamplingRate > 0`. |
|
||||||
| `LastSample` | Same as `FirstSample` but `TimeSignal` is the timestamp of element `[N-1]`. | Scalar `TimeSignal`; `SamplingRate > 0`. |
|
| `LastSample` | Same as `FirstSample` but `TimeSignal` is the timestamp of element `[N-1]`. | Scalar `TimeSignal`; `SamplingRate > 0`. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Network Modes
|
||||||
|
|
||||||
|
### Unicast (default)
|
||||||
|
|
||||||
|
The server opens a single UDP socket on `Port`. The client initiates the session by sending a
|
||||||
|
CONNECT packet to that port. The server replies with a CONFIG packet on the same socket and
|
||||||
|
subsequently sends DATA packets directly to the client's address. One client at a time; a new
|
||||||
|
CONNECT evicts the previous client.
|
||||||
|
|
||||||
|
### Multicast
|
||||||
|
|
||||||
|
Enabled by setting `MulticastGroup` to a valid IPv4 multicast address (224.0.0.0/4).
|
||||||
|
The `Interface` parameter is **mandatory** and specifies the network interface to bind.
|
||||||
|
|
||||||
|
The server opens a TCP listener on `Port` for control traffic and a UDP socket aimed at
|
||||||
|
`MulticastGroup:DataPort` for data traffic. The client:
|
||||||
|
|
||||||
|
1. Connects to `Port` via TCP and sends a CONNECT packet.
|
||||||
|
2. Receives the CONFIG packet over TCP.
|
||||||
|
3. Joins the multicast group (`MulticastGroup:DataPort`) to receive DATA packets.
|
||||||
|
|
||||||
|
Multiple clients may receive data simultaneously by joining the same group.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Publishing Modes
|
||||||
|
|
||||||
|
### Strict (default)
|
||||||
|
|
||||||
|
Sends one DATA packet for every `Synchronise()` call (every RT cycle). Simplest and lowest
|
||||||
|
latency.
|
||||||
|
|
||||||
|
### Accumulate
|
||||||
|
|
||||||
|
Batches multiple RT-cycle snapshots into a single DATA packet. All signals (scalars and arrays)
|
||||||
|
are accumulated: one full snapshot per RT cycle. The batch is flushed when either:
|
||||||
|
|
||||||
|
- **Size condition**: adding one more sample would exceed `MaxPayloadSize`.
|
||||||
|
- **Time condition**: `1/MinRefreshRate` seconds have elapsed since the last flush.
|
||||||
|
|
||||||
|
The maximum batch count is computed automatically from `MaxPayloadSize` and the total wire size
|
||||||
|
of all signals. Scalar signals with `Unit="us"` or `"ns"` are auto-promoted as the per-sample
|
||||||
|
FullArray time reference for all other scalars.
|
||||||
|
|
||||||
|
Requires `MinRefreshRate` (Hz) to be set.
|
||||||
|
|
||||||
|
### Decimate
|
||||||
|
|
||||||
|
Sends one DATA packet every `Ratio` RT cycles, dropping intermediate cycles. Only the most
|
||||||
|
recent snapshot at the Nth cycle is sent.
|
||||||
|
|
||||||
|
Requires `Ratio` (≥ 1) to be set. `Ratio = 1` is equivalent to `Strict` mode (a warning is
|
||||||
|
logged).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -151,7 +229,7 @@ PrepareNextState() ← opens UDP server socket, starts background threa
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Example: minimal scalar streaming
|
## Example: minimal scalar streaming (unicast)
|
||||||
|
|
||||||
```
|
```
|
||||||
+Data = {
|
+Data = {
|
||||||
@@ -168,6 +246,26 @@ PrepareNextState() ← opens UDP server socket, starts background threa
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Example: multicast with accumulation
|
||||||
|
|
||||||
|
```
|
||||||
|
+Streamer = {
|
||||||
|
Class = UDPStreamer
|
||||||
|
Port = 44500 // TCP control port
|
||||||
|
MulticastGroup = "239.0.0.1" // Enables multicast mode
|
||||||
|
Interface = "eth0" // Mandatory for multicast
|
||||||
|
DataPort = 44501 // UDP data port (default: Port+1)
|
||||||
|
MaxPayloadSize = 1400
|
||||||
|
PublishingMode = "Accumulate"
|
||||||
|
MinRefreshRate = 60.0 // Flush at least 60 times/s
|
||||||
|
|
||||||
|
Signals = {
|
||||||
|
Time = { Type = uint32; Unit = "us" }
|
||||||
|
Voltage = { Type = float32; Unit = "V"; RangeMin = -10.0; RangeMax = 10.0; QuantizedType = uint16 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Example: high-frequency burst
|
## Example: high-frequency burst
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -198,3 +296,19 @@ With `MaxPayloadSize = 1400`, a single 1000-element float32 signal produces:
|
|||||||
payload = 8 B (HRT timestamp) + 4 B (T0/uint32) + 4000 B (float32×1000) = 4012 B
|
payload = 8 B (HRT timestamp) + 4 B (T0/uint32) + 4000 B (float32×1000) = 4012 B
|
||||||
fragments = ceil(4012 / 1383) = 3
|
fragments = ceil(4012 / 1383) = 3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Example: decimated output
|
||||||
|
|
||||||
|
```
|
||||||
|
+Streamer = {
|
||||||
|
Class = UDPStreamer
|
||||||
|
Port = 44500
|
||||||
|
PublishingMode = "Decimate"
|
||||||
|
Ratio = 10 // Send 1 packet every 10 RT cycles
|
||||||
|
|
||||||
|
Signals = {
|
||||||
|
Time = { Type = uint32; Unit = "us" }
|
||||||
|
Position = { Type = float64; Unit = "mm" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ for control applications built with [MARTe2](https://vcis.f4e.europa.eu/marte2-d
|
|||||||
|
|
||||||
This repository integrates two complementary capabilities:
|
This repository integrates two complementary capabilities:
|
||||||
|
|
||||||
| Capability | Component | Purpose |
|
| Capability | Component | Purpose |
|
||||||
|---|---|---|
|
| --------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------- |
|
||||||
| **Signal streaming** | `UDPStreamer` DataSource | Continuously stream selected signals to a browser-based oscilloscope over UDP |
|
| **Signal streaming** | `UDPStreamer` DataSource | Continuously stream selected signals to a browser-based oscilloscope over UDP |
|
||||||
| **Signal debugging** | `DebugService` Interface | On-demand signal tracing, value forcing, and conditional breakpoints — zero application code changes required |
|
| **Signal debugging** | `DebugService` Interface | On-demand signal tracing, value forcing, and conditional breakpoints — zero application code changes required |
|
||||||
| **Sine generation** | `SineArrayGAM` | Generate continuous sine-wave arrays for testing and simulation |
|
| **Sine generation** | `SineArrayGAM` | Generate continuous sine-wave arrays for testing and simulation |
|
||||||
| **Time stamping** | `TimeArrayGAM` | Provide time-reference arrays aligned to an RT cycle |
|
| **Time stamping** | `TimeArrayGAM` | Provide time-reference arrays aligned to an RT cycle |
|
||||||
| **Log forwarding** | `TCPLogger` Interface | Forward `REPORT_ERROR` log events to TCP clients in real time |
|
| **Log forwarding** | `TCPLogger` Interface | Forward `REPORT_ERROR` log events to TCP clients in real time |
|
||||||
| **Integrated client** | `Common/Client/go` | Go packages for UDPS protocol and WebSocket hub |
|
| **Integrated client** | `Common/Client/go` | Go packages for UDPS protocol and WebSocket hub |
|
||||||
| **Debug web client** | `Client/debugger` | Browser-based debug UI communicating with `DebugService` |
|
| **Debug web client** | `Client/debugger` | Browser-based debug UI communicating with `DebugService` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ MARTe_Integrated_components/
|
|||||||
|
|
||||||
### UDPStreamer DataSource
|
### UDPStreamer DataSource
|
||||||
|
|
||||||
Streams MARTe2 signals over UDP using the UDPS binary protocol. Clients register by
|
Streams MARTe2 signals over UDP using the UDPS binary protocol. Clients register by
|
||||||
sending a `CONNECT` packet; the server then sends `CONFIG` (signal metadata) and continuous
|
sending a `CONNECT` packet; the server then sends `CONFIG` (signal metadata) and continuous
|
||||||
`DATA` packets. Features:
|
`DATA` packets. Features:
|
||||||
|
|
||||||
- Optional 16-bit quantization (configurable per signal: `QuantizedType`)
|
- Optional 16-bit quantization (configurable per signal: `QuantizedType`)
|
||||||
- Packed high-frequency bursts (`NumberOfElements > 1` with `SamplingRate`)
|
- Packed high-frequency bursts (`NumberOfElements > 1` with `SamplingRate`)
|
||||||
@@ -61,8 +61,8 @@ See `Docs/UDPStreamer.md` and `Docs/Protocol.md`.
|
|||||||
|
|
||||||
### SineArrayGAM
|
### SineArrayGAM
|
||||||
|
|
||||||
Generates a continuous float32 sine-wave array every RT cycle. Used as a signal
|
Generates a continuous float32 sine-wave array every RT cycle. Used as a signal
|
||||||
source for testing and demo applications. Configurable: `Frequency`, `Amplitude`,
|
source for testing and demo applications. Configurable: `Frequency`, `Amplitude`,
|
||||||
`Phase`, `SamplingRate`, `NumberOfElements`.
|
`Phase`, `SamplingRate`, `NumberOfElements`.
|
||||||
|
|
||||||
See `Docs/SineArrayGAM.md`.
|
See `Docs/SineArrayGAM.md`.
|
||||||
@@ -75,12 +75,13 @@ configured `SamplingRate`.
|
|||||||
|
|
||||||
### DebugService Interface
|
### DebugService Interface
|
||||||
|
|
||||||
Instruments a running MARTe2 application **without modifying its source code**. On
|
Instruments a running MARTe2 application **without modifying its source code**. On
|
||||||
`Initialise()` it patches the `ClassRegistryDatabase` to wrap all standard
|
`Initialise()` it patches the `ClassRegistryDatabase` to wrap all standard
|
||||||
`MemoryMap*Broker` types. When `RealTimeApplication::ConfigureApplication()` runs
|
`MemoryMap*Broker` types. When `RealTimeApplication::ConfigureApplication()` runs
|
||||||
afterward the application transparently uses the wrapped brokers.
|
afterward the application transparently uses the wrapped brokers.
|
||||||
|
|
||||||
Capabilities accessible over TCP (port 8080 by default):
|
Capabilities accessible over TCP (port 8080 by default):
|
||||||
|
|
||||||
- `DISCOVER` — enumerate all signals with type and alias metadata
|
- `DISCOVER` — enumerate all signals with type and alias metadata
|
||||||
- `TRACE` — enable/disable high-speed UDP telemetry per signal (with decimation)
|
- `TRACE` — enable/disable high-speed UDP telemetry per signal (with decimation)
|
||||||
- `FORCE` / `UNFORCE` — inject persistent values into signals on the RT path
|
- `FORCE` / `UNFORCE` — inject persistent values into signals on the RT path
|
||||||
@@ -98,7 +99,7 @@ See `Docs/DebugService.md`.
|
|||||||
### TCPLogger Interface
|
### TCPLogger Interface
|
||||||
|
|
||||||
A `LoggerConsumerI` that forwards every MARTe2 `REPORT_ERROR` call to up to 8 TCP
|
A `LoggerConsumerI` that forwards every MARTe2 `REPORT_ERROR` call to up to 8 TCP
|
||||||
clients on a configurable port. Works as a sidecar to `DebugService`.
|
clients on a configurable port. Works as a sidecar to `DebugService`.
|
||||||
|
|
||||||
### StreamHub Application
|
### StreamHub Application
|
||||||
|
|
||||||
@@ -108,7 +109,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`.
|
||||||
@@ -116,7 +117,7 @@ See `Docs/StreamHub-UserGuide.md`, `Docs/StreamHub-API.md` and
|
|||||||
### UDPS Protocol
|
### UDPS Protocol
|
||||||
|
|
||||||
The `Common/UDP/UDPSProtocol.h` header defines the shared binary wire format used by
|
The `Common/UDP/UDPSProtocol.h` header defines the shared binary wire format used by
|
||||||
both `UDPStreamer` and `DebugService`. It is intentionally free of MARTe2-specific
|
both `UDPStreamer` and `DebugService`. It is intentionally free of MARTe2-specific
|
||||||
dependencies so it can also be used by Go clients (via `Common/Client/go/udpsprotocol`).
|
dependencies so it can also be used by Go clients (via `Common/Client/go/udpsprotocol`).
|
||||||
|
|
||||||
See `Docs/Protocol.md`.
|
See `Docs/Protocol.md`.
|
||||||
@@ -224,18 +225,18 @@ Open `http://localhost:9090`, explore the object tree, trace signals, force valu
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
| Document | Contents |
|
| Document | Contents |
|
||||||
|---|---|
|
| ----------------------------- | -------------------------------------------------------------- |
|
||||||
| `Docs/Protocol.md` | UDPS binary wire protocol specification |
|
| `Docs/Protocol.md` | UDPS binary wire protocol specification |
|
||||||
| `Docs/UDPStreamer.md` | UDPStreamer DataSource configuration reference |
|
| `Docs/UDPStreamer.md` | UDPStreamer DataSource configuration reference |
|
||||||
| `Docs/SineArrayGAM.md` | SineArrayGAM configuration reference |
|
| `Docs/SineArrayGAM.md` | SineArrayGAM configuration reference |
|
||||||
| `Docs/DebugService.md` | DebugService TCP API and architecture |
|
| `Docs/DebugService.md` | DebugService TCP API and architecture |
|
||||||
| `Docs/Tutorial.md` | Step-by-step tutorial covering both components |
|
| `Docs/Tutorial.md` | Step-by-step tutorial covering both components |
|
||||||
| `Docs/WebUI.md` | Web client user guide |
|
| `Docs/WebUI.md` | Web client user guide |
|
||||||
| `Docs/StreamHub-UserGuide.md` | StreamHub oscilloscope user guide (web + ImGui clients) |
|
| `Docs/StreamHub-UserGuide.md` | StreamHub oscilloscope user guide (web + ImGui clients) |
|
||||||
| `Docs/StreamHub-API.md` | StreamHub WebSocket protocol (commands, events, binary frames) |
|
| `Docs/StreamHub-API.md` | StreamHub WebSocket protocol (commands, events, binary frames) |
|
||||||
| `Docs/StreamHub-Developer.md` | StreamHub internals, threading, time base, build & E2E tests |
|
| `Docs/StreamHub-Developer.md` | StreamHub internals, threading, time base, build & E2E tests |
|
||||||
| `ARCHITECTURE.md` | System architecture overview |
|
| `ARCHITECTURE.md` | System architecture overview |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -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) &&
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,16 +140,17 @@ struct UDPStreamerSignalInfo {
|
|||||||
* fragmented into multiple datagrams if payload exceeds MaxPayloadSize).
|
* fragmented into multiple datagrams if payload exceeds MaxPayloadSize).
|
||||||
*
|
*
|
||||||
* @par Top-level configuration parameters
|
* @par Top-level configuration parameters
|
||||||
* | Parameter | Type | Default | Description |
|
* | Parameter | Type | Default | Description |
|
||||||
* |-----------------|---------|---------|-------------|
|
* |-----------------|---------|------------------|-------------|
|
||||||
* | Port | uint16 | 44500 | TCP control port (multicast) or UDP server port (unicast). Values ≤ 1024 produce a warning. |
|
* | Port | uint16 | 44500 | TCP control port (multicast) or UDP server port (unicast). Values ≤ 1024 produce a warning. |
|
||||||
* | MulticastGroup | string | *(absent)* | **Enables multicast mode.** IPv4 multicast address, e.g. `"239.0.0.1"`. Must be in 224.0.0.0/4. Absent or empty = unicast. |
|
* | MulticastGroup | string | *(absent)* | **Enables multicast mode.** IPv4 multicast address, e.g. `"239.0.0.1"`. Must be in 224.0.0.0/4. Absent or empty = unicast. |
|
||||||
* | DataPort | uint16 | Port+1 | UDP port for multicast DATA datagrams. Ignored in unicast mode. Must be non-zero and differ from Port. |
|
* | Interface | string | *(absent)* | Multicast binded interface **ONLY FOR MULTICAST** |
|
||||||
* | MaxPayloadSize | uint32 | 1400 | Maximum bytes of signal payload per UDP datagram (excluding the 17-byte header). Larger signals are fragmented. |
|
* | DataPort | uint16 | Port+1 | UDP port for multicast DATA datagrams. Ignored in unicast mode. Must be non-zero and differ from Port. |
|
||||||
* | PublishingMode | string | Strict | `Strict`: send one packet every Synchronise() call. `Auto`: rate-limited; flush only when MinRefreshRate interval has elapsed. |
|
* | MaxPayloadSize | uint32 | 1400 | Maximum bytes of signal payload per UDP datagram (excluding the 17-byte header). Larger signals are fragmented. |
|
||||||
* | MinRefreshRate | float64 | — | Required when PublishingMode = Auto. Flush frequency in Hz (e.g. 120.0). |
|
* | PublishingMode | string | Strict | `Strict`: send one packet every Synchronise() call. `Auto`: rate-limited; flush only when MinRefreshRate interval has elapsed. |
|
||||||
* | MaxBatchSize | uint32 | 1 | Optional when PublishingMode = Auto. Number of RT cycles to accumulate before flushing one packet. Scalar signals are expanded to arrays of MaxBatchSize elements; the first scalar with Unit="us" or "ns" is auto-promoted as the per-sample FullArray timestamp reference for all other scalars. When omitted or 1, the most-recent single value is sent at MinRefreshRate. |
|
* | MinRefreshRate | float64 | — | Required when PublishingMode = Auto. Flush frequency in Hz (e.g. 120.0). |
|
||||||
* | CPUMask | uint32 | 0xFFFFFFFF | CPU affinity bitmask for the background thread. |
|
* | MaxBatchSize | uint32 | 1 | Optional when PublishingMode = Auto. Number of RT cycles to accumulate before flushing one packet. Scalar signals are expanded to arrays of MaxBatchSize elements; the first scalar with Unit="us" or "ns" is auto-promoted as the per-sample FullArray timestamp reference for all other scalars. When omitted or 1, the most-recent single value is sent at MinRefreshRate. |
|
||||||
|
* | CPUMask | uint32 | 0xFFFFFFFF | CPU affinity bitmask for the background thread. |
|
||||||
* | StackSize | uint32 | (MARTe2 default) | Stack size in bytes for the background thread. |
|
* | StackSize | uint32 | (MARTe2 default) | Stack size in bytes for the background thread. |
|
||||||
*
|
*
|
||||||
* @par Per-signal configuration parameters
|
* @par Per-signal configuration parameters
|
||||||
@@ -358,8 +359,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 */
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
../../../..//Build/x86-linux/Components/DataSources/UDPStreamer/UDPStreamer.o: UDPStreamer.cpp \
|
../../../..//Build/x86-linux/Components/DataSources/UDPStreamer/UDPStreamer.o: UDPStreamer.cpp \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.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/CompilerTypes.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/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/BitBoolean.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/TemplateParametersVerificator.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.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/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/ErrorManagement.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.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/GeneralDefinitions.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.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/TimeoutType.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.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/TimeStamp.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.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/../../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/HighResolutionTimerCalibrator.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.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/TimeStamp.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.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/L3Streams/BufferedStreamI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.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/AnyType.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.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/L2Objects/ClassRegistryDatabase.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.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/GlobalObjectI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.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/../../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/Environment/Linux/../Generic/StandardHeap_Generic.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.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/Atomic.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.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/L1Portability/Sleep.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.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/CString.h \
|
||||||
@@ -53,7 +53,6 @@
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.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/FractionalInteger.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.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/ZeroTerminatedArray.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.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/LinkedListHolderT.h \
|
||||||
@@ -70,17 +69,18 @@
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.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/Matrix.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.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/MemoryOperationsHelper.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.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/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/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 \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.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/L4Configuration/AnyObject.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.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/StructuredDataI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.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/CLASSREGISTER.h \
|
||||||
@@ -104,8 +104,6 @@
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.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/L4Configuration/TypeConversion.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.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 \
|
||||||
@@ -116,18 +114,12 @@
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapSynchronisedOutputBroker.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapOutputBroker.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapBroker.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/BrokerI.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/L1Portability/Sleep.h \
|
|
||||||
UDPStreamer.h \
|
UDPStreamer.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.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/Scheduler/L3Services/SingleThreadService.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/EmbeddedServiceI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
||||||
@@ -141,5 +133,6 @@
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.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/Environment/Linux/SocketCore.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.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/FileSystem/L1Portability/InternetHost.h \
|
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
|
||||||
../../../..//Common/UDP/UDPSProtocol.h
|
../../../..//Common/UDP/UDPSProtocol.h
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
UDPStreamer.o: UDPStreamer.cpp \
|
UDPStreamer.o: UDPStreamer.cpp \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.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/CompilerTypes.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/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/BitBoolean.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/TemplateParametersVerificator.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.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/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/ErrorManagement.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.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/GeneralDefinitions.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.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/TimeoutType.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.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/TimeStamp.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.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/../../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/HighResolutionTimerCalibrator.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.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/TimeStamp.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.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/L3Streams/BufferedStreamI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.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/AnyType.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.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/L2Objects/ClassRegistryDatabase.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.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/GlobalObjectI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.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/../../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/Environment/Linux/../Generic/StandardHeap_Generic.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.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/Atomic.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.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/L1Portability/Sleep.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.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/CString.h \
|
||||||
@@ -53,7 +53,6 @@ UDPStreamer.o: UDPStreamer.cpp \
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.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/FractionalInteger.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.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/ZeroTerminatedArray.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.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/LinkedListHolderT.h \
|
||||||
@@ -70,17 +69,18 @@ UDPStreamer.o: UDPStreamer.cpp \
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.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/Matrix.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.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/MemoryOperationsHelper.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.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/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/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 \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.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/L4Configuration/AnyObject.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.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/StructuredDataI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.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/CLASSREGISTER.h \
|
||||||
@@ -104,8 +104,6 @@ UDPStreamer.o: UDPStreamer.cpp \
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.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/L4Configuration/TypeConversion.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.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 \
|
||||||
@@ -116,18 +114,12 @@ UDPStreamer.o: UDPStreamer.cpp \
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapSynchronisedOutputBroker.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapOutputBroker.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapBroker.h \
|
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/BrokerI.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/L1Portability/Sleep.h \
|
|
||||||
UDPStreamer.h \
|
UDPStreamer.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
|
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.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/Scheduler/L3Services/SingleThreadService.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/EmbeddedServiceI.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
|
||||||
@@ -141,5 +133,6 @@ UDPStreamer.o: UDPStreamer.cpp \
|
|||||||
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.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/Environment/Linux/SocketCore.h \
|
||||||
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.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/FileSystem/L1Portability/InternetHost.h \
|
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
|
||||||
../../../..//Common/UDP/UDPSProtocol.h
|
../../../..//Common/UDP/UDPSProtocol.h
|
||||||
|
|||||||
@@ -55,6 +55,12 @@ static const uint16 UDPS_CLIENT_DEFAULT_DP_OFFSET = 1u;
|
|||||||
/** Default max payload per UDP datagram (bytes). */
|
/** Default max payload per UDP datagram (bytes). */
|
||||||
static const uint32 UDPS_CLIENT_DEFAULT_MAX_PAYLOAD = 1400u;
|
static const uint32 UDPS_CLIENT_DEFAULT_MAX_PAYLOAD = 1400u;
|
||||||
|
|
||||||
|
/** Default unicast keepalive interval (seconds); 0 disables. */
|
||||||
|
static const uint32 UDPS_CLIENT_DEFAULT_KEEPALIVE_INTERVAL_S = 15u;
|
||||||
|
|
||||||
|
/** Default silence timeout before reconnect (seconds); sub-second values allowed. */
|
||||||
|
static const float32 UDPS_CLIENT_DEFAULT_SILENCE_TIMEOUT_S = 1.0f;
|
||||||
|
|
||||||
/** Bytes prepended to each DATA payload for the HRT packet timestamp. */
|
/** Bytes prepended to each DATA payload for the HRT packet timestamp. */
|
||||||
static const uint32 UDPS_CLIENT_TIMESTAMP_BYTES = 8u;
|
static const uint32 UDPS_CLIENT_TIMESTAMP_BYTES = 8u;
|
||||||
|
|
||||||
@@ -129,6 +135,8 @@ UDPStreamerClient::UDPStreamerClient() :
|
|||||||
serverAddress = UDPS_CLIENT_DEFAULT_ADDR;
|
serverAddress = UDPS_CLIENT_DEFAULT_ADDR;
|
||||||
port = UDPS_CLIENT_DEFAULT_PORT;
|
port = UDPS_CLIENT_DEFAULT_PORT;
|
||||||
maxPayloadSize = UDPS_CLIENT_DEFAULT_MAX_PAYLOAD;
|
maxPayloadSize = UDPS_CLIENT_DEFAULT_MAX_PAYLOAD;
|
||||||
|
keepAliveInterval = UDPS_CLIENT_DEFAULT_KEEPALIVE_INTERVAL_S;
|
||||||
|
silenceTimeout = UDPS_CLIENT_DEFAULT_SILENCE_TIMEOUT_S;
|
||||||
cpuMask = 0xFFFFFFFFu;
|
cpuMask = 0xFFFFFFFFu;
|
||||||
stackSize = THREADS_DEFAULT_STACKSIZE;
|
stackSize = THREADS_DEFAULT_STACKSIZE;
|
||||||
dataPort = UDPS_CLIENT_DEFAULT_PORT + UDPS_CLIENT_DEFAULT_DP_OFFSET;
|
dataPort = UDPS_CLIENT_DEFAULT_PORT + UDPS_CLIENT_DEFAULT_DP_OFFSET;
|
||||||
@@ -201,6 +209,18 @@ bool UDPStreamerClient::Initialise(StructuredDataI &data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
if (!data.Read("KeepAliveInterval", keepAliveInterval)) {
|
||||||
|
keepAliveInterval = UDPS_CLIENT_DEFAULT_KEEPALIVE_INTERVAL_S;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
if (!data.Read("SilenceTimeout", silenceTimeout)) {
|
||||||
|
silenceTimeout = UDPS_CLIENT_DEFAULT_SILENCE_TIMEOUT_S;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (!data.Read("CPUMask", cpuMask)) {
|
if (!data.Read("CPUMask", cpuMask)) {
|
||||||
cpuMask = 0xFFFFFFFFu;
|
cpuMask = 0xFFFFFFFFu;
|
||||||
@@ -245,6 +265,8 @@ bool UDPStreamerClient::Initialise(StructuredDataI &data) {
|
|||||||
if (ok) { ok = cdb.Write("DataPort", static_cast<uint32>(dataPort)); }
|
if (ok) { ok = cdb.Write("DataPort", static_cast<uint32>(dataPort)); }
|
||||||
}
|
}
|
||||||
if (ok) { ok = cdb.Write("MaxPayloadSize", maxPayloadSize); }
|
if (ok) { ok = cdb.Write("MaxPayloadSize", maxPayloadSize); }
|
||||||
|
if (ok) { ok = cdb.Write("KeepAliveInterval", keepAliveInterval); }
|
||||||
|
if (ok) { ok = cdb.Write("SilenceTimeout", silenceTimeout); }
|
||||||
if (ok) { ok = cdb.Write("CPUMask", cpuMask); }
|
if (ok) { ok = cdb.Write("CPUMask", cpuMask); }
|
||||||
if (ok) { ok = cdb.Write("StackSize", stackSize); }
|
if (ok) { ok = cdb.Write("StackSize", stackSize); }
|
||||||
if (ok) { ok = cdb.MoveToRoot(); }
|
if (ok) { ok = cdb.MoveToRoot(); }
|
||||||
@@ -517,7 +539,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;
|
||||||
|
|
||||||
|
|||||||
@@ -174,11 +174,13 @@ private:
|
|||||||
StreamString serverAddress; /**< Server IP address. */
|
StreamString serverAddress; /**< Server IP address. */
|
||||||
uint16 port; /**< Server port. */
|
uint16 port; /**< Server port. */
|
||||||
uint32 maxPayloadSize; /**< Max payload bytes per datagram. */
|
uint32 maxPayloadSize; /**< Max payload bytes per datagram. */
|
||||||
|
uint32 keepAliveInterval; /**< Seconds between unicast keepalive ACKs (0 disables). */
|
||||||
|
float32 silenceTimeout; /**< Seconds of no data before reconnect (sub-second allowed, 0 disables). */
|
||||||
uint32 cpuMask; /**< Background thread CPU affinity. */
|
uint32 cpuMask; /**< Background thread CPU affinity. */
|
||||||
uint32 stackSize; /**< Background thread stack size. */
|
uint32 stackSize; /**< Background thread stack size. */
|
||||||
StreamString multicastGroup; /**< Multicast group IP; empty = unicast. */
|
StreamString multicastGroup; /**< Multicast group IP; empty = unicast. */
|
||||||
uint16 dataPort; /**< UDP port for DATA datagrams (multicast). */
|
uint16 dataPort; /**< UDP port for DATA datagrams (multicast). */
|
||||||
bool useMulticast; /**< True when MulticastGroup is set. */
|
bool useMulticast; /**< True when MulticastGroup is set. */
|
||||||
|
|
||||||
/* Signal metadata */
|
/* Signal metadata */
|
||||||
uint32 numSigs; /**< Number of signals. */
|
uint32 numSigs; /**< Number of signals. */
|
||||||
|
|||||||
@@ -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 ×tamp, void* dataBuffer, uint32 &size, uint32 maxSize) {
|
bool Pop(uint32 &signalID, uint64 ×tamp, 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,23 +360,101 @@ 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
|
||||||
StreamString out;
|
* configured, the client must send
|
||||||
HandleCommand(command, out);
|
* "AUTH <token>" before any other command. */
|
||||||
if (out.Size() > 0u) {
|
if (authToken.Size() > 0u) {
|
||||||
const char8 *wPtr = out.Buffer();
|
const char8 *cmdPtr = command.Buffer();
|
||||||
uint32 remaining = (uint32)out.Size();
|
if (cmdLen >= 5u &&
|
||||||
lastDataTimeMs = (uint64)((float64)HighResolutionTimer::Counter() *
|
strncmp(cmdPtr, "AUTH ", 5u) == 0) {
|
||||||
HighResolutionTimer::Period() * 1000.0);
|
const char8 *recvToken = cmdPtr + 5u;
|
||||||
while (remaining > 0u) {
|
uint32 recvLen = cmdLen - 5u;
|
||||||
uint32 wrote = remaining;
|
/* Strip trailing \r if present */
|
||||||
if (!activeClient->Write(wPtr, wrote) || wrote == 0u) {
|
if (recvLen > 0u &&
|
||||||
break;
|
recvToken[recvLen - 1u] == '\r') {
|
||||||
|
recvLen--;
|
||||||
}
|
}
|
||||||
wPtr += wrote;
|
if (recvLen == authToken.Size() &&
|
||||||
remaining -= wrote;
|
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;
|
||||||
|
HandleCommand(command, out);
|
||||||
|
if (out.Size() > 0u) {
|
||||||
|
const char8 *wPtr = out.Buffer();
|
||||||
|
uint32 remaining = (uint32)out.Size();
|
||||||
lastDataTimeMs = (uint64)((float64)HighResolutionTimer::Counter() *
|
lastDataTimeMs = (uint64)((float64)HighResolutionTimer::Counter() *
|
||||||
HighResolutionTimer::Period() * 1000.0);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,29 +1141,39 @@ 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
|
||||||
|
// 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()) {
|
||||||
|
rc = dynamic_cast<ReferenceContainer *>(ref.operator->());
|
||||||
|
}
|
||||||
|
}
|
||||||
out.Printf("Nodes under %s:\n", path ? path : "/");
|
out.Printf("Nodes under %s:\n", path ? path : "/");
|
||||||
if (ref.IsValid()) {
|
if (rc != NULL_PTR(ReferenceContainer *)) {
|
||||||
ReferenceContainer *rc =
|
uint32 n = rc->Size();
|
||||||
dynamic_cast<ReferenceContainer *>(ref.operator->());
|
for (uint32 i = 0u; i < n; i++) {
|
||||||
if (rc != NULL_PTR(ReferenceContainer *)) {
|
Reference c = rc->Get(i);
|
||||||
uint32 n = rc->Size();
|
if (c.IsValid()) {
|
||||||
for (uint32 i = 0u; i < n; i++) {
|
out.Printf(" %s [%s]\n", c->GetName(),
|
||||||
Reference c = rc->Get(i);
|
c->GetClassProperties()->GetName());
|
||||||
if (c.IsValid()) {
|
|
||||||
out.Printf(" %s [%s]\n", c->GetName(),
|
|
||||||
c->GetClassProperties()->GetName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -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 {
|
||||||
@@ -23,14 +24,17 @@ UDPSClient::UDPSClient()
|
|||||||
useMulticast(false),
|
useMulticast(false),
|
||||||
silenceTimeoutTicks(0u),
|
silenceTimeoutTicks(0u),
|
||||||
reconnectDelayTicks(0u),
|
reconnectDelayTicks(0u),
|
||||||
|
keepAliveIntervalTicks(0u),
|
||||||
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),
|
||||||
lastDataTicks(0u),
|
lastDataTicks(0u),
|
||||||
disconnectTick(0u),
|
disconnectTick(0u),
|
||||||
|
lastKeepAliveTicks(0u),
|
||||||
localPort(0u),
|
localPort(0u),
|
||||||
lastGcTicks(0u) {
|
lastGcTicks(0u) {
|
||||||
|
|
||||||
@@ -83,14 +87,20 @@ bool UDPSClient::Initialise(StructuredDataI &data) {
|
|||||||
dataPort = static_cast<uint16>(dpU32);
|
dataPort = static_cast<uint16>(dpU32);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 silenceS = UDPS_CLIENT_DEFAULT_SILENCE_TIMEOUT_S;
|
float32 silenceS = UDPS_CLIENT_DEFAULT_SILENCE_TIMEOUT_S;
|
||||||
(void) data.Read("SilenceTimeout", silenceS);
|
(void) data.Read("SilenceTimeout", silenceS);
|
||||||
silenceTimeoutTicks = static_cast<uint64>(silenceS) * HighResolutionTimer::Frequency();
|
/* float64 math: the tick rate (~1e9) exceeds float32's 24-bit mantissa */
|
||||||
|
silenceTimeoutTicks = static_cast<uint64>(static_cast<float64>(silenceS) *
|
||||||
|
static_cast<float64>(HighResolutionTimer::Frequency()));
|
||||||
|
|
||||||
uint32 reconnectS = UDPS_CLIENT_DEFAULT_RECONNECT_DELAY_S;
|
uint32 reconnectS = UDPS_CLIENT_DEFAULT_RECONNECT_DELAY_S;
|
||||||
(void) data.Read("ReconnectDelay", reconnectS);
|
(void) data.Read("ReconnectDelay", reconnectS);
|
||||||
reconnectDelayTicks = static_cast<uint64>(reconnectS) * HighResolutionTimer::Frequency();
|
reconnectDelayTicks = static_cast<uint64>(reconnectS) * HighResolutionTimer::Frequency();
|
||||||
|
|
||||||
|
uint32 keepAliveS = UDPS_CLIENT_DEFAULT_KEEPALIVE_INTERVAL_S;
|
||||||
|
(void) data.Read("KeepAliveInterval", keepAliveS);
|
||||||
|
keepAliveIntervalTicks = static_cast<uint64>(keepAliveS) * HighResolutionTimer::Frequency();
|
||||||
|
|
||||||
uint32 mps = UDPS_CLIENT_DEFAULT_MAX_PAYLOAD;
|
uint32 mps = UDPS_CLIENT_DEFAULT_MAX_PAYLOAD;
|
||||||
(void) data.Read("MaxPayloadSize", mps);
|
(void) data.Read("MaxPayloadSize", mps);
|
||||||
maxPayloadSize = mps;
|
maxPayloadSize = mps;
|
||||||
@@ -98,6 +108,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +193,18 @@ ErrorManagement::ErrorType UDPSClient::Execute(ExecutionInfo &info) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unicast keepalive: UDPSServer evicts silent unicast clients after its
|
||||||
|
// ClientTimeout (default 30 s). Re-sending CONNECT would also re-trigger
|
||||||
|
// a CONFIG resend; an ACK refreshes the server's last-seen with no side
|
||||||
|
// effects, so it is the keepalive packet of choice. Multicast clients
|
||||||
|
// hold a persistent TCP control connection and need no keepalive.
|
||||||
|
if (!useMulticast && (keepAliveIntervalTicks > 0u)) {
|
||||||
|
if ((now - lastKeepAliveTicks) >= keepAliveIntervalTicks) {
|
||||||
|
SendKeepAlive();
|
||||||
|
lastKeepAliveTicks = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Periodic GC of stale reassembly slots (~every 1 s)
|
// Periodic GC of stale reassembly slots (~every 1 s)
|
||||||
uint64 gcFreq = HighResolutionTimer::Frequency();
|
uint64 gcFreq = HighResolutionTimer::Frequency();
|
||||||
if ((now - lastGcTicks) >= gcFreq) {
|
if ((now - lastGcTicks) >= gcFreq) {
|
||||||
@@ -199,6 +224,7 @@ bool UDPSClient::Connect() {
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
connected = true;
|
connected = true;
|
||||||
lastDataTicks = HighResolutionTimer::Counter();
|
lastDataTicks = HighResolutionTimer::Counter();
|
||||||
|
lastKeepAliveTicks = lastDataTicks;
|
||||||
if (listener != NULL_PTR(UDPSClientListener *)) {
|
if (listener != NULL_PTR(UDPSClientListener *)) {
|
||||||
listener->OnUDPSConnected();
|
listener->OnUDPSConnected();
|
||||||
}
|
}
|
||||||
@@ -209,6 +235,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 +259,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 +300,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) {
|
||||||
@@ -354,6 +399,25 @@ void UDPSClient::Disconnect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Private: SendKeepAlive
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void UDPSClient::SendKeepAlive() {
|
||||||
|
if (useMulticast || !recvSocket.IsValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8 ackPkt[UDPS_HEADER_SIZE];
|
||||||
|
UDPSBuildHeader(ackPkt, UDPS_TYPE_ACK, 0u, 0u, 1u, 0u);
|
||||||
|
InternetHost serverDest(serverPort, serverAddr.Buffer());
|
||||||
|
(void) recvSocket.SetDestination(serverDest);
|
||||||
|
uint32 sendSize = UDPS_HEADER_SIZE;
|
||||||
|
if (!recvSocket.Write(reinterpret_cast<const char8 *>(ackPkt), sendSize)) {
|
||||||
|
/* Non-fatal: if the server is truly gone, the silence timeout
|
||||||
|
* triggers the usual disconnect + reconnect. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Private: ReceiveAndProcess
|
// Private: ReceiveAndProcess
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -378,6 +442,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);
|
||||||
|
|||||||
@@ -86,15 +86,26 @@ public:
|
|||||||
* 256-fragment span the recvMask[32] tracks at typical chunk sizes. */
|
* 256-fragment span the recvMask[32] tracks at typical chunk sizes. */
|
||||||
static const uint32 UDPS_CLIENT_MAX_PACKET_BYTES = 1048576u; // 1 MiB
|
static const uint32 UDPS_CLIENT_MAX_PACKET_BYTES = 1048576u; // 1 MiB
|
||||||
|
|
||||||
/** Default silence timeout before reconnect (seconds). */
|
/** Default silence timeout before reconnect (seconds); sub-second values allowed. */
|
||||||
static const uint32 UDPS_CLIENT_DEFAULT_SILENCE_TIMEOUT_S = 5u;
|
static const float32 UDPS_CLIENT_DEFAULT_SILENCE_TIMEOUT_S = 1.0f;
|
||||||
|
|
||||||
/** Default delay between reconnect attempts (seconds). */
|
/** Default delay between reconnect attempts (seconds). */
|
||||||
static const uint32 UDPS_CLIENT_DEFAULT_RECONNECT_DELAY_S = 2u;
|
static const uint32 UDPS_CLIENT_DEFAULT_RECONNECT_DELAY_S = 2u;
|
||||||
|
|
||||||
|
/** Default unicast keepalive interval (seconds). UDPSServer evicts silent
|
||||||
|
* unicast clients after its ClientTimeout (default 30 s); the client
|
||||||
|
* re-sends an ACK on this interval to stay registered. 0 disables. */
|
||||||
|
static const uint32 UDPS_CLIENT_DEFAULT_KEEPALIVE_INTERVAL_S = 15u;
|
||||||
|
|
||||||
/** 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();
|
||||||
|
|
||||||
@@ -105,12 +116,16 @@ public:
|
|||||||
* - ServerAddr (char*) Server IPv4 address. Required.
|
* - ServerAddr (char*) Server IPv4 address. Required.
|
||||||
* - Port (uint16) Server UDP port (unicast) or TCP listen port (multicast). Required.
|
* - Port (uint16) Server UDP port (unicast) or TCP listen port (multicast). Required.
|
||||||
* - MulticastGroup (char*) IPv4 multicast address; presence enables multicast mode.
|
* - MulticastGroup (char*) IPv4 multicast address; presence enables multicast mode.
|
||||||
|
* - Interface (char*) Network interface for multicast join (e.g. "lo"). Required when MulticastGroup is set.
|
||||||
* - DataPort (uint16) UDP multicast data port (defaults to Port+1).
|
* - DataPort (uint16) UDP multicast data port (defaults to Port+1).
|
||||||
* - SilenceTimeout (uint32) Seconds of no data before reconnect. Default 5.
|
* - SilenceTimeout (float32) Seconds of no data before reconnect. Default 1.0.
|
||||||
|
* Sub-second values allowed; 0 disables the check.
|
||||||
* - ReconnectDelay (uint32) Seconds to wait between reconnect attempts. Default 2.
|
* - ReconnectDelay (uint32) Seconds to wait between reconnect attempts. Default 2.
|
||||||
|
* - KeepAliveInterval (uint32) Seconds between unicast keepalive ACKs. Default 15. 0 disables.
|
||||||
* - 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);
|
||||||
|
|
||||||
@@ -160,11 +175,16 @@ private:
|
|||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
bool Connect();
|
bool Connect();
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
/** Send a keepalive ACK to the server (unicast only, same socket). */
|
||||||
|
void SendKeepAlive();
|
||||||
bool ReceiveAndProcess();
|
bool ReceiveAndProcess();
|
||||||
|
|
||||||
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();
|
||||||
@@ -185,9 +205,11 @@ private:
|
|||||||
bool useMulticast;
|
bool useMulticast;
|
||||||
uint64 silenceTimeoutTicks;
|
uint64 silenceTimeoutTicks;
|
||||||
uint64 reconnectDelayTicks;
|
uint64 reconnectDelayTicks;
|
||||||
|
uint64 keepAliveIntervalTicks; ///< 0 = keepalive disabled
|
||||||
uint32 maxPayloadSize;
|
uint32 maxPayloadSize;
|
||||||
uint32 cpuMask;
|
uint32 cpuMask;
|
||||||
uint32 stackSize;
|
uint32 stackSize;
|
||||||
|
uint32 recvBufferSize;
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Runtime state
|
// Runtime state
|
||||||
@@ -197,6 +219,7 @@ private:
|
|||||||
bool connected;
|
bool connected;
|
||||||
uint64 lastDataTicks; ///< Ticks at last received DATA/CONFIG
|
uint64 lastDataTicks; ///< Ticks at last received DATA/CONFIG
|
||||||
uint64 disconnectTick; ///< Ticks when we disconnected (for delay)
|
uint64 disconnectTick; ///< Ticks when we disconnected (for delay)
|
||||||
|
uint64 lastKeepAliveTicks; ///< Ticks at last keepalive ACK sent
|
||||||
|
|
||||||
// Unicast
|
// Unicast
|
||||||
BasicUDPSocket recvSocket; ///< Bound to ephemeral port; receives DATA
|
BasicUDPSocket recvSocket; ///< Bound to ephemeral port; receives DATA
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -235,6 +235,7 @@ private:
|
|||||||
uint16 port;
|
uint16 port;
|
||||||
uint32 maxPayloadSize;
|
uint32 maxPayloadSize;
|
||||||
StreamString multicastGroup;
|
StreamString multicastGroup;
|
||||||
|
StreamString interface;
|
||||||
uint16 dataPort;
|
uint16 dataPort;
|
||||||
bool useMulticast;
|
bool useMulticast;
|
||||||
uint64 clientTimeoutTicks; ///< 0 = disabled
|
uint64 clientTimeoutTicks; ///< 0 = disabled
|
||||||
|
|||||||
@@ -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";
|
||||||
|
}
|
||||||
@@ -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,147 @@
|
|||||||
|
/**
|
||||||
|
* @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_SilenceTimeoutFloat) {
|
||||||
|
UDPStreamerClientTest test;
|
||||||
|
ASSERT_TRUE(test.TestInitialise_SilenceTimeoutFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
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,163 @@
|
|||||||
|
/**
|
||||||
|
* @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 Initialise with a sub-second float32 SilenceTimeout (0.25 s)
|
||||||
|
* forwarded through to the UDPSClient receiver.
|
||||||
|
*/
|
||||||
|
bool TestInitialise_SilenceTimeoutFloat();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
@@ -424,6 +424,7 @@ $TestApp = {
|
|||||||
Port = 44500
|
Port = 44500
|
||||||
MulticastGroup = "239.0.0.1"
|
MulticastGroup = "239.0.0.1"
|
||||||
DataPort = 44503
|
DataPort = 44503
|
||||||
|
Interface = "127.0.0.1"
|
||||||
MaxPayloadSize = 1400
|
MaxPayloadSize = 1400
|
||||||
PublishingMode = "Accumulate"
|
PublishingMode = "Accumulate"
|
||||||
MinRefreshRate = 100
|
MinRefreshRate = 100
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ $App = {
|
|||||||
Port = 44500
|
Port = 44500
|
||||||
MulticastGroup = "239.0.0.1"
|
MulticastGroup = "239.0.0.1"
|
||||||
DataPort = 44503
|
DataPort = 44503
|
||||||
|
Interface = "127.0.0.1"
|
||||||
MaxPayloadSize = 1400
|
MaxPayloadSize = 1400
|
||||||
PublishingMode = "Accumulate"
|
PublishingMode = "Accumulate"
|
||||||
MinRefreshRate = 100
|
MinRefreshRate = 100
|
||||||
@@ -373,7 +374,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
|
||||||
|
|||||||
@@ -411,6 +411,7 @@ $App = {
|
|||||||
Port = 44500
|
Port = 44500
|
||||||
MulticastGroup = "239.0.0.1"
|
MulticastGroup = "239.0.0.1"
|
||||||
DataPort = 44503
|
DataPort = 44503
|
||||||
|
Interface = "127.0.0.1"
|
||||||
MaxPayloadSize = 1400
|
MaxPayloadSize = 1400
|
||||||
PublishingMode = "Accumulate"
|
PublishingMode = "Accumulate"
|
||||||
MinRefreshRate = 100
|
MinRefreshRate = 100
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
|
||||||
@@ -64,6 +64,7 @@ $E2EMulticastTest = {
|
|||||||
Port = 44600
|
Port = 44600
|
||||||
MulticastGroup = "239.0.0.1"
|
MulticastGroup = "239.0.0.1"
|
||||||
DataPort = 44610
|
DataPort = 44610
|
||||||
|
Interface = "127.0.0.1"
|
||||||
MaxPayloadSize = 65507
|
MaxPayloadSize = 65507
|
||||||
PublishingMode = "Strict"
|
PublishingMode = "Strict"
|
||||||
Signals = {
|
Signals = {
|
||||||
|
|||||||
@@ -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 — 1 kHz, 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
|
|
||||||
|
|
||||||
Thread 2 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: 54 ms → ∼18 Hz max throughput. Bottlenecks: `FileWriter` async flush (50 ms) and poll sleeps (2 ms).],
|
|
||||||
)
|
|
||||||
|
|
||||||
== Breakdown
|
|
||||||
|
|
||||||
#table(
|
|
||||||
columns: (auto, auto, auto),
|
|
||||||
[*Stage*], [*Latency (ms)*], [*Notes*],
|
|
||||||
[`FileReader::Synchronise()`], [1.0], [Blocking read from OS buffer],
|
|
||||||
[`IOGAM` (memcpy)], [0.1], [24 KB 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], [24 KB copy (6100 floats)],
|
|
||||||
[`FileWriter` (async flush)], [50.0], [Disk I/O, buffer count configurable],
|
|
||||||
[*Total*], [*54.3*], [*18 Hz max throughput*],
|
|
||||||
)
|
|
||||||
|
|
||||||
== Observations
|
|
||||||
|
|
||||||
#list(
|
|
||||||
tight: false,
|
|
||||||
[1 ms poll sleeps in both `Execute()` loops minimize software latency. Total poll overhead: 2 ms.],
|
|
||||||
[`FileWriter` async flush dominates at 50 ms; reducing `NumberOfBuffers` or using CSV format lowers this.],
|
|
||||||
[Maximum theoretical throughput with zero sleeps and sync FileWriter: ∼500 Hz (limited by 24 KB 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 (42 B signal descriptor) + 6100 floats per row (24.4 KB/row).
|
|
||||||
100 rows total, 2.44 MB 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 54 ms, P95 103 ms, P99 129 ms). 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 1 ms. Lower `ResetWait` timeout from 1000 to 100 ms.],
|
|
||||||
[*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`.],
|
|
||||||
)
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -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 "=========================================="
|
|
||||||
@@ -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 "=========================================="
|
|
||||||
@@ -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
|
|
||||||
@@ -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.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
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)
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
Executable
BIN
Binary file not shown.
@@ -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
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -17,6 +17,8 @@ expected, not an error.
|
|||||||
"""
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
@@ -25,6 +27,41 @@ import scenarios as S # noqa: E402
|
|||||||
PRODUCER_HZ = 1000 # LinuxTimer frequency (Hz)
|
PRODUCER_HZ = 1000 # LinuxTimer frequency (Hz)
|
||||||
|
|
||||||
|
|
||||||
|
def _iface_to_ip(name):
|
||||||
|
"""Resolve a network interface name (e.g. ``"wlan0"``) to its first IPv4
|
||||||
|
address via ``ip -4 addr show <name>``. Returns ``"127.0.0.1"`` on failure."""
|
||||||
|
try:
|
||||||
|
out = subprocess.check_output(
|
||||||
|
["ip", "-4", "addr", "show", name],
|
||||||
|
stderr=subprocess.DEVNULL, text=True)
|
||||||
|
m = re.search(r"inet\s+(\d+\.\d+\.\d+\.\d+)", out)
|
||||||
|
if m:
|
||||||
|
return m.group(1)
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
||||||
|
pass
|
||||||
|
return "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
|
def _mcast_interface_ip(group):
|
||||||
|
"""Return the IPv4 address of the OS-selected interface for a multicast
|
||||||
|
group. MARTe2's ``BasicUDPSocket::Join`` expects an IP address (passed to
|
||||||
|
``inet_addr``), not an interface name.
|
||||||
|
|
||||||
|
Uses ``ip route get <group>`` to find the outgoing device, then resolves
|
||||||
|
its IP. Falls back to ``"127.0.0.1"`` if the route or device lookup fails.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
out = subprocess.check_output(
|
||||||
|
["ip", "route", "get", group],
|
||||||
|
stderr=subprocess.DEVNULL, text=True)
|
||||||
|
m = re.search(r"dev\s+(\S+)", out)
|
||||||
|
if m:
|
||||||
|
return _iface_to_ip(m.group(1))
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
||||||
|
pass
|
||||||
|
return "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
def _ndims(elements):
|
def _ndims(elements):
|
||||||
return 0 if elements == 1 else 1
|
return 0 if elements == 1 else 1
|
||||||
|
|
||||||
@@ -78,6 +115,8 @@ def _streamer_block(src, scenario):
|
|||||||
if scenario["network"] == "multicast":
|
if scenario["network"] == "multicast":
|
||||||
parts.append(f'MulticastGroup = "{src["multicast_group"]}"')
|
parts.append(f'MulticastGroup = "{src["multicast_group"]}"')
|
||||||
parts.append(f"DataPort = {src['data_port']}")
|
parts.append(f"DataPort = {src['data_port']}")
|
||||||
|
iface = src.get("interface") or _mcast_interface_ip(src["multicast_group"])
|
||||||
|
parts.append(f'Interface = "{iface}"')
|
||||||
sigs = " ".join(_streamer_sig(sig) for sig in s)
|
sigs = " ".join(_streamer_sig(sig) for sig in s)
|
||||||
return (f" +Streamer_{src['id']} = {{ Class = UDPStreamer "
|
return (f" +Streamer_{src['id']} = {{ Class = UDPStreamer "
|
||||||
f"{' '.join(parts)} Signals = {{ {sigs} }} }}")
|
f"{' '.join(parts)} Signals = {{ {sigs} }} }}")
|
||||||
@@ -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
|
||||||
trig = s.get("trig_signal") or ""
|
if s["kind"] in skip_kinds:
|
||||||
checks = ",".join(s.get("client_checks", []))
|
continue
|
||||||
if not trig:
|
kind = s["kind"]
|
||||||
checks = ",".join(c for c in s.get("client_checks", []) if c != "trigger")
|
if kind == "chain":
|
||||||
print("|".join([s["id"], str(s["ws_port"]), str(s["sources"][0]["udp_port"]),
|
trig = s.get("trig_signal") or ""
|
||||||
s["network"], s["oracle"], trig, checks]))
|
checks = ",".join(s.get("client_checks", []))
|
||||||
|
if not trig:
|
||||||
|
checks = ",".join(c for c in s.get("client_checks", []) if c != "trigger")
|
||||||
|
print("|".join([kind, s["id"], str(s["ws_port"]), str(s["sources"][0]["udp_port"]),
|
||||||
|
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
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user