xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/fuchsia/lib/fidl/hanging_getter_unittest.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/fuchsia/lib/fidl/hanging_getter.h"
16 
17 #include <gtest/gtest.h>
18 
19 namespace bt_lib_fidl {
20 namespace {
21 
22 template <typename T, typename Getter = HangingGetter<T>>
23 class HangingGetterTestBase : public ::testing::Test {
24  public:
Watch()25   void Watch() {
26     getter_.Watch([this](T value) {
27       callback_count_++;
28       last_value_ = value;
29     });
30   }
31 
callback_count() const32   int callback_count() const { return callback_count_; }
last_value() const33   const std::optional<T>& last_value() const { return last_value_; }
34 
getter()35   Getter* getter() { return &getter_; }
36 
37  private:
38   int callback_count_ = 0;
39   std::optional<T> last_value_;
40   Getter getter_;
41 };
42 
43 using HangingGetterTest = HangingGetterTestBase<bool>;
44 
TEST_F(HangingGetterTest,Armed)45 TEST_F(HangingGetterTest, Armed) {
46   EXPECT_FALSE(getter()->armed());
47   Watch();
48   EXPECT_TRUE(getter()->armed());
49 }
50 
TEST_F(HangingGetterTest,WatchFailsWhilePending)51 TEST_F(HangingGetterTest, WatchFailsWhilePending) {
52   Watch();
53   EXPECT_EQ(0, callback_count());
54   Watch();
55   EXPECT_EQ(0, callback_count());
56 }
57 
TEST_F(HangingGetterTest,WatchCallbackDeferredWithoutAValue)58 TEST_F(HangingGetterTest, WatchCallbackDeferredWithoutAValue) {
59   Watch();
60   EXPECT_EQ(0, callback_count());
61   EXPECT_FALSE(last_value().has_value());
62 
63   getter()->Set(false);
64   EXPECT_EQ(1, callback_count());
65   ASSERT_TRUE(last_value().has_value());
66   EXPECT_FALSE(*last_value());
67 }
68 
TEST_F(HangingGetterTest,WatchCallbackRunsRightAwayWithAValue)69 TEST_F(HangingGetterTest, WatchCallbackRunsRightAwayWithAValue) {
70   getter()->Set(false);
71   EXPECT_EQ(0, callback_count());
72   EXPECT_FALSE(last_value().has_value());
73 
74   // Assign the value again to test that the latest value is returned in
75   // Watch().
76   getter()->Set(true);
77   EXPECT_EQ(0, callback_count());
78   EXPECT_FALSE(last_value().has_value());
79   EXPECT_FALSE(getter()->armed());
80 
81   Watch();
82   EXPECT_EQ(1, callback_count());
83   ASSERT_TRUE(last_value().has_value());
84   EXPECT_TRUE(*last_value());
85 
86   // Calling Watch() again should succeed and defer the callback.
87   Watch();
88   EXPECT_EQ(1, callback_count());
89 }
90 
TEST_F(HangingGetterTest,MultipleWatchersPending)91 TEST_F(HangingGetterTest, MultipleWatchersPending) {
92   Watch();  // 1
93   Watch();  // 2
94   Watch();  // 3
95   getter()->Set(true);
96   EXPECT_EQ(3, callback_count());
97   ASSERT_TRUE(last_value().has_value());
98   EXPECT_TRUE(*last_value());
99   EXPECT_FALSE(getter()->armed());
100 }
101 
TEST_F(HangingGetterTest,OnlyFirstOfManyWatchersRunsWithAValue)102 TEST_F(HangingGetterTest, OnlyFirstOfManyWatchersRunsWithAValue) {
103   getter()->Set(true);
104 
105   // Only the first watch call should result in a callback. The following two
106   // are expected to remain pending until a new value gets assigned.
107   Watch();  // 1
108   Watch();  // 2
109   Watch();  // 3
110   EXPECT_EQ(1, callback_count());
111   ASSERT_TRUE(last_value().has_value());
112   EXPECT_TRUE(*last_value());
113 
114   EXPECT_TRUE(getter()->armed());
115   getter()->Set(false);
116   EXPECT_EQ(3, callback_count());
117   ASSERT_TRUE(last_value().has_value());
118   EXPECT_FALSE(*last_value());
119 }
120 
TEST_F(HangingGetterTest,WatchClearsExistingValue)121 TEST_F(HangingGetterTest, WatchClearsExistingValue) {
122   getter()->Set(true);
123   Watch();
124   EXPECT_EQ(1, callback_count());
125   ASSERT_TRUE(last_value().has_value());
126   EXPECT_TRUE(*last_value());
127 
128   // Callback should be deferred.
129   Watch();
130   EXPECT_EQ(1, callback_count());
131 
132   // Test the deferral.
133   getter()->Set(true);
134   EXPECT_EQ(2, callback_count());
135 }
136 
TEST_F(HangingGetterTest,Transform)137 TEST_F(HangingGetterTest, Transform) {
138   getter()->Set(false);
139   getter()->Transform([](bool current) {
140     EXPECT_FALSE(current);
141     return true;
142   });
143 
144   Watch();
145   EXPECT_EQ(1, callback_count());
146   ASSERT_TRUE(last_value().has_value());
147   EXPECT_TRUE(*last_value());
148 }
149 
150 using HangingVectorGetterTest =
151     HangingGetterTestBase<std::vector<bool>, HangingVectorGetter<bool>>;
152 
TEST_F(HangingVectorGetterTest,AddAndWatch)153 TEST_F(HangingVectorGetterTest, AddAndWatch) {
154   getter()->Add(false);
155   getter()->Add(true);
156 
157   Watch();
158   EXPECT_EQ(1, callback_count());
159   EXPECT_TRUE(last_value().has_value());
160   EXPECT_EQ(2u, last_value()->size());
161   EXPECT_FALSE((*last_value())[0]);
162   EXPECT_TRUE((*last_value())[1]);
163 }
164 
TEST_F(HangingVectorGetterTest,WatchAndAdd)165 TEST_F(HangingVectorGetterTest, WatchAndAdd) {
166   Watch();
167   EXPECT_EQ(0, callback_count());
168 
169   getter()->Add(true);
170   EXPECT_EQ(1, callback_count());
171   EXPECT_TRUE(last_value().has_value());
172   EXPECT_EQ(1u, last_value()->size());
173   EXPECT_TRUE((*last_value())[0]);
174 }
175 
176 }  // namespace
177 }  // namespace bt_lib_fidl
178