Add foundation event dispatcher tests
This commit is contained in:
@@ -69,6 +69,7 @@ add_custom_target(panopainter_validate_shaders
|
|||||||
|
|
||||||
add_library(pp_foundation STATIC
|
add_library(pp_foundation STATIC
|
||||||
src/foundation/binary_stream.cpp
|
src/foundation/binary_stream.cpp
|
||||||
|
src/foundation/event.cpp
|
||||||
src/foundation/log.cpp
|
src/foundation/log.cpp
|
||||||
src/foundation/parse.cpp
|
src/foundation/parse.cpp
|
||||||
src/foundation/task_queue.cpp
|
src/foundation/task_queue.cpp
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ Known local toolchain state:
|
|||||||
`platform-build` automation wrapper for `pp_foundation`, `pp_assets`,
|
`platform-build` automation wrapper for `pp_foundation`, `pp_assets`,
|
||||||
`pp_paint`, `pp_document`, `pp_renderer_api`, `pp_paint_renderer`,
|
`pp_paint`, `pp_document`, `pp_renderer_api`, `pp_paint_renderer`,
|
||||||
`pp_ui_core`, `pano_cli`, and their current headless test binaries,
|
`pp_ui_core`, `pano_cli`, and their current headless test binaries,
|
||||||
including foundation logging/task queue coverage, PPI header, paint stroke
|
including foundation event/logging/task queue coverage, PPI header, paint
|
||||||
sampling, and layout XML parse coverage.
|
stroke sampling, and layout XML parse coverage.
|
||||||
- `panopainter_validate_shaders` validates the current combined GLSL shader
|
- `panopainter_validate_shaders` validates the current combined GLSL shader
|
||||||
files for one vertex stage marker, one fragment stage marker, valid marker
|
files for one vertex stage marker, one fragment stage marker, valid marker
|
||||||
order, and existing relative includes.
|
order, and existing relative includes.
|
||||||
|
|||||||
@@ -304,9 +304,10 @@ Goal: split libraries while keeping current app behavior.
|
|||||||
Status: started. `pp_foundation` exists with binary stream utilities and
|
Status: started. `pp_foundation` exists with binary stream utilities and
|
||||||
boundary/overread tests. It also owns strict decimal `uint32` parsing used by
|
boundary/overread tests. It also owns strict decimal `uint32` parsing used by
|
||||||
`pano_cli`, with rejection tests for empty, signed, mixed, and overflowing
|
`pano_cli`, with rejection tests for empty, signed, mixed, and overflowing
|
||||||
input. A structured logging facade, bounded FIFO task queue, and deterministic
|
input. A synchronous event dispatcher, structured logging facade, bounded FIFO
|
||||||
`TraceRecorder` now record component/name/thread/frame/stroke metadata with
|
task queue, and deterministic `TraceRecorder` now record
|
||||||
filtering, capacity, and invalid-end tests. `pp_assets` has started with
|
component/name/thread/frame/stroke metadata with filtering, capacity, and
|
||||||
|
invalid-end tests. `pp_assets` has started with
|
||||||
PNG/JPEG signature detection plus PPI header recognition, with
|
PNG/JPEG signature detection plus PPI header recognition, with
|
||||||
corrupt/truncated/unsupported tests.
|
corrupt/truncated/unsupported tests.
|
||||||
`pp_paint` has started with CPU reference math for the five current shader
|
`pp_paint` has started with CPU reference math for the five current shader
|
||||||
@@ -524,7 +525,7 @@ Last verified on 2026-06-01:
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cmake --preset windows-msvc-default
|
cmake --preset windows-msvc-default
|
||||||
cmake --build --preset windows-msvc-default --config Debug --target pp_foundation_binary_stream_tests pp_foundation_log_tests pp_foundation_parse_tests pp_foundation_task_queue_tests pp_foundation_trace_tests pp_assets_image_format_tests pp_assets_ppi_header_tests pp_paint_blend_tests pp_paint_stroke_tests pp_document_tests pp_renderer_api_tests pp_paint_renderer_compositor_tests pp_ui_core_layout_value_tests pp_ui_core_layout_xml_tests pano_cli PanoPainter
|
cmake --build --preset windows-msvc-default --config Debug --target pp_foundation_binary_stream_tests pp_foundation_event_tests pp_foundation_log_tests pp_foundation_parse_tests pp_foundation_task_queue_tests pp_foundation_trace_tests pp_assets_image_format_tests pp_assets_ppi_header_tests pp_paint_blend_tests pp_paint_stroke_tests pp_document_tests pp_renderer_api_tests pp_paint_renderer_compositor_tests pp_ui_core_layout_value_tests pp_ui_core_layout_xml_tests pano_cli PanoPainter
|
||||||
ctest --preset desktop-fast --build-config Debug
|
ctest --preset desktop-fast --build-config Debug
|
||||||
powershell -ExecutionPolicy Bypass -File scripts\automation\test.ps1 -Preset desktop-fast -Configuration Debug
|
powershell -ExecutionPolicy Bypass -File scripts\automation\test.ps1 -Preset desktop-fast -Configuration Debug
|
||||||
powershell -ExecutionPolicy Bypass -File scripts\automation\build.ps1 -Preset windows-msvc-default -Configuration Debug -Target pano_cli
|
powershell -ExecutionPolicy Bypass -File scripts\automation\build.ps1 -Preset windows-msvc-default -Configuration Debug -Target pano_cli
|
||||||
@@ -538,6 +539,7 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -P
|
|||||||
Results:
|
Results:
|
||||||
|
|
||||||
- `pp_foundation_binary_stream_tests` passed.
|
- `pp_foundation_binary_stream_tests` passed.
|
||||||
|
- `pp_foundation_event_tests` passed.
|
||||||
- `pp_foundation_log_tests` passed.
|
- `pp_foundation_log_tests` passed.
|
||||||
- `pp_foundation_parse_tests` passed.
|
- `pp_foundation_parse_tests` passed.
|
||||||
- `pp_foundation_task_queue_tests` passed.
|
- `pp_foundation_task_queue_tests` passed.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[string[]]$Presets = @("android-arm64"),
|
[string[]]$Presets = @("android-arm64"),
|
||||||
[string[]]$Targets = @("pp_foundation", "pp_assets", "pp_paint", "pp_document", "pp_renderer_api", "pp_paint_renderer", "pp_ui_core", "pano_cli", "pp_foundation_binary_stream_tests", "pp_foundation_log_tests", "pp_foundation_parse_tests", "pp_foundation_task_queue_tests", "pp_foundation_trace_tests", "pp_assets_image_format_tests", "pp_assets_ppi_header_tests", "pp_paint_blend_tests", "pp_paint_stroke_tests", "pp_document_tests", "pp_renderer_api_tests", "pp_paint_renderer_compositor_tests", "pp_ui_core_layout_value_tests", "pp_ui_core_layout_xml_tests")
|
[string[]]$Targets = @("pp_foundation", "pp_assets", "pp_paint", "pp_document", "pp_renderer_api", "pp_paint_renderer", "pp_ui_core", "pano_cli", "pp_foundation_binary_stream_tests", "pp_foundation_event_tests", "pp_foundation_log_tests", "pp_foundation_parse_tests", "pp_foundation_task_queue_tests", "pp_foundation_trace_tests", "pp_assets_image_format_tests", "pp_assets_ppi_header_tests", "pp_paint_blend_tests", "pp_paint_stroke_tests", "pp_document_tests", "pp_renderer_api_tests", "pp_paint_renderer_compositor_tests", "pp_ui_core_layout_value_tests", "pp_ui_core_layout_xml_tests")
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ set -u
|
|||||||
|
|
||||||
preset="${1:-android-arm64}"
|
preset="${1:-android-arm64}"
|
||||||
shift || true
|
shift || true
|
||||||
targets="${*:-pp_foundation pp_assets pp_paint pp_document pp_renderer_api pp_paint_renderer pp_ui_core pano_cli pp_foundation_binary_stream_tests pp_foundation_log_tests pp_foundation_parse_tests pp_foundation_task_queue_tests pp_foundation_trace_tests pp_assets_image_format_tests pp_assets_ppi_header_tests pp_paint_blend_tests pp_paint_stroke_tests pp_document_tests pp_renderer_api_tests pp_paint_renderer_compositor_tests pp_ui_core_layout_value_tests pp_ui_core_layout_xml_tests}"
|
targets="${*:-pp_foundation pp_assets pp_paint pp_document pp_renderer_api pp_paint_renderer pp_ui_core pano_cli pp_foundation_binary_stream_tests pp_foundation_event_tests pp_foundation_log_tests pp_foundation_parse_tests pp_foundation_task_queue_tests pp_foundation_trace_tests pp_assets_image_format_tests pp_assets_ppi_header_tests pp_paint_blend_tests pp_paint_stroke_tests pp_document_tests pp_renderer_api_tests pp_paint_renderer_compositor_tests pp_ui_core_layout_value_tests pp_ui_core_layout_xml_tests}"
|
||||||
start="$(date +%s)"
|
start="$(date +%s)"
|
||||||
|
|
||||||
cmake --preset "$preset"
|
cmake --preset "$preset"
|
||||||
|
|||||||
97
src/foundation/event.cpp
Normal file
97
src/foundation/event.cpp
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#include "foundation/event.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace pp::foundation {
|
||||||
|
|
||||||
|
EventDispatcher::EventDispatcher(std::size_t max_subscriptions) noexcept
|
||||||
|
: max_subscriptions_(max_subscriptions)
|
||||||
|
{
|
||||||
|
subscriptions_.reserve(std::min(max_subscriptions_, max_event_subscriptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t EventDispatcher::size() const noexcept
|
||||||
|
{
|
||||||
|
return subscriptions_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EventDispatcher::empty() const noexcept
|
||||||
|
{
|
||||||
|
return subscriptions_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t EventDispatcher::max_subscriptions() const noexcept
|
||||||
|
{
|
||||||
|
return max_subscriptions_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<std::uint64_t> EventDispatcher::subscribe(std::uint32_t type, EventCallback callback, void* user_data)
|
||||||
|
{
|
||||||
|
if (max_subscriptions_ == 0U || max_subscriptions_ > max_event_subscriptions) {
|
||||||
|
return Result<std::uint64_t>::failure(
|
||||||
|
Status::out_of_range("event dispatcher capacity is outside the configured range"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == 0U) {
|
||||||
|
return Result<std::uint64_t>::failure(Status::invalid_argument("event type must not be zero"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback == nullptr) {
|
||||||
|
return Result<std::uint64_t>::failure(Status::invalid_argument("event callback must not be null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subscriptions_.size() >= max_subscriptions_) {
|
||||||
|
return Result<std::uint64_t>::failure(Status::out_of_range("event dispatcher is full"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto id = next_subscription_id_++;
|
||||||
|
subscriptions_.push_back(EventSubscription {
|
||||||
|
.id = id,
|
||||||
|
.type = type,
|
||||||
|
.callback = callback,
|
||||||
|
.user_data = user_data,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Result<std::uint64_t>::success(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status EventDispatcher::unsubscribe(std::uint64_t subscription_id) noexcept
|
||||||
|
{
|
||||||
|
const auto found = std::find_if(
|
||||||
|
subscriptions_.begin(),
|
||||||
|
subscriptions_.end(),
|
||||||
|
[subscription_id](const EventSubscription& subscription) {
|
||||||
|
return subscription.id == subscription_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (found == subscriptions_.end()) {
|
||||||
|
return Status::out_of_range("event subscription id was not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
subscriptions_.erase(found);
|
||||||
|
return Status::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t EventDispatcher::publish(const Event& event) const noexcept
|
||||||
|
{
|
||||||
|
if (event.type == 0U) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t delivered = 0;
|
||||||
|
for (const auto& subscription : subscriptions_) {
|
||||||
|
if (subscription.type == event.type) {
|
||||||
|
subscription.callback(event, subscription.user_data);
|
||||||
|
++delivered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return delivered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::clear() noexcept
|
||||||
|
{
|
||||||
|
subscriptions_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
48
src/foundation/event.h
Normal file
48
src/foundation/event.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "foundation/result.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace pp::foundation {
|
||||||
|
|
||||||
|
constexpr std::size_t max_event_subscriptions = 65536;
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
std::uint32_t type = 0;
|
||||||
|
std::uint64_t source_id = 0;
|
||||||
|
std::uint64_t frame_id = 0;
|
||||||
|
std::uint64_t payload_u64 = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
using EventCallback = void (*)(const Event& event, void* user_data) noexcept;
|
||||||
|
|
||||||
|
struct EventSubscription {
|
||||||
|
std::uint64_t id = 0;
|
||||||
|
std::uint32_t type = 0;
|
||||||
|
EventCallback callback = nullptr;
|
||||||
|
void* user_data = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EventDispatcher {
|
||||||
|
public:
|
||||||
|
explicit EventDispatcher(std::size_t max_subscriptions = max_event_subscriptions) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] std::size_t size() const noexcept;
|
||||||
|
[[nodiscard]] bool empty() const noexcept;
|
||||||
|
[[nodiscard]] std::size_t max_subscriptions() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] Result<std::uint64_t> subscribe(std::uint32_t type, EventCallback callback, void* user_data);
|
||||||
|
[[nodiscard]] Status unsubscribe(std::uint64_t subscription_id) noexcept;
|
||||||
|
[[nodiscard]] std::size_t publish(const Event& event) const noexcept;
|
||||||
|
void clear() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t max_subscriptions_ = max_event_subscriptions;
|
||||||
|
std::uint64_t next_subscription_id_ = 1;
|
||||||
|
std::vector<EventSubscription> subscriptions_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,6 +16,16 @@ add_test(NAME pp_foundation_binary_stream_tests COMMAND pp_foundation_binary_str
|
|||||||
set_tests_properties(pp_foundation_binary_stream_tests PROPERTIES
|
set_tests_properties(pp_foundation_binary_stream_tests PROPERTIES
|
||||||
LABELS "foundation;desktop-fast")
|
LABELS "foundation;desktop-fast")
|
||||||
|
|
||||||
|
add_executable(pp_foundation_event_tests
|
||||||
|
foundation/event_tests.cpp)
|
||||||
|
target_link_libraries(pp_foundation_event_tests PRIVATE
|
||||||
|
pp_foundation
|
||||||
|
pp_test_harness)
|
||||||
|
|
||||||
|
add_test(NAME pp_foundation_event_tests COMMAND pp_foundation_event_tests)
|
||||||
|
set_tests_properties(pp_foundation_event_tests PROPERTIES
|
||||||
|
LABELS "foundation;desktop-fast")
|
||||||
|
|
||||||
add_executable(pp_foundation_log_tests
|
add_executable(pp_foundation_log_tests
|
||||||
foundation/log_tests.cpp)
|
foundation/log_tests.cpp)
|
||||||
target_link_libraries(pp_foundation_log_tests PRIVATE
|
target_link_libraries(pp_foundation_log_tests PRIVATE
|
||||||
|
|||||||
136
tests/foundation/event_tests.cpp
Normal file
136
tests/foundation/event_tests.cpp
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
#include "foundation/event.h"
|
||||||
|
#include "test_harness.h"
|
||||||
|
|
||||||
|
using pp::foundation::Event;
|
||||||
|
using pp::foundation::EventDispatcher;
|
||||||
|
using pp::foundation::StatusCode;
|
||||||
|
using pp::foundation::max_event_subscriptions;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct Receiver {
|
||||||
|
int count = 0;
|
||||||
|
std::uint64_t payload_sum = 0;
|
||||||
|
std::uint64_t last_source = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void receive_event(const Event& event, void* user_data) noexcept
|
||||||
|
{
|
||||||
|
auto* receiver = static_cast<Receiver*>(user_data);
|
||||||
|
++receiver->count;
|
||||||
|
receiver->payload_sum += event.payload_u64;
|
||||||
|
receiver->last_source = event.source_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subscribe_and_publish_matching_events(pp::tests::Harness& h)
|
||||||
|
{
|
||||||
|
EventDispatcher dispatcher(4);
|
||||||
|
Receiver receiver;
|
||||||
|
|
||||||
|
const auto subscription = dispatcher.subscribe(7, receive_event, &receiver);
|
||||||
|
PP_EXPECT(h, subscription.ok());
|
||||||
|
PP_EXPECT(h, subscription.value() == 1U);
|
||||||
|
PP_EXPECT(h, dispatcher.size() == 1U);
|
||||||
|
PP_EXPECT(h, dispatcher.max_subscriptions() == 4U);
|
||||||
|
|
||||||
|
const auto delivered = dispatcher.publish(Event {
|
||||||
|
.type = 7,
|
||||||
|
.source_id = 42,
|
||||||
|
.frame_id = 3,
|
||||||
|
.payload_u64 = 11,
|
||||||
|
});
|
||||||
|
|
||||||
|
PP_EXPECT(h, delivered == 1U);
|
||||||
|
PP_EXPECT(h, receiver.count == 1);
|
||||||
|
PP_EXPECT(h, receiver.payload_sum == 11U);
|
||||||
|
PP_EXPECT(h, receiver.last_source == 42U);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ignores_non_matching_or_zero_events(pp::tests::Harness& h)
|
||||||
|
{
|
||||||
|
EventDispatcher dispatcher(4);
|
||||||
|
Receiver receiver;
|
||||||
|
|
||||||
|
PP_EXPECT(h, dispatcher.subscribe(2, receive_event, &receiver).ok());
|
||||||
|
PP_EXPECT(h, dispatcher.publish(Event { .type = 3, .payload_u64 = 1 }) == 0U);
|
||||||
|
PP_EXPECT(h, dispatcher.publish(Event { .type = 0, .payload_u64 = 1 }) == 0U);
|
||||||
|
PP_EXPECT(h, receiver.count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void preserves_subscription_order_and_unsubscribes(pp::tests::Harness& h)
|
||||||
|
{
|
||||||
|
EventDispatcher dispatcher(4);
|
||||||
|
Receiver first;
|
||||||
|
Receiver second;
|
||||||
|
|
||||||
|
const auto first_subscription = dispatcher.subscribe(9, receive_event, &first);
|
||||||
|
const auto second_subscription = dispatcher.subscribe(9, receive_event, &second);
|
||||||
|
PP_EXPECT(h, first_subscription.ok());
|
||||||
|
PP_EXPECT(h, second_subscription.ok());
|
||||||
|
|
||||||
|
PP_EXPECT(h, dispatcher.publish(Event { .type = 9, .payload_u64 = 5 }) == 2U);
|
||||||
|
PP_EXPECT(h, first.payload_sum == 5U);
|
||||||
|
PP_EXPECT(h, second.payload_sum == 5U);
|
||||||
|
|
||||||
|
PP_EXPECT(h, dispatcher.unsubscribe(first_subscription.value()).ok());
|
||||||
|
PP_EXPECT(h, dispatcher.publish(Event { .type = 9, .payload_u64 = 7 }) == 1U);
|
||||||
|
PP_EXPECT(h, first.payload_sum == 5U);
|
||||||
|
PP_EXPECT(h, second.payload_sum == 12U);
|
||||||
|
|
||||||
|
const auto missing = dispatcher.unsubscribe(first_subscription.value());
|
||||||
|
PP_EXPECT(h, !missing.ok());
|
||||||
|
PP_EXPECT(h, missing.code == StatusCode::out_of_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rejects_invalid_subscriptions_and_capacity(pp::tests::Harness& h)
|
||||||
|
{
|
||||||
|
EventDispatcher dispatcher(1);
|
||||||
|
EventDispatcher zero_capacity(0);
|
||||||
|
EventDispatcher excessive_capacity(max_event_subscriptions + 1U);
|
||||||
|
Receiver receiver;
|
||||||
|
|
||||||
|
const auto zero_type = dispatcher.subscribe(0, receive_event, &receiver);
|
||||||
|
const auto null_callback = dispatcher.subscribe(1, nullptr, &receiver);
|
||||||
|
PP_EXPECT(h, !zero_type.ok());
|
||||||
|
PP_EXPECT(h, zero_type.status().code == StatusCode::invalid_argument);
|
||||||
|
PP_EXPECT(h, !null_callback.ok());
|
||||||
|
PP_EXPECT(h, null_callback.status().code == StatusCode::invalid_argument);
|
||||||
|
|
||||||
|
PP_EXPECT(h, dispatcher.subscribe(1, receive_event, &receiver).ok());
|
||||||
|
const auto full = dispatcher.subscribe(2, receive_event, &receiver);
|
||||||
|
PP_EXPECT(h, !full.ok());
|
||||||
|
PP_EXPECT(h, full.status().code == StatusCode::out_of_range);
|
||||||
|
|
||||||
|
const auto zero_capacity_result = zero_capacity.subscribe(1, receive_event, &receiver);
|
||||||
|
const auto excessive_capacity_result = excessive_capacity.subscribe(1, receive_event, &receiver);
|
||||||
|
PP_EXPECT(h, !zero_capacity_result.ok());
|
||||||
|
PP_EXPECT(h, zero_capacity_result.status().code == StatusCode::out_of_range);
|
||||||
|
PP_EXPECT(h, !excessive_capacity_result.ok());
|
||||||
|
PP_EXPECT(h, excessive_capacity_result.status().code == StatusCode::out_of_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_removes_all_subscriptions(pp::tests::Harness& h)
|
||||||
|
{
|
||||||
|
EventDispatcher dispatcher(4);
|
||||||
|
Receiver receiver;
|
||||||
|
|
||||||
|
PP_EXPECT(h, dispatcher.subscribe(1, receive_event, &receiver).ok());
|
||||||
|
PP_EXPECT(h, dispatcher.subscribe(2, receive_event, &receiver).ok());
|
||||||
|
dispatcher.clear();
|
||||||
|
PP_EXPECT(h, dispatcher.empty());
|
||||||
|
PP_EXPECT(h, dispatcher.publish(Event { .type = 1, .payload_u64 = 5 }) == 0U);
|
||||||
|
PP_EXPECT(h, receiver.count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
pp::tests::Harness harness;
|
||||||
|
harness.run("subscribe_and_publish_matching_events", subscribe_and_publish_matching_events);
|
||||||
|
harness.run("ignores_non_matching_or_zero_events", ignores_non_matching_or_zero_events);
|
||||||
|
harness.run("preserves_subscription_order_and_unsubscribes", preserves_subscription_order_and_unsubscribes);
|
||||||
|
harness.run("rejects_invalid_subscriptions_and_capacity", rejects_invalid_subscriptions_and_capacity);
|
||||||
|
harness.run("clear_removes_all_subscriptions", clear_removes_all_subscriptions);
|
||||||
|
return harness.finish();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user