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/synchronization/waitable_event.h"
11 #include "components/policy/core/common/fake_async_policy_loader.h"
12 #include "policy/policy_constants.h"
13 #include "remoting/host/dns_blackhole_checker.h"
14 #include "remoting/host/policy_watcher.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
20 namespace key
= ::policy::key
;
22 MATCHER_P(IsPolicies
, dict
, "") {
23 bool equal
= arg
->Equals(dict
);
25 std::string actual_value
;
26 base::JSONWriter::WriteWithOptions(
27 arg
, base::JSONWriter::OPTIONS_PRETTY_PRINT
, &actual_value
);
29 std::string expected_value
;
30 base::JSONWriter::WriteWithOptions(
31 dict
, base::JSONWriter::OPTIONS_PRETTY_PRINT
, &expected_value
);
33 *result_listener
<< "Policies are not equal. ";
34 *result_listener
<< "Expected policy: " << expected_value
<< ". ";
35 *result_listener
<< "Actual policy: " << actual_value
<< ".";
40 class MockPolicyCallback
{
42 MockPolicyCallback(){};
44 // TODO(lukasza): gmock cannot mock a method taking scoped_ptr<T>...
45 MOCK_METHOD1(OnPolicyUpdatePtr
, void(const base::DictionaryValue
* policies
));
46 void OnPolicyUpdate(scoped_ptr
<base::DictionaryValue
> policies
) {
47 OnPolicyUpdatePtr(policies
.get());
50 MOCK_METHOD0(OnPolicyError
, void());
53 DISALLOW_COPY_AND_ASSIGN(MockPolicyCallback
);
56 class PolicyWatcherTest
: public testing::Test
{
58 PolicyWatcherTest() : message_loop_(base::MessageLoop::TYPE_IO
) {}
60 void SetUp() override
{
61 // We expect no callbacks unless explicitly specified by individual tests.
62 EXPECT_CALL(mock_policy_callback_
, OnPolicyUpdatePtr(testing::_
)).Times(0);
63 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(0);
65 message_loop_proxy_
= base::MessageLoopProxy::current();
67 // Retaining a raw pointer to keep control over policy contents.
68 policy_loader_
= new policy::FakeAsyncPolicyLoader(message_loop_proxy_
);
70 PolicyWatcher::CreateFromPolicyLoader(make_scoped_ptr(policy_loader_
));
72 nat_true_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
, true);
73 nat_false_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
, false);
74 nat_one_
.SetInteger(key::kRemoteAccessHostFirewallTraversal
, 1);
75 nat_one_domain_full_
.SetInteger(key::kRemoteAccessHostFirewallTraversal
, 1);
76 nat_one_domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
77 domain_empty_
.SetString(key::kRemoteAccessHostDomain
, std::string());
78 domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
79 SetDefaults(nat_true_others_default_
);
80 nat_true_others_default_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
82 SetDefaults(nat_false_others_default_
);
83 nat_false_others_default_
.SetBoolean(
84 key::kRemoteAccessHostFirewallTraversal
, false);
85 SetDefaults(domain_empty_others_default_
);
86 domain_empty_others_default_
.SetString(key::kRemoteAccessHostDomain
,
88 SetDefaults(domain_full_others_default_
);
89 domain_full_others_default_
.SetString(key::kRemoteAccessHostDomain
,
91 nat_true_domain_empty_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
93 nat_true_domain_empty_
.SetString(key::kRemoteAccessHostDomain
,
95 nat_true_domain_full_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
97 nat_true_domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
98 nat_false_domain_empty_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
100 nat_false_domain_empty_
.SetString(key::kRemoteAccessHostDomain
,
102 nat_false_domain_full_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
104 nat_false_domain_full_
.SetString(key::kRemoteAccessHostDomain
, kHostDomain
);
105 SetDefaults(nat_true_domain_empty_others_default_
);
106 nat_true_domain_empty_others_default_
.SetBoolean(
107 key::kRemoteAccessHostFirewallTraversal
, true);
108 nat_true_domain_empty_others_default_
.SetString(
109 key::kRemoteAccessHostDomain
, std::string());
110 unknown_policies_
.SetString("UnknownPolicyOne", std::string());
111 unknown_policies_
.SetString("UnknownPolicyTwo", std::string());
112 unknown_policies_
.SetBoolean("RemoteAccessHostUnknownPolicyThree", true);
114 const char kOverrideNatTraversalToFalse
[] =
115 "{ \"RemoteAccessHostFirewallTraversal\": false }";
116 nat_true_and_overridden_
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
,
118 nat_true_and_overridden_
.SetString(
119 key::kRemoteAccessHostDebugOverridePolicies
,
120 kOverrideNatTraversalToFalse
);
121 pairing_true_
.SetBoolean(key::kRemoteAccessHostAllowClientPairing
, true);
122 pairing_false_
.SetBoolean(key::kRemoteAccessHostAllowClientPairing
, false);
123 gnubby_auth_true_
.SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth
, true);
124 gnubby_auth_false_
.SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth
, false);
125 relay_true_
.SetBoolean(key::kRemoteAccessHostAllowRelayedConnection
, true);
126 relay_false_
.SetBoolean(key::kRemoteAccessHostAllowRelayedConnection
,
128 port_range_full_
.SetString(key::kRemoteAccessHostUdpPortRange
, kPortRange
);
129 port_range_empty_
.SetString(key::kRemoteAccessHostUdpPortRange
,
131 port_range_malformed_
.SetString(key::kRemoteAccessHostUdpPortRange
,
133 port_range_malformed_domain_full_
.MergeDictionary(&port_range_malformed_
);
134 port_range_malformed_domain_full_
.SetString(key::kRemoteAccessHostDomain
,
137 curtain_true_
.SetBoolean(key::kRemoteAccessHostRequireCurtain
, true);
138 curtain_false_
.SetBoolean(key::kRemoteAccessHostRequireCurtain
, false);
139 username_true_
.SetBoolean(key::kRemoteAccessHostMatchUsername
, true);
140 username_false_
.SetBoolean(key::kRemoteAccessHostMatchUsername
, false);
141 talk_gadget_blah_
.SetString(key::kRemoteAccessHostTalkGadgetPrefix
, "blah");
142 third_party_auth_partial_
.SetString(key::kRemoteAccessHostTokenUrl
,
143 "https://token.com");
144 third_party_auth_partial_
.SetString(
145 key::kRemoteAccessHostTokenValidationUrl
, "https://validation.com");
146 third_party_auth_full_
.MergeDictionary(&third_party_auth_partial_
);
147 third_party_auth_full_
.SetString(
148 key::kRemoteAccessHostTokenValidationCertificateIssuer
,
149 "certificate subject");
150 third_party_auth_cert_empty_
.MergeDictionary(&third_party_auth_partial_
);
151 third_party_auth_cert_empty_
.SetString(
152 key::kRemoteAccessHostTokenValidationCertificateIssuer
, "");
155 SetDefaults(nat_false_overridden_others_default_
);
156 nat_false_overridden_others_default_
.SetBoolean(
157 key::kRemoteAccessHostFirewallTraversal
, false);
158 nat_false_overridden_others_default_
.SetString(
159 key::kRemoteAccessHostDebugOverridePolicies
,
160 kOverrideNatTraversalToFalse
);
164 void TearDown() override
{
165 policy_watcher_
.reset();
166 policy_loader_
= nullptr;
167 base::RunLoop().RunUntilIdle();
171 void StartWatching() {
172 policy_watcher_
->StartWatching(
173 base::Bind(&MockPolicyCallback::OnPolicyUpdate
,
174 base::Unretained(&mock_policy_callback_
)),
175 base::Bind(&MockPolicyCallback::OnPolicyError
,
176 base::Unretained(&mock_policy_callback_
)));
177 base::RunLoop().RunUntilIdle();
180 void SetPolicies(const base::DictionaryValue
& dict
) {
181 // Copy |dict| into |policy_bundle|.
182 policy::PolicyNamespace policy_namespace
=
183 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME
, std::string());
184 policy::PolicyBundle policy_bundle
;
185 policy::PolicyMap
& policy_map
= policy_bundle
.Get(policy_namespace
);
186 policy_map
.LoadFrom(&dict
, policy::POLICY_LEVEL_MANDATORY
,
187 policy::POLICY_SCOPE_MACHINE
);
189 // Simulate a policy file/registry/preference update.
190 policy_loader_
->SetPolicies(policy_bundle
);
191 policy_loader_
->PostReloadOnBackgroundThread(true /* force reload asap */);
192 base::RunLoop().RunUntilIdle();
195 const policy::Schema
* GetPolicySchema() {
196 return policy_watcher_
->GetPolicySchema();
199 const base::DictionaryValue
& GetDefaultValues() {
200 return *(policy_watcher_
->default_values_
);
203 MOCK_METHOD0(PostPolicyWatcherShutdown
, void());
205 static const char* kHostDomain
;
206 static const char* kPortRange
;
207 base::MessageLoop message_loop_
;
208 scoped_refptr
<base::MessageLoopProxy
> message_loop_proxy_
;
209 MockPolicyCallback mock_policy_callback_
;
211 // |policy_loader_| is owned by |policy_watcher_|. PolicyWatcherTest retains
212 // a raw pointer to |policy_loader_| in order to control the simulated / faked
214 policy::FakeAsyncPolicyLoader
* policy_loader_
;
215 scoped_ptr
<PolicyWatcher
> policy_watcher_
;
217 base::DictionaryValue empty_
;
218 base::DictionaryValue nat_true_
;
219 base::DictionaryValue nat_false_
;
220 base::DictionaryValue nat_one_
;
221 base::DictionaryValue nat_one_domain_full_
;
222 base::DictionaryValue domain_empty_
;
223 base::DictionaryValue domain_full_
;
224 base::DictionaryValue nat_true_others_default_
;
225 base::DictionaryValue nat_false_others_default_
;
226 base::DictionaryValue domain_empty_others_default_
;
227 base::DictionaryValue domain_full_others_default_
;
228 base::DictionaryValue nat_true_domain_empty_
;
229 base::DictionaryValue nat_true_domain_full_
;
230 base::DictionaryValue nat_false_domain_empty_
;
231 base::DictionaryValue nat_false_domain_full_
;
232 base::DictionaryValue nat_true_domain_empty_others_default_
;
233 base::DictionaryValue unknown_policies_
;
234 base::DictionaryValue nat_true_and_overridden_
;
235 base::DictionaryValue nat_false_overridden_others_default_
;
236 base::DictionaryValue pairing_true_
;
237 base::DictionaryValue pairing_false_
;
238 base::DictionaryValue gnubby_auth_true_
;
239 base::DictionaryValue gnubby_auth_false_
;
240 base::DictionaryValue relay_true_
;
241 base::DictionaryValue relay_false_
;
242 base::DictionaryValue port_range_full_
;
243 base::DictionaryValue port_range_empty_
;
244 base::DictionaryValue port_range_malformed_
;
245 base::DictionaryValue port_range_malformed_domain_full_
;
246 base::DictionaryValue curtain_true_
;
247 base::DictionaryValue curtain_false_
;
248 base::DictionaryValue username_true_
;
249 base::DictionaryValue username_false_
;
250 base::DictionaryValue talk_gadget_blah_
;
251 base::DictionaryValue third_party_auth_full_
;
252 base::DictionaryValue third_party_auth_partial_
;
253 base::DictionaryValue third_party_auth_cert_empty_
;
256 void SetDefaults(base::DictionaryValue
& dict
) {
257 dict
.SetBoolean(key::kRemoteAccessHostFirewallTraversal
, true);
258 dict
.SetBoolean(key::kRemoteAccessHostAllowRelayedConnection
, true);
259 dict
.SetString(key::kRemoteAccessHostUdpPortRange
, "");
260 dict
.SetString(key::kRemoteAccessHostDomain
, std::string());
261 dict
.SetBoolean(key::kRemoteAccessHostMatchUsername
, false);
262 dict
.SetString(key::kRemoteAccessHostTalkGadgetPrefix
,
263 kDefaultHostTalkGadgetPrefix
);
264 dict
.SetBoolean(key::kRemoteAccessHostRequireCurtain
, false);
265 dict
.SetString(key::kRemoteAccessHostTokenUrl
, "");
266 dict
.SetString(key::kRemoteAccessHostTokenValidationUrl
, "");
267 dict
.SetString(key::kRemoteAccessHostTokenValidationCertificateIssuer
, "");
268 dict
.SetBoolean(key::kRemoteAccessHostAllowClientPairing
, true);
269 dict
.SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth
, true);
271 dict
.SetString(key::kRemoteAccessHostDebugOverridePolicies
, "");
274 ASSERT_THAT(&dict
, IsPolicies(&GetDefaultValues()))
275 << "Sanity check that defaults expected by the test code "
276 << "match what is stored in PolicyWatcher::default_values_";
280 const char* PolicyWatcherTest::kHostDomain
= "google.com";
281 const char* PolicyWatcherTest::kPortRange
= "12400-12409";
283 TEST_F(PolicyWatcherTest
, None
) {
284 EXPECT_CALL(mock_policy_callback_
,
285 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
291 TEST_F(PolicyWatcherTest
, NatTrue
) {
292 EXPECT_CALL(mock_policy_callback_
,
293 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
295 SetPolicies(nat_true_
);
299 TEST_F(PolicyWatcherTest
, NatFalse
) {
300 EXPECT_CALL(mock_policy_callback_
,
301 OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_
)));
303 SetPolicies(nat_false_
);
307 TEST_F(PolicyWatcherTest
, NatWrongType
) {
308 EXPECT_CALL(mock_policy_callback_
, OnPolicyError());
310 SetPolicies(nat_one_
);
314 // This test verifies that a mistyped policy value is still detected
315 // even though it doesn't change during the second SetPolicies call.
316 TEST_F(PolicyWatcherTest
, NatWrongTypeThenIrrelevantChange
) {
317 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(2);
319 SetPolicies(nat_one_
);
321 SetPolicies(nat_one_domain_full_
);
324 // This test verifies that a malformed policy value is still detected
325 // even though it doesn't change during the second SetPolicies call.
326 TEST_F(PolicyWatcherTest
, PortRangeMalformedThenIrrelevantChange
) {
327 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(2);
329 SetPolicies(port_range_malformed_
);
331 SetPolicies(port_range_malformed_domain_full_
);
334 TEST_F(PolicyWatcherTest
, DomainEmpty
) {
335 EXPECT_CALL(mock_policy_callback_
,
336 OnPolicyUpdatePtr(IsPolicies(&domain_empty_others_default_
)));
338 SetPolicies(domain_empty_
);
342 TEST_F(PolicyWatcherTest
, DomainFull
) {
343 EXPECT_CALL(mock_policy_callback_
,
344 OnPolicyUpdatePtr(IsPolicies(&domain_full_others_default_
)));
346 SetPolicies(domain_full_
);
350 TEST_F(PolicyWatcherTest
, NatNoneThenTrue
) {
351 EXPECT_CALL(mock_policy_callback_
,
352 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
356 SetPolicies(nat_true_
);
359 TEST_F(PolicyWatcherTest
, NatNoneThenTrueThenTrue
) {
360 EXPECT_CALL(mock_policy_callback_
,
361 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
365 SetPolicies(nat_true_
);
366 SetPolicies(nat_true_
);
369 TEST_F(PolicyWatcherTest
, NatNoneThenTrueThenTrueThenFalse
) {
370 testing::InSequence sequence
;
371 EXPECT_CALL(mock_policy_callback_
,
372 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
373 EXPECT_CALL(mock_policy_callback_
,
374 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
378 SetPolicies(nat_true_
);
379 SetPolicies(nat_true_
);
380 SetPolicies(nat_false_
);
383 TEST_F(PolicyWatcherTest
, NatNoneThenFalse
) {
384 testing::InSequence sequence
;
385 EXPECT_CALL(mock_policy_callback_
,
386 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
387 EXPECT_CALL(mock_policy_callback_
,
388 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
392 SetPolicies(nat_false_
);
395 TEST_F(PolicyWatcherTest
, NatNoneThenFalseThenTrue
) {
396 testing::InSequence sequence
;
397 EXPECT_CALL(mock_policy_callback_
,
398 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
399 EXPECT_CALL(mock_policy_callback_
,
400 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
401 EXPECT_CALL(mock_policy_callback_
, OnPolicyUpdatePtr(IsPolicies(&nat_true_
)));
405 SetPolicies(nat_false_
);
406 SetPolicies(nat_true_
);
409 TEST_F(PolicyWatcherTest
, ChangeOneRepeatedlyThenTwo
) {
410 testing::InSequence sequence
;
412 mock_policy_callback_
,
413 OnPolicyUpdatePtr(IsPolicies(&nat_true_domain_empty_others_default_
)));
414 EXPECT_CALL(mock_policy_callback_
,
415 OnPolicyUpdatePtr(IsPolicies(&domain_full_
)));
416 EXPECT_CALL(mock_policy_callback_
,
417 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
418 EXPECT_CALL(mock_policy_callback_
,
419 OnPolicyUpdatePtr(IsPolicies(&domain_empty_
)));
420 EXPECT_CALL(mock_policy_callback_
,
421 OnPolicyUpdatePtr(IsPolicies(&nat_true_domain_full_
)));
423 SetPolicies(nat_true_domain_empty_
);
425 SetPolicies(nat_true_domain_full_
);
426 SetPolicies(nat_false_domain_full_
);
427 SetPolicies(nat_false_domain_empty_
);
428 SetPolicies(nat_true_domain_full_
);
431 TEST_F(PolicyWatcherTest
, FilterUnknownPolicies
) {
432 testing::InSequence sequence
;
433 EXPECT_CALL(mock_policy_callback_
,
434 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
438 SetPolicies(unknown_policies_
);
442 TEST_F(PolicyWatcherTest
, DebugOverrideNatPolicy
) {
445 mock_policy_callback_
,
446 OnPolicyUpdatePtr(IsPolicies(&nat_false_overridden_others_default_
)));
448 EXPECT_CALL(mock_policy_callback_
,
449 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
452 SetPolicies(nat_true_and_overridden_
);
456 TEST_F(PolicyWatcherTest
, PairingFalseThenTrue
) {
457 testing::InSequence sequence
;
458 EXPECT_CALL(mock_policy_callback_
,
459 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
460 EXPECT_CALL(mock_policy_callback_
,
461 OnPolicyUpdatePtr(IsPolicies(&pairing_false_
)));
462 EXPECT_CALL(mock_policy_callback_
,
463 OnPolicyUpdatePtr(IsPolicies(&pairing_true_
)));
467 SetPolicies(pairing_false_
);
468 SetPolicies(pairing_true_
);
471 TEST_F(PolicyWatcherTest
, GnubbyAuth
) {
472 testing::InSequence sequence
;
473 EXPECT_CALL(mock_policy_callback_
,
474 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
475 EXPECT_CALL(mock_policy_callback_
,
476 OnPolicyUpdatePtr(IsPolicies(&gnubby_auth_false_
)));
477 EXPECT_CALL(mock_policy_callback_
,
478 OnPolicyUpdatePtr(IsPolicies(&gnubby_auth_true_
)));
482 SetPolicies(gnubby_auth_false_
);
483 SetPolicies(gnubby_auth_true_
);
486 TEST_F(PolicyWatcherTest
, Relay
) {
487 testing::InSequence sequence
;
488 EXPECT_CALL(mock_policy_callback_
,
489 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
490 EXPECT_CALL(mock_policy_callback_
,
491 OnPolicyUpdatePtr(IsPolicies(&relay_false_
)));
492 EXPECT_CALL(mock_policy_callback_
,
493 OnPolicyUpdatePtr(IsPolicies(&relay_true_
)));
497 SetPolicies(relay_false_
);
498 SetPolicies(relay_true_
);
501 TEST_F(PolicyWatcherTest
, Curtain
) {
502 testing::InSequence sequence
;
503 EXPECT_CALL(mock_policy_callback_
,
504 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
505 EXPECT_CALL(mock_policy_callback_
,
506 OnPolicyUpdatePtr(IsPolicies(&curtain_true_
)));
507 EXPECT_CALL(mock_policy_callback_
,
508 OnPolicyUpdatePtr(IsPolicies(&curtain_false_
)));
512 SetPolicies(curtain_true_
);
513 SetPolicies(curtain_false_
);
516 TEST_F(PolicyWatcherTest
, MatchUsername
) {
517 testing::InSequence sequence
;
518 EXPECT_CALL(mock_policy_callback_
,
519 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
521 EXPECT_CALL(mock_policy_callback_
,
522 OnPolicyUpdatePtr(IsPolicies(&username_true_
)));
523 EXPECT_CALL(mock_policy_callback_
,
524 OnPolicyUpdatePtr(IsPolicies(&username_false_
)));
526 // On Windows the MatchUsername policy is ignored and therefore the 2
527 // SetPolicies calls won't result in any calls to OnPolicyUpdate.
532 SetPolicies(username_true_
);
533 SetPolicies(username_false_
);
536 TEST_F(PolicyWatcherTest
, TalkGadgetPrefix
) {
537 testing::InSequence sequence
;
538 EXPECT_CALL(mock_policy_callback_
,
539 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
540 EXPECT_CALL(mock_policy_callback_
,
541 OnPolicyUpdatePtr(IsPolicies(&talk_gadget_blah_
)));
545 SetPolicies(talk_gadget_blah_
);
548 TEST_F(PolicyWatcherTest
, ThirdPartyAuthFull
) {
549 testing::InSequence sequence
;
550 EXPECT_CALL(mock_policy_callback_
,
551 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
552 EXPECT_CALL(mock_policy_callback_
,
553 OnPolicyUpdatePtr(IsPolicies(&third_party_auth_full_
)));
557 SetPolicies(third_party_auth_full_
);
560 // This test verifies what happens when only 1 out of 3 third-party auth
561 // policies changes. Without the other 2 policy values such policy values
562 // combination is invalid (i.e. cannot have TokenUrl without
563 // TokenValidationUrl) and can trigger OnPolicyError unless PolicyWatcher
564 // implementation is careful around this scenario.
565 TEST_F(PolicyWatcherTest
, ThirdPartyAuthPartialToFull
) {
566 testing::InSequence sequence
;
567 EXPECT_CALL(mock_policy_callback_
,
568 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
569 EXPECT_CALL(mock_policy_callback_
,
570 OnPolicyUpdatePtr(IsPolicies(&third_party_auth_cert_empty_
)));
571 EXPECT_CALL(mock_policy_callback_
,
572 OnPolicyUpdatePtr(IsPolicies(&third_party_auth_full_
)));
576 SetPolicies(third_party_auth_partial_
);
577 SetPolicies(third_party_auth_full_
);
580 TEST_F(PolicyWatcherTest
, UdpPortRange
) {
581 testing::InSequence sequence
;
582 EXPECT_CALL(mock_policy_callback_
,
583 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
584 EXPECT_CALL(mock_policy_callback_
,
585 OnPolicyUpdatePtr(IsPolicies(&port_range_full_
)));
586 EXPECT_CALL(mock_policy_callback_
,
587 OnPolicyUpdatePtr(IsPolicies(&port_range_empty_
)));
591 SetPolicies(port_range_full_
);
592 SetPolicies(port_range_empty_
);
595 TEST_F(PolicyWatcherTest
, PolicySchemaAndPolicyWatcherShouldBeInSync
) {
596 // This test verifies that
597 // 1) policy schema (generated out of policy_templates.json)
599 // 2) PolicyWatcher's code (i.e. contents of the |default_values_| field)
602 std::map
<std::string
, base::Value::Type
> expected_schema
;
603 for (base::DictionaryValue::Iterator
i(GetDefaultValues()); !i
.IsAtEnd();
605 expected_schema
[i
.key()] = i
.value().GetType();
608 // RemoteAccessHostMatchUsername is marked in policy_templates.json as not
609 // supported on Windows and therefore is (by design) excluded from the schema.
610 expected_schema
.erase(key::kRemoteAccessHostMatchUsername
);
613 // Policy schema / policy_templates.json cannot differ between debug and
614 // release builds so we compensate below to account for the fact that
615 // PolicyWatcher::default_values_ does differ between debug and release.
616 expected_schema
[key::kRemoteAccessHostDebugOverridePolicies
] =
617 base::Value::TYPE_STRING
;
620 std::map
<std::string
, base::Value::Type
> actual_schema
;
621 const policy::Schema
* schema
= GetPolicySchema();
622 ASSERT_TRUE(schema
->valid());
623 for (auto it
= schema
->GetPropertiesIterator(); !it
.IsAtEnd(); it
.Advance()) {
624 std::string key
= it
.key();
625 if (key
.find("RemoteAccessHost") == std::string::npos
) {
626 // For now PolicyWatcher::GetPolicySchema() mixes Chrome and Chromoting
627 // policies, so we have to skip them here.
630 actual_schema
[key
] = it
.schema().type();
633 EXPECT_THAT(actual_schema
, testing::ContainerEq(expected_schema
));
636 TEST_F(PolicyWatcherTest
, SchemaTypeCheck
) {
637 const policy::Schema
* schema
= GetPolicySchema();
638 ASSERT_TRUE(schema
->valid());
640 // Check one, random "string" policy to see if the type propagated correctly
641 // from policy_templates.json file.
642 const policy::Schema string_schema
=
643 schema
->GetKnownProperty("RemoteAccessHostDomain");
644 EXPECT_TRUE(string_schema
.valid());
645 EXPECT_EQ(string_schema
.type(), base::Value::Type::TYPE_STRING
);
647 // And check one, random "boolean" policy to see if the type propagated
648 // correctly from policy_templates.json file.
649 const policy::Schema boolean_schema
=
650 schema
->GetKnownProperty("RemoteAccessHostRequireCurtain");
651 EXPECT_TRUE(boolean_schema
.valid());
652 EXPECT_EQ(boolean_schema
.type(), base::Value::Type::TYPE_BOOLEAN
);
655 // Unit tests cannot instantiate PolicyWatcher on ChromeOS
656 // (as this requires running inside a browser process).
661 void OnPolicyUpdatedDumpPolicy(scoped_ptr
<base::DictionaryValue
> policies
) {
662 VLOG(1) << "OnPolicyUpdated callback received the following policies:";
664 for (base::DictionaryValue::Iterator
iter(*policies
); !iter
.IsAtEnd();
666 switch (iter
.value().GetType()) {
667 case base::Value::Type::TYPE_STRING
: {
669 CHECK(iter
.value().GetAsString(&value
));
670 VLOG(1) << iter
.key() << " = "
671 << "string: " << '"' << value
<< '"';
674 case base::Value::Type::TYPE_BOOLEAN
: {
676 CHECK(iter
.value().GetAsBoolean(&value
));
677 VLOG(1) << iter
.key() << " = "
678 << "boolean: " << (value
? "True" : "False");
682 VLOG(1) << iter
.key() << " = "
683 << "unrecognized type";
690 } // anonymous namespace
692 // To dump policy contents, run unit tests with the following flags:
693 // out/Debug/remoting_unittests --gtest_filter=*TestRealChromotingPolicy* -v=1
694 TEST_F(PolicyWatcherTest
, TestRealChromotingPolicy
) {
695 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
=
696 base::MessageLoop::current()->task_runner();
697 scoped_ptr
<PolicyWatcher
> policy_watcher(
698 PolicyWatcher::Create(nullptr, task_runner
));
701 base::RunLoop run_loop
;
702 policy_watcher
->StartWatching(base::Bind(OnPolicyUpdatedDumpPolicy
),
703 base::Bind(base::DoNothing
));
704 run_loop
.RunUntilIdle();
707 // Today, the only verification offered by this test is:
708 // - Manual verification of policy values dumped by OnPolicyUpdatedDumpPolicy
709 // - Automated verification that nothing crashed
714 } // namespace remoting