blob: b066af36c03906fd6be70a47f049b55152c01973 [file] [log] [blame]
//
// Copyright (C) 2012 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 "shill/cellular/modem_manager.h"
#include <ModemManager/ModemManager.h>
#include <memory>
#include <utility>
#include <base/stl_util.h>
#include "shill/cellular/mock_dbus_objectmanager_proxy.h"
#include "shill/cellular/mock_modem.h"
#include "shill/cellular/mock_modem_info.h"
#include "shill/cellular/mock_modem_manager_proxy.h"
#include "shill/manager.h"
#include "shill/mock_control.h"
#include "shill/mock_manager.h"
#include "shill/test_event_dispatcher.h"
#include "shill/testing.h"
using std::string;
using std::vector;
using testing::_;
using testing::ByMove;
using testing::Pointee;
using testing::Return;
using testing::SaveArg;
using testing::StrEq;
using testing::Test;
namespace shill {
class ModemManagerTest : public Test {
public:
ModemManagerTest()
: manager_(&control_, &dispatcher_, nullptr),
modem_info_(&control_, &dispatcher_, nullptr, &manager_) {}
protected:
static const char kService[];
static const char kPath[];
static const char kModemPath[];
std::unique_ptr<StrictModem> CreateModem() {
return std::make_unique<StrictModem>(kService, kModemPath, &modem_info_);
}
EventDispatcherForTest dispatcher_;
MockControl control_;
MockManager manager_;
MockModemInfo modem_info_;
};
const char ModemManagerTest::kService[] = "org.chromium.ModemManager";
const char ModemManagerTest::kPath[] = "/org/chromium/ModemManager";
const char ModemManagerTest::kModemPath[] = "/org/blah/Modem/blah/0";
class ModemManagerForTest : public ModemManager {
public:
ModemManagerForTest(const string& service,
const string& path,
ModemInfo* modem_info)
: ModemManager(service, path, modem_info) {}
MOCK_METHOD0(Start, void());
MOCK_METHOD0(Stop, void());
};
class ModemManagerCoreTest : public ModemManagerTest {
public:
ModemManagerCoreTest() : modem_manager_(kService, kPath, &modem_info_) {}
protected:
ModemManagerForTest modem_manager_;
};
TEST_F(ModemManagerCoreTest, ConnectDisconnect) {
EXPECT_FALSE(modem_manager_.service_connected_);
modem_manager_.Connect();
EXPECT_TRUE(modem_manager_.service_connected_);
modem_manager_.RecordAddedModem(CreateModem());
EXPECT_EQ(1, modem_manager_.modems_.size());
modem_manager_.ModemManager::Disconnect();
EXPECT_EQ(0, modem_manager_.modems_.size());
EXPECT_FALSE(modem_manager_.service_connected_);
}
TEST_F(ModemManagerCoreTest, AddRemoveModem) {
modem_manager_.Connect();
EXPECT_FALSE(modem_manager_.ModemExists(kModemPath));
// Remove non-existent modem path.
modem_manager_.RemoveModem(kModemPath);
EXPECT_FALSE(modem_manager_.ModemExists(kModemPath));
modem_manager_.RecordAddedModem(CreateModem());
EXPECT_TRUE(modem_manager_.ModemExists(kModemPath));
// Add an already added modem.
modem_manager_.RecordAddedModem(CreateModem());
EXPECT_TRUE(modem_manager_.ModemExists(kModemPath));
modem_manager_.RemoveModem(kModemPath);
EXPECT_FALSE(modem_manager_.ModemExists(kModemPath));
// Remove an already removed modem path.
modem_manager_.RemoveModem(kModemPath);
EXPECT_FALSE(modem_manager_.ModemExists(kModemPath));
}
class ModemManagerClassicMockInit : public ModemManagerClassic {
public:
ModemManagerClassicMockInit(const string& service,
const string& path,
ModemInfo* modem_info_)
: ModemManagerClassic(service, path, modem_info_) {}
MOCK_METHOD1(InitModemClassic, void(ModemClassic*));
};
class ModemManagerClassicTest : public ModemManagerTest {
public:
ModemManagerClassicTest() : modem_manager_(kService, kPath, &modem_info_) {}
protected:
ModemManagerClassicMockInit modem_manager_;
};
TEST_F(ModemManagerClassicTest, StartStop) {
EXPECT_EQ(nullptr, modem_manager_.proxy_.get());
EXPECT_CALL(control_, CreateModemManagerProxy(_, kPath, kService, _, _))
.WillOnce(Return(ByMove(std::make_unique<MockModemManagerProxy>())));
modem_manager_.Start();
EXPECT_NE(nullptr, modem_manager_.proxy_.get());
modem_manager_.Stop();
EXPECT_EQ(nullptr, modem_manager_.proxy_.get());
}
TEST_F(ModemManagerClassicTest, Connect) {
auto proxy = std::make_unique<MockModemManagerProxy>();
EXPECT_CALL(*proxy, EnumerateDevices())
.WillOnce(Return(vector<string>(1, kModemPath)));
// Setup proxy.
modem_manager_.proxy_ = std::move(proxy);
EXPECT_CALL(modem_manager_,
InitModemClassic(
Pointee(Field(&Modem::path_, StrEq(kModemPath)))));
modem_manager_.Connect();
EXPECT_EQ(1, modem_manager_.modems_.size());
ASSERT_TRUE(base::ContainsKey(modem_manager_.modems_, kModemPath));
}
class ModemManager1MockInit : public ModemManager1 {
public:
ModemManager1MockInit(const string& service,
const string& path,
ModemInfo* modem_info_)
: ModemManager1(service, path, modem_info_) {}
MOCK_METHOD2(InitModem1, void(Modem1*, const InterfaceToProperties&));
};
class ModemManager1Test : public ModemManagerTest {
public:
ModemManager1Test() : modem_manager_(kService, kPath, &modem_info_) {}
protected:
std::unique_ptr<MockDBusObjectManagerProxy> CreateDBusObjectManagerProxy() {
auto proxy = std::make_unique<MockDBusObjectManagerProxy>();
proxy->IgnoreSetCallbacks();
return proxy;
}
void Connect(const ObjectsWithProperties& expected_objects) {
auto proxy = CreateDBusObjectManagerProxy();
ManagedObjectsCallback get_managed_objects_callback;
EXPECT_CALL(*proxy, GetManagedObjects(_, _, _))
.WillOnce(SaveArg<1>(&get_managed_objects_callback));
// Set up proxy.
modem_manager_.proxy_ = std::move(proxy);
modem_manager_.Connect();
get_managed_objects_callback.Run(expected_objects, Error());
}
static ObjectsWithProperties GetModemWithProperties() {
KeyValueStore o_fd_mm1_modem;
InterfaceToProperties properties;
properties[MM_DBUS_INTERFACE_MODEM] = o_fd_mm1_modem;
ObjectsWithProperties objects_with_properties;
objects_with_properties[kModemPath] = properties;
return objects_with_properties;
}
ModemManager1MockInit modem_manager_;
};
TEST_F(ModemManager1Test, StartStop) {
EXPECT_EQ(nullptr, modem_manager_.proxy_.get());
auto proxy = CreateDBusObjectManagerProxy();
EXPECT_CALL(*proxy, set_interfaces_added_callback(_));
EXPECT_CALL(*proxy, set_interfaces_removed_callback(_));
EXPECT_CALL(control_, CreateDBusObjectManagerProxy(kPath, kService, _, _))
.WillOnce(Return(ByMove(std::move(proxy))));
modem_manager_.Start();
EXPECT_NE(nullptr, modem_manager_.proxy_.get());
modem_manager_.Stop();
EXPECT_EQ(nullptr, modem_manager_.proxy_.get());
}
TEST_F(ModemManager1Test, Connect) {
Connect(GetModemWithProperties());
EXPECT_EQ(1, modem_manager_.modems_.size());
EXPECT_TRUE(base::ContainsKey(modem_manager_.modems_, kModemPath));
}
TEST_F(ModemManager1Test, AddRemoveInterfaces) {
// Have nothing come back from GetManagedObjects
Connect(ObjectsWithProperties());
EXPECT_EQ(0, modem_manager_.modems_.size());
// Add an object that doesn't have a modem interface. Nothing should be added
EXPECT_CALL(modem_manager_, InitModem1(_, _)).Times(0);
modem_manager_.OnInterfacesAddedSignal(kModemPath,
InterfaceToProperties());
EXPECT_EQ(0, modem_manager_.modems_.size());
// Actually add a modem
EXPECT_CALL(modem_manager_, InitModem1(_, _)).Times(1);
modem_manager_.OnInterfacesAddedSignal(kModemPath,
GetModemWithProperties()[kModemPath]);
EXPECT_EQ(1, modem_manager_.modems_.size());
// Remove an irrelevant interface
vector<string> not_including_modem_interface;
not_including_modem_interface.push_back("not.a.modem.interface");
modem_manager_.OnInterfacesRemovedSignal(kModemPath,
not_including_modem_interface);
EXPECT_EQ(1, modem_manager_.modems_.size());
// Remove the modem
vector<string> with_modem_interface;
with_modem_interface.push_back(MM_DBUS_INTERFACE_MODEM);
modem_manager_.OnInterfacesRemovedSignal(kModemPath, with_modem_interface);
EXPECT_EQ(0, modem_manager_.modems_.size());
}
} // namespace shill