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