From 50648583edc16a5ffbd4bc2434fa1eb5fedbb963 Mon Sep 17 00:00:00 2001 From: "torlando-agent[bot]" <281092095+torlando-agent[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 16:57:09 +0000 Subject: [PATCH] feat: add bounded peer location state --- lib/tdeck_ui/Telemetry/LocationShareState.cpp | 191 +++++++++++++ lib/tdeck_ui/Telemetry/LocationShareState.h | 80 ++++++ tests/native/test_location_share_state.cpp | 254 ++++++++++++++++++ tests/native/test_location_share_state.py | 24 ++ 4 files changed, 549 insertions(+) create mode 100644 lib/tdeck_ui/Telemetry/LocationShareState.cpp create mode 100644 lib/tdeck_ui/Telemetry/LocationShareState.h create mode 100644 tests/native/test_location_share_state.cpp create mode 100644 tests/native/test_location_share_state.py diff --git a/lib/tdeck_ui/Telemetry/LocationShareState.cpp b/lib/tdeck_ui/Telemetry/LocationShareState.cpp new file mode 100644 index 00000000..2a4fefaf --- /dev/null +++ b/lib/tdeck_ui/Telemetry/LocationShareState.cpp @@ -0,0 +1,191 @@ +#include "LocationShareState.h" + +#include +#include +#include +#include + +namespace Telemetry { +namespace { + +constexpr std::size_t NO_SLOT = MAX_PEER_LOCATIONS; + +bool effectiveTimestampMillis( + const LocationTelemetry& location, + const CustomLocationMeta& meta, + uint64_t& timestamp_millis) { + if (meta.has_timestamp) { + timestamp_millis = meta.timestamp_millis; + return true; + } + if (location.timestamp_seconds > + std::numeric_limits::max() / 1000ULL) { + return false; + } + timestamp_millis = location.timestamp_seconds * 1000ULL; + return true; +} + +bool locationInRange(const LocationTelemetry& location) { + return location.latitude_e6 >= -90000000 && + location.latitude_e6 <= 90000000 && + location.longitude_e6 >= -180000000 && + location.longitude_e6 <= 180000000; +} + +} // namespace + +bool PeerLocationStore::peerEquals(const PeerId& left, const PeerId& right) { + return std::memcmp(left.bytes, right.bytes, PEER_ID_SIZE) == 0; +} + +std::size_t PeerLocationStore::find(const PeerId& peer) const { + for (std::size_t index = 0; index < MAX_PEER_LOCATIONS; ++index) { + if (slots_[index].occupied && peerEquals(slots_[index].record.peer, peer)) { + return index; + } + } + return NO_SLOT; +} + +std::size_t PeerLocationStore::firstVacant() const { + for (std::size_t index = 0; index < MAX_PEER_LOCATIONS; ++index) { + if (!slots_[index].occupied) return index; + } + return NO_SLOT; +} + +std::size_t PeerLocationStore::evictionCandidate() const { + std::size_t candidate = NO_SLOT; + for (std::size_t index = 0; index < MAX_PEER_LOCATIONS; ++index) { + if (!slots_[index].occupied) continue; + if (candidate == NO_SLOT || + slots_[index].record.received_at_millis < + slots_[candidate].record.received_at_millis) { + candidate = index; + } + } + return candidate; +} + +bool PeerLocationStore::visible( + const PeerLocationRecord& record, + uint64_t now_millis, + uint64_t maximum_age_millis) { + if (record.expires_at_millis != 0 && + now_millis >= record.expires_at_millis) { + return false; + } + if (now_millis >= record.received_at_millis && + now_millis - record.received_at_millis > maximum_age_millis) { + return false; + } + return true; +} + +void PeerLocationStore::clear(std::size_t index) { + if (index >= MAX_PEER_LOCATIONS || !slots_[index].occupied) return; + slots_[index] = Slot{}; + --size_; +} + +PeerLocationResult PeerLocationStore::apply( + const PeerId& peer, + const LocationTelemetry& location, + const CustomLocationMeta& meta, + uint64_t received_at_millis) { + uint64_t source_timestamp_millis = 0; + if (!effectiveTimestampMillis(location, meta, source_timestamp_millis)) { + return PeerLocationResult::INVALID_ARGUMENT; + } + + const std::size_t existing = find(peer); + if (existing != NO_SLOT && + source_timestamp_millis < + slots_[existing].record.source_timestamp_millis) { + return PeerLocationResult::STALE; + } + + if (meta.has_cease && meta.cease) { + if (existing == NO_SLOT) return PeerLocationResult::NOT_FOUND; + clear(existing); + return PeerLocationResult::CEASED; + } + + const uint64_t expires_at_millis = + meta.has_expires ? meta.expires_millis : 0; + if (expires_at_millis != 0 && + received_at_millis >= expires_at_millis) { + if (existing != NO_SLOT) clear(existing); + return PeerLocationResult::EXPIRED; + } + if (!locationInRange(location)) { + return PeerLocationResult::INVALID_ARGUMENT; + } + + PeerLocationRecord record{}; + record.peer = peer; + record.location = location; + record.source_timestamp_millis = source_timestamp_millis; + record.received_at_millis = received_at_millis; + record.expires_at_millis = expires_at_millis; + record.approx_radius_meters = + meta.has_approx_radius ? meta.approx_radius_meters : 0; + + if (existing != NO_SLOT) { + slots_[existing].record = record; + return PeerLocationResult::UPDATED; + } + + std::size_t target = firstVacant(); + if (target == NO_SLOT) target = evictionCandidate(); + if (target == NO_SLOT) return PeerLocationResult::INVALID_ARGUMENT; + if (!slots_[target].occupied) ++size_; + slots_[target].record = record; + slots_[target].occupied = true; + return PeerLocationResult::INSERTED; +} + +bool PeerLocationStore::get( + const PeerId& peer, + PeerLocationRecord& output) const { + const std::size_t index = find(peer); + if (index == NO_SLOT) return false; + output = slots_[index].record; + return true; +} + +std::size_t PeerLocationStore::snapshot( + uint64_t now_millis, + uint64_t maximum_age_millis, + PeerLocationRecord* output, + std::size_t capacity) const { + if (output == nullptr || capacity == 0) return 0; + std::size_t copied = 0; + for (std::size_t index = 0; + index < MAX_PEER_LOCATIONS && copied < capacity; + ++index) { + if (!slots_[index].occupied || + !visible(slots_[index].record, now_millis, maximum_age_millis)) { + continue; + } + output[copied++] = slots_[index].record; + } + return copied; +} + +std::size_t PeerLocationStore::prune( + uint64_t now_millis, + uint64_t maximum_age_millis) { + std::size_t removed = 0; + for (std::size_t index = 0; index < MAX_PEER_LOCATIONS; ++index) { + if (slots_[index].occupied && + !visible(slots_[index].record, now_millis, maximum_age_millis)) { + clear(index); + ++removed; + } + } + return removed; +} + +} // namespace Telemetry diff --git a/lib/tdeck_ui/Telemetry/LocationShareState.h b/lib/tdeck_ui/Telemetry/LocationShareState.h new file mode 100644 index 00000000..41cc3891 --- /dev/null +++ b/lib/tdeck_ui/Telemetry/LocationShareState.h @@ -0,0 +1,80 @@ +#ifndef PYXIS_TELEMETRY_LOCATION_SHARE_STATE_H +#define PYXIS_TELEMETRY_LOCATION_SHARE_STATE_H + +#include +#include + +#include "LocationTelemetryCodec.h" + +namespace Telemetry { + +constexpr std::size_t PEER_ID_SIZE = 16; +constexpr std::size_t MAX_PEER_LOCATIONS = 32; + +struct PeerId { + PeerId() : bytes{} {} + uint8_t bytes[PEER_ID_SIZE]; +}; + +struct PeerLocationRecord { + PeerId peer{}; + LocationTelemetry location{}; + uint64_t source_timestamp_millis = 0; + uint64_t received_at_millis = 0; + uint64_t expires_at_millis = 0; + uint32_t approx_radius_meters = 0; +}; + +enum class PeerLocationResult : uint8_t { + INSERTED, + UPDATED, + CEASED, + NOT_FOUND, + STALE, + EXPIRED, + INVALID_ARGUMENT, +}; + +class PeerLocationStore { +public: + PeerLocationStore() = default; + + PeerLocationResult apply( + const PeerId& peer, + const LocationTelemetry& location, + const CustomLocationMeta& meta, + uint64_t received_at_millis); + + bool get(const PeerId& peer, PeerLocationRecord& output) const; + + std::size_t snapshot( + uint64_t now_millis, + uint64_t maximum_age_millis, + PeerLocationRecord* output, + std::size_t capacity) const; + + std::size_t prune(uint64_t now_millis, uint64_t maximum_age_millis); + std::size_t size() const { return size_; } + +private: + struct Slot { + bool occupied = false; + PeerLocationRecord record{}; + }; + + std::size_t find(const PeerId& peer) const; + std::size_t firstVacant() const; + std::size_t evictionCandidate() const; + static bool peerEquals(const PeerId& left, const PeerId& right); + static bool visible(const PeerLocationRecord& record, + uint64_t now_millis, + uint64_t maximum_age_millis); + void clear(std::size_t index); + + Slot slots_[MAX_PEER_LOCATIONS]{}; + std::size_t size_ = 0; +}; + +} // namespace Telemetry + +#endif // PYXIS_TELEMETRY_LOCATION_SHARE_STATE_H diff --git a/tests/native/test_location_share_state.cpp b/tests/native/test_location_share_state.cpp new file mode 100644 index 00000000..b1d9260e --- /dev/null +++ b/tests/native/test_location_share_state.cpp @@ -0,0 +1,254 @@ +#include +#include +#include +#include +#include +#include + +#include "Telemetry/LocationShareState.h" + +namespace { + +int passed = 0; +int failures = 0; + +#define CHECK(expr) \ + do { \ + if (expr) { \ + ++passed; \ + } else { \ + ++failures; \ + std::cerr << "FAIL line " << __LINE__ << ": " #expr << '\n'; \ + } \ + } while (false) + +Telemetry::PeerId peer(uint8_t seed) { + Telemetry::PeerId id{}; + for (std::size_t index = 0; index < Telemetry::PEER_ID_SIZE; ++index) { + id.bytes[index] = static_cast(seed + index); + } + return id; +} + +Telemetry::LocationTelemetry location(uint64_t seconds, int32_t latitude = 1000000) { + Telemetry::LocationTelemetry value{}; + value.latitude_e6 = latitude; + value.longitude_e6 = -1000000; + value.accuracy_cm = 100; + value.timestamp_seconds = seconds; + value.sensor_timestamp_seconds = seconds; + return value; +} + +Telemetry::CustomLocationMeta metaTimestamp(uint64_t millis) { + Telemetry::CustomLocationMeta meta{}; + meta.has_timestamp = true; + meta.timestamp_millis = millis; + return meta; +} + +bool hasPeer(const Telemetry::PeerLocationStore& store, + const Telemetry::PeerId& id, + Telemetry::PeerLocationRecord* record = nullptr) { + Telemetry::PeerLocationRecord candidate{}; + const bool found = store.get(id, candidate); + if (found && record != nullptr) *record = candidate; + return found; +} + +void insertsUpdatesAndRejectsStaleData() { + Telemetry::PeerLocationStore store; + const auto id = peer(1); + Telemetry::CustomLocationMeta no_meta{}; + + CHECK(store.apply(id, location(10, 100), no_meta, 1000) == + Telemetry::PeerLocationResult::INSERTED); + CHECK(store.size() == 1); + CHECK(store.apply(id, location(10, 200), no_meta, 1001) == + Telemetry::PeerLocationResult::UPDATED); + + Telemetry::PeerLocationRecord record{}; + CHECK(hasPeer(store, id, &record)); + CHECK(record.location.latitude_e6 == 200); + CHECK(record.source_timestamp_millis == 10000); + CHECK(record.received_at_millis == 1001); + + CHECK(store.apply(id, location(9, 300), no_meta, 1002) == + Telemetry::PeerLocationResult::STALE); + CHECK(hasPeer(store, id, &record)); + CHECK(record.location.latitude_e6 == 200); + CHECK(record.received_at_millis == 1001); + + const auto precise = metaTimestamp(10001); + CHECK(store.apply(id, location(1, 400), precise, 1003) == + Telemetry::PeerLocationResult::UPDATED); + CHECK(hasPeer(store, id, &record)); + CHECK(record.source_timestamp_millis == 10001); + CHECK(record.location.latitude_e6 == 400); +} + +void appliesOrderedCeaseWithoutTouchingOtherPeers() { + Telemetry::PeerLocationStore store; + Telemetry::CustomLocationMeta no_meta{}; + const auto first = peer(10); + const auto second = peer(20); + CHECK(store.apply(first, location(10), no_meta, 1000) == + Telemetry::PeerLocationResult::INSERTED); + CHECK(store.apply(second, location(10), no_meta, 1001) == + Telemetry::PeerLocationResult::INSERTED); + + auto cease = metaTimestamp(9999); + cease.has_cease = true; + cease.cease = true; + CHECK(store.apply(first, location(0), cease, 1002) == + Telemetry::PeerLocationResult::STALE); + CHECK(hasPeer(store, first)); + CHECK(hasPeer(store, second)); + + cease.timestamp_millis = 10000; + CHECK(store.apply(first, location(0), cease, 1003) == + Telemetry::PeerLocationResult::CEASED); + CHECK(!hasPeer(store, first)); + CHECK(hasPeer(store, second)); + CHECK(store.size() == 1); + CHECK(store.apply(first, location(0), cease, 1004) == + Telemetry::PeerLocationResult::NOT_FOUND); +} + +void reusesVacanciesBeforeDeterministicEviction() { + Telemetry::PeerLocationStore store; + Telemetry::CustomLocationMeta no_meta{}; + for (std::size_t index = 0; index < Telemetry::MAX_PEER_LOCATIONS; ++index) { + CHECK(store.apply(peer(static_cast(index)), location(10), no_meta, 5) == + Telemetry::PeerLocationResult::INSERTED); + } + CHECK(store.size() == Telemetry::MAX_PEER_LOCATIONS); + + auto cease = metaTimestamp(10000); + cease.has_cease = true; + cease.cease = true; + CHECK(store.apply(peer(10), location(0), cease, 6) == + Telemetry::PeerLocationResult::CEASED); + CHECK(store.apply(peer(100), location(11), no_meta, 6) == + Telemetry::PeerLocationResult::INSERTED); + CHECK(hasPeer(store, peer(0))); + CHECK(hasPeer(store, peer(100))); + + // Every live record had received_at=5 except the replacement at 6. With + // no vacancy, the stable tie-breaker evicts the lowest slot, peer 0. + CHECK(store.apply(peer(101), location(12), no_meta, 7) == + Telemetry::PeerLocationResult::INSERTED); + CHECK(!hasPeer(store, peer(0))); + CHECK(hasPeer(store, peer(1))); + CHECK(hasPeer(store, peer(101))); + CHECK(store.size() == Telemetry::MAX_PEER_LOCATIONS); +} + +void enforcesExpiryAndStaleDisplayBoundaries() { + Telemetry::PeerLocationStore store; + const auto id = peer(30); + auto meta = metaTimestamp(10000); + meta.has_expires = true; + meta.expires_millis = 5000; + CHECK(store.apply(id, location(10), meta, 1000) == + Telemetry::PeerLocationResult::INSERTED); + + Telemetry::PeerLocationRecord snapshot[2]{}; + CHECK(store.snapshot(4999, 10000, snapshot, 2) == 1); + CHECK(store.snapshot(5000, 10000, snapshot, 2) == 0); + CHECK(store.prune(4999, 10000) == 0); + CHECK(store.prune(5000, 10000) == 1); + CHECK(store.size() == 0); + + Telemetry::CustomLocationMeta no_meta{}; + CHECK(store.apply(id, location(20), no_meta, 1000) == + Telemetry::PeerLocationResult::INSERTED); + CHECK(store.snapshot(1100, 100, snapshot, 2) == 1); + CHECK(store.snapshot(1101, 100, snapshot, 2) == 0); + CHECK(store.snapshot(999, 100, snapshot, 2) == 1); // clock moved backward + CHECK(store.prune(1100, 100) == 0); + CHECK(store.prune(1101, 100) == 1); +} + +void expiredNewerUpdateClearsExistingState() { + Telemetry::PeerLocationStore store; + const auto id = peer(40); + Telemetry::CustomLocationMeta no_meta{}; + CHECK(store.apply(id, location(10), no_meta, 1000) == + Telemetry::PeerLocationResult::INSERTED); + + auto expired = metaTimestamp(11000); + expired.has_expires = true; + expired.expires_millis = 1999; + CHECK(store.apply(id, location(11), expired, 2000) == + Telemetry::PeerLocationResult::EXPIRED); + CHECK(!hasPeer(store, id)); + CHECK(store.size() == 0); +} + +void snapshotsAreCallerOwnedAndCapacityBounded() { + Telemetry::PeerLocationStore store; + Telemetry::CustomLocationMeta no_meta{}; + CHECK(store.apply(peer(1), location(1, 10), no_meta, 1) == + Telemetry::PeerLocationResult::INSERTED); + CHECK(store.apply(peer(2), location(2, 20), no_meta, 2) == + Telemetry::PeerLocationResult::INSERTED); + + Telemetry::PeerLocationRecord snapshot[1]{}; + CHECK(store.snapshot(2, std::numeric_limits::max(), snapshot, 1) == 1); + CHECK(snapshot[0].location.latitude_e6 == 10); + CHECK(store.apply(peer(1), location(3, 99), no_meta, 3) == + Telemetry::PeerLocationResult::UPDATED); + CHECK(snapshot[0].location.latitude_e6 == 10); +} + +void rejectsTimestampOverflowWithoutMutation() { + Telemetry::PeerLocationStore store; + Telemetry::CustomLocationMeta no_meta{}; + auto invalid = location(std::numeric_limits::max()); + CHECK(store.apply(peer(50), invalid, no_meta, 1) == + Telemetry::PeerLocationResult::INVALID_ARGUMENT); + CHECK(store.size() == 0); +} + +void survivesDeterministicHundredThousandOperationStress() { + Telemetry::PeerLocationStore store; + CHECK(sizeof(store) <= 4096); + uint32_t state = 0x12345678U; + for (std::size_t operation = 0; operation < 100000; ++operation) { + state = state * 1664525U + 1013904223U; + const auto id = peer(static_cast(state >> 24U)); + Telemetry::CustomLocationMeta meta{}; + meta.has_timestamp = true; + meta.timestamp_millis = operation; + if ((state & 0x3fU) == 0) { + meta.has_cease = true; + meta.cease = true; + } + if ((state & 0x1fU) == 1) { + meta.has_expires = true; + meta.expires_millis = operation + 10; + } + store.apply(id, location(operation / 1000U), meta, operation); + if ((operation % 257U) == 0) { + store.prune(operation, 1000); + } + CHECK(store.size() <= Telemetry::MAX_PEER_LOCATIONS); + } +} + +} // namespace + +int main() { + insertsUpdatesAndRejectsStaleData(); + appliesOrderedCeaseWithoutTouchingOtherPeers(); + reusesVacanciesBeforeDeterministicEviction(); + enforcesExpiryAndStaleDisplayBoundaries(); + expiredNewerUpdateClearsExistingState(); + snapshotsAreCallerOwnedAndCapacityBounded(); + rejectsTimestampOverflowWithoutMutation(); + survivesDeterministicHundredThousandOperationStress(); + std::cout << "location share state: " << passed << " passed, " + << failures << " failed\n"; + return failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/native/test_location_share_state.py b/tests/native/test_location_share_state.py new file mode 100644 index 00000000..de180a49 --- /dev/null +++ b/tests/native/test_location_share_state.py @@ -0,0 +1,24 @@ +"""Compile and execute bounded peer location state tests.""" + +from pathlib import Path + +from native_test import compile_and_run + +HERE = Path(__file__).resolve().parent +PYXIS_ROOT = HERE.parent.parent + + +def test_location_share_state(tmp_path): + ran = compile_and_run( + tmp_path, + name="test_location_share_state", + sources=[ + HERE / "test_location_share_state.cpp", + PYXIS_ROOT / "lib" / "tdeck_ui" / "Telemetry" / "LocationShareState.cpp", + ], + include_dirs=[PYXIS_ROOT / "lib" / "tdeck_ui"], + sanitize=True, + timeout=60, + ) + assert "location share state:" in ran.stdout + assert "0 failed" in ran.stdout