Home | History | Annotate | Download | only in test
      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 
     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>
     62   void RunTestClient(const std::string& client_name, HandlerFunc handler) {
     63     EXPECT_EQ(0, RunTestClientAndGetExitCode(client_name, handler));
     64   }
     65 
     66   template <typename HandlerFunc>
     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 
    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