Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: chrome/browser/policy/remote_commands/remote_commands_browsertest.cc

Issue 879233003: Initial RemoteCommandService (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@remote-commands
Patch Set: comments grammar fixes; fix win compile Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include <string>
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/time/time.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/policy/cloud/test_request_interceptor.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "components/policy/core/browser/browser_policy_connector.h"
22 #include "components/policy/core/common/policy_switches.h"
23 #include "components/policy/core/common/remote_commands/remote_command_job.h"
24 #include "components/policy/core/common/remote_commands/remote_commands_factory. h"
25 #include "components/policy/core/common/remote_commands/remote_commands_service. h"
26 #include "components/policy/core/common/remote_commands/test_remote_command_job. h"
27 #include "components/policy/core/common/remote_commands/testing_remote_commands_ server.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "net/base/net_errors.h"
30 #include "net/url_request/url_request_context_getter.h"
31 #include "policy/proto/device_management_backend.pb.h"
32 #include "testing/gmock/include/gmock/gmock.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34
35 #if defined(OS_CHROMEOS)
36 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
37 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chrom eos.h"
38 #else
39 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
40 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
41 #endif
42
43 using testing::AnyNumber;
44 using testing::InvokeWithoutArgs;
45 using testing::ReturnNew;
46 using testing::_;
47
48 namespace policy {
49
50 namespace {
51 const char kTestToken[] = "secret_token";
52 const char kTestClientID[] = "testing_client_id";
53 const char kTestPayload[] = "_testing_payload_";
54 } // namespace
55
56 namespace em = enterprise_management;
57
58 // Mocked RemoteCommand factory to allow us to build test commands.
59 class MockTestRemoteCommandFactory : public RemoteCommandsFactory {
60 public:
61 MockTestRemoteCommandFactory() {}
62 ~MockTestRemoteCommandFactory() override {}
63
64 MOCK_METHOD0(BuildTestCommand, TestRemoteCommandJob*());
bartfab (slow) 2015/02/18 13:21:53 It looks like BuildTestCommand() always does the s
binjin 2015/02/18 15:37:49 Done.
65
66 private:
67 // RemoteCommandJobsFactory:
68 scoped_ptr<RemoteCommandJob> BuildJobForType(
69 em::RemoteCommand_Type type) override {
70 if (type != em::RemoteCommand_Type_COMMAND_ECHO_TEST) {
71 NOTREACHED();
bartfab (slow) 2015/02/18 13:21:53 Since this is test code, use ADD_FAILURE(). NOTREA
binjin 2015/02/18 15:37:49 Done.
72 return nullptr;
73 }
74 return make_scoped_ptr<RemoteCommandJob>(BuildTestCommand());
75 }
76
77 DISALLOW_COPY_AND_ASSIGN(MockTestRemoteCommandFactory);
78 };
79
80 // Mocked TestingRemoteCommandsServer for verifying commands results.
81 class MockRemoteCommandsServer : public TestingRemoteCommandsServer {
bartfab (slow) 2015/02/18 13:21:52 Is this the only implementation of TestingRemoteCo
binjin 2015/02/18 15:37:49 I would like to to keep the derived class, since t
bartfab (slow) 2015/02/23 13:13:56 I understand the purpose of MockRemoteCommandsServ
binjin 2015/02/24 05:29:49 Class removed. N/A now
82 public:
83 MockRemoteCommandsServer() {}
84 ~MockRemoteCommandsServer() override {}
85
86 MOCK_CONST_METHOD2(SucceededJobReported,
87 void(const std::string&, base::Time));
88 MOCK_CONST_METHOD1(FailedJobReported, void(base::Time));
89 MOCK_CONST_METHOD1(IgnoredJobReported, void(base::Time));
90
91 private:
92 // TestingRemoteCommandsServer:
93 void OnJobResultReported(const enterprise_management::RemoteCommandResult&
94 job_result) const override {
95 base::Time timestamp =
bartfab (slow) 2015/02/18 13:21:53 Nit: const.
binjin 2015/02/18 15:37:48 Done.
96 base::TimeDelta::FromMilliseconds(job_result.timestamp()) +
97 base::Time::UnixEpoch();
98 switch (job_result.result()) {
99 case em::RemoteCommandResult_ResultType_RESULT_SUCCESS:
100 SucceededJobReported(job_result.payload(), timestamp);
101 break;
102 case em::RemoteCommandResult_ResultType_RESULT_FAILURE:
103 FailedJobReported(timestamp);
104 break;
105 case em::RemoteCommandResult_ResultType_RESULT_IGNORED:
106 IgnoredJobReported(timestamp);
107 break;
108 default:
109 NOTREACHED();
bartfab (slow) 2015/02/18 13:21:52 Nit: Use ADD_FAILURE() instead.
binjin 2015/02/18 15:37:49 Done.
110 }
111 }
112
113 DISALLOW_COPY_AND_ASSIGN(MockRemoteCommandsServer);
114 };
115
116 // Base class for all browser tests regarding remote commands service.
117 class RemoteCommandsBrowserTest : public InProcessBrowserTest {
118 protected:
119 RemoteCommandsBrowserTest() {}
120 ~RemoteCommandsBrowserTest() override {}
121
122 // Register on DMServer with faked token and client id.
123 void Register() {
124 ASSERT_TRUE(policy_manager());
125 ASSERT_TRUE(policy_manager()->core()->client());
126
127 EXPECT_FALSE(policy_manager()->core()->client()->is_registered());
128 policy_manager()->core()->client()->SetupRegistration(kTestToken,
129 kTestClientID);
130 EXPECT_TRUE(policy_manager()->core()->client()->is_registered());
131 }
132
133 // Start the service, must be called after Register(). Note that remote
134 // commands service will immediately start fetching commands.
135 void StartService(scoped_ptr<MockTestRemoteCommandFactory> factory) {
136 ASSERT_FALSE(service_started_);
bartfab (slow) 2015/02/18 13:21:52 Nit: s/ASSERT/EXPECT/
binjin 2015/02/18 15:37:49 Done.
137 service_started_ = true;
138
139 mock_factory_ = factory.get();
bartfab (slow) 2015/02/18 13:21:52 Nit: Not used.
binjin 2015/02/18 15:37:49 Done.
140
141 policy_manager()->core()->StartRemoteCommandsService(factory.Pass());
142 }
143
144 // Start the service, but will wait until the initial remote commands
145 // fetch completes (with no command fetched).
146 void StartServiceWithoutCommandsFetched(
147 scoped_ptr<MockTestRemoteCommandFactory> factory) {
148 base::RunLoop run_loop;
149 interceptor_->PushJobCallback(
bartfab (slow) 2015/02/18 13:21:53 Lines 149-151 are copy & pasted to many places. Co
binjin 2015/02/18 15:37:49 Done. But with more methods used.
150 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 0u));
151 interceptor_->AddRequestServicedCallback(run_loop.QuitClosure());
152 StartService(factory.Pass());
153 run_loop.Run();
154 }
155
156 void SetUpInProcessBrowserTestFixture() override {
157 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
158 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl,
159 "http://localhost");
160 }
161
162 void SetUpOnMainThread() override {
163 // Set up interceptor and ignore 'register' and 'policy' requests.
164 interceptor_.reset(new TestRequestInterceptor(
165 "localhost", content::BrowserThread::GetMessageLoopProxyForThread(
166 content::BrowserThread::IO)));
167 interceptor_->AddIgnoredRequestType("register");
168 interceptor_->AddIgnoredRequestType("policy");
169
170 server_.reset(new MockRemoteCommandsServer());
171
172 BrowserPolicyConnector* const connector =
173 g_browser_process->browser_policy_connector();
174 connector->ScheduleServiceInitialization(0);
175
176 ASSERT_TRUE(policy_manager());
177
178 #if !defined(OS_CHROMEOS)
179 policy_manager()->Connect(
bartfab (slow) 2015/02/18 13:21:52 It feels like you are using a browser test so that
binjin 2015/02/18 15:37:49 I'm not sure, but TestRequestInteceptor is used in
bartfab (slow) 2015/02/23 13:13:56 Having a browser test for each command is definite
binjin 2015/02/24 05:29:49 1) It's always okay to redefine policy_manager() l
180 g_browser_process->local_state(),
181 g_browser_process->system_request_context(),
182 UserCloudPolicyManager::CreateCloudPolicyClient(
183 connector->device_management_service(),
184 g_browser_process->system_request_context()).Pass());
185 #endif
186 }
187
188 void TearDownOnMainThread() override {
189 EXPECT_EQ(0u, interceptor_->GetPendingSize());
190 server_.reset();
bartfab (slow) 2015/02/18 13:21:52 Nit: Is this actually necessary?
binjin 2015/02/18 15:37:48 It can only be destroyed on main thread.
191 interceptor_.reset();
bartfab (slow) 2015/02/18 13:21:52 Nit: Is this actually necessary?
binjin 2015/02/18 15:37:49 It depends on |server_|.
192 }
193
194 #if defined(OS_CHROMEOS)
195 UserCloudPolicyManagerChromeOS* policy_manager() {
196 return UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
197 browser()->profile());
198 }
199 #else
200 UserCloudPolicyManager* policy_manager() {
201 return UserCloudPolicyManagerFactory::GetForBrowserContext(
202 browser()->profile());
203 }
204 #endif // defined(OS_CHROMEOS)
205
206 scoped_ptr<TestRequestInterceptor> interceptor_;
bartfab (slow) 2015/02/18 13:21:52 Why can this not just be |TestRequestInterceptor i
binjin 2015/02/18 15:37:49 Use of TestRequestInterceptor is kind of restricte
207 scoped_ptr<MockRemoteCommandsServer> server_;
bartfab (slow) 2015/02/18 13:21:53 Why can this not just be |MockRemoteCommandsServer
binjin 2015/02/18 15:37:49 constructor of TestingRemoteCommandsServer will tr
208 MockTestRemoteCommandFactory* mock_factory_ = nullptr;
bartfab (slow) 2015/02/18 13:21:52 Nit: Not used.
binjin 2015/02/18 15:37:49 Done.
209
210 private:
211 bool service_started_ = false;
212
213 DISALLOW_COPY_AND_ASSIGN(RemoteCommandsBrowserTest);
214 };
215
216 // Tests that no command will be fetched if no commands is issued.
217 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NoCommands) {
218 scoped_ptr<MockTestRemoteCommandFactory> factory(
219 new MockTestRemoteCommandFactory());
220 EXPECT_CALL(*factory, BuildTestCommand()).Times(0);
221
222 Register();
223 StartServiceWithoutCommandsFetched(factory.Pass());
224
225 // A follow up fetch requst should also get nothing from server.
226 base::RunLoop run_loop;
227 interceptor_->PushJobCallback(
228 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 0u));
229 interceptor_->AddRequestServicedCallback(run_loop.QuitClosure());
230 EXPECT_TRUE(policy_manager()
bartfab (slow) 2015/02/18 13:21:52 Nit: This piece is copy & pasted to other places.
binjin 2015/02/18 15:37:49 Done.
231 ->core()
232 ->remote_commands_service()
233 ->FetchRemoteCommands());
234 run_loop.Run();
235 }
236
237 // Tests that existing commands issued before service started will be fetched.
238 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, ExistingCommand) {
239 scoped_ptr<MockTestRemoteCommandFactory> factory(
240 new MockTestRemoteCommandFactory());
241 EXPECT_CALL(*factory, BuildTestCommand())
bartfab (slow) 2015/02/18 13:21:52 This code is copy & pasted to other places. Please
binjin 2015/02/18 15:37:49 Done. Used WillByDefault() though.
242 .Times(1)
243 .WillOnce(ReturnNew<TestRemoteCommandJob>(
244 true, base::TimeDelta::FromSeconds(1)));
bartfab (slow) 2015/02/18 13:21:53 Nit: Can you create a constant for |base::TimeDelt
binjin 2015/02/18 15:37:49 I'm not sure if it's okay to create a global insta
bartfab (slow) 2015/02/23 13:13:56 The way you did it is correct. A static initialize
binjin 2015/02/24 05:29:49 Acknowledged.
245
246 Register();
247
248 // Issue a command before service started.
249 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
250 false);
251
252 {
253 // Start the service, run until the command is fetched.
254 base::RunLoop run_loop;
255 interceptor_->PushJobCallback(
256 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 1u));
257 interceptor_->AddRequestServicedCallback(run_loop.QuitClosure());
258 StartService(factory.Pass());
259 run_loop.Run();
260 }
261
262 {
263 // And run until the command result is reported.
264 base::RunLoop run_loop;
265 interceptor_->PushJobCallback(
266 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 1u, 0u));
267 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
268 .Times(1)
269 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
270 run_loop.Run();
271 }
272
273 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
274 }
275
276 // Tests that commands issued after service started will be fetched.
277 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NewCommand) {
278 scoped_ptr<MockTestRemoteCommandFactory> factory(
279 new MockTestRemoteCommandFactory());
280 EXPECT_CALL(*factory, BuildTestCommand())
281 .Times(1)
282 .WillOnce(ReturnNew<TestRemoteCommandJob>(
283 true, base::TimeDelta::FromSeconds(1)));
284
285 Register();
286 StartServiceWithoutCommandsFetched(factory.Pass());
287
288 // The first request will fetch one command, and the second will fetch none
289 // but provide result for the previous command instead.
290 interceptor_->PushJobCallback(
291 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 1u));
292 interceptor_->PushJobCallback(
293 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 1u, 0u));
294
295 base::RunLoop run_loop;
296 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
297 .Times(1)
298 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
299 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
300 false);
301
302 // Manually trigger a command fetch immediately, it's supposed to be
303 // triggered by invalidation service though.
304 EXPECT_TRUE(policy_manager()
305 ->core()
306 ->remote_commands_service()
307 ->FetchRemoteCommands());
308
309 // Run until the result of commands is reported.
310 run_loop.Run();
311
312 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
313 }
314
315 // Tests that commands issued after service will be fetched even if there is
316 // delay between command issued and invalidation service triggerred fetch.
bartfab (slow) 2015/02/18 13:21:53 I am not sure this test is necessary. You tested t
binjin 2015/02/18 15:37:49 Deleted.
317 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NewDelayedCommand) {
318 scoped_ptr<MockTestRemoteCommandFactory> factory(
319 new MockTestRemoteCommandFactory());
320 EXPECT_CALL(*factory, BuildTestCommand())
321 .Times(1)
322 .WillOnce(ReturnNew<TestRemoteCommandJob>(
323 true, base::TimeDelta::FromSeconds(1)));
324
325 Register();
326 StartServiceWithoutCommandsFetched(factory.Pass());
327
328 // The first request will fetch one command, and the second will fetch none
329 // but provide result for the previous command instead.
330 interceptor_->PushJobCallback(
331 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 1u));
332 interceptor_->PushJobCallback(
333 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 1u, 0u));
334
335 base::RunLoop run_loop;
336 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
337 .Times(1)
338 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
bartfab (slow) 2015/02/18 13:21:53 AFAICT, all of the code above is shared with the p
binjin 2015/02/18 15:37:49 Acknowledged.
339
340 // Issue the command and simulate one second delay for invalidation service.
341 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
342 false);
343 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
bartfab (slow) 2015/02/18 13:21:52 You cannot do this in tests. Tests must not slow d
binjin 2015/02/18 15:37:48 Acknowledged.
344 FROM_HERE,
345 base::Bind(
346 base::IgnoreResult(&RemoteCommandsService::FetchRemoteCommands),
347 base::Unretained(
348 policy_manager()->core()->remote_commands_service())),
349 base::TimeDelta::FromSeconds(1));
350
351 // Run until the result of command is reported.
352 run_loop.Run();
353
354 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
355 }
356
357 // Tests that commands issued after service will be fetched even if the
358 // network is unstable.
bartfab (slow) 2015/02/18 13:21:52 Nice. Good to see you are testing such an (sadly,
binjin 2015/02/18 15:37:49 Acknowledged.
359 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NewCommandWithBadConnection) {
360 scoped_ptr<MockTestRemoteCommandFactory> factory(
361 new MockTestRemoteCommandFactory());
362 EXPECT_CALL(*factory, BuildTestCommand())
363 .Times(1)
364 .WillOnce(ReturnNew<TestRemoteCommandJob>(
365 true, base::TimeDelta::FromSeconds(1)));
366
367 Register();
368 StartServiceWithoutCommandsFetched(factory.Pass());
369
370 // Inserts some bad request resposne due to network here.
371 interceptor_->PushJobCallback(
372 TestRequestInterceptor::ErrorJob(net::ERR_NETWORK_CHANGED));
373 interceptor_->PushJobCallback(
374 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 1u));
375 interceptor_->PushJobCallback(
376 TestRequestInterceptor::ErrorJob(net::ERR_NETWORK_CHANGED));
377 interceptor_->PushJobCallback(
378 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 1u, 0u));
379
380 base::RunLoop run_loop;
381 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
382 .Times(1)
383 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
384 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
385 false);
386
387 EXPECT_TRUE(policy_manager()
388 ->core()
389 ->remote_commands_service()
390 ->FetchRemoteCommands());
391
392 // Run until the result of command is reported.
393 run_loop.Run();
394
395 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
396 }
397
398 // Tests that commands issued after service started will be fetched, even if
399 // the command is issued when a fetch request is ongoing.
400 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NewCommandFollwingFetch) {
401 scoped_ptr<MockTestRemoteCommandFactory> factory(
402 new MockTestRemoteCommandFactory());
403 EXPECT_CALL(*factory, BuildTestCommand())
404 .Times(1)
405 .WillOnce(ReturnNew<TestRemoteCommandJob>(
406 true, base::TimeDelta::FromSeconds(1)));
407
408 Register();
409 StartServiceWithoutCommandsFetched(factory.Pass());
410
411 // Add a command which will be issued after first fetch.
412 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
413 true);
414
415 {
416 base::RunLoop run_loop;
417 interceptor_->PushJobCallback(
418 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 0u));
419 interceptor_->AddRequestServicedCallback(run_loop.QuitClosure());
420
421 // Attempts to fetch commands.
422 EXPECT_TRUE(policy_manager()
423 ->core()
424 ->remote_commands_service()
425 ->FetchRemoteCommands());
426
427 // There should be not issued command at this point.
428 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
429
430 // The command fetch should be in progress.
431 EXPECT_TRUE(policy_manager()
432 ->core()
433 ->remote_commands_service()
434 ->IsCommandFetchInProgressForTesting());
435
436 // And second a following up fetch request should be ignored.
bartfab (slow) 2015/02/18 13:21:52 It is not ignored but enqueued.
binjin 2015/02/18 15:37:49 Done.
437 EXPECT_FALSE(policy_manager()
438 ->core()
439 ->remote_commands_service()
440 ->FetchRemoteCommands());
441
442 // Run until first fetch request is completed.
443 run_loop.Run();
444 }
445
446 // The delayed command should be issued now.
bartfab (slow) 2015/02/18 13:21:52 In reality, the order would be different: The seco
binjin 2015/02/18 15:37:49 Done.
447 EXPECT_EQ(1u, server_->NumberOfCommandsPendingResult());
448
449 interceptor_->PushJobCallback(
450 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 0u, 1u));
451 interceptor_->PushJobCallback(
452 TestRequestInterceptor::FetchRemoteCommandsJob(server_.get(), 1u, 0u));
453
454 // No further fetch request is made, but the new issued command should be
455 // fetched and executed.
456 base::RunLoop run_loop;
457 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
458 .Times(1)
459 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
460
461 run_loop.Run();
462
463 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
464 }
465
466 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698