OLD | NEW |
| (Empty) |
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. | |
4 | |
5 // This file contains unit tests for the job object. | |
6 | |
7 #include "base/win/scoped_process_information.h" | |
8 #include "sandbox/win/src/job.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 | |
11 namespace sandbox { | |
12 | |
13 // Tests the creation and destruction of the job. | |
14 TEST(JobTest, TestCreation) { | |
15 // Scope the creation of Job. | |
16 { | |
17 // Create the job. | |
18 Job job; | |
19 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
20 job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); | |
21 | |
22 // check if the job exists. | |
23 HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, | |
24 L"my_test_job_name"); | |
25 ASSERT_TRUE(job_handle != NULL); | |
26 | |
27 if (job_handle) | |
28 CloseHandle(job_handle); | |
29 } | |
30 | |
31 // Check if the job is destroyed when the object goes out of scope. | |
32 HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); | |
33 ASSERT_TRUE(job_handle == NULL); | |
34 ASSERT_EQ(static_cast<DWORD>(ERROR_FILE_NOT_FOUND), ::GetLastError()); | |
35 } | |
36 | |
37 // Tests the method "Take". | |
38 TEST(JobTest, Take) { | |
39 base::win::ScopedHandle job_handle; | |
40 // Scope the creation of Job. | |
41 { | |
42 // Create the job. | |
43 Job job; | |
44 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
45 job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); | |
46 | |
47 job_handle = job.Take(); | |
48 ASSERT_TRUE(job_handle.IsValid()); | |
49 } | |
50 | |
51 // Check to be sure that the job is still alive even after the object is gone | |
52 // out of scope. | |
53 HANDLE job_handle_dup = ::OpenJobObjectW(GENERIC_ALL, FALSE, | |
54 L"my_test_job_name"); | |
55 ASSERT_TRUE(job_handle_dup != NULL); | |
56 | |
57 // Remove all references. | |
58 if (job_handle_dup) | |
59 ::CloseHandle(job_handle_dup); | |
60 | |
61 job_handle.Close(); | |
62 | |
63 // Check if the jbo is really dead. | |
64 job_handle_dup = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); | |
65 ASSERT_TRUE(job_handle_dup == NULL); | |
66 ASSERT_EQ(static_cast<DWORD>(ERROR_FILE_NOT_FOUND), ::GetLastError()); | |
67 } | |
68 | |
69 // Tests the ui exceptions | |
70 TEST(JobTest, TestExceptions) { | |
71 base::win::ScopedHandle job_handle; | |
72 // Scope the creation of Job. | |
73 { | |
74 // Create the job. | |
75 Job job; | |
76 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
77 job.Init(JOB_LOCKDOWN, L"my_test_job_name", | |
78 JOB_OBJECT_UILIMIT_READCLIPBOARD, 0)); | |
79 | |
80 job_handle = job.Take(); | |
81 ASSERT_TRUE(job_handle.IsValid()); | |
82 | |
83 JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; | |
84 DWORD size = sizeof(jbur); | |
85 BOOL result = ::QueryInformationJobObject(job_handle.Get(), | |
86 JobObjectBasicUIRestrictions, | |
87 &jbur, size, &size); | |
88 ASSERT_TRUE(result); | |
89 | |
90 ASSERT_EQ(0u, jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD); | |
91 job_handle.Close(); | |
92 } | |
93 | |
94 // Scope the creation of Job. | |
95 { | |
96 // Create the job. | |
97 Job job; | |
98 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
99 job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); | |
100 | |
101 job_handle = job.Take(); | |
102 ASSERT_TRUE(job_handle.IsValid()); | |
103 | |
104 JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; | |
105 DWORD size = sizeof(jbur); | |
106 BOOL result = ::QueryInformationJobObject(job_handle.Get(), | |
107 JobObjectBasicUIRestrictions, | |
108 &jbur, size, &size); | |
109 ASSERT_TRUE(result); | |
110 | |
111 ASSERT_EQ(static_cast<DWORD>(JOB_OBJECT_UILIMIT_READCLIPBOARD), | |
112 jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD); | |
113 } | |
114 } | |
115 | |
116 // Tests the error case when the job is initialized twice. | |
117 TEST(JobTest, DoubleInit) { | |
118 // Create the job. | |
119 Job job; | |
120 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
121 job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); | |
122 ASSERT_EQ(static_cast<DWORD>(ERROR_ALREADY_INITIALIZED), | |
123 job.Init(JOB_LOCKDOWN, L"test", 0, 0)); | |
124 } | |
125 | |
126 // Tests the error case when we use a method and the object is not yet | |
127 // initialized. | |
128 TEST(JobTest, NoInit) { | |
129 Job job; | |
130 ASSERT_EQ(static_cast<DWORD>(ERROR_NO_DATA), job.UserHandleGrantAccess(NULL)); | |
131 ASSERT_EQ(static_cast<DWORD>(ERROR_NO_DATA), job.AssignProcessToJob(NULL)); | |
132 ASSERT_FALSE(job.Take().IsValid()); | |
133 } | |
134 | |
135 // Tests the initialization of the job with different security level. | |
136 TEST(JobTest, SecurityLevel) { | |
137 Job job1; | |
138 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
139 job1.Init(JOB_LOCKDOWN, L"job1", 0, 0)); | |
140 | |
141 Job job2; | |
142 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
143 job2.Init(JOB_RESTRICTED, L"job2", 0, 0)); | |
144 | |
145 Job job3; | |
146 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
147 job3.Init(JOB_LIMITED_USER, L"job3", 0, 0)); | |
148 | |
149 Job job4; | |
150 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
151 job4.Init(JOB_INTERACTIVE, L"job4", 0, 0)); | |
152 | |
153 Job job5; | |
154 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
155 job5.Init(JOB_UNPROTECTED, L"job5", 0, 0)); | |
156 | |
157 // JOB_NONE means we run without a job object so Init should fail. | |
158 Job job6; | |
159 ASSERT_EQ(static_cast<DWORD>(ERROR_BAD_ARGUMENTS), | |
160 job6.Init(JOB_NONE, L"job6", 0, 0)); | |
161 | |
162 Job job7; | |
163 ASSERT_EQ(static_cast<DWORD>(ERROR_BAD_ARGUMENTS), | |
164 job7.Init(static_cast<JobLevel>(JOB_NONE + 1), L"job7", 0, 0)); | |
165 } | |
166 | |
167 // Tests the method "AssignProcessToJob". | |
168 TEST(JobTest, ProcessInJob) { | |
169 // Create the job. | |
170 Job job; | |
171 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
172 job.Init(JOB_UNPROTECTED, L"job_test_process", 0, 0)); | |
173 | |
174 BOOL result = FALSE; | |
175 | |
176 wchar_t notepad[] = L"notepad"; | |
177 STARTUPINFO si = { sizeof(si) }; | |
178 PROCESS_INFORMATION temp_process_info = {}; | |
179 result = ::CreateProcess(NULL, notepad, NULL, NULL, FALSE, 0, NULL, NULL, &si, | |
180 &temp_process_info); | |
181 ASSERT_TRUE(result); | |
182 base::win::ScopedProcessInformation pi(temp_process_info); | |
183 ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | |
184 job.AssignProcessToJob(pi.process_handle())); | |
185 | |
186 // Get the job handle. | |
187 base::win::ScopedHandle job_handle = job.Take(); | |
188 | |
189 // Check if the process is in the job. | |
190 JOBOBJECT_BASIC_PROCESS_ID_LIST jbpidl = {0}; | |
191 DWORD size = sizeof(jbpidl); | |
192 result = ::QueryInformationJobObject(job_handle.Get(), | |
193 JobObjectBasicProcessIdList, | |
194 &jbpidl, size, &size); | |
195 EXPECT_TRUE(result); | |
196 | |
197 EXPECT_EQ(1u, jbpidl.NumberOfAssignedProcesses); | |
198 EXPECT_EQ(1u, jbpidl.NumberOfProcessIdsInList); | |
199 EXPECT_EQ(pi.process_id(), jbpidl.ProcessIdList[0]); | |
200 | |
201 EXPECT_TRUE(::TerminateProcess(pi.process_handle(), 0)); | |
202 } | |
203 | |
204 } // namespace sandbox | |
OLD | NEW |