blob: 91af403309107653e309425085cf16dcb0031277 [file] [log] [blame]
Brian Silvermanf5f34902015-03-29 17:57:59 -04001#include "aos/common/event.h"
2
3#include <thread>
4
5#include "gtest/gtest.h"
6
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05007#include "aos/testing/test_logging.h"
Brian Silvermanf5f34902015-03-29 17:57:59 -04008#include "aos/common/time.h"
9
10namespace aos {
11namespace testing {
12
13class EventTest : public ::testing::Test {
14 public:
Brian Silverman30608942015-04-08 19:16:46 -040015 Event test_event_;
Brian Silvermanf5f34902015-03-29 17:57:59 -040016
17 protected:
18 void SetUp() override {
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050019 ::aos::testing::EnableTestLogging();
Brian Silvermanf5f34902015-03-29 17:57:59 -040020 }
21};
22
23// Makes sure that basic operations with no blocking or anything work.
24TEST_F(EventTest, Basic) {
Brian Silverman30608942015-04-08 19:16:46 -040025 EXPECT_FALSE(test_event_.Clear());
26 EXPECT_FALSE(test_event_.Clear());
Brian Silvermanf5f34902015-03-29 17:57:59 -040027
Brian Silverman30608942015-04-08 19:16:46 -040028 test_event_.Set();
29 test_event_.Wait();
30 EXPECT_TRUE(test_event_.Clear());
31 EXPECT_FALSE(test_event_.Clear());
Brian Silvermanf5f34902015-03-29 17:57:59 -040032}
33
34// Tests that tsan understands that events establish a happens-before
35// relationship.
36TEST_F(EventTest, ThreadSanitizer) {
Brian Silvermand6ee9a12015-03-31 01:37:49 -040037 for (int i = 0; i < 3000; ++i) {
Brian Silvermanf5f34902015-03-29 17:57:59 -040038 int variable = 0;
Brian Silverman30608942015-04-08 19:16:46 -040039 test_event_.Clear();
Brian Silvermanf5f34902015-03-29 17:57:59 -040040 ::std::thread thread([this, &variable]() {
Brian Silverman30608942015-04-08 19:16:46 -040041 test_event_.Wait();
Brian Silvermanf5f34902015-03-29 17:57:59 -040042 --variable;
43 });
44 ++variable;
Brian Silverman30608942015-04-08 19:16:46 -040045 test_event_.Set();
Brian Silvermanf5f34902015-03-29 17:57:59 -040046 thread.join();
47 EXPECT_EQ(0, variable);
48 }
49}
50
51// Tests that an event blocks correctly.
52TEST_F(EventTest, Blocks) {
53 time::Time start_time, finish_time;
Brian Silvermand6ee9a12015-03-31 01:37:49 -040054 // Without this, it sometimes manages to fail under tsan.
55 Event started;
56 ::std::thread thread([this, &start_time, &finish_time, &started]() {
Brian Silvermanf5f34902015-03-29 17:57:59 -040057 start_time = time::Time::Now();
Brian Silvermand6ee9a12015-03-31 01:37:49 -040058 started.Set();
Brian Silverman30608942015-04-08 19:16:46 -040059 test_event_.Wait();
Brian Silvermanf5f34902015-03-29 17:57:59 -040060 finish_time = time::Time::Now();
61 });
62 static const time::Time kWaitTime = time::Time::InSeconds(0.05);
Brian Silvermand6ee9a12015-03-31 01:37:49 -040063 started.Wait();
Brian Silvermanf5f34902015-03-29 17:57:59 -040064 time::SleepFor(kWaitTime);
Brian Silverman30608942015-04-08 19:16:46 -040065 test_event_.Set();
66 thread.join();
67 EXPECT_GE(finish_time - start_time, kWaitTime);
68}
69
70TEST_F(EventTest, WaitTimeout) {
71 EXPECT_FALSE(test_event_.WaitTimeout(time::Time::InSeconds(0.05)));
72
73 time::Time start_time, finish_time;
74 // Without this, it sometimes manages to fail under tsan.
75 Event started;
76 ::std::thread thread([this, &start_time, &finish_time, &started]() {
77 start_time = time::Time::Now();
78 started.Set();
79 EXPECT_TRUE(test_event_.WaitTimeout(time::Time::InSeconds(0.5)));
80 finish_time = time::Time::Now();
81 });
82 static const time::Time kWaitTime = time::Time::InSeconds(0.05);
83 started.Wait();
84 time::SleepFor(kWaitTime);
85 test_event_.Set();
Brian Silvermanf5f34902015-03-29 17:57:59 -040086 thread.join();
87 EXPECT_GE(finish_time - start_time, kWaitTime);
88}
89
90} // namespace testing
91} // namespace aos