Home | History | Annotate | Download | only in cellular
      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 
     32 using std::string;
     33 using std::shared_ptr;
     34 using std::vector;
     35 using testing::_;
     36 using testing::Invoke;
     37 using testing::Pointee;
     38 using testing::Return;
     39 using testing::SaveArg;
     40 using testing::StrEq;
     41 using testing::Test;
     42 
     43 namespace shill {
     44 
     45 class 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 
     69 const char ModemManagerTest::kService[] = "org.chromium.ModemManager";
     70 const char ModemManagerTest::kPath[] = "/org/chromium/ModemManager";
     71 const char ModemManagerTest::kModemPath[] = "/org/blah/Modem/blah/0";
     72 
     73 class 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 
     85 class 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 
     95 TEST_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 
    108 TEST_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 
    131 class 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 
    142 class 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 
    154 TEST_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 
    166 TEST_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 
    180 class 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 
    192 class 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 
    229 TEST_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 
    243 TEST_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 
    252 TEST_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