From 9b26b9922d470e675f28d75ae3930ae70345ff35 Mon Sep 17 00:00:00 2001 From: mad201802 Date: Sat, 7 Mar 2026 15:35:33 +0100 Subject: [PATCH] chore: resolved code findings by claude --- include/sero/core/config.hpp | 25 +++++++++++ include/sero/core/diagnostic_counters.hpp | 2 +- include/sero/core/dtc_store.hpp | 4 +- include/sero/runtime.hpp | 39 ++++++++++------ include/sero/security/e2e_protection.hpp | 2 +- include/sero/service/event_manager.hpp | 4 +- include/sero/service/method_dispatcher.hpp | 2 +- include/sero/service/request_tracker.hpp | 16 ++++++- include/sero/service/service_discovery.hpp | 14 ++++++ src/verify_build.cpp | 12 ++--- test/test_diagnostics_service.cpp | 6 +-- test/test_runtime.cpp | 52 +++++++++++----------- 12 files changed, 122 insertions(+), 56 deletions(-) diff --git a/include/sero/core/config.hpp b/include/sero/core/config.hpp index f32f110..e564c9c 100644 --- a/include/sero/core/config.hpp +++ b/include/sero/core/config.hpp @@ -35,4 +35,29 @@ struct DefaultConfig { static constexpr std::size_t MaxDtcs = 32; }; +/// Embedded-friendly configuration for resource-constrained MCUs (ESP32, STM32, etc.). +/// sizeof(Runtime) with this config is approximately 3–4 KB. +struct EmbeddedConfig { + static constexpr std::size_t MaxPayloadSize = 256; + static constexpr std::size_t MaxServices = 4; + static constexpr std::size_t MaxMethods = 8; + static constexpr std::size_t MaxEvents = 4; + static constexpr std::size_t MaxSubscribers = 4; + static constexpr std::size_t MaxPendingRequests = 4; + static constexpr std::size_t MaxKnownServices = 8; + static constexpr uint32_t RequestTimeoutMs = 500; + static constexpr uint16_t OfferTtlSeconds = 5; + static constexpr uint16_t SubscriptionTtlSeconds = 10; + static constexpr uint8_t SdFindRetryCount = 3; + static constexpr uint32_t SdFindInitialDelayMs = 100; + static constexpr uint8_t SdFindBackoffMultiplier = 2; + static constexpr uint32_t SdFindJitterMs = 50; + static constexpr uint8_t SeqCounterAcceptWindow = 15; + static constexpr std::size_t TransportAddressSize = 8; + static constexpr std::size_t MaxReceiveQueueSize = 8; + static constexpr std::size_t MaxTrackedPeers = 8; + static constexpr std::size_t HmacKeySize = 32; + static constexpr std::size_t MaxDtcs = 8; +}; + } // namespace sero diff --git a/include/sero/core/diagnostic_counters.hpp b/include/sero/core/diagnostic_counters.hpp index 64b36fb..12e209e 100644 --- a/include/sero/core/diagnostic_counters.hpp +++ b/include/sero/core/diagnostic_counters.hpp @@ -31,7 +31,7 @@ struct DiagnosticCounters { void increment(DiagnosticCounter c, const uint8_t* header_or_null = nullptr) { auto idx = static_cast(c); - ++counters[idx]; // wrapping uint32_t + if (counters[idx] < UINT32_MAX) ++counters[idx]; // saturating if (callback) { callback(c, header_or_null, callback_ctx); } diff --git a/include/sero/core/dtc_store.hpp b/include/sero/core/dtc_store.hpp index 7d6fc62..9477ec8 100644 --- a/include/sero/core/dtc_store.hpp +++ b/include/sero/core/dtc_store.hpp @@ -35,7 +35,7 @@ class DtcStore { for (std::size_t i = 0; i < count_; ++i) { if (dtcs_[i].active && dtcs_[i].code == code) { dtcs_[i].severity = static_cast(severity); - dtcs_[i].occurrence_count++; + if (dtcs_[i].occurrence_count < UINT32_MAX) dtcs_[i].occurrence_count++; dtcs_[i].last_seen_ms = now_ms; return true; } @@ -57,7 +57,7 @@ class DtcStore { bool clear(uint16_t code) { for (std::size_t i = 0; i < count_; ++i) { if (dtcs_[i].active && dtcs_[i].code == code) { - dtcs_[i] = dtcs_[count_ - 1]; + if (i != count_ - 1) dtcs_[i] = dtcs_[count_ - 1]; dtcs_[count_ - 1] = Dtc{}; --count_; return true; diff --git a/include/sero/runtime.hpp b/include/sero/runtime.hpp index cd634f6..7c0cd68 100644 --- a/include/sero/runtime.hpp +++ b/include/sero/runtime.hpp @@ -33,6 +33,14 @@ class Runtime { static constexpr std::size_t MAX_MSG_SIZE = MessageHeader::SIZE + Config::MaxPayloadSize + HMAC_SIZE + CRC_SIZE; + // Compile-time sanity checks for config products that determine RAM usage. + static_assert(Config::MaxServices * Config::MaxEvents <= 1024, + "MaxServices * MaxEvents is very large — review RAM budget"); + static_assert(Config::MaxKnownServices * Config::MaxEvents <= 1024, + "MaxKnownServices * MaxEvents is very large — review RAM budget"); + static_assert(Config::MaxPayloadSize <= 8192, + "MaxPayloadSize exceeds 8 KB — review RAM budget"); + // ── Construction ──────────────────────────────────────────── Runtime(TransportImpl& transport, uint16_t client_id) @@ -58,11 +66,13 @@ class Runtime { } uptime_ms_ = now_ms - uptime_epoch_ms_; - // 1. Drain transport + // 1. Drain transport (bounded to prevent starvation) Addr source{}; const uint8_t* data = nullptr; std::size_t length = 0; - while (transport_.poll(source, data, length)) { + for (std::size_t drain = 0; + drain < Config::MaxReceiveQueueSize && transport_.poll(source, data, length); + ++drain) { validate_and_dispatch(source, data, length, now_ms); } @@ -99,7 +109,7 @@ class Runtime { // ── Service registration (provider side) ──────────────────── template - bool register_service(uint16_t service_id, IService& svc, + [[nodiscard]] bool register_service(uint16_t service_id, IService& svc, uint8_t major, uint8_t minor, bool auth_required = false) { @@ -112,13 +122,13 @@ class Runtime { } /// Register an event that this device can produce notifications for. - bool register_event(uint16_t service_id, uint16_t event_id) { + [[nodiscard]] bool register_event(uint16_t service_id, uint16_t event_id) { return event_manager_.register_event(service_id, event_id); } // ── Service offering (provider SD) ────────────────────────── - bool offer_service(uint16_t service_id, uint16_t ttl_seconds, uint32_t now_ms) { + [[nodiscard]] bool offer_service(uint16_t service_id, uint16_t ttl_seconds, uint32_t now_ms) { const ServiceEntry* se = dispatcher_.find(service_id); if (!se) return false; return sd_.offer(service_id, se->major_version, se->minor_version, @@ -131,7 +141,7 @@ class Runtime { // ── Service discovery (consumer SD) ───────────────────────── - bool find_service(uint16_t service_id, uint8_t major_version, uint32_t now_ms) { + [[nodiscard]] bool find_service(uint16_t service_id, uint8_t major_version, uint32_t now_ms) { return sd_.find(service_id, major_version, now_ms); } @@ -141,7 +151,7 @@ class Runtime { /// Send a REQUEST and track the pending response. /// Returns the request_id or std::nullopt if failed. - std::optional request(uint16_t service_id, + [[nodiscard]] std::optional request(uint16_t service_id, uint16_t method_id, const uint8_t* payload, std::size_t payload_length, @@ -176,7 +186,7 @@ class Runtime { } /// Fire-and-forget REQUEST_NO_RETURN (§5.2). - bool fire_and_forget(uint16_t service_id, uint16_t method_id, + [[nodiscard]] bool fire_and_forget(uint16_t service_id, uint16_t method_id, const uint8_t* payload, std::size_t payload_length) { Addr provider{}; @@ -207,7 +217,7 @@ class Runtime { /// Subscribe to a remote event. Handler receives notifications. template - bool subscribe_event(uint16_t service_id, uint16_t event_id, + [[nodiscard]] bool subscribe_event(uint16_t service_id, uint16_t event_id, IEventHandler& handler, uint16_t ttl_seconds, uint32_t now_ms) { @@ -227,7 +237,7 @@ class Runtime { // ── Event notification (provider side, §6.2) ──────────────── /// Push a notification to all subscribers of an event. - bool notify_event(uint16_t service_id, uint16_t event_id, + [[nodiscard]] bool notify_event(uint16_t service_id, uint16_t event_id, const uint8_t* payload, std::size_t payload_length, uint32_t /*now_ms*/ = 0) { @@ -278,7 +288,7 @@ class Runtime { /// @param auth_required When true, requests to the diagnostics service /// must carry a valid HMAC (recommended for /// state-changing methods like DIAG_CLEAR_DTCS). - bool enable_diagnostics(uint32_t now_ms, bool auth_required = false) { + [[nodiscard]] bool enable_diagnostics(uint32_t now_ms, bool auth_required = false) { if (diag_enabled_) return true; // idempotent diag_service_.init(&dtc_store_, &diag_, &dispatcher_, client_id_, &uptime_ms_); @@ -295,7 +305,7 @@ class Runtime { } /// Report a DTC (application-level error code). - bool report_dtc(uint16_t code, DtcSeverity severity, uint32_t now_ms) { + [[nodiscard]] bool report_dtc(uint16_t code, DtcSeverity severity, uint32_t now_ms) { if constexpr (Config::MaxDtcs == 0) { return false; } else { @@ -742,6 +752,9 @@ class Runtime { bool auth, const Addr& peer) { + // Bounds check — prevent buffer overflow + if (payload_length > Config::MaxPayloadSize) return 0; + // Header MessageHeader mutable_hdr = hdr; mutable_hdr.serialize(tx_buffer_); @@ -847,7 +860,7 @@ class Runtime { if (event_handlers_[i].active && event_handlers_[i].service_id == service_id && event_handlers_[i].event_id == event_id) { - event_handlers_[i] = event_handlers_[event_handler_count_ - 1]; + if (i != event_handler_count_ - 1) event_handlers_[i] = event_handlers_[event_handler_count_ - 1]; event_handlers_[event_handler_count_ - 1] = EventHandlerEntry{}; --event_handler_count_; return; diff --git a/include/sero/security/e2e_protection.hpp b/include/sero/security/e2e_protection.hpp index 4ccbe9f..2f5b548 100644 --- a/include/sero/security/e2e_protection.hpp +++ b/include/sero/security/e2e_protection.hpp @@ -39,7 +39,7 @@ class E2EProtection { for (std::size_t i = 0; i < peer_count_; ++i) { if (peers_[i].address == source) { // Remove by compacting - peers_[i] = peers_[peer_count_ - 1]; + if (i != peer_count_ - 1) peers_[i] = peers_[peer_count_ - 1]; peers_[peer_count_ - 1] = PeerEntry{}; --peer_count_; return; diff --git a/include/sero/service/event_manager.hpp b/include/sero/service/event_manager.hpp index e6c5f6a..8e30b82 100644 --- a/include/sero/service/event_manager.hpp +++ b/include/sero/service/event_manager.hpp @@ -78,7 +78,7 @@ class EventManager { for (std::size_t i = 0; i < ev->sub_count; ++i) { if (ev->subscribers[i].client_id == client_id) { // Compact: move last into this slot - ev->subscribers[i] = ev->subscribers[ev->sub_count - 1]; + if (i != ev->sub_count - 1) ev->subscribers[i] = ev->subscribers[ev->sub_count - 1]; ev->subscribers[ev->sub_count - 1] = Subscriber{}; --ev->sub_count; return; @@ -95,7 +95,7 @@ class EventManager { while (i < ev.sub_count) { if (time_after(now_ms, ev.subscribers[i].expiry_ms)) { // Expired — compact - ev.subscribers[i] = ev.subscribers[ev.sub_count - 1]; + if (i != ev.sub_count - 1) ev.subscribers[i] = ev.subscribers[ev.sub_count - 1]; ev.subscribers[ev.sub_count - 1] = Subscriber{}; --ev.sub_count; } else { diff --git a/include/sero/service/method_dispatcher.hpp b/include/sero/service/method_dispatcher.hpp index 3b988b1..530caf9 100644 --- a/include/sero/service/method_dispatcher.hpp +++ b/include/sero/service/method_dispatcher.hpp @@ -35,7 +35,7 @@ class MethodDispatcher { for (std::size_t i = 0; i < count_; ++i) { if (services_[i].active && services_[i].service_id == service_id) { // Move last into this slot to keep array compact - services_[i] = services_[count_ - 1]; + if (i != count_ - 1) services_[i] = services_[count_ - 1]; services_[count_ - 1] = ServiceEntry{}; --count_; return true; diff --git a/include/sero/service/request_tracker.hpp b/include/sero/service/request_tracker.hpp index 3f58d65..a45e5fe 100644 --- a/include/sero/service/request_tracker.hpp +++ b/include/sero/service/request_tracker.hpp @@ -33,7 +33,21 @@ class RequestTracker { { for (std::size_t i = 0; i < Config::MaxPendingRequests; ++i) { if (!entries_[i].active) { - uint32_t rid = next_request_id_++; + // Find a request_id that isn't already active + uint32_t rid = next_request_id_; + for (std::size_t attempt = 0; attempt < Config::MaxPendingRequests; ++attempt) { + bool collision = false; + for (std::size_t j = 0; j < Config::MaxPendingRequests; ++j) { + if (entries_[j].active && entries_[j].request_id == rid) { + collision = true; + break; + } + } + if (!collision) break; + ++rid; + } + next_request_id_ = rid + 1; + auto& e = entries_[i]; e.request_id = rid; e.service_id = service_id; diff --git a/include/sero/service/service_discovery.hpp b/include/sero/service/service_discovery.hpp index d88a61b..f02b0fa 100644 --- a/include/sero/service/service_discovery.hpp +++ b/include/sero/service/service_discovery.hpp @@ -357,6 +357,19 @@ class ServiceDiscovery { send_subscribe(st, ce->provider_addr, send_fn); st.last_sent_ms = now_ms; } + } else { + // No ACK received yet — retry after SubscriptionTtlSeconds + uint32_t retry_interval = static_cast(Config::SubscriptionTtlSeconds) * 1000u; + if (time_after_or_eq(now_ms, st.last_sent_ms + retry_interval)) { + if (st.ack_retry_count < 2) { + send_subscribe(st, ce->provider_addr, send_fn); + st.last_sent_ms = now_ms; + ++st.ack_retry_count; + } else { + // Retries exhausted — give up + st.active = false; + } + } } } } @@ -542,6 +555,7 @@ class ServiceDiscovery { bool needs_send = false; bool needs_unsubscribe = false; uint32_t last_sent_ms = 0; + uint8_t ack_retry_count = 0; ///< Retries when no ACK received. }; std::array providers_{}; diff --git a/src/verify_build.cpp b/src/verify_build.cpp index 0251270..32a42b7 100644 --- a/src/verify_build.cpp +++ b/src/verify_build.cpp @@ -58,14 +58,14 @@ int main() { rt.set_local_address(local_addr); EchoService echo; - rt.register_service(0x0100, echo, 1, 0); - rt.register_event(0x0100, 0x8001); - rt.offer_service(0x0100, 5, 0); + (void)rt.register_service(0x0100, echo, 1, 0); + (void)rt.register_event(0x0100, 0x8001); + (void)rt.offer_service(0x0100, 5, 0); // Diagnostics service - rt.enable_diagnostics(0); - rt.report_dtc(0x0010, sero::DtcSeverity::Error, 100); - rt.report_dtc(0x0020, sero::DtcSeverity::Warning, 200); + (void)rt.enable_diagnostics(0); + (void)rt.report_dtc(0x0010, sero::DtcSeverity::Error, 100); + (void)rt.report_dtc(0x0020, sero::DtcSeverity::Warning, 200); rt.clear_dtc(0x0010); rt.clear_all_dtcs(); diff --git a/test/test_diagnostics_service.cpp b/test/test_diagnostics_service.cpp index ebd25d8..fa749a3 100644 --- a/test/test_diagnostics_service.cpp +++ b/test/test_diagnostics_service.cpp @@ -266,8 +266,8 @@ TEST(DiagnosticsService_Runtime, ClearDtcs) { test::MockTransport transport; Runtime rt(transport, 0x0042); - rt.report_dtc(0x0001, DtcSeverity::Info, 100); - rt.report_dtc(0x0002, DtcSeverity::Warning, 200); + (void)rt.report_dtc(0x0001, DtcSeverity::Info, 100); + (void)rt.report_dtc(0x0002, DtcSeverity::Warning, 200); EXPECT_TRUE(rt.clear_dtc(0x0001)); EXPECT_EQ(rt.dtc_store().count(), 1u); @@ -285,7 +285,7 @@ TEST(DiagnosticsService_Runtime, EndToEndGetDeviceInfo) { rt.set_local_address(local); uint32_t now = 5000; - rt.enable_diagnostics(now); + (void)rt.enable_diagnostics(now); rt.process(now); // establish uptime // Build a request for DIAG_GET_DEVICE_INFO from a remote peer diff --git a/test/test_runtime.cpp b/test/test_runtime.cpp index 021c6fd..62f8af3 100644 --- a/test/test_runtime.cpp +++ b/test/test_runtime.cpp @@ -188,7 +188,7 @@ TEST_F(RuntimeTest, Validation_RequestWithZeroClientId_Drops) { TEST_F(RuntimeTest, Validation_DuplicateSequence_IncrementsCounter) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); // First message with seq=5 → FirstSeen, accepted MessageHeader hdr1 = make_request(0x1000, 0x0001, 0, 1); @@ -207,7 +207,7 @@ TEST_F(RuntimeTest, Validation_DuplicateSequence_IncrementsCounter) { TEST_F(RuntimeTest, Validation_AuthRequired_NoHmac_Drops) { StubService svc; - rt->register_service(0x1000, svc, 1, 0, /*auth_required=*/true); + (void)rt->register_service(0x1000, svc, 1, 0, /*auth_required=*/true); // Message without auth flag → auth failure MessageHeader hdr = make_request(0x1000, 0x0001, 0, 1); @@ -224,7 +224,7 @@ TEST_F(RuntimeTest, Validation_AuthPresentButBadHmac_Drops) { rt->set_hmac_key(peer, key); StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); MessageHeader hdr = make_request(0x1000, 0x0001, 0, 1); hdr.flags = FLAG_AUTH; @@ -242,7 +242,7 @@ TEST_F(RuntimeTest, Validation_AuthPresentButBadHmac_Drops) { TEST_F(RuntimeTest, RequestResponse_FullFlow) { StubService svc; svc.response_data = {0xCA, 0xFE}; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); uint8_t payload[] = {0x01, 0x02}; MessageHeader hdr = make_request(0x1000, 0x0042, 2, 100); @@ -282,7 +282,7 @@ TEST_F(RuntimeTest, RequestResponse_UnknownService_SendsError) { TEST_F(RuntimeTest, RequestResponse_NotReady_SendsError) { StubService svc; svc.ready = false; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); MessageHeader hdr = make_request(0x1000, 0x0001, 0, 1); inject_and_process(hdr, nullptr, 0, make_addr(10), 0); @@ -298,7 +298,7 @@ TEST_F(RuntimeTest, RequestResponse_NotReady_SendsError) { TEST_F(RuntimeTest, FireAndForget_Dispatches_NoResponse) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); MessageHeader hdr{}; hdr.version = PROTOCOL_VERSION; @@ -327,7 +327,7 @@ TEST_F(RuntimeTest, ClientRequest_ServiceNotFound_ReturnsNullopt) { TEST_F(RuntimeTest, ClientRequest_ServiceFound_SendsAndTracksRequest) { // Emulate consumer-side: find → handle_offer → provider known - rt->find_service(0x1000, 1, 0); + (void)rt->find_service(0x1000, 1, 0); rt->service_discovery().handle_offer(0x1000, 1, 30, 0x0001, make_addr(20), 0); bool callback_called = false; @@ -401,7 +401,7 @@ TEST_F(RuntimeTest, ClientRequest_ExplicitTarget_ResponseCompletesCallback) { // ── Client-side Fire-and-Forget ───────────────────────────────── TEST_F(RuntimeTest, ClientFireAndForget_ServiceFound_Sends) { - rt->find_service(0x1000, 1, 0); + (void)rt->find_service(0x1000, 1, 0); rt->service_discovery().handle_offer(0x1000, 1, 30, 0x0001, make_addr(20), 0); bool ok = rt->fire_and_forget(0x1000, 0x0042, nullptr, 0); @@ -421,7 +421,7 @@ TEST_F(RuntimeTest, ClientFireAndForget_ServiceNotFound_ReturnsFalse) { // ── Notification (provider side) ──────────────────────────────── TEST_F(RuntimeTest, NotifyEvent_NoSubscribers_ReturnsFalse) { - rt->register_event(0x1000, 0x8001); + (void)rt->register_event(0x1000, 0x8001); EXPECT_FALSE(rt->notify_event(0x1000, 0x8001, nullptr, 0)); } @@ -430,9 +430,9 @@ TEST_F(RuntimeTest, NotifyEvent_NoSubscribers_ReturnsFalse) { TEST_F(RuntimeTest, NotificationDispatch_MatchingHandler) { StubEventHandler handler; // Register a service so we can subscribe - rt->find_service(0x1000, 1, 0); + (void)rt->find_service(0x1000, 1, 0); rt->service_discovery().handle_offer(0x1000, 1, 30, 0x0001, make_addr(20), 0); - rt->subscribe_event(0x1000, 0x8001, handler, 60, 0); + (void)rt->subscribe_event(0x1000, 0x8001, handler, 60, 0); // Inject a NOTIFICATION uint8_t payload[] = {0xDE, 0xAD}; @@ -456,7 +456,7 @@ TEST_F(RuntimeTest, NotificationDispatch_NoHandler_Ignored) { // ── SD message routing ────────────────────────────────────────── TEST_F(RuntimeTest, SdOfferMessage_ParsesToConsumer) { - rt->find_service(0x1000, 1, 0); + (void)rt->find_service(0x1000, 1, 0); // Build an SD_OFFER message MessageHeader sd_hdr{}; @@ -485,8 +485,8 @@ TEST_F(RuntimeTest, SdOfferMessage_ParsesToConsumer) { TEST_F(RuntimeTest, SdFindMessage_ProviderResponds) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); - rt->offer_service(0x1000, 10, 0); + (void)rt->register_service(0x1000, svc, 1, 0); + (void)rt->offer_service(0x1000, 10, 0); // Build an SD_FIND message MessageHeader sd_hdr{}; @@ -520,8 +520,8 @@ TEST_F(RuntimeTest, SdFindMessage_ProviderResponds) { // so the subsequent requests are treated as FirstSeen and accepted. TEST_F(RuntimeTest, SdFindMessage_ResetsConsumerE2EState) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); - rt->offer_service(0x1000, 10, 0); + (void)rt->register_service(0x1000, svc, 1, 0); + (void)rt->offer_service(0x1000, 10, 0); const Addr consumer = make_addr(50); @@ -575,7 +575,7 @@ TEST_F(RuntimeTest, SdFindMessage_ResetsConsumerE2EState) { // This confirms the above test exercises a real code path. TEST_F(RuntimeTest, StaleSequence_WithoutSdFind_IsRejected) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); const Addr consumer = make_addr(51); @@ -602,7 +602,7 @@ TEST_F(RuntimeTest, StaleSequence_WithoutSdFind_IsRejected) { // ── Request timeout eviction ──────────────────────────────────── TEST_F(RuntimeTest, RequestTimeout_EvictsAndCallsCallback) { - rt->find_service(0x1000, 1, 0); + (void)rt->find_service(0x1000, 1, 0); rt->service_discovery().handle_offer(0x1000, 1, 30, 0x0001, make_addr(20), 0); ReturnCode timeout_rc = ReturnCode::E_OK; @@ -624,7 +624,7 @@ TEST_F(RuntimeTest, RequestTimeout_EvictsAndCallsCallback) { // ── Subscription eviction ─────────────────────────────────────── TEST_F(RuntimeTest, EventSubscriptionExpiry_RemovesSubscriber) { - rt->register_event(0x1000, 0x8001); + (void)rt->register_event(0x1000, 0x8001); // Simulate an incoming subscribe from a remote client MessageHeader sd_hdr{}; @@ -664,7 +664,7 @@ TEST_F(RuntimeTest, Auth_ValidHmac_Accepted) { StubService svc; svc.response_data = {0xCC}; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); // Build a message with valid HMAC uint8_t payload[] = {0x01}; @@ -695,7 +695,7 @@ TEST_F(RuntimeTest, Auth_ValidHmac_Accepted) { TEST_F(RuntimeTest, ProcessDrainsMultipleMessages) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); for (int i = 0; i < 3; ++i) { MessageHeader hdr = make_request(0x1000, 0x0001, 0, static_cast(i + 1)); @@ -732,7 +732,7 @@ TEST_F(RuntimeTest, DiagnosticCallback_FiredOnError) { TEST_F(RuntimeTest, SendFailure_IncrementsDroppedMessages) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); transport.send_fails = true; @@ -750,7 +750,7 @@ TEST_F(RuntimeTest, OfferService_RequiresRegisteredService) { TEST_F(RuntimeTest, OfferService_Success_ProcessBroadcasts) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); EXPECT_TRUE(rt->offer_service(0x1000, 10, 0)); rt->process(0); // fires the broadcast @@ -759,8 +759,8 @@ TEST_F(RuntimeTest, OfferService_Success_ProcessBroadcasts) { TEST_F(RuntimeTest, StopOffer_NoMoreBroadcasts) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); - rt->offer_service(0x1000, 10, 0); + (void)rt->register_service(0x1000, svc, 1, 0); + (void)rt->offer_service(0x1000, 10, 0); rt->process(0); // initial broadcast transport.clear(); @@ -774,7 +774,7 @@ TEST_F(RuntimeTest, StopOffer_NoMoreBroadcasts) { TEST_F(RuntimeTest, UnregisterService_RemovesFromDispatcher) { StubService svc; - rt->register_service(0x1000, svc, 1, 0); + (void)rt->register_service(0x1000, svc, 1, 0); EXPECT_TRUE(rt->unregister_service(0x1000)); // Now a request should get UNKNOWN_SERVICE error