1 // Copyright 2013 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 MOJO_CORE_TEST_MULTIPROCESS_TEST_HELPER_H_
6 #define MOJO_CORE_TEST_MULTIPROCESS_TEST_HELPER_H_
7 
8 #include <string>
9 
10 #include "base/callback.h"
11 #include "base/macros.h"
12 #include "base/process/process.h"
13 #include "base/test/multiprocess_test.h"
14 #include "base/test/test_timeouts.h"
15 #include "build/build_config.h"
16 #include "mojo/public/cpp/system/message_pipe.h"
17 #include "testing/multiprocess_func_list.h"
18 
19 namespace mojo {
20 
21 class IsolatedConnection;
22 
23 namespace core {
24 namespace test {
25 
26 class MultiprocessTestHelper {
27  public:
28   enum class LaunchType {
29     // Launch the child process as a child in the mojo system.
30     CHILD,
31 
32     // Launch the child process as an unrelated peer process in the mojo system.
33     PEER,
34 
35     // Same as CHILD but uses the newer async channel handshake.
36     ASYNC,
37 
38 #if !defined(OS_FUCHSIA)
39     // Launch the child process as a child in the mojo system, using a named
40     // pipe.
41     NAMED_CHILD,
42 
43     // Launch the child process as an unrelated peer process in the mojo
44     // system, using a named pipe.
45     NAMED_PEER,
46 #endif  //  !defined(OS_FUCHSIA)
47   };
48 
49   MultiprocessTestHelper();
50   ~MultiprocessTestHelper();
51 
52   // Start a child process and run the "main" function "named" |test_child_name|
53   // declared using |MOJO_MULTIPROCESS_TEST_CHILD_MAIN()| or
54   // |MOJO_MULTIPROCESS_TEST_CHILD_TEST()| (below).
55   ScopedMessagePipeHandle StartChild(
56       const std::string& test_child_name,
57       LaunchType launch_type = LaunchType::CHILD);
58 
59   // Like |StartChild()|, but appends an extra switch (with ASCII value) to the
60   // command line. (The switch must not already be present in the default
61   // command line.)
62   ScopedMessagePipeHandle StartChildWithExtraSwitch(
63       const std::string& test_child_name,
64       const std::string& switch_string,
65       const std::string& switch_value,
66       LaunchType launch_type);
67 
68   // Wait for the child process to terminate.
69   // Returns the exit code of the child process. Note that, though it's declared
70   // to be an |int|, the exit code is subject to mangling by the OS. E.g., we
71   // usually return -1 on error in the child (e.g., if |test_child_name| was not
72   // found), but this is mangled to 255 on Linux. You should only rely on codes
73   // 0-127 being preserved, and -1 being outside the range 0-127.
74   int WaitForChildShutdown();
75 
76   // Like |WaitForChildShutdown()|, but returns true on success (exit code of 0)
77   // and false otherwise. You probably want to do something like
78   // |EXPECT_TRUE(WaitForChildTestShutdown());|.
79   bool WaitForChildTestShutdown();
80 
test_child()81   const base::Process& test_child() const { return test_child_; }
82 
83   // Used by macros in mojo/core/test/mojo_test_base.h to support multiprocess
84   // test client initialization.
85   static void ChildSetup();
86   static int RunClientMain(base::OnceCallback<int(MojoHandle)> main,
87                            bool pass_pipe_ownership_to_main = false);
88   static int RunClientTestMain(base::OnceCallback<void(MojoHandle)> main);
89 
90   // For use (and only valid) in the child process:
91   static mojo::ScopedMessagePipeHandle primordial_pipe;
92 
93  private:
94   // Valid after |StartChild()| and before |WaitForChildShutdown()|.
95   base::Process test_child_;
96 
97   std::unique_ptr<IsolatedConnection> isolated_connection_;
98 
99   DISALLOW_COPY_AND_ASSIGN(MultiprocessTestHelper);
100 };
101 
102 }  // namespace test
103 }  // namespace core
104 }  // namespace mojo
105 
106 #endif  // MOJO_CORE_TEST_MULTIPROCESS_TEST_HELPER_H_
107