blob: 5a8e644817950f8ddc89390f0fdd134a032baa51 [file] [log] [blame]
Brian Silverman7b266d92021-02-17 21:24:02 -08001#include "aos/ipc_lib/event.h"
Brian Silvermanf5f34902015-03-29 17:57:59 -04002
Austin Schuhf2a50ba2016-12-24 16:16:26 -08003#include <chrono>
Stephan Pleines682928d2024-05-31 20:43:48 -07004#include <memory>
Brian Silvermanf5f34902015-03-29 17:57:59 -04005#include <thread>
6
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "gtest/gtest.h"
8
Austin Schuhf2a50ba2016-12-24 16:16:26 -08009#include "aos/testing/test_logging.h"
Brian Silverman7b266d92021-02-17 21:24:02 -080010#include "aos/time/time.h"
Brian Silvermanf5f34902015-03-29 17:57:59 -040011
Stephan Pleinesf63bde82024-01-13 15:59:33 -080012namespace aos::testing {
Brian Silvermanf5f34902015-03-29 17:57:59 -040013
Austin Schuhf2a50ba2016-12-24 16:16:26 -080014namespace chrono = ::std::chrono;
15namespace this_thread = ::std::this_thread;
16
Brian Silvermanf5f34902015-03-29 17:57:59 -040017class EventTest : public ::testing::Test {
18 public:
Brian Silverman30608942015-04-08 19:16:46 -040019 Event test_event_;
Brian Silvermanf5f34902015-03-29 17:57:59 -040020
21 protected:
Brian Silverman7b266d92021-02-17 21:24:02 -080022 void SetUp() override { ::aos::testing::EnableTestLogging(); }
Brian Silvermanf5f34902015-03-29 17:57:59 -040023};
24
25// Makes sure that basic operations with no blocking or anything work.
26TEST_F(EventTest, Basic) {
Brian Silverman30608942015-04-08 19:16:46 -040027 EXPECT_FALSE(test_event_.Clear());
28 EXPECT_FALSE(test_event_.Clear());
Brian Silvermanf5f34902015-03-29 17:57:59 -040029
Brian Silverman30608942015-04-08 19:16:46 -040030 test_event_.Set();
31 test_event_.Wait();
32 EXPECT_TRUE(test_event_.Clear());
33 EXPECT_FALSE(test_event_.Clear());
Brian Silvermanf5f34902015-03-29 17:57:59 -040034}
35
36// Tests that tsan understands that events establish a happens-before
37// relationship.
38TEST_F(EventTest, ThreadSanitizer) {
Brian Silvermand6ee9a12015-03-31 01:37:49 -040039 for (int i = 0; i < 3000; ++i) {
Brian Silvermanf5f34902015-03-29 17:57:59 -040040 int variable = 0;
Brian Silverman30608942015-04-08 19:16:46 -040041 test_event_.Clear();
Brian Silvermanf5f34902015-03-29 17:57:59 -040042 ::std::thread thread([this, &variable]() {
Brian Silverman30608942015-04-08 19:16:46 -040043 test_event_.Wait();
Brian Silvermanf5f34902015-03-29 17:57:59 -040044 --variable;
45 });
46 ++variable;
Brian Silverman30608942015-04-08 19:16:46 -040047 test_event_.Set();
Brian Silvermanf5f34902015-03-29 17:57:59 -040048 thread.join();
49 EXPECT_EQ(0, variable);
50 }
51}
52
53// Tests that an event blocks correctly.
54TEST_F(EventTest, Blocks) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080055 monotonic_clock::time_point start_time, finish_time;
Brian Silvermand6ee9a12015-03-31 01:37:49 -040056 // Without this, it sometimes manages to fail under tsan.
57 Event started;
58 ::std::thread thread([this, &start_time, &finish_time, &started]() {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080059 start_time = monotonic_clock::now();
Brian Silvermand6ee9a12015-03-31 01:37:49 -040060 started.Set();
Brian Silverman30608942015-04-08 19:16:46 -040061 test_event_.Wait();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080062 finish_time = monotonic_clock::now();
Brian Silvermanf5f34902015-03-29 17:57:59 -040063 });
Austin Schuhf2a50ba2016-12-24 16:16:26 -080064 static constexpr auto kWaitTime = chrono::milliseconds(50);
Brian Silvermand6ee9a12015-03-31 01:37:49 -040065 started.Wait();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080066 this_thread::sleep_for(kWaitTime);
Brian Silverman30608942015-04-08 19:16:46 -040067 test_event_.Set();
68 thread.join();
69 EXPECT_GE(finish_time - start_time, kWaitTime);
70}
71
72TEST_F(EventTest, WaitTimeout) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080073 EXPECT_FALSE(test_event_.WaitTimeout(chrono::milliseconds(50)));
Brian Silverman30608942015-04-08 19:16:46 -040074
Austin Schuhf2a50ba2016-12-24 16:16:26 -080075 monotonic_clock::time_point start_time, finish_time;
Brian Silverman30608942015-04-08 19:16:46 -040076 // Without this, it sometimes manages to fail under tsan.
77 Event started;
78 ::std::thread thread([this, &start_time, &finish_time, &started]() {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080079 start_time = monotonic_clock::now();
Brian Silverman30608942015-04-08 19:16:46 -040080 started.Set();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080081 EXPECT_TRUE(test_event_.WaitTimeout(chrono::milliseconds(500)));
82 finish_time = monotonic_clock::now();
Brian Silverman30608942015-04-08 19:16:46 -040083 });
Austin Schuhf2a50ba2016-12-24 16:16:26 -080084 constexpr auto kWaitTime = chrono::milliseconds(50);
Brian Silverman30608942015-04-08 19:16:46 -040085 started.Wait();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080086 this_thread::sleep_for(kWaitTime);
Brian Silverman30608942015-04-08 19:16:46 -040087 test_event_.Set();
Brian Silvermanf5f34902015-03-29 17:57:59 -040088 thread.join();
89 EXPECT_GE(finish_time - start_time, kWaitTime);
90}
91
Stephan Pleinesf63bde82024-01-13 15:59:33 -080092} // namespace aos::testing