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 "base/bind.h"
6#include "base/values.h"
7#include "chromeos/dbus/shill_client_unittest_base.h"
8#include "chromeos/dbus/shill_device_client.h"
9#include "dbus/message.h"
10#include "dbus/object_path.h"
11#include "dbus/values_util.h"
12#include "testing/gtest/include/gtest/gtest.h"
13#include "third_party/cros_system_api/dbus/service_constants.h"
14
15using testing::_;
16using testing::ByRef;
17
18namespace chromeos {
19
20namespace {
21
22const char kExampleDevicePath[] = "/foo/bar";
23
24// Expects the reader to have a string and a bool.
25void ExpectStringAndBoolArguments(const std::string& expected_string,
26                                  bool expected_bool,
27                                  dbus::MessageReader* reader) {
28  std::string arg1;
29  ASSERT_TRUE(reader->PopString(&arg1));
30  EXPECT_EQ(expected_string, arg1);
31  bool arg2 = false;
32  ASSERT_TRUE(reader->PopBool(&arg2));
33  EXPECT_EQ(expected_bool, arg2);
34  EXPECT_FALSE(reader->HasMoreData());
35}
36
37// Expects the reader to have two strings.
38void ExpectTwoStringArguments(const std::string& expected_string1,
39                              const std::string& expected_string2,
40                              dbus::MessageReader* reader) {
41  std::string arg1;
42  ASSERT_TRUE(reader->PopString(&arg1));
43  EXPECT_EQ(expected_string1, arg1);
44  std::string arg2;
45  ASSERT_TRUE(reader->PopString(&arg2));
46  EXPECT_EQ(expected_string2, arg2);
47  EXPECT_FALSE(reader->HasMoreData());
48}
49
50}  // namespace
51
52class ShillDeviceClientTest : public ShillClientUnittestBase {
53 public:
54  ShillDeviceClientTest()
55      : ShillClientUnittestBase(shill::kFlimflamDeviceInterface,
56                                   dbus::ObjectPath(kExampleDevicePath)) {
57  }
58
59  virtual void SetUp() {
60    ShillClientUnittestBase::SetUp();
61    // Create a client with the mock bus.
62    client_.reset(ShillDeviceClient::Create());
63    client_->Init(mock_bus_.get());
64    // Run the message loop to run the signal connection result callback.
65    message_loop_.RunUntilIdle();
66  }
67
68  virtual void TearDown() {
69    ShillClientUnittestBase::TearDown();
70  }
71
72 protected:
73  scoped_ptr<ShillDeviceClient> client_;
74};
75
76TEST_F(ShillDeviceClientTest, PropertyChanged) {
77  const bool kValue = true;
78  // Create a signal.
79  dbus::Signal signal(shill::kFlimflamDeviceInterface,
80                      shill::kMonitorPropertyChanged);
81  dbus::MessageWriter writer(&signal);
82  writer.AppendString(shill::kCellularAllowRoamingProperty);
83  writer.AppendVariantOfBool(kValue);
84
85  // Set expectations.
86  const base::FundamentalValue value(kValue);
87  MockPropertyChangeObserver observer;
88  EXPECT_CALL(observer,
89              OnPropertyChanged(shill::kCellularAllowRoamingProperty,
90                                ValueEq(ByRef(value)))).Times(1);
91
92  // Add the observer
93  client_->AddPropertyChangedObserver(
94      dbus::ObjectPath(kExampleDevicePath),
95      &observer);
96
97  // Run the signal callback.
98  SendPropertyChangedSignal(&signal);
99
100  // Remove the observer.
101  client_->RemovePropertyChangedObserver(
102      dbus::ObjectPath(kExampleDevicePath),
103      &observer);
104
105  EXPECT_CALL(observer,
106              OnPropertyChanged(shill::kCellularAllowRoamingProperty,
107                                ValueEq(ByRef(value)))).Times(0);
108
109  // Run the signal callback again and make sure the observer isn't called.
110  SendPropertyChangedSignal(&signal);
111}
112
113TEST_F(ShillDeviceClientTest, GetProperties) {
114  const bool kValue = true;
115  // Create response.
116  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
117  dbus::MessageWriter writer(response.get());
118  dbus::MessageWriter array_writer(NULL);
119  writer.OpenArray("{sv}", &array_writer);
120  dbus::MessageWriter entry_writer(NULL);
121  array_writer.OpenDictEntry(&entry_writer);
122  entry_writer.AppendString(shill::kCellularAllowRoamingProperty);
123  entry_writer.AppendVariantOfBool(kValue);
124  array_writer.CloseContainer(&entry_writer);
125  writer.CloseContainer(&array_writer);
126
127  // Set expectations.
128  base::DictionaryValue value;
129  value.SetWithoutPathExpansion(shill::kCellularAllowRoamingProperty,
130                                new base::FundamentalValue(kValue));
131  PrepareForMethodCall(shill::kGetPropertiesFunction,
132                       base::Bind(&ExpectNoArgument),
133                       response.get());
134  // Call method.
135  client_->GetProperties(dbus::ObjectPath(kExampleDevicePath),
136                         base::Bind(&ExpectDictionaryValueResult, &value));
137  // Run the message loop.
138  message_loop_.RunUntilIdle();
139}
140
141TEST_F(ShillDeviceClientTest, ProposeScan) {
142  // Create response.
143  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
144
145  // Set expectations.
146  PrepareForMethodCall(shill::kProposeScanFunction,
147                       base::Bind(&ExpectNoArgument),
148                       response.get());
149  // Call method.
150  client_->ProposeScan(dbus::ObjectPath(kExampleDevicePath),
151                       base::Bind(&ExpectNoResultValue));
152  // Run the message loop.
153  message_loop_.RunUntilIdle();
154}
155
156TEST_F(ShillDeviceClientTest, SetProperty) {
157  const bool kValue = true;
158  // Create response.
159  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
160
161  // Set expectations.
162  const base::FundamentalValue value(kValue);
163  PrepareForMethodCall(shill::kSetPropertyFunction,
164                       base::Bind(&ExpectStringAndValueArguments,
165                                  shill::kCellularAllowRoamingProperty,
166                                  &value),
167                       response.get());
168  // Call method.
169  MockClosure mock_closure;
170  MockErrorCallback mock_error_callback;
171  client_->SetProperty(dbus::ObjectPath(kExampleDevicePath),
172                       shill::kCellularAllowRoamingProperty,
173                       value,
174                       mock_closure.GetCallback(),
175                       mock_error_callback.GetCallback());
176  EXPECT_CALL(mock_closure, Run()).Times(1);
177  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
178
179  // Run the message loop.
180  message_loop_.RunUntilIdle();
181}
182
183TEST_F(ShillDeviceClientTest, ClearProperty) {
184  // Create response.
185  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
186
187  // Set expectations.
188  PrepareForMethodCall(shill::kClearPropertyFunction,
189                       base::Bind(&ExpectStringArgument,
190                                  shill::kCellularAllowRoamingProperty),
191                       response.get());
192  // Call method.
193  client_->ClearProperty(dbus::ObjectPath(kExampleDevicePath),
194                         shill::kCellularAllowRoamingProperty,
195                         base::Bind(&ExpectNoResultValue));
196  // Run the message loop.
197  message_loop_.RunUntilIdle();
198}
199
200TEST_F(ShillDeviceClientTest, AddIPConfig) {
201  const dbus::ObjectPath expected_result("/result/path");
202  // Create response.
203  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
204  dbus::MessageWriter writer(response.get());
205  writer.AppendObjectPath(expected_result);
206
207  // Set expectations.
208  PrepareForMethodCall(shill::kAddIPConfigFunction,
209                       base::Bind(&ExpectStringArgument, shill::kTypeDHCP),
210                       response.get());
211  // Call method.
212  client_->AddIPConfig(dbus::ObjectPath(kExampleDevicePath),
213                       shill::kTypeDHCP,
214                       base::Bind(&ExpectObjectPathResult, expected_result));
215  // Run the message loop.
216  message_loop_.RunUntilIdle();
217}
218
219TEST_F(ShillDeviceClientTest, RequirePin) {
220  const char kPin[] = "123456";
221  const bool kRequired = true;
222  // Create response.
223  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
224
225  // Set expectations.
226  MockClosure mock_closure;
227  MockErrorCallback mock_error_callback;
228  PrepareForMethodCall(shill::kRequirePinFunction,
229                       base::Bind(&ExpectStringAndBoolArguments,
230                                  kPin,
231                                  kRequired),
232                       response.get());
233  EXPECT_CALL(mock_closure, Run()).Times(1);
234  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
235  // Call method.
236  client_->RequirePin(dbus::ObjectPath(kExampleDevicePath),
237                      kPin,
238                      kRequired,
239                      mock_closure.GetCallback(),
240                      mock_error_callback.GetCallback());
241  // Run the message loop.
242  message_loop_.RunUntilIdle();
243}
244
245TEST_F(ShillDeviceClientTest, EnterPin) {
246  const char kPin[] = "123456";
247  // Create response.
248  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
249
250  // Set expectations.
251  MockClosure mock_closure;
252  MockErrorCallback mock_error_callback;
253  PrepareForMethodCall(shill::kEnterPinFunction,
254                       base::Bind(&ExpectStringArgument,
255                                  kPin),
256                       response.get());
257  EXPECT_CALL(mock_closure, Run()).Times(1);
258  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
259
260  // Call method.
261  client_->EnterPin(dbus::ObjectPath(kExampleDevicePath),
262                    kPin,
263                    mock_closure.GetCallback(),
264                    mock_error_callback.GetCallback());
265  // Run the message loop.
266  message_loop_.RunUntilIdle();
267}
268
269TEST_F(ShillDeviceClientTest, UnblockPin) {
270  const char kPuk[] = "987654";
271  const char kPin[] = "123456";
272  // Create response.
273  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
274
275  // Set expectations.
276  MockClosure mock_closure;
277  MockErrorCallback mock_error_callback;
278  PrepareForMethodCall(shill::kUnblockPinFunction,
279                       base::Bind(&ExpectTwoStringArguments, kPuk, kPin),
280                       response.get());
281  EXPECT_CALL(mock_closure, Run()).Times(1);
282  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
283
284  // Call method.
285  client_->UnblockPin(dbus::ObjectPath(kExampleDevicePath),
286                      kPuk,
287                      kPin,
288                      mock_closure.GetCallback(),
289                      mock_error_callback.GetCallback());
290  // Run the message loop.
291  message_loop_.RunUntilIdle();
292}
293
294TEST_F(ShillDeviceClientTest, ChangePin) {
295  const char kOldPin[] = "123456";
296  const char kNewPin[] = "234567";
297  // Create response.
298  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
299
300  // Set expectations.
301  MockClosure mock_closure;
302  MockErrorCallback mock_error_callback;
303  PrepareForMethodCall(shill::kChangePinFunction,
304                       base::Bind(&ExpectTwoStringArguments,
305                                  kOldPin,
306                                  kNewPin),
307                       response.get());
308  EXPECT_CALL(mock_closure, Run()).Times(1);
309  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
310
311  // Call method.
312  client_->ChangePin(dbus::ObjectPath(kExampleDevicePath),
313                     kOldPin,
314                     kNewPin,
315                     mock_closure.GetCallback(),
316                     mock_error_callback.GetCallback());
317  // Run the message loop.
318  message_loop_.RunUntilIdle();
319}
320
321TEST_F(ShillDeviceClientTest, Register) {
322  const char kNetworkId[] = "networkid";
323  // Create response.
324  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
325
326  // Set expectations.
327  MockClosure mock_closure;
328  MockErrorCallback mock_error_callback;
329  PrepareForMethodCall(shill::kRegisterFunction,
330                       base::Bind(&ExpectStringArgument, kNetworkId),
331                       response.get());
332  EXPECT_CALL(mock_closure, Run()).Times(1);
333  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
334
335  // Call method.
336  client_->Register(dbus::ObjectPath(kExampleDevicePath),
337                    kNetworkId,
338                    mock_closure.GetCallback(),
339                    mock_error_callback.GetCallback());
340  // Run the message loop.
341  message_loop_.RunUntilIdle();
342}
343
344TEST_F(ShillDeviceClientTest, SetCarrier) {
345  const char kCarrier[] = "carrier";
346  // Create response.
347  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
348
349  // Set expectations.
350  MockClosure mock_closure;
351  MockErrorCallback mock_error_callback;
352  PrepareForMethodCall(shill::kSetCarrierFunction,
353                       base::Bind(&ExpectStringArgument, kCarrier),
354                       response.get());
355  EXPECT_CALL(mock_closure, Run()).Times(1);
356  // Call method.
357  client_->SetCarrier(dbus::ObjectPath(kExampleDevicePath),
358                    kCarrier,
359                    mock_closure.GetCallback(),
360                    mock_error_callback.GetCallback());
361  // Run the message loop.
362  message_loop_.RunUntilIdle();
363}
364
365TEST_F(ShillDeviceClientTest, Reset) {
366  // Create response.
367  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
368
369  // Set expectations.
370  MockClosure mock_closure;
371  MockErrorCallback mock_error_callback;
372  PrepareForMethodCall(shill::kResetFunction,
373                       base::Bind(&ExpectNoArgument),
374                       response.get());
375  EXPECT_CALL(mock_closure, Run()).Times(1);
376  // Call method.
377  client_->Reset(dbus::ObjectPath(kExampleDevicePath),
378                 mock_closure.GetCallback(),
379                 mock_error_callback.GetCallback());
380  // Run the message loop.
381  message_loop_.RunUntilIdle();
382}
383
384}  // namespace chromeos
385