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