managed_network_configuration_handler_unittest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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. 4 5#include "chromeos/network/managed_network_configuration_handler.h" 6 7#include <iostream> 8#include <sstream> 9 10#include "base/message_loop.h" 11#include "chromeos/dbus/dbus_thread_manager.h" 12#include "chromeos/dbus/mock_dbus_thread_manager.h" 13#include "chromeos/dbus/mock_shill_manager_client.h" 14#include "chromeos/dbus/mock_shill_profile_client.h" 15#include "chromeos/dbus/mock_shill_service_client.h" 16#include "chromeos/dbus/shill_profile_client_stub.h" 17#include "chromeos/network/network_configuration_handler.h" 18#include "chromeos/network/network_profile_handler.h" 19#include "chromeos/network/onc/onc_test_utils.h" 20#include "chromeos/network/onc/onc_utils.h" 21#include "dbus/object_path.h" 22#include "testing/gmock/include/gmock/gmock.h" 23#include "testing/gtest/include/gtest/gtest.h" 24#include "third_party/cros_system_api/dbus/service_constants.h" 25 26using ::testing::AnyNumber; 27using ::testing::Invoke; 28using ::testing::Mock; 29using ::testing::Pointee; 30using ::testing::Return; 31using ::testing::SaveArg; 32using ::testing::StrEq; 33using ::testing::StrictMock; 34using ::testing::_; 35 36namespace test_utils = ::chromeos::onc::test_utils; 37 38namespace chromeos { 39 40namespace { 41 42std::string ValueToString(const base::Value* value) { 43 std::stringstream str; 44 str << *value; 45 return str.str(); 46} 47 48const char kSharedProfilePath[] = "/profile/default"; 49const char kUser1[] = "user1"; 50const char kUser1ProfilePath[] = "/profile/user1/shill"; 51 52// Matcher to match base::Value. 53MATCHER_P(IsEqualTo, 54 value, 55 std::string(negation ? "isn't" : "is") + " equal to " + 56 ValueToString(value)) { 57 return value->Equals(&arg); 58} 59 60class ShillProfileTestClient { 61 public: 62 typedef ShillClientHelper::DictionaryValueCallbackWithoutStatus 63 DictionaryValueCallbackWithoutStatus; 64 typedef ShillClientHelper::ErrorCallback ErrorCallback; 65 66 void AddProfile(const std::string& profile_path, 67 const std::string& userhash) { 68 if (profile_entries_.HasKey(profile_path)) 69 return; 70 71 base::DictionaryValue* profile = new base::DictionaryValue; 72 profile_entries_.SetWithoutPathExpansion(profile_path, profile); 73 profile_to_user_[profile_path] = userhash; 74 } 75 76 void AddEntry(const std::string& profile_path, 77 const std::string& entry_path, 78 const base::DictionaryValue& entry) { 79 base::DictionaryValue* entries = NULL; 80 profile_entries_.GetDictionaryWithoutPathExpansion(profile_path, &entries); 81 ASSERT_TRUE(entries); 82 83 base::DictionaryValue* new_entry = entry.DeepCopy(); 84 new_entry->SetStringWithoutPathExpansion(flimflam::kProfileProperty, 85 profile_path); 86 entries->SetWithoutPathExpansion(entry_path, new_entry); 87 } 88 89 void GetProperties(const dbus::ObjectPath& profile_path, 90 const DictionaryValueCallbackWithoutStatus& callback, 91 const ErrorCallback& error_callback) { 92 base::DictionaryValue* entries = NULL; 93 profile_entries_.GetDictionaryWithoutPathExpansion(profile_path.value(), 94 &entries); 95 ASSERT_TRUE(entries); 96 97 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); 98 base::ListValue* entry_paths = new base::ListValue; 99 result->SetWithoutPathExpansion(flimflam::kEntriesProperty, 100 entry_paths); 101 for (base::DictionaryValue::Iterator it(*entries); !it.IsAtEnd(); 102 it.Advance()) { 103 entry_paths->AppendString(it.key()); 104 } 105 106 ASSERT_GT(profile_to_user_.count(profile_path.value()), 0UL); 107 const std::string& userhash = profile_to_user_[profile_path.value()]; 108 result->SetStringWithoutPathExpansion(shill::kUserHashProperty, userhash); 109 110 callback.Run(*result); 111 } 112 113 void GetEntry(const dbus::ObjectPath& profile_path, 114 const std::string& entry_path, 115 const DictionaryValueCallbackWithoutStatus& callback, 116 const ErrorCallback& error_callback) { 117 base::DictionaryValue* entries = NULL; 118 profile_entries_.GetDictionaryWithoutPathExpansion(profile_path.value(), 119 &entries); 120 ASSERT_TRUE(entries); 121 122 base::DictionaryValue* entry = NULL; 123 entries->GetDictionaryWithoutPathExpansion(entry_path, &entry); 124 ASSERT_TRUE(entry); 125 callback.Run(*entry); 126 } 127 128 protected: 129 base::DictionaryValue profile_entries_; 130 std::map<std::string, std::string> profile_to_user_; 131}; 132 133class TestNetworkProfileHandler : public NetworkProfileHandler { 134 public: 135 TestNetworkProfileHandler() { 136 Init(NULL /* No NetworkStateHandler */); 137 } 138 virtual ~TestNetworkProfileHandler() {} 139 140 void AddProfileForTest(const NetworkProfile& profile) { 141 AddProfile(profile); 142 } 143 144 private: 145 DISALLOW_COPY_AND_ASSIGN(TestNetworkProfileHandler); 146}; 147 148} // namespace 149 150class ManagedNetworkConfigurationHandlerTest : public testing::Test { 151 public: 152 ManagedNetworkConfigurationHandlerTest() { 153 } 154 155 virtual ~ManagedNetworkConfigurationHandlerTest() { 156 } 157 158 virtual void SetUp() OVERRIDE { 159 MockDBusThreadManager* dbus_thread_manager = new MockDBusThreadManager; 160 EXPECT_CALL(*dbus_thread_manager, GetSystemBus()) 161 .WillRepeatedly(Return(static_cast<dbus::Bus*>(NULL))); 162 DBusThreadManager::InitializeForTesting(dbus_thread_manager); 163 164 SetNetworkConfigurationHandlerExpectations(); 165 166 EXPECT_CALL(*dbus_thread_manager, GetShillManagerClient()) 167 .WillRepeatedly(Return(&mock_manager_client_)); 168 EXPECT_CALL(*dbus_thread_manager, GetShillServiceClient()) 169 .WillRepeatedly(Return(&mock_service_client_)); 170 EXPECT_CALL(*dbus_thread_manager, GetShillProfileClient()) 171 .WillRepeatedly(Return(&mock_profile_client_)); 172 173 ON_CALL(mock_profile_client_, GetProperties(_,_,_)) 174 .WillByDefault(Invoke(&profiles_stub_, 175 &ShillProfileTestClient::GetProperties)); 176 177 ON_CALL(mock_profile_client_, GetEntry(_,_,_,_)) 178 .WillByDefault(Invoke(&profiles_stub_, 179 &ShillProfileTestClient::GetEntry)); 180 181 network_profile_handler_.reset(new TestNetworkProfileHandler()); 182 network_configuration_handler_.reset( 183 NetworkConfigurationHandler::InitializeForTest( 184 NULL /* no NetworkStateHandler */)); 185 managed_network_configuration_handler_.reset( 186 new ManagedNetworkConfigurationHandler()); 187 managed_network_configuration_handler_->Init( 188 NULL /* no NetworkStateHandler */, 189 network_profile_handler_.get(), 190 network_configuration_handler_.get()); 191 192 message_loop_.RunUntilIdle(); 193 } 194 195 virtual void TearDown() OVERRIDE { 196 managed_network_configuration_handler_.reset(); 197 network_configuration_handler_.reset(); 198 network_profile_handler_.reset(); 199 DBusThreadManager::Shutdown(); 200 } 201 202 void VerifyAndClearExpectations() { 203 Mock::VerifyAndClearExpectations(&mock_manager_client_); 204 Mock::VerifyAndClearExpectations(&mock_service_client_); 205 Mock::VerifyAndClearExpectations(&mock_profile_client_); 206 SetNetworkConfigurationHandlerExpectations(); 207 } 208 209 void InitializeStandardProfiles() { 210 profiles_stub_.AddProfile(kUser1ProfilePath, kUser1); 211 network_profile_handler_-> 212 AddProfileForTest(NetworkProfile(kUser1ProfilePath, kUser1)); 213 network_profile_handler_-> 214 AddProfileForTest(NetworkProfile(kSharedProfilePath, std::string())); 215 } 216 217 void SetUpEntry(const std::string& path_to_shill_json, 218 const std::string& profile_path, 219 const std::string& entry_path) { 220 scoped_ptr<base::DictionaryValue> entry = 221 test_utils::ReadTestDictionary(path_to_shill_json); 222 profiles_stub_.AddEntry(profile_path, entry_path, *entry); 223 } 224 225 void SetPolicy(onc::ONCSource onc_source, 226 const std::string& userhash, 227 const std::string& path_to_onc) { 228 scoped_ptr<base::DictionaryValue> policy; 229 if (path_to_onc.empty()) 230 policy = onc::ReadDictionaryFromJson(onc::kEmptyUnencryptedConfiguration); 231 else 232 policy = test_utils::ReadTestDictionary(path_to_onc); 233 234 base::ListValue* network_configs = NULL; 235 policy->GetListWithoutPathExpansion( 236 onc::toplevel_config::kNetworkConfigurations, &network_configs); 237 238 managed_handler()->SetPolicy( 239 onc::ONC_SOURCE_USER_POLICY, userhash, *network_configs); 240 } 241 242 void SetNetworkConfigurationHandlerExpectations() { 243 // These calls occur in NetworkConfigurationHandler. 244 EXPECT_CALL(mock_manager_client_, GetProperties(_)).Times(AnyNumber()); 245 EXPECT_CALL(mock_manager_client_, 246 AddPropertyChangedObserver(_)).Times(AnyNumber()); 247 EXPECT_CALL(mock_manager_client_, 248 RemovePropertyChangedObserver(_)).Times(AnyNumber()); 249 } 250 251 ManagedNetworkConfigurationHandler* managed_handler() { 252 return managed_network_configuration_handler_.get(); 253 } 254 255 protected: 256 StrictMock<MockShillManagerClient> mock_manager_client_; 257 StrictMock<MockShillServiceClient> mock_service_client_; 258 StrictMock<MockShillProfileClient> mock_profile_client_; 259 ShillProfileTestClient profiles_stub_; 260 scoped_ptr<TestNetworkProfileHandler> network_profile_handler_; 261 scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_; 262 scoped_ptr<ManagedNetworkConfigurationHandler> 263 managed_network_configuration_handler_; 264 base::MessageLoop message_loop_; 265 266 private: 267 DISALLOW_COPY_AND_ASSIGN(ManagedNetworkConfigurationHandlerTest); 268}; 269 270TEST_F(ManagedNetworkConfigurationHandlerTest, ProfileInitialization) { 271 InitializeStandardProfiles(); 272 message_loop_.RunUntilIdle(); 273} 274 275TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnconfigured) { 276 InitializeStandardProfiles(); 277 scoped_ptr<base::DictionaryValue> expected_shill_properties = 278 test_utils::ReadTestDictionary( 279 "policy/shill_policy_on_unconfigured_wifi1.json"); 280 281 EXPECT_CALL(mock_profile_client_, 282 GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); 283 284 EXPECT_CALL(mock_manager_client_, 285 ConfigureServiceForProfile( 286 dbus::ObjectPath(kUser1ProfilePath), 287 IsEqualTo(expected_shill_properties.get()), 288 _, _)); 289 290 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); 291 message_loop_.RunUntilIdle(); 292} 293 294TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmodified) { 295 InitializeStandardProfiles(); 296 EXPECT_CALL(mock_profile_client_, GetProperties(_, _, _)); 297 298 EXPECT_CALL(mock_manager_client_, ConfigureServiceForProfile(_, _, _, _)); 299 300 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); 301 message_loop_.RunUntilIdle(); 302 VerifyAndClearExpectations(); 303 304 SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json", 305 kUser1ProfilePath, 306 "some_entry_path"); 307 308 EXPECT_CALL(mock_profile_client_, GetProperties(_, _, _)); 309 310 EXPECT_CALL(mock_profile_client_, 311 GetEntry(dbus::ObjectPath(kUser1ProfilePath), 312 "some_entry_path", 313 _, _)); 314 315 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); 316 message_loop_.RunUntilIdle(); 317} 318 319TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnmanaged) { 320 InitializeStandardProfiles(); 321 SetUpEntry("policy/shill_unmanaged_user_wifi1.json", 322 kUser1ProfilePath, 323 "old_entry_path"); 324 325 scoped_ptr<base::DictionaryValue> expected_shill_properties = 326 test_utils::ReadTestDictionary( 327 "policy/shill_policy_on_unmanaged_user_wifi1.json"); 328 329 EXPECT_CALL(mock_profile_client_, 330 GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); 331 332 EXPECT_CALL(mock_profile_client_, 333 GetEntry(dbus::ObjectPath(kUser1ProfilePath), 334 "old_entry_path", 335 _, _)); 336 337 EXPECT_CALL(mock_manager_client_, 338 ConfigureServiceForProfile( 339 dbus::ObjectPath(kUser1ProfilePath), 340 IsEqualTo(expected_shill_properties.get()), 341 _, _)); 342 343 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); 344 message_loop_.RunUntilIdle(); 345} 346 347TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUpdateManagedNewGUID) { 348 InitializeStandardProfiles(); 349 SetUpEntry("policy/shill_managed_wifi1.json", 350 kUser1ProfilePath, 351 "old_entry_path"); 352 353 scoped_ptr<base::DictionaryValue> expected_shill_properties = 354 test_utils::ReadTestDictionary( 355 "policy/shill_policy_on_unmanaged_user_wifi1.json"); 356 357 // The passphrase isn't sent again, because it's configured by the user and 358 // Shill doesn't sent it on GetProperties calls. 359 expected_shill_properties->RemoveWithoutPathExpansion( 360 flimflam::kPassphraseProperty, NULL); 361 362 EXPECT_CALL(mock_profile_client_, 363 GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); 364 365 EXPECT_CALL(mock_profile_client_, 366 GetEntry(dbus::ObjectPath(kUser1ProfilePath), 367 "old_entry_path", 368 _, _)); 369 370 EXPECT_CALL(mock_manager_client_, 371 ConfigureServiceForProfile( 372 dbus::ObjectPath(kUser1ProfilePath), 373 IsEqualTo(expected_shill_properties.get()), 374 _, _)); 375 376 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); 377 message_loop_.RunUntilIdle(); 378} 379 380TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyReapplyToManaged) { 381 InitializeStandardProfiles(); 382 SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json", 383 kUser1ProfilePath, 384 "old_entry_path"); 385 386 scoped_ptr<base::DictionaryValue> expected_shill_properties = 387 test_utils::ReadTestDictionary( 388 "policy/shill_policy_on_unmanaged_user_wifi1.json"); 389 390 // The passphrase isn't sent again, because it's configured by the user and 391 // Shill doesn't sent it on GetProperties calls. 392 expected_shill_properties->RemoveWithoutPathExpansion( 393 flimflam::kPassphraseProperty, NULL); 394 395 EXPECT_CALL(mock_profile_client_, 396 GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); 397 398 EXPECT_CALL(mock_profile_client_, 399 GetEntry(dbus::ObjectPath(kUser1ProfilePath), 400 "old_entry_path", 401 _, _)); 402 403 EXPECT_CALL(mock_manager_client_, 404 ConfigureServiceForProfile( 405 dbus::ObjectPath(kUser1ProfilePath), 406 IsEqualTo(expected_shill_properties.get()), 407 _, _)); 408 409 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); 410 message_loop_.RunUntilIdle(); 411} 412 413TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUnmanageManaged) { 414 InitializeStandardProfiles(); 415 SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json", 416 kUser1ProfilePath, 417 "old_entry_path"); 418 419 EXPECT_CALL(mock_profile_client_, 420 GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); 421 422 EXPECT_CALL(mock_profile_client_, 423 GetEntry(dbus::ObjectPath(kUser1ProfilePath), 424 "old_entry_path", 425 _, _)); 426 427 EXPECT_CALL(mock_profile_client_, 428 DeleteEntry(dbus::ObjectPath(kUser1ProfilePath), 429 "old_entry_path", 430 _, _)); 431 432 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, ""); 433 message_loop_.RunUntilIdle(); 434} 435 436TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmanaged) { 437 InitializeStandardProfiles(); 438 SetUpEntry("policy/shill_unmanaged_user_wifi1.json", 439 kUser1ProfilePath, 440 "old_entry_path"); 441 442 EXPECT_CALL(mock_profile_client_, 443 GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); 444 445 EXPECT_CALL(mock_profile_client_, 446 GetEntry(dbus::ObjectPath(kUser1ProfilePath), 447 "old_entry_path", 448 _, _)); 449 450 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, ""); 451 message_loop_.RunUntilIdle(); 452} 453 454TEST_F(ManagedNetworkConfigurationHandlerTest, LateProfileLoading) { 455 SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc"); 456 457 message_loop_.RunUntilIdle(); 458 VerifyAndClearExpectations(); 459 460 scoped_ptr<base::DictionaryValue> expected_shill_properties = 461 test_utils::ReadTestDictionary( 462 "policy/shill_policy_on_unconfigured_wifi1.json"); 463 464 EXPECT_CALL(mock_profile_client_, 465 GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); 466 467 EXPECT_CALL(mock_manager_client_, 468 ConfigureServiceForProfile( 469 dbus::ObjectPath(kUser1ProfilePath), 470 IsEqualTo(expected_shill_properties.get()), 471 _, _)); 472 473 InitializeStandardProfiles(); 474 message_loop_.RunUntilIdle(); 475} 476 477} // namespace chromeos 478