blob: 4cce549173e8d0d16657875ada871ccfb49d6c03 [file] [log] [blame]
Jason Glasgowef965562012-04-10 16:12:35 -04001// Copyright (c) 2012 The Chromium OS 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 "shill/cellular_capability_universal.h"
6
Nathan Williams4b7c2a82012-04-13 15:19:47 -04007#include <string>
8#include <vector>
9
Jason Glasgowef965562012-04-10 16:12:35 -040010#include <base/bind.h>
11#include <chromeos/dbus/service_constants.h>
12#include <gtest/gtest.h>
13#include <mobile_provider.h>
Jason Glasgowaf583282012-04-18 15:18:22 -040014#include <mm/ModemManager-names.h>
Jason Glasgowef965562012-04-10 16:12:35 -040015
16#include "shill/cellular.h"
17#include "shill/cellular_service.h"
Jason Glasgowaf583282012-04-18 15:18:22 -040018#include "shill/dbus_adaptor.h"
Jason Glasgowef965562012-04-10 16:12:35 -040019#include "shill/error.h"
20#include "shill/event_dispatcher.h"
21#include "shill/mock_adaptors.h"
Jason Glasgowaf583282012-04-18 15:18:22 -040022#include "shill/mock_dbus_properties_proxy.h"
Jason Glasgowef965562012-04-10 16:12:35 -040023#include "shill/mock_glib.h"
24#include "shill/mock_manager.h"
25#include "shill/mock_metrics.h"
26#include "shill/mock_mm1_modem_modem3gpp_proxy.h"
27#include "shill/mock_mm1_modem_modemcdma_proxy.h"
28#include "shill/mock_mm1_modem_proxy.h"
29#include "shill/mock_mm1_modem_simple_proxy.h"
30#include "shill/mock_mm1_sim_proxy.h"
31#include "shill/mock_profile.h"
32#include "shill/mock_rtnl_handler.h"
33#include "shill/nice_mock_control.h"
34#include "shill/proxy_factory.h"
35
36using base::Bind;
37using base::Unretained;
38using std::string;
Nathan Williams4b7c2a82012-04-13 15:19:47 -040039using std::vector;
Jason Glasgowef965562012-04-10 16:12:35 -040040using testing::InSequence;
41using testing::NiceMock;
42using testing::Return;
43using testing::_;
44
45namespace shill {
46
47MATCHER(IsSuccess, "") {
48 return arg.IsSuccess();
49}
50MATCHER(IsFailure, "") {
51 return arg.IsFailure();
52}
53
54class CellularCapabilityUniversalTest : public testing::Test {
55 public:
56 CellularCapabilityUniversalTest()
57 : manager_(&control_, &dispatcher_, &metrics_, &glib_),
58 cellular_(new Cellular(&control_,
59 &dispatcher_,
60 NULL,
61 &manager_,
62 "",
63 "",
64 0,
65 Cellular::kTypeUniversal,
66 "",
67 "",
68 NULL)),
69 modem_3gpp_proxy_(new mm1::MockModemModem3gppProxy()),
70 modem_cdma_proxy_(new mm1::MockModemModemCdmaProxy()),
71 modem_proxy_(new mm1::MockModemProxy()),
72 modem_simple_proxy_(new mm1::MockModemSimpleProxy()),
73 sim_proxy_(new mm1::MockSimProxy()),
Jason Glasgowaf583282012-04-18 15:18:22 -040074 properties_proxy_(new MockDBusPropertiesProxy()),
Jason Glasgowef965562012-04-10 16:12:35 -040075 proxy_factory_(this),
76 capability_(NULL),
77 device_adaptor_(NULL) {}
78
79 virtual ~CellularCapabilityUniversalTest() {
80 cellular_->service_ = NULL;
81 capability_ = NULL;
82 device_adaptor_ = NULL;
83 }
84
85 virtual void SetUp() {
86 capability_ = dynamic_cast<CellularCapabilityUniversal *>(
87 cellular_->capability_.get());
88 capability_->proxy_factory_ = &proxy_factory_;
89 device_adaptor_ =
90 dynamic_cast<NiceMock<DeviceMockAdaptor> *>(cellular_->adaptor());
91 }
92
93 virtual void TearDown() {
94 capability_->proxy_factory_ = NULL;
95 }
96
Jason Glasgow4380f0d2012-05-03 18:05:04 -040097 void InitProviderDB() {
98 const char kTestMobileProviderDBPath[] = "provider_db_unittest.bfd";
99
100 provider_db_ = mobile_provider_open_db(kTestMobileProviderDBPath);
101 ASSERT_TRUE(provider_db_);
102 cellular_->provider_db_ = provider_db_;
103 }
104
Jason Glasgowef965562012-04-10 16:12:35 -0400105 void InvokeEnable(bool enable, Error *error,
106 const ResultCallback &callback, int timeout) {
107 callback.Run(Error());
108 }
109 void InvokeEnableFail(bool enable, Error *error,
110 const ResultCallback &callback, int timeout) {
111 callback.Run(Error(Error::kOperationFailed));
112 }
Jason Glasgowaf583282012-04-18 15:18:22 -0400113 void InvokeRegister(const string &operator_id, Error *error,
114 const ResultCallback &callback, int timeout) {
115 callback.Run(Error());
116 }
117
Jason Glasgowef965562012-04-10 16:12:35 -0400118
Gary Morainceba6aa2012-05-03 10:28:26 -0700119 void InvokeScan(Error *error, const DBusPropertyMapsCallback &callback,
120 int timeout) {
121 callback.Run(CellularCapabilityUniversal::ScanResults(), Error());
122 }
123
124 void Set3gppProxy() {
125 capability_->modem_3gpp_proxy_.reset(modem_3gpp_proxy_.release());
126 }
127
Jason Glasgowef965562012-04-10 16:12:35 -0400128 MOCK_METHOD1(TestCallback, void(const Error &error));
129
130 protected:
131 static const char kImei[];
Jason Glasgowaf583282012-04-18 15:18:22 -0400132 static const char kSimPath[];
133 static const uint32 kAccessTechnologies;
Jason Glasgowef965562012-04-10 16:12:35 -0400134
135 class TestProxyFactory : public ProxyFactory {
136 public:
137 explicit TestProxyFactory(CellularCapabilityUniversalTest *test) :
138 test_(test) {}
139
140 virtual mm1::ModemModem3gppProxyInterface *CreateMM1ModemModem3gppProxy(
141 const std::string &/* path */,
142 const std::string &/* service */) {
143 return test_->modem_3gpp_proxy_.release();
144 }
145
146 virtual mm1::ModemModemCdmaProxyInterface *CreateMM1ModemModemCdmaProxy(
147 const std::string &/* path */,
148 const std::string &/* service */) {
149 return test_->modem_cdma_proxy_.release();
150 }
151
152 virtual mm1::ModemProxyInterface *CreateMM1ModemProxy(
153 const std::string &/* path */,
154 const std::string &/* service */) {
155 return test_->modem_proxy_.release();
156 }
157
158 virtual mm1::ModemSimpleProxyInterface *CreateMM1ModemSimpleProxy(
159 const std::string &/* path */,
160 const std::string &/* service */) {
161 return test_->modem_simple_proxy_.release();
162 }
163
164 virtual mm1::SimProxyInterface *CreateSimProxy(
165 const std::string &/* path */,
166 const std::string &/* service */) {
167 return test_->sim_proxy_.release();
168 }
Jason Glasgowaf583282012-04-18 15:18:22 -0400169 virtual DBusPropertiesProxyInterface *CreateDBusPropertiesProxy(
170 const std::string &/* path */,
171 const std::string &/* service */) {
172 return test_->properties_proxy_.release();
173 }
Jason Glasgowef965562012-04-10 16:12:35 -0400174
175 private:
176 CellularCapabilityUniversalTest *test_;
177 };
178
179 NiceMockControl control_;
180 EventDispatcher dispatcher_;
181 MockMetrics metrics_;
182 MockGLib glib_;
183 MockManager manager_;
184 CellularRefPtr cellular_;
185 scoped_ptr<mm1::MockModemModem3gppProxy> modem_3gpp_proxy_;
186 scoped_ptr<mm1::MockModemModemCdmaProxy> modem_cdma_proxy_;
187 scoped_ptr<mm1::MockModemProxy> modem_proxy_;
188 scoped_ptr<mm1::MockModemSimpleProxy> modem_simple_proxy_;
189 scoped_ptr<mm1::MockSimProxy> sim_proxy_;
Jason Glasgowaf583282012-04-18 15:18:22 -0400190 scoped_ptr<MockDBusPropertiesProxy> properties_proxy_;
Jason Glasgowef965562012-04-10 16:12:35 -0400191 TestProxyFactory proxy_factory_;
192 CellularCapabilityUniversal *capability_; // Owned by |cellular_|.
193 NiceMock<DeviceMockAdaptor> *device_adaptor_; // Owned by |cellular_|.
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400194 mobile_provider_db *provider_db_;
Jason Glasgowef965562012-04-10 16:12:35 -0400195};
196
197const char CellularCapabilityUniversalTest::kImei[] = "999911110000";
Jason Glasgowaf583282012-04-18 15:18:22 -0400198const char CellularCapabilityUniversalTest::kSimPath[] = "/foo/sim";
199const uint32 CellularCapabilityUniversalTest::kAccessTechnologies =
200 MM_MODEM_ACCESS_TECHNOLOGY_LTE |
201 MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS;
Jason Glasgowef965562012-04-10 16:12:35 -0400202
203TEST_F(CellularCapabilityUniversalTest, StartModem) {
Jason Glasgowaf583282012-04-18 15:18:22 -0400204 // Set up mock modem properties
205 DBusPropertiesMap modem_properties;
206 string operator_name = "TestOperator";
207 string operator_code = "001400";
208
209 modem_properties[MM_MODEM_PROPERTY_ACCESSTECHNOLOGIES].
210 writer().append_uint32(kAccessTechnologies);
211
212 ::DBus::Variant v;
213 ::DBus::MessageIter writer = v.writer();
Jason Glasgowef965562012-04-10 16:12:35 -0400214 ::DBus::Struct< uint32_t, bool > quality;
215 quality._1 = 90;
216 quality._2 = true;
Jason Glasgowaf583282012-04-18 15:18:22 -0400217 writer << quality;
218 modem_properties[MM_MODEM_PROPERTY_SIGNALQUALITY] = v;
219
220 // Set up mock modem 3gpp properties
221 DBusPropertiesMap modem3gpp_properties;
222 modem3gpp_properties[MM_MODEM_MODEM3GPP_PROPERTY_ENABLEDFACILITYLOCKS].
223 writer().append_uint32(0);
224 modem3gpp_properties[MM_MODEM_MODEM3GPP_PROPERTY_IMEI].
225 writer().append_string(kImei);
226
227 EXPECT_CALL(*modem_proxy_,
228 Enable(true, _, _, CellularCapability::kTimeoutEnable))
229 .WillOnce(Invoke(this, &CellularCapabilityUniversalTest::InvokeEnable));
230 EXPECT_CALL(*properties_proxy_,
231 GetAll(MM_DBUS_INTERFACE_MODEM))
232 .WillOnce(Return(modem_properties));
233 EXPECT_CALL(*properties_proxy_,
234 GetAll(MM_DBUS_INTERFACE_MODEM_MODEM3GPP))
235 .WillOnce(Return(modem3gpp_properties));
Jason Glasgowef965562012-04-10 16:12:35 -0400236
237 // After setup we lose pointers to the proxies, so it is hard to set
238 // expectations.
239 SetUp();
240
241 Error error;
Jason Glasgowaf583282012-04-18 15:18:22 -0400242 EXPECT_CALL(*this, TestCallback(IsSuccess()));
Jason Glasgowef965562012-04-10 16:12:35 -0400243 ResultCallback callback =
244 Bind(&CellularCapabilityUniversalTest::TestCallback, Unretained(this));
245 capability_->StartModem(&error, callback);
246 EXPECT_TRUE(error.IsSuccess());
Jason Glasgowaf583282012-04-18 15:18:22 -0400247 EXPECT_EQ(kImei, capability_->imei_);
248 EXPECT_EQ(kAccessTechnologies, capability_->access_technologies_);
Jason Glasgowef965562012-04-10 16:12:35 -0400249}
250
251TEST_F(CellularCapabilityUniversalTest, StartModemFail) {
252 EXPECT_CALL(*modem_proxy_,
253 Enable(true, _, _, CellularCapability::kTimeoutEnable))
254 .WillOnce(
255 Invoke(this, &CellularCapabilityUniversalTest::InvokeEnableFail));
256 EXPECT_CALL(*this, TestCallback(IsFailure()));
257 ResultCallback callback =
258 Bind(&CellularCapabilityUniversalTest::TestCallback, Unretained(this));
259 SetUp();
260
261 Error error;
262 capability_->StartModem(&error, callback);
263 EXPECT_TRUE(error.IsSuccess());
264}
265
Jason Glasgowaf583282012-04-18 15:18:22 -0400266TEST_F(CellularCapabilityUniversalTest, PropertiesChanged) {
267 // Set up mock modem properties
268 DBusPropertiesMap modem_properties;
269 modem_properties[MM_MODEM_PROPERTY_ACCESSTECHNOLOGIES].
270 writer().append_uint32(kAccessTechnologies);
271 modem_properties[MM_MODEM_PROPERTY_SIM].
272 writer().append_path(kSimPath);
273
274 // Set up mock modem 3gpp properties
275 DBusPropertiesMap modem3gpp_properties;
276 modem3gpp_properties[MM_MODEM_MODEM3GPP_PROPERTY_ENABLEDFACILITYLOCKS].
277 writer().append_uint32(0);
278 modem3gpp_properties[MM_MODEM_MODEM3GPP_PROPERTY_IMEI].
279 writer().append_string(kImei);
280
281 // Set up mock modem sim properties
282 DBusPropertiesMap sim_properties;
283
284 // After setup we lose pointers to the proxies, so it is hard to set
285 // expectations.
286 EXPECT_CALL(*properties_proxy_,
287 GetAll(MM_DBUS_INTERFACE_SIM))
288 .WillOnce(Return(sim_properties));
289
290 SetUp();
291
292 EXPECT_EQ("", capability_->imei_);
293 EXPECT_EQ(MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN,
294 capability_->access_technologies_);
295 EXPECT_FALSE(capability_->sim_proxy_.get());
296 capability_->OnDBusPropertiesChanged(MM_DBUS_INTERFACE_MODEM,
297 modem_properties, vector<string>());
298 EXPECT_EQ(kAccessTechnologies, capability_->access_technologies_);
299 EXPECT_EQ(kSimPath, capability_->sim_path_);
300 EXPECT_TRUE(capability_->sim_proxy_.get());
301
302 // Changing properties on wrong interface will not have an effect
303 capability_->OnDBusPropertiesChanged(MM_DBUS_INTERFACE_MODEM,
304 modem3gpp_properties,
305 vector<string>());
306 EXPECT_EQ("", capability_->imei_);
307
308 // Changing properties on the right interface gets reflected in the
309 // capabilities object
310 capability_->OnDBusPropertiesChanged(MM_DBUS_INTERFACE_MODEM_MODEM3GPP,
311 modem3gpp_properties,
312 vector<string>());
313 EXPECT_EQ(kImei, capability_->imei_);
314}
315
316TEST_F(CellularCapabilityUniversalTest, SimPropertiesChanged) {
317 // Set up mock modem properties
318 DBusPropertiesMap modem_properties;
319 modem_properties[MM_MODEM_PROPERTY_SIM].writer().append_path(kSimPath);
320
321 // Set up mock modem sim properties
322 const char kImsi[] = "310100000001";
323 DBusPropertiesMap sim_properties;
324 sim_properties[MM_SIM_PROPERTY_IMSI].writer().append_string(kImsi);
325
326 EXPECT_CALL(*properties_proxy_, GetAll(MM_DBUS_INTERFACE_SIM))
327 .WillOnce(Return(sim_properties));
328
329 // After setup we lose pointers to the proxies, so it is hard to set
330 // expectations.
331 SetUp();
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400332 InitProviderDB();
Jason Glasgowaf583282012-04-18 15:18:22 -0400333
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400334 EXPECT_TRUE(cellular_->home_provider().GetName().empty());
335 EXPECT_TRUE(cellular_->home_provider().GetCountry().empty());
336 EXPECT_TRUE(cellular_->home_provider().GetCode().empty());
Jason Glasgowaf583282012-04-18 15:18:22 -0400337 EXPECT_FALSE(capability_->sim_proxy_.get());
338 capability_->OnDBusPropertiesChanged(MM_DBUS_INTERFACE_MODEM,
339 modem_properties, vector<string>());
340 EXPECT_EQ(kSimPath, capability_->sim_path_);
341 EXPECT_TRUE(capability_->sim_proxy_.get());
342 EXPECT_EQ(kImsi, capability_->imsi_);
343
344 // Updating the SIM
345 DBusPropertiesMap new_properties;
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400346 const char kCountry[] = "us";
347 const char kCode[] = "310160";
348 const char kNewImsi[] = "310240123456789";
Jason Glasgowaf583282012-04-18 15:18:22 -0400349 const char kSimIdentifier[] = "9999888";
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400350 const char kOperatorIdentifier[] = "310240";
351 const char kOperatorName[] = "Custom SPN";
Jason Glasgowaf583282012-04-18 15:18:22 -0400352 new_properties[MM_SIM_PROPERTY_IMSI].writer().append_string(kNewImsi);
353 new_properties[MM_SIM_PROPERTY_SIMIDENTIFIER].writer().
354 append_string(kSimIdentifier);
355 new_properties[MM_SIM_PROPERTY_OPERATORIDENTIFIER].writer().
356 append_string(kOperatorIdentifier);
Jason Glasgowaf583282012-04-18 15:18:22 -0400357 capability_->OnDBusPropertiesChanged(MM_DBUS_INTERFACE_SIM,
358 new_properties,
359 vector<string>());
360 EXPECT_EQ(kNewImsi, capability_->imsi_);
361 EXPECT_EQ(kSimIdentifier, capability_->sim_identifier_);
362 EXPECT_EQ(kOperatorIdentifier, capability_->operator_id_);
Jason Glasgow4380f0d2012-05-03 18:05:04 -0400363 EXPECT_EQ("", capability_->spn_);
364 EXPECT_EQ("T-Mobile", cellular_->home_provider().GetName());
365 EXPECT_EQ(kCountry, cellular_->home_provider().GetCountry());
366 EXPECT_EQ(kCode, cellular_->home_provider().GetCode());
367 EXPECT_EQ(4, capability_->apn_list_.size());
368
369 new_properties[MM_SIM_PROPERTY_OPERATORNAME].writer().
370 append_string(kOperatorName);
371 capability_->OnDBusPropertiesChanged(MM_DBUS_INTERFACE_SIM,
372 new_properties,
373 vector<string>());
374 EXPECT_EQ(kOperatorName, cellular_->home_provider().GetName());
Jason Glasgowaf583282012-04-18 15:18:22 -0400375 EXPECT_EQ(kOperatorName, capability_->spn_);
376}
377
Gary Morainceba6aa2012-05-03 10:28:26 -0700378MATCHER_P(SizeIs, value, "") {
379 return static_cast<size_t>(value) == arg.size();
380}
381
382// Validates that OnScanReply does not crash with a null callback.
383TEST_F(CellularCapabilityUniversalTest, ScanWithNullCallback) {
384 Error error;
385 EXPECT_CALL(*modem_3gpp_proxy_, Scan(_, _, CellularCapability::kTimeoutScan))
386 .WillOnce(Invoke(this, &CellularCapabilityUniversalTest::InvokeScan));
387 EXPECT_CALL(*device_adaptor_,
388 EmitStringmapsChanged(flimflam::kFoundNetworksProperty,
389 SizeIs(0)));
390 Set3gppProxy();
391 capability_->Scan(&error, ResultCallback());
392 EXPECT_TRUE(error.IsSuccess());
393}
394
Jason Glasgowef965562012-04-10 16:12:35 -0400395} // namespace shill