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
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
7 #include "base/json/json_writer.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/test/mock_log.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "components/policy/core/common/fake_async_policy_loader.h"
15 #include "policy/policy_constants.h"
16 #include "remoting/host/dns_blackhole_checker.h"
17 #include "remoting/host/policy_watcher.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
23 namespace key
= ::policy::key
;
25 MATCHER_P(IsPolicies
, dict
, "") {
26 bool equal
= arg
->Equals(dict
);
28 std::string actual_value
;
29 base::JSONWriter::WriteWithOptions(
30 *arg
, base::JSONWriter::OPTIONS_PRETTY_PRINT
, &actual_value
);
32 std::string expected_value
;
33 base::JSONWriter::WriteWithOptions(
34 *dict
, base::JSONWriter::OPTIONS_PRETTY_PRINT
, &expected_value
);
36 *result_listener
<< "Policies are not equal. ";
37 *result_listener
<< "Expected policy: " << expected_value
<< ". ";
38 *result_listener
<< "Actual policy: " << actual_value
<< ".";
43 class MockPolicyCallback
{
45 MockPolicyCallback(){};
47 // TODO(lukasza): gmock cannot mock a method taking scoped_ptr<T>...
48 MOCK_METHOD1(OnPolicyUpdatePtr
, void(const base::DictionaryValue
* policies
));
49 void OnPolicyUpdate(scoped_ptr
<base::DictionaryValue
> policies
) {
50 OnPolicyUpdatePtr(policies
.get());
53 MOCK_METHOD0(OnPolicyError
, void());
56 DISALLOW_COPY_AND_ASSIGN(MockPolicyCallback
);
59 class PolicyWatcherTest
: public testing::Test
{
61 PolicyWatcherTest() : message_loop_(base::MessageLoop::TYPE_IO
) {}
63 void SetUp() override
{
64 // We expect no callbacks unless explicitly specified by individual tests.
65 EXPECT_CALL(mock_policy_callback_
, OnPolicyUpdatePtr(testing::_
)).Times(0);
66 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(0);
68 // Retaining a raw pointer to keep control over policy contents.
70 new policy::FakeAsyncPolicyLoader(base::ThreadTaskRunnerHandle::Get());
72 PolicyWatcher::CreateFromPolicyLoader(make_scoped_ptr(policy_loader_
));
74 nat_true_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
, true);
75 nat_false_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
, false);
76 nat_one_
.SetInteger(key::kRemoteAccessHostFirewallTraversal
, 1);
77 nat_one_domain_full_
.SetInteger(key::kRemoteAccessHostFirewallTraversal
, 1);
78 nat_one_domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
79 domain_empty_
.SetString(key::kRemoteAccessHostDomain
, std::string());
80 domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
81 SetDefaults(nat_true_others_default_
);
82 nat_true_others_default_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
84 SetDefaults(nat_false_others_default_
);
85 nat_false_others_default_
.SetBoolean(
86 key::kRemoteAccessHostFirewallTraversal
, false);
87 SetDefaults(domain_empty_others_default_
);
88 domain_empty_others_default_
.SetString(key::kRemoteAccessHostDomain
,
90 SetDefaults(domain_full_others_default_
);
91 domain_full_others_default_
.SetString(key::kRemoteAccessHostDomain
,
93 nat_true_domain_empty_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
95 nat_true_domain_empty_
.SetString(key::kRemoteAccessHostDomain
,
97 nat_true_domain_full_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
99 nat_true_domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
100 nat_false_domain_empty_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
102 nat_false_domain_empty_
.SetString(key::kRemoteAccessHostDomain
,
104 nat_false_domain_full_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
106 nat_false_domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
107 SetDefaults(nat_true_domain_empty_others_default_
);
108 nat_true_domain_empty_others_default_
.SetBoolean(
109 key::kRemoteAccessHostFirewallTraversal
, true);
110 nat_true_domain_empty_others_default_
.SetString(
111 key::kRemoteAccessHostDomain
, std::string());
112 unknown_policies_
.SetString("UnknownPolicyOne", std::string());
113 unknown_policies_
.SetString("UnknownPolicyTwo", std::string());
114 unknown_policies_
.SetBoolean("RemoteAccessHostUnknownPolicyThree", true);
116 const char kOverrideNatTraversalToFalse
[] =
117 "{ \"RemoteAccessHostFirewallTraversal\": false }";
118 nat_true_and_overridden_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
120 nat_true_and_overridden_
.SetString(
121 key::kRemoteAccessHostDebugOverridePolicies
,
122 kOverrideNatTraversalToFalse
);
123 pairing_true_
.SetBoolean(key::kRemoteAccessHostAllowClientPairing
, true);
124 pairing_false_
.SetBoolean(key::kRemoteAccessHostAllowClientPairing
, false);
125 gnubby_auth_true_
.SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth
, true);
126 gnubby_auth_false_
.SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth
, false);
127 relay_true_
.SetBoolean(key::kRemoteAccessHostAllowRelayedConnection
, true);
128 relay_false_
.SetBoolean(key::kRemoteAccessHostAllowRelayedConnection
,
130 port_range_full_
.SetString(key::kRemoteAccessHostUdpPortRange
, kPortRange
);
131 port_range_empty_
.SetString(key::kRemoteAccessHostUdpPortRange
,
133 port_range_malformed_
.SetString(key::kRemoteAccessHostUdpPortRange
,
135 port_range_malformed_domain_full_
.MergeDictionary(&port_range_malformed_
);
136 port_range_malformed_domain_full_
.SetString(key::kRemoteAccessHostDomain
,
139 curtain_true_
.SetBoolean(key::kRemoteAccessHostRequireCurtain
, true);
140 curtain_false_
.SetBoolean(key::kRemoteAccessHostRequireCurtain
, false);
141 username_true_
.SetBoolean(key::kRemoteAccessHostMatchUsername
, true);
142 username_false_
.SetBoolean(key::kRemoteAccessHostMatchUsername
, false);
143 talk_gadget_blah_
.SetString(key::kRemoteAccessHostTalkGadgetPrefix
, "blah");
144 third_party_auth_partial_
.SetString(key::kRemoteAccessHostTokenUrl
,
145 "https://token.com");
146 third_party_auth_partial_
.SetString(
147 key::kRemoteAccessHostTokenValidationUrl
, "https://validation.com");
148 third_party_auth_full_
.MergeDictionary(&third_party_auth_partial_
);
149 third_party_auth_full_
.SetString(
150 key::kRemoteAccessHostTokenValidationCertificateIssuer
,
151 "certificate subject");
152 third_party_auth_cert_empty_
.MergeDictionary(&third_party_auth_partial_
);
153 third_party_auth_cert_empty_
.SetString(
154 key::kRemoteAccessHostTokenValidationCertificateIssuer
, "");
157 SetDefaults(nat_false_overridden_others_default_
);
158 nat_false_overridden_others_default_
.SetBoolean(
159 key::kRemoteAccessHostFirewallTraversal
, false);
160 nat_false_overridden_others_default_
.SetString(
161 key::kRemoteAccessHostDebugOverridePolicies
,
162 kOverrideNatTraversalToFalse
);
166 void TearDown() override
{
167 policy_watcher_
.reset();
168 policy_loader_
= nullptr;
169 base::RunLoop().RunUntilIdle();
173 void StartWatching() {
174 policy_watcher_
->StartWatching(
175 base::Bind(&MockPolicyCallback::OnPolicyUpdate
,
176 base::Unretained(&mock_policy_callback_
)),
177 base::Bind(&MockPolicyCallback::OnPolicyError
,
178 base::Unretained(&mock_policy_callback_
)));
179 base::RunLoop().RunUntilIdle();
182 void SetPolicies(const base::DictionaryValue
& dict
) {
183 // Copy |dict| into |policy_bundle|.
184 policy::PolicyNamespace policy_namespace
=
185 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME
, std::string());
186 policy::PolicyBundle policy_bundle
;
187 policy::PolicyMap
& policy_map
= policy_bundle
.Get(policy_namespace
);
188 policy_map
.LoadFrom(&dict
, policy::POLICY_LEVEL_MANDATORY
,
189 policy::POLICY_SCOPE_MACHINE
);
191 // Simulate a policy file/registry/preference update.
192 policy_loader_
->SetPolicies(policy_bundle
);
193 policy_loader_
->PostReloadOnBackgroundThread(true /* force reload asap */);
194 base::RunLoop().RunUntilIdle();
197 const policy::Schema
* GetPolicySchema() {
198 return policy_watcher_
->GetPolicySchema();
201 const base::DictionaryValue
& GetDefaultValues() {
202 return *(policy_watcher_
->default_values_
);
205 MOCK_METHOD0(PostPolicyWatcherShutdown
, void());
207 static const char* kHostDomain
;
208 static const char* kPortRange
;
209 base::MessageLoop message_loop_
;
210 MockPolicyCallback mock_policy_callback_
;
212 // |policy_loader_| is owned by |policy_watcher_|. PolicyWatcherTest retains
213 // a raw pointer to |policy_loader_| in order to control the simulated / faked
215 policy::FakeAsyncPolicyLoader
* policy_loader_
;
216 scoped_ptr
<PolicyWatcher
> policy_watcher_
;
218 base::DictionaryValue empty_
;
219 base::DictionaryValue nat_true_
;
220 base::DictionaryValue nat_false_
;
221 base::DictionaryValue nat_one_
;
222 base::DictionaryValue nat_one_domain_full_
;
223 base::DictionaryValue domain_empty_
;
224 base::DictionaryValue domain_full_
;
225 base::DictionaryValue nat_true_others_default_
;
226 base::DictionaryValue nat_false_others_default_
;
227 base::DictionaryValue domain_empty_others_default_
;
228 base::DictionaryValue domain_full_others_default_
;
229 base::DictionaryValue nat_true_domain_empty_
;
230 base::DictionaryValue nat_true_domain_full_
;
231 base::DictionaryValue nat_false_domain_empty_
;
232 base::DictionaryValue nat_false_domain_full_
;
233 base::DictionaryValue nat_true_domain_empty_others_default_
;
234 base::DictionaryValue unknown_policies_
;
235 base::DictionaryValue nat_true_and_overridden_
;
236 base::DictionaryValue nat_false_overridden_others_default_
;
237 base::DictionaryValue pairing_true_
;
238 base::DictionaryValue pairing_false_
;
239 base::DictionaryValue gnubby_auth_true_
;
240 base::DictionaryValue gnubby_auth_false_
;
241 base::DictionaryValue relay_true_
;
242 base::DictionaryValue relay_false_
;
243 base::DictionaryValue port_range_full_
;
244 base::DictionaryValue port_range_empty_
;
245 base::DictionaryValue port_range_malformed_
;
246 base::DictionaryValue port_range_malformed_domain_full_
;
247 base::DictionaryValue curtain_true_
;
248 base::DictionaryValue curtain_false_
;
249 base::DictionaryValue username_true_
;
250 base::DictionaryValue username_false_
;
251 base::DictionaryValue talk_gadget_blah_
;
252 base::DictionaryValue third_party_auth_full_
;
253 base::DictionaryValue third_party_auth_partial_
;
254 base::DictionaryValue third_party_auth_cert_empty_
;
257 void SetDefaults(base::DictionaryValue
& dict
) {
258 dict
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
, true);
259 dict
.SetBoolean(key::kRemoteAccessHostAllowRelayedConnection
, true);
260 dict
.SetString(key::kRemoteAccessHostUdpPortRange
, "");
261 dict
.SetString(key::kRemoteAccessHostDomain
, std::string());
262 dict
.SetBoolean(key::kRemoteAccessHostMatchUsername
, false);
263 dict
.SetString(key::kRemoteAccessHostTalkGadgetPrefix
,
264 kDefaultHostTalkGadgetPrefix
);
265 dict
.SetBoolean(key::kRemoteAccessHostRequireCurtain
, false);
266 dict
.SetString(key::kRemoteAccessHostTokenUrl
, "");
267 dict
.SetString(key::kRemoteAccessHostTokenValidationUrl
, "");
268 dict
.SetString(key::kRemoteAccessHostTokenValidationCertificateIssuer
, "");
269 dict
.SetBoolean(key::kRemoteAccessHostAllowClientPairing
, true);
270 dict
.SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth
, true);
272 dict
.SetString(key::kRemoteAccessHostDebugOverridePolicies
, "");
275 ASSERT_THAT(&dict
, IsPolicies(&GetDefaultValues()))
276 << "Sanity check that defaults expected by the test code "
277 << "match what is stored in PolicyWatcher::default_values_";
281 const char* PolicyWatcherTest::kHostDomain
= "google.com";
282 const char* PolicyWatcherTest::kPortRange
= "12400-12409";
284 TEST_F(PolicyWatcherTest
, None
) {
285 EXPECT_CALL(mock_policy_callback_
,
286 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
292 TEST_F(PolicyWatcherTest
, NatTrue
) {
293 EXPECT_CALL(mock_policy_callback_
,
294 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
296 SetPolicies(nat_true_
);
300 TEST_F(PolicyWatcherTest
, NatFalse
) {
301 EXPECT_CALL(mock_policy_callback_
,
302 OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_
)));
304 SetPolicies(nat_false_
);
308 TEST_F(PolicyWatcherTest
, NatWrongType
) {
309 EXPECT_CALL(mock_policy_callback_
, OnPolicyError());
311 SetPolicies(nat_one_
);
315 // This test verifies that a mistyped policy value is still detected
316 // even though it doesn't change during the second SetPolicies call.
317 TEST_F(PolicyWatcherTest
, NatWrongTypeThenIrrelevantChange
) {
318 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(2);
320 SetPolicies(nat_one_
);
322 SetPolicies(nat_one_domain_full_
);
325 // This test verifies that a malformed policy value is still detected
326 // even though it doesn't change during the second SetPolicies call.
327 TEST_F(PolicyWatcherTest
, PortRangeMalformedThenIrrelevantChange
) {
328 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(2);
330 SetPolicies(port_range_malformed_
);
332 SetPolicies(port_range_malformed_domain_full_
);
335 TEST_F(PolicyWatcherTest
, DomainEmpty
) {
336 EXPECT_CALL(mock_policy_callback_
,
337 OnPolicyUpdatePtr(IsPolicies(&domain_empty_others_default_
)));
339 SetPolicies(domain_empty_
);
343 TEST_F(PolicyWatcherTest
, DomainFull
) {
344 EXPECT_CALL(mock_policy_callback_
,
345 OnPolicyUpdatePtr(IsPolicies(&domain_full_others_default_
)));
347 SetPolicies(domain_full_
);
351 TEST_F(PolicyWatcherTest
, NatNoneThenTrue
) {
352 EXPECT_CALL(mock_policy_callback_
,
353 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
357 SetPolicies(nat_true_
);
360 TEST_F(PolicyWatcherTest
, NatNoneThenTrueThenTrue
) {
361 EXPECT_CALL(mock_policy_callback_
,
362 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
366 SetPolicies(nat_true_
);
367 SetPolicies(nat_true_
);
370 TEST_F(PolicyWatcherTest
, NatNoneThenTrueThenTrueThenFalse
) {
371 testing::InSequence sequence
;
372 EXPECT_CALL(mock_policy_callback_
,
373 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
374 EXPECT_CALL(mock_policy_callback_
,
375 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
379 SetPolicies(nat_true_
);
380 SetPolicies(nat_true_
);
381 SetPolicies(nat_false_
);
384 TEST_F(PolicyWatcherTest
, NatNoneThenFalse
) {
385 testing::InSequence sequence
;
386 EXPECT_CALL(mock_policy_callback_
,
387 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
388 EXPECT_CALL(mock_policy_callback_
,
389 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
393 SetPolicies(nat_false_
);
396 TEST_F(PolicyWatcherTest
, NatNoneThenFalseThenTrue
) {
397 testing::InSequence sequence
;
398 EXPECT_CALL(mock_policy_callback_
,
399 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
400 EXPECT_CALL(mock_policy_callback_
,
401 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
402 EXPECT_CALL(mock_policy_callback_
, OnPolicyUpdatePtr(IsPolicies(&nat_true_
)));
406 SetPolicies(nat_false_
);
407 SetPolicies(nat_true_
);
410 TEST_F(PolicyWatcherTest
, ChangeOneRepeatedlyThenTwo
) {
411 testing::InSequence sequence
;
413 mock_policy_callback_
,
414 OnPolicyUpdatePtr(IsPolicies(&nat_true_domain_empty_others_default_
)));
415 EXPECT_CALL(mock_policy_callback_
,
416 OnPolicyUpdatePtr(IsPolicies(&domain_full_
)));
417 EXPECT_CALL(mock_policy_callback_
,
418 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
419 EXPECT_CALL(mock_policy_callback_
,
420 OnPolicyUpdatePtr(IsPolicies(&domain_empty_
)));
421 EXPECT_CALL(mock_policy_callback_
,
422 OnPolicyUpdatePtr(IsPolicies(&nat_true_domain_full_
)));
424 SetPolicies(nat_true_domain_empty_
);
426 SetPolicies(nat_true_domain_full_
);
427 SetPolicies(nat_false_domain_full_
);
428 SetPolicies(nat_false_domain_empty_
);
429 SetPolicies(nat_true_domain_full_
);
432 TEST_F(PolicyWatcherTest
, FilterUnknownPolicies
) {
433 testing::InSequence sequence
;
434 EXPECT_CALL(mock_policy_callback_
,
435 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
439 SetPolicies(unknown_policies_
);
443 class MisspelledPolicyTest
: public PolicyWatcherTest
,
444 public ::testing::WithParamInterface
<const char*> {
447 // Verify that a misspelled policy causes a warning written to the log.
448 TEST_P(MisspelledPolicyTest
, WarningLogged
) {
449 const char* misspelled_policy_name
= GetParam();
450 base::test::MockLog mock_log
;
452 ON_CALL(mock_log
, Log(testing::_
, testing::_
, testing::_
, testing::_
,
453 testing::_
)).WillByDefault(testing::Return(true));
455 EXPECT_CALL(mock_log
,
456 Log(logging::LOG_WARNING
, testing::_
, testing::_
, testing::_
,
457 testing::HasSubstr(misspelled_policy_name
))).Times(1);
459 EXPECT_CALL(mock_policy_callback_
,
460 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
462 base::DictionaryValue misspelled_policies
;
463 misspelled_policies
.SetString(misspelled_policy_name
, "some test value");
464 mock_log
.StartCapturingLogs();
466 SetPolicies(misspelled_policies
);
469 mock_log
.StopCapturingLogs();
472 INSTANTIATE_TEST_CASE_P(
474 MisspelledPolicyTest
,
475 ::testing::Values("RemoteAccessHostDomainX",
476 "XRemoteAccessHostDomain",
477 "RemoteAccessHostdomain",
478 "RemoteAccessHostPolicyForFutureVersion"));
480 TEST_F(PolicyWatcherTest
, DebugOverrideNatPolicy
) {
483 mock_policy_callback_
,
484 OnPolicyUpdatePtr(IsPolicies(&nat_false_overridden_others_default_
)));
486 EXPECT_CALL(mock_policy_callback_
,
487 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
490 SetPolicies(nat_true_and_overridden_
);
494 TEST_F(PolicyWatcherTest
, PairingFalseThenTrue
) {
495 testing::InSequence sequence
;
496 EXPECT_CALL(mock_policy_callback_
,
497 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
498 EXPECT_CALL(mock_policy_callback_
,
499 OnPolicyUpdatePtr(IsPolicies(&pairing_false_
)));
500 EXPECT_CALL(mock_policy_callback_
,
501 OnPolicyUpdatePtr(IsPolicies(&pairing_true_
)));
505 SetPolicies(pairing_false_
);
506 SetPolicies(pairing_true_
);
509 TEST_F(PolicyWatcherTest
, GnubbyAuth
) {
510 testing::InSequence sequence
;
511 EXPECT_CALL(mock_policy_callback_
,
512 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
513 EXPECT_CALL(mock_policy_callback_
,
514 OnPolicyUpdatePtr(IsPolicies(&gnubby_auth_false_
)));
515 EXPECT_CALL(mock_policy_callback_
,
516 OnPolicyUpdatePtr(IsPolicies(&gnubby_auth_true_
)));
520 SetPolicies(gnubby_auth_false_
);
521 SetPolicies(gnubby_auth_true_
);
524 TEST_F(PolicyWatcherTest
, Relay
) {
525 testing::InSequence sequence
;
526 EXPECT_CALL(mock_policy_callback_
,
527 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
528 EXPECT_CALL(mock_policy_callback_
,
529 OnPolicyUpdatePtr(IsPolicies(&relay_false_
)));
530 EXPECT_CALL(mock_policy_callback_
,
531 OnPolicyUpdatePtr(IsPolicies(&relay_true_
)));
535 SetPolicies(relay_false_
);
536 SetPolicies(relay_true_
);
539 TEST_F(PolicyWatcherTest
, Curtain
) {
540 testing::InSequence sequence
;
541 EXPECT_CALL(mock_policy_callback_
,
542 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
543 EXPECT_CALL(mock_policy_callback_
,
544 OnPolicyUpdatePtr(IsPolicies(&curtain_true_
)));
545 EXPECT_CALL(mock_policy_callback_
,
546 OnPolicyUpdatePtr(IsPolicies(&curtain_false_
)));
550 SetPolicies(curtain_true_
);
551 SetPolicies(curtain_false_
);
554 TEST_F(PolicyWatcherTest
, MatchUsername
) {
555 testing::InSequence sequence
;
556 EXPECT_CALL(mock_policy_callback_
,
557 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
559 EXPECT_CALL(mock_policy_callback_
,
560 OnPolicyUpdatePtr(IsPolicies(&username_true_
)));
561 EXPECT_CALL(mock_policy_callback_
,
562 OnPolicyUpdatePtr(IsPolicies(&username_false_
)));
564 // On Windows the MatchUsername policy is ignored and therefore the 2
565 // SetPolicies calls won't result in any calls to OnPolicyUpdate.
570 SetPolicies(username_true_
);
571 SetPolicies(username_false_
);
574 TEST_F(PolicyWatcherTest
, TalkGadgetPrefix
) {
575 testing::InSequence sequence
;
576 EXPECT_CALL(mock_policy_callback_
,
577 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
578 EXPECT_CALL(mock_policy_callback_
,
579 OnPolicyUpdatePtr(IsPolicies(&talk_gadget_blah_
)));
583 SetPolicies(talk_gadget_blah_
);
586 TEST_F(PolicyWatcherTest
, ThirdPartyAuthFull
) {
587 testing::InSequence sequence
;
588 EXPECT_CALL(mock_policy_callback_
,
589 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
590 EXPECT_CALL(mock_policy_callback_
,
591 OnPolicyUpdatePtr(IsPolicies(&third_party_auth_full_
)));
595 SetPolicies(third_party_auth_full_
);
598 // This test verifies what happens when only 1 out of 3 third-party auth
599 // policies changes. Without the other 2 policy values such policy values
600 // combination is invalid (i.e. cannot have TokenUrl without
601 // TokenValidationUrl) and can trigger OnPolicyError unless PolicyWatcher
602 // implementation is careful around this scenario.
603 TEST_F(PolicyWatcherTest
, ThirdPartyAuthPartialToFull
) {
604 testing::InSequence sequence
;
605 EXPECT_CALL(mock_policy_callback_
,
606 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
607 EXPECT_CALL(mock_policy_callback_
,
608 OnPolicyUpdatePtr(IsPolicies(&third_party_auth_cert_empty_
)));
609 EXPECT_CALL(mock_policy_callback_
,
610 OnPolicyUpdatePtr(IsPolicies(&third_party_auth_full_
)));
614 SetPolicies(third_party_auth_partial_
);
615 SetPolicies(third_party_auth_full_
);
618 TEST_F(PolicyWatcherTest
, UdpPortRange
) {
619 testing::InSequence sequence
;
620 EXPECT_CALL(mock_policy_callback_
,
621 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
622 EXPECT_CALL(mock_policy_callback_
,
623 OnPolicyUpdatePtr(IsPolicies(&port_range_full_
)));
624 EXPECT_CALL(mock_policy_callback_
,
625 OnPolicyUpdatePtr(IsPolicies(&port_range_empty_
)));
629 SetPolicies(port_range_full_
);
630 SetPolicies(port_range_empty_
);
633 TEST_F(PolicyWatcherTest
, PolicySchemaAndPolicyWatcherShouldBeInSync
) {
634 // This test verifies that
635 // 1) policy schema (generated out of policy_templates.json)
637 // 2) PolicyWatcher's code (i.e. contents of the |default_values_| field)
640 std::map
<std::string
, base::Value::Type
> expected_schema
;
641 for (base::DictionaryValue::Iterator
i(GetDefaultValues()); !i
.IsAtEnd();
643 expected_schema
[i
.key()] = i
.value().GetType();
646 // RemoteAccessHostMatchUsername is marked in policy_templates.json as not
647 // supported on Windows and therefore is (by design) excluded from the schema.
648 expected_schema
.erase(key::kRemoteAccessHostMatchUsername
);
651 // Policy schema / policy_templates.json cannot differ between debug and
652 // release builds so we compensate below to account for the fact that
653 // PolicyWatcher::default_values_ does differ between debug and release.
654 expected_schema
[key::kRemoteAccessHostDebugOverridePolicies
] =
655 base::Value::TYPE_STRING
;
658 std::map
<std::string
, base::Value::Type
> actual_schema
;
659 const policy::Schema
* schema
= GetPolicySchema();
660 ASSERT_TRUE(schema
->valid());
661 for (auto it
= schema
->GetPropertiesIterator(); !it
.IsAtEnd(); it
.Advance()) {
662 std::string key
= it
.key();
663 if (key
.find("RemoteAccessHost") == std::string::npos
) {
664 // For now PolicyWatcher::GetPolicySchema() mixes Chrome and Chromoting
665 // policies, so we have to skip them here.
668 actual_schema
[key
] = it
.schema().type();
671 EXPECT_THAT(actual_schema
, testing::ContainerEq(expected_schema
));
674 TEST_F(PolicyWatcherTest
, SchemaTypeCheck
) {
675 const policy::Schema
* schema
= GetPolicySchema();
676 ASSERT_TRUE(schema
->valid());
678 // Check one, random "string" policy to see if the type propagated correctly
679 // from policy_templates.json file.
680 const policy::Schema string_schema
=
681 schema
->GetKnownProperty("RemoteAccessHostDomain");
682 EXPECT_TRUE(string_schema
.valid());
683 EXPECT_EQ(string_schema
.type(), base::Value::Type::TYPE_STRING
);
685 // And check one, random "boolean" policy to see if the type propagated
686 // correctly from policy_templates.json file.
687 const policy::Schema boolean_schema
=
688 schema
->GetKnownProperty("RemoteAccessHostRequireCurtain");
689 EXPECT_TRUE(boolean_schema
.valid());
690 EXPECT_EQ(boolean_schema
.type(), base::Value::Type::TYPE_BOOLEAN
);
693 // Unit tests cannot instantiate PolicyWatcher on ChromeOS
694 // (as this requires running inside a browser process).
699 void OnPolicyUpdatedDumpPolicy(scoped_ptr
<base::DictionaryValue
> policies
) {
700 VLOG(1) << "OnPolicyUpdated callback received the following policies:";
702 for (base::DictionaryValue::Iterator
iter(*policies
); !iter
.IsAtEnd();
704 switch (iter
.value().GetType()) {
705 case base::Value::Type::TYPE_STRING
: {
707 CHECK(iter
.value().GetAsString(&value
));
708 VLOG(1) << iter
.key() << " = "
709 << "string: " << '"' << value
<< '"';
712 case base::Value::Type::TYPE_BOOLEAN
: {
714 CHECK(iter
.value().GetAsBoolean(&value
));
715 VLOG(1) << iter
.key() << " = "
716 << "boolean: " << (value
? "True" : "False");
720 VLOG(1) << iter
.key() << " = "
721 << "unrecognized type";
728 } // anonymous namespace
730 // To dump policy contents, run unit tests with the following flags:
731 // out/Debug/remoting_unittests --gtest_filter=*TestRealChromotingPolicy* -v=1
732 TEST_F(PolicyWatcherTest
, TestRealChromotingPolicy
) {
733 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
=
734 base::MessageLoop::current()->task_runner();
735 scoped_ptr
<PolicyWatcher
> policy_watcher(
736 PolicyWatcher::Create(nullptr, task_runner
));
739 base::RunLoop run_loop
;
740 policy_watcher
->StartWatching(base::Bind(OnPolicyUpdatedDumpPolicy
),
741 base::Bind(base::DoNothing
));
742 run_loop
.RunUntilIdle();
745 // Today, the only verification offered by this test is:
746 // - Manual verification of policy values dumped by OnPolicyUpdatedDumpPolicy
747 // - Automated verification that nothing crashed
752 } // namespace remoting