• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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