Home | History | Annotate | Download | only in win
      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 #include <windows.h>
      6 
      7 #include <string>
      8 
      9 #include "base/command_line.h"
     10 #include "base/process/kill.h"
     11 #include "base/test/multiprocess_test.h"
     12 #include "base/win/scoped_process_information.h"
     13 #include "testing/multiprocess_func_list.h"
     14 
     15 namespace {
     16 
     17 const DWORD kProcessId = 4321;
     18 const DWORD kThreadId = 1234;
     19 const HANDLE kProcessHandle = reinterpret_cast<HANDLE>(7651);
     20 const HANDLE kThreadHandle = reinterpret_cast<HANDLE>(1567);
     21 
     22 void MockCreateProcess(base::win::ScopedProcessInformation* process_info) {
     23   PROCESS_INFORMATION process_information = {};
     24   process_information.dwProcessId = kProcessId;
     25   process_information.dwThreadId = kThreadId;
     26   process_information.hProcess = kProcessHandle;
     27   process_information.hThread = kThreadHandle;
     28   process_info->Set(process_information);
     29 }
     30 
     31 }  // namespace
     32 
     33 class ScopedProcessInformationTest : public base::MultiProcessTest {
     34  protected:
     35   void DoCreateProcess(const std::string& main_id,
     36                        PROCESS_INFORMATION* process_handle);
     37 };
     38 
     39 MULTIPROCESS_TEST_MAIN(ReturnSeven) {
     40   return 7;
     41 }
     42 
     43 MULTIPROCESS_TEST_MAIN(ReturnNine) {
     44   return 9;
     45 }
     46 
     47 void ScopedProcessInformationTest::DoCreateProcess(
     48     const std::string& main_id, PROCESS_INFORMATION* process_handle) {
     49   std::wstring cmd_line = MakeCmdLine(main_id).GetCommandLineString();
     50   STARTUPINFO startup_info = {};
     51   startup_info.cb = sizeof(startup_info);
     52 
     53   EXPECT_TRUE(::CreateProcess(NULL,
     54                               const_cast<wchar_t*>(cmd_line.c_str()),
     55                               NULL, NULL, false, 0, NULL, NULL,
     56                               &startup_info, process_handle));
     57 }
     58 
     59 TEST_F(ScopedProcessInformationTest, InitiallyInvalid) {
     60   base::win::ScopedProcessInformation process_info;
     61   ASSERT_FALSE(process_info.IsValid());
     62 }
     63 
     64 TEST_F(ScopedProcessInformationTest, Receive) {
     65   base::win::ScopedProcessInformation process_info;
     66   MockCreateProcess(&process_info);
     67 
     68   EXPECT_TRUE(process_info.IsValid());
     69   EXPECT_EQ(kProcessId, process_info.process_id());
     70   EXPECT_EQ(kThreadId, process_info.thread_id());
     71   EXPECT_EQ(kProcessHandle, process_info.process_handle());
     72   EXPECT_EQ(kThreadHandle, process_info.thread_handle());
     73   PROCESS_INFORMATION to_discard = process_info.Take();
     74 }
     75 
     76 TEST_F(ScopedProcessInformationTest, TakeProcess) {
     77   base::win::ScopedProcessInformation process_info;
     78   MockCreateProcess(&process_info);
     79 
     80   HANDLE process = process_info.TakeProcessHandle();
     81   EXPECT_EQ(kProcessHandle, process);
     82   EXPECT_EQ(NULL, process_info.process_handle());
     83   EXPECT_EQ(0, process_info.process_id());
     84   EXPECT_TRUE(process_info.IsValid());
     85   PROCESS_INFORMATION to_discard = process_info.Take();
     86 }
     87 
     88 TEST_F(ScopedProcessInformationTest, TakeThread) {
     89   base::win::ScopedProcessInformation process_info;
     90   MockCreateProcess(&process_info);
     91 
     92   HANDLE thread = process_info.TakeThreadHandle();
     93   EXPECT_EQ(kThreadHandle, thread);
     94   EXPECT_EQ(NULL, process_info.thread_handle());
     95   EXPECT_EQ(0, process_info.thread_id());
     96   EXPECT_TRUE(process_info.IsValid());
     97   PROCESS_INFORMATION to_discard = process_info.Take();
     98 }
     99 
    100 TEST_F(ScopedProcessInformationTest, TakeBoth) {
    101   base::win::ScopedProcessInformation process_info;
    102   MockCreateProcess(&process_info);
    103 
    104   HANDLE process = process_info.TakeProcessHandle();
    105   HANDLE thread = process_info.TakeThreadHandle();
    106   EXPECT_FALSE(process_info.IsValid());
    107   PROCESS_INFORMATION to_discard = process_info.Take();
    108 }
    109 
    110 TEST_F(ScopedProcessInformationTest, TakeWholeStruct) {
    111   base::win::ScopedProcessInformation process_info;
    112   MockCreateProcess(&process_info);
    113 
    114   PROCESS_INFORMATION to_discard = process_info.Take();
    115   EXPECT_EQ(kProcessId, to_discard.dwProcessId);
    116   EXPECT_EQ(kThreadId, to_discard.dwThreadId);
    117   EXPECT_EQ(kProcessHandle, to_discard.hProcess);
    118   EXPECT_EQ(kThreadHandle, to_discard.hThread);
    119   EXPECT_FALSE(process_info.IsValid());
    120 }
    121 
    122 TEST_F(ScopedProcessInformationTest, Duplicate) {
    123   PROCESS_INFORMATION temp_process_information;
    124   DoCreateProcess("ReturnSeven", &temp_process_information);
    125   base::win::ScopedProcessInformation process_info;
    126   process_info.Set(temp_process_information);
    127 
    128   base::win::ScopedProcessInformation duplicate;
    129   duplicate.DuplicateFrom(process_info);
    130 
    131   ASSERT_TRUE(process_info.IsValid());
    132   ASSERT_NE(0u, process_info.process_id());
    133   ASSERT_EQ(duplicate.process_id(), process_info.process_id());
    134   ASSERT_NE(0u, process_info.thread_id());
    135   ASSERT_EQ(duplicate.thread_id(), process_info.thread_id());
    136 
    137   // Validate that we have separate handles that are good.
    138   int exit_code = 0;
    139   ASSERT_TRUE(base::WaitForExitCode(process_info.TakeProcessHandle(),
    140                                     &exit_code));
    141   ASSERT_EQ(7, exit_code);
    142 
    143   exit_code = 0;
    144   ASSERT_TRUE(base::WaitForExitCode(duplicate.TakeProcessHandle(),
    145                                     &exit_code));
    146   ASSERT_EQ(7, exit_code);
    147 
    148   ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
    149   ASSERT_TRUE(::CloseHandle(duplicate.TakeThreadHandle()));
    150 }
    151 
    152 TEST_F(ScopedProcessInformationTest, Set) {
    153   base::win::ScopedProcessInformation base_process_info;
    154   MockCreateProcess(&base_process_info);
    155 
    156   PROCESS_INFORMATION base_struct = base_process_info.Take();
    157 
    158   base::win::ScopedProcessInformation process_info;
    159   process_info.Set(base_struct);
    160 
    161   EXPECT_EQ(kProcessId, process_info.process_id());
    162   EXPECT_EQ(kThreadId, process_info.thread_id());
    163   EXPECT_EQ(kProcessHandle, process_info.process_handle());
    164   EXPECT_EQ(kThreadHandle, process_info.thread_handle());
    165   base_struct = process_info.Take();
    166 }
    167