Files
roro9stack/test/test_event_bus/test_event_bus.cpp
T
twislaandClaude Opus 5.5 ae0726b7f9 Add core runtime: event bus, services, app lifecycle
lib/core is hardware-independent and unit-tested on the host:
- EventBus: fixed-size thread-safe queue, delivered on the UI task by
  dispatch(); drops newest when full and counts drops
- Service / ServiceManager: cooperative ticking at per-service intervals,
  no catch-up bursts, safe across millis() wraparound
- App / AppManager: one foreground App, Home always to Launcher, Back
  offered to the App first, hidden Apps, redraw requests
- KeyEvent: logical keys for the upcoming input layer

Firmware main loop now ticks services and dispatches events.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-02 09:10:10 +02:00

119 lines
3.9 KiB
C++

#include <unity.h>
#include <string>
#include <vector>
#include "event_bus.h"
using namespace roro;
void setUp() {}
void tearDown() {}
void test_published_events_are_delivered_on_dispatch_not_before() {
EventBus bus(8);
int calls = 0;
bus.subscribe(EventType::BatteryChanged, [&](const Event&) { calls++; });
bus.publish(Event{EventType::BatteryChanged});
TEST_ASSERT_EQUAL(0, calls);
TEST_ASSERT_EQUAL(1, bus.dispatch());
TEST_ASSERT_EQUAL(1, calls);
}
void test_only_subscribers_of_the_event_type_are_called() {
EventBus bus(8);
int battery = 0, notification = 0;
bus.subscribe(EventType::BatteryChanged, [&](const Event&) { battery++; });
bus.subscribe(EventType::Notification, [&](const Event&) { notification++; });
bus.publish(Event{EventType::Notification});
bus.dispatch();
TEST_ASSERT_EQUAL(0, battery);
TEST_ASSERT_EQUAL(1, notification);
}
void test_every_subscriber_of_a_type_is_called_in_subscription_order() {
EventBus bus(8);
std::vector<int> order;
bus.subscribe(EventType::Notification, [&](const Event&) { order.push_back(1); });
bus.subscribe(EventType::Notification, [&](const Event&) { order.push_back(2); });
bus.publish(Event{EventType::Notification});
bus.dispatch();
TEST_ASSERT_EQUAL(2, order.size());
TEST_ASSERT_EQUAL(1, order[0]);
TEST_ASSERT_EQUAL(2, order[1]);
}
void test_events_keep_publish_order_and_payload() {
EventBus bus(8);
std::vector<int32_t> values;
bus.subscribe(EventType::BatteryChanged, [&](const Event& e) { values.push_back(e.a); });
bus.publish(Event::withValues(EventType::BatteryChanged, 80));
bus.publish(Event::withValues(EventType::BatteryChanged, 79));
bus.dispatch();
TEST_ASSERT_EQUAL(2, values.size());
TEST_ASSERT_EQUAL(80, values[0]);
TEST_ASSERT_EQUAL(79, values[1]);
}
void test_text_payload_is_copied_and_truncated_safely() {
EventBus bus(8);
std::string received;
bus.subscribe(EventType::Notification, [&](const Event& e) { received = e.text; });
std::string longText(200, 'x');
bus.publish(Event::withText(EventType::Notification, longText.c_str()));
bus.dispatch();
TEST_ASSERT_EQUAL(Event::kTextCapacity - 1, received.size());
}
void test_full_queue_drops_newest_and_counts_drops() {
EventBus bus(2);
std::vector<int32_t> values;
bus.subscribe(EventType::BatteryChanged, [&](const Event& e) { values.push_back(e.a); });
TEST_ASSERT_TRUE(bus.publish(Event::withValues(EventType::BatteryChanged, 1)));
TEST_ASSERT_TRUE(bus.publish(Event::withValues(EventType::BatteryChanged, 2)));
TEST_ASSERT_FALSE(bus.publish(Event::withValues(EventType::BatteryChanged, 3)));
TEST_ASSERT_EQUAL(1, bus.dropped());
bus.dispatch();
TEST_ASSERT_EQUAL(2, values.size());
TEST_ASSERT_EQUAL(2, values[1]);
}
void test_events_published_during_dispatch_wait_for_next_dispatch() {
EventBus bus(8);
int notifications = 0;
bus.subscribe(EventType::BatteryChanged,
[&](const Event&) { bus.publish(Event{EventType::Notification}); });
bus.subscribe(EventType::Notification, [&](const Event&) { notifications++; });
bus.publish(Event{EventType::BatteryChanged});
TEST_ASSERT_EQUAL(1, bus.dispatch());
TEST_ASSERT_EQUAL(0, notifications);
TEST_ASSERT_EQUAL(1, bus.dispatch());
TEST_ASSERT_EQUAL(1, notifications);
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_published_events_are_delivered_on_dispatch_not_before);
RUN_TEST(test_only_subscribers_of_the_event_type_are_called);
RUN_TEST(test_every_subscriber_of_a_type_is_called_in_subscription_order);
RUN_TEST(test_events_keep_publish_order_and_payload);
RUN_TEST(test_text_payload_is_copied_and_truncated_safely);
RUN_TEST(test_full_queue_drops_newest_and_counts_drops);
RUN_TEST(test_events_published_during_dispatch_wait_for_next_dispatch);
return UNITY_END();
}