1 /******************************************************************************
2 *
3 * Copyright 2020 Google, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 #include "os/wakelock_manager.h"
19
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <optional>
24 #include <unordered_map>
25
26 #include "common/bind.h"
27 #include "os/handler.h"
28 #include "os/thread.h"
29
30 namespace testing {
31
32 using bluetooth::os::Handler;
33 using bluetooth::os::Thread;
34 using bluetooth::os::WakelockManager;
35
36 class TestOsCallouts : public WakelockManager::OsCallouts {
37 public:
AcquireCallout(const std::string & lock_name)38 void AcquireCallout(const std::string& lock_name) override {
39 auto iter = acquired_lock_counts.find(lock_name);
40 if (iter == acquired_lock_counts.end()) {
41 acquired_lock_counts[lock_name] = 0;
42 }
43 acquired_lock_counts[lock_name] += 1;
44 }
45
ReleaseCallout(const std::string & lock_name)46 void ReleaseCallout(const std::string& lock_name) override {
47 auto iter = acquired_lock_counts.find(lock_name);
48 if (iter == acquired_lock_counts.end()) {
49 acquired_lock_counts[lock_name] = 0;
50 }
51 acquired_lock_counts[lock_name] -= 1;
52 }
53
GetNetAcquiredCount(const std::string & lock_name) const54 std::optional<int> GetNetAcquiredCount(const std::string& lock_name) const {
55 auto iter = acquired_lock_counts.find(lock_name);
56 if (iter == acquired_lock_counts.end()) {
57 return std::nullopt;
58 }
59 return iter->second;
60 }
61
62 // how many times each lock is acquired, net, can go negative
63 std::unordered_map<std::string, int> acquired_lock_counts;
64 };
65
66 class WakelockManagerTest : public Test {
67 protected:
SetUp()68 void SetUp() override {
69 thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
70 handler_ = new Handler(thread_);
71 }
TearDown()72 void TearDown() override {
73 handler_->Clear();
74 delete handler_;
75 delete thread_;
76 }
77
SyncHandler()78 void SyncHandler() {
79 std::promise<void> promise;
80 auto future = promise.get_future();
81 handler_->Post(bluetooth::common::BindOnce(&std::promise<void>::set_value,
82 bluetooth::common::Unretained(&promise)));
83 auto future_status = future.wait_for(std::chrono::seconds(1));
84 ASSERT_EQ(future_status, std::future_status::ready);
85 }
86
87 Handler* handler_;
88 Thread* thread_;
89 };
90
TEST_F(WakelockManagerTest,test_set_os_callouts_repeated_acquire)91 TEST_F(WakelockManagerTest, test_set_os_callouts_repeated_acquire) {
92 TestOsCallouts os_callouts;
93 WakelockManager::Get().SetOsCallouts(&os_callouts, handler_);
94
95 // Initially, no wakelock is acquired
96 ASSERT_TRUE(os_callouts.acquired_lock_counts.empty());
97 ASSERT_FALSE(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId));
98
99 WakelockManager::Get().Acquire();
100 SyncHandler();
101 ASSERT_EQ(os_callouts.acquired_lock_counts.size(), (size_t)1);
102 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
103
104 WakelockManager::Get().Acquire();
105 SyncHandler();
106 ASSERT_EQ(os_callouts.acquired_lock_counts.size(), (size_t)1);
107 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(2)));
108
109 WakelockManager::Get().Release();
110 SyncHandler();
111 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
112
113 WakelockManager::Get().CleanUp();
114 SyncHandler();
115 }
116
TEST_F(WakelockManagerTest,test_set_os_callouts_repeated_release)117 TEST_F(WakelockManagerTest, test_set_os_callouts_repeated_release) {
118 TestOsCallouts os_callouts;
119 WakelockManager::Get().SetOsCallouts(&os_callouts, handler_);
120
121 // Initially, no wakelock is acquired
122 ASSERT_TRUE(os_callouts.acquired_lock_counts.empty());
123 ASSERT_FALSE(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId));
124
125 WakelockManager::Get().Acquire();
126 SyncHandler();
127 ASSERT_EQ(os_callouts.acquired_lock_counts.size(), (size_t)1);
128 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
129
130 WakelockManager::Get().Release();
131 SyncHandler();
132 ASSERT_EQ(os_callouts.acquired_lock_counts.size(), (size_t)1);
133 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(0)));
134
135 // OS callouts allow pass through for repeated release calls
136 WakelockManager::Get().Release();
137 SyncHandler();
138 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(-1)));
139
140 WakelockManager::Get().CleanUp();
141 SyncHandler();
142 }
143
TEST_F(WakelockManagerTest,test_with_os_callouts_in_a_loop_and_dump)144 TEST_F(WakelockManagerTest, test_with_os_callouts_in_a_loop_and_dump) {
145 TestOsCallouts os_callouts;
146 WakelockManager::Get().SetOsCallouts(&os_callouts, handler_);
147
148 // Initially, no wakelock is acquired
149 ASSERT_TRUE(os_callouts.acquired_lock_counts.empty());
150 ASSERT_FALSE(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId));
151
152 for (size_t i = 0; i < 1000; i++) {
153 WakelockManager::Get().Acquire();
154 SyncHandler();
155 ASSERT_EQ(os_callouts.acquired_lock_counts.size(), (size_t)1);
156 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
157 WakelockManager::Get().Release();
158 SyncHandler();
159 ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(0)));
160 }
161
162 WakelockManager::Get().CleanUp();
163 SyncHandler();
164 }
165
166 } // namespace testing
167