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 |