1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "module_state_dumper_unittest.h"
18
19 #include <base/callback.h>
20 #include <base/functional/bind.h>
21 #include <base/location.h>
22 #include <base/threading/platform_thread.h>
23 #include <bluetooth/log.h>
24 #include <sys/syscall.h>
25
26 #include <sstream>
27 #include <string>
28
29 #include "gtest/gtest.h"
30 #include "module_dumper.h"
31 #include "os/handler.h"
32 #include "os/thread.h"
33 #include "stack/include/main_thread.h"
34
35 using namespace bluetooth;
36
37 namespace {
38
39 constexpr int sync_timeout_in_ms = 3000;
40 constexpr char title[] = "module_state_dumper_test";
41
42 } // namespace
43
44 // Module private implementation that is inaccessible externally
45 struct StateDumperTestModule::PrivateImpl : public ModuleMainloop {};
46
IsStarted() const47 bool StateDumperTestModule::IsStarted() const {
48 return pimpl_ != nullptr;
49 }
50
Start()51 void StateDumperTestModule::Start() {
52 ASSERT_FALSE(IsStarted());
53 pimpl_ = std::make_shared<StateDumperTestModule::PrivateImpl>();
54 }
55
Stop()56 void StateDumperTestModule::Stop() {
57 ASSERT_TRUE(IsStarted());
58 pimpl_.reset();
59 }
60
ToString() const61 std::string StateDumperTestModule::ToString() const {
62 return std::string(__func__);
63 }
64
65 const bluetooth::ModuleFactory StateDumperTestModule::Factory =
__anon78b7e1210202() 66 bluetooth::ModuleFactory([]() { return new StateDumperTestModule(); });
67
GetDumpsysData(flatbuffers::FlatBufferBuilder *) const68 DumpsysDataFinisher StateDumperTestModule::GetDumpsysData(
69 flatbuffers::FlatBufferBuilder* /* builder */) const {
70 log::info("flatbuffers");
71 return EmptyDumpsysDataFinisher;
72 }
73
74 //
75 // Module GDx Testing Below
76 //
77 class ModuleStateDumperTest : public ::testing::Test {
78 protected:
SetUp()79 void SetUp() override {
80 test_framework_tid_ = base::PlatformThread::CurrentId();
81 module_ = new StateDumperTestModule();
82 main_thread_start_up();
83 mainloop_tid_ = get_mainloop_tid();
84 }
85
TearDown()86 void TearDown() override {
87 sync_main_handler();
88 main_thread_shut_down();
89 delete module_;
90 }
91
sync_main_handler()92 void sync_main_handler() {
93 std::promise promise = std::promise<void>();
94 std::future future = promise.get_future();
95 post_on_bt_main([&promise]() { promise.set_value(); });
96 future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms));
97 };
98
get_mainloop_tid()99 static pid_t get_mainloop_tid() {
100 std::promise<pid_t> pid_promise = std::promise<pid_t>();
101 auto future = pid_promise.get_future();
102 post_on_bt_main([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); });
103 return future.get();
104 }
105
106 pid_t test_framework_tid_{-1};
107 pid_t mainloop_tid_{-1};
108 TestModuleRegistry module_registry_;
109 StateDumperTestModule* module_;
110 };
111
112 class ModuleStateDumperWithStackTest : public ModuleStateDumperTest {
113 protected:
SetUp()114 void SetUp() override {
115 ModuleStateDumperTest::SetUp();
116 module_registry_.InjectTestModule(
117 &StateDumperTestModule::Factory, module_ /* pass ownership */);
118 module_ = nullptr; // ownership is passed
119 }
120
get_handler_tid(os::Handler * handler)121 static pid_t get_handler_tid(os::Handler* handler) {
122 std::promise<pid_t> handler_tid_promise = std::promise<pid_t>();
123 std::future<pid_t> future = handler_tid_promise.get_future();
124 handler->Post(common::BindOnce(
125 [](std::promise<pid_t> promise) { promise.set_value(base::PlatformThread::CurrentId()); },
126 std::move(handler_tid_promise)));
127 return future.get();
128 }
129
TearDown()130 void TearDown() override {
131 module_registry_.StopAll();
132 ModuleStateDumperTest::TearDown();
133 }
134
Mod()135 StateDumperTestModule* Mod() {
136 return module_registry_.GetModuleUnderTest<StateDumperTestModule>();
137 }
138
139 pid_t handler_tid_{-1};
140 };
141
TEST_F(ModuleStateDumperTest,lifecycle)142 TEST_F(ModuleStateDumperTest, lifecycle) {
143 ::bluetooth::os::Thread* thread =
144 new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME);
145 ASSERT_FALSE(module_registry_.IsStarted<StateDumperTestModule>());
146 module_registry_.Start<StateDumperTestModule>(thread);
147 ASSERT_TRUE(module_registry_.IsStarted<StateDumperTestModule>());
148 module_registry_.StopAll();
149 ASSERT_FALSE(module_registry_.IsStarted<StateDumperTestModule>());
150 delete thread;
151 }
152
TEST_F(ModuleStateDumperWithStackTest,dump_state)153 TEST_F(ModuleStateDumperWithStackTest, dump_state) {
154 ModuleDumper dumper(STDOUT_FILENO, module_registry_, title);
155
156 std::string output;
157 std::ostringstream oss;
158 dumper.DumpState(&output, oss);
159
160 log::info("DUMP STATE");
161 log::info("{}", oss.str());
162 log::info("{}", output);
163 }
164