| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
| 6 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/json/json_writer.h" | 7 #include "base/json/json_writer.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 PolicyWatcherTest() : message_loop_(base::MessageLoop::TYPE_IO) {} | 56 PolicyWatcherTest() : message_loop_(base::MessageLoop::TYPE_IO) {} |
| 57 | 57 |
| 58 void SetUp() override { | 58 void SetUp() override { |
| 59 message_loop_proxy_ = base::MessageLoopProxy::current(); | 59 message_loop_proxy_ = base::MessageLoopProxy::current(); |
| 60 | 60 |
| 61 // Retaining a raw pointer to keep control over policy contents. | 61 // Retaining a raw pointer to keep control over policy contents. |
| 62 policy_loader_ = new policy::FakeAsyncPolicyLoader(message_loop_proxy_); | 62 policy_loader_ = new policy::FakeAsyncPolicyLoader(message_loop_proxy_); |
| 63 policy_watcher_ = | 63 policy_watcher_ = |
| 64 PolicyWatcher::CreateFromPolicyLoader(make_scoped_ptr(policy_loader_)); | 64 PolicyWatcher::CreateFromPolicyLoader(make_scoped_ptr(policy_loader_)); |
| 65 | 65 |
| 66 schema_ = policy::Schema::Wrap(policy::GetChromeSchemaData()); | |
| 67 | |
| 68 nat_true_.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, true); | 66 nat_true_.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, true); |
| 69 nat_false_.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, | 67 nat_false_.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, |
| 70 false); | 68 false); |
| 71 nat_one_.SetInteger(policy::key::kRemoteAccessHostFirewallTraversal, 1); | 69 nat_one_.SetInteger(policy::key::kRemoteAccessHostFirewallTraversal, 1); |
| 72 domain_empty_.SetString(policy::key::kRemoteAccessHostDomain, | 70 domain_empty_.SetString(policy::key::kRemoteAccessHostDomain, |
| 73 std::string()); | 71 std::string()); |
| 74 domain_full_.SetString(policy::key::kRemoteAccessHostDomain, kHostDomain); | 72 domain_full_.SetString(policy::key::kRemoteAccessHostDomain, kHostDomain); |
| 75 SetDefaults(nat_true_others_default_); | 73 SetDefaults(nat_true_others_default_); |
| 76 nat_true_others_default_.SetBoolean( | 74 nat_true_others_default_.SetBoolean( |
| 77 policy::key::kRemoteAccessHostFirewallTraversal, true); | 75 policy::key::kRemoteAccessHostFirewallTraversal, true); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 policy::PolicyMap& policy_map = policy_bundle.Get(policy_namespace); | 164 policy::PolicyMap& policy_map = policy_bundle.Get(policy_namespace); |
| 167 policy_map.LoadFrom(&dict, policy::POLICY_LEVEL_MANDATORY, | 165 policy_map.LoadFrom(&dict, policy::POLICY_LEVEL_MANDATORY, |
| 168 policy::POLICY_SCOPE_MACHINE); | 166 policy::POLICY_SCOPE_MACHINE); |
| 169 | 167 |
| 170 // Simulate a policy file/registry/preference update. | 168 // Simulate a policy file/registry/preference update. |
| 171 policy_loader_->SetPolicies(policy_bundle); | 169 policy_loader_->SetPolicies(policy_bundle); |
| 172 policy_loader_->PostReloadOnBackgroundThread(true /* force reload asap */); | 170 policy_loader_->PostReloadOnBackgroundThread(true /* force reload asap */); |
| 173 base::RunLoop().RunUntilIdle(); | 171 base::RunLoop().RunUntilIdle(); |
| 174 } | 172 } |
| 175 | 173 |
| 176 void SignalTransientErrorForTest() { | 174 const policy::Schema* GetPolicySchema() { |
| 177 policy_watcher_->SignalTransientPolicyError(); | 175 return policy_watcher_->GetPolicySchema(); |
| 178 } | 176 } |
| 179 | 177 |
| 180 const policy::Schema* GetPolicySchema() { return &schema_; } | |
| 181 | |
| 182 const base::DictionaryValue& GetDefaultValues() { | 178 const base::DictionaryValue& GetDefaultValues() { |
| 183 return *(policy_watcher_->default_values_); | 179 return *(policy_watcher_->default_values_); |
| 184 } | 180 } |
| 185 | 181 |
| 186 MOCK_METHOD0(PostPolicyWatcherShutdown, void()); | 182 MOCK_METHOD0(PostPolicyWatcherShutdown, void()); |
| 187 | 183 |
| 188 static const char* kHostDomain; | 184 static const char* kHostDomain; |
| 189 static const char* kPortRange; | 185 static const char* kPortRange; |
| 190 base::MessageLoop message_loop_; | 186 base::MessageLoop message_loop_; |
| 191 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; | 187 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 217 base::DictionaryValue nat_false_overridden_others_default_; | 213 base::DictionaryValue nat_false_overridden_others_default_; |
| 218 base::DictionaryValue pairing_true_; | 214 base::DictionaryValue pairing_true_; |
| 219 base::DictionaryValue pairing_false_; | 215 base::DictionaryValue pairing_false_; |
| 220 base::DictionaryValue gnubby_auth_true_; | 216 base::DictionaryValue gnubby_auth_true_; |
| 221 base::DictionaryValue gnubby_auth_false_; | 217 base::DictionaryValue gnubby_auth_false_; |
| 222 base::DictionaryValue relay_true_; | 218 base::DictionaryValue relay_true_; |
| 223 base::DictionaryValue relay_false_; | 219 base::DictionaryValue relay_false_; |
| 224 base::DictionaryValue port_range_full_; | 220 base::DictionaryValue port_range_full_; |
| 225 base::DictionaryValue port_range_empty_; | 221 base::DictionaryValue port_range_empty_; |
| 226 | 222 |
| 227 policy::Schema schema_; | |
| 228 | |
| 229 private: | 223 private: |
| 230 void SetDefaults(base::DictionaryValue& dict) { | 224 void SetDefaults(base::DictionaryValue& dict) { |
| 231 dict.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, true); | 225 dict.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, true); |
| 232 dict.SetBoolean(policy::key::kRemoteAccessHostAllowRelayedConnection, true); | 226 dict.SetBoolean(policy::key::kRemoteAccessHostAllowRelayedConnection, true); |
| 233 dict.SetString(policy::key::kRemoteAccessHostUdpPortRange, ""); | 227 dict.SetString(policy::key::kRemoteAccessHostUdpPortRange, ""); |
| 234 dict.SetString(policy::key::kRemoteAccessHostDomain, std::string()); | 228 dict.SetString(policy::key::kRemoteAccessHostDomain, std::string()); |
| 235 dict.SetBoolean(policy::key::kRemoteAccessHostMatchUsername, false); | 229 dict.SetBoolean(policy::key::kRemoteAccessHostMatchUsername, false); |
| 236 dict.SetString(policy::key::kRemoteAccessHostTalkGadgetPrefix, | 230 dict.SetString(policy::key::kRemoteAccessHostTalkGadgetPrefix, |
| 237 kDefaultHostTalkGadgetPrefix); | 231 kDefaultHostTalkGadgetPrefix); |
| 238 dict.SetBoolean(policy::key::kRemoteAccessHostRequireCurtain, false); | 232 dict.SetBoolean(policy::key::kRemoteAccessHostRequireCurtain, false); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 } | 268 } |
| 275 | 269 |
| 276 TEST_F(PolicyWatcherTest, NatFalse) { | 270 TEST_F(PolicyWatcherTest, NatFalse) { |
| 277 EXPECT_CALL(mock_policy_callback_, | 271 EXPECT_CALL(mock_policy_callback_, |
| 278 OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_))); | 272 OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_))); |
| 279 | 273 |
| 280 SetPolicies(nat_false_); | 274 SetPolicies(nat_false_); |
| 281 StartWatching(); | 275 StartWatching(); |
| 282 } | 276 } |
| 283 | 277 |
| 284 TEST_F(PolicyWatcherTest, NatOne) { | 278 TEST_F(PolicyWatcherTest, NatWrongType) { |
| 285 EXPECT_CALL(mock_policy_callback_, | 279 EXPECT_CALL(mock_policy_callback_, OnPolicyError()); |
| 286 OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_))); | |
| 287 | 280 |
| 288 SetPolicies(nat_one_); | 281 SetPolicies(nat_one_); |
| 289 StartWatching(); | 282 StartWatching(); |
| 290 } | 283 } |
| 291 | 284 |
| 292 TEST_F(PolicyWatcherTest, DomainEmpty) { | 285 TEST_F(PolicyWatcherTest, DomainEmpty) { |
| 293 EXPECT_CALL(mock_policy_callback_, | 286 EXPECT_CALL(mock_policy_callback_, |
| 294 OnPolicyUpdatePtr(IsPolicies(&domain_empty_others_default_))); | 287 OnPolicyUpdatePtr(IsPolicies(&domain_empty_others_default_))); |
| 295 | 288 |
| 296 SetPolicies(domain_empty_); | 289 SetPolicies(domain_empty_); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 OnPolicyUpdatePtr(IsPolicies(&port_range_full_))); | 457 OnPolicyUpdatePtr(IsPolicies(&port_range_full_))); |
| 465 EXPECT_CALL(mock_policy_callback_, | 458 EXPECT_CALL(mock_policy_callback_, |
| 466 OnPolicyUpdatePtr(IsPolicies(&port_range_empty_))); | 459 OnPolicyUpdatePtr(IsPolicies(&port_range_empty_))); |
| 467 | 460 |
| 468 SetPolicies(empty_); | 461 SetPolicies(empty_); |
| 469 StartWatching(); | 462 StartWatching(); |
| 470 SetPolicies(port_range_full_); | 463 SetPolicies(port_range_full_); |
| 471 SetPolicies(port_range_empty_); | 464 SetPolicies(port_range_empty_); |
| 472 } | 465 } |
| 473 | 466 |
| 474 const int kMaxTransientErrorRetries = 5; | |
| 475 | |
| 476 TEST_F(PolicyWatcherTest, SingleTransientErrorDoesntTriggerErrorCallback) { | |
| 477 EXPECT_CALL(mock_policy_callback_, OnPolicyError()).Times(0); | |
| 478 | |
| 479 StartWatching(); | |
| 480 SignalTransientErrorForTest(); | |
| 481 } | |
| 482 | |
| 483 TEST_F(PolicyWatcherTest, MultipleTransientErrorsTriggerErrorCallback) { | |
| 484 EXPECT_CALL(mock_policy_callback_, OnPolicyError()); | |
| 485 | |
| 486 StartWatching(); | |
| 487 for (int i = 0; i < kMaxTransientErrorRetries; i++) { | |
| 488 SignalTransientErrorForTest(); | |
| 489 } | |
| 490 } | |
| 491 | |
| 492 TEST_F(PolicyWatcherTest, PolicyUpdateResetsTransientErrorsCounter) { | |
| 493 testing::InSequence s; | |
| 494 EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(testing::_)); | |
| 495 EXPECT_CALL(mock_policy_callback_, OnPolicyError()).Times(0); | |
| 496 | |
| 497 StartWatching(); | |
| 498 for (int i = 0; i < (kMaxTransientErrorRetries - 1); i++) { | |
| 499 SignalTransientErrorForTest(); | |
| 500 } | |
| 501 SetPolicies(nat_true_); | |
| 502 for (int i = 0; i < (kMaxTransientErrorRetries - 1); i++) { | |
| 503 SignalTransientErrorForTest(); | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 TEST_F(PolicyWatcherTest, PolicySchemaAndPolicyWatcherShouldBeInSync) { | 467 TEST_F(PolicyWatcherTest, PolicySchemaAndPolicyWatcherShouldBeInSync) { |
| 508 // This test verifies that | 468 // This test verifies that |
| 509 // 1) policy schema (generated out of policy_templates.json) | 469 // 1) policy schema (generated out of policy_templates.json) |
| 510 // and | 470 // and |
| 511 // 2) PolicyWatcher's code (i.e. contents of the |default_values_| field) | 471 // 2) PolicyWatcher's code (i.e. contents of the |default_values_| field) |
| 512 // are kept in-sync. | 472 // are kept in-sync. |
| 513 | 473 |
| 514 std::set<std::string> expected_schema_keys; | 474 std::map<std::string, base::Value::Type> expected_schema; |
| 515 for (base::DictionaryValue::Iterator i(GetDefaultValues()); !i.IsAtEnd(); | 475 for (base::DictionaryValue::Iterator i(GetDefaultValues()); !i.IsAtEnd(); |
| 516 i.Advance()) { | 476 i.Advance()) { |
| 517 expected_schema_keys.insert(i.key()); | 477 expected_schema[i.key()] = i.value().GetType(); |
| 518 } | 478 } |
| 519 #if defined(OS_WIN) | 479 #if defined(OS_WIN) |
| 520 // RemoteAccessHostMatchUsername is marked in policy_templates.json as not | 480 // RemoteAccessHostMatchUsername is marked in policy_templates.json as not |
| 521 // supported on Windows and therefore is (by design) excluded from the schema. | 481 // supported on Windows and therefore is (by design) excluded from the schema. |
| 522 expected_schema_keys.erase(policy::key::kRemoteAccessHostMatchUsername); | 482 expected_schema.erase(policy::key::kRemoteAccessHostMatchUsername); |
| 523 #endif | 483 #endif |
| 524 #if defined(NDEBUG) | 484 #if defined(NDEBUG) |
| 525 // Policy schema / policy_templates.json cannot differ between debug and | 485 // Policy schema / policy_templates.json cannot differ between debug and |
| 526 // release builds so we compensate below to account for the fact that | 486 // release builds so we compensate below to account for the fact that |
| 527 // PolicyWatcher::default_values_ does differ between debug and release. | 487 // PolicyWatcher::default_values_ does differ between debug and release. |
| 528 expected_schema_keys.insert( | 488 expected_schema[policy::key::kRemoteAccessHostDebugOverridePolicies] = |
| 529 policy::key::kRemoteAccessHostDebugOverridePolicies); | 489 base::Value::TYPE_STRING; |
| 530 #endif | 490 #endif |
| 531 | 491 |
| 532 std::set<std::string> actual_schema_keys; | 492 std::map<std::string, base::Value::Type> actual_schema; |
| 533 const policy::Schema* schema = GetPolicySchema(); | 493 const policy::Schema* schema = GetPolicySchema(); |
| 534 ASSERT_TRUE(schema->valid()); | 494 ASSERT_TRUE(schema->valid()); |
| 535 for (auto it = schema->GetPropertiesIterator(); !it.IsAtEnd(); it.Advance()) { | 495 for (auto it = schema->GetPropertiesIterator(); !it.IsAtEnd(); it.Advance()) { |
| 536 std::string key = it.key(); | 496 std::string key = it.key(); |
| 537 if (key.find("RemoteAccessHost") == std::string::npos) { | 497 if (key.find("RemoteAccessHost") == std::string::npos) { |
| 538 // For now PolicyWatcher::GetPolicySchema() mixes Chrome and Chromoting | 498 // For now PolicyWatcher::GetPolicySchema() mixes Chrome and Chromoting |
| 539 // policies, so we have to skip them here. | 499 // policies, so we have to skip them here. |
| 540 continue; | 500 continue; |
| 541 } | 501 } |
| 542 actual_schema_keys.insert(key); | 502 actual_schema[key] = it.schema().type(); |
| 543 } | 503 } |
| 544 | 504 |
| 545 EXPECT_THAT(actual_schema_keys, testing::ContainerEq(expected_schema_keys)); | 505 EXPECT_THAT(actual_schema, testing::ContainerEq(expected_schema)); |
| 506 } |
| 507 |
| 508 TEST_F(PolicyWatcherTest, SchemaTypeCheck) { |
| 509 const policy::Schema* schema = GetPolicySchema(); |
| 510 ASSERT_TRUE(schema->valid()); |
| 511 |
| 512 // Check one, random "string" policy to see if the type propagated correctly |
| 513 // from policy_templates.json file. |
| 514 const policy::Schema string_schema = |
| 515 schema->GetKnownProperty("RemoteAccessHostDomain"); |
| 516 EXPECT_TRUE(string_schema.valid()); |
| 517 EXPECT_EQ(string_schema.type(), base::Value::Type::TYPE_STRING); |
| 518 |
| 519 // And check one, random "boolean" policy to see if the type propagated |
| 520 // correctly from policy_templates.json file. |
| 521 const policy::Schema boolean_schema = |
| 522 schema->GetKnownProperty("RemoteAccessHostRequireCurtain"); |
| 523 EXPECT_TRUE(boolean_schema.valid()); |
| 524 EXPECT_EQ(boolean_schema.type(), base::Value::Type::TYPE_BOOLEAN); |
| 546 } | 525 } |
| 547 | 526 |
| 548 // Unit tests cannot instantiate PolicyWatcher on ChromeOS | 527 // Unit tests cannot instantiate PolicyWatcher on ChromeOS |
| 549 // (as this requires running inside a browser process). | 528 // (as this requires running inside a browser process). |
| 550 #ifndef OS_CHROMEOS | 529 #ifndef OS_CHROMEOS |
| 551 | 530 |
| 552 namespace { | 531 namespace { |
| 553 | 532 |
| 554 void OnPolicyUpdatedDumpPolicy(scoped_ptr<base::DictionaryValue> policies) { | 533 void OnPolicyUpdatedDumpPolicy(scoped_ptr<base::DictionaryValue> policies) { |
| 555 VLOG(1) << "OnPolicyUpdated callback received the following policies:"; | 534 VLOG(1) << "OnPolicyUpdated callback received the following policies:"; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 } | 577 } |
| 599 | 578 |
| 600 // Today, the only verification offered by this test is: | 579 // Today, the only verification offered by this test is: |
| 601 // - Manual verification of policy values dumped by OnPolicyUpdatedDumpPolicy | 580 // - Manual verification of policy values dumped by OnPolicyUpdatedDumpPolicy |
| 602 // - Automated verification that nothing crashed | 581 // - Automated verification that nothing crashed |
| 603 } | 582 } |
| 604 | 583 |
| 605 #endif | 584 #endif |
| 606 | 585 |
| 607 } // namespace remoting | 586 } // namespace remoting |
| OLD | NEW |