blob: b8eaa2cd3bb19b20034868fcd9f5e260ff71fd57 [file] [log] [blame]
John Park398c74a2018-10-20 21:17:39 -07001#include "aos/complex_thread_local.h"
Brian Silverman2fa99cb2014-09-06 00:53:00 -04002
3#include <atomic>
4
5#include "gtest/gtest.h"
6
John Park33858a32018-09-28 23:05:48 -07007#include "aos/util/thread.h"
Brian Silverman2fa99cb2014-09-06 00:53:00 -04008
9namespace aos {
10namespace testing {
11
12class ComplexThreadLocalTest : public ::testing::Test {
13 protected:
14 struct TraceableObject {
15 TraceableObject(int data = 0) : data(data) { ++constructions; }
16 ~TraceableObject() { ++destructions; }
17
18 static ::std::atomic<int> constructions, destructions;
19
20 int data;
21 };
22 ComplexThreadLocal<TraceableObject> local;
23
24 private:
25 void SetUp() override {
26 local.Clear();
27 EXPECT_EQ(TraceableObject::constructions, TraceableObject::destructions)
28 << "There should be no way to create and destroy different numbers.";
29 TraceableObject::constructions = TraceableObject::destructions = 0;
30 }
31};
32::std::atomic<int> ComplexThreadLocalTest::TraceableObject::constructions;
33::std::atomic<int> ComplexThreadLocalTest::TraceableObject::destructions;
34
35TEST_F(ComplexThreadLocalTest, Basic) {
36 EXPECT_EQ(0, TraceableObject::constructions);
37 EXPECT_EQ(0, TraceableObject::destructions);
38 EXPECT_FALSE(local.created());
39 EXPECT_EQ(nullptr, local.get());
40
41 local.Create(971);
42 EXPECT_EQ(1, TraceableObject::constructions);
43 EXPECT_EQ(0, TraceableObject::destructions);
44 EXPECT_TRUE(local.created());
45 EXPECT_EQ(971, local->data);
46
47 local.Create(254);
48 EXPECT_EQ(1, TraceableObject::constructions);
49 EXPECT_EQ(0, TraceableObject::destructions);
50 EXPECT_TRUE(local.created());
51 EXPECT_EQ(971, local->data);
52
53 local.Clear();
54 EXPECT_EQ(1, TraceableObject::constructions);
55 EXPECT_EQ(1, TraceableObject::destructions);
56 EXPECT_FALSE(local.created());
57 EXPECT_EQ(nullptr, local.get());
58
59 local.Create(973);
60 EXPECT_EQ(2, TraceableObject::constructions);
61 EXPECT_EQ(1, TraceableObject::destructions);
62 EXPECT_TRUE(local.created());
63 EXPECT_EQ(973, local->data);
64}
65
66TEST_F(ComplexThreadLocalTest, AnotherThread) {
67 EXPECT_FALSE(local.created());
68 util::FunctionThread::RunInOtherThread([this]() {
69 EXPECT_FALSE(local.created());
70 local.Create(971);
71 EXPECT_TRUE(local.created());
72 EXPECT_EQ(971, local->data);
73 EXPECT_EQ(1, TraceableObject::constructions);
74 EXPECT_EQ(0, TraceableObject::destructions);
75 });
76 EXPECT_EQ(1, TraceableObject::constructions);
77 EXPECT_EQ(1, TraceableObject::destructions);
78 EXPECT_FALSE(local.created());
79}
80
81TEST_F(ComplexThreadLocalTest, TwoThreads) {
82 util::FunctionThread thread([this](util::FunctionThread *) {
83 local.Create(971);
84 EXPECT_EQ(971, local->data);
85 EXPECT_EQ(0, TraceableObject::destructions);
86 });
87 thread.Start();
88 local.Create(973);
89 EXPECT_EQ(973, local->data);
90 thread.Join();
91 EXPECT_TRUE(local.created());
92 EXPECT_EQ(2, TraceableObject::constructions);
93 EXPECT_EQ(1, TraceableObject::destructions);
94 local.Clear();
95 EXPECT_EQ(2, TraceableObject::constructions);
96 EXPECT_EQ(2, TraceableObject::destructions);
97 EXPECT_FALSE(local.created());
98}
99
100} // namespace testing
101} // namespace aos