123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- //
- // Copyright 2015 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 <memory>
- #include <sys/socket.h>
- #include <sys/un.h>
- #include <base/at_exit.h>
- #include <base/command_line.h>
- #include <base/files/scoped_file.h>
- #include <base/macros.h>
- #include <base/run_loop.h>
- #include <base/strings/stringprintf.h>
- #include <gtest/gtest.h>
- #include "service/adapter.h"
- #include "service/hal/fake_bluetooth_gatt_interface.h"
- #include "service/hal/fake_bluetooth_interface.h"
- #include "service/ipc/ipc_manager.h"
- #include "service/settings.h"
- #include "service/test/mock_daemon.h"
- namespace {
- using testing::Return;
- const char kTestSocketPath[] = "test_socket_path";
- class IPCLinuxTest : public ::testing::Test {
- public:
- IPCLinuxTest() = default;
- ~IPCLinuxTest() override = default;
- void SetUp() override {
- SetUpCommandLine();
- ASSERT_TRUE(settings_.Init());
- auto mock_daemon = new bluetooth::testing::MockDaemon();
- ON_CALL(*mock_daemon, GetSettings()).WillByDefault(Return(&settings_));
- ON_CALL(*mock_daemon, GetMessageLoop())
- .WillByDefault(Return(&message_loop_));
- bluetooth::Daemon::InitializeForTesting(mock_daemon);
- bluetooth::hal::BluetoothInterface::InitializeForTesting(
- new bluetooth::hal::FakeBluetoothInterface());
- bluetooth::hal::BluetoothGattInterface::InitializeForTesting(
- new bluetooth::hal::FakeBluetoothGattInterface(nullptr, nullptr,
- nullptr, nullptr));
- adapter_ = bluetooth::Adapter::Create();
- ipc_manager_.reset(new ipc::IPCManager(adapter_.get()));
- }
- void TearDown() override {
- client_fd_.reset();
- ipc_manager_.reset();
- adapter_.reset();
- bluetooth::hal::BluetoothGattInterface::CleanUp();
- bluetooth::hal::BluetoothInterface::CleanUp();
- bluetooth::Daemon::ShutDown();
- base::CommandLine::Reset();
- }
- virtual void SetUpCommandLine() {
- std::string ipc_socket_arg =
- base::StringPrintf("--create-ipc-socket=%s", kTestSocketPath);
- const base::CommandLine::CharType* argv[] = {
- "program", ipc_socket_arg.c_str(),
- };
- base::CommandLine::Init(arraysize(argv), argv);
- }
- void ConnectToTestSocket() {
- client_fd_.reset(socket(PF_UNIX, SOCK_SEQPACKET, 0));
- ASSERT_TRUE(client_fd_.is_valid());
- struct sockaddr_un address;
- memset(&address, 0, sizeof(address));
- address.sun_family = AF_UNIX;
- strncpy(address.sun_path, kTestSocketPath, sizeof(address.sun_path) - 1);
- int status =
- connect(client_fd_.get(), (struct sockaddr*)&address, sizeof(address));
- EXPECT_EQ(0, status);
- }
- protected:
- base::AtExitManager exit_manager_;
- base::MessageLoop message_loop_;
- bluetooth::Settings settings_;
- std::unique_ptr<bluetooth::Adapter> adapter_;
- std::unique_ptr<ipc::IPCManager> ipc_manager_;
- base::ScopedFD client_fd_;
- DISALLOW_COPY_AND_ASSIGN(IPCLinuxTest);
- };
- class IPCLinuxTestDisabled : public IPCLinuxTest {
- public:
- IPCLinuxTestDisabled() = default;
- ~IPCLinuxTestDisabled() override = default;
- void SetUpCommandLine() override {
- // Set up with no --ipc-socket-path
- const base::CommandLine::CharType* argv[] = {"program"};
- base::CommandLine::Init(arraysize(argv), argv);
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(IPCLinuxTestDisabled);
- };
- class TestDelegate : public ipc::IPCManager::Delegate,
- public base::SupportsWeakPtr<TestDelegate> {
- public:
- TestDelegate() : started_count_(0), stopped_count_(0) {}
- void OnIPCHandlerStarted(ipc::IPCManager::Type type) override {
- ASSERT_EQ(ipc::IPCManager::TYPE_LINUX, type);
- started_count_++;
- base::MessageLoop::current()->QuitWhenIdle();
- }
- void OnIPCHandlerStopped(ipc::IPCManager::Type type) override {
- ASSERT_EQ(ipc::IPCManager::TYPE_LINUX, type);
- stopped_count_++;
- base::MessageLoop::current()->QuitWhenIdle();
- }
- int started_count() const { return started_count_; }
- int stopped_count() const { return stopped_count_; }
- private:
- int started_count_;
- int stopped_count_;
- DISALLOW_COPY_AND_ASSIGN(TestDelegate);
- };
- TEST_F(IPCLinuxTestDisabled, StartWithNoSocketPath) {
- TestDelegate delegate;
- EXPECT_FALSE(ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, &delegate));
- EXPECT_FALSE(ipc_manager_->LinuxStarted());
- EXPECT_EQ(0, delegate.started_count());
- EXPECT_EQ(0, delegate.stopped_count());
- }
- TEST_F(IPCLinuxTest, BasicStartAndExit) {
- TestDelegate delegate;
- EXPECT_TRUE(ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, &delegate));
- EXPECT_TRUE(ipc_manager_->LinuxStarted());
- // Run the message loop. We will stop the loop when we receive a delegate
- // event.
- base::RunLoop().Run();
- // We should have received the started event.
- EXPECT_EQ(1, delegate.started_count());
- EXPECT_EQ(0, delegate.stopped_count());
- // At this point the thread is blocking on accept and listening for incoming
- // connections. TearDown should gracefully clean up the thread and the test
- // should succeed without hanging.
- ipc_manager_.reset();
- base::RunLoop().Run();
- EXPECT_EQ(1, delegate.stopped_count());
- }
- TEST_F(IPCLinuxTest, BasicStartAndConnect) {
- TestDelegate delegate;
- EXPECT_TRUE(ipc_manager_->Start(ipc::IPCManager::TYPE_LINUX, &delegate));
- EXPECT_TRUE(ipc_manager_->LinuxStarted());
- // Run the message loop. We will stop the loop when we receive a delegate
- // event.
- base::RunLoop().Run();
- // We should have received the started event.
- EXPECT_EQ(1, delegate.started_count());
- EXPECT_EQ(0, delegate.stopped_count());
- // IPC successfully started. Now attempt to connect to the socket.
- ConnectToTestSocket();
- // TODO(armansito): Test that the IPC event loop shuts down cleanly while a
- // client is connected. Currently this will fail and the fix is to use
- // MessageLoopForIO rather than a custom event loop.
- }
- } // namespace
|