blob: 0a36643586bf17e02f32c9d72851537cc01c5c0f [file] [log] [blame]
Sabina Davis2ed5ea22017-09-26 22:27:42 -07001#include "aos/once.h"
brians2fdfc072013-02-26 05:35:15 +00002
Brian Silvermanaf784862014-05-13 08:14:55 -07003#include <stdlib.h>
4#include <limits.h>
brians2fdfc072013-02-26 05:35:15 +00005
6#include "gtest/gtest.h"
7
8namespace aos {
9namespace testing {
10
11class OnceTest : public ::testing::Test {
12 public:
13 static int *Function() {
14 ++times_run_;
Brian Silvermanaf784862014-05-13 08:14:55 -070015 value_ = 971 + times_run_;
brians2fdfc072013-02-26 05:35:15 +000016 return &value_;
17 }
18
19 protected:
20 void SetUp() {
21 value_ = 0;
22 times_run_ = 0;
23 }
24
25 static int value_;
26 static int times_run_;
27};
28int OnceTest::value_, OnceTest::times_run_;
29
30// Makes sure that it calls the function at the right time and that it correctly
31// passes the result out.
32TEST_F(OnceTest, Works) {
33 static Once<int> once(Function);
34
35 EXPECT_EQ(0, value_);
36 EXPECT_EQ(0, times_run_);
37
38 EXPECT_EQ(value_, *once.Get());
39 EXPECT_NE(0, value_);
40 EXPECT_NE(0, times_run_);
41 // Make sure it's not passing it through an assignment by value or something
42 // else weird.
43 EXPECT_EQ(&value_, once.Get());
44}
45
46// Makes sure that having a Once at namespace scope works correctly.
47namespace {
48
49Once<int> global_once(OnceTest::Function);
50
51} // namespace
52
53TEST_F(OnceTest, Global) {
54 EXPECT_EQ(value_, *global_once.Get());
55 EXPECT_NE(0, value_);
56 EXPECT_NE(0, times_run_);
57}
58
59// Makes sure that an instance keeps returning the same value without running
60// the function again.
61TEST_F(OnceTest, MultipleGets) {
62 static Once<int> once(Function);
63
64 EXPECT_EQ(value_, *once.Get());
65 EXPECT_EQ(1, times_run_);
66 EXPECT_EQ(value_, *once.Get());
67 EXPECT_EQ(1, times_run_);
68 EXPECT_EQ(value_, *once.Get());
69 EXPECT_EQ(1, times_run_);
70}
71
72// Tests to make sure that the right methods clear out the instance variables at
73// the right times.
74TEST_F(OnceTest, MemoryClearing) {
75 Once<int> once(NULL);
76
77 once.run_ = 1;
78 once.done_ = true;
79 // Run the constructor again to make sure it doesn't touch the variables set
80 // above.
81 new (&once)Once<int>(Function);
82
83 // Should return a random, (potentially) uninitialized value.
84 once.Get();
85 EXPECT_EQ(0, times_run_);
86
87 once.Reset();
88 EXPECT_EQ(0, times_run_);
89 EXPECT_EQ(value_, *once.Get());
90 EXPECT_EQ(1, times_run_);
91}
92
93namespace {
94
95int second_result = 0;
96int *SecondFunction() {
Brian Silvermanaf784862014-05-13 08:14:55 -070097 static int result = 254;
98 second_result = ++result;
brians2fdfc072013-02-26 05:35:15 +000099 return &second_result;
100}
101
102} // namespace
103
104// Makes sure that multiple instances don't interfere with each other.
105TEST_F(OnceTest, MultipleInstances) {
106 static Once<int> once1(Function);
107 static Once<int> once2(SecondFunction);
108
109 EXPECT_EQ(&value_, once1.Get());
110 EXPECT_EQ(&second_result, once2.Get());
111 EXPECT_EQ(&value_, once1.Get());
112 EXPECT_EQ(&second_result, once2.Get());
113}
114
115// Tests calling Reset() to run the function a second time.
116TEST_F(OnceTest, Recalculate) {
117 Once<int> once(Function);
brians295f1f32013-03-03 21:01:48 +0000118 once.Reset();
brians2fdfc072013-02-26 05:35:15 +0000119
120 EXPECT_EQ(value_, *once.Get());
121 EXPECT_EQ(1, times_run_);
122
123 value_ = 0;
124 once.Reset();
125 EXPECT_EQ(value_, *once.Get());
126 EXPECT_EQ(2, times_run_);
127}
128
129} // namespace testing
130} // namespace aos