/* * Copyright 2019 The Android Open Source Project * * 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 "module.h" #include "module_unittest_generated.h" #include "os/handler.h" #include "os/thread.h" #include "gtest/gtest.h" #include #include #include using ::bluetooth::os::Thread; namespace bluetooth { namespace { class ModuleTest : public ::testing::Test { protected: void SetUp() override { thread_ = new Thread("test_thread", Thread::Priority::NORMAL); registry_ = new ModuleRegistry(); } void TearDown() override { delete registry_; delete thread_; } ModuleRegistry* registry_; Thread* thread_; }; os::Handler* test_module_no_dependency_handler = nullptr; class TestModuleNoDependency : public Module { public: static const ModuleFactory Factory; protected: void ListDependencies(ModuleList* list) override { } void Start() override { // A module is not considered started until Start() finishes EXPECT_FALSE(GetModuleRegistry()->IsStarted()); test_module_no_dependency_handler = GetHandler(); } void Stop() override { // A module is not considered stopped until after Stop() finishes EXPECT_TRUE(GetModuleRegistry()->IsStarted()); } std::string ToString() const override { return std::string("TestModuleNoDependency"); } }; const ModuleFactory TestModuleNoDependency::Factory = ModuleFactory([]() { return new TestModuleNoDependency(); }); os::Handler* test_module_one_dependency_handler = nullptr; class TestModuleOneDependency : public Module { public: static const ModuleFactory Factory; protected: void ListDependencies(ModuleList* list) override { list->add(); } void Start() override { EXPECT_TRUE(GetModuleRegistry()->IsStarted()); // A module is not considered started until Start() finishes EXPECT_FALSE(GetModuleRegistry()->IsStarted()); test_module_one_dependency_handler = GetHandler(); } void Stop() override { EXPECT_TRUE(GetModuleRegistry()->IsStarted()); // A module is not considered stopped until after Stop() finishes EXPECT_TRUE(GetModuleRegistry()->IsStarted()); } std::string ToString() const override { return std::string("TestModuleOneDependency"); } }; const ModuleFactory TestModuleOneDependency::Factory = ModuleFactory([]() { return new TestModuleOneDependency(); }); class TestModuleNoDependencyTwo : public Module { public: static const ModuleFactory Factory; protected: void ListDependencies(ModuleList* list) override { } void Start() override { // A module is not considered started until Start() finishes EXPECT_FALSE(GetModuleRegistry()->IsStarted()); } void Stop() override { // A module is not considered stopped until after Stop() finishes EXPECT_TRUE(GetModuleRegistry()->IsStarted()); } std::string ToString() const override { return std::string("TestModuleNoDependencyTwo"); } }; const ModuleFactory TestModuleNoDependencyTwo::Factory = ModuleFactory([]() { return new TestModuleNoDependencyTwo(); }); class TestModuleTwoDependencies : public Module { public: static const ModuleFactory Factory; protected: void ListDependencies(ModuleList* list) override { list->add(); list->add(); } void Start() override { EXPECT_TRUE(GetModuleRegistry()->IsStarted()); EXPECT_TRUE(GetModuleRegistry()->IsStarted()); // A module is not considered started until Start() finishes EXPECT_FALSE(GetModuleRegistry()->IsStarted()); } void Stop() override { EXPECT_TRUE(GetModuleRegistry()->IsStarted()); EXPECT_TRUE(GetModuleRegistry()->IsStarted()); // A module is not considered stopped until after Stop() finishes EXPECT_TRUE(GetModuleRegistry()->IsStarted()); } std::string ToString() const override { return std::string("TestModuleTwoDependencies"); } }; const ModuleFactory TestModuleTwoDependencies::Factory = ModuleFactory([]() { return new TestModuleTwoDependencies(); }); // To generate module unittest flatbuffer headers: // $ flatc --cpp module_unittest.fbs class TestModuleDumpState : public Module { public: static const ModuleFactory Factory; std::string test_string_{"Initial Test String"}; protected: void ListDependencies(ModuleList* list) override { list->add(); } void Start() override { EXPECT_TRUE(GetModuleRegistry()->IsStarted()); // A module is not considered started until Start() finishes EXPECT_FALSE(GetModuleRegistry()->IsStarted()); test_module_one_dependency_handler = GetHandler(); } void Stop() override { EXPECT_TRUE(GetModuleRegistry()->IsStarted()); // A module is not considered stopped until after Stop() finishes EXPECT_TRUE(GetModuleRegistry()->IsStarted()); } std::string ToString() const override { return std::string("TestModuleDumpState"); } DumpsysDataFinisher GetDumpsysData(flatbuffers::FlatBufferBuilder* fb_builder) const override { auto string = fb_builder->CreateString(test_string_.c_str()); auto builder = ModuleUnitTestDataBuilder(*fb_builder); builder.add_title(string); auto table = builder.Finish(); return [table](DumpsysDataBuilder* builder) { builder->add_module_unittest_data(table); }; } }; const ModuleFactory TestModuleDumpState::Factory = ModuleFactory([]() { return new TestModuleDumpState(); }); TEST_F(ModuleTest, no_dependency) { ModuleList list; list.add(); registry_->Start(&list, thread_); EXPECT_TRUE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); registry_->StopAll(); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); } TEST_F(ModuleTest, one_dependency) { ModuleList list; list.add(); registry_->Start(&list, thread_); EXPECT_TRUE(registry_->IsStarted()); EXPECT_TRUE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); registry_->StopAll(); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); } TEST_F(ModuleTest, two_dependencies) { ModuleList list; list.add(); registry_->Start(&list, thread_); EXPECT_TRUE(registry_->IsStarted()); EXPECT_TRUE(registry_->IsStarted()); EXPECT_TRUE(registry_->IsStarted()); EXPECT_TRUE(registry_->IsStarted()); registry_->StopAll(); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); EXPECT_FALSE(registry_->IsStarted()); } void post_to_module_one_handler() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); test_module_one_dependency_handler->Post(common::BindOnce([] { FAIL(); })); } TEST_F(ModuleTest, shutdown_with_unhandled_callback) { ModuleList list; list.add(); registry_->Start(&list, thread_); test_module_no_dependency_handler->Post(common::BindOnce(&post_to_module_one_handler)); registry_->StopAll(); } TEST_F(ModuleTest, dump_state) { static const char* title = "Test Dump Title"; ModuleList list; list.add(); registry_->Start(&list, thread_); ModuleDumper dumper(*registry_, title); std::string output; dumper.DumpState(&output); auto data = flatbuffers::GetRoot(output.data()); EXPECT_STREQ(title, data->title()->c_str()); auto test_data = data->module_unittest_data(); EXPECT_STREQ("Initial Test String", test_data->title()->c_str()); TestModuleDumpState* test_module = static_cast(registry_->Start(&TestModuleDumpState::Factory, nullptr)); test_module->test_string_ = "A Second Test String"; dumper.DumpState(&output); data = flatbuffers::GetRoot(output.data()); test_data = data->module_unittest_data(); EXPECT_STREQ("A Second Test String", test_data->title()->c_str()); registry_->StopAll(); } } // namespace } // namespace bluetooth