From 25aee56af9de0028407d390048e5896241f75eb8 Mon Sep 17 00:00:00 2001 From: Teddy Reed Date: Fri, 3 Oct 2014 16:25:55 -0700 Subject: [PATCH 1/2] [events] Stabilize INotify event tests --- osquery/events/darwin/fsevents_tests.cpp | 1 - osquery/events/linux/inotify_tests.cpp | 78 +++++++++++++++--------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/osquery/events/darwin/fsevents_tests.cpp b/osquery/events/darwin/fsevents_tests.cpp index 99013fda..90598cc0 100644 --- a/osquery/events/darwin/fsevents_tests.cpp +++ b/osquery/events/darwin/fsevents_tests.cpp @@ -223,7 +223,6 @@ TEST_F(FSEventsTests, test_fsevents_event_action) { StartEventLoop(); TestFSEventsEventSubscriber::getInstance()->init(); - TestFSEventsEventSubscriber::getInstance()->callback_count_ = 0; SubscriptionAction(0, TestFSEventsEventSubscriber::EventCallback); CreateEvents(); diff --git a/osquery/events/linux/inotify_tests.cpp b/osquery/events/linux/inotify_tests.cpp index 97e5454e..a316eb64 100644 --- a/osquery/events/linux/inotify_tests.cpp +++ b/osquery/events/linux/inotify_tests.cpp @@ -12,14 +12,15 @@ namespace osquery { const std::string kRealTestPath = "/tmp/osquery-inotify-trigger"; +int kMaxEventLatency = 3000; class INotifyTests : public testing::Test { protected: virtual void TearDown() { EventFactory::deregisterEventPublishers(); } void StartEventLoop() { - auto event_pub = std::make_shared(); - EventFactory::registerEventPublisher(event_pub); + event_pub_ = std::make_shared(); + EventFactory::registerEventPublisher(event_pub_); FILE* fd = fopen(kRealTestPath.c_str(), "w"); fclose(fd); @@ -34,32 +35,31 @@ class INotifyTests : public testing::Test { EventFactory::addSubscription("INotifyEventPublisher", mc, ec); } + bool WaitForEvents(int max, int num_events = 0) { + int delay = 0; + while (delay <= max * 1000) { + if (num_events > 0 && event_pub_->numEvents() >= num_events) { + return true; + } else if (num_events == 0 && event_pub_->numEvents() > 0) { + return true; + } + delay += 50; + ::usleep(50); + } + return false; + } + void EndEventLoop() { EventFactory::end(); + event_pub_->tearDown(); temp_thread_.join(); EventFactory::end(false); } + std::shared_ptr event_pub_; boost::thread temp_thread_; }; -// Helper eager wait function. -bool waitForEvent(int max, int num_events = 0) { - int step = 50; - int delay = 0; - const auto& et = EventFactory::getEventPublisher("INotifyEventPublisher"); - while (delay <= max * 1000) { - if (num_events > 0 && et->numEvents() >= num_events) { - return true; - } else if (num_events == 0 && et->numEvents() > 0) { - return true; - } - delay += step; - ::usleep(step); - } - return false; -} - TEST_F(INotifyTests, test_register_event_pub) { auto status = EventFactory::registerEventPublisher(); EXPECT_TRUE(status.ok()); @@ -90,7 +90,8 @@ TEST_F(INotifyTests, test_inotify_add_subscription_fail) { mc->path = "/this/path/is/fake"; auto subscription = Subscription::create(mc); - auto status = EventFactory::addSubscription("INotifyEventPublisher", subscription); + auto status = EventFactory::addSubscription("INotifyEventPublisher", + subscription); EXPECT_FALSE(status.ok()); } @@ -102,14 +103,15 @@ TEST_F(INotifyTests, test_inotify_add_subscription_success) { mc->path = "/"; auto subscription = Subscription::create(mc); - auto status = EventFactory::addSubscription("INotifyEventPublisher", subscription); + auto status = EventFactory::addSubscription("INotifyEventPublisher", + subscription); EXPECT_TRUE(status.ok()); } TEST_F(INotifyTests, test_inotify_run) { // Assume event type is registered. - auto event_pub = std::make_shared(); - EventFactory::registerEventPublisher(event_pub); + event_pub_ = std::make_shared(); + EventFactory::registerEventPublisher(event_pub_); // Create a temporary file to watch, open writeable FILE* fd = fopen(kRealTestPath.c_str(), "w"); @@ -117,19 +119,20 @@ TEST_F(INotifyTests, test_inotify_run) { // Create a subscriptioning context auto mc = std::make_shared(); mc->path = kRealTestPath; - EventFactory::addSubscription("INotifyEventPublisher", Subscription::create(mc)); + EventFactory::addSubscription("INotifyEventPublisher", + Subscription::create(mc)); // Create an event loop thread (similar to main) boost::thread temp_thread(EventFactory::run, "INotifyEventPublisher"); - EXPECT_TRUE(event_pub->numEvents() == 0); + EXPECT_TRUE(event_pub_->numEvents() == 0); // Cause an inotify event by writing to the watched path. fputs("inotify", fd); fclose(fd); // Wait for the thread's run loop to select. - waitForEvent(2000); - EXPECT_TRUE(event_pub->numEvents() > 0); + WaitForEvents(kMaxEventLatency); + EXPECT_TRUE(event_pub_->numEvents() > 0); // Cause the thread to tear down. EventFactory::end(); @@ -157,9 +160,21 @@ class TestINotifyEventSubscriber : public EventSubscriber { // Normally would call Add here. actions_.push_back(ec->action); + callback_count_ += 1; return Status(0, "OK"); } + static void WaitForEvents(int max, int num_events = 1) { + int delay = 0; + while (delay < max * 1000) { + if (getInstance()->callback_count_ >= num_events) { + return; + } + ::usleep(50); + delay += 50; + } + } + public: int callback_count_; std::vector actions_; @@ -168,6 +183,7 @@ class TestINotifyEventSubscriber : public EventSubscriber { TEST_F(INotifyTests, test_inotify_fire_event) { // Assume event type is registered. StartEventLoop(); + TestINotifyEventSubscriber::getInstance()->init(); // Create a subscriptioning context, note the added Event to the symbol SubscriptionAction(0, TestINotifyEventSubscriber::EventSimpleCallback); @@ -175,7 +191,8 @@ TEST_F(INotifyTests, test_inotify_fire_event) { FILE* fd = fopen(kRealTestPath.c_str(), "w"); fputs("inotify", fd); fclose(fd); - waitForEvent(2000); + + TestINotifyEventSubscriber::WaitForEvents(kMaxEventLatency); // Make sure our expected event fired (aka subscription callback was called). EXPECT_TRUE(TestINotifyEventSubscriber::getInstance()->callback_count_ > 0); @@ -187,12 +204,15 @@ TEST_F(INotifyTests, test_inotify_fire_event) { TEST_F(INotifyTests, test_inotify_event_action) { // Assume event type is registered. StartEventLoop(); + TestINotifyEventSubscriber::getInstance()->init(); + SubscriptionAction(0, TestINotifyEventSubscriber::EventCallback); FILE* fd = fopen(kRealTestPath.c_str(), "w"); fputs("inotify", fd); fclose(fd); - waitForEvent(2000, 4); + + TestINotifyEventSubscriber::WaitForEvents(kMaxEventLatency, 4); // Make sure the inotify action was expected. EXPECT_EQ(TestINotifyEventSubscriber::getInstance()->actions_.size(), 4); From a36117670bca5b109986c7d4f5356bcdae54f69a Mon Sep 17 00:00:00 2001 From: Teddy Reed Date: Fri, 3 Oct 2014 17:02:00 -0700 Subject: [PATCH 2/2] Revert "disabling inotify_tests" --- osquery/events/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osquery/events/CMakeLists.txt b/osquery/events/CMakeLists.txt index 0749cf04..a0fdd337 100644 --- a/osquery/events/CMakeLists.txt +++ b/osquery/events/CMakeLists.txt @@ -22,6 +22,5 @@ ADD_OSQUERY_TEST(events_database_tests events_database_tests.cpp) if(APPLE) ADD_OSQUERY_TEST(fsevents_tests darwin/fsevents_tests.cpp) else() - # TODO https://github.com/facebook/osquery/issues/197 - # ADD_OSQUERY_TEST(inotify_tests linux/inotify_tests.cpp) + ADD_OSQUERY_TEST(inotify_tests linux/inotify_tests.cpp) endif()