1 // Copyright (c) 2012 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 // This file contains unit tests for the job object.
7 #include "base/win/scoped_process_information.h"
8 #include "sandbox/win/src/job.h"
9 #include "testing/gtest/include/gtest/gtest.h"
13 // Tests the creation and destruction of the job.
14 TEST(JobTest
, TestCreation
) {
15 // Scope the creation of Job.
19 ASSERT_EQ(ERROR_SUCCESS
, job
.Init(JOB_LOCKDOWN
, L
"my_test_job_name", 0, 0));
21 // check if the job exists.
22 HANDLE job_handle
= ::OpenJobObjectW(GENERIC_ALL
, FALSE
,
24 ASSERT_TRUE(job_handle
!= NULL
);
27 CloseHandle(job_handle
);
30 // Check if the job is destroyed when the object goes out of scope.
31 HANDLE job_handle
= ::OpenJobObjectW(GENERIC_ALL
, FALSE
, L
"my_test_job_name");
32 ASSERT_TRUE(job_handle
== NULL
);
33 ASSERT_EQ(ERROR_FILE_NOT_FOUND
, ::GetLastError());
36 // Tests the method "Take".
38 base::win::ScopedHandle job_handle
;
39 // Scope the creation of Job.
43 ASSERT_EQ(ERROR_SUCCESS
, job
.Init(JOB_LOCKDOWN
, L
"my_test_job_name", 0, 0));
45 job_handle
= job
.Take();
46 ASSERT_TRUE(job_handle
.IsValid());
49 // Check to be sure that the job is still alive even after the object is gone
51 HANDLE job_handle_dup
= ::OpenJobObjectW(GENERIC_ALL
, FALSE
,
53 ASSERT_TRUE(job_handle_dup
!= NULL
);
55 // Remove all references.
57 ::CloseHandle(job_handle_dup
);
61 // Check if the jbo is really dead.
62 job_handle_dup
= ::OpenJobObjectW(GENERIC_ALL
, FALSE
, L
"my_test_job_name");
63 ASSERT_TRUE(job_handle_dup
== NULL
);
64 ASSERT_EQ(ERROR_FILE_NOT_FOUND
, ::GetLastError());
67 // Tests the ui exceptions
68 TEST(JobTest
, TestExceptions
) {
69 base::win::ScopedHandle job_handle
;
70 // Scope the creation of Job.
74 ASSERT_EQ(ERROR_SUCCESS
, job
.Init(JOB_LOCKDOWN
, L
"my_test_job_name",
75 JOB_OBJECT_UILIMIT_READCLIPBOARD
, 0));
77 job_handle
= job
.Take();
78 ASSERT_TRUE(job_handle
.IsValid());
80 JOBOBJECT_BASIC_UI_RESTRICTIONS jbur
= {0};
81 DWORD size
= sizeof(jbur
);
82 BOOL result
= ::QueryInformationJobObject(job_handle
.Get(),
83 JobObjectBasicUIRestrictions
,
87 ASSERT_EQ(jbur
.UIRestrictionsClass
& JOB_OBJECT_UILIMIT_READCLIPBOARD
, 0);
91 // Scope the creation of Job.
95 ASSERT_EQ(ERROR_SUCCESS
, job
.Init(JOB_LOCKDOWN
, L
"my_test_job_name", 0, 0));
97 job_handle
= job
.Take();
98 ASSERT_TRUE(job_handle
.IsValid());
100 JOBOBJECT_BASIC_UI_RESTRICTIONS jbur
= {0};
101 DWORD size
= sizeof(jbur
);
102 BOOL result
= ::QueryInformationJobObject(job_handle
.Get(),
103 JobObjectBasicUIRestrictions
,
107 ASSERT_EQ(jbur
.UIRestrictionsClass
& JOB_OBJECT_UILIMIT_READCLIPBOARD
,
108 JOB_OBJECT_UILIMIT_READCLIPBOARD
);
112 // Tests the error case when the job is initialized twice.
113 TEST(JobTest
, DoubleInit
) {
116 ASSERT_EQ(ERROR_SUCCESS
, job
.Init(JOB_LOCKDOWN
, L
"my_test_job_name", 0, 0));
117 ASSERT_EQ(ERROR_ALREADY_INITIALIZED
, job
.Init(JOB_LOCKDOWN
, L
"test", 0, 0));
120 // Tests the error case when we use a method and the object is not yet
122 TEST(JobTest
, NoInit
) {
124 ASSERT_EQ(ERROR_NO_DATA
, job
.UserHandleGrantAccess(NULL
));
125 ASSERT_EQ(ERROR_NO_DATA
, job
.AssignProcessToJob(NULL
));
126 ASSERT_FALSE(job
.Take().IsValid());
129 // Tests the initialization of the job with different security level.
130 TEST(JobTest
, SecurityLevel
) {
132 ASSERT_EQ(ERROR_SUCCESS
, job1
.Init(JOB_LOCKDOWN
, L
"job1", 0, 0));
135 ASSERT_EQ(ERROR_SUCCESS
, job2
.Init(JOB_RESTRICTED
, L
"job2", 0, 0));
138 ASSERT_EQ(ERROR_SUCCESS
, job3
.Init(JOB_LIMITED_USER
, L
"job3", 0, 0));
141 ASSERT_EQ(ERROR_SUCCESS
, job4
.Init(JOB_INTERACTIVE
, L
"job4", 0, 0));
144 ASSERT_EQ(ERROR_SUCCESS
, job5
.Init(JOB_UNPROTECTED
, L
"job5", 0, 0));
146 // JOB_NONE means we run without a job object so Init should fail.
148 ASSERT_EQ(ERROR_BAD_ARGUMENTS
, job6
.Init(JOB_NONE
, L
"job6", 0, 0));
151 ASSERT_EQ(ERROR_BAD_ARGUMENTS
, job7
.Init(
152 static_cast<JobLevel
>(JOB_NONE
+1), L
"job7", 0, 0));
155 // Tests the method "AssignProcessToJob".
156 TEST(JobTest
, ProcessInJob
) {
159 ASSERT_EQ(ERROR_SUCCESS
, job
.Init(JOB_UNPROTECTED
, L
"job_test_process", 0,
164 wchar_t notepad
[] = L
"notepad";
165 STARTUPINFO si
= { sizeof(si
) };
166 PROCESS_INFORMATION temp_process_info
= {};
167 result
= ::CreateProcess(NULL
, notepad
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
,
170 base::win::ScopedProcessInformation
pi(temp_process_info
);
171 ASSERT_EQ(ERROR_SUCCESS
, job
.AssignProcessToJob(pi
.process_handle()));
173 // Get the job handle.
174 base::win::ScopedHandle job_handle
= job
.Take();
176 // Check if the process is in the job.
177 JOBOBJECT_BASIC_PROCESS_ID_LIST jbpidl
= {0};
178 DWORD size
= sizeof(jbpidl
);
179 result
= ::QueryInformationJobObject(job_handle
.Get(),
180 JobObjectBasicProcessIdList
,
181 &jbpidl
, size
, &size
);
184 EXPECT_EQ(1, jbpidl
.NumberOfAssignedProcesses
);
185 EXPECT_EQ(1, jbpidl
.NumberOfProcessIdsInList
);
186 EXPECT_EQ(pi
.process_id(), jbpidl
.ProcessIdList
[0]);
188 EXPECT_TRUE(::TerminateProcess(pi
.process_handle(), 0));
191 } // namespace sandbox