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"
15 // Returns the current process state.
16 SBOX_TESTS_COMMAND
int IntegrationTestsTest_state(int argc
, wchar_t **argv
) {
17 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
20 if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf())
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
)
35 if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
36 if (BEFORE_INIT
== state
)
37 state
= BEFORE_REVERT
;
41 if (BEFORE_REVERT
== state
)
46 // Blocks the process for argv[0] milliseconds simulating stuck child.
47 SBOX_TESTS_COMMAND
int IntegrationTestsTest_stuck(int argc
, wchar_t **argv
) {
50 timeout
= _wtoi(argv
[0]);
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
++) {
61 size_t argument_bytes
= wcslen(argv
[i
]) * sizeof(wchar_t);
62 memcpy(argument
, argv
[i
], __min(sizeof(argument
), argument_bytes
));
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
76 SBOX_TESTS_COMMAND
int IntegrationTestsTest_job(int argc
, wchar_t **argv
) {
77 HANDLE job
= ::CreateJobObject(NULL
, NULL
);
81 JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_limits
;
82 if (!::QueryInformationJobObject(job
, JobObjectExtendedLimitInformation
,
83 &job_limits
, sizeof(job_limits
), NULL
)) {
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.
89 job_limits
.BasicLimitInformation
.LimitFlags
|=
90 JOB_OBJECT_LIMIT_BREAKAWAY_OK
;
92 job_limits
.BasicLimitInformation
.LimitFlags
&=
93 ~JOB_OBJECT_LIMIT_BREAKAWAY_OK
;
95 if (!::SetInformationJobObject(job
, JobObjectExtendedLimitInformation
,
96 &job_limits
, sizeof(job_limits
))) {
99 if (!::AssignProcessToJobObject(job
, ::GetCurrentProcess()))
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"))
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
) {
120 runner
.SetTimeout(2000);
121 runner
.SetTestState(BEFORE_INIT
);
122 ASSERT_EQ(BEFORE_INIT
, runner
.RunTest(L
"IntegrationTestsTest_state"));
125 TEST(IntegrationTestsTest
, CallsBeforeRevert
) {
127 runner
.SetTimeout(2000);
128 runner
.SetTestState(BEFORE_REVERT
);
129 ASSERT_EQ(BEFORE_REVERT
, runner
.RunTest(L
"IntegrationTestsTest_state"));
132 TEST(IntegrationTestsTest
, CallsAfterRevert
) {
134 runner
.SetTimeout(2000);
135 runner
.SetTestState(AFTER_REVERT
);
136 ASSERT_EQ(AFTER_REVERT
, runner
.RunTest(L
"IntegrationTestsTest_state"));
139 TEST(IntegrationTestsTest
, CallsEveryState
) {
141 runner
.SetTimeout(2000);
142 runner
.SetTestState(EVERY_STATE
);
143 ASSERT_EQ(AFTER_REVERT
, runner
.RunTest(L
"IntegrationTestsTest_state2"));
146 TEST(IntegrationTestsTest
, ForwardsArguments
) {
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 "
155 TEST(IntegrationTestsTest
, WaitForStuckChild
) {
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
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
) {
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
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
) {
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
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
) {
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());
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
) {
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
;
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
) {
300 runner
.SetUnsandboxed(true);
301 runner
.SetTimeout(2000);
302 ASSERT_EQ(SBOX_TEST_SUCCEEDED
,
303 runner
.RunTest(L
"IntegrationTestsTest_job none"));
306 } // namespace sandbox