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#ifndef BASE_TEST_MULTIPROCESS_TEST_H_
6#define BASE_TEST_MULTIPROCESS_TEST_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/process/launch.h"
12#include "base/process/process_handle.h"
13#include "build/build_config.h"
14#include "testing/platform_test.h"
15
16namespace base {
17
18class CommandLine;
19
20// Helpers to spawn a child for a multiprocess test and execute a designated
21// function. Use these when you already have another base class for your test
22// fixture, but you want (some) of your tests to be multiprocess (otherwise you
23// may just want to derive your fixture from |MultiProcessTest|, below).
24//
25// Use these helpers as follows:
26//
27//   TEST_F(MyTest, ATest) {
28//     CommandLine command_line(
29//         base::GetMultiProcessTestChildBaseCommandLine());
30//     // Maybe add our own switches to |command_line|....
31//
32//     LaunchOptions options;
33//     // Maybe set some options (e.g., |start_hidden| on Windows)....
34//
35//     // Start a child process and run |a_test_func|.
36//     base::ProcessHandle test_child_handle =
37//         base::SpawnMultiProcessTestChild("a_test_func", command_line,
38//                                          options);
39//
40//     // Do stuff involving |test_child_handle| and the child process....
41//
42//     int rv = -1;
43//     ASSERT_TRUE(base::WaitForExitCodeWithTimeout(
44//         test_child_handle, &rv, TestTimeouts::action_timeout()));
45//     base::CloseProcessHandle(test_child_handle);
46//     EXPECT_EQ(0, rv);
47//   }
48//
49//   // Note: |MULTIPROCESS_TEST_MAIN()| is defined in
50//   // testing/multi_process_function_list.h.
51//   MULTIPROCESS_TEST_MAIN(a_test_func) {
52//     // Code here runs in a child process....
53//     return 0;
54//   }
55
56// Spawns a child process and executes the function |procname| declared using
57// |MULTIPROCESS_TEST_MAIN()| or |MULTIPROCESS_TEST_MAIN_WITH_SETUP()|.
58// |command_line| should be as provided by
59// |GetMultiProcessTestChildBaseCommandLine()| (below), possibly with arguments
60// added. Note: On Windows, you probably want to set |options.start_hidden|.
61ProcessHandle SpawnMultiProcessTestChild(
62    const std::string& procname,
63    const CommandLine& command_line,
64    const LaunchOptions& options);
65
66// Gets the base command line for |SpawnMultiProcessTestChild()|. To this, you
67// may add any flags needed for your child process.
68CommandLine GetMultiProcessTestChildBaseCommandLine();
69
70// MultiProcessTest ------------------------------------------------------------
71
72// A MultiProcessTest is a test class which makes it easier to
73// write a test which requires code running out of process.
74//
75// To create a multiprocess test simply follow these steps:
76//
77// 1) Derive your test from MultiProcessTest. Example:
78//
79//    class MyTest : public MultiProcessTest {
80//    };
81//
82//    TEST_F(MyTest, TestCaseName) {
83//      ...
84//    }
85//
86// 2) Create a mainline function for the child processes and include
87//    testing/multiprocess_func_list.h.
88//    See the declaration of the MULTIPROCESS_TEST_MAIN macro
89//    in that file for an example.
90// 3) Call SpawnChild("foo"), where "foo" is the name of
91//    the function you wish to run in the child processes.
92// That's it!
93class MultiProcessTest : public PlatformTest {
94 public:
95  MultiProcessTest();
96
97 protected:
98  // Run a child process.
99  // 'procname' is the name of a function which the child will
100  // execute.  It must be exported from this library in order to
101  // run.
102  //
103  // Example signature:
104  //    extern "C" int __declspec(dllexport) FooBar() {
105  //         // do client work here
106  //    }
107  //
108  // Returns the handle to the child, or NULL on failure
109  ProcessHandle SpawnChild(const std::string& procname);
110
111  // Run a child process using the given launch options.
112  //
113  // Note: On Windows, you probably want to set |options.start_hidden|.
114  ProcessHandle SpawnChildWithOptions(const std::string& procname,
115                                      const LaunchOptions& options);
116
117  // Set up the command line used to spawn the child process.
118  // Override this to add things to the command line (calling this first in the
119  // override).
120  // Note that currently some tests rely on this providing a full command line,
121  // which they then use directly with |LaunchProcess()|.
122  // TODO(viettrungluu): Remove this and add a virtual
123  // |ModifyChildCommandLine()|; make the two divergent uses more sane.
124  virtual CommandLine MakeCmdLine(const std::string& procname);
125
126 private:
127  DISALLOW_COPY_AND_ASSIGN(MultiProcessTest);
128};
129
130}  // namespace base
131
132#endif  // BASE_TEST_MULTIPROCESS_TEST_H_
133