• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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_MOJO_TEST_BASE_H_
6 #define MOJO_CORE_TEST_MOJO_TEST_BASE_H_
7 
8 #include <memory>
9 #include <string>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "build/build_config.h"
18 #include "mojo/core/test/multiprocess_test_helper.h"
19 #include "mojo/public/c/system/trap.h"
20 #include "mojo/public/c/system/types.h"
21 #include "mojo/public/cpp/system/message_pipe.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 
24 namespace mojo {
25 namespace core {
26 namespace test {
27 
28 class MojoTestBase : public testing::Test {
29  public:
30   MojoTestBase();
31   ~MojoTestBase() override;
32 
33   using LaunchType = MultiprocessTestHelper::LaunchType;
34   using HandlerCallback = base::Callback<void(ScopedMessagePipeHandle)>;
35 
36   class ClientController {
37    public:
38     ClientController(const std::string& client_name,
39                      MojoTestBase* test,
40                      LaunchType launch_type);
41     ~ClientController();
42 
pipe()43     MojoHandle pipe() const { return pipe_.get().value(); }
44 
45     int WaitForShutdown();
46 
47    private:
48     friend class MojoTestBase;
49 
50 #if !defined(OS_IOS)
51     MultiprocessTestHelper helper_;
52 #endif
53     ScopedMessagePipeHandle pipe_;
54     bool was_shutdown_ = false;
55 
56     DISALLOW_COPY_AND_ASSIGN(ClientController);
57   };
58 
59   ClientController& StartClient(const std::string& client_name);
60 
61   template <typename HandlerFunc>
RunTestClient(const std::string & client_name,HandlerFunc handler)62   void RunTestClient(const std::string& client_name, HandlerFunc handler) {
63     EXPECT_EQ(0, RunTestClientAndGetExitCode(client_name, handler));
64   }
65 
66   template <typename HandlerFunc>
RunTestClientAndGetExitCode(const std::string & client_name,HandlerFunc handler)67   int RunTestClientAndGetExitCode(const std::string& client_name,
68                                   HandlerFunc handler) {
69     ClientController& c = StartClient(client_name);
70     handler(c.pipe());
71     return c.WaitForShutdown();
72   }
73 
74   // Closes a handle and expects success.
75   static void CloseHandle(MojoHandle h);
76 
77   ////// Message pipe test utilities ///////
78 
79   // Creates a new pipe, returning endpoint handles in |p0| and |p1|.
80   static void CreateMessagePipe(MojoHandle* p0, MojoHandle* p1);
81 
82   // Writes a string to the pipe, transferring handles in the process.
83   static void WriteMessageWithHandles(MojoHandle mp,
84                                       const std::string& message,
85                                       const MojoHandle* handles,
86                                       uint32_t num_handles);
87 
88   // Writes a string to the pipe with no handles.
89   static void WriteMessage(MojoHandle mp, const std::string& message);
90 
91   // Reads a string from the pipe, expecting to read an exact number of handles
92   // in the process. Returns the read string.
93   static std::string ReadMessageWithHandles(MojoHandle mp,
94                                             MojoHandle* handles,
95                                             uint32_t expected_num_handles);
96 
97   // Reads a string from the pipe, expecting either zero or one handles.
98   // If no handle is read, |handle| will be reset.
99   static std::string ReadMessageWithOptionalHandle(MojoHandle mp,
100                                                    MojoHandle* handle);
101 
102   // Reads a string from the pipe, expecting to read no handles.
103   // Returns the string.
104   static std::string ReadMessage(MojoHandle mp);
105 
106   // Reads a string from the pipe, expecting to read no handles and exactly
107   // |num_bytes| bytes, which are read into |data|.
108   static void ReadMessage(MojoHandle mp, char* data, size_t num_bytes);
109 
110   // Writes |message| to |in| and expects to read it back from |out|.
111   static void VerifyTransmission(MojoHandle in,
112                                  MojoHandle out,
113                                  const std::string& message);
114 
115   // Writes |message| to |mp| and expects to read it back from the same handle.
116   static void VerifyEcho(MojoHandle mp, const std::string& message);
117 
118   //////// Shared buffer test utilities /////////
119 
120   // Creates a new shared buffer.
121   static MojoHandle CreateBuffer(uint64_t size);
122 
123   // Duplicates a shared buffer to a new handle.
124   static MojoHandle DuplicateBuffer(MojoHandle h, bool read_only);
125 
126   // Maps a buffer, writes some data into it, and unmaps it.
127   static void WriteToBuffer(MojoHandle h,
128                             size_t offset,
129                             const base::StringPiece& s);
130 
131   // Maps a buffer, tests the value of some of its contents, and unmaps it.
132   static void ExpectBufferContents(MojoHandle h,
133                                    size_t offset,
134                                    const base::StringPiece& s);
135 
136   //////// Data pipe test utilities /////////
137 
138   // Creates a new data pipe.
139   static void CreateDataPipe(MojoHandle* producer,
140                              MojoHandle* consumer,
141                              size_t capacity);
142 
143   // Writes data to a data pipe.
144   static void WriteData(MojoHandle producer, const std::string& data);
145 
146   // Reads data from a data pipe.
147   static std::string ReadData(MojoHandle consumer, size_t size);
148 
149   // Queries the signals state of |handle|.
150   static MojoHandleSignalsState GetSignalsState(MojoHandle handle);
151 
152   // Helper to block the calling thread waiting for signals to go high or low.
153   static MojoResult WaitForSignals(MojoHandle handle,
154                                    MojoHandleSignals signals,
155                                    MojoTriggerCondition condition,
156                                    MojoHandleSignalsState* state = nullptr);
157 
158   // Like above but only waits for signals to go high.
159   static MojoResult WaitForSignals(MojoHandle handle,
160                                    MojoHandleSignals signals,
161                                    MojoHandleSignalsState* state = nullptr);
162 
set_launch_type(LaunchType launch_type)163   void set_launch_type(LaunchType launch_type) { launch_type_ = launch_type; }
164 
165  private:
166   friend class ClientController;
167 
168   std::vector<std::unique_ptr<ClientController>> clients_;
169 
170   LaunchType launch_type_ = LaunchType::CHILD;
171 
172   DISALLOW_COPY_AND_ASSIGN(MojoTestBase);
173 };
174 
175 // Use this to declare the child process's "main()" function for tests using
176 // MojoTestBase and MultiprocessTestHelper. It returns an |int|, which will
177 // will be the process's exit code (but see the comment about
178 // WaitForChildShutdown()).
179 //
180 // The function is defined as a subclass of |test_base| to facilitate shared
181 // code between test clients and to allow clients to spawn children
182 // themselves.
183 //
184 // |pipe_name| will be bound to the MojoHandle of a message pipe connected
185 // to the test process (see RunTestClient* above.) This pipe handle is
186 // automatically closed on test client teardown.
187 #if !defined(OS_IOS)
188 #define DEFINE_TEST_CLIENT_WITH_PIPE(client_name, test_base, pipe_name) \
189   class client_name##_MainFixture : public test_base {                  \
190     void TestBody() override {}                                         \
191                                                                         \
192    public:                                                              \
193     int Main(MojoHandle);                                               \
194   };                                                                    \
195   MULTIPROCESS_TEST_MAIN_WITH_SETUP(                                    \
196       client_name##TestChildMain,                                       \
197       ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {         \
198     client_name##_MainFixture test;                                     \
199     return ::mojo::core::test::MultiprocessTestHelper::RunClientMain(   \
200         base::Bind(&client_name##_MainFixture::Main,                    \
201                    base::Unretained(&test)));                           \
202   }                                                                     \
203   int client_name##_MainFixture::Main(MojoHandle pipe_name)
204 
205 // This is a version of DEFINE_TEST_CLIENT_WITH_PIPE which can be used with
206 // gtest ASSERT/EXPECT macros.
207 #define DEFINE_TEST_CLIENT_TEST_WITH_PIPE(client_name, test_base, pipe_name) \
208   class client_name##_MainFixture : public test_base {                       \
209     void TestBody() override {}                                              \
210                                                                              \
211    public:                                                                   \
212     void Main(MojoHandle);                                                   \
213   };                                                                         \
214   MULTIPROCESS_TEST_MAIN_WITH_SETUP(                                         \
215       client_name##TestChildMain,                                            \
216       ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {              \
217     client_name##_MainFixture test;                                          \
218     return ::mojo::core::test::MultiprocessTestHelper::RunClientTestMain(    \
219         base::Bind(&client_name##_MainFixture::Main,                         \
220                    base::Unretained(&test)));                                \
221   }                                                                          \
222   void client_name##_MainFixture::Main(MojoHandle pipe_name)
223 #else  // !defined(OS_IOS)
224 #define DEFINE_TEST_CLIENT_WITH_PIPE(client_name, test_base, pipe_name)
225 #define DEFINE_TEST_CLIENT_TEST_WITH_PIPE(client_name, test_base, pipe_name)
226 #endif  // !defined(OS_IOS)
227 
228 }  // namespace test
229 }  // namespace core
230 }  // namespace mojo
231 
232 #endif  // MOJO_CORE_TEST_MOJO_TEST_BASE_H_
233