Remove EventPublisher macros

This commit is contained in:
Teddy Reed 2014-12-14 04:43:31 -07:00
parent 353b44c6cc
commit 0d00e4b0e9
4 changed files with 141 additions and 157 deletions

View File

@ -19,6 +19,8 @@
namespace osquery { namespace osquery {
struct Subscription; struct Subscription;
template <class SC, class EC>
class EventPublisher; class EventPublisher;
class EventSubscriber; class EventSubscriber;
@ -62,7 +64,8 @@ struct EventContext {
}; };
typedef std::shared_ptr<Subscription> SubscriptionRef; typedef std::shared_ptr<Subscription> SubscriptionRef;
typedef std::shared_ptr<EventPublisher> EventPublisherRef; typedef std::shared_ptr<EventPublisher<SubscriptionContext, EventContext> >
EventPublisherRef;
typedef std::shared_ptr<SubscriptionContext> SubscriptionContextRef; typedef std::shared_ptr<SubscriptionContext> SubscriptionContextRef;
typedef std::shared_ptr<EventContext> EventContextRef; typedef std::shared_ptr<EventContext> EventContextRef;
typedef std::shared_ptr<EventSubscriber> EventSubscriberRef; typedef std::shared_ptr<EventSubscriber> EventSubscriberRef;
@ -78,49 +81,6 @@ typedef std::map<EventPublisherID, EventPublisherRef> EventPublisherMap;
/// The set of search-time binned lookup tables. /// The set of search-time binned lookup tables.
extern const std::vector<size_t> kEventTimeLists; extern const std::vector<size_t> kEventTimeLists;
/**
* @brief Helper type casting methods for EventPublisher classes.
*
* A new osquery EventPublisher should subclass EventPublisher and use the
* following:
*
* @code{.cpp}
* #include <osquery/events.h>
*
* class MyEventPublisher: public EventPublisher {
* DECLARE_EVENTPUBLISHER(MyEventPublisher, MySubscriptionContext,
* MyEventContext);
* }
* @endcode
*
* This assumes new EventPublisher%s will always include a custom
* SubscriptionContext and EventContext. In the above example
* MySubscriptionContext allows EventSubscriber%s to downselect or customize
* what events to handle. And MyEventContext includes fields specific to the
* new EventPublisher.
*/
#define DECLARE_EVENTPUBLISHER(TYPE, MONITOR, EVENT) \
public: \
EventPublisherID type() const { return #TYPE; } \
bool shouldFire(const SubscriptionContextRef mc, const EventContextRef ec) { \
if (#MONITOR == "SubscriptionContext" && #EVENT == "EventContext") \
return true; \
return shouldFire(getSubscriptionContext(mc), getEventContext(ec)); \
} \
static std::shared_ptr<EVENT> getEventContext(EventContextRef context) { \
return std::static_pointer_cast<EVENT>(context); \
} \
static std::shared_ptr<MONITOR> getSubscriptionContext( \
SubscriptionContextRef context) { \
return std::static_pointer_cast<MONITOR>(context); \
} \
static std::shared_ptr<EVENT> createEventContext() { \
return std::make_shared<EVENT>(); \
} \
static std::shared_ptr<MONITOR> createSubscriptionContext() { \
return std::make_shared<MONITOR>(); \
}
/** /**
* @brief Required getter and namespace helper methods for EventSubscriber%s. * @brief Required getter and namespace helper methods for EventSubscriber%s.
* *
@ -308,7 +268,11 @@ struct Subscription {
* only call the Subscription%'s callback function is the EventContext * only call the Subscription%'s callback function is the EventContext
* (thus event) matches. * (thus event) matches.
*/ */
template <typename SC, typename EC>
class EventPublisher { class EventPublisher {
typedef std::shared_ptr<SC> SCRef;
typedef std::shared_ptr<EC> ECRef;
public: public:
/** /**
* @brief A new Subscription was added, potentially change state based on all * @brief A new Subscription was added, potentially change state based on all
@ -329,7 +293,7 @@ class EventPublisher {
* When `setUp` is called the EventPublisher is running in a dedicated thread * When `setUp` is called the EventPublisher is running in a dedicated thread
* and may manage/allocate/wait for resources. * and may manage/allocate/wait for resources.
*/ */
virtual Status setUp() { return Status(0, "Not used."); } virtual Status setUp() { return Status(0, "Not used"); }
/** /**
* @brief Perform handle closing, resource cleanup. * @brief Perform handle closing, resource cleanup.
@ -345,7 +309,7 @@ class EventPublisher {
* @return A SUCCESS status will immediately call `run` again. A FAILED status * @return A SUCCESS status will immediately call `run` again. A FAILED status
* will exit the run loop and the thread. * will exit the run loop and the thread.
*/ */
virtual Status run(); virtual Status run() { return Status(1, "No runloop required"); }
/** /**
* @brief A new EventSubscriber is subscriptioning events of this * @brief A new EventSubscriber is subscriptioning events of this
@ -376,16 +340,7 @@ class EventPublisher {
virtual ~EventPublisher() {} virtual ~EventPublisher() {}
/// Return a string identifier associated with this EventPublisher. /// Return a string identifier associated with this EventPublisher.
virtual EventPublisherID type() const = 0; virtual EventPublisherID type() { return "publisher"; }
/// Return a string identifier for the given EventPublisher symbol.
template <typename T>
static EventPublisherID type() {
const auto& event_pub = new T();
auto type_id = event_pub->type();
delete event_pub;
return type_id;
}
public: public:
/** /**
@ -399,6 +354,19 @@ class EventPublisher {
*/ */
void fire(const EventContextRef ec, EventTime time = 0); void fire(const EventContextRef ec, EventTime time = 0);
public:
/// Templating accessors/factories.
static ECRef getEventContext(EventContextRef ec) {
return std::static_pointer_cast<EC>(ec);
}
static SCRef getSubscriptionContext(SubscriptionContextRef sc) {
return std::static_pointer_cast<SC>(sc);
}
static ECRef createEventContext() { return std::make_shared<EC>(); }
static SCRef createSubscriptionContext() { return std::make_shared<SC>(); }
protected: protected:
/** /**
* @brief The generic `fire` will call `shouldFire` for each Subscription. * @brief The generic `fire` will call `shouldFire` for each Subscription.
@ -409,8 +377,7 @@ class EventPublisher {
* *
* @return should the Subscription%'s EventCallback be called for this event. * @return should the Subscription%'s EventCallback be called for this event.
*/ */
virtual bool shouldFire(const SubscriptionContextRef mc, virtual bool shouldFire(const SCRef sc, const ECRef ec) { return true; }
const EventContextRef ec);
protected: protected:
/// The EventPublisher will keep track of Subscription%s that contain callins. /// The EventPublisher will keep track of Subscription%s that contain callins.
@ -425,6 +392,7 @@ class EventPublisher {
boost::mutex ec_id_lock_; boost::mutex ec_id_lock_;
private: private:
FRIEND_TEST(EventsTests, test_event_pub);
FRIEND_TEST(EventsTests, test_fire_event); FRIEND_TEST(EventsTests, test_fire_event);
}; };
@ -600,6 +568,7 @@ class EventSubscriber {
boost::mutex event_record_lock_; boost::mutex event_record_lock_;
private: private:
FRIEND_TEST(EventsTests, test_event_sub);
FRIEND_TEST(EventsDatabaseTests, test_event_module_id); FRIEND_TEST(EventsDatabaseTests, test_event_module_id);
FRIEND_TEST(EventsDatabaseTests, test_unique_event_module_id); FRIEND_TEST(EventsDatabaseTests, test_unique_event_module_id);
FRIEND_TEST(EventsDatabaseTests, test_record_indexing); FRIEND_TEST(EventsDatabaseTests, test_record_indexing);
@ -627,10 +596,10 @@ class EventFactory {
* *
* The registration is mostly abstracted using osquery's registery. * The registration is mostly abstracted using osquery's registery.
*/ */
template <typename T> template <class T>
static Status registerEventPublisher() { static Status registerEventPublisher() {
auto event_pub = std::make_shared<T>(); auto pub = std::make_shared<T>();
return EventFactory::registerEventPublisher(event_pub); return registerEventPublisher<T>(pub);
} }
/** /**
@ -644,7 +613,13 @@ class EventFactory {
* Access to the EventPublisher instance is not discouraged, but using the * Access to the EventPublisher instance is not discouraged, but using the
* EventFactory `getEventPublisher` accessor is encouraged. * EventFactory `getEventPublisher` accessor is encouraged.
*/ */
static Status registerEventPublisher(const EventPublisherRef event_pub); template <class T>
static Status registerEventPublisher(std::shared_ptr<T> pub) {
auto base_pub = reinterpret_cast<EventPublisherRef&>(pub);
return registerEventPublisher(base_pub);
}
static Status registerEventPublisher(const EventPublisherRef pub);
/** /**
* @brief Add an EventSubscriber to the factory. * @brief Add an EventSubscriber to the factory.
@ -699,14 +674,14 @@ class EventFactory {
template <typename T> template <typename T>
static Status addSubscription(const SubscriptionContextRef mc, static Status addSubscription(const SubscriptionContextRef mc,
EventCallback cb = 0) { EventCallback cb = 0) {
return addSubscription(EventPublisher::type<T>(), mc, cb); return addSubscription(T::type(), mc, cb);
} }
/// Add a Subscription by templating the EventPublisher, using a Subscription /// Add a Subscription by templating the EventPublisher, using a Subscription
/// instance. /// instance.
template <typename T> template <typename T>
static Status addSubscription(const SubscriptionRef subscription) { static Status addSubscription(const SubscriptionRef subscription) {
return addSubscription(EventPublisher::type<T>(), subscription); return addSubscription(T::type(), subscription);
} }
/// Get the total number of Subscription%s across ALL EventPublisher%s. /// Get the total number of Subscription%s across ALL EventPublisher%s.
@ -750,7 +725,7 @@ class EventFactory {
/// If a static EventPublisher callback wants to fire /// If a static EventPublisher callback wants to fire
template <typename T> template <typename T>
static void fire(const EventContextRef ec) { static void fire(const EventContextRef ec) {
auto event_pub = getEventPublisher(EventPublisher::type<T>()); auto event_pub = getEventPublisher(T::type());
event_pub->fire(ec); event_pub->fire(ec);
} }

View File

@ -30,7 +30,8 @@ const std::vector<size_t> kEventTimeLists = {
10, // 10 seconds 10, // 10 seconds
}; };
void EventPublisher::fire(const EventContextRef ec, EventTime time) { template <typename SC, typename EC>
void EventPublisher<SC, EC>::fire(const EventContextRef ec, EventTime time) {
EventContextID ec_id; EventContextID ec_id;
{ {
@ -55,21 +56,16 @@ void EventPublisher::fire(const EventContextRef ec, EventTime time) {
for (const auto& subscription : subscriptions_) { for (const auto& subscription : subscriptions_) {
auto callback = subscription->callback; auto callback = subscription->callback;
if (shouldFire(subscription->context, ec) && callback != nullptr) { if (shouldFire(getSubscriptionContext(subscription->context),
getEventContext(ec)) &&
callback != nullptr) {
callback(ec, false); callback(ec, false);
} }
} }
} }
bool EventPublisher::shouldFire(const SubscriptionContextRef mc, /// Force generation of EventPublisher::fire
const EventContextRef ec) { template class EventPublisher<SubscriptionContext, EventContext>;
return true;
}
Status EventPublisher::run() {
// Runloops/entrypoints are ONLY implemented if needed.
return Status(1, "No runloop required");
}
std::vector<std::string> EventSubscriber::getIndexes(EventTime start, std::vector<std::string> EventSubscriber::getIndexes(EventTime start,
EventTime stop, EventTime stop,
@ -417,21 +413,21 @@ EventFactory& EventFactory::getInstance() {
return ef; return ef;
} }
Status EventFactory::registerEventPublisher(const EventPublisherRef event_pub) { Status EventFactory::registerEventPublisher(const EventPublisherRef pub) {
auto& ef = EventFactory::getInstance(); auto& ef = EventFactory::getInstance();
auto type_id = event_pub->type(); auto type_id = pub->type();
if (ef.getEventPublisher(type_id) != nullptr) { if (ef.getEventPublisher(type_id) != nullptr) {
// This is a duplicate type id? // This is a duplicate type id?
return Status(1, "Duplicate Event Type"); return Status(1, "Duplicate Event Type");
} }
if (!event_pub->setUp().ok()) { if (!pub->setUp().ok()) {
// Only add the publisher if setUp was successful. // Only add the publisher if setUp was successful.
return Status(1, "SetUp failed."); return Status(1, "SetUp failed.");
} }
ef.event_pubs_[type_id] = event_pub; ef.event_pubs_[type_id] = pub;
return Status(0, "OK"); return Status(0, "OK");
} }
@ -474,8 +470,7 @@ size_t EventFactory::numSubscriptions(EventPublisherID type_id) {
return 0; return 0;
} }
std::shared_ptr<EventPublisher> EventFactory::getEventPublisher( EventPublisherRef EventFactory::getEventPublisher(EventPublisherID type_id) {
EventPublisherID type_id) {
auto& ef = EventFactory::getInstance(); auto& ef = EventFactory::getInstance();
const auto& it = ef.event_pubs_.find(type_id); const auto& it = ef.event_pubs_.find(type_id);
if (it != ef.event_pubs_.end()) { if (it != ef.event_pubs_.end()) {

View File

@ -34,8 +34,10 @@ class FakeEventSubscriber : public EventSubscriber {
} }
}; };
class FakeEventPublisher : public EventPublisher { class FakeEventPublisher
DECLARE_EVENTPUBLISHER(FakeEventPublisher, SubscriptionContext, EventContext); : public EventPublisher<SubscriptionContext, EventContext> {
public:
EventPublisherID type() { return "Fake"; }
}; };
class AnotherFakeEventSubscriber : public EventSubscriber { class AnotherFakeEventSubscriber : public EventSubscriber {

View File

@ -1,5 +1,7 @@
// Copyright 2004-present Facebook. All Rights Reserved. // Copyright 2004-present Facebook. All Rights Reserved.
#include <typeinfo>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <osquery/events.h> #include <osquery/events.h>
@ -7,71 +9,91 @@
namespace osquery { namespace osquery {
class EventsTests : public testing::Test { class EventsTests : public ::testing::Test {
public: public:
void TearDown() { EventFactory::deregisterEventPublishers(); } void TearDown() { EventFactory::deregisterEventPublishers(); }
}; };
class BasicEventPublisher : public EventPublisher { // The most basic event publisher uses useless Subscription/Event.
DECLARE_EVENTPUBLISHER(BasicEventPublisher, class BasicEventPublisher
SubscriptionContext, : public EventPublisher<SubscriptionContext, EventContext> {};
EventContext); class AnotherBasicEventPublisher
: public EventPublisher<SubscriptionContext, EventContext> {};
// Create some still-useless subscription and event structures.
struct FakeSubscriptionContext : SubscriptionContext {};
struct FakeEventContext : EventContext {};
// Typdef the shared_ptr accessors.
typedef std::shared_ptr<FakeSubscriptionContext> FakeSubscriptionContextRef;
typedef std::shared_ptr<FakeEventContext> FakeEventContextRef;
// Now a publisher with a type.
class FakeEventPublisher
: public EventPublisher<FakeSubscriptionContext, FakeEventContext> {
public:
EventPublisherID type() { return "Fake"; }
}; };
class FakeBasicEventPublisher : public EventPublisher { class AnotherFakeEventPublisher
DECLARE_EVENTPUBLISHER(FakeBasicEventPublisher, : public EventPublisher<FakeSubscriptionContext, FakeEventContext> {
SubscriptionContext, public:
EventContext); EventPublisherID type() { return "AnotherFake"; }
}; };
TEST_F(EventsTests, test_event_pub) {
auto pub = std::make_shared<FakeEventPublisher>();
EXPECT_EQ(pub->type(), "Fake");
// Test type names.
auto pub_sub = pub->createSubscriptionContext();
EXPECT_EQ(typeid(FakeSubscriptionContext), typeid(*pub_sub));
}
TEST_F(EventsTests, test_register_event_pub) { TEST_F(EventsTests, test_register_event_pub) {
Status status;
// A caller may register an event type using the class template. // A caller may register an event type using the class template.
status = EventFactory::registerEventPublisher<BasicEventPublisher>(); // This template class is equivilent to the reinterpret casting target.
auto status = EventFactory::registerEventPublisher<BasicEventPublisher>();
EXPECT_TRUE(status.ok());
// This class is the SAME, there was no type override.
status = EventFactory::registerEventPublisher<AnotherBasicEventPublisher>();
EXPECT_FALSE(status.ok());
// This class is different but also uses different types!
status = EventFactory::registerEventPublisher<FakeEventPublisher>();
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
// May also register the event_pub instance // May also register the event_pub instance
auto event_pub_instance = std::make_shared<FakeBasicEventPublisher>(); auto pub = std::make_shared<AnotherFakeEventPublisher>();
status = EventFactory::registerEventPublisher(event_pub_instance); status = EventFactory::registerEventPublisher<AnotherFakeEventPublisher>(pub);
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
// May NOT register without subclassing, enforced at compile time.
} }
TEST_F(EventsTests, test_create_event_pub) { TEST_F(EventsTests, test_create_event_pub) {
Status status; auto status = EventFactory::registerEventPublisher<BasicEventPublisher>();
status = EventFactory::registerEventPublisher<BasicEventPublisher>();
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
// Do not register the same event type twice.
status = EventFactory::registerEventPublisher<BasicEventPublisher>();
EXPECT_FALSE(status.ok());
// Make sure only the first event type was recorded. // Make sure only the first event type was recorded.
EXPECT_EQ(EventFactory::numEventPublishers(), 1); EXPECT_EQ(EventFactory::numEventPublishers(), 1);
} }
TEST_F(EventsTests, test_create_subscription) { TEST_F(EventsTests, test_create_subscription) {
Status status;
EventFactory::registerEventPublisher<BasicEventPublisher>(); EventFactory::registerEventPublisher<BasicEventPublisher>();
// Make sure a subscription cannot be added for a non-existent event type. // Make sure a subscription cannot be added for a non-existent event type.
// Note: It normally would not make sense to create a blank subscription. // Note: It normally would not make sense to create a blank subscription.
auto subscription = Subscription::create(); auto subscription = Subscription::create();
status = auto status = EventFactory::addSubscription("Fake", subscription);
EventFactory::addSubscription("FakeBasicEventPublisher", subscription);
EXPECT_FALSE(status.ok()); EXPECT_FALSE(status.ok());
// In this case we can still add a blank subscription to an existing event // In this case we can still add a blank subscription to an existing event
// type. // type.
status = EventFactory::addSubscription("BasicEventPublisher", subscription); status = EventFactory::addSubscription("publisher", subscription);
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
// Make sure the subscription is added. // Make sure the subscription is added.
EXPECT_EQ(EventFactory::numSubscriptions("BasicEventPublisher"), 1); EXPECT_EQ(EventFactory::numSubscriptions("publisher"), 1);
} }
TEST_F(EventsTests, test_multiple_subscriptions) { TEST_F(EventsTests, test_multiple_subscriptions) {
@ -80,22 +102,20 @@ TEST_F(EventsTests, test_multiple_subscriptions) {
EventFactory::registerEventPublisher<BasicEventPublisher>(); EventFactory::registerEventPublisher<BasicEventPublisher>();
auto subscription = Subscription::create(); auto subscription = Subscription::create();
status = EventFactory::addSubscription("BasicEventPublisher", subscription); status = EventFactory::addSubscription("publisher", subscription);
status = EventFactory::addSubscription("BasicEventPublisher", subscription); status = EventFactory::addSubscription("publisher", subscription);
EXPECT_EQ(EventFactory::numSubscriptions("BasicEventPublisher"), 2); EXPECT_EQ(EventFactory::numSubscriptions("publisher"), 2);
} }
struct TestSubscriptionContext : public SubscriptionContext { struct TestSubscriptionContext : public SubscriptionContext {
int smallest; int smallest;
}; };
class TestEventPublisher : public EventPublisher { class TestEventPublisher
DECLARE_EVENTPUBLISHER(TestEventPublisher, : public EventPublisher<TestSubscriptionContext, EventContext> {
TestSubscriptionContext,
EventContext);
public: public:
EventPublisherID type() { return "Test"; }
Status setUp() { Status setUp() {
smallest_ever_ += 1; smallest_ever_ += 1;
return Status(0, "OK"); return Status(0, "OK");
@ -133,65 +153,58 @@ class TestEventPublisher : public EventPublisher {
}; };
TEST_F(EventsTests, test_create_custom_event_pub) { TEST_F(EventsTests, test_create_custom_event_pub) {
Status status; auto status = EventFactory::registerEventPublisher<BasicEventPublisher>();
auto pub = std::make_shared<TestEventPublisher>();
status = EventFactory::registerEventPublisher<BasicEventPublisher>(); status = EventFactory::registerEventPublisher(pub);
auto test_event_pub = std::make_shared<TestEventPublisher>();
status = EventFactory::registerEventPublisher(test_event_pub);
// These event types have unique event type IDs // These event types have unique event type IDs
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
EXPECT_EQ(EventFactory::numEventPublishers(), 2); EXPECT_EQ(EventFactory::numEventPublishers(), 2);
// Make sure the setUp function was called. // Make sure the setUp function was called.
EXPECT_EQ(test_event_pub->getTestValue(), 1); EXPECT_EQ(pub->getTestValue(), 1);
} }
TEST_F(EventsTests, test_custom_subscription) { TEST_F(EventsTests, test_custom_subscription) {
Status status;
// Step 1, register event type // Step 1, register event type
auto event_pub = std::make_shared<TestEventPublisher>(); auto pub = std::make_shared<TestEventPublisher>();
status = EventFactory::registerEventPublisher(event_pub); auto status = EventFactory::registerEventPublisher(pub);
// Step 2, create and configure a subscription context // Step 2, create and configure a subscription context
auto subscription_context = std::make_shared<TestSubscriptionContext>(); auto sc = std::make_shared<TestSubscriptionContext>();
subscription_context->smallest = -1; sc->smallest = -1;
// Step 3, add the subscription to the event type // Step 3, add the subscription to the event type
status = status = EventFactory::addSubscription("Test", sc);
EventFactory::addSubscription("TestEventPublisher", subscription_context);
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
EXPECT_EQ(event_pub->numSubscriptions(), 1); EXPECT_EQ(pub->numSubscriptions(), 1);
// The event type must run configure for each added subscription. // The event type must run configure for each added subscription.
EXPECT_TRUE(event_pub->configure_run); EXPECT_TRUE(pub->configure_run);
EXPECT_EQ(event_pub->getTestValue(), -1); EXPECT_EQ(pub->getTestValue(), -1);
} }
TEST_F(EventsTests, test_tear_down) { TEST_F(EventsTests, test_tear_down) {
Status status; auto pub = std::make_shared<TestEventPublisher>();
auto status = EventFactory::registerEventPublisher(pub);
auto event_pub = std::make_shared<TestEventPublisher>();
status = EventFactory::registerEventPublisher(event_pub);
// Make sure set up incremented the test value. // Make sure set up incremented the test value.
EXPECT_EQ(event_pub->getTestValue(), 1); EXPECT_EQ(pub->getTestValue(), 1);
status = EventFactory::deregisterEventPublisher("TestEventPublisher"); status = EventFactory::deregisterEventPublisher("Test");
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
// Make sure tear down inremented the test value. // Make sure tear down inremented the test value.
EXPECT_EQ(event_pub->getTestValue(), 2); EXPECT_EQ(pub->getTestValue(), 2);
// Once more, now deregistering all event types. // Once more, now deregistering all event types.
status = EventFactory::registerEventPublisher(event_pub); status = EventFactory::registerEventPublisher(pub);
EXPECT_EQ(event_pub->getTestValue(), 3); EXPECT_EQ(pub->getTestValue(), 3);
status = EventFactory::deregisterEventPublishers(); status = EventFactory::deregisterEventPublishers();
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
EXPECT_EQ(event_pub->getTestValue(), 4); EXPECT_EQ(pub->getTestValue(), 4);
// Make sure the factory state represented. // Make sure the factory state represented.
EXPECT_EQ(EventFactory::numEventPublishers(), 0); EXPECT_EQ(EventFactory::numEventPublishers(), 0);
@ -207,29 +220,28 @@ Status TestTheeCallback(EventContextRef context, bool reserved) {
TEST_F(EventsTests, test_fire_event) { TEST_F(EventsTests, test_fire_event) {
Status status; Status status;
auto event_pub = std::make_shared<BasicEventPublisher>(); auto pub = std::make_shared<BasicEventPublisher>();
status = EventFactory::registerEventPublisher(event_pub); status = EventFactory::registerEventPublisher(pub);
auto subscription = Subscription::create(); auto subscription = Subscription::create();
subscription->callback = TestTheeCallback; subscription->callback = TestTheeCallback;
status = EventFactory::addSubscription("BasicEventPublisher", subscription); status = EventFactory::addSubscription("publisher", subscription);
// The event context creation would normally happen in the event type. // The event context creation would normally happen in the event type.
auto ec = event_pub->createEventContext(); auto ec = pub->createEventContext();
event_pub->fire(ec, 0); pub->fire(ec, 0);
EXPECT_EQ(kBellHathTolled, 1); EXPECT_EQ(kBellHathTolled, 1);
auto second_subscription = Subscription::create(); auto second_subscription = Subscription::create();
status = status = EventFactory::addSubscription("publisher", second_subscription);
EventFactory::addSubscription("BasicEventPublisher", second_subscription);
// Now there are two subscriptions (one sans callback). // Now there are two subscriptions (one sans callback).
event_pub->fire(ec, 0); pub->fire(ec, 0);
EXPECT_EQ(kBellHathTolled, 2); EXPECT_EQ(kBellHathTolled, 2);
// Now both subscriptions have callbacks. // Now both subscriptions have callbacks.
second_subscription->callback = TestTheeCallback; second_subscription->callback = TestTheeCallback;
event_pub->fire(ec, 0); pub->fire(ec, 0);
EXPECT_EQ(kBellHathTolled, 4); EXPECT_EQ(kBellHathTolled, 4);
} }
} }