mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-07 18:08:53 +00:00
Remove EventPublisher macros
This commit is contained in:
parent
353b44c6cc
commit
0d00e4b0e9
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user