2014-09-18 04:20:30 +00:00
|
|
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
#include <typeinfo>
|
|
|
|
|
2014-09-30 02:06:33 +00:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/events.h>
|
|
|
|
#include <osquery/tables.h>
|
2014-11-26 01:19:11 +00:00
|
|
|
|
2014-09-18 04:20:30 +00:00
|
|
|
namespace osquery {
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
class EventsTests : public ::testing::Test {
|
2014-09-30 02:06:33 +00:00
|
|
|
public:
|
2014-10-03 15:14:36 +00:00
|
|
|
void TearDown() { EventFactory::deregisterEventPublishers(); }
|
2014-09-18 04:20:30 +00:00
|
|
|
};
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
// The most basic event publisher uses useless Subscription/Event.
|
|
|
|
class BasicEventPublisher
|
|
|
|
: public EventPublisher<SubscriptionContext, 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> {
|
2014-12-15 02:03:41 +00:00
|
|
|
DECLARE_PUBLISHER("FakePublisher");
|
2014-09-18 04:20:30 +00:00
|
|
|
};
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
class AnotherFakeEventPublisher
|
|
|
|
: public EventPublisher<FakeSubscriptionContext, FakeEventContext> {
|
2014-12-15 02:03:41 +00:00
|
|
|
DECLARE_PUBLISHER("AnotherFakePublisher");
|
2014-09-18 04:20:30 +00:00
|
|
|
};
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
TEST_F(EventsTests, test_event_pub) {
|
|
|
|
auto pub = std::make_shared<FakeEventPublisher>();
|
2014-12-15 02:03:41 +00:00
|
|
|
EXPECT_EQ(pub->type(), "FakePublisher");
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
// Test type names.
|
|
|
|
auto pub_sub = pub->createSubscriptionContext();
|
|
|
|
EXPECT_EQ(typeid(FakeSubscriptionContext), typeid(*pub_sub));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(EventsTests, test_register_event_pub) {
|
2014-09-18 04:20:30 +00:00
|
|
|
// A caller may register an event type using the class template.
|
2014-12-14 11:43:31 +00:00
|
|
|
// This template class is equivilent to the reinterpret casting target.
|
|
|
|
auto status = EventFactory::registerEventPublisher<BasicEventPublisher>();
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_TRUE(status.ok());
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
// 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>();
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_TRUE(status.ok());
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
// May also register the event_pub instance
|
|
|
|
auto pub = std::make_shared<AnotherFakeEventPublisher>();
|
|
|
|
status = EventFactory::registerEventPublisher<AnotherFakeEventPublisher>(pub);
|
|
|
|
EXPECT_TRUE(status.ok());
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
2014-12-15 02:03:41 +00:00
|
|
|
TEST_F(EventsTests, test_event_pub_types) {
|
|
|
|
auto pub = std::make_shared<FakeEventPublisher>();
|
|
|
|
EXPECT_EQ(pub->type(), "FakePublisher");
|
|
|
|
|
|
|
|
EventFactory::registerEventPublisher(pub);
|
|
|
|
auto pub2 = EventFactory::getEventPublisher("FakePublisher");
|
|
|
|
EXPECT_EQ(pub->type(), pub2->type());
|
|
|
|
}
|
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
TEST_F(EventsTests, test_create_event_pub) {
|
2014-12-14 11:43:31 +00:00
|
|
|
auto status = EventFactory::registerEventPublisher<BasicEventPublisher>();
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_TRUE(status.ok());
|
|
|
|
|
|
|
|
// Make sure only the first event type was recorded.
|
2014-10-03 15:14:36 +00:00
|
|
|
EXPECT_EQ(EventFactory::numEventPublishers(), 1);
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
TEST_F(EventsTests, test_create_subscription) {
|
2014-10-03 15:14:36 +00:00
|
|
|
EventFactory::registerEventPublisher<BasicEventPublisher>();
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
// 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.
|
|
|
|
auto subscription = Subscription::create();
|
2014-12-15 02:03:41 +00:00
|
|
|
auto status = EventFactory::addSubscription("FakePublisher", subscription);
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_FALSE(status.ok());
|
|
|
|
|
2014-10-04 00:50:25 +00:00
|
|
|
// In this case we can still add a blank subscription to an existing event
|
|
|
|
// type.
|
2014-12-14 11:43:31 +00:00
|
|
|
status = EventFactory::addSubscription("publisher", subscription);
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_TRUE(status.ok());
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
// Make sure the subscription is added.
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_EQ(EventFactory::numSubscriptions("publisher"), 1);
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
TEST_F(EventsTests, test_multiple_subscriptions) {
|
2014-09-18 04:20:30 +00:00
|
|
|
Status status;
|
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
EventFactory::registerEventPublisher<BasicEventPublisher>();
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
auto subscription = Subscription::create();
|
2014-12-14 11:43:31 +00:00
|
|
|
status = EventFactory::addSubscription("publisher", subscription);
|
|
|
|
status = EventFactory::addSubscription("publisher", subscription);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_EQ(EventFactory::numSubscriptions("publisher"), 2);
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
struct TestSubscriptionContext : public SubscriptionContext {
|
2014-09-18 04:20:30 +00:00
|
|
|
int smallest;
|
|
|
|
};
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
class TestEventPublisher
|
|
|
|
: public EventPublisher<TestSubscriptionContext, EventContext> {
|
2014-12-15 02:03:41 +00:00
|
|
|
DECLARE_PUBLISHER("TestPublisher");
|
2014-09-22 21:35:07 +00:00
|
|
|
public:
|
2014-12-08 10:22:59 +00:00
|
|
|
Status setUp() {
|
|
|
|
smallest_ever_ += 1;
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
void configure() {
|
2014-10-03 15:26:41 +00:00
|
|
|
int smallest_subscription = smallest_ever_;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
configure_run = true;
|
2014-10-03 15:26:41 +00:00
|
|
|
for (const auto& subscription : subscriptions_) {
|
|
|
|
auto subscription_context = getSubscriptionContext(subscription->context);
|
|
|
|
if (smallest_subscription > subscription_context->smallest) {
|
|
|
|
smallest_subscription = subscription_context->smallest;
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
smallest_ever_ = smallest_subscription;
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
void tearDown() { smallest_ever_ += 1; }
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
TestEventPublisher() : EventPublisher() {
|
2014-09-18 04:20:30 +00:00
|
|
|
smallest_ever_ = 0;
|
|
|
|
configure_run = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Custom methods do not make sense, but for testing it exists.
|
2014-09-22 21:35:07 +00:00
|
|
|
int getTestValue() { return smallest_ever_; }
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
public:
|
2014-09-18 04:20:30 +00:00
|
|
|
bool configure_run;
|
|
|
|
|
2014-09-22 21:35:07 +00:00
|
|
|
private:
|
2014-09-18 04:20:30 +00:00
|
|
|
int smallest_ever_;
|
|
|
|
};
|
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
TEST_F(EventsTests, test_create_custom_event_pub) {
|
2014-12-14 11:43:31 +00:00
|
|
|
auto status = EventFactory::registerEventPublisher<BasicEventPublisher>();
|
|
|
|
auto pub = std::make_shared<TestEventPublisher>();
|
|
|
|
status = EventFactory::registerEventPublisher(pub);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
// These event types have unique event type IDs
|
|
|
|
EXPECT_TRUE(status.ok());
|
2014-10-03 15:14:36 +00:00
|
|
|
EXPECT_EQ(EventFactory::numEventPublishers(), 2);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
// Make sure the setUp function was called.
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_EQ(pub->getTestValue(), 1);
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
TEST_F(EventsTests, test_custom_subscription) {
|
2014-09-18 04:20:30 +00:00
|
|
|
// Step 1, register event type
|
2014-12-14 11:43:31 +00:00
|
|
|
auto pub = std::make_shared<TestEventPublisher>();
|
|
|
|
auto status = EventFactory::registerEventPublisher(pub);
|
2014-09-22 21:35:07 +00:00
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
// Step 2, create and configure a subscription context
|
2014-12-14 11:43:31 +00:00
|
|
|
auto sc = std::make_shared<TestSubscriptionContext>();
|
|
|
|
sc->smallest = -1;
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
// Step 3, add the subscription to the event type
|
2014-12-15 02:03:41 +00:00
|
|
|
status = EventFactory::addSubscription("TestPublisher", sc);
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_TRUE(status.ok());
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_EQ(pub->numSubscriptions(), 1);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
// The event type must run configure for each added subscription.
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_TRUE(pub->configure_run);
|
|
|
|
EXPECT_EQ(pub->getTestValue(), -1);
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(EventsTests, test_tear_down) {
|
2014-12-14 11:43:31 +00:00
|
|
|
auto pub = std::make_shared<TestEventPublisher>();
|
|
|
|
auto status = EventFactory::registerEventPublisher(pub);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
// Make sure set up incremented the test value.
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_EQ(pub->getTestValue(), 1);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-12-15 02:03:41 +00:00
|
|
|
status = EventFactory::deregisterEventPublisher("TestPublisher");
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_TRUE(status.ok());
|
|
|
|
|
|
|
|
// Make sure tear down inremented the test value.
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_EQ(pub->getTestValue(), 2);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
// Once more, now deregistering all event types.
|
2014-12-14 11:43:31 +00:00
|
|
|
status = EventFactory::registerEventPublisher(pub);
|
|
|
|
EXPECT_EQ(pub->getTestValue(), 3);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:14:36 +00:00
|
|
|
status = EventFactory::deregisterEventPublishers();
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_TRUE(status.ok());
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
EXPECT_EQ(pub->getTestValue(), 4);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
|
|
|
// Make sure the factory state represented.
|
2014-10-03 15:14:36 +00:00
|
|
|
EXPECT_EQ(EventFactory::numEventPublishers(), 0);
|
2014-09-18 04:20:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int kBellHathTolled = 0;
|
|
|
|
|
2014-09-25 17:17:32 +00:00
|
|
|
Status TestTheeCallback(EventContextRef context, bool reserved) {
|
2014-09-18 04:20:30 +00:00
|
|
|
kBellHathTolled += 1;
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(EventsTests, test_fire_event) {
|
|
|
|
Status status;
|
|
|
|
|
2014-12-14 11:43:31 +00:00
|
|
|
auto pub = std::make_shared<BasicEventPublisher>();
|
|
|
|
status = EventFactory::registerEventPublisher(pub);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
auto subscription = Subscription::create();
|
|
|
|
subscription->callback = TestTheeCallback;
|
2014-12-14 11:43:31 +00:00
|
|
|
status = EventFactory::addSubscription("publisher", subscription);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-09-19 08:54:33 +00:00
|
|
|
// The event context creation would normally happen in the event type.
|
2014-12-14 11:43:31 +00:00
|
|
|
auto ec = pub->createEventContext();
|
|
|
|
pub->fire(ec, 0);
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_EQ(kBellHathTolled, 1);
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
auto second_subscription = Subscription::create();
|
2014-12-14 11:43:31 +00:00
|
|
|
status = EventFactory::addSubscription("publisher", second_subscription);
|
2014-09-18 04:20:30 +00:00
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
// Now there are two subscriptions (one sans callback).
|
2014-12-14 11:43:31 +00:00
|
|
|
pub->fire(ec, 0);
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_EQ(kBellHathTolled, 2);
|
|
|
|
|
2014-10-03 15:26:41 +00:00
|
|
|
// Now both subscriptions have callbacks.
|
|
|
|
second_subscription->callback = TestTheeCallback;
|
2014-12-14 11:43:31 +00:00
|
|
|
pub->fire(ec, 0);
|
2014-09-18 04:20:30 +00:00
|
|
|
EXPECT_EQ(kBellHathTolled, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
testing::InitGoogleTest(&argc, argv);
|
|
|
|
return RUN_ALL_TESTS();
|
|
|
|
}
|