blob: 7fe573d2352cc5f8daec0fc34e8cc6ff12a81f58 [file] [log] [blame]
#include "aos/event.h"
#include <chrono>
#include <thread>
#include "gtest/gtest.h"
#include "aos/time/time.h"
#include "aos/testing/test_logging.h"
namespace aos {
namespace testing {
namespace chrono = ::std::chrono;
namespace this_thread = ::std::this_thread;
class EventTest : public ::testing::Test {
public:
Event test_event_;
protected:
void SetUp() override {
::aos::testing::EnableTestLogging();
}
};
// Makes sure that basic operations with no blocking or anything work.
TEST_F(EventTest, Basic) {
EXPECT_FALSE(test_event_.Clear());
EXPECT_FALSE(test_event_.Clear());
test_event_.Set();
test_event_.Wait();
EXPECT_TRUE(test_event_.Clear());
EXPECT_FALSE(test_event_.Clear());
}
// Tests that tsan understands that events establish a happens-before
// relationship.
TEST_F(EventTest, ThreadSanitizer) {
for (int i = 0; i < 3000; ++i) {
int variable = 0;
test_event_.Clear();
::std::thread thread([this, &variable]() {
test_event_.Wait();
--variable;
});
++variable;
test_event_.Set();
thread.join();
EXPECT_EQ(0, variable);
}
}
// Tests that an event blocks correctly.
TEST_F(EventTest, Blocks) {
monotonic_clock::time_point start_time, finish_time;
// Without this, it sometimes manages to fail under tsan.
Event started;
::std::thread thread([this, &start_time, &finish_time, &started]() {
start_time = monotonic_clock::now();
started.Set();
test_event_.Wait();
finish_time = monotonic_clock::now();
});
static constexpr auto kWaitTime = chrono::milliseconds(50);
started.Wait();
this_thread::sleep_for(kWaitTime);
test_event_.Set();
thread.join();
EXPECT_GE(finish_time - start_time, kWaitTime);
}
TEST_F(EventTest, WaitTimeout) {
EXPECT_FALSE(test_event_.WaitTimeout(chrono::milliseconds(50)));
monotonic_clock::time_point start_time, finish_time;
// Without this, it sometimes manages to fail under tsan.
Event started;
::std::thread thread([this, &start_time, &finish_time, &started]() {
start_time = monotonic_clock::now();
started.Set();
EXPECT_TRUE(test_event_.WaitTimeout(chrono::milliseconds(500)));
finish_time = monotonic_clock::now();
});
constexpr auto kWaitTime = chrono::milliseconds(50);
started.Wait();
this_thread::sleep_for(kWaitTime);
test_event_.Set();
thread.join();
EXPECT_GE(finish_time - start_time, kWaitTime);
}
} // namespace testing
} // namespace aos