• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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