Commit 616f02b2 authored by Dan Melnic's avatar Dan Melnic Committed by Facebook Github Bot

Skip the EventBase tests if the backend is not available

Summary: Skip the EventBase tests if the backend is not available

Reviewed By: yfeldblum

Differential Revision: D19002064

fbshipit-source-id: a995df02998c80de2f9076ea16a0281b6288d6b5
parent c4ce1953
...@@ -102,8 +102,17 @@ void testOverflow(bool overflow) { ...@@ -102,8 +102,17 @@ void testOverflow(bool overflow) {
static constexpr size_t kEventFdCount = 16; static constexpr size_t kEventFdCount = 16;
auto total = kNumEventFds * kEventFdCount; auto total = kNumEventFds * kEventFdCount;
folly::EventBase evb(std::make_unique<folly::IoUringBackend>( std::unique_ptr<folly::EventBaseBackendBase> backend;
kBackendCapacity, kBackendMaxSubmit));
try {
backend = std::make_unique<folly::IoUringBackend>(
kBackendCapacity, kBackendMaxSubmit);
} catch (const folly::IoUringBackend::NotAvailable&) {
}
SKIP_IF(!backend) << "Backend not available";
folly::EventBase evb(std::move(backend));
std::vector<std::unique_ptr<EventFD>> eventsVec; std::vector<std::unique_ptr<EventFD>> eventsVec;
eventsVec.reserve(kNumEventFds); eventsVec.reserve(kNumEventFds);
...@@ -128,26 +137,27 @@ TEST(IoUringBackend, Overflow) { ...@@ -128,26 +137,27 @@ TEST(IoUringBackend, Overflow) {
testOverflow(true); testOverflow(true);
} }
int main(int argc, char** argv) { namespace folly {
::testing::InitGoogleTest(&argc, argv); namespace test {
folly::init(&argc, &argv); static constexpr size_t kCapacity = 16 * 1024;
static constexpr size_t kMaxSubmit = 128;
bool avail = folly::IoUringBackend::isAvailable(); struct IoUringBackendProvider {
LOG(INFO) << "folly::IoUringBackend::isAvailable() returned " << avail; static std::unique_ptr<folly::EventBaseBackendBase> getBackend() {
if (!avail) { try {
LOG(INFO)
<< "Not running tests since IoUringBackend is not available on this kernel version";
return 0;
}
static constexpr size_t kCapacity = 16 * 1024;
static constexpr size_t kMaxSubmit = 128;
folly::test::EventBaseBackendProvider::GetBackendFunc func;
func = []() {
return std::make_unique<folly::IoUringBackend>(kCapacity, kMaxSubmit); return std::make_unique<folly::IoUringBackend>(kCapacity, kMaxSubmit);
}; } catch (const IoUringBackend::NotAvailable&) {
return nullptr;
folly::test::EventBaseBackendProvider::setGetBackendFunc(std::move(func)); }
}
};
return RUN_ALL_TESTS(); INSTANTIATE_TYPED_TEST_CASE_P(
} EventBaseTest,
EventBaseTest,
IoUringBackendProvider);
INSTANTIATE_TYPED_TEST_CASE_P(
EventBaseTest1,
EventBaseTest1,
IoUringBackendProvider);
} // namespace test
} // namespace folly
...@@ -18,15 +18,20 @@ ...@@ -18,15 +18,20 @@
#include <folly/io/async/test/EventBaseTestLib.h> #include <folly/io/async/test/EventBaseTestLib.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
int main(int argc, char** argv) { namespace folly {
::testing::InitGoogleTest(&argc, argv); namespace test {
folly::init(&argc, &argv); struct DefaultBackendProvider {
static std::unique_ptr<folly::EventBaseBackendBase> getBackend() {
folly::test::EventBaseBackendProvider::GetBackendFunc func = []() {
return folly::EventBase::getDefaultBackend(); return folly::EventBase::getDefaultBackend();
}; }
};
folly::test::EventBaseBackendProvider::setGetBackendFunc(std::move(func)); INSTANTIATE_TYPED_TEST_CASE_P(
EventBaseTest,
return RUN_ALL_TESTS(); EventBaseTest,
} DefaultBackendProvider);
INSTANTIATE_TYPED_TEST_CASE_P(
EventBaseTest1,
EventBaseTest1,
DefaultBackendProvider);
} // namespace test
} // namespace folly
...@@ -27,37 +27,16 @@ ...@@ -27,37 +27,16 @@
#include <folly/futures/Promise.h> #include <folly/futures/Promise.h>
#include <folly/io/async/test/EventBaseTestLibProvider.h>
#include <atomic> #include <atomic>
#include <future> #include <future>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <thread> #include <thread>
using std::atomic; #define FOLLY_SKIP_IF_NULLPTR_BACKEND(evb) \
using std::cerr; auto backend = TypeParam::getBackend(); \
using std::deque; SKIP_IF(!backend) << "Backend not available"; \
using std::endl; EventBase evb(std::move(backend))
using std::make_pair;
using std::pair;
using std::thread;
using std::unique_ptr;
using std::vector;
using std::chrono::duration_cast;
using std::chrono::microseconds;
using std::chrono::milliseconds;
using folly::AsyncTimeout;
using folly::Baton;
using folly::EventBase;
using folly::EventHandler;
using folly::Executor;
using folly::NetworkSocket;
using folly::RequestContext;
using folly::RequestContextScopeGuard;
using folly::SocketPair;
using folly::TimePoint;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Tests for read and write events // Tests for read and write events
...@@ -65,16 +44,9 @@ using folly::TimePoint; ...@@ -65,16 +44,9 @@ using folly::TimePoint;
namespace folly { namespace folly {
namespace test { namespace test {
class EventBaseTestBase : public ::testing::Test {
class BackendEventBase : public EventBase {
public: public:
BackendEventBase() EventBaseTestBase() {
: EventBase(folly::test::EventBaseBackendProvider::getBackend()) {}
};
class EventBaseTest : public ::testing::Test {
public:
EventBaseTest() {
// libevent 2.x uses a coarse monotonic timer by default on Linux. // libevent 2.x uses a coarse monotonic timer by default on Linux.
// This timer is imprecise enough to cause several of our tests to fail. // This timer is imprecise enough to cause several of our tests to fail.
// //
...@@ -88,11 +60,27 @@ class EventBaseTest : public ::testing::Test { ...@@ -88,11 +60,27 @@ class EventBaseTest : public ::testing::Test {
} }
}; };
template <typename T>
class EventBaseTest : public EventBaseTestBase {
public:
EventBaseTest() = default;
};
TYPED_TEST_CASE_P(EventBaseTest);
template <typename T>
class EventBaseTest1 : public EventBaseTestBase {
public:
EventBaseTest1() = default;
};
TYPED_TEST_CASE_P(EventBaseTest1);
enum { BUF_SIZE = 4096 }; enum { BUF_SIZE = 4096 };
FOLLY_ALWAYS_INLINE ssize_t writeToFD(int fd, size_t length) { FOLLY_ALWAYS_INLINE ssize_t writeToFD(int fd, size_t length) {
// write an arbitrary amount of data to the fd // write an arbitrary amount of data to the fd
auto bufv = vector<char>(length); auto bufv = std::vector<char>(length);
auto buf = bufv.data(); auto buf = bufv.data();
memset(buf, 'a', length); memset(buf, 'a', length);
ssize_t rc = write(fd, buf, length); ssize_t rc = write(fd, buf, length);
...@@ -119,7 +107,7 @@ FOLLY_ALWAYS_INLINE size_t writeUntilFull(int fd) { ...@@ -119,7 +107,7 @@ FOLLY_ALWAYS_INLINE size_t writeUntilFull(int fd) {
FOLLY_ALWAYS_INLINE ssize_t readFromFD(int fd, size_t length) { FOLLY_ALWAYS_INLINE ssize_t readFromFD(int fd, size_t length) {
// write an arbitrary amount of data to the fd // write an arbitrary amount of data to the fd
auto buf = vector<char>(length); auto buf = std::vector<char>(length);
return read(fd, buf.data(), length); return read(fd, buf.data(), length);
} }
...@@ -152,14 +140,14 @@ struct ScheduledEvent { ...@@ -152,14 +140,14 @@ struct ScheduledEvent {
ssize_t result; ssize_t result;
void perform(int fd) { void perform(int fd) {
if (events & EventHandler::READ) { if (events & folly::EventHandler::READ) {
if (length == 0) { if (length == 0) {
result = readUntilEmpty(fd); result = readUntilEmpty(fd);
} else { } else {
result = readFromFD(fd, length); result = readFromFD(fd, length);
} }
} }
if (events & EventHandler::WRITE) { if (events & folly::EventHandler::WRITE) {
if (length == 0) { if (length == 0) {
result = writeUntilFull(fd); result = writeUntilFull(fd);
} else { } else {
...@@ -177,10 +165,10 @@ scheduleEvents(EventBase* eventBase, int fd, ScheduledEvent* events) { ...@@ -177,10 +165,10 @@ scheduleEvents(EventBase* eventBase, int fd, ScheduledEvent* events) {
} }
} }
class TestHandler : public EventHandler { class TestHandler : public folly::EventHandler {
public: public:
TestHandler(EventBase* eventBase, int fd) TestHandler(folly::EventBase* eventBase, int fd)
: EventHandler(eventBase, NetworkSocket::fromFd(fd)), fd_(fd) {} : EventHandler(eventBase, folly::NetworkSocket::fromFd(fd)), fd_(fd) {}
void handlerReady(uint16_t events) noexcept override { void handlerReady(uint16_t events) noexcept override {
ssize_t bytesRead = 0; ssize_t bytesRead = 0;
...@@ -207,35 +195,22 @@ class TestHandler : public EventHandler { ...@@ -207,35 +195,22 @@ class TestHandler : public EventHandler {
bytesWritten(bytesWritten_) {} bytesWritten(bytesWritten_) {}
uint16_t events; uint16_t events;
TimePoint timestamp; folly::TimePoint timestamp;
ssize_t bytesRead; ssize_t bytesRead;
ssize_t bytesWritten; ssize_t bytesWritten;
}; };
deque<EventRecord> log; std::deque<EventRecord> log;
private: private:
int fd_; int fd_;
}; };
} // namespace test
} // namespace folly
using folly::test::BackendEventBase;
using folly::test::checkReadUntilEmpty;
using folly::test::EventBaseTest;
using folly::test::readFromFD;
using folly::test::readUntilEmpty;
using folly::test::ScheduledEvent;
using folly::test::TestHandler;
using folly::test::writeToFD;
using folly::test::writeUntilFull;
/** /**
* Test a READ event * Test a READ event
*/ */
TEST_F(EventBaseTest, ReadEvent) { TYPED_TEST_P(EventBaseTest, ReadEvent) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Register for read events // Register for read events
...@@ -263,12 +238,15 @@ TEST_F(EventBaseTest, ReadEvent) { ...@@ -263,12 +238,15 @@ TEST_F(EventBaseTest, ReadEvent) {
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, start,
handler.log[0].timestamp, handler.log[0].timestamp,
milliseconds(events[0].milliseconds), std::chrono::milliseconds(events[0].milliseconds),
milliseconds(90)); std::chrono::milliseconds(90));
ASSERT_EQ(handler.log[0].bytesRead, events[0].length); ASSERT_EQ(handler.log[0].bytesRead, events[0].length);
ASSERT_EQ(handler.log[0].bytesWritten, 0); ASSERT_EQ(handler.log[0].bytesWritten, 0);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, end, milliseconds(events[1].milliseconds), milliseconds(30)); start,
end,
std::chrono::milliseconds(events[1].milliseconds),
std::chrono::milliseconds(30));
// Make sure the second chunk of data is still waiting to be read. // Make sure the second chunk of data is still waiting to be read.
size_t bytesRemaining = readUntilEmpty(sp[0]); size_t bytesRemaining = readUntilEmpty(sp[0]);
...@@ -278,8 +256,8 @@ TEST_F(EventBaseTest, ReadEvent) { ...@@ -278,8 +256,8 @@ TEST_F(EventBaseTest, ReadEvent) {
/** /**
* Test (READ | PERSIST) * Test (READ | PERSIST)
*/ */
TEST_F(EventBaseTest, ReadPersist) { TYPED_TEST_P(EventBaseTest, ReadPersist) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Register for read events // Register for read events
...@@ -310,11 +288,14 @@ TEST_F(EventBaseTest, ReadPersist) { ...@@ -310,11 +288,14 @@ TEST_F(EventBaseTest, ReadPersist) {
for (int n = 0; n < 3; ++n) { for (int n = 0; n < 3; ++n) {
ASSERT_EQ(handler.log[n].events, EventHandler::READ); ASSERT_EQ(handler.log[n].events, EventHandler::READ);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[n].timestamp, milliseconds(events[n].milliseconds)); start,
handler.log[n].timestamp,
std::chrono::milliseconds(events[n].milliseconds));
ASSERT_EQ(handler.log[n].bytesRead, events[n].length); ASSERT_EQ(handler.log[n].bytesRead, events[n].length);
ASSERT_EQ(handler.log[n].bytesWritten, 0); ASSERT_EQ(handler.log[n].bytesWritten, 0);
} }
T_CHECK_TIMEOUT(start, end, milliseconds(events[3].milliseconds)); T_CHECK_TIMEOUT(
start, end, std::chrono::milliseconds(events[3].milliseconds));
// Make sure the data from the last write is still waiting to be read // Make sure the data from the last write is still waiting to be read
size_t bytesRemaining = readUntilEmpty(sp[0]); size_t bytesRemaining = readUntilEmpty(sp[0]);
...@@ -324,8 +305,8 @@ TEST_F(EventBaseTest, ReadPersist) { ...@@ -324,8 +305,8 @@ TEST_F(EventBaseTest, ReadPersist) {
/** /**
* Test registering for READ when the socket is immediately readable * Test registering for READ when the socket is immediately readable
*/ */
TEST_F(EventBaseTest, ReadImmediate) { TYPED_TEST_P(EventBaseTest, ReadImmediate) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Write some data to the socket so the other end will // Write some data to the socket so the other end will
...@@ -356,25 +337,28 @@ TEST_F(EventBaseTest, ReadImmediate) { ...@@ -356,25 +337,28 @@ TEST_F(EventBaseTest, ReadImmediate) {
// There should have been 1 event for immediate readability // There should have been 1 event for immediate readability
ASSERT_EQ(handler.log[0].events, EventHandler::READ); ASSERT_EQ(handler.log[0].events, EventHandler::READ);
T_CHECK_TIMEOUT(start, handler.log[0].timestamp, milliseconds(0)); T_CHECK_TIMEOUT(
start, handler.log[0].timestamp, std::chrono::milliseconds(0));
ASSERT_EQ(handler.log[0].bytesRead, dataLength); ASSERT_EQ(handler.log[0].bytesRead, dataLength);
ASSERT_EQ(handler.log[0].bytesWritten, 0); ASSERT_EQ(handler.log[0].bytesWritten, 0);
// There should be another event after the timeout wrote more data // There should be another event after the timeout wrote more data
ASSERT_EQ(handler.log[1].events, EventHandler::READ); ASSERT_EQ(handler.log[1].events, EventHandler::READ);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[1].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[1].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[1].bytesRead, events[0].length); ASSERT_EQ(handler.log[1].bytesRead, events[0].length);
ASSERT_EQ(handler.log[1].bytesWritten, 0); ASSERT_EQ(handler.log[1].bytesWritten, 0);
T_CHECK_TIMEOUT(start, end, milliseconds(20)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(20));
} }
/** /**
* Test a WRITE event * Test a WRITE event
*/ */
TEST_F(EventBaseTest, WriteEvent) { TYPED_TEST_P(EventBaseTest, WriteEvent) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Fill up the write buffer before starting // Fill up the write buffer before starting
...@@ -402,10 +386,13 @@ TEST_F(EventBaseTest, WriteEvent) { ...@@ -402,10 +386,13 @@ TEST_F(EventBaseTest, WriteEvent) {
ASSERT_EQ(handler.log.size(), 1); ASSERT_EQ(handler.log.size(), 1);
ASSERT_EQ(handler.log[0].events, EventHandler::WRITE); ASSERT_EQ(handler.log[0].events, EventHandler::WRITE);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[0].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[0].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[0].bytesRead, 0); ASSERT_EQ(handler.log[0].bytesRead, 0);
ASSERT_GT(handler.log[0].bytesWritten, 0); ASSERT_GT(handler.log[0].bytesWritten, 0);
T_CHECK_TIMEOUT(start, end, milliseconds(events[1].milliseconds)); T_CHECK_TIMEOUT(
start, end, std::chrono::milliseconds(events[1].milliseconds));
ASSERT_EQ(events[0].result, initialBytesWritten); ASSERT_EQ(events[0].result, initialBytesWritten);
ASSERT_EQ(events[1].result, handler.log[0].bytesWritten); ASSERT_EQ(events[1].result, handler.log[0].bytesWritten);
...@@ -414,8 +401,8 @@ TEST_F(EventBaseTest, WriteEvent) { ...@@ -414,8 +401,8 @@ TEST_F(EventBaseTest, WriteEvent) {
/** /**
* Test (WRITE | PERSIST) * Test (WRITE | PERSIST)
*/ */
TEST_F(EventBaseTest, WritePersist) { TYPED_TEST_P(EventBaseTest, WritePersist) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Fill up the write buffer before starting // Fill up the write buffer before starting
...@@ -450,19 +437,22 @@ TEST_F(EventBaseTest, WritePersist) { ...@@ -450,19 +437,22 @@ TEST_F(EventBaseTest, WritePersist) {
for (int n = 0; n < 3; ++n) { for (int n = 0; n < 3; ++n) {
ASSERT_EQ(handler.log[n].events, EventHandler::WRITE); ASSERT_EQ(handler.log[n].events, EventHandler::WRITE);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[n].timestamp, milliseconds(events[n].milliseconds)); start,
handler.log[n].timestamp,
std::chrono::milliseconds(events[n].milliseconds));
ASSERT_EQ(handler.log[n].bytesRead, 0); ASSERT_EQ(handler.log[n].bytesRead, 0);
ASSERT_GT(handler.log[n].bytesWritten, 0); ASSERT_GT(handler.log[n].bytesWritten, 0);
ASSERT_EQ(handler.log[n].bytesWritten, events[n + 1].result); ASSERT_EQ(handler.log[n].bytesWritten, events[n + 1].result);
} }
T_CHECK_TIMEOUT(start, end, milliseconds(events[3].milliseconds)); T_CHECK_TIMEOUT(
start, end, std::chrono::milliseconds(events[3].milliseconds));
} }
/** /**
* Test registering for WRITE when the socket is immediately writable * Test registering for WRITE when the socket is immediately writable
*/ */
TEST_F(EventBaseTest, WriteImmediate) { TYPED_TEST_P(EventBaseTest, WriteImmediate) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Register for write events // Register for write events
...@@ -491,25 +481,28 @@ TEST_F(EventBaseTest, WriteImmediate) { ...@@ -491,25 +481,28 @@ TEST_F(EventBaseTest, WriteImmediate) {
// Since the socket buffer was initially empty, // Since the socket buffer was initially empty,
// there should have been 1 event for immediate writability // there should have been 1 event for immediate writability
ASSERT_EQ(handler.log[0].events, EventHandler::WRITE); ASSERT_EQ(handler.log[0].events, EventHandler::WRITE);
T_CHECK_TIMEOUT(start, handler.log[0].timestamp, milliseconds(0)); T_CHECK_TIMEOUT(
start, handler.log[0].timestamp, std::chrono::milliseconds(0));
ASSERT_EQ(handler.log[0].bytesRead, 0); ASSERT_EQ(handler.log[0].bytesRead, 0);
ASSERT_GT(handler.log[0].bytesWritten, 0); ASSERT_GT(handler.log[0].bytesWritten, 0);
// There should be another event after the timeout wrote more data // There should be another event after the timeout wrote more data
ASSERT_EQ(handler.log[1].events, EventHandler::WRITE); ASSERT_EQ(handler.log[1].events, EventHandler::WRITE);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[1].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[1].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[1].bytesRead, 0); ASSERT_EQ(handler.log[1].bytesRead, 0);
ASSERT_GT(handler.log[1].bytesWritten, 0); ASSERT_GT(handler.log[1].bytesWritten, 0);
T_CHECK_TIMEOUT(start, end, milliseconds(unregisterTimeout)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(unregisterTimeout));
} }
/** /**
* Test (READ | WRITE) when the socket becomes readable first * Test (READ | WRITE) when the socket becomes readable first
*/ */
TEST_F(EventBaseTest, ReadWrite) { TYPED_TEST_P(EventBaseTest, ReadWrite) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Fill up the write buffer before starting // Fill up the write buffer before starting
...@@ -538,18 +531,21 @@ TEST_F(EventBaseTest, ReadWrite) { ...@@ -538,18 +531,21 @@ TEST_F(EventBaseTest, ReadWrite) {
ASSERT_EQ(handler.log.size(), 1); ASSERT_EQ(handler.log.size(), 1);
ASSERT_EQ(handler.log[0].events, EventHandler::READ); ASSERT_EQ(handler.log[0].events, EventHandler::READ);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[0].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[0].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[0].bytesRead, events[0].length); ASSERT_EQ(handler.log[0].bytesRead, events[0].length);
ASSERT_EQ(handler.log[0].bytesWritten, 0); ASSERT_EQ(handler.log[0].bytesWritten, 0);
ASSERT_EQ(events[1].result, sock0WriteLength); ASSERT_EQ(events[1].result, sock0WriteLength);
T_CHECK_TIMEOUT(start, end, milliseconds(events[1].milliseconds)); T_CHECK_TIMEOUT(
start, end, std::chrono::milliseconds(events[1].milliseconds));
} }
/** /**
* Test (READ | WRITE) when the socket becomes writable first * Test (READ | WRITE) when the socket becomes writable first
*/ */
TEST_F(EventBaseTest, WriteRead) { TYPED_TEST_P(EventBaseTest, WriteRead) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Fill up the write buffer before starting // Fill up the write buffer before starting
...@@ -579,12 +575,15 @@ TEST_F(EventBaseTest, WriteRead) { ...@@ -579,12 +575,15 @@ TEST_F(EventBaseTest, WriteRead) {
ASSERT_EQ(handler.log.size(), 1); ASSERT_EQ(handler.log.size(), 1);
ASSERT_EQ(handler.log[0].events, EventHandler::WRITE); ASSERT_EQ(handler.log[0].events, EventHandler::WRITE);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[0].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[0].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[0].bytesRead, 0); ASSERT_EQ(handler.log[0].bytesRead, 0);
ASSERT_GT(handler.log[0].bytesWritten, 0); ASSERT_GT(handler.log[0].bytesWritten, 0);
ASSERT_EQ(events[0].result, sock0WriteLength); ASSERT_EQ(events[0].result, sock0WriteLength);
ASSERT_EQ(events[1].result, sock1WriteLength); ASSERT_EQ(events[1].result, sock1WriteLength);
T_CHECK_TIMEOUT(start, end, milliseconds(events[1].milliseconds)); T_CHECK_TIMEOUT(
start, end, std::chrono::milliseconds(events[1].milliseconds));
// Make sure the written data is still waiting to be read. // Make sure the written data is still waiting to be read.
size_t bytesRemaining = readUntilEmpty(sp[0]); size_t bytesRemaining = readUntilEmpty(sp[0]);
...@@ -595,8 +594,8 @@ TEST_F(EventBaseTest, WriteRead) { ...@@ -595,8 +594,8 @@ TEST_F(EventBaseTest, WriteRead) {
* Test (READ | WRITE) when the socket becomes readable and writable * Test (READ | WRITE) when the socket becomes readable and writable
* at the same time. * at the same time.
*/ */
TEST_F(EventBaseTest, ReadWriteSimultaneous) { TYPED_TEST_P(EventBaseTest, ReadWriteSimultaneous) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Fill up the write buffer before starting // Fill up the write buffer before starting
...@@ -629,15 +628,18 @@ TEST_F(EventBaseTest, ReadWriteSimultaneous) { ...@@ -629,15 +628,18 @@ TEST_F(EventBaseTest, ReadWriteSimultaneous) {
ASSERT_GT(handler.log[0].bytesWritten, 0); ASSERT_GT(handler.log[0].bytesWritten, 0);
} }
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[0].timestamp, milliseconds(events[0].milliseconds)); start,
T_CHECK_TIMEOUT(start, end, milliseconds(events[0].milliseconds)); handler.log[0].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
T_CHECK_TIMEOUT(
start, end, std::chrono::milliseconds(events[0].milliseconds));
} }
/** /**
* Test (READ | WRITE | PERSIST) * Test (READ | WRITE | PERSIST)
*/ */
TEST_F(EventBaseTest, ReadWritePersist) { TYPED_TEST_P(EventBaseTest, ReadWritePersist) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Register for read and write events // Register for read and write events
...@@ -670,7 +672,8 @@ TEST_F(EventBaseTest, ReadWritePersist) { ...@@ -670,7 +672,8 @@ TEST_F(EventBaseTest, ReadWritePersist) {
// Since we didn't fill up the write buffer immediately, there should // Since we didn't fill up the write buffer immediately, there should
// be an immediate event for writability. // be an immediate event for writability.
ASSERT_EQ(handler.log[0].events, EventHandler::WRITE); ASSERT_EQ(handler.log[0].events, EventHandler::WRITE);
T_CHECK_TIMEOUT(start, handler.log[0].timestamp, milliseconds(0)); T_CHECK_TIMEOUT(
start, handler.log[0].timestamp, std::chrono::milliseconds(0));
ASSERT_EQ(handler.log[0].bytesRead, 0); ASSERT_EQ(handler.log[0].bytesRead, 0);
ASSERT_GT(handler.log[0].bytesWritten, 0); ASSERT_GT(handler.log[0].bytesWritten, 0);
...@@ -678,7 +681,9 @@ TEST_F(EventBaseTest, ReadWritePersist) { ...@@ -678,7 +681,9 @@ TEST_F(EventBaseTest, ReadWritePersist) {
for (int n = 1; n < 6; ++n) { for (int n = 1; n < 6; ++n) {
ScheduledEvent* event = &events[n - 1]; ScheduledEvent* event = &events[n - 1];
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[n].timestamp, milliseconds(event->milliseconds)); start,
handler.log[n].timestamp,
std::chrono::milliseconds(event->milliseconds));
if (event->events == EventHandler::READ) { if (event->events == EventHandler::READ) {
ASSERT_EQ(handler.log[n].events, EventHandler::WRITE); ASSERT_EQ(handler.log[n].events, EventHandler::WRITE);
ASSERT_EQ(handler.log[n].bytesRead, 0); ASSERT_EQ(handler.log[n].bytesRead, 0);
...@@ -719,8 +724,8 @@ class PartialReadHandler : public TestHandler { ...@@ -719,8 +724,8 @@ class PartialReadHandler : public TestHandler {
* When PERSIST is used, make sure the handler gets notified again the next * When PERSIST is used, make sure the handler gets notified again the next
* time around the loop. * time around the loop.
*/ */
TEST_F(EventBaseTest, ReadPartial) { TYPED_TEST_P(EventBaseTest, ReadPartial) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Register for read events // Register for read events
...@@ -750,14 +755,18 @@ TEST_F(EventBaseTest, ReadPartial) { ...@@ -750,14 +755,18 @@ TEST_F(EventBaseTest, ReadPartial) {
for (int n = 0; n < 3; ++n) { for (int n = 0; n < 3; ++n) {
ASSERT_EQ(handler.log[n].events, EventHandler::READ); ASSERT_EQ(handler.log[n].events, EventHandler::READ);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[n].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[n].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[n].bytesRead, readLength); ASSERT_EQ(handler.log[n].bytesRead, readLength);
ASSERT_EQ(handler.log[n].bytesWritten, 0); ASSERT_EQ(handler.log[n].bytesWritten, 0);
} }
// The last read only has readLength/2 bytes // The last read only has readLength/2 bytes
ASSERT_EQ(handler.log[3].events, EventHandler::READ); ASSERT_EQ(handler.log[3].events, EventHandler::READ);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[3].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[3].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[3].bytesRead, readLength / 2); ASSERT_EQ(handler.log[3].bytesRead, readLength / 2);
ASSERT_EQ(handler.log[3].bytesWritten, 0); ASSERT_EQ(handler.log[3].bytesWritten, 0);
} }
...@@ -785,8 +794,8 @@ class PartialWriteHandler : public TestHandler { ...@@ -785,8 +794,8 @@ class PartialWriteHandler : public TestHandler {
* becomes writable. When PERSIST is used, make sure the handler gets * becomes writable. When PERSIST is used, make sure the handler gets
* notified again the next time around the loop. * notified again the next time around the loop.
*/ */
TEST_F(EventBaseTest, WritePartial) { TYPED_TEST_P(EventBaseTest, WritePartial) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Fill up the write buffer before starting // Fill up the write buffer before starting
...@@ -822,7 +831,9 @@ TEST_F(EventBaseTest, WritePartial) { ...@@ -822,7 +831,9 @@ TEST_F(EventBaseTest, WritePartial) {
for (int n = 0; n < numChecked; ++n) { for (int n = 0; n < numChecked; ++n) {
ASSERT_EQ(handler.log[n].events, EventHandler::WRITE); ASSERT_EQ(handler.log[n].events, EventHandler::WRITE);
T_CHECK_TIMEOUT( T_CHECK_TIMEOUT(
start, handler.log[n].timestamp, milliseconds(events[0].milliseconds)); start,
handler.log[n].timestamp,
std::chrono::milliseconds(events[0].milliseconds));
ASSERT_EQ(handler.log[n].bytesRead, 0); ASSERT_EQ(handler.log[n].bytesRead, 0);
ASSERT_EQ(handler.log[n].bytesWritten, writeLength); ASSERT_EQ(handler.log[n].bytesWritten, writeLength);
} }
...@@ -831,7 +842,7 @@ TEST_F(EventBaseTest, WritePartial) { ...@@ -831,7 +842,7 @@ TEST_F(EventBaseTest, WritePartial) {
/** /**
* Test destroying a registered EventHandler * Test destroying a registered EventHandler
*/ */
TEST_F(EventBaseTest, DestroyHandler) { TYPED_TEST_P(EventBaseTest, DestroyHandler) {
class DestroyHandler : public AsyncTimeout { class DestroyHandler : public AsyncTimeout {
public: public:
DestroyHandler(EventBase* eb, EventHandler* h) DestroyHandler(EventBase* eb, EventHandler* h)
...@@ -845,7 +856,7 @@ TEST_F(EventBaseTest, DestroyHandler) { ...@@ -845,7 +856,7 @@ TEST_F(EventBaseTest, DestroyHandler) {
EventHandler* handler_; EventHandler* handler_;
}; };
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
SocketPair sp; SocketPair sp;
// Fill up the write buffer before starting // Fill up the write buffer before starting
...@@ -871,7 +882,7 @@ TEST_F(EventBaseTest, DestroyHandler) { ...@@ -871,7 +882,7 @@ TEST_F(EventBaseTest, DestroyHandler) {
// Make sure the EventHandler was uninstalled properly when it was // Make sure the EventHandler was uninstalled properly when it was
// destroyed, and the EventBase loop exited // destroyed, and the EventBase loop exited
T_CHECK_TIMEOUT(start, end, milliseconds(25)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(25));
// Make sure that the handler wrote data to the socket // Make sure that the handler wrote data to the socket
// before it was destroyed // before it was destroyed
...@@ -883,8 +894,8 @@ TEST_F(EventBaseTest, DestroyHandler) { ...@@ -883,8 +894,8 @@ TEST_F(EventBaseTest, DestroyHandler) {
// Tests for timeout events // Tests for timeout events
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
TEST_F(EventBaseTest, RunAfterDelay) { TYPED_TEST_P(EventBaseTest, RunAfterDelay) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
TimePoint timestamp1(false); TimePoint timestamp1(false);
TimePoint timestamp2(false); TimePoint timestamp2(false);
...@@ -901,17 +912,17 @@ TEST_F(EventBaseTest, RunAfterDelay) { ...@@ -901,17 +912,17 @@ TEST_F(EventBaseTest, RunAfterDelay) {
eb.loop(); eb.loop();
TimePoint end; TimePoint end;
T_CHECK_TIMEOUT(start, timestamp1, milliseconds(10)); T_CHECK_TIMEOUT(start, timestamp1, std::chrono::milliseconds(10));
T_CHECK_TIMEOUT(start, timestamp2, milliseconds(20)); T_CHECK_TIMEOUT(start, timestamp2, std::chrono::milliseconds(20));
T_CHECK_TIMEOUT(start, timestamp3, milliseconds(40)); T_CHECK_TIMEOUT(start, timestamp3, std::chrono::milliseconds(40));
T_CHECK_TIMEOUT(start, end, milliseconds(40)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(40));
} }
/** /**
* Test the behavior of tryRunAfterDelay() when some timeouts are * Test the behavior of tryRunAfterDelay() when some timeouts are
* still scheduled when the EventBase is destroyed. * still scheduled when the EventBase is destroyed.
*/ */
TEST_F(EventBaseTest, RunAfterDelayDestruction) { TYPED_TEST_P(EventBaseTest, RunAfterDelayDestruction) {
TimePoint timestamp1(false); TimePoint timestamp1(false);
TimePoint timestamp2(false); TimePoint timestamp2(false);
TimePoint timestamp3(false); TimePoint timestamp3(false);
...@@ -920,7 +931,7 @@ TEST_F(EventBaseTest, RunAfterDelayDestruction) { ...@@ -920,7 +931,7 @@ TEST_F(EventBaseTest, RunAfterDelayDestruction) {
TimePoint end(false); TimePoint end(false);
{ {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
start.reset(); start.reset();
// Run two normal timeouts // Run two normal timeouts
...@@ -938,9 +949,9 @@ TEST_F(EventBaseTest, RunAfterDelayDestruction) { ...@@ -938,9 +949,9 @@ TEST_F(EventBaseTest, RunAfterDelayDestruction) {
end.reset(); end.reset();
} }
T_CHECK_TIMEOUT(start, timestamp1, milliseconds(10)); T_CHECK_TIMEOUT(start, timestamp1, std::chrono::milliseconds(10));
T_CHECK_TIMEOUT(start, timestamp2, milliseconds(20)); T_CHECK_TIMEOUT(start, timestamp2, std::chrono::milliseconds(20));
T_CHECK_TIMEOUT(start, end, milliseconds(40)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(40));
ASSERT_TRUE(timestamp3.isUnset()); ASSERT_TRUE(timestamp3.isUnset());
ASSERT_TRUE(timestamp4.isUnset()); ASSERT_TRUE(timestamp4.isUnset());
...@@ -963,8 +974,8 @@ class TestTimeout : public AsyncTimeout { ...@@ -963,8 +974,8 @@ class TestTimeout : public AsyncTimeout {
}; };
} // namespace } // namespace
TEST_F(EventBaseTest, BasicTimeouts) { TYPED_TEST_P(EventBaseTest, BasicTimeouts) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
TestTimeout t1(&eb); TestTimeout t1(&eb);
TestTimeout t2(&eb); TestTimeout t2(&eb);
...@@ -977,16 +988,16 @@ TEST_F(EventBaseTest, BasicTimeouts) { ...@@ -977,16 +988,16 @@ TEST_F(EventBaseTest, BasicTimeouts) {
eb.loop(); eb.loop();
TimePoint end; TimePoint end;
T_CHECK_TIMEOUT(start, t1.timestamp, milliseconds(10)); T_CHECK_TIMEOUT(start, t1.timestamp, std::chrono::milliseconds(10));
T_CHECK_TIMEOUT(start, t2.timestamp, milliseconds(20)); T_CHECK_TIMEOUT(start, t2.timestamp, std::chrono::milliseconds(20));
T_CHECK_TIMEOUT(start, t3.timestamp, milliseconds(40)); T_CHECK_TIMEOUT(start, t3.timestamp, std::chrono::milliseconds(40));
T_CHECK_TIMEOUT(start, end, milliseconds(40)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(40));
} }
namespace { namespace {
class ReschedulingTimeout : public AsyncTimeout { class ReschedulingTimeout : public AsyncTimeout {
public: public:
ReschedulingTimeout(EventBase* evb, const vector<uint32_t>& timeouts) ReschedulingTimeout(EventBase* evb, const std::vector<uint32_t>& timeouts)
: AsyncTimeout(evb), timeouts_(timeouts), iterator_(timeouts_.begin()) {} : AsyncTimeout(evb), timeouts_(timeouts), iterator_(timeouts_.begin()) {}
void start() { void start() {
...@@ -1006,21 +1017,21 @@ class ReschedulingTimeout : public AsyncTimeout { ...@@ -1006,21 +1017,21 @@ class ReschedulingTimeout : public AsyncTimeout {
} }
} }
vector<TimePoint> timestamps; std::vector<TimePoint> timestamps;
private: private:
vector<uint32_t> timeouts_; std::vector<uint32_t> timeouts_;
vector<uint32_t>::const_iterator iterator_; std::vector<uint32_t>::const_iterator iterator_;
}; };
} // namespace } // namespace
/** /**
* Test rescheduling the same timeout multiple times * Test rescheduling the same timeout multiple times
*/ */
TEST_F(EventBaseTest, ReuseTimeout) { TYPED_TEST_P(EventBaseTest, ReuseTimeout) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
vector<uint32_t> timeouts; std::vector<uint32_t> timeouts;
timeouts.push_back(10); timeouts.push_back(10);
timeouts.push_back(30); timeouts.push_back(30);
timeouts.push_back(15); timeouts.push_back(15);
...@@ -1034,22 +1045,23 @@ TEST_F(EventBaseTest, ReuseTimeout) { ...@@ -1034,22 +1045,23 @@ TEST_F(EventBaseTest, ReuseTimeout) {
// Use a higher tolerance than usual. We're waiting on 3 timeouts // Use a higher tolerance than usual. We're waiting on 3 timeouts
// consecutively. In general, each timeout may go over by a few // consecutively. In general, each timeout may go over by a few
// milliseconds, and we're tripling this error by witing on 3 timeouts. // milliseconds, and we're tripling this error by witing on 3 timeouts.
milliseconds tolerance{6}; std::chrono::milliseconds tolerance{6};
ASSERT_EQ(timeouts.size(), t.timestamps.size()); ASSERT_EQ(timeouts.size(), t.timestamps.size());
uint32_t total = 0; uint32_t total = 0;
for (size_t n = 0; n < timeouts.size(); ++n) { for (size_t n = 0; n < timeouts.size(); ++n) {
total += timeouts[n]; total += timeouts[n];
T_CHECK_TIMEOUT(start, t.timestamps[n], milliseconds(total), tolerance); T_CHECK_TIMEOUT(
start, t.timestamps[n], std::chrono::milliseconds(total), tolerance);
} }
T_CHECK_TIMEOUT(start, end, milliseconds(total), tolerance); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(total), tolerance);
} }
/** /**
* Test rescheduling a timeout before it has fired * Test rescheduling a timeout before it has fired
*/ */
TEST_F(EventBaseTest, RescheduleTimeout) { TYPED_TEST_P(EventBaseTest, RescheduleTimeout) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
TestTimeout t1(&eb); TestTimeout t1(&eb);
TestTimeout t2(&eb); TestTimeout t2(&eb);
...@@ -1071,19 +1083,19 @@ TEST_F(EventBaseTest, RescheduleTimeout) { ...@@ -1071,19 +1083,19 @@ TEST_F(EventBaseTest, RescheduleTimeout) {
eb.loop(); eb.loop();
TimePoint end; TimePoint end;
T_CHECK_TIMEOUT(start, t1.timestamp, milliseconds(15)); T_CHECK_TIMEOUT(start, t1.timestamp, std::chrono::milliseconds(15));
T_CHECK_TIMEOUT(start, t2.timestamp, milliseconds(20)); T_CHECK_TIMEOUT(start, t2.timestamp, std::chrono::milliseconds(20));
T_CHECK_TIMEOUT(start, t3.timestamp, milliseconds(50)); T_CHECK_TIMEOUT(start, t3.timestamp, std::chrono::milliseconds(50));
T_CHECK_TIMEOUT(start, end, milliseconds(50)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(50));
} }
/** /**
* Test cancelling a timeout * Test cancelling a timeout
*/ */
TEST_F(EventBaseTest, CancelTimeout) { TYPED_TEST_P(EventBaseTest, CancelTimeout) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
vector<uint32_t> timeouts; std::vector<uint32_t> timeouts;
timeouts.push_back(10); timeouts.push_back(10);
timeouts.push_back(30); timeouts.push_back(30);
timeouts.push_back(25); timeouts.push_back(25);
...@@ -1097,15 +1109,15 @@ TEST_F(EventBaseTest, CancelTimeout) { ...@@ -1097,15 +1109,15 @@ TEST_F(EventBaseTest, CancelTimeout) {
TimePoint end; TimePoint end;
ASSERT_EQ(t.timestamps.size(), 2); ASSERT_EQ(t.timestamps.size(), 2);
T_CHECK_TIMEOUT(start, t.timestamps[0], milliseconds(10)); T_CHECK_TIMEOUT(start, t.timestamps[0], std::chrono::milliseconds(10));
T_CHECK_TIMEOUT(start, t.timestamps[1], milliseconds(40)); T_CHECK_TIMEOUT(start, t.timestamps[1], std::chrono::milliseconds(40));
T_CHECK_TIMEOUT(start, end, milliseconds(50)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(50));
} }
/** /**
* Test destroying a scheduled timeout object * Test destroying a scheduled timeout object
*/ */
TEST_F(EventBaseTest, DestroyTimeout) { TYPED_TEST_P(EventBaseTest, DestroyTimeout) {
class DestroyTimeout : public AsyncTimeout { class DestroyTimeout : public AsyncTimeout {
public: public:
DestroyTimeout(EventBase* eb, AsyncTimeout* t) DestroyTimeout(EventBase* eb, AsyncTimeout* t)
...@@ -1119,7 +1131,7 @@ TEST_F(EventBaseTest, DestroyTimeout) { ...@@ -1119,7 +1131,7 @@ TEST_F(EventBaseTest, DestroyTimeout) {
AsyncTimeout* timeout_; AsyncTimeout* timeout_;
}; };
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
TestTimeout* t1 = new TestTimeout(&eb); TestTimeout* t1 = new TestTimeout(&eb);
TimePoint start; TimePoint start;
...@@ -1131,14 +1143,14 @@ TEST_F(EventBaseTest, DestroyTimeout) { ...@@ -1131,14 +1143,14 @@ TEST_F(EventBaseTest, DestroyTimeout) {
eb.loop(); eb.loop();
TimePoint end; TimePoint end;
T_CHECK_TIMEOUT(start, end, milliseconds(10)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(10));
} }
/** /**
* Test the scheduled executor impl * Test the scheduled executor impl
*/ */
TEST_F(EventBaseTest, ScheduledFn) { TYPED_TEST_P(EventBaseTest, ScheduledFn) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
TimePoint timestamp1(false); TimePoint timestamp1(false);
TimePoint timestamp2(false); TimePoint timestamp2(false);
...@@ -1147,21 +1159,21 @@ TEST_F(EventBaseTest, ScheduledFn) { ...@@ -1147,21 +1159,21 @@ TEST_F(EventBaseTest, ScheduledFn) {
auto fn2 = std::bind(&TimePoint::reset, &timestamp2); auto fn2 = std::bind(&TimePoint::reset, &timestamp2);
auto fn3 = std::bind(&TimePoint::reset, &timestamp3); auto fn3 = std::bind(&TimePoint::reset, &timestamp3);
TimePoint start; TimePoint start;
eb.schedule(std::move(fn1), milliseconds(9)); eb.schedule(std::move(fn1), std::chrono::milliseconds(9));
eb.schedule(std::move(fn2), milliseconds(19)); eb.schedule(std::move(fn2), std::chrono::milliseconds(19));
eb.schedule(std::move(fn3), milliseconds(39)); eb.schedule(std::move(fn3), std::chrono::milliseconds(39));
eb.loop(); eb.loop();
TimePoint end; TimePoint end;
T_CHECK_TIMEOUT(start, timestamp1, milliseconds(9)); T_CHECK_TIMEOUT(start, timestamp1, std::chrono::milliseconds(9));
T_CHECK_TIMEOUT(start, timestamp2, milliseconds(19)); T_CHECK_TIMEOUT(start, timestamp2, std::chrono::milliseconds(19));
T_CHECK_TIMEOUT(start, timestamp3, milliseconds(39)); T_CHECK_TIMEOUT(start, timestamp3, std::chrono::milliseconds(39));
T_CHECK_TIMEOUT(start, end, milliseconds(39)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(39));
} }
TEST_F(EventBaseTest, ScheduledFnAt) { TYPED_TEST_P(EventBaseTest, ScheduledFnAt) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
TimePoint timestamp0(false); TimePoint timestamp0(false);
TimePoint timestamp1(false); TimePoint timestamp1(false);
...@@ -1172,10 +1184,10 @@ TEST_F(EventBaseTest, ScheduledFnAt) { ...@@ -1172,10 +1184,10 @@ TEST_F(EventBaseTest, ScheduledFnAt) {
auto fn2 = std::bind(&TimePoint::reset, &timestamp2); auto fn2 = std::bind(&TimePoint::reset, &timestamp2);
auto fn3 = std::bind(&TimePoint::reset, &timestamp3); auto fn3 = std::bind(&TimePoint::reset, &timestamp3);
TimePoint start; TimePoint start;
eb.scheduleAt(fn0, eb.now() - milliseconds(5)); eb.scheduleAt(fn0, eb.now() - std::chrono::milliseconds(5));
eb.scheduleAt(fn1, eb.now() + milliseconds(9)); eb.scheduleAt(fn1, eb.now() + std::chrono::milliseconds(9));
eb.scheduleAt(fn2, eb.now() + milliseconds(19)); eb.scheduleAt(fn2, eb.now() + std::chrono::milliseconds(19));
eb.scheduleAt(fn3, eb.now() + milliseconds(39)); eb.scheduleAt(fn3, eb.now() + std::chrono::milliseconds(39));
TimePoint loopStart; TimePoint loopStart;
eb.loop(); eb.loop();
...@@ -1186,10 +1198,10 @@ TEST_F(EventBaseTest, ScheduledFnAt) { ...@@ -1186,10 +1198,10 @@ TEST_F(EventBaseTest, ScheduledFnAt) {
// interval. // interval.
T_CHECK_TIMEOUT(start, timestamp0, eb.timer().getTickInterval()); T_CHECK_TIMEOUT(start, timestamp0, eb.timer().getTickInterval());
T_CHECK_TIMEOUT(start, timestamp1, milliseconds(9)); T_CHECK_TIMEOUT(start, timestamp1, std::chrono::milliseconds(9));
T_CHECK_TIMEOUT(start, timestamp2, milliseconds(19)); T_CHECK_TIMEOUT(start, timestamp2, std::chrono::milliseconds(19));
T_CHECK_TIMEOUT(start, timestamp3, milliseconds(39)); T_CHECK_TIMEOUT(start, timestamp3, std::chrono::milliseconds(39));
T_CHECK_TIMEOUT(start, end, milliseconds(39)); T_CHECK_TIMEOUT(start, end, std::chrono::milliseconds(39));
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
...@@ -1199,11 +1211,16 @@ TEST_F(EventBaseTest, ScheduledFnAt) { ...@@ -1199,11 +1211,16 @@ TEST_F(EventBaseTest, ScheduledFnAt) {
namespace { namespace {
struct RunInThreadData { struct RunInThreadData {
RunInThreadData(int numThreads, int opsPerThread_) RunInThreadData(
: opsPerThread(opsPerThread_), opsToGo(numThreads * opsPerThread) {} std::unique_ptr<folly::EventBaseBackendBase>&& backend,
int numThreads,
int opsPerThread_)
: evb(std::move(backend)),
opsPerThread(opsPerThread_),
opsToGo(numThreads * opsPerThread) {}
BackendEventBase evb; EventBase evb;
deque<pair<int, int>> values; std::deque<std::pair<int, int>> values;
int opsPerThread; int opsPerThread;
int opsToGo; int opsToGo;
...@@ -1218,7 +1235,7 @@ struct RunInThreadArg { ...@@ -1218,7 +1235,7 @@ struct RunInThreadArg {
int value; int value;
}; };
void runInThreadTestFunc(RunInThreadArg* arg) { static inline void runInThreadTestFunc(RunInThreadArg* arg) {
arg->data->values.emplace_back(arg->thread, arg->value); arg->data->values.emplace_back(arg->thread, arg->value);
RunInThreadData* data = arg->data; RunInThreadData* data = arg->data;
delete arg; delete arg;
...@@ -1231,12 +1248,14 @@ void runInThreadTestFunc(RunInThreadArg* arg) { ...@@ -1231,12 +1248,14 @@ void runInThreadTestFunc(RunInThreadArg* arg) {
} // namespace } // namespace
TEST_F(EventBaseTest, RunInThread) { TYPED_TEST_P(EventBaseTest, RunInThread) {
constexpr uint32_t numThreads = 50; constexpr uint32_t numThreads = 50;
constexpr uint32_t opsPerThread = 100; constexpr uint32_t opsPerThread = 100;
RunInThreadData data(numThreads, opsPerThread); auto backend = TypeParam::getBackend();
SKIP_IF(!backend) << "Backend not available";
RunInThreadData data(std::move(backend), numThreads, opsPerThread);
deque<std::thread> threads; std::deque<std::thread> threads;
SCOPE_EXIT { SCOPE_EXIT {
// Wait on all of the threads. // Wait on all of the threads.
for (auto& thread : threads) { for (auto& thread : threads) {
...@@ -1271,8 +1290,8 @@ TEST_F(EventBaseTest, RunInThread) { ...@@ -1271,8 +1290,8 @@ TEST_F(EventBaseTest, RunInThread) {
// Assert that it happens in under a second. (This is still tons of extra // Assert that it happens in under a second. (This is still tons of extra
// padding.) // padding.)
auto timeTaken = auto timeTaken = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::duration_cast<milliseconds>(end.getTime() - start.getTime()); end.getTime() - start.getTime());
ASSERT_LT(timeTaken.count(), 1000); ASSERT_LT(timeTaken.count(), 1000);
VLOG(11) << "Time taken: " << timeTaken.count(); VLOG(11) << "Time taken: " << timeTaken.count();
...@@ -1281,7 +1300,7 @@ TEST_F(EventBaseTest, RunInThread) { ...@@ -1281,7 +1300,7 @@ TEST_F(EventBaseTest, RunInThread) {
for (uint32_t n = 0; n < numThreads; ++n) { for (uint32_t n = 0; n < numThreads; ++n) {
expectedValues[n] = 0; expectedValues[n] = 0;
} }
for (deque<pair<int, int>>::const_iterator it = data.values.begin(); for (std::deque<std::pair<int, int>>::const_iterator it = data.values.begin();
it != data.values.end(); it != data.values.end();
++it) { ++it) {
int threadID = it->first; int threadID = it->first;
...@@ -1297,19 +1316,23 @@ TEST_F(EventBaseTest, RunInThread) { ...@@ -1297,19 +1316,23 @@ TEST_F(EventBaseTest, RunInThread) {
// This test simulates some calls, and verifies that the waiting happens by // This test simulates some calls, and verifies that the waiting happens by
// triggering what otherwise would be race conditions, and trying to detect // triggering what otherwise would be race conditions, and trying to detect
// whether any of the race conditions happened. // whether any of the race conditions happened.
TEST_F(EventBaseTest, RunInEventBaseThreadAndWait) { TYPED_TEST_P(EventBaseTest, RunInEventBaseThreadAndWait) {
const size_t c = 256; const size_t c = 256;
vector<unique_ptr<atomic<size_t>>> atoms(c); std::vector<std::unique_ptr<std::atomic<size_t>>> atoms(c);
std::vector<std::unique_ptr<folly::EventBaseBackendBase>> backends(c);
for (size_t i = 0; i < c; ++i) { for (size_t i = 0; i < c; ++i) {
auto& atom = atoms.at(i); auto& atom = atoms.at(i);
atom = std::make_unique<atomic<size_t>>(0); atom = std::make_unique<std::atomic<size_t>>(0);
auto backend = TypeParam::getBackend();
SKIP_IF(!backend) << i << " : Backend not available";
backends[i] = std::move(backend);
} }
vector<thread> threads; std::vector<std::thread> threads;
for (size_t i = 0; i < c; ++i) { for (size_t i = 0; i < c; ++i) {
threads.emplace_back([&atoms, i] { threads.emplace_back([&atoms, &backends, i] {
BackendEventBase eb; EventBase eb(std::move(backends[i]));
auto& atom = *atoms.at(i); auto& atom = *atoms.at(i);
auto ebth = thread([&] { eb.loopForever(); }); auto ebth = std::thread([&] { eb.loopForever(); });
eb.waitUntilRunning(); eb.waitUntilRunning();
eb.runInEventBaseThreadAndWait([&] { eb.runInEventBaseThreadAndWait([&] {
size_t x = 0; size_t x = 0;
...@@ -1334,9 +1357,9 @@ TEST_F(EventBaseTest, RunInEventBaseThreadAndWait) { ...@@ -1334,9 +1357,9 @@ TEST_F(EventBaseTest, RunInEventBaseThreadAndWait) {
EXPECT_EQ(c, sum); EXPECT_EQ(c, sum);
} }
TEST_F(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitCross) { TYPED_TEST_P(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitCross) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
thread th(&EventBase::loopForever, &eb); std::thread th(&EventBase::loopForever, &eb);
SCOPE_EXIT { SCOPE_EXIT {
eb.terminateLoopSoon(); eb.terminateLoopSoon();
th.join(); th.join();
...@@ -1346,9 +1369,9 @@ TEST_F(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitCross) { ...@@ -1346,9 +1369,9 @@ TEST_F(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitCross) {
EXPECT_TRUE(mutated); EXPECT_TRUE(mutated);
} }
TEST_F(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitWithin) { TYPED_TEST_P(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitWithin) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
thread th(&EventBase::loopForever, &eb); std::thread th(&EventBase::loopForever, &eb);
SCOPE_EXIT { SCOPE_EXIT {
eb.terminateLoopSoon(); eb.terminateLoopSoon();
th.join(); th.join();
...@@ -1360,8 +1383,8 @@ TEST_F(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitWithin) { ...@@ -1360,8 +1383,8 @@ TEST_F(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadAndWaitWithin) {
}); });
} }
TEST_F(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadNotLooping) { TYPED_TEST_P(EventBaseTest, RunImmediatelyOrRunInEventBaseThreadNotLooping) {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
auto mutated = false; auto mutated = false;
eb.runImmediatelyOrRunInEventBaseThreadAndWait([&] { mutated = true; }); eb.runImmediatelyOrRunInEventBaseThreadAndWait([&] { mutated = true; });
EXPECT_TRUE(mutated); EXPECT_TRUE(mutated);
...@@ -1402,8 +1425,8 @@ class CountedLoopCallback : public EventBase::LoopCallback { ...@@ -1402,8 +1425,8 @@ class CountedLoopCallback : public EventBase::LoopCallback {
// Test that EventBase::loop() doesn't exit while there are // Test that EventBase::loop() doesn't exit while there are
// still LoopCallbacks remaining to be invoked. // still LoopCallbacks remaining to be invoked.
TEST_F(EventBaseTest, RepeatedRunInLoop) { TYPED_TEST_P(EventBaseTest, RepeatedRunInLoop) {
EventBase eventBase; FOLLY_SKIP_IF_NULLPTR_BACKEND(eventBase);
CountedLoopCallback c(&eventBase, 10); CountedLoopCallback c(&eventBase, 10);
eventBase.runInLoop(&c); eventBase.runInLoop(&c);
...@@ -1417,8 +1440,11 @@ TEST_F(EventBaseTest, RepeatedRunInLoop) { ...@@ -1417,8 +1440,11 @@ TEST_F(EventBaseTest, RepeatedRunInLoop) {
} }
// Test that EventBase::loop() works as expected without time measurements. // Test that EventBase::loop() works as expected without time measurements.
TEST_F(EventBaseTest, RunInLoopNoTimeMeasurement) { TYPED_TEST_P(EventBaseTest, RunInLoopNoTimeMeasurement) {
EventBase eventBase(false); auto backend = TypeParam::getBackend();
SKIP_IF(!backend) << "Backend not available";
EventBase eventBase(std::move(backend), false);
CountedLoopCallback c(&eventBase, 10); CountedLoopCallback c(&eventBase, 10);
eventBase.runInLoop(&c); eventBase.runInLoop(&c);
...@@ -1432,8 +1458,8 @@ TEST_F(EventBaseTest, RunInLoopNoTimeMeasurement) { ...@@ -1432,8 +1458,8 @@ TEST_F(EventBaseTest, RunInLoopNoTimeMeasurement) {
} }
// Test runInLoop() calls with terminateLoopSoon() // Test runInLoop() calls with terminateLoopSoon()
TEST_F(EventBaseTest, RunInLoopStopLoop) { TYPED_TEST_P(EventBaseTest, RunInLoopStopLoop) {
EventBase eventBase; FOLLY_SKIP_IF_NULLPTR_BACKEND(eventBase);
CountedLoopCallback c1(&eventBase, 20); CountedLoopCallback c1(&eventBase, 20);
CountedLoopCallback c2( CountedLoopCallback c2(
...@@ -1460,9 +1486,11 @@ TEST_F(EventBaseTest, RunInLoopStopLoop) { ...@@ -1460,9 +1486,11 @@ TEST_F(EventBaseTest, RunInLoopStopLoop) {
ASSERT_LE(c1.getCount(), 11); ASSERT_LE(c1.getCount(), 11);
} }
TEST_F(EventBaseTest, messageAvailableException) { TYPED_TEST_P(EventBaseTest, messageAvailableException) {
auto deadManWalking = [] { auto backend = TypeParam::getBackend();
EventBase eventBase; SKIP_IF(!backend) << "Backend not available";
auto deadManWalking = [backend = std::move(backend)]() mutable {
EventBase eventBase(std::move(backend));
std::thread t([&] { std::thread t([&] {
// Call this from another thread to force use of NotificationQueue in // Call this from another thread to force use of NotificationQueue in
// runInEventBaseThread // runInEventBaseThread
...@@ -1475,10 +1503,13 @@ TEST_F(EventBaseTest, messageAvailableException) { ...@@ -1475,10 +1503,13 @@ TEST_F(EventBaseTest, messageAvailableException) {
EXPECT_DEATH(deadManWalking(), ".*"); EXPECT_DEATH(deadManWalking(), ".*");
} }
TEST_F(EventBaseTest, TryRunningAfterTerminate) { TYPED_TEST_P(EventBaseTest, TryRunningAfterTerminate) {
auto backend = TypeParam::getBackend();
SKIP_IF(!backend) << "Backend not available";
bool ran = false; bool ran = false;
{ {
EventBase eventBase; EventBase eventBase(std::move(backend));
CountedLoopCallback c1( CountedLoopCallback c1(
&eventBase, 1, std::bind(&EventBase::terminateLoopSoon, &eventBase)); &eventBase, 1, std::bind(&EventBase::terminateLoopSoon, &eventBase));
eventBase.runInLoop(&c1); eventBase.runInLoop(&c1);
...@@ -1492,8 +1523,8 @@ TEST_F(EventBaseTest, TryRunningAfterTerminate) { ...@@ -1492,8 +1523,8 @@ TEST_F(EventBaseTest, TryRunningAfterTerminate) {
} }
// Test cancelling runInLoop() callbacks // Test cancelling runInLoop() callbacks
TEST_F(EventBaseTest, CancelRunInLoop) { TYPED_TEST_P(EventBaseTest, CancelRunInLoop) {
EventBase eventBase; FOLLY_SKIP_IF_NULLPTR_BACKEND(eventBase);
CountedLoopCallback c1(&eventBase, 20); CountedLoopCallback c1(&eventBase, 20);
CountedLoopCallback c2(&eventBase, 20); CountedLoopCallback c2(&eventBase, 20);
...@@ -1613,8 +1644,8 @@ class TerminateTestCallback : public EventBase::LoopCallback, ...@@ -1613,8 +1644,8 @@ class TerminateTestCallback : public EventBase::LoopCallback,
* EventBase::loop() incorrectly exited if there were no more fd handlers * EventBase::loop() incorrectly exited if there were no more fd handlers
* registered, but a loop callback installed a new fd handler. * registered, but a loop callback installed a new fd handler.
*/ */
TEST_F(EventBaseTest, LoopTermination) { TYPED_TEST_P(EventBaseTest, LoopTermination) {
EventBase eventBase; FOLLY_SKIP_IF_NULLPTR_BACKEND(eventBase);
// Open a pipe and close the write end, // Open a pipe and close the write end,
// so the read endpoint will be readable // so the read endpoint will be readable
...@@ -1641,9 +1672,9 @@ TEST_F(EventBaseTest, LoopTermination) { ...@@ -1641,9 +1672,9 @@ TEST_F(EventBaseTest, LoopTermination) {
close(pipeFds[0]); close(pipeFds[0]);
} }
TEST_F(EventBaseTest, CallbackOrderTest) { TYPED_TEST_P(EventBaseTest, CallbackOrderTest) {
size_t num = 0; size_t num = 0;
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
evb.runInEventBaseThread([&]() { evb.runInEventBaseThread([&]() {
std::thread t([&]() { std::thread t([&]() {
...@@ -1666,9 +1697,9 @@ TEST_F(EventBaseTest, CallbackOrderTest) { ...@@ -1666,9 +1697,9 @@ TEST_F(EventBaseTest, CallbackOrderTest) {
EXPECT_EQ(num, 2); EXPECT_EQ(num, 2);
} }
TEST_F(EventBaseTest, AlwaysEnqueueCallbackOrderTest) { TYPED_TEST_P(EventBaseTest, AlwaysEnqueueCallbackOrderTest) {
size_t num = 0; size_t num = 0;
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
evb.runInEventBaseThread([&]() { evb.runInEventBaseThread([&]() {
std::thread t([&]() { std::thread t([&]() {
...@@ -1741,8 +1772,8 @@ class IdleTimeTimeoutSeries : public AsyncTimeout { ...@@ -1741,8 +1772,8 @@ class IdleTimeTimeoutSeries : public AsyncTimeout {
* later timeout is far enough in the future that the idle time should have * later timeout is far enough in the future that the idle time should have
* caused the loop time to decay. * caused the loop time to decay.
*/ */
TEST_F(EventBaseTest, IdleTime) { TYPED_TEST_P(EventBaseTest, IdleTime) {
EventBase eventBase; FOLLY_SKIP_IF_NULLPTR_BACKEND(eventBase);
std::deque<std::size_t> timeouts0(4, 8080); std::deque<std::size_t> timeouts0(4, 8080);
timeouts0.push_front(8000); timeouts0.push_front(8000);
timeouts0.push_back(14000); timeouts0.push_back(14000);
...@@ -1756,12 +1787,12 @@ TEST_F(EventBaseTest, IdleTime) { ...@@ -1756,12 +1787,12 @@ TEST_F(EventBaseTest, IdleTime) {
// created. We want to make sure they don't interfere with the timing // created. We want to make sure they don't interfere with the timing
// operations below. // operations below.
eventBase.loopOnce(EVLOOP_NONBLOCK); eventBase.loopOnce(EVLOOP_NONBLOCK);
eventBase.setLoadAvgMsec(milliseconds(1000)); eventBase.setLoadAvgMsec(std::chrono::milliseconds(1000));
eventBase.resetLoadAvg(5900.0); eventBase.resetLoadAvg(5900.0);
auto testStart = std::chrono::steady_clock::now(); auto testStart = std::chrono::steady_clock::now();
int latencyCallbacks = 0; int latencyCallbacks = 0;
eventBase.setMaxLatency(microseconds(6000), [&]() { eventBase.setMaxLatency(std::chrono::microseconds(6000), [&]() {
++latencyCallbacks; ++latencyCallbacks;
if (latencyCallbacks != 1) { if (latencyCallbacks != 1) {
FAIL() << "Unexpected latency callback"; FAIL() << "Unexpected latency callback";
...@@ -1770,7 +1801,7 @@ TEST_F(EventBaseTest, IdleTime) { ...@@ -1770,7 +1801,7 @@ TEST_F(EventBaseTest, IdleTime) {
if (tos0.getTimeouts() < 6) { if (tos0.getTimeouts() < 6) {
// This could only happen if the host this test is running // This could only happen if the host this test is running
// on is heavily loaded. // on is heavily loaded.
int64_t usElapsed = duration_cast<microseconds>( int64_t usElapsed = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - testStart) std::chrono::steady_clock::now() - testStart)
.count(); .count();
EXPECT_LE(43800, usElapsed); EXPECT_LE(43800, usElapsed);
...@@ -1803,12 +1834,12 @@ TEST_F(EventBaseTest, IdleTime) { ...@@ -1803,12 +1834,12 @@ TEST_F(EventBaseTest, IdleTime) {
/** /**
* Test that thisLoop functionality works with terminateLoopSoon * Test that thisLoop functionality works with terminateLoopSoon
*/ */
TEST_F(EventBaseTest, ThisLoop) { TYPED_TEST_P(EventBaseTest, ThisLoop) {
bool runInLoop = false; bool runInLoop = false;
bool runThisLoop = false; bool runThisLoop = false;
{ {
BackendEventBase eb; FOLLY_SKIP_IF_NULLPTR_BACKEND(eb);
eb.runInLoop( eb.runInLoop(
[&]() { [&]() {
eb.terminateLoopSoon(); eb.terminateLoopSoon();
...@@ -1828,8 +1859,8 @@ TEST_F(EventBaseTest, ThisLoop) { ...@@ -1828,8 +1859,8 @@ TEST_F(EventBaseTest, ThisLoop) {
ASSERT_TRUE(runInLoop); ASSERT_TRUE(runInLoop);
} }
TEST_F(EventBaseTest, EventBaseThreadLoop) { TYPED_TEST_P(EventBaseTest, EventBaseThreadLoop) {
BackendEventBase base; FOLLY_SKIP_IF_NULLPTR_BACKEND(base);
bool ran = false; bool ran = false;
base.runInEventBaseThread([&]() { ran = true; }); base.runInEventBaseThread([&]() { ran = true; });
...@@ -1838,8 +1869,8 @@ TEST_F(EventBaseTest, EventBaseThreadLoop) { ...@@ -1838,8 +1869,8 @@ TEST_F(EventBaseTest, EventBaseThreadLoop) {
ASSERT_TRUE(ran); ASSERT_TRUE(ran);
} }
TEST_F(EventBaseTest, EventBaseThreadName) { TYPED_TEST_P(EventBaseTest, EventBaseThreadName) {
BackendEventBase base; FOLLY_SKIP_IF_NULLPTR_BACKEND(base);
base.setName("foo"); base.setName("foo");
base.loop(); base.loop();
...@@ -1850,16 +1881,16 @@ TEST_F(EventBaseTest, EventBaseThreadName) { ...@@ -1850,16 +1881,16 @@ TEST_F(EventBaseTest, EventBaseThreadName) {
#endif #endif
} }
TEST_F(EventBaseTest, RunBeforeLoop) { TYPED_TEST_P(EventBaseTest, RunBeforeLoop) {
BackendEventBase base; FOLLY_SKIP_IF_NULLPTR_BACKEND(base);
CountedLoopCallback cb(&base, 1, [&]() { base.terminateLoopSoon(); }); CountedLoopCallback cb(&base, 1, [&]() { base.terminateLoopSoon(); });
base.runBeforeLoop(&cb); base.runBeforeLoop(&cb);
base.loopForever(); base.loopForever();
ASSERT_EQ(cb.getCount(), 0); ASSERT_EQ(cb.getCount(), 0);
} }
TEST_F(EventBaseTest, RunBeforeLoopWait) { TYPED_TEST_P(EventBaseTest, RunBeforeLoopWait) {
BackendEventBase base; FOLLY_SKIP_IF_NULLPTR_BACKEND(base);
CountedLoopCallback cb(&base, 1); CountedLoopCallback cb(&base, 1);
base.tryRunAfterDelay([&]() { base.terminateLoopSoon(); }, 500); base.tryRunAfterDelay([&]() { base.terminateLoopSoon(); }, 500);
base.runBeforeLoop(&cb); base.runBeforeLoop(&cb);
...@@ -1881,8 +1912,8 @@ class PipeHandler : public EventHandler { ...@@ -1881,8 +1912,8 @@ class PipeHandler : public EventHandler {
}; };
} // namespace } // namespace
TEST_F(EventBaseTest, StopBeforeLoop) { TYPED_TEST_P(EventBaseTest, StopBeforeLoop) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
// Give the evb something to do. // Give the evb something to do.
int p[2]; int p[2];
...@@ -1904,19 +1935,19 @@ TEST_F(EventBaseTest, StopBeforeLoop) { ...@@ -1904,19 +1935,19 @@ TEST_F(EventBaseTest, StopBeforeLoop) {
SUCCEED(); SUCCEED();
} }
TEST_F(EventBaseTest, RunCallbacksOnDestruction) { TYPED_TEST_P(EventBaseTest, RunCallbacksOnDestruction) {
bool ran = false; bool ran = false;
{ {
BackendEventBase base; FOLLY_SKIP_IF_NULLPTR_BACKEND(base);
base.runInEventBaseThread([&]() { ran = true; }); base.runInEventBaseThread([&]() { ran = true; });
} }
ASSERT_TRUE(ran); ASSERT_TRUE(ran);
} }
TEST_F(EventBaseTest, LoopKeepAlive) { TYPED_TEST_P(EventBaseTest, LoopKeepAlive) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
bool done = false; bool done = false;
std::thread t([&, loopKeepAlive = getKeepAliveToken(evb)]() mutable { std::thread t([&, loopKeepAlive = getKeepAliveToken(evb)]() mutable {
...@@ -1933,8 +1964,8 @@ TEST_F(EventBaseTest, LoopKeepAlive) { ...@@ -1933,8 +1964,8 @@ TEST_F(EventBaseTest, LoopKeepAlive) {
t.join(); t.join();
} }
TEST_F(EventBaseTest, LoopKeepAliveInLoop) { TYPED_TEST_P(EventBaseTest, LoopKeepAliveInLoop) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
bool done = false; bool done = false;
std::thread t; std::thread t;
...@@ -1955,8 +1986,11 @@ TEST_F(EventBaseTest, LoopKeepAliveInLoop) { ...@@ -1955,8 +1986,11 @@ TEST_F(EventBaseTest, LoopKeepAliveInLoop) {
t.join(); t.join();
} }
TEST_F(EventBaseTest, LoopKeepAliveWithLoopForever) { TYPED_TEST_P(EventBaseTest, LoopKeepAliveWithLoopForever) {
std::unique_ptr<EventBase> evb = std::make_unique<EventBase>(); auto backend = TypeParam::getBackend();
SKIP_IF(!backend) << "Backend not available";
std::unique_ptr<EventBase> evb =
std::make_unique<EventBase>(std::move(backend));
bool done = false; bool done = false;
...@@ -1983,8 +2017,11 @@ TEST_F(EventBaseTest, LoopKeepAliveWithLoopForever) { ...@@ -1983,8 +2017,11 @@ TEST_F(EventBaseTest, LoopKeepAliveWithLoopForever) {
ASSERT_TRUE(done); ASSERT_TRUE(done);
} }
TEST_F(EventBaseTest, LoopKeepAliveShutdown) { TYPED_TEST_P(EventBaseTest, LoopKeepAliveShutdown) {
auto evb = std::make_unique<EventBase>(); auto backend = TypeParam::getBackend();
SKIP_IF(!backend) << "Backend not available";
auto evb = std::make_unique<EventBase>(std::move(backend));
bool done = false; bool done = false;
...@@ -2004,8 +2041,10 @@ TEST_F(EventBaseTest, LoopKeepAliveShutdown) { ...@@ -2004,8 +2041,10 @@ TEST_F(EventBaseTest, LoopKeepAliveShutdown) {
t.join(); t.join();
} }
TEST_F(EventBaseTest, LoopKeepAliveAtomic) { TYPED_TEST_P(EventBaseTest, LoopKeepAliveAtomic) {
auto evb = std::make_unique<EventBase>(); auto backend = TypeParam::getBackend();
SKIP_IF(!backend) << "Backend not available";
auto evb = std::make_unique<EventBase>(std::move(backend));
static constexpr size_t kNumThreads = 100; static constexpr size_t kNumThreads = 100;
static constexpr size_t kNumTasks = 100; static constexpr size_t kNumTasks = 100;
...@@ -2049,15 +2088,15 @@ TEST_F(EventBaseTest, LoopKeepAliveAtomic) { ...@@ -2049,15 +2088,15 @@ TEST_F(EventBaseTest, LoopKeepAliveAtomic) {
} }
} }
TEST_F(EventBaseTest, LoopKeepAliveCast) { TYPED_TEST_P(EventBaseTest, LoopKeepAliveCast) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
Executor::KeepAlive<> keepAlive = getKeepAliveToken(evb); Executor::KeepAlive<> keepAlive = getKeepAliveToken(evb);
} }
TEST_F(EventBaseTest, DrivableExecutorTest) { TYPED_TEST_P(EventBaseTest1, DrivableExecutorTest) {
folly::Promise<bool> p; folly::Promise<bool> p;
auto f = p.getFuture(); auto f = p.getFuture();
BackendEventBase base; FOLLY_SKIP_IF_NULLPTR_BACKEND(base);
bool finished = false; bool finished = false;
std::thread t([&] { std::thread t([&] {
...@@ -2083,15 +2122,15 @@ TEST_F(EventBaseTest, DrivableExecutorTest) { ...@@ -2083,15 +2122,15 @@ TEST_F(EventBaseTest, DrivableExecutorTest) {
t.join(); t.join();
} }
TEST_F(EventBaseTest, IOExecutorTest) { TYPED_TEST_P(EventBaseTest1, IOExecutorTest) {
BackendEventBase base; FOLLY_SKIP_IF_NULLPTR_BACKEND(base);
// Ensure EventBase manages itself as an IOExecutor. // Ensure EventBase manages itself as an IOExecutor.
EXPECT_EQ(base.getEventBase(), &base); EXPECT_EQ(base.getEventBase(), &base);
} }
TEST_F(EventBaseTest, RequestContextTest) { TYPED_TEST_P(EventBaseTest1, RequestContextTest) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
auto defaultCtx = RequestContext::get(); auto defaultCtx = RequestContext::get();
std::weak_ptr<RequestContext> rctx_weak_ptr; std::weak_ptr<RequestContext> rctx_weak_ptr;
...@@ -2111,8 +2150,8 @@ TEST_F(EventBaseTest, RequestContextTest) { ...@@ -2111,8 +2150,8 @@ TEST_F(EventBaseTest, RequestContextTest) {
EXPECT_EQ(defaultCtx, RequestContext::get()); EXPECT_EQ(defaultCtx, RequestContext::get());
} }
TEST_F(EventBaseTest, CancelLoopCallbackRequestContextTest) { TYPED_TEST_P(EventBaseTest1, CancelLoopCallbackRequestContextTest) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
CountedLoopCallback c(&evb, 1); CountedLoopCallback c(&evb, 1);
auto defaultCtx = RequestContext::get(); auto defaultCtx = RequestContext::get();
...@@ -2135,8 +2174,8 @@ TEST_F(EventBaseTest, CancelLoopCallbackRequestContextTest) { ...@@ -2135,8 +2174,8 @@ TEST_F(EventBaseTest, CancelLoopCallbackRequestContextTest) {
EXPECT_EQ(defaultCtx, RequestContext::get()); EXPECT_EQ(defaultCtx, RequestContext::get());
} }
TEST_F(EventBaseTest, TestStarvation) { TYPED_TEST_P(EventBaseTest1, TestStarvation) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
std::promise<void> stopRequested; std::promise<void> stopRequested;
std::promise<void> stopScheduled; std::promise<void> stopScheduled;
bool stopping{false}; bool stopping{false};
...@@ -2168,16 +2207,16 @@ TEST_F(EventBaseTest, TestStarvation) { ...@@ -2168,16 +2207,16 @@ TEST_F(EventBaseTest, TestStarvation) {
t.join(); t.join();
} }
TEST_F(EventBaseTest, RunOnDestructionBasic) { TYPED_TEST_P(EventBaseTest1, RunOnDestructionBasic) {
bool ranOnDestruction = false; bool ranOnDestruction = false;
{ {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
evb.runOnDestruction([&ranOnDestruction] { ranOnDestruction = true; }); evb.runOnDestruction([&ranOnDestruction] { ranOnDestruction = true; });
} }
EXPECT_TRUE(ranOnDestruction); EXPECT_TRUE(ranOnDestruction);
} }
TEST_F(EventBaseTest, RunOnDestructionCancelled) { TYPED_TEST_P(EventBaseTest1, RunOnDestructionCancelled) {
struct Callback : EventBase::OnDestructionCallback { struct Callback : EventBase::OnDestructionCallback {
bool ranOnDestruction{false}; bool ranOnDestruction{false};
...@@ -2188,7 +2227,7 @@ TEST_F(EventBaseTest, RunOnDestructionCancelled) { ...@@ -2188,7 +2227,7 @@ TEST_F(EventBaseTest, RunOnDestructionCancelled) {
auto cb = std::make_unique<Callback>(); auto cb = std::make_unique<Callback>();
{ {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
evb.runOnDestruction(*cb); evb.runOnDestruction(*cb);
EXPECT_TRUE(cb->cancel()); EXPECT_TRUE(cb->cancel());
} }
...@@ -2196,8 +2235,8 @@ TEST_F(EventBaseTest, RunOnDestructionCancelled) { ...@@ -2196,8 +2235,8 @@ TEST_F(EventBaseTest, RunOnDestructionCancelled) {
EXPECT_FALSE(cb->cancel()); EXPECT_FALSE(cb->cancel());
} }
TEST_F(EventBaseTest, RunOnDestructionAfterHandleDestroyed) { TYPED_TEST_P(EventBaseTest1, RunOnDestructionAfterHandleDestroyed) {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
{ {
bool ranOnDestruction = false; bool ranOnDestruction = false;
auto* cb = new EventBase::FunctionOnDestructionCallback( auto* cb = new EventBase::FunctionOnDestructionCallback(
...@@ -2208,10 +2247,10 @@ TEST_F(EventBaseTest, RunOnDestructionAfterHandleDestroyed) { ...@@ -2208,10 +2247,10 @@ TEST_F(EventBaseTest, RunOnDestructionAfterHandleDestroyed) {
} }
} }
TEST_F(EventBaseTest, RunOnDestructionAddCallbackWithinCallback) { TYPED_TEST_P(EventBaseTest1, RunOnDestructionAddCallbackWithinCallback) {
size_t callbacksCalled = 0; size_t callbacksCalled = 0;
{ {
BackendEventBase evb; FOLLY_SKIP_IF_NULLPTR_BACKEND(evb);
evb.runOnDestruction([&] { evb.runOnDestruction([&] {
++callbacksCalled; ++callbacksCalled;
evb.runOnDestruction([&] { ++callbacksCalled; }); evb.runOnDestruction([&] { ++callbacksCalled; });
...@@ -2219,3 +2258,70 @@ TEST_F(EventBaseTest, RunOnDestructionAddCallbackWithinCallback) { ...@@ -2219,3 +2258,70 @@ TEST_F(EventBaseTest, RunOnDestructionAddCallbackWithinCallback) {
} }
EXPECT_EQ(2, callbacksCalled); EXPECT_EQ(2, callbacksCalled);
} }
REGISTER_TYPED_TEST_CASE_P(
EventBaseTest,
ReadEvent,
ReadPersist,
ReadImmediate,
WriteEvent,
WritePersist,
WriteImmediate,
ReadWrite,
WriteRead,
ReadWriteSimultaneous,
ReadWritePersist,
ReadPartial,
WritePartial,
DestroyHandler,
RunAfterDelay,
RunAfterDelayDestruction,
BasicTimeouts,
ReuseTimeout,
RescheduleTimeout,
CancelTimeout,
DestroyTimeout,
ScheduledFn,
ScheduledFnAt,
RunInThread,
RunInEventBaseThreadAndWait,
RunImmediatelyOrRunInEventBaseThreadAndWaitCross,
RunImmediatelyOrRunInEventBaseThreadAndWaitWithin,
RunImmediatelyOrRunInEventBaseThreadNotLooping,
RepeatedRunInLoop,
RunInLoopNoTimeMeasurement,
RunInLoopStopLoop,
messageAvailableException,
TryRunningAfterTerminate,
CancelRunInLoop,
LoopTermination,
CallbackOrderTest,
AlwaysEnqueueCallbackOrderTest,
IdleTime,
ThisLoop,
EventBaseThreadLoop,
EventBaseThreadName,
RunBeforeLoop,
RunBeforeLoopWait,
StopBeforeLoop,
RunCallbacksOnDestruction,
LoopKeepAlive,
LoopKeepAliveInLoop,
LoopKeepAliveWithLoopForever,
LoopKeepAliveShutdown,
LoopKeepAliveAtomic,
LoopKeepAliveCast);
REGISTER_TYPED_TEST_CASE_P(
EventBaseTest1,
DrivableExecutorTest,
IOExecutorTest,
RequestContextTest,
CancelLoopCallbackRequestContextTest,
TestStarvation,
RunOnDestructionBasic,
RunOnDestructionCancelled,
RunOnDestructionAfterHandleDestroyed,
RunOnDestructionAddCallbackWithinCallback);
} // namespace test
} // namespace folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment