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