1 // Copyright (c) 2009 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 #ifndef BASE_MULTIPROCESS_TEST_H_ 6 #define BASE_MULTIPROCESS_TEST_H_ 7 8 #include "base/base_switches.h" 9 #include "base/command_line.h" 10 #include "base/process_util.h" 11 #include "base/string_util.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/multiprocess_func_list.h" 14 #include "testing/platform_test.h" 15 16 #if defined(OS_POSIX) 17 #include <sys/types.h> 18 #include <unistd.h> 19 #endif 20 21 // Command line switch to invoke a child process rather than 22 // to run the normal test suite. 23 static const char kRunClientProcess[] = "client"; 24 25 // A MultiProcessTest is a test class which makes it easier to 26 // write a test which requires code running out of process. 27 // 28 // To create a multiprocess test simply follow these steps: 29 // 30 // 1) Derive your test from MultiProcessTest. Example: 31 // 32 // class MyTest : public MultiProcessTest { 33 // }; 34 // 35 // TEST_F(MyTest, TestCaseName) { 36 // ... 37 // } 38 // 39 // 2) Create a mainline function for the child processes and include 40 // testing/multiprocess_func_list.h. 41 // See the declaration of the MULTIPROCESS_TEST_MAIN macro 42 // in that file for an example. 43 // 3) Call SpawnChild(L"foo"), where "foo" is the name of 44 // the function you wish to run in the child processes. 45 // That's it! 46 // 47 class MultiProcessTest : public PlatformTest { 48 protected: 49 // Run a child process. 50 // 'procname' is the name of a function which the child will 51 // execute. It must be exported from this library in order to 52 // run. 53 // 54 // Example signature: 55 // extern "C" int __declspec(dllexport) FooBar() { 56 // // do client work here 57 // } 58 // 59 // Returns the handle to the child, or NULL on failure 60 // 61 // TODO(darin): re-enable this once we have base/debug_util.h 62 // ProcessDebugFlags(&cl, DebugUtil::UNKNOWN, false); SpawnChild(const std::wstring & procname)63 base::ProcessHandle SpawnChild(const std::wstring& procname) { 64 return SpawnChild(procname, false); 65 } 66 SpawnChild(const std::wstring & procname,bool debug_on_start)67 base::ProcessHandle SpawnChild(const std::wstring& procname, 68 bool debug_on_start) { 69 #if defined(OS_WIN) 70 return SpawnChildImpl(procname, debug_on_start); 71 #elif defined(OS_POSIX) 72 base::file_handle_mapping_vector empty_file_list; 73 return SpawnChildImpl(procname, empty_file_list, debug_on_start); 74 #endif 75 } 76 77 #if defined(OS_POSIX) SpawnChild(const std::wstring & procname,const base::file_handle_mapping_vector & fds_to_map,bool debug_on_start)78 base::ProcessHandle SpawnChild( 79 const std::wstring& procname, 80 const base::file_handle_mapping_vector& fds_to_map, 81 bool debug_on_start) { 82 return SpawnChildImpl(procname, fds_to_map, debug_on_start); 83 } 84 #endif 85 86 protected: MakeCmdLine(const std::wstring & procname,bool debug_on_start)87 CommandLine MakeCmdLine(const std::wstring& procname, bool debug_on_start) { 88 CommandLine cl(*CommandLine::ForCurrentProcess()); 89 cl.AppendSwitchWithValue(kRunClientProcess, procname); 90 if (debug_on_start) 91 cl.AppendSwitch(switches::kDebugOnStart); 92 return cl; 93 } 94 95 private: 96 #if defined(OS_WIN) SpawnChildImpl(const std::wstring & procname,bool debug_on_start)97 base::ProcessHandle SpawnChildImpl(const std::wstring& procname, 98 bool debug_on_start) { 99 base::ProcessHandle handle = static_cast<base::ProcessHandle>(NULL); 100 base::LaunchApp(MakeCmdLine(procname, debug_on_start), 101 false, true, &handle); 102 return handle; 103 } 104 105 #elif defined(OS_POSIX) 106 // TODO(port): with the CommandLine refactoring, this code is very similar 107 // to the Windows code. Investigate whether this can be made shorter. 108 base::ProcessHandle SpawnChildImpl( 109 const std::wstring& procname, 110 const base::file_handle_mapping_vector& fds_to_map, 111 bool debug_on_start) { 112 base::ProcessHandle handle = base::kNullProcessHandle; 113 base::LaunchApp(MakeCmdLine(procname, debug_on_start).argv(), 114 fds_to_map, false, &handle); 115 return handle; 116 } 117 #endif 118 }; 119 120 #endif // BASE_MULTIPROCESS_TEST_H_ 121