blob: 0ae9704484148e7018e08e5578c30d26ea87675c [file] [log] [blame]
/******************************************************************************
*
* Copyright 2020 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <optional>
#include <unordered_map>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "flatbuffers/flatbuffers.h"
#include "common/bind.h"
#include "os/handler.h"
#include "os/thread.h"
#include "os/wakelock_manager.h"
#include "wakelock_manager_generated.h"
namespace testing {
using bluetooth::os::FinishWakelockManagerDataBuffer;
using bluetooth::os::GetWakelockManagerData;
using bluetooth::os::Handler;
using bluetooth::os::Thread;
using bluetooth::os::WakelockManager;
using bluetooth::os::WakelockManagerData;
using bluetooth::os::WakelockManagerDataBuilder;
class TestOsCallouts : public WakelockManager::OsCallouts {
public:
void AcquireCallout(const std::string& lock_name) override {
auto iter = acquired_lock_counts.find(lock_name);
if (iter == acquired_lock_counts.end()) {
acquired_lock_counts[lock_name] = 0;
}
acquired_lock_counts[lock_name] += 1;
}
void ReleaseCallout(const std::string& lock_name) override {
auto iter = acquired_lock_counts.find(lock_name);
if (iter == acquired_lock_counts.end()) {
acquired_lock_counts[lock_name] = 0;
}
acquired_lock_counts[lock_name] -= 1;
}
std::optional<int> GetNetAcquiredCount(const std::string& lock_name) const {
auto iter = acquired_lock_counts.find(lock_name);
if (iter == acquired_lock_counts.end()) {
return std::nullopt;
}
return iter->second;
}
// how many times each lock is acquired, net, can go negative
std::unordered_map<std::string, int> acquired_lock_counts;
};
class WakelockManagerTest : public Test {
protected:
void SetUp() override {
thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
handler_ = new Handler(thread_);
}
void TearDown() override {
handler_->Clear();
delete handler_;
delete thread_;
}
void SyncHandler() {
std::promise<void> promise;
auto future = promise.get_future();
handler_->Post(
bluetooth::common::BindOnce(&std::promise<void>::set_value, bluetooth::common::Unretained(&promise)));
auto future_status = future.wait_for(std::chrono::seconds(1));
ASSERT_EQ(future_status, std::future_status::ready);
}
Handler* handler_;
Thread* thread_;
};
TEST_F(WakelockManagerTest, test_set_os_callouts_repeated_acquire) {
TestOsCallouts os_callouts;
WakelockManager::Get().SetOsCallouts(&os_callouts, handler_);
// Initially, no wakelock is acquired
ASSERT_TRUE(os_callouts.acquired_lock_counts.empty());
ASSERT_FALSE(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId));
WakelockManager::Get().Acquire();
SyncHandler();
ASSERT_EQ(os_callouts.acquired_lock_counts.size(), 1);
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
WakelockManager::Get().Acquire();
SyncHandler();
ASSERT_EQ(os_callouts.acquired_lock_counts.size(), 1);
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(2)));
WakelockManager::Get().Release();
SyncHandler();
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
WakelockManager::Get().CleanUp();
SyncHandler();
}
TEST_F(WakelockManagerTest, test_set_os_callouts_repeated_release) {
TestOsCallouts os_callouts;
WakelockManager::Get().SetOsCallouts(&os_callouts, handler_);
// Initially, no wakelock is acquired
ASSERT_TRUE(os_callouts.acquired_lock_counts.empty());
ASSERT_FALSE(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId));
WakelockManager::Get().Acquire();
SyncHandler();
ASSERT_EQ(os_callouts.acquired_lock_counts.size(), 1);
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
WakelockManager::Get().Release();
SyncHandler();
ASSERT_EQ(os_callouts.acquired_lock_counts.size(), 1);
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(0)));
// OS callouts allow pass through for repeated release calls
WakelockManager::Get().Release();
SyncHandler();
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(-1)));
WakelockManager::Get().CleanUp();
SyncHandler();
}
TEST_F(WakelockManagerTest, test_with_os_callouts_in_a_loop_and_dump) {
TestOsCallouts os_callouts;
WakelockManager::Get().SetOsCallouts(&os_callouts, handler_);
// Initially, no wakelock is acquired
ASSERT_TRUE(os_callouts.acquired_lock_counts.empty());
ASSERT_FALSE(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId));
for (size_t i = 0; i < 1000; i++) {
WakelockManager::Get().Acquire();
SyncHandler();
ASSERT_EQ(os_callouts.acquired_lock_counts.size(), 1);
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(1)));
WakelockManager::Get().Release();
SyncHandler();
ASSERT_THAT(os_callouts.GetNetAcquiredCount(WakelockManager::kBtWakelockId), Optional(Eq(0)));
}
{
flatbuffers::FlatBufferBuilder builder(1024);
auto offset = WakelockManager::Get().GetDumpsysData(&builder);
FinishWakelockManagerDataBuffer(builder, offset);
auto data = GetWakelockManagerData(builder.GetBufferPointer());
ASSERT_EQ(data->acquired_count(), 1000);
ASSERT_EQ(data->released_count(), 1000);
}
WakelockManager::Get().CleanUp();
SyncHandler();
{
flatbuffers::FlatBufferBuilder builder(1024);
auto offset = WakelockManager::Get().GetDumpsysData(&builder);
FinishWakelockManagerDataBuffer(builder, offset);
auto data = GetWakelockManagerData(builder.GetBufferPointer());
ASSERT_EQ(data->acquired_count(), 0);
ASSERT_EQ(data->released_count(), 0);
}
}
} // namespace testing