// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <base/stl_util.h>
#include <gtest/gtest.h>
#include <ModemManager/ModemManager.h>

#include "shill/manager.h"
#include "shill/mock_control.h"
#include "shill/mock_dbus_objectmanager_proxy.h"
#include "shill/mock_glib.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_modem.h"
#include "shill/mock_modem_manager_proxy.h"
#include "shill/modem.h"
#include "shill/modem_manager.h"
#include "shill/proxy_factory.h"

using std::string;
using std::tr1::shared_ptr;
using std::vector;
using testing::_;
using testing::Invoke;
using testing::Pointee;
using testing::Return;
using testing::StrEq;
using testing::Test;

namespace shill {

// A testing subclass of ModemManager.
class ModemManagerCore : public ModemManager {
 public:
  ModemManagerCore(const string &service,
                   const string &path,
                   ControlInterface *control_interface,
                   EventDispatcher *dispatcher,
                   Metrics *metrics,
                   Manager *manager,
                   GLib *glib,
                   CellularOperatorInfo *cellular_operator_info,
                   mobile_provider_db *provider_db)
      : ModemManager(service,
                     path,
                     control_interface,
                     dispatcher,
                     metrics,
                     manager,
                     glib,
                     cellular_operator_info,
                     provider_db) {}

  virtual ~ModemManagerCore() {}

  MOCK_METHOD1(Connect, void(const string &owner));
  MOCK_METHOD0(Disconnect, void());
};

class ModemManagerTest : public Test {
 public:
  ModemManagerTest()
      : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_) {
  }

  virtual void SetUp() {
    modem_.reset(new StrictModem(
        kOwner, kService, kModemPath, &control_interface_, &dispatcher_,
        &metrics_, &manager_, static_cast<CellularOperatorInfo *>(NULL),
        static_cast<mobile_provider_db *>(NULL)));
  }

 protected:
  static const char kService[];
  static const char kPath[];
  static const char kOwner[];
  static const char kModemPath[];

  shared_ptr<StrictModem> modem_;

  MockGLib glib_;
  MockControl control_interface_;
  EventDispatcher dispatcher_;
  MockMetrics metrics_;
  MockManager manager_;
};

const char ModemManagerTest::kService[] = "org.chromium.ModemManager";
const char ModemManagerTest::kPath[] = "/org/chromium/ModemManager";
const char ModemManagerTest::kOwner[] = ":1.17";
const char ModemManagerTest::kModemPath[] = "/org/blah/Modem/blah/0";

class ModemManagerCoreTest : public ModemManagerTest {
 public:
  ModemManagerCoreTest()
      : ModemManagerTest(),
        modem_manager_(kService,
                       kPath,
                       &control_interface_,
                       &dispatcher_,
                       &metrics_,
                       &manager_,
                       &glib_,
                       NULL,
                       NULL) {}

  virtual void TearDown() {
    modem_manager_.watcher_id_ = 0;
  }

 protected:
  ModemManagerCore modem_manager_;
};

TEST_F(ModemManagerCoreTest, Start) {
  const int kWatcher = 123;
  EXPECT_CALL(glib_, BusWatchName(G_BUS_TYPE_SYSTEM,
                                  StrEq(kService),
                                  G_BUS_NAME_WATCHER_FLAGS_NONE,
                                  ModemManager::OnAppear,
                                  ModemManager::OnVanish,
                                  &modem_manager_,
                                  NULL))
      .WillOnce(Return(kWatcher));
  EXPECT_EQ(0, modem_manager_.watcher_id_);
  modem_manager_.Start();
  EXPECT_EQ(kWatcher, modem_manager_.watcher_id_);
}

TEST_F(ModemManagerCoreTest, Stop) {
  const int kWatcher = 345;
  modem_manager_.watcher_id_ = kWatcher;
  modem_manager_.owner_ = kOwner;
  EXPECT_CALL(glib_, BusUnwatchName(kWatcher)).Times(1);
  EXPECT_CALL(modem_manager_, Disconnect());
  modem_manager_.Stop();
}

TEST_F(ModemManagerCoreTest, OnAppearVanish) {
  EXPECT_EQ("", modem_manager_.owner_);
  EXPECT_CALL(modem_manager_, Connect(kOwner));
  EXPECT_CALL(modem_manager_, Disconnect());
  ModemManager::OnAppear(NULL, kService, kOwner, &modem_manager_);
  ModemManager::OnVanish(NULL, kService, &modem_manager_);
}

TEST_F(ModemManagerCoreTest, Connect) {
  EXPECT_EQ("", modem_manager_.owner_);
  modem_manager_.ModemManager::Connect(kOwner);
  EXPECT_EQ(kOwner, modem_manager_.owner_);
}

TEST_F(ModemManagerCoreTest, Disconnect) {
  modem_manager_.owner_ = kOwner;
  modem_manager_.RecordAddedModem(modem_);
  EXPECT_EQ(1, modem_manager_.modems_.size());

  modem_manager_.ModemManager::Disconnect();
  EXPECT_EQ("", modem_manager_.owner_);
  EXPECT_EQ(0, modem_manager_.modems_.size());
}

TEST_F(ModemManagerCoreTest, ModemExists) {
  modem_manager_.owner_ = kOwner;

  EXPECT_FALSE(modem_manager_.ModemExists(kModemPath));
  modem_manager_.RecordAddedModem(modem_);
  EXPECT_TRUE(modem_manager_.ModemExists(kModemPath));
}

class ModemManagerClassicMockInit : public ModemManagerClassic {
 public:
  ModemManagerClassicMockInit(const string &service,
                              const string &path,
                              ControlInterface *control_interface,
                              EventDispatcher *dispatcher,
                              Metrics *metrics,
                              Manager *manager,
                              GLib *glib,
                              CellularOperatorInfo *cellular_operator_info,
                              mobile_provider_db *provider_db) :
      ModemManagerClassic(service,
                          path,
                          control_interface,
                          dispatcher,
                          metrics,
                          manager,
                          glib,
                          cellular_operator_info,
                          provider_db) {}
  MOCK_METHOD1(InitModemClassic, void(shared_ptr<ModemClassic>));
};

class ModemManagerClassicTest : public ModemManagerTest {
 public:
  ModemManagerClassicTest()
      : ModemManagerTest(),
        modem_manager_(kService,
                       kPath,
                       &control_interface_,
                       &dispatcher_,
                       &metrics_,
                       &manager_,
                       &glib_,
                       NULL,
                       NULL),
        proxy_(new MockModemManagerProxy()),
        proxy_factory_(this) {
  }

 protected:
  class TestProxyFactory : public ProxyFactory {
   public:
    explicit TestProxyFactory(ModemManagerClassicTest *test) : test_(test) {}

    virtual ModemManagerProxyInterface *CreateModemManagerProxy(
        ModemManagerClassic */*manager*/,
        const string &/*path*/,
        const string &/*service*/) {
      return test_->proxy_.release();
    }

   private:
    ModemManagerClassicTest *test_;
  };

  virtual void SetUp() {
    modem_manager_.proxy_factory_ = &proxy_factory_;
  }

  virtual void TearDown() {
    modem_manager_.proxy_factory_ = NULL;
  }

  ModemManagerClassicMockInit modem_manager_;
  scoped_ptr<MockModemManagerProxy> proxy_;
  TestProxyFactory proxy_factory_;
};

TEST_F(ModemManagerClassicTest, Connect) {
  EXPECT_EQ("", modem_manager_.owner_);

  EXPECT_CALL(*proxy_, EnumerateDevices())
      .WillOnce(Return(vector<DBus::Path>(1, kModemPath)));

  EXPECT_CALL(modem_manager_,
              InitModemClassic(
                  Pointee(Field(&Modem::path_, StrEq(kModemPath)))));

  modem_manager_.Connect(kOwner);
  EXPECT_EQ(kOwner, modem_manager_.owner_);
  EXPECT_EQ(1, modem_manager_.modems_.size());
  ASSERT_TRUE(ContainsKey(modem_manager_.modems_, kModemPath));
}


class ModemManager1MockInit : public ModemManager1 {
 public:
  ModemManager1MockInit(const string &service,
                        const string &path,
                        ControlInterface *control_interface,
                        EventDispatcher *dispatcher,
                        Metrics *metrics,
                        Manager *manager,
                        GLib *glib,
                        CellularOperatorInfo *cellular_operator_info,
                        mobile_provider_db *provider_db) :
      ModemManager1(service,
                    path,
                    control_interface,
                    dispatcher,
                    metrics,
                    manager,
                    glib,
                    cellular_operator_info,
                    provider_db) {}
  MOCK_METHOD2(InitModem1, void(shared_ptr<Modem1>,
                                const DBusInterfaceToProperties &));
};


class ModemManager1Test : public ModemManagerTest {
 public:
  ModemManager1Test()
      : ModemManagerTest(),
        modem_manager_(kService,
                       kPath,
                       &control_interface_,
                       &dispatcher_,
                       &metrics_,
                       &manager_,
                       &glib_,
                       NULL,
                       NULL),
        proxy_(new MockDBusObjectManagerProxy()),
        proxy_factory_(this) {
  }

 protected:
  class TestProxyFactory : public ProxyFactory {
   public:
    explicit TestProxyFactory(ModemManager1Test *test) : test_(test) {}

    virtual DBusObjectManagerProxyInterface *CreateDBusObjectManagerProxy(
        const string &/*path*/,
        const string &/*service*/) {
      return test_->proxy_.release();
    }

   private:
    ModemManager1Test *test_;
  };

  virtual void SetUp() {
    modem_manager_.proxy_factory_ = &proxy_factory_;
    proxy_->IgnoreSetCallbacks();
  }

  virtual void TearDown() {
    modem_manager_.proxy_factory_ = NULL;
  }

  static DBusObjectsWithProperties GetModemWithProperties() {
    DBusPropertiesMap o_fd_mm1_modem;

    DBusInterfaceToProperties properties;
    properties[MM_DBUS_INTERFACE_MODEM] = o_fd_mm1_modem;

    DBusObjectsWithProperties objects_with_properties;
    objects_with_properties[kModemPath] = properties;

    return objects_with_properties;
  }

  ModemManager1MockInit modem_manager_;
  scoped_ptr<MockDBusObjectManagerProxy> proxy_;
  TestProxyFactory proxy_factory_;
};

TEST_F(ModemManager1Test, Connect) {
  Error e;

  EXPECT_CALL(*proxy_, GetManagedObjects(_, _, _));
  EXPECT_CALL(modem_manager_,
              InitModem1(
                  Pointee(Field(&Modem::path_, StrEq(kModemPath))),
                  _));

  modem_manager_.Connect(kOwner);
  modem_manager_.OnGetManagedObjectsReply(GetModemWithProperties(), e);
  EXPECT_EQ(1, modem_manager_.modems_.size());
  EXPECT_TRUE(ContainsKey(modem_manager_.modems_, kModemPath));
}


TEST_F(ModemManager1Test, AddRemoveInterfaces) {
  EXPECT_CALL(*proxy_, GetManagedObjects(_, _, _));
  modem_manager_.Connect(kOwner);

  // Have nothing come back from GetManagedObjects
  modem_manager_.OnGetManagedObjectsReply(DBusObjectsWithProperties(), Error());
  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,
                                         DBusInterfaceToProperties());
  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
