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: fixes addressing #10 #11 and #12 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"
bartfab (slow) 2015/02/23 13:13:57 Nit: Not used.
binjin 2015/02/24 05:29:49 Done.
11 #include "base/macros.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/policy/cloud/test_request_interceptor.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "components/policy/core/browser/browser_policy_connector.h"
21 #include "components/policy/core/common/policy_switches.h"
22 #include "components/policy/core/common/remote_commands/remote_command_job.h"
23 #include "components/policy/core/common/remote_commands/remote_commands_factory. h"
24 #include "components/policy/core/common/remote_commands/remote_commands_service. h"
25 #include "components/policy/core/common/remote_commands/test_remote_command_job. h"
26 #include "components/policy/core/common/remote_commands/testing_remote_commands_ server.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "net/base/net_errors.h"
29 #include "net/url_request/url_request_context_getter.h"
30 #include "policy/proto/device_management_backend.pb.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 #if defined(OS_CHROMEOS)
35 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
36 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chrom eos.h"
37 #else
38 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
39 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
40 #endif
41
42 using testing::AnyNumber;
43 using testing::InvokeWithoutArgs;
44 using testing::ReturnNew;
45 using testing::_;
46
47 namespace policy {
48
49 namespace {
50 const char kTestToken[] = "secret_token";
51 const char kTestClientID[] = "testing_client_id";
52 const char kTestPayload[] = "_testing_payload_";
53
54 const int kTestCommandExecutionTimeInSeconds = 1;
55 } // namespace
56
57 namespace em = enterprise_management;
58
59 // Mocked RemoteCommand factory to allow us to build test commands.
60 class MockTestRemoteCommandFactory : public RemoteCommandsFactory {
61 public:
62 MockTestRemoteCommandFactory() {
63 ON_CALL(*this, BuildTestCommand())
64 .WillByDefault(ReturnNew<TestRemoteCommandJob>(
65 true,
66 base::TimeDelta::FromSeconds(kTestCommandExecutionTimeInSeconds)));
67 }
68 ~MockTestRemoteCommandFactory() override {}
69
70 MOCK_METHOD0(BuildTestCommand, TestRemoteCommandJob*());
71
72 private:
73 // RemoteCommandJobsFactory:
74 scoped_ptr<RemoteCommandJob> BuildJobForType(
75 em::RemoteCommand_Type type) override {
76 if (type != em::RemoteCommand_Type_COMMAND_ECHO_TEST) {
77 ADD_FAILURE();
78 return nullptr;
79 }
80 return make_scoped_ptr<RemoteCommandJob>(BuildTestCommand());
81 }
82
83 DISALLOW_COPY_AND_ASSIGN(MockTestRemoteCommandFactory);
84 };
85
86 // Mocked TestingRemoteCommandsServer for verifying commands results.
87 class MockRemoteCommandsServer : public TestingRemoteCommandsServer {
88 public:
89 MockRemoteCommandsServer() {}
90 ~MockRemoteCommandsServer() override {}
91
92 MOCK_CONST_METHOD2(SucceededJobReported,
93 void(const std::string&, base::Time));
94 MOCK_CONST_METHOD1(FailedJobReported, void(base::Time));
95 MOCK_CONST_METHOD1(IgnoredJobReported, void(base::Time));
96
97 private:
98 // TestingRemoteCommandsServer:
99 void OnJobResultReported(const enterprise_management::RemoteCommandResult&
100 job_result) const override {
101 const base::Time timestamp =
102 base::TimeDelta::FromMilliseconds(job_result.timestamp()) +
103 base::Time::UnixEpoch();
104 switch (job_result.result()) {
105 case em::RemoteCommandResult_ResultType_RESULT_SUCCESS:
106 SucceededJobReported(job_result.payload(), timestamp);
107 break;
108 case em::RemoteCommandResult_ResultType_RESULT_FAILURE:
109 FailedJobReported(timestamp);
110 break;
111 case em::RemoteCommandResult_ResultType_RESULT_IGNORED:
112 IgnoredJobReported(timestamp);
113 break;
114 default:
115 ADD_FAILURE();
116 }
117 }
118
119 DISALLOW_COPY_AND_ASSIGN(MockRemoteCommandsServer);
120 };
121
122 // Base class for all browser tests regarding remote commands service.
123 class RemoteCommandsBrowserTest : public InProcessBrowserTest {
124 protected:
125 RemoteCommandsBrowserTest() {}
126 ~RemoteCommandsBrowserTest() override {}
127
128 // Register on DMServer with faked token and client id.
129 void Register() {
130 ASSERT_TRUE(policy_manager());
131 ASSERT_TRUE(policy_manager()->core()->client());
132
133 EXPECT_FALSE(policy_manager()->core()->client()->is_registered());
134 policy_manager()->core()->client()->SetupRegistration(kTestToken,
135 kTestClientID);
136 EXPECT_TRUE(policy_manager()->core()->client()->is_registered());
137 }
138
139 // Start the service, must be called after Register(). Note that remote
140 // commands service will immediately start fetching commands.
141 void StartService(scoped_ptr<MockTestRemoteCommandFactory> factory) {
142 EXPECT_FALSE(service_started_);
143 service_started_ = true;
144
145 policy_manager()->core()->StartRemoteCommandsService(factory.Pass());
146 }
147
148 // Start the service, but will wait until the initial remote commands
149 // fetch completes (with no command fetched).
150 void StartServiceWithoutCommandsFetched(
151 scoped_ptr<MockTestRemoteCommandFactory> factory) {
152 PrepareRunLoopForNextFetch();
153 ExpectFetchCommands(0u, 0u);
154 StartService(factory.Pass());
155 run_loop_->Run();
156 }
157
158 void ExpectFetchCommands(size_t expected_command_results,
159 size_t expected_fetched_commands) {
160 interceptor_->PushJobCallback(
161 TestRequestInterceptor::FetchRemoteCommandsJob(
162 server_.get(), expected_command_results,
163 expected_fetched_commands));
164 }
165
166 void PrepareRunLoop() {
167 run_loop_.reset(new base::RunLoop);
168 }
169
170 void PrepareRunLoopForNextFetch() {
171 PrepareRunLoop();
172 interceptor_->AddRequestServicedCallback(run_loop_->QuitClosure());
173 }
174
175 void SetUpInProcessBrowserTestFixture() override {
176 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
177 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl,
178 "http://localhost");
179 }
180
181 void SetUpOnMainThread() override {
182 // Set up interceptor and ignore 'register' and 'policy' requests.
183 interceptor_.reset(new TestRequestInterceptor(
184 "localhost", content::BrowserThread::GetMessageLoopProxyForThread(
185 content::BrowserThread::IO)));
186 interceptor_->AddIgnoredRequestType("register");
187 interceptor_->AddIgnoredRequestType("policy");
188
189 server_.reset(new MockRemoteCommandsServer());
190
191 BrowserPolicyConnector* const connector =
192 g_browser_process->browser_policy_connector();
193 connector->ScheduleServiceInitialization(0);
194
195 ASSERT_TRUE(policy_manager());
196
197 #if !defined(OS_CHROMEOS)
198 policy_manager()->Connect(
199 g_browser_process->local_state(),
200 g_browser_process->system_request_context(),
201 UserCloudPolicyManager::CreateCloudPolicyClient(
202 connector->device_management_service(),
203 g_browser_process->system_request_context()).Pass());
204 #endif
205 }
206
207 void TearDownOnMainThread() override {
208 EXPECT_EQ(0u, interceptor_->GetPendingSize());
209 interceptor_.reset();
210 server_.reset();
211 }
212
213 #if defined(OS_CHROMEOS)
214 UserCloudPolicyManagerChromeOS* policy_manager() {
215 return UserCloudPolicyManagerFactoryChromeOS::GetForProfile(
216 browser()->profile());
217 }
218 #else
219 UserCloudPolicyManager* policy_manager() {
220 return UserCloudPolicyManagerFactory::GetForBrowserContext(
221 browser()->profile());
222 }
223 #endif // defined(OS_CHROMEOS)
224
225 RemoteCommandsService* remote_commands_service() {
226 return policy_manager()->core()->remote_commands_service();
227 }
228
229 scoped_ptr<base::RunLoop> run_loop_;
230
231 scoped_ptr<TestRequestInterceptor> interceptor_;
232 scoped_ptr<MockRemoteCommandsServer> server_;
233
234 private:
235 bool service_started_ = false;
236
237 DISALLOW_COPY_AND_ASSIGN(RemoteCommandsBrowserTest);
238 };
239
240 // Tests that no command will be fetched if no commands is issued.
241 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NoCommands) {
242 scoped_ptr<MockTestRemoteCommandFactory> factory(
243 new MockTestRemoteCommandFactory());
244 EXPECT_CALL(*factory, BuildTestCommand()).Times(0);
245
246 Register();
247 StartServiceWithoutCommandsFetched(factory.Pass());
248
249 // A follow up fetch requst should also get nothing from server.
250 ExpectFetchCommands(0u, 0u);
251 PrepareRunLoopForNextFetch();
252 EXPECT_TRUE(remote_commands_service()->FetchRemoteCommands());
253 run_loop_->Run();
254 }
255
256 // Tests that existing commands issued before service started will be fetched.
257 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, ExistingCommand) {
258 scoped_ptr<MockTestRemoteCommandFactory> factory(
259 new MockTestRemoteCommandFactory());
260 EXPECT_CALL(*factory, BuildTestCommand()).Times(1);
261
262 Register();
263
264 // Issue a command before service started.
265 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
266 false);
267
268 // Start the service, run until the command is fetched.
269 ExpectFetchCommands(0u, 1u);
270 PrepareRunLoopForNextFetch();
271 StartService(factory.Pass());
272 run_loop_->Run();
273
274 // And run until the command result is reported.
275 PrepareRunLoop();
276 ExpectFetchCommands(1u, 0u);
277 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
278 .Times(1)
279 .WillOnce(InvokeWithoutArgs(run_loop_.get(), &base::RunLoop::Quit));
280 run_loop_->Run();
281
282 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
283 }
284
285 // Tests that commands issued after service started will be fetched.
286 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NewCommand) {
287 scoped_ptr<MockTestRemoteCommandFactory> factory(
288 new MockTestRemoteCommandFactory());
289 EXPECT_CALL(*factory, BuildTestCommand()).Times(1);
290
291 Register();
292 StartServiceWithoutCommandsFetched(factory.Pass());
293
294 // The first request will fetch one command, and the second will fetch none
295 // but provide result for the previous command instead.
296 ExpectFetchCommands(0u, 1u);
297 ExpectFetchCommands(1u, 0u);
298
299 PrepareRunLoop();
300 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
301 .Times(1)
302 .WillOnce(InvokeWithoutArgs(run_loop_.get(), &base::RunLoop::Quit));
303 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
304 false);
305
306 // Manually trigger a command fetch immediately, it's supposed to be
307 // triggered by invalidation service though.
308 EXPECT_TRUE(remote_commands_service()->FetchRemoteCommands());
309
310 // Run until the result of commands is reported.
311 run_loop_->Run();
312
313 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
314 }
315
316 // Tests that commands issued after service will be fetched even if the
317 // network is unstable.
318 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NewCommandWithBadConnection) {
319 scoped_ptr<MockTestRemoteCommandFactory> factory(
320 new MockTestRemoteCommandFactory());
321 EXPECT_CALL(*factory, BuildTestCommand()).Times(1);
322
323 Register();
324 StartServiceWithoutCommandsFetched(factory.Pass());
325
326 // Inserts some bad request resposne due to network here.
327 interceptor_->PushJobCallback(
328 TestRequestInterceptor::ErrorJob(net::ERR_NETWORK_CHANGED));
329 ExpectFetchCommands(0u, 1u);
330 interceptor_->PushJobCallback(
331 TestRequestInterceptor::ErrorJob(net::ERR_NETWORK_CHANGED));
332 ExpectFetchCommands(1u, 0u);
333
334 PrepareRunLoop();
335 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
336 .Times(1)
337 .WillOnce(InvokeWithoutArgs(run_loop_.get(), &base::RunLoop::Quit));
338 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
339 false);
340
341 EXPECT_TRUE(remote_commands_service()->FetchRemoteCommands());
342
343 // Run until the result of command is reported.
344 run_loop_->Run();
345
346 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
347 }
348
349 // Tests that commands issued after service started will be fetched, even if
350 // the command is issued when a fetch request is ongoing.
351 IN_PROC_BROWSER_TEST_F(RemoteCommandsBrowserTest, NewCommandFollwingFetch) {
352 scoped_ptr<MockTestRemoteCommandFactory> factory(
353 new MockTestRemoteCommandFactory());
354 EXPECT_CALL(*factory, BuildTestCommand()).Times(1);
355
356 Register();
357 StartServiceWithoutCommandsFetched(factory.Pass());
358
359 // Add a command which will be issued after first fetch.
360 server_->IssueCommand(em::RemoteCommand_Type_COMMAND_ECHO_TEST, kTestPayload,
361 true);
362
363 PrepareRunLoopForNextFetch();
364 ExpectFetchCommands(0u, 0u);
365
366 // Attempts to fetch commands.
367 EXPECT_TRUE(remote_commands_service()->FetchRemoteCommands());
368
369 // There should be not issued command at this point.
370 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
371
372 // The command fetch should be in progress.
373 EXPECT_TRUE(remote_commands_service()->IsCommandFetchInProgressForTesting());
374
375 // And second a following up fetch request should be enqueued.
376 EXPECT_FALSE(remote_commands_service()->FetchRemoteCommands());
377
378 // Run until first fetch request is completed.
379 run_loop_->Run();
380
381 // The command should be issued now. Note that this command was actually
382 // issued before the first fetch request completes in previous run loop.
383 EXPECT_EQ(1u, server_->NumberOfCommandsPendingResult());
384
385 ExpectFetchCommands(0u, 1u);
386 ExpectFetchCommands(1u, 0u);
387
388 // No further fetch request is made, but the new issued command should be
389 // fetched and executed.
390 PrepareRunLoop();
391 EXPECT_CALL(*server_, SucceededJobReported(kTestPayload, _))
392 .Times(1)
393 .WillOnce(InvokeWithoutArgs(run_loop_.get(), &base::RunLoop::Quit));
bartfab (slow) 2015/02/23 13:13:57 Nit: This EXPECT_CALL() appears in at least four p
binjin 2015/02/24 05:29:49 Code removed, N/A now.
394
395 run_loop_->Run();
396
397 EXPECT_EQ(0u, server_->NumberOfCommandsPendingResult());
398 }
399
400 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698