Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / sandbox / win / tests / integration_tests / integration_tests_test.cc
blob44055d3d5337339b5a502b2e80f76b833b8eafbc
1 // Copyright (c) 2006-2008 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 // Some tests for the framework itself.
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "sandbox/win/src/sandbox.h"
9 #include "sandbox/win/src/target_services.h"
10 #include "sandbox/win/src/sandbox_factory.h"
11 #include "sandbox/win/tests/common/controller.h"
13 namespace sandbox {
15 // Returns the current process state.
16 SBOX_TESTS_COMMAND int IntegrationTestsTest_state(int argc, wchar_t **argv) {
17 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
18 return BEFORE_INIT;
20 if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf())
21 return BEFORE_REVERT;
23 return AFTER_REVERT;
26 // Returns the current process state, keeping track of it.
27 SBOX_TESTS_COMMAND int IntegrationTestsTest_state2(int argc, wchar_t **argv) {
28 static SboxTestsState state = MIN_STATE;
29 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) {
30 if (MIN_STATE == state)
31 state = BEFORE_INIT;
32 return state;
35 if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
36 if (BEFORE_INIT == state)
37 state = BEFORE_REVERT;
38 return state;
41 if (BEFORE_REVERT == state)
42 state = AFTER_REVERT;
43 return state;
46 // Blocks the process for argv[0] milliseconds simulating stuck child.
47 SBOX_TESTS_COMMAND int IntegrationTestsTest_stuck(int argc, wchar_t **argv) {
48 int timeout = 500;
49 if (argc > 0) {
50 timeout = _wtoi(argv[0]);
53 ::Sleep(timeout);
54 return 1;
57 // Returns the number of arguments
58 SBOX_TESTS_COMMAND int IntegrationTestsTest_args(int argc, wchar_t **argv) {
59 for (int i = 0; i < argc; i++) {
60 wchar_t argument[20];
61 size_t argument_bytes = wcslen(argv[i]) * sizeof(wchar_t);
62 memcpy(argument, argv[i], __min(sizeof(argument), argument_bytes));
65 return argc;
68 // Creates a job and tries to run a process inside it. The function can be
69 // called with up to two parameters. The first one if set to "none" means that
70 // the child process should be run with the JOB_NONE JobLevel else it is run
71 // with JOB_LOCKDOWN level. The second if present specifies that the
72 // JOB_OBJECT_LIMIT_BREAKAWAY_OK flag should be set on the job object created
73 // in this function. The return value is either SBOX_TEST_SUCCEEDED if the test
74 // has passed or a value between 0 and 4 indicating which part of the test has
75 // failed.
76 SBOX_TESTS_COMMAND int IntegrationTestsTest_job(int argc, wchar_t **argv) {
77 HANDLE job = ::CreateJobObject(NULL, NULL);
78 if (!job)
79 return 0;
81 JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_limits;
82 if (!::QueryInformationJobObject(job, JobObjectExtendedLimitInformation,
83 &job_limits, sizeof(job_limits), NULL)) {
84 return 1;
86 // We cheat here and assume no 2-nd parameter means no breakaway flag and any
87 // value for the second param means with breakaway flag.
88 if (argc > 1) {
89 job_limits.BasicLimitInformation.LimitFlags |=
90 JOB_OBJECT_LIMIT_BREAKAWAY_OK;
91 } else {
92 job_limits.BasicLimitInformation.LimitFlags &=
93 ~JOB_OBJECT_LIMIT_BREAKAWAY_OK;
95 if (!::SetInformationJobObject(job, JobObjectExtendedLimitInformation,
96 &job_limits, sizeof(job_limits))) {
97 return 2;
99 if (!::AssignProcessToJobObject(job, ::GetCurrentProcess()))
100 return 3;
102 JobLevel job_level = JOB_LOCKDOWN;
103 if (argc > 0 && wcscmp(argv[0], L"none") == 0)
104 job_level = JOB_NONE;
106 TestRunner runner(job_level, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
107 runner.SetTimeout(2000);
109 if (1 != runner.RunTest(L"IntegrationTestsTest_args 1"))
110 return 4;
112 // Terminate the job now.
113 ::TerminateJobObject(job, SBOX_TEST_SUCCEEDED);
114 // We should not make it to here but it doesn't mean our test failed.
115 return SBOX_TEST_SUCCEEDED;
118 TEST(IntegrationTestsTest, CallsBeforeInit) {
119 TestRunner runner;
120 runner.SetTimeout(2000);
121 runner.SetTestState(BEFORE_INIT);
122 ASSERT_EQ(BEFORE_INIT, runner.RunTest(L"IntegrationTestsTest_state"));
125 TEST(IntegrationTestsTest, CallsBeforeRevert) {
126 TestRunner runner;
127 runner.SetTimeout(2000);
128 runner.SetTestState(BEFORE_REVERT);
129 ASSERT_EQ(BEFORE_REVERT, runner.RunTest(L"IntegrationTestsTest_state"));
132 TEST(IntegrationTestsTest, CallsAfterRevert) {
133 TestRunner runner;
134 runner.SetTimeout(2000);
135 runner.SetTestState(AFTER_REVERT);
136 ASSERT_EQ(AFTER_REVERT, runner.RunTest(L"IntegrationTestsTest_state"));
139 TEST(IntegrationTestsTest, CallsEveryState) {
140 TestRunner runner;
141 runner.SetTimeout(2000);
142 runner.SetTestState(EVERY_STATE);
143 ASSERT_EQ(AFTER_REVERT, runner.RunTest(L"IntegrationTestsTest_state2"));
146 TEST(IntegrationTestsTest, ForwardsArguments) {
147 TestRunner runner;
148 runner.SetTimeout(2000);
149 runner.SetTestState(BEFORE_INIT);
150 ASSERT_EQ(1, runner.RunTest(L"IntegrationTestsTest_args first"));
151 ASSERT_EQ(4, runner.RunTest(L"IntegrationTestsTest_args first second third "
152 L"fourth"));
155 TEST(IntegrationTestsTest, WaitForStuckChild) {
156 TestRunner runner;
157 runner.SetTimeout(2000);
158 runner.SetAsynchronous(true);
159 runner.SetKillOnDestruction(false);
160 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
161 runner.RunTest(L"IntegrationTestsTest_stuck 100"));
162 ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
165 TEST(IntegrationTestsTest, NoWaitForStuckChildNoJob) {
166 TestRunner runner(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
167 runner.SetTimeout(2000);
168 runner.SetAsynchronous(true);
169 runner.SetKillOnDestruction(false);
170 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
171 runner.RunTest(L"IntegrationTestsTest_stuck 2000"));
172 ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
173 // In this case the processes are not tracked by the broker and should be
174 // still active.
175 DWORD exit_code;
176 ASSERT_TRUE(::GetExitCodeProcess(runner.process(), &exit_code));
177 ASSERT_EQ(STILL_ACTIVE, exit_code);
178 // Terminate the test process now.
179 ::TerminateProcess(runner.process(), 0);
182 TEST(IntegrationTestsTest, TwoStuckChildrenSecondOneHasNoJob) {
183 TestRunner runner;
184 runner.SetTimeout(2000);
185 runner.SetAsynchronous(true);
186 runner.SetKillOnDestruction(false);
187 TestRunner runner2(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
188 runner2.SetTimeout(2000);
189 runner2.SetAsynchronous(true);
190 runner2.SetKillOnDestruction(false);
191 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
192 runner.RunTest(L"IntegrationTestsTest_stuck 100"));
193 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
194 runner2.RunTest(L"IntegrationTestsTest_stuck 2000"));
195 // Actually both runners share the same singleton broker.
196 ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
197 // In this case the processes are not tracked by the broker and should be
198 // still active.
199 DWORD exit_code;
200 // Checking the exit code for |runner| is flaky on the slow bots but at
201 // least we know that the wait above has succeeded if we are here.
202 ASSERT_TRUE(::GetExitCodeProcess(runner2.process(), &exit_code));
203 ASSERT_EQ(STILL_ACTIVE, exit_code);
204 // Terminate the test process now.
205 ::TerminateProcess(runner2.process(), 0);
208 TEST(IntegrationTestsTest, TwoStuckChildrenFirstOneHasNoJob) {
209 TestRunner runner;
210 runner.SetTimeout(2000);
211 runner.SetAsynchronous(true);
212 runner.SetKillOnDestruction(false);
213 TestRunner runner2(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
214 runner2.SetTimeout(2000);
215 runner2.SetAsynchronous(true);
216 runner2.SetKillOnDestruction(false);
217 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
218 runner2.RunTest(L"IntegrationTestsTest_stuck 2000"));
219 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
220 runner.RunTest(L"IntegrationTestsTest_stuck 100"));
221 // Actually both runners share the same singleton broker.
222 ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
223 // In this case the processes are not tracked by the broker and should be
224 // still active.
225 DWORD exit_code;
226 // Checking the exit code for |runner| is flaky on the slow bots but at
227 // least we know that the wait above has succeeded if we are here.
228 ASSERT_TRUE(::GetExitCodeProcess(runner2.process(), &exit_code));
229 ASSERT_EQ(STILL_ACTIVE, exit_code);
230 // Terminate the test process now.
231 ::TerminateProcess(runner2.process(), 0);
234 TEST(IntegrationTestsTest, MultipleStuckChildrenSequential) {
235 TestRunner runner;
236 runner.SetTimeout(2000);
237 runner.SetAsynchronous(true);
238 runner.SetKillOnDestruction(false);
239 TestRunner runner2(JOB_NONE, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
240 runner2.SetTimeout(2000);
241 runner2.SetAsynchronous(true);
242 runner2.SetKillOnDestruction(false);
244 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
245 runner.RunTest(L"IntegrationTestsTest_stuck 100"));
246 // Actually both runners share the same singleton broker.
247 ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
248 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
249 runner2.RunTest(L"IntegrationTestsTest_stuck 2000"));
250 // Actually both runners share the same singleton broker.
251 ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
253 DWORD exit_code;
254 // Checking the exit code for |runner| is flaky on the slow bots but at
255 // least we know that the wait above has succeeded if we are here.
256 ASSERT_TRUE(::GetExitCodeProcess(runner2.process(), &exit_code));
257 ASSERT_EQ(STILL_ACTIVE, exit_code);
258 // Terminate the test process now.
259 ::TerminateProcess(runner2.process(), 0);
261 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
262 runner.RunTest(L"IntegrationTestsTest_stuck 100"));
263 // Actually both runners share the same singleton broker.
264 ASSERT_EQ(SBOX_ALL_OK, runner.broker()->WaitForAllTargets());
267 // Running from inside job that allows us to escape from it should be ok.
268 TEST(IntegrationTestsTest, RunChildFromInsideJob) {
269 TestRunner runner;
270 runner.SetUnsandboxed(true);
271 runner.SetTimeout(2000);
272 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
273 runner.RunTest(L"IntegrationTestsTest_job with_job escape_flag"));
276 // Running from inside job that doesn't allow us to escape from it should fail
277 // on any windows prior to 8.
278 TEST(IntegrationTestsTest, RunChildFromInsideJobNoEscape) {
279 int expect_result = 4; // Means the runner has failed to execute the child.
280 // Check if we are on Win8 or newer and expect a success as newer windows
281 // versions support nested jobs.
282 OSVERSIONINFOEX version_info = { sizeof version_info };
283 ::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info));
284 if (version_info.dwMajorVersion > 6 ||
285 (version_info.dwMajorVersion == 6 && version_info.dwMinorVersion >= 2)) {
286 expect_result = SBOX_TEST_SUCCEEDED;
289 TestRunner runner;
290 runner.SetUnsandboxed(true);
291 runner.SetTimeout(2000);
292 ASSERT_EQ(expect_result,
293 runner.RunTest(L"IntegrationTestsTest_job with_job"));
296 // Running without a job object should be ok regardless of the fact that we are
297 // running inside an outter job.
298 TEST(IntegrationTestsTest, RunJoblessChildFromInsideJob) {
299 TestRunner runner;
300 runner.SetUnsandboxed(true);
301 runner.SetTimeout(2000);
302 ASSERT_EQ(SBOX_TEST_SUCCEEDED,
303 runner.RunTest(L"IntegrationTestsTest_job none"));
306 } // namespace sandbox