| 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 |