Public Access
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
119 lines
3.9 KiB
C++
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();
|
|
}
|