15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains unit tests for the job object. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_process_information.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/job.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the creation and destruction of the job. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(JobTest, TestCreation) { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scope the creation of Job. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the job. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job; 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // check if the job exists. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"my_test_job_name"); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job_handle != NULL); 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job_handle) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(job_handle); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the job is destroyed when the object goes out of scope. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job_handle == NULL); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError()); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the method "Detach". 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(JobTest, TestDetach) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE job_handle; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scope the creation of Job. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the job. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job; 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_handle = job.Detach(); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job_handle != NULL); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to be sure that the job is still alive even after the object is gone 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // out of scope. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE job_handle_dup = ::OpenJobObjectW(GENERIC_ALL, FALSE, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"my_test_job_name"); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job_handle_dup != NULL); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove all references. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job_handle_dup) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(job_handle_dup); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (job_handle) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(job_handle); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the jbo is really dead. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_handle = ::OpenJobObjectW(GENERIC_ALL, FALSE, L"my_test_job_name"); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job_handle == NULL); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERROR_FILE_NOT_FOUND, ::GetLastError()); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the ui exceptions 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(JobTest, TestExceptions) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE job_handle; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scope the creation of Job. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the job. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) JOB_OBJECT_UILIMIT_READCLIPBOARD, 0)); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_handle = job.Detach(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job_handle != NULL); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = sizeof(jbur); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL result = ::QueryInformationJobObject(job_handle, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JobObjectBasicUIRestrictions, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &jbur, size, &size); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(result); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD, 0); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(job_handle); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scope the creation of Job. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the job. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job; 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_handle = job.Detach(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job_handle != NULL); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0}; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = sizeof(jbur); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL result = ::QueryInformationJobObject(job_handle, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JobObjectBasicUIRestrictions, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &jbur, size, &size); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(result); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(jbur.UIRestrictionsClass & JOB_OBJECT_UILIMIT_READCLIPBOARD, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JOB_OBJECT_UILIMIT_READCLIPBOARD); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(job_handle); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the error case when the job is initialized twice. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(JobTest, DoubleInit) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the job. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job; 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_LOCKDOWN, L"my_test_job_name", 0, 0)); 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_ALREADY_INITIALIZED, job.Init(JOB_LOCKDOWN, L"test", 0, 0)); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the error case when we use a method and the object is not yet 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialized. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(JobTest, NoInit) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERROR_NO_DATA, job.UserHandleGrantAccess(NULL)); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERROR_NO_DATA, job.AssignProcessToJob(NULL)); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(job.Detach() == NULL); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the initialization of the job with different security level. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(JobTest, SecurityLevel) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job1; 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job1.Init(JOB_LOCKDOWN, L"job1", 0, 0)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job2; 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job2.Init(JOB_RESTRICTED, L"job2", 0, 0)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job3; 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job3.Init(JOB_LIMITED_USER, L"job3", 0, 0)); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job4; 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job4.Init(JOB_INTERACTIVE, L"job4", 0, 0)); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job5; 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job5.Init(JOB_UNPROTECTED, L"job5", 0, 0)); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JOB_NONE means we run without a job object so Init should fail. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job6; 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_BAD_ARGUMENTS, job6.Init(JOB_NONE, L"job6", 0, 0)); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job7; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERROR_BAD_ARGUMENTS, job7.Init( 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static_cast<JobLevel>(JOB_NONE+1), L"job7", 0, 0)); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests the method "AssignProcessToJob". 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(JobTest, ProcessInJob) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the job. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Job job; 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job.Init(JOB_UNPROTECTED, L"job_test_process", 0, 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 0)); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL result = FALSE; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t notepad[] = L"notepad"; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STARTUPINFO si = { sizeof(si) }; 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PROCESS_INFORMATION temp_process_info = {}; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = ::CreateProcess(NULL, notepad, NULL, NULL, FALSE, 0, NULL, NULL, &si, 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &temp_process_info); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(result); 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::win::ScopedProcessInformation pi(temp_process_info); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(ERROR_SUCCESS, job.AssignProcessToJob(pi.process_handle())); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the job handle. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE job_handle = job.Detach(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the process is in the job. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JOBOBJECT_BASIC_PROCESS_ID_LIST jbpidl = {0}; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = sizeof(jbpidl); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = ::QueryInformationJobObject(job_handle, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JobObjectBasicProcessIdList, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &jbpidl, size, &size); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(result); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, jbpidl.NumberOfAssignedProcesses); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, jbpidl.NumberOfProcessIdsInList); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(pi.process_id(), jbpidl.ProcessIdList[0]); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(::TerminateProcess(pi.process_handle(), 0)); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(::CloseHandle(job_handle)); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace sandbox 196