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 class MockPolicyCallback
{
22 MockPolicyCallback(){};
24 // TODO(lukasza): gmock cannot mock a method taking scoped_ptr<T>...
25 MOCK_METHOD1(OnPolicyUpdatePtr
, void(const base::DictionaryValue
* policies
));
26 void OnPolicyUpdate(scoped_ptr
<base::DictionaryValue
> policies
) {
27 OnPolicyUpdatePtr(policies
.get());
30 MOCK_METHOD0(OnPolicyError
, void());
33 DISALLOW_COPY_AND_ASSIGN(MockPolicyCallback
);
36 class PolicyWatcherTest
: public testing::Test
{
38 PolicyWatcherTest() : message_loop_(base::MessageLoop::TYPE_IO
) {}
40 void SetUp() override
{
41 message_loop_proxy_
= base::MessageLoopProxy::current();
43 // Retaining a raw pointer to keep control over policy contents.
44 policy_loader_
= new policy::FakeAsyncPolicyLoader(message_loop_proxy_
);
46 PolicyWatcher::CreateFromPolicyLoader(make_scoped_ptr(policy_loader_
));
48 nat_true_
.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal
, true);
49 nat_false_
.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal
,
51 nat_one_
.SetInteger(policy::key::kRemoteAccessHostFirewallTraversal
, 1);
52 domain_empty_
.SetString(policy::key::kRemoteAccessHostDomain
,
54 domain_full_
.SetString(policy::key::kRemoteAccessHostDomain
, kHostDomain
);
55 SetDefaults(nat_true_others_default_
);
56 nat_true_others_default_
.SetBoolean(
57 policy::key::kRemoteAccessHostFirewallTraversal
, true);
58 SetDefaults(nat_false_others_default_
);
59 nat_false_others_default_
.SetBoolean(
60 policy::key::kRemoteAccessHostFirewallTraversal
, false);
61 SetDefaults(domain_empty_others_default_
);
62 domain_empty_others_default_
.SetString(policy::key::kRemoteAccessHostDomain
,
64 SetDefaults(domain_full_others_default_
);
65 domain_full_others_default_
.SetString(policy::key::kRemoteAccessHostDomain
,
67 nat_true_domain_empty_
.SetBoolean(
68 policy::key::kRemoteAccessHostFirewallTraversal
, true);
69 nat_true_domain_empty_
.SetString(policy::key::kRemoteAccessHostDomain
,
71 nat_true_domain_full_
.SetBoolean(
72 policy::key::kRemoteAccessHostFirewallTraversal
, true);
73 nat_true_domain_full_
.SetString(policy::key::kRemoteAccessHostDomain
,
75 nat_false_domain_empty_
.SetBoolean(
76 policy::key::kRemoteAccessHostFirewallTraversal
, false);
77 nat_false_domain_empty_
.SetString(policy::key::kRemoteAccessHostDomain
,
79 nat_false_domain_full_
.SetBoolean(
80 policy::key::kRemoteAccessHostFirewallTraversal
, false);
81 nat_false_domain_full_
.SetString(policy::key::kRemoteAccessHostDomain
,
83 SetDefaults(nat_true_domain_empty_others_default_
);
84 nat_true_domain_empty_others_default_
.SetBoolean(
85 policy::key::kRemoteAccessHostFirewallTraversal
, true);
86 nat_true_domain_empty_others_default_
.SetString(
87 policy::key::kRemoteAccessHostDomain
, std::string());
88 unknown_policies_
.SetString("UnknownPolicyOne", std::string());
89 unknown_policies_
.SetString("UnknownPolicyTwo", std::string());
91 const char kOverrideNatTraversalToFalse
[] =
92 "{ \"RemoteAccessHostFirewallTraversal\": false }";
93 nat_true_and_overridden_
.SetBoolean(
94 policy::key::kRemoteAccessHostFirewallTraversal
, true);
95 nat_true_and_overridden_
.SetString(
96 policy::key::kRemoteAccessHostDebugOverridePolicies
,
97 kOverrideNatTraversalToFalse
);
98 pairing_true_
.SetBoolean(policy::key::kRemoteAccessHostAllowClientPairing
,
100 pairing_false_
.SetBoolean(policy::key::kRemoteAccessHostAllowClientPairing
,
102 gnubby_auth_true_
.SetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth
,
104 gnubby_auth_false_
.SetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth
,
106 relay_true_
.SetBoolean(policy::key::kRemoteAccessHostAllowRelayedConnection
,
108 relay_false_
.SetBoolean(
109 policy::key::kRemoteAccessHostAllowRelayedConnection
, false);
110 port_range_full_
.SetString(policy::key::kRemoteAccessHostUdpPortRange
,
112 port_range_empty_
.SetString(policy::key::kRemoteAccessHostUdpPortRange
,
116 SetDefaults(nat_false_overridden_others_default_
);
117 nat_false_overridden_others_default_
.SetBoolean(
118 policy::key::kRemoteAccessHostFirewallTraversal
, false);
119 nat_false_overridden_others_default_
.SetString(
120 policy::key::kRemoteAccessHostDebugOverridePolicies
,
121 kOverrideNatTraversalToFalse
);
125 void TearDown() override
{
126 policy_watcher_
.reset();
127 policy_loader_
= nullptr;
128 base::RunLoop().RunUntilIdle();
132 void StartWatching() {
133 policy_watcher_
->StartWatching(
134 base::Bind(&MockPolicyCallback::OnPolicyUpdate
,
135 base::Unretained(&mock_policy_callback_
)),
136 base::Bind(&MockPolicyCallback::OnPolicyError
,
137 base::Unretained(&mock_policy_callback_
)));
138 base::RunLoop().RunUntilIdle();
141 void SetPolicies(const base::DictionaryValue
& dict
) {
142 // Copy |dict| into |policy_bundle|.
143 policy::PolicyNamespace policy_namespace
=
144 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME
, std::string());
145 policy::PolicyBundle policy_bundle
;
146 policy::PolicyMap
& policy_map
= policy_bundle
.Get(policy_namespace
);
147 policy_map
.LoadFrom(&dict
, policy::POLICY_LEVEL_MANDATORY
,
148 policy::POLICY_SCOPE_MACHINE
);
150 // Simulate a policy file/registry/preference update.
151 policy_loader_
->SetPolicies(policy_bundle
);
152 policy_loader_
->PostReloadOnBackgroundThread(true /* force reload asap */);
153 base::RunLoop().RunUntilIdle();
156 void SignalTransientErrorForTest() {
157 policy_watcher_
->SignalTransientPolicyError();
160 MOCK_METHOD0(PostPolicyWatcherShutdown
, void());
162 static const char* kHostDomain
;
163 static const char* kPortRange
;
164 base::MessageLoop message_loop_
;
165 scoped_refptr
<base::MessageLoopProxy
> message_loop_proxy_
;
166 MockPolicyCallback mock_policy_callback_
;
168 // |policy_loader_| is owned by |policy_watcher_|. PolicyWatcherTest retains
169 // a raw pointer to |policy_loader_| in order to control the simulated / faked
171 policy::FakeAsyncPolicyLoader
* policy_loader_
;
172 scoped_ptr
<PolicyWatcher
> policy_watcher_
;
174 base::DictionaryValue empty_
;
175 base::DictionaryValue nat_true_
;
176 base::DictionaryValue nat_false_
;
177 base::DictionaryValue nat_one_
;
178 base::DictionaryValue domain_empty_
;
179 base::DictionaryValue domain_full_
;
180 base::DictionaryValue nat_true_others_default_
;
181 base::DictionaryValue nat_false_others_default_
;
182 base::DictionaryValue domain_empty_others_default_
;
183 base::DictionaryValue domain_full_others_default_
;
184 base::DictionaryValue nat_true_domain_empty_
;
185 base::DictionaryValue nat_true_domain_full_
;
186 base::DictionaryValue nat_false_domain_empty_
;
187 base::DictionaryValue nat_false_domain_full_
;
188 base::DictionaryValue nat_true_domain_empty_others_default_
;
189 base::DictionaryValue unknown_policies_
;
190 base::DictionaryValue nat_true_and_overridden_
;
191 base::DictionaryValue nat_false_overridden_others_default_
;
192 base::DictionaryValue pairing_true_
;
193 base::DictionaryValue pairing_false_
;
194 base::DictionaryValue gnubby_auth_true_
;
195 base::DictionaryValue gnubby_auth_false_
;
196 base::DictionaryValue relay_true_
;
197 base::DictionaryValue relay_false_
;
198 base::DictionaryValue port_range_full_
;
199 base::DictionaryValue port_range_empty_
;
202 void SetDefaults(base::DictionaryValue
& dict
) {
203 dict
.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal
, true);
204 dict
.SetBoolean(policy::key::kRemoteAccessHostAllowRelayedConnection
, true);
205 dict
.SetString(policy::key::kRemoteAccessHostUdpPortRange
, "");
206 dict
.SetBoolean(policy::key::kRemoteAccessHostRequireTwoFactor
, false);
207 dict
.SetString(policy::key::kRemoteAccessHostDomain
, std::string());
208 dict
.SetBoolean(policy::key::kRemoteAccessHostMatchUsername
, false);
209 dict
.SetString(policy::key::kRemoteAccessHostTalkGadgetPrefix
,
210 kDefaultHostTalkGadgetPrefix
);
211 dict
.SetBoolean(policy::key::kRemoteAccessHostRequireCurtain
, false);
212 dict
.SetString(policy::key::kRemoteAccessHostTokenUrl
, std::string());
213 dict
.SetString(policy::key::kRemoteAccessHostTokenValidationUrl
,
216 policy::key::kRemoteAccessHostTokenValidationCertificateIssuer
,
218 dict
.SetBoolean(policy::key::kRemoteAccessHostAllowClientPairing
, true);
219 dict
.SetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth
, true);
221 dict
.SetString(policy::key::kRemoteAccessHostDebugOverridePolicies
, "");
226 const char* PolicyWatcherTest::kHostDomain
= "google.com";
227 const char* PolicyWatcherTest::kPortRange
= "12400-12409";
229 MATCHER_P(IsPolicies
, dict
, "") {
230 bool equal
= arg
->Equals(dict
);
232 std::string actual_value
;
233 base::JSONWriter::WriteWithOptions(
234 arg
, base::JSONWriter::OPTIONS_PRETTY_PRINT
, &actual_value
);
236 std::string expected_value
;
237 base::JSONWriter::WriteWithOptions(
238 dict
, base::JSONWriter::OPTIONS_PRETTY_PRINT
, &expected_value
);
240 *result_listener
<< "Policies are not equal. ";
241 *result_listener
<< "Expected policy: " << expected_value
<< ". ";
242 *result_listener
<< "Actual policy: " << actual_value
<< ".";
247 TEST_F(PolicyWatcherTest
, None
) {
248 EXPECT_CALL(mock_policy_callback_
,
249 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
255 TEST_F(PolicyWatcherTest
, NatTrue
) {
256 EXPECT_CALL(mock_policy_callback_
,
257 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
259 SetPolicies(nat_true_
);
263 TEST_F(PolicyWatcherTest
, NatFalse
) {
264 EXPECT_CALL(mock_policy_callback_
,
265 OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_
)));
267 SetPolicies(nat_false_
);
271 TEST_F(PolicyWatcherTest
, NatOne
) {
272 EXPECT_CALL(mock_policy_callback_
,
273 OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_
)));
275 SetPolicies(nat_one_
);
279 TEST_F(PolicyWatcherTest
, DomainEmpty
) {
280 EXPECT_CALL(mock_policy_callback_
,
281 OnPolicyUpdatePtr(IsPolicies(&domain_empty_others_default_
)));
283 SetPolicies(domain_empty_
);
287 TEST_F(PolicyWatcherTest
, DomainFull
) {
288 EXPECT_CALL(mock_policy_callback_
,
289 OnPolicyUpdatePtr(IsPolicies(&domain_full_others_default_
)));
291 SetPolicies(domain_full_
);
295 TEST_F(PolicyWatcherTest
, NatNoneThenTrue
) {
296 EXPECT_CALL(mock_policy_callback_
,
297 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
301 SetPolicies(nat_true_
);
304 TEST_F(PolicyWatcherTest
, NatNoneThenTrueThenTrue
) {
305 EXPECT_CALL(mock_policy_callback_
,
306 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
310 SetPolicies(nat_true_
);
311 SetPolicies(nat_true_
);
314 TEST_F(PolicyWatcherTest
, NatNoneThenTrueThenTrueThenFalse
) {
315 testing::InSequence sequence
;
316 EXPECT_CALL(mock_policy_callback_
,
317 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
318 EXPECT_CALL(mock_policy_callback_
,
319 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
323 SetPolicies(nat_true_
);
324 SetPolicies(nat_true_
);
325 SetPolicies(nat_false_
);
328 TEST_F(PolicyWatcherTest
, NatNoneThenFalse
) {
329 testing::InSequence sequence
;
330 EXPECT_CALL(mock_policy_callback_
,
331 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
332 EXPECT_CALL(mock_policy_callback_
,
333 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
337 SetPolicies(nat_false_
);
340 TEST_F(PolicyWatcherTest
, NatNoneThenFalseThenTrue
) {
341 testing::InSequence sequence
;
342 EXPECT_CALL(mock_policy_callback_
,
343 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
344 EXPECT_CALL(mock_policy_callback_
,
345 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
346 EXPECT_CALL(mock_policy_callback_
, OnPolicyUpdatePtr(IsPolicies(&nat_true_
)));
350 SetPolicies(nat_false_
);
351 SetPolicies(nat_true_
);
354 TEST_F(PolicyWatcherTest
, ChangeOneRepeatedlyThenTwo
) {
355 testing::InSequence sequence
;
357 mock_policy_callback_
,
358 OnPolicyUpdatePtr(IsPolicies(&nat_true_domain_empty_others_default_
)));
359 EXPECT_CALL(mock_policy_callback_
,
360 OnPolicyUpdatePtr(IsPolicies(&domain_full_
)));
361 EXPECT_CALL(mock_policy_callback_
,
362 OnPolicyUpdatePtr(IsPolicies(&nat_false_
)));
363 EXPECT_CALL(mock_policy_callback_
,
364 OnPolicyUpdatePtr(IsPolicies(&domain_empty_
)));
365 EXPECT_CALL(mock_policy_callback_
,
366 OnPolicyUpdatePtr(IsPolicies(&nat_true_domain_full_
)));
368 SetPolicies(nat_true_domain_empty_
);
370 SetPolicies(nat_true_domain_full_
);
371 SetPolicies(nat_false_domain_full_
);
372 SetPolicies(nat_false_domain_empty_
);
373 SetPolicies(nat_true_domain_full_
);
376 TEST_F(PolicyWatcherTest
, FilterUnknownPolicies
) {
377 testing::InSequence sequence
;
378 EXPECT_CALL(mock_policy_callback_
,
379 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
383 SetPolicies(unknown_policies_
);
387 TEST_F(PolicyWatcherTest
, DebugOverrideNatPolicy
) {
390 mock_policy_callback_
,
391 OnPolicyUpdatePtr(IsPolicies(&nat_false_overridden_others_default_
)));
393 EXPECT_CALL(mock_policy_callback_
,
394 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
397 SetPolicies(nat_true_and_overridden_
);
401 TEST_F(PolicyWatcherTest
, PairingFalseThenTrue
) {
402 testing::InSequence sequence
;
403 EXPECT_CALL(mock_policy_callback_
,
404 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
405 EXPECT_CALL(mock_policy_callback_
,
406 OnPolicyUpdatePtr(IsPolicies(&pairing_false_
)));
407 EXPECT_CALL(mock_policy_callback_
,
408 OnPolicyUpdatePtr(IsPolicies(&pairing_true_
)));
412 SetPolicies(pairing_false_
);
413 SetPolicies(pairing_true_
);
416 TEST_F(PolicyWatcherTest
, GnubbyAuth
) {
417 testing::InSequence sequence
;
418 EXPECT_CALL(mock_policy_callback_
,
419 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
420 EXPECT_CALL(mock_policy_callback_
,
421 OnPolicyUpdatePtr(IsPolicies(&gnubby_auth_false_
)));
422 EXPECT_CALL(mock_policy_callback_
,
423 OnPolicyUpdatePtr(IsPolicies(&gnubby_auth_true_
)));
427 SetPolicies(gnubby_auth_false_
);
428 SetPolicies(gnubby_auth_true_
);
431 TEST_F(PolicyWatcherTest
, Relay
) {
432 testing::InSequence sequence
;
433 EXPECT_CALL(mock_policy_callback_
,
434 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
435 EXPECT_CALL(mock_policy_callback_
,
436 OnPolicyUpdatePtr(IsPolicies(&relay_false_
)));
437 EXPECT_CALL(mock_policy_callback_
,
438 OnPolicyUpdatePtr(IsPolicies(&relay_true_
)));
442 SetPolicies(relay_false_
);
443 SetPolicies(relay_true_
);
446 TEST_F(PolicyWatcherTest
, UdpPortRange
) {
447 testing::InSequence sequence
;
448 EXPECT_CALL(mock_policy_callback_
,
449 OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_
)));
450 EXPECT_CALL(mock_policy_callback_
,
451 OnPolicyUpdatePtr(IsPolicies(&port_range_full_
)));
452 EXPECT_CALL(mock_policy_callback_
,
453 OnPolicyUpdatePtr(IsPolicies(&port_range_empty_
)));
457 SetPolicies(port_range_full_
);
458 SetPolicies(port_range_empty_
);
461 const int kMaxTransientErrorRetries
= 5;
463 TEST_F(PolicyWatcherTest
, SingleTransientErrorDoesntTriggerErrorCallback
) {
464 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(0);
467 SignalTransientErrorForTest();
470 TEST_F(PolicyWatcherTest
, MultipleTransientErrorsTriggerErrorCallback
) {
471 EXPECT_CALL(mock_policy_callback_
, OnPolicyError());
474 for (int i
= 0; i
< kMaxTransientErrorRetries
; i
++) {
475 SignalTransientErrorForTest();
479 TEST_F(PolicyWatcherTest
, PolicyUpdateResetsTransientErrorsCounter
) {
480 testing::InSequence s
;
481 EXPECT_CALL(mock_policy_callback_
, OnPolicyUpdatePtr(testing::_
));
482 EXPECT_CALL(mock_policy_callback_
, OnPolicyError()).Times(0);
485 for (int i
= 0; i
< (kMaxTransientErrorRetries
- 1); i
++) {
486 SignalTransientErrorForTest();
488 SetPolicies(nat_true_
);
489 for (int i
= 0; i
< (kMaxTransientErrorRetries
- 1); i
++) {
490 SignalTransientErrorForTest();
494 // Unit tests cannot instantiate PolicyWatcher on ChromeOS
495 // (as this requires running inside a browser process).
500 void OnPolicyUpdatedDumpPolicy(scoped_ptr
<base::DictionaryValue
> policies
) {
501 VLOG(1) << "OnPolicyUpdated callback received the following policies:";
503 for (base::DictionaryValue::Iterator
iter(*policies
); !iter
.IsAtEnd();
505 switch (iter
.value().GetType()) {
506 case base::Value::Type::TYPE_STRING
: {
508 CHECK(iter
.value().GetAsString(&value
));
509 VLOG(1) << iter
.key() << " = "
510 << "string: " << '"' << value
<< '"';
513 case base::Value::Type::TYPE_BOOLEAN
: {
515 CHECK(iter
.value().GetAsBoolean(&value
));
516 VLOG(1) << iter
.key() << " = "
517 << "boolean: " << (value
? "True" : "False");
521 VLOG(1) << iter
.key() << " = "
522 << "unrecognized type";
529 } // anonymous namespace
531 // To dump policy contents, run unit tests with the following flags:
532 // out/Debug/remoting_unittests --gtest_filter=*TestRealChromotingPolicy* -v=1
533 TEST_F(PolicyWatcherTest
, TestRealChromotingPolicy
) {
534 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
=
535 base::MessageLoop::current()->task_runner();
536 scoped_ptr
<PolicyWatcher
> policy_watcher(
537 PolicyWatcher::Create(nullptr, task_runner
));
540 base::RunLoop run_loop
;
541 policy_watcher
->StartWatching(base::Bind(OnPolicyUpdatedDumpPolicy
),
542 base::Bind(base::DoNothing
));
543 run_loop
.RunUntilIdle();
546 // Today, the only verification offered by this test is:
547 // - Manual verification of policy values dumped by OnPolicyUpdatedDumpPolicy
548 // - Automated verification that nothing crashed
553 } // namespace remoting