1// 2// Copyright (C) 2012 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 "shill/cellular/modem_manager.h" 18 19#include <base/stl_util.h> 20#include <ModemManager/ModemManager.h> 21 22#include "shill/cellular/mock_dbus_objectmanager_proxy.h" 23#include "shill/cellular/mock_modem.h" 24#include "shill/cellular/mock_modem_info.h" 25#include "shill/cellular/mock_modem_manager_proxy.h" 26#include "shill/manager.h" 27#include "shill/mock_control.h" 28#include "shill/mock_manager.h" 29#include "shill/test_event_dispatcher.h" 30#include "shill/testing.h" 31 32using std::string; 33using std::shared_ptr; 34using std::vector; 35using testing::_; 36using testing::Invoke; 37using testing::Pointee; 38using testing::Return; 39using testing::SaveArg; 40using testing::StrEq; 41using testing::Test; 42 43namespace shill { 44 45class ModemManagerTest : public Test { 46 public: 47 ModemManagerTest() 48 : manager_(&control_, &dispatcher_, nullptr), 49 modem_info_(&control_, &dispatcher_, nullptr, &manager_) {} 50 51 virtual void SetUp() { 52 modem_.reset( 53 new StrictModem(kService, kModemPath, &modem_info_, &control_)); 54 } 55 56 protected: 57 static const char kService[]; 58 static const char kPath[]; 59 static const char kModemPath[]; 60 61 shared_ptr<StrictModem> modem_; 62 63 EventDispatcherForTest dispatcher_; 64 MockControl control_; 65 MockManager manager_; 66 MockModemInfo modem_info_; 67}; 68 69const char ModemManagerTest::kService[] = "org.chromium.ModemManager"; 70const char ModemManagerTest::kPath[] = "/org/chromium/ModemManager"; 71const char ModemManagerTest::kModemPath[] = "/org/blah/Modem/blah/0"; 72 73class ModemManagerForTest : public ModemManager { 74 public: 75 ModemManagerForTest(ControlInterface* control_interface, 76 const string& service, 77 const string& path, 78 ModemInfo* modem_info) 79 : ModemManager(control_interface, service, path, modem_info) {} 80 81 MOCK_METHOD0(Start, void()); 82 MOCK_METHOD0(Stop, void()); 83}; 84 85class ModemManagerCoreTest : public ModemManagerTest { 86 public: 87 ModemManagerCoreTest() 88 : ModemManagerTest(), 89 modem_manager_(&control_, kService, kPath, &modem_info_) {} 90 91 protected: 92 ModemManagerForTest modem_manager_; 93}; 94 95TEST_F(ModemManagerCoreTest, ConnectDisconnect) { 96 EXPECT_FALSE(modem_manager_.service_connected_); 97 modem_manager_.Connect(); 98 EXPECT_TRUE(modem_manager_.service_connected_); 99 100 modem_manager_.RecordAddedModem(modem_); 101 EXPECT_EQ(1, modem_manager_.modems_.size()); 102 103 modem_manager_.ModemManager::Disconnect(); 104 EXPECT_EQ(0, modem_manager_.modems_.size()); 105 EXPECT_FALSE(modem_manager_.service_connected_); 106} 107 108TEST_F(ModemManagerCoreTest, AddRemoveModem) { 109 modem_manager_.Connect(); 110 EXPECT_FALSE(modem_manager_.ModemExists(kModemPath)); 111 112 // Remove non-existent modem path. 113 modem_manager_.RemoveModem(kModemPath); 114 EXPECT_FALSE(modem_manager_.ModemExists(kModemPath)); 115 116 modem_manager_.RecordAddedModem(modem_); 117 EXPECT_TRUE(modem_manager_.ModemExists(kModemPath)); 118 119 // Add an already added modem. 120 modem_manager_.RecordAddedModem(modem_); 121 EXPECT_TRUE(modem_manager_.ModemExists(kModemPath)); 122 123 modem_manager_.RemoveModem(kModemPath); 124 EXPECT_FALSE(modem_manager_.ModemExists(kModemPath)); 125 126 // Remove an already removed modem path. 127 modem_manager_.RemoveModem(kModemPath); 128 EXPECT_FALSE(modem_manager_.ModemExists(kModemPath)); 129} 130 131class ModemManagerClassicMockInit : public ModemManagerClassic { 132 public: 133 ModemManagerClassicMockInit(ControlInterface* control_interface, 134 const string& service, 135 const string& path, 136 ModemInfo* modem_info_) : 137 ModemManagerClassic(control_interface, service, path, modem_info_) {} 138 139 MOCK_METHOD1(InitModemClassic, void(shared_ptr<ModemClassic>)); 140}; 141 142class ModemManagerClassicTest : public ModemManagerTest { 143 public: 144 ModemManagerClassicTest() 145 : ModemManagerTest(), 146 modem_manager_(&control_, kService, kPath, &modem_info_), 147 proxy_(new MockModemManagerProxy()) {} 148 149 protected: 150 ModemManagerClassicMockInit modem_manager_; 151 MockModemManagerProxy* proxy_; 152}; 153 154TEST_F(ModemManagerClassicTest, StartStop) { 155 EXPECT_EQ(nullptr, modem_manager_.proxy_.get()); 156 157 EXPECT_CALL(control_, CreateModemManagerProxy(_, kPath, kService, _, _)) 158 .WillOnce(Return(proxy_)); 159 modem_manager_.Start(); 160 EXPECT_NE(nullptr, modem_manager_.proxy_.get()); 161 162 modem_manager_.Stop(); 163 EXPECT_EQ(nullptr, modem_manager_.proxy_.get()); 164} 165 166TEST_F(ModemManagerClassicTest, Connect) { 167 // Setup proxy. 168 modem_manager_.proxy_.reset(proxy_); 169 170 EXPECT_CALL(*proxy_, EnumerateDevices()) 171 .WillOnce(Return(vector<string>(1, kModemPath))); 172 EXPECT_CALL(modem_manager_, 173 InitModemClassic( 174 Pointee(Field(&Modem::path_, StrEq(kModemPath))))); 175 modem_manager_.Connect(); 176 EXPECT_EQ(1, modem_manager_.modems_.size()); 177 ASSERT_TRUE(ContainsKey(modem_manager_.modems_, kModemPath)); 178} 179 180class ModemManager1MockInit : public ModemManager1 { 181 public: 182 ModemManager1MockInit(ControlInterface* control_interface, 183 const string& service, 184 const string& path, 185 ModemInfo* modem_info_) : 186 ModemManager1(control_interface, service, path, modem_info_) {} 187 MOCK_METHOD2(InitModem1, void(shared_ptr<Modem1>, 188 const InterfaceToProperties&)); 189}; 190 191 192class ModemManager1Test : public ModemManagerTest { 193 public: 194 ModemManager1Test() 195 : ModemManagerTest(), 196 modem_manager_(&control_, kService, kPath, &modem_info_), 197 proxy_(new MockDBusObjectManagerProxy()) {} 198 199 protected: 200 virtual void SetUp() { 201 proxy_->IgnoreSetCallbacks(); 202 } 203 204 void Connect(const ObjectsWithProperties& expected_objects) { 205 ManagedObjectsCallback get_managed_objects_callback; 206 EXPECT_CALL(*proxy_, GetManagedObjects(_, _, _)) 207 .WillOnce(SaveArg<1>(&get_managed_objects_callback)); 208 modem_manager_.Connect(); 209 get_managed_objects_callback.Run(expected_objects, Error()); 210 } 211 212 static ObjectsWithProperties GetModemWithProperties() { 213 KeyValueStore o_fd_mm1_modem; 214 215 InterfaceToProperties properties; 216 properties[MM_DBUS_INTERFACE_MODEM] = o_fd_mm1_modem; 217 218 ObjectsWithProperties objects_with_properties; 219 objects_with_properties[kModemPath] = properties; 220 221 return objects_with_properties; 222 } 223 224 ModemManager1MockInit modem_manager_; 225 MockDBusObjectManagerProxy* proxy_; 226 MockControl control_; 227}; 228 229TEST_F(ModemManager1Test, StartStop) { 230 EXPECT_EQ(nullptr, modem_manager_.proxy_.get()); 231 232 EXPECT_CALL(control_, CreateDBusObjectManagerProxy(kPath, kService, _, _)) 233 .WillOnce(Return(proxy_)); 234 EXPECT_CALL(*proxy_, set_interfaces_added_callback(_)); 235 EXPECT_CALL(*proxy_, set_interfaces_removed_callback(_)); 236 modem_manager_.Start(); 237 EXPECT_NE(nullptr, modem_manager_.proxy_.get()); 238 239 modem_manager_.Stop(); 240 EXPECT_EQ(nullptr, modem_manager_.proxy_.get()); 241} 242 243TEST_F(ModemManager1Test, Connect) { 244 // Setup proxy. 245 modem_manager_.proxy_.reset(proxy_); 246 247 Connect(GetModemWithProperties()); 248 EXPECT_EQ(1, modem_manager_.modems_.size()); 249 EXPECT_TRUE(ContainsKey(modem_manager_.modems_, kModemPath)); 250} 251 252TEST_F(ModemManager1Test, AddRemoveInterfaces) { 253 // Setup proxy. 254 modem_manager_.proxy_.reset(proxy_); 255 256 // Have nothing come back from GetManagedObjects 257 Connect(ObjectsWithProperties()); 258 EXPECT_EQ(0, modem_manager_.modems_.size()); 259 260 // Add an object that doesn't have a modem interface. Nothing should be added 261 EXPECT_CALL(modem_manager_, InitModem1(_, _)).Times(0); 262 modem_manager_.OnInterfacesAddedSignal(kModemPath, 263 InterfaceToProperties()); 264 EXPECT_EQ(0, modem_manager_.modems_.size()); 265 266 // Actually add a modem 267 EXPECT_CALL(modem_manager_, InitModem1(_, _)).Times(1); 268 modem_manager_.OnInterfacesAddedSignal(kModemPath, 269 GetModemWithProperties()[kModemPath]); 270 EXPECT_EQ(1, modem_manager_.modems_.size()); 271 272 // Remove an irrelevant interface 273 vector<string> not_including_modem_interface; 274 not_including_modem_interface.push_back("not.a.modem.interface"); 275 modem_manager_.OnInterfacesRemovedSignal(kModemPath, 276 not_including_modem_interface); 277 EXPECT_EQ(1, modem_manager_.modems_.size()); 278 279 // Remove the modem 280 vector<string> with_modem_interface; 281 with_modem_interface.push_back(MM_DBUS_INTERFACE_MODEM); 282 modem_manager_.OnInterfacesRemovedSignal(kModemPath, with_modem_interface); 283 EXPECT_EQ(0, modem_manager_.modems_.size()); 284} 285 286} // namespace shill 287