15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_TEST_MULTIPROCESS_TEST_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_TEST_MULTIPROCESS_TEST_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
1158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/launch.h"
1258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_handle.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace base {
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommandLine;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Helpers to spawn a child for a multiprocess test and execute a designated
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// function. Use these when you already have another base class for your test
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// fixture, but you want (some) of your tests to be multiprocess (otherwise you
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// may just want to derive your fixture from |MultiProcessTest|, below).
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use these helpers as follows:
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   TEST_F(MyTest, ATest) {
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     CommandLine command_line(
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//         base::GetMultiProcessTestChildBaseCommandLine());
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     // Maybe add our own switches to |command_line|....
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     LaunchOptions options;
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     // Maybe set some options (e.g., |start_hidden| on Windows)....
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     // Start a child process and run |a_test_func|.
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     base::ProcessHandle test_child_handle =
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//         base::SpawnMultiProcessTestChild("a_test_func", command_line,
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//                                          options);
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     // Do stuff involving |test_child_handle| and the child process....
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     int rv = -1;
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     ASSERT_TRUE(base::WaitForExitCodeWithTimeout(
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//         test_child_handle, &rv, TestTimeouts::action_timeout()));
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     base::CloseProcessHandle(test_child_handle);
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     EXPECT_EQ(0, rv);
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   }
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   // Note: |MULTIPROCESS_TEST_MAIN()| is defined in
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   // testing/multi_process_function_list.h.
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   MULTIPROCESS_TEST_MAIN(a_test_func) {
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     // Code here runs in a child process....
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//     return 0;
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//   }
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Spawns a child process and executes the function |procname| declared using
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |MULTIPROCESS_TEST_MAIN()| or |MULTIPROCESS_TEST_MAIN_WITH_SETUP()|.
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |command_line| should be as provided by
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |GetMultiProcessTestChildBaseCommandLine()| (below), possibly with arguments
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// added. Note: On Windows, you probably want to set |options.start_hidden|.
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ProcessHandle SpawnMultiProcessTestChild(
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& procname,
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const CommandLine& command_line,
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const LaunchOptions& options);
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Gets the base command line for |SpawnMultiProcessTestChild()|. To this, you
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// may add any flags needed for your child process.
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)CommandLine GetMultiProcessTestChildBaseCommandLine();
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// MultiProcessTest ------------------------------------------------------------
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A MultiProcessTest is a test class which makes it easier to
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// write a test which requires code running out of process.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To create a multiprocess test simply follow these steps:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1) Derive your test from MultiProcessTest. Example:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    class MyTest : public MultiProcessTest {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    };
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    TEST_F(MyTest, TestCaseName) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//      ...
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2) Create a mainline function for the child processes and include
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    testing/multiprocess_func_list.h.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    See the declaration of the MULTIPROCESS_TEST_MAIN macro
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    in that file for an example.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3) Call SpawnChild("foo"), where "foo" is the name of
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    the function you wish to run in the child processes.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// That's it!
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultiProcessTest : public PlatformTest {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiProcessTest();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run a child process.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'procname' is the name of a function which the child will
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // execute.  It must be exported from this library in order to
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // run.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Example signature:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    extern "C" int __declspec(dllexport) FooBar() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //         // do client work here
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the handle to the child, or NULL on failure
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProcessHandle SpawnChild(const std::string& procname);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Run a child process using the given launch options.
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  //
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Note: On Windows, you probably want to set |options.start_hidden|.
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ProcessHandle SpawnChildWithOptions(const std::string& procname,
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                      const LaunchOptions& options);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up the command line used to spawn the child process.
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Override this to add things to the command line (calling this first in the
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // override).
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Note that currently some tests rely on this providing a full command line,
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // which they then use directly with |LaunchProcess()|.
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(viettrungluu): Remove this and add a virtual
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |ModifyChildCommandLine()|; make the two divergent uses more sane.
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual CommandLine MakeCmdLine(const std::string& procname);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MultiProcessTest);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_TEST_MULTIPROCESS_TEST_H_
133