mobile_activator_unittest.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/mobile/mobile_activator.h"
6
7#include "base/message_loop/message_loop.h"
8#include "chromeos/dbus/dbus_thread_manager.h"
9#include "chromeos/network/network_handler.h"
10#include "chromeos/network/network_state.h"
11#include "content/public/browser/browser_thread.h"
12#include "testing/gmock/include/gmock/gmock.h"
13#include "testing/gtest/include/gtest/gtest.h"
14#include "third_party/cros_system_api/dbus/service_constants.h"
15
16using std::string;
17
18using content::BrowserThread;
19using testing::_;
20using testing::Eq;
21using testing::Invoke;
22using testing::Return;
23
24namespace {
25
26const char kTestServicePath[] = "/a/service/path";
27
28const size_t kNumOTASPStates = 3;
29
30chromeos::MobileActivator::PlanActivationState kOTASPStates[kNumOTASPStates] = {
31  chromeos::MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
32  chromeos::MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
33  chromeos::MobileActivator::PLAN_ACTIVATION_OTASP,
34};
35
36}  // namespace
37namespace chromeos {
38
39class TestMobileActivator : public MobileActivator {
40 public:
41  explicit TestMobileActivator(NetworkState* cellular_network) :
42        cellular_network_(cellular_network) {
43    // Provide reasonable defaults for basic things we're usually not testing.
44    ON_CALL(*this, DCheckOnThread(_))
45        .WillByDefault(Return());
46    ON_CALL(*this, GetNetworkState(_))
47        .WillByDefault(Return(cellular_network_));
48  }
49  virtual ~TestMobileActivator() {}
50
51  MOCK_METHOD3(RequestCellularActivation,
52               void(const NetworkState*,
53                    const base::Closure&,
54                    const network_handler::ErrorCallback&));
55  MOCK_METHOD3(ChangeState, void(const NetworkState*,
56                                 MobileActivator::PlanActivationState,
57                                 const std::string&));
58  MOCK_METHOD1(GetNetworkState, const NetworkState*(const std::string&));
59  MOCK_METHOD1(EvaluateCellularNetwork, void(const NetworkState*));
60  MOCK_METHOD0(SignalCellularPlanPayment, void(void));
61  MOCK_METHOD0(StartOTASPTimer, void(void));
62  MOCK_CONST_METHOD0(HasRecentCellularPlanPayment, bool(void));
63
64  void InvokeChangeState(const NetworkState* network,
65                         MobileActivator::PlanActivationState new_state,
66                         const std::string& error_description) {
67    MobileActivator::ChangeState(network, new_state, error_description);
68  }
69
70 private:
71  MOCK_CONST_METHOD1(DCheckOnThread, void(const BrowserThread::ID id));
72
73  NetworkState* cellular_network_;
74
75  DISALLOW_COPY_AND_ASSIGN(TestMobileActivator);
76};
77
78class MobileActivatorTest : public testing::Test {
79 public:
80  MobileActivatorTest()
81      : cellular_network_(string(kTestServicePath)),
82        mobile_activator_(&cellular_network_) {
83  }
84  virtual ~MobileActivatorTest() {}
85
86 protected:
87  virtual void SetUp() {
88    DBusThreadManager::InitializeWithStub();
89    NetworkHandler::Initialize();
90  }
91  virtual void TearDown() {
92    NetworkHandler::Shutdown();
93    DBusThreadManager::Shutdown();
94  }
95
96  void set_activator_state(const MobileActivator::PlanActivationState state) {
97    mobile_activator_.state_ = state;
98  }
99  void set_network_activation_state(const std::string& activation_state) {
100    cellular_network_.activation_state_ = activation_state;
101  }
102  void set_connection_state(const std::string& state) {
103    cellular_network_.connection_state_ = state;
104  }
105
106  base::MessageLoop message_loop_;
107  NetworkState cellular_network_;
108  TestMobileActivator mobile_activator_;
109 private:
110  DISALLOW_COPY_AND_ASSIGN(MobileActivatorTest);
111};
112
113TEST_F(MobileActivatorTest, BasicFlowForNewDevices) {
114  // In a new device, we aren't connected to Verizon, we start at START
115  // because we haven't paid Verizon (ever), and the modem isn't even partially
116  // activated.
117  std::string error_description;
118  set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
119  set_connection_state(shill::kStateIdle);
120  set_network_activation_state(shill::kActivationStateNotActivated);
121  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
122            mobile_activator_.PickNextState(&cellular_network_,
123                                            &error_description));
124  // Now behave as if ChangeState() has initiated an activation.
125  set_activator_state(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION);
126  set_network_activation_state(shill::kActivationStateActivating);
127  // We'll sit in this state while we wait for the OTASP to finish.
128  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
129            mobile_activator_.PickNextState(&cellular_network_,
130                                            &error_description));
131  set_network_activation_state(shill::kActivationStatePartiallyActivated);
132  // We'll sit in this state until we go online as well.
133  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_INITIATING_ACTIVATION,
134            mobile_activator_.PickNextState(&cellular_network_,
135                                            &error_description));
136  set_connection_state(shill::kStatePortal);
137  // After we go online, we go back to START, which acts as a jumping off
138  // point for the two types of initial OTASP.
139  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_START,
140            mobile_activator_.PickNextState(&cellular_network_,
141                                            &error_description));
142  set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
143  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
144            mobile_activator_.PickNextState(&cellular_network_,
145                                            &error_description));
146  // Very similar things happen while we're trying OTASP.
147  set_activator_state(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP);
148  set_network_activation_state(shill::kActivationStateActivating);
149  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_TRYING_OTASP,
150            mobile_activator_.PickNextState(&cellular_network_,
151                                            &error_description));
152  set_network_activation_state(shill::kActivationStatePartiallyActivated);
153  set_connection_state(shill::kStatePortal);
154  // And when we come back online again and aren't activating, load the portal.
155  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING,
156            mobile_activator_.PickNextState(&cellular_network_,
157                                            &error_description));
158  // The JS drives us through the payment portal.
159  set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
160  // The JS also calls us to signal that the portal is done.  This triggers us
161  // to start our final OTASP via the aptly named StartOTASP().
162  EXPECT_CALL(mobile_activator_, SignalCellularPlanPayment());
163  EXPECT_CALL(mobile_activator_,
164              ChangeState(Eq(&cellular_network_),
165                          Eq(MobileActivator::PLAN_ACTIVATION_START_OTASP),
166                          _));
167  EXPECT_CALL(mobile_activator_,
168              EvaluateCellularNetwork(Eq(&cellular_network_)));
169  mobile_activator_.HandleSetTransactionStatus(true);
170  // Evaluate state will defer to PickNextState to select what to do now that
171  // we're in START_ACTIVATION.  PickNextState should decide to start a final
172  // OTASP.
173  set_activator_state(MobileActivator::PLAN_ACTIVATION_START_OTASP);
174  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
175            mobile_activator_.PickNextState(&cellular_network_,
176                                            &error_description));
177  // Similarly to TRYING_OTASP and INITIATING_OTASP above...
178  set_activator_state(MobileActivator::PLAN_ACTIVATION_OTASP);
179  set_network_activation_state(shill::kActivationStateActivating);
180  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_OTASP,
181            mobile_activator_.PickNextState(&cellular_network_,
182                                            &error_description));
183  set_network_activation_state(shill::kActivationStateActivated);
184  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_DONE,
185            mobile_activator_.PickNextState(&cellular_network_,
186                                            &error_description));
187}
188
189// A fake for MobileActivator::RequestCellularActivation that always succeeds.
190void FakeRequestCellularActivationSuccess(
191    const NetworkState* network,
192    const base::Closure& success_callback,
193    const network_handler::ErrorCallback& error_callback) {
194  success_callback.Run();
195}
196
197// A fake for MobileActivator::RequestCellularActivation that always fails.
198void FakeRequestCellularActivationFailure(
199    const NetworkState* network,
200    const base::Closure& success_callback,
201    const network_handler::ErrorCallback& error_callback) {
202  scoped_ptr<base::DictionaryValue> value;
203  error_callback.Run("", value.Pass());
204}
205
206TEST_F(MobileActivatorTest, OTASPScheduling) {
207  const std::string error;
208  for (size_t i = 0; i < kNumOTASPStates; ++i) {
209    // When activation works, we start a timer to watch for success.
210    EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
211        .Times(1)
212        .WillOnce(Invoke(FakeRequestCellularActivationSuccess));
213    EXPECT_CALL(mobile_activator_, StartOTASPTimer())
214         .Times(1);
215    set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
216    mobile_activator_.InvokeChangeState(&cellular_network_,
217                                        kOTASPStates[i],
218                                        error);
219
220    // When activation fails, it's an error, unless we're trying for the final
221    // OTASP, in which case we try again via DELAY_OTASP.
222    EXPECT_CALL(mobile_activator_, RequestCellularActivation(_, _, _))
223        .Times(1)
224        .WillOnce(Invoke(FakeRequestCellularActivationFailure));
225    if (kOTASPStates[i] == MobileActivator::PLAN_ACTIVATION_OTASP) {
226      EXPECT_CALL(mobile_activator_, ChangeState(
227          Eq(&cellular_network_),
228          Eq(MobileActivator::PLAN_ACTIVATION_DELAY_OTASP),
229          _));
230    } else {
231      EXPECT_CALL(mobile_activator_, ChangeState(
232          Eq(&cellular_network_),
233          Eq(MobileActivator::PLAN_ACTIVATION_ERROR),
234          _));
235    }
236    set_activator_state(MobileActivator::PLAN_ACTIVATION_START);
237    mobile_activator_.InvokeChangeState(&cellular_network_,
238                                        kOTASPStates[i],
239                                        error);
240  }
241}
242
243TEST_F(MobileActivatorTest, ReconnectOnDisconnectFromPaymentPortal) {
244  // Most states either don't care if we're offline or expect to be offline at
245  // some point.  For instance the OTASP states expect to go offline during
246  // activation and eventually come back.  There are a few transitions states
247  // like START_OTASP and DELAY_OTASP which don't really depend on the state of
248  // the modem (offline or online) to work correctly.  A few places however,
249  // like when we're displaying the portal care quite a bit about going
250  // offline.  Lets test for those cases.
251  std::string error_description;
252  set_connection_state(shill::kStateFailure);
253  set_network_activation_state(shill::kActivationStatePartiallyActivated);
254  set_activator_state(MobileActivator::PLAN_ACTIVATION_PAYMENT_PORTAL_LOADING);
255  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
256            mobile_activator_.PickNextState(&cellular_network_,
257                                            &error_description));
258  set_activator_state(MobileActivator::PLAN_ACTIVATION_SHOWING_PAYMENT);
259  EXPECT_EQ(MobileActivator::PLAN_ACTIVATION_RECONNECTING,
260            mobile_activator_.PickNextState(&cellular_network_,
261                                            &error_description));
262}
263
264TEST_F(MobileActivatorTest, StartAtStart) {
265  EXPECT_CALL(mobile_activator_, HasRecentCellularPlanPayment())
266      .WillOnce(Return(false));
267  EXPECT_CALL(mobile_activator_,
268              EvaluateCellularNetwork(Eq(&cellular_network_)));
269  mobile_activator_.StartActivation();
270  EXPECT_EQ(mobile_activator_.state(), MobileActivator::PLAN_ACTIVATION_START);
271}
272
273}  // namespace chromeos
274