root/chrome/browser/chromeos/mobile/mobile_activator_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. InvokeChangeState
  2. mobile_activator_
  3. SetUp
  4. TearDown
  5. set_activator_state
  6. set_network_activation_state
  7. set_connection_state
  8. TEST_F
  9. FakeRequestCellularActivationSuccess
  10. FakeRequestCellularActivationFailure
  11. TEST_F
  12. TEST_F
  13. TEST_F

// Copyright (c) 2012 The Chromium 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 "chrome/browser/chromeos/mobile/mobile_activator.h"

#include "base/message_loop/message_loop.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_state.h"
#include "content/public/browser/browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

using std::string;

using content::BrowserThread;
using testing::_;
using testing::Eq;
using testing::Invoke;
using testing::Return;

namespace {

const char kTestServicePath[] = "/a/service/path";

const size_t kNumOTASPStates = 3;

chromeos::MobileActivator::PlanActivationState kOTASPStates[kNumOTASPStates] = {
  chromeos::MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
  chromeos::MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
  chromeos::MobileActivator::PLAN_ACTIVATION_OTASP,
};

}  // namespace
namespace chromeos {

class TestMobileActivator : public MobileActivator {
 public:
  explicit TestMobileActivator(NetworkState* cellular_network) :
        cellular_network_(cellular_network) {
    // Provide reasonable defaults for basic things we're usually not testing.
    ON_CALL(*this, DCheckOnThread(_))
        .WillByDefault(Return());
    ON_CALL(*this, GetNetworkState(_))
        .WillByDefault(Return(cellular_network_));
  }
  virtual ~TestMobileActivator() {}

  MOCK_METHOD3(RequestCellularActivation,
               void(const NetworkState*,
                    const base::Closure&,
                    const network_handler::ErrorCallback&));
  MOCK_METHOD3(ChangeState, void(const NetworkState*,
                                 MobileActivator::PlanActivationState,
                                 std::string));
  MOCK_METHOD1(GetNetworkState, const NetworkState*(const std::string&));
  MOCK_METHOD1(EvaluateCellularNetwork, void(const NetworkState*));
  MOCK_METHOD0(SignalCellularPlanPayment, void(void));
  MOCK_METHOD0(StartOTASPTimer, void(void));
  MOCK_CONST_METHOD0(HasRecentCellularPlanPayment, bool(void));

  void InvokeChangeState(const NetworkState* network,
                         MobileActivator::PlanActivationState new_state,
                         std::string error_description) {
    MobileActivator::ChangeState(network, new_state, error_description);
  }

 private:
  MOCK_CONST_METHOD1(DCheckOnThread, void(const BrowserThread::ID id));

  NetworkState* cellular_network_;

  DISALLOW_COPY_AND_ASSIGN(TestMobileActivator);
};

class MobileActivatorTest : public testing::Test {
 public:
  MobileActivatorTest()
      : cellular_network_(string(kTestServicePath)),
        mobile_activator_(&cellular_network_) {
  }
  virtual ~MobileActivatorTest() {}

 protected:
  virtual void SetUp() {
    DBusThreadManager::InitializeWithStub();
    NetworkHandler::Initialize();
  }
  virtual void TearDown() {
    NetworkHandler::Shutdown();
    DBusThreadManager::Shutdown();
  }

  void set_activator_state(const MobileActivator::PlanActivationState state) {
    mobile_activator_.state_ = state;
  }
  void set_network_activation_state(const std::string& activation_state) {
    cellular_network_.activation_state_ = activation_state;
  }
  void set_connection_state(const std::string& state) {
    cellular_network_.connection_state_ = state;
  }

  base::MessageLoop message_loop_;
  NetworkState cellular_network_;
  TestMobileActivator mobile_activator_;
 private:
  DISALLOW_COPY_AND_ASSIGN(MobileActivatorTest);
};

TEST_F(MobileActivatorTest, BasicFlowForNewDevices) {
  // In a new device, we aren't connected to Verizon, we start at START
  // because we haven't paid Verizon (ever), and the modem isn't even partially
  // activated.
  std::string error_description;
  set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
  set_connection_state(shill::kStateIdle);
  set_network_activation_state(shill::kActivationStateNotActivated);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  // Now behave as if ChangeState() has initiated an activation.
  set_activator_state(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION);
  set_network_activation_state(shill::kActivationStateActivating);
  // We'll sit in this state while we wait for the OTASP to finish.
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  set_network_activation_state(shill::kActivationStatePartiallyActivated);
  // We'll sit in this state until we go online as well.
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  set_connection_state(shill::kStatePortal);
  // After we go online, we go back to START, which acts as a jumping off
  // point for the two types of initial OTASP.
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_START,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  // Very similar things happen while we're trying OTASP.
  set_activator_state(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP);
  set_network_activation_state(shill::kActivationStateActivating);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  set_network_activation_state(shill::kActivationStatePartiallyActivated);
  set_connection_state(shill::kStatePortal);
  // And when we come back online again and aren't activating, load the portal.
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  // The JS drives us through the payment portal.
  set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
  // The JS also calls us to signal that the portal is done.  This triggers us
  // to start our final OTASP via the aptly named StartOTASP().
  EXPECT_CALL(mobile_activator_, SignalCellularPlanPayment());
  EXPECT_CALL(mobile_activator_,
              ChangeState(Eq(&cellular_network_),
                          Eq(MobileActivator::PLAN_ACTIVATION_START_OTASP),
                          _));
  EXPECT_CALL(mobile_activator_,
              EvaluateCellularNetwork(Eq(&cellular_network_)));
  mobile_activator_.HandleSetTransactionStatus(true);
  // Evaluate state will defer to PickNextState to select what to do now that
  // we're in START_ACTIVATION.  PickNextState should decide to start a final
  // OTASP.
  set_activator_state(MobileActivator::PLAN_ACTIVATION_START_OTASP);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  // Similarly to TRYING_OTASP and INITIATING_OTASP above...
  set_activator_state(MobileActivator::PLAN_ACTIVATION_OTASP);
  set_network_activation_state(shill::kActivationStateActivating);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  set_network_activation_state(shill::kActivationStateActivated);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_DONE,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
}

// A fake for MobileActivator::RequestCellularActivation that always succeeds.
void FakeRequestCellularActivationSuccess(
    const NetworkState* network,
    const base::Closure& success_callback,
    const network_handler::ErrorCallback& error_callback) {
  success_callback.Run();
}

// A fake for MobileActivator::RequestCellularActivation that always fails.
void FakeRequestCellularActivationFailure(
    const NetworkState* network,
    const base::Closure& success_callback,
    const network_handler::ErrorCallback& error_callback) {
  scoped_ptr<base::DictionaryValue> value;
  error_callback.Run("", value.Pass());
}

TEST_F(MobileActivatorTest, OTASPScheduling) {
  const std::string error;
  for (size_t i = 0; i < kNumOTASPStates; ++i) {
    // When activation works, we start a timer to watch for success.
    EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
        .Times(1)
        .WillOnce(Invoke(FakeRequestCellularActivationSuccess));
    EXPECT_CALL(mobile_activator_, StartOTASPTimer())
         .Times(1);
    set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    mobile_activator_.InvokeChangeState(&cellular_network_,
                                        kOTASPStates[i],
                                        error);

    // When activation fails, it's an error, unless we're trying for the final
    // OTASP, in which case we try again via DELAY_OTASP.
    EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
        .Times(1)
        .WillOnce(Invoke(FakeRequestCellularActivationFailure));
    if (kOTASPStates[i] == MobileActivator::PLAN_ACTIVATION_OTASP) {
      EXPECT_CALL(mobile_activator_, ChangeState(
          Eq(&cellular_network_),
          Eq(MobileActivator::PLAN_ACTIVATION_DELAY_OTASP),
          _));
    } else {
      EXPECT_CALL(mobile_activator_, ChangeState(
          Eq(&cellular_network_),
          Eq(MobileActivator::PLAN_ACTIVATION_ERROR),
          _));
    }
    set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
    mobile_activator_.InvokeChangeState(&cellular_network_,
                                        kOTASPStates[i],
                                        error);
  }
}

TEST_F(MobileActivatorTest, ReconnectOnDisconnectFromPaymentPortal) {
  // Most states either don't care if we're offline or expect to be offline at
  // some point.  For instance the OTASP states expect to go offline during
  // activation and eventually come back.  There are a few transitions states
  // like START_OTASP and DELAY_OTASP which don't really depend on the state of
  // the modem (offline or online) to work correctly.  A few places however,
  // like when we're displaying the portal care quite a bit about going
  // offline.  Lets test for those cases.
  std::string error_description;
  set_connection_state(shill::kStateFailure);
  set_network_activation_state(shill::kActivationStatePartiallyActivated);
  set_activator_state(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
  set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
            mobile_activator_.PickNextState(&cellular_network_,
                                            &error_description));
}

TEST_F(MobileActivatorTest, StartAtStart) {
  EXPECT_CALL(mobile_activator_, HasRecentCellularPlanPayment())
      .WillOnce(Return(false));
  EXPECT_CALL(mobile_activator_,
              EvaluateCellularNetwork(Eq(&cellular_network_)));
  mobile_activator_.StartActivation();
  EXPECT_EQ(mobile_activator_.state(), MobileActivator::PLAN_ACTIVATION_START);
}

}  // namespace chromeos

/* [<][>][^][v][top][bottom][index][help] */