1 // Copyright (c) 2013 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.
8 #include "base/message_loop/message_loop.h"
9 #include "chromeos/dbus/dbus_thread_manager.h"
10 #include "chromeos/dbus/mock_dbus_thread_manager.h"
11 #include "chromeos/dbus/mock_shill_manager_client.h"
12 #include "chromeos/dbus/mock_shill_profile_client.h"
13 #include "chromeos/dbus/mock_shill_service_client.h"
14 #include "chromeos/network/managed_network_configuration_handler_impl.h"
15 #include "chromeos/network/network_configuration_handler.h"
16 #include "chromeos/network/network_profile_handler.h"
17 #include "chromeos/network/onc/onc_test_utils.h"
18 #include "chromeos/network/onc/onc_utils.h"
19 #include "dbus/object_path.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
24 using ::testing::AnyNumber
;
25 using ::testing::Invoke
;
26 using ::testing::Mock
;
27 using ::testing::Pointee
;
28 using ::testing::Return
;
29 using ::testing::SaveArg
;
30 using ::testing::StrEq
;
31 using ::testing::StrictMock
;
34 namespace test_utils
= ::chromeos::onc::test_utils
;
40 std::string
ValueToString(const base::Value
* value
) {
41 std::stringstream str
;
46 const char kSharedProfilePath
[] = "/profile/default";
47 const char kUser1
[] = "user1";
48 const char kUser1ProfilePath
[] = "/profile/user1/shill";
50 // Matcher to match base::Value.
53 std::string(negation
? "isn't" : "is") + " equal to " +
54 ValueToString(value
)) {
55 return value
->Equals(&arg
);
58 class ShillProfileTestClient
{
60 typedef ShillClientHelper::DictionaryValueCallbackWithoutStatus
61 DictionaryValueCallbackWithoutStatus
;
62 typedef ShillClientHelper::ErrorCallback ErrorCallback
;
64 void AddProfile(const std::string
& profile_path
,
65 const std::string
& userhash
) {
66 if (profile_entries_
.HasKey(profile_path
))
69 base::DictionaryValue
* profile
= new base::DictionaryValue
;
70 profile_entries_
.SetWithoutPathExpansion(profile_path
, profile
);
71 profile_to_user_
[profile_path
] = userhash
;
74 void AddEntry(const std::string
& profile_path
,
75 const std::string
& entry_path
,
76 const base::DictionaryValue
& entry
) {
77 base::DictionaryValue
* entries
= NULL
;
78 profile_entries_
.GetDictionaryWithoutPathExpansion(profile_path
, &entries
);
81 base::DictionaryValue
* new_entry
= entry
.DeepCopy();
82 new_entry
->SetStringWithoutPathExpansion(flimflam::kProfileProperty
,
84 entries
->SetWithoutPathExpansion(entry_path
, new_entry
);
87 void GetProperties(const dbus::ObjectPath
& profile_path
,
88 const DictionaryValueCallbackWithoutStatus
& callback
,
89 const ErrorCallback
& error_callback
) {
90 base::DictionaryValue
* entries
= NULL
;
91 profile_entries_
.GetDictionaryWithoutPathExpansion(profile_path
.value(),
95 scoped_ptr
<base::DictionaryValue
> result(new base::DictionaryValue
);
96 base::ListValue
* entry_paths
= new base::ListValue
;
97 result
->SetWithoutPathExpansion(flimflam::kEntriesProperty
,
99 for (base::DictionaryValue::Iterator
it(*entries
); !it
.IsAtEnd();
101 entry_paths
->AppendString(it
.key());
104 ASSERT_GT(profile_to_user_
.count(profile_path
.value()), 0UL);
105 const std::string
& userhash
= profile_to_user_
[profile_path
.value()];
106 result
->SetStringWithoutPathExpansion(shill::kUserHashProperty
, userhash
);
108 callback
.Run(*result
);
111 void GetEntry(const dbus::ObjectPath
& profile_path
,
112 const std::string
& entry_path
,
113 const DictionaryValueCallbackWithoutStatus
& callback
,
114 const ErrorCallback
& error_callback
) {
115 base::DictionaryValue
* entries
= NULL
;
116 profile_entries_
.GetDictionaryWithoutPathExpansion(profile_path
.value(),
118 ASSERT_TRUE(entries
);
120 base::DictionaryValue
* entry
= NULL
;
121 entries
->GetDictionaryWithoutPathExpansion(entry_path
, &entry
);
123 callback
.Run(*entry
);
127 base::DictionaryValue profile_entries_
;
128 std::map
<std::string
, std::string
> profile_to_user_
;
131 class TestNetworkProfileHandler
: public NetworkProfileHandler
{
133 TestNetworkProfileHandler() {
134 Init(NULL
/* No NetworkStateHandler */);
136 virtual ~TestNetworkProfileHandler() {}
138 void AddProfileForTest(const NetworkProfile
& profile
) {
143 DISALLOW_COPY_AND_ASSIGN(TestNetworkProfileHandler
);
148 class ManagedNetworkConfigurationHandlerTest
: public testing::Test
{
150 ManagedNetworkConfigurationHandlerTest() {
153 virtual ~ManagedNetworkConfigurationHandlerTest() {
156 virtual void SetUp() OVERRIDE
{
157 MockDBusThreadManager
* dbus_thread_manager
= new MockDBusThreadManager
;
158 EXPECT_CALL(*dbus_thread_manager
, GetSystemBus())
159 .WillRepeatedly(Return(static_cast<dbus::Bus
*>(NULL
)));
160 DBusThreadManager::InitializeForTesting(dbus_thread_manager
);
162 SetNetworkConfigurationHandlerExpectations();
164 EXPECT_CALL(*dbus_thread_manager
, GetShillManagerClient())
165 .WillRepeatedly(Return(&mock_manager_client_
));
166 EXPECT_CALL(*dbus_thread_manager
, GetShillServiceClient())
167 .WillRepeatedly(Return(&mock_service_client_
));
168 EXPECT_CALL(*dbus_thread_manager
, GetShillProfileClient())
169 .WillRepeatedly(Return(&mock_profile_client_
));
171 ON_CALL(mock_profile_client_
, GetProperties(_
,_
,_
))
172 .WillByDefault(Invoke(&profiles_stub_
,
173 &ShillProfileTestClient::GetProperties
));
175 ON_CALL(mock_profile_client_
, GetEntry(_
,_
,_
,_
))
176 .WillByDefault(Invoke(&profiles_stub_
,
177 &ShillProfileTestClient::GetEntry
));
179 network_profile_handler_
.reset(new TestNetworkProfileHandler());
180 network_configuration_handler_
.reset(
181 NetworkConfigurationHandler::InitializeForTest(
182 NULL
/* no NetworkStateHandler */));
183 managed_network_configuration_handler_
.reset(
184 new ManagedNetworkConfigurationHandlerImpl());
185 managed_network_configuration_handler_
->Init(
186 NULL
/* no NetworkStateHandler */,
187 network_profile_handler_
.get(),
188 network_configuration_handler_
.get());
190 message_loop_
.RunUntilIdle();
193 virtual void TearDown() OVERRIDE
{
194 managed_network_configuration_handler_
.reset();
195 network_configuration_handler_
.reset();
196 network_profile_handler_
.reset();
197 DBusThreadManager::Shutdown();
200 void VerifyAndClearExpectations() {
201 Mock::VerifyAndClearExpectations(&mock_manager_client_
);
202 Mock::VerifyAndClearExpectations(&mock_service_client_
);
203 Mock::VerifyAndClearExpectations(&mock_profile_client_
);
204 SetNetworkConfigurationHandlerExpectations();
207 void InitializeStandardProfiles() {
208 profiles_stub_
.AddProfile(kUser1ProfilePath
, kUser1
);
209 network_profile_handler_
->
210 AddProfileForTest(NetworkProfile(kUser1ProfilePath
, kUser1
));
211 network_profile_handler_
->
212 AddProfileForTest(NetworkProfile(kSharedProfilePath
, std::string()));
215 void SetUpEntry(const std::string
& path_to_shill_json
,
216 const std::string
& profile_path
,
217 const std::string
& entry_path
) {
218 scoped_ptr
<base::DictionaryValue
> entry
=
219 test_utils::ReadTestDictionary(path_to_shill_json
);
220 profiles_stub_
.AddEntry(profile_path
, entry_path
, *entry
);
223 void SetPolicy(onc::ONCSource onc_source
,
224 const std::string
& userhash
,
225 const std::string
& path_to_onc
) {
226 scoped_ptr
<base::DictionaryValue
> policy
;
227 if (path_to_onc
.empty())
228 policy
= onc::ReadDictionaryFromJson(onc::kEmptyUnencryptedConfiguration
);
230 policy
= test_utils::ReadTestDictionary(path_to_onc
);
232 base::ListValue
* network_configs
= NULL
;
233 policy
->GetListWithoutPathExpansion(
234 onc::toplevel_config::kNetworkConfigurations
, &network_configs
);
236 managed_handler()->SetPolicy(
237 onc::ONC_SOURCE_USER_POLICY
, userhash
, *network_configs
);
240 void SetNetworkConfigurationHandlerExpectations() {
241 // These calls occur in NetworkConfigurationHandler.
242 EXPECT_CALL(mock_manager_client_
, GetProperties(_
)).Times(AnyNumber());
243 EXPECT_CALL(mock_manager_client_
,
244 AddPropertyChangedObserver(_
)).Times(AnyNumber());
245 EXPECT_CALL(mock_manager_client_
,
246 RemovePropertyChangedObserver(_
)).Times(AnyNumber());
249 ManagedNetworkConfigurationHandler
* managed_handler() {
250 return managed_network_configuration_handler_
.get();
254 StrictMock
<MockShillManagerClient
> mock_manager_client_
;
255 StrictMock
<MockShillServiceClient
> mock_service_client_
;
256 StrictMock
<MockShillProfileClient
> mock_profile_client_
;
257 ShillProfileTestClient profiles_stub_
;
258 scoped_ptr
<TestNetworkProfileHandler
> network_profile_handler_
;
259 scoped_ptr
<NetworkConfigurationHandler
> network_configuration_handler_
;
260 scoped_ptr
<ManagedNetworkConfigurationHandlerImpl
>
261 managed_network_configuration_handler_
;
262 base::MessageLoop message_loop_
;
265 DISALLOW_COPY_AND_ASSIGN(ManagedNetworkConfigurationHandlerTest
);
268 TEST_F(ManagedNetworkConfigurationHandlerTest
, ProfileInitialization
) {
269 InitializeStandardProfiles();
270 message_loop_
.RunUntilIdle();
273 TEST_F(ManagedNetworkConfigurationHandlerTest
, RemoveIrrelevantFields
) {
274 InitializeStandardProfiles();
275 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
276 test_utils::ReadTestDictionary(
277 "policy/shill_policy_on_unconfigured_wifi1.json");
279 EXPECT_CALL(mock_profile_client_
,
280 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
282 EXPECT_CALL(mock_manager_client_
,
283 ConfigureServiceForProfile(
284 dbus::ObjectPath(kUser1ProfilePath
),
285 IsEqualTo(expected_shill_properties
.get()),
288 SetPolicy(onc::ONC_SOURCE_USER_POLICY
,
290 "policy/policy_wifi1_with_redundant_fields.onc");
291 message_loop_
.RunUntilIdle();
294 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetPolicyManageUnconfigured
) {
295 InitializeStandardProfiles();
296 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
297 test_utils::ReadTestDictionary(
298 "policy/shill_policy_on_unconfigured_wifi1.json");
300 EXPECT_CALL(mock_profile_client_
,
301 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
303 EXPECT_CALL(mock_manager_client_
,
304 ConfigureServiceForProfile(
305 dbus::ObjectPath(kUser1ProfilePath
),
306 IsEqualTo(expected_shill_properties
.get()),
309 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
310 message_loop_
.RunUntilIdle();
313 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetPolicyIgnoreUnmodified
) {
314 InitializeStandardProfiles();
315 EXPECT_CALL(mock_profile_client_
, GetProperties(_
, _
, _
));
317 EXPECT_CALL(mock_manager_client_
, ConfigureServiceForProfile(_
, _
, _
, _
));
319 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
320 message_loop_
.RunUntilIdle();
321 VerifyAndClearExpectations();
323 SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json",
327 EXPECT_CALL(mock_profile_client_
, GetProperties(_
, _
, _
));
329 EXPECT_CALL(mock_profile_client_
,
330 GetEntry(dbus::ObjectPath(kUser1ProfilePath
),
334 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
335 message_loop_
.RunUntilIdle();
338 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetPolicyManageUnmanaged
) {
339 InitializeStandardProfiles();
340 SetUpEntry("policy/shill_unmanaged_user_wifi1.json",
344 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
345 test_utils::ReadTestDictionary(
346 "policy/shill_policy_on_unmanaged_user_wifi1.json");
348 EXPECT_CALL(mock_profile_client_
,
349 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
352 mock_profile_client_
,
353 GetEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
356 mock_profile_client_
,
357 DeleteEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
359 EXPECT_CALL(mock_manager_client_
,
360 ConfigureServiceForProfile(
361 dbus::ObjectPath(kUser1ProfilePath
),
362 IsEqualTo(expected_shill_properties
.get()),
365 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
366 message_loop_
.RunUntilIdle();
369 // Old ChromeOS versions may not have used the UIData property
370 TEST_F(ManagedNetworkConfigurationHandlerTest
,
371 SetPolicyManageUnmanagedWithoutUIData
) {
372 InitializeStandardProfiles();
373 SetUpEntry("policy/shill_unmanaged_user_wifi1.json",
377 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
378 test_utils::ReadTestDictionary(
379 "policy/shill_policy_on_unmanaged_user_wifi1.json");
381 EXPECT_CALL(mock_profile_client_
,
382 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
385 mock_profile_client_
,
386 GetEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
389 mock_profile_client_
,
390 DeleteEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
392 EXPECT_CALL(mock_manager_client_
,
393 ConfigureServiceForProfile(
394 dbus::ObjectPath(kUser1ProfilePath
),
395 IsEqualTo(expected_shill_properties
.get()),
398 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
399 message_loop_
.RunUntilIdle();
402 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetPolicyUpdateManagedNewGUID
) {
403 InitializeStandardProfiles();
404 SetUpEntry("policy/shill_managed_wifi1.json",
408 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
409 test_utils::ReadTestDictionary(
410 "policy/shill_policy_on_unmanaged_user_wifi1.json");
412 // The passphrase isn't sent again, because it's configured by the user and
413 // Shill doesn't sent it on GetProperties calls.
414 expected_shill_properties
->RemoveWithoutPathExpansion(
415 flimflam::kPassphraseProperty
, NULL
);
417 EXPECT_CALL(mock_profile_client_
,
418 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
421 mock_profile_client_
,
422 GetEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
425 mock_profile_client_
,
426 DeleteEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
428 EXPECT_CALL(mock_manager_client_
,
429 ConfigureServiceForProfile(
430 dbus::ObjectPath(kUser1ProfilePath
),
431 IsEqualTo(expected_shill_properties
.get()),
434 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
435 message_loop_
.RunUntilIdle();
438 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetPolicyReapplyToManaged
) {
439 InitializeStandardProfiles();
440 SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json",
444 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
445 test_utils::ReadTestDictionary(
446 "policy/shill_policy_on_unmanaged_user_wifi1.json");
448 // The passphrase isn't sent again, because it's configured by the user and
449 // Shill doesn't sent it on GetProperties calls.
450 expected_shill_properties
->RemoveWithoutPathExpansion(
451 flimflam::kPassphraseProperty
, NULL
);
453 EXPECT_CALL(mock_profile_client_
,
454 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
457 mock_profile_client_
,
458 GetEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
460 EXPECT_CALL(mock_manager_client_
,
461 ConfigureServiceForProfile(
462 dbus::ObjectPath(kUser1ProfilePath
),
463 IsEqualTo(expected_shill_properties
.get()),
466 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
467 message_loop_
.RunUntilIdle();
468 VerifyAndClearExpectations();
470 // If we apply the policy again, without change, then the Shill profile will
472 EXPECT_CALL(mock_profile_client_
,
473 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
476 mock_profile_client_
,
477 GetEntry(dbus::ObjectPath(kUser1ProfilePath
), "old_entry_path", _
, _
));
479 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
480 message_loop_
.RunUntilIdle();
483 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetPolicyUnmanageManaged
) {
484 InitializeStandardProfiles();
485 SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json",
489 EXPECT_CALL(mock_profile_client_
,
490 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
492 EXPECT_CALL(mock_profile_client_
,
493 GetEntry(dbus::ObjectPath(kUser1ProfilePath
),
497 EXPECT_CALL(mock_profile_client_
,
498 DeleteEntry(dbus::ObjectPath(kUser1ProfilePath
),
502 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "");
503 message_loop_
.RunUntilIdle();
506 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetEmptyPolicyIgnoreUnmanaged
) {
507 InitializeStandardProfiles();
508 SetUpEntry("policy/shill_unmanaged_user_wifi1.json",
512 EXPECT_CALL(mock_profile_client_
,
513 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
515 EXPECT_CALL(mock_profile_client_
,
516 GetEntry(dbus::ObjectPath(kUser1ProfilePath
),
520 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "");
521 message_loop_
.RunUntilIdle();
524 TEST_F(ManagedNetworkConfigurationHandlerTest
, SetPolicyIgnoreUnmanaged
) {
525 InitializeStandardProfiles();
526 SetUpEntry("policy/shill_unmanaged_user_wifi2.json",
530 EXPECT_CALL(mock_profile_client_
,
531 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
534 mock_profile_client_
,
535 GetEntry(dbus::ObjectPath(kUser1ProfilePath
), "wifi2_entry_path", _
, _
));
537 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
538 test_utils::ReadTestDictionary(
539 "policy/shill_policy_on_unconfigured_wifi1.json");
541 EXPECT_CALL(mock_manager_client_
,
542 ConfigureServiceForProfile(
543 dbus::ObjectPath(kUser1ProfilePath
),
544 IsEqualTo(expected_shill_properties
.get()),
547 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
548 message_loop_
.RunUntilIdle();
551 TEST_F(ManagedNetworkConfigurationHandlerTest
, LateProfileLoading
) {
552 SetPolicy(onc::ONC_SOURCE_USER_POLICY
, kUser1
, "policy/policy_wifi1.onc");
554 message_loop_
.RunUntilIdle();
555 VerifyAndClearExpectations();
557 scoped_ptr
<base::DictionaryValue
> expected_shill_properties
=
558 test_utils::ReadTestDictionary(
559 "policy/shill_policy_on_unconfigured_wifi1.json");
561 EXPECT_CALL(mock_profile_client_
,
562 GetProperties(dbus::ObjectPath(kUser1ProfilePath
), _
, _
));
564 EXPECT_CALL(mock_manager_client_
,
565 ConfigureServiceForProfile(
566 dbus::ObjectPath(kUser1ProfilePath
),
567 IsEqualTo(expected_shill_properties
.get()),
570 InitializeStandardProfiles();
571 message_loop_
.RunUntilIdle();
574 } // namespace chromeos