Home | History | Annotate | Download | only in test
      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 #include "mojo/edk/test/multiprocess_test_helper.h"
      6 
      7 #include <stddef.h>
      8 
      9 #include <utility>
     10 
     11 #include "base/logging.h"
     12 #include "build/build_config.h"
     13 #include "mojo/edk/embedder/scoped_platform_handle.h"
     14 #include "mojo/edk/system/test_utils.h"
     15 #include "mojo/edk/test/test_utils.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 #if defined(OS_POSIX)
     19 #include <fcntl.h>
     20 #endif
     21 
     22 namespace mojo {
     23 namespace edk {
     24 namespace test {
     25 namespace {
     26 
     27 bool IsNonBlocking(const PlatformHandle& handle) {
     28 #if defined(OS_WIN)
     29   // Haven't figured out a way to query whether a HANDLE was created with
     30   // FILE_FLAG_OVERLAPPED.
     31   return true;
     32 #else
     33   return fcntl(handle.handle, F_GETFL) & O_NONBLOCK;
     34 #endif
     35 }
     36 
     37 bool WriteByte(const PlatformHandle& handle, char c) {
     38   size_t bytes_written = 0;
     39   BlockingWrite(handle, &c, 1, &bytes_written);
     40   return bytes_written == 1;
     41 }
     42 
     43 bool ReadByte(const PlatformHandle& handle, char* c) {
     44   size_t bytes_read = 0;
     45   BlockingRead(handle, c, 1, &bytes_read);
     46   return bytes_read == 1;
     47 }
     48 
     49 using MultiprocessTestHelperTest = testing::Test;
     50 
     51 TEST_F(MultiprocessTestHelperTest, RunChild) {
     52   MultiprocessTestHelper helper;
     53   EXPECT_TRUE(helper.server_platform_handle.is_valid());
     54 
     55   helper.StartChild("RunChild");
     56   EXPECT_EQ(123, helper.WaitForChildShutdown());
     57 }
     58 
     59 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) {
     60   CHECK(MultiprocessTestHelper::client_platform_handle.is_valid());
     61   return 123;
     62 }
     63 
     64 TEST_F(MultiprocessTestHelperTest, TestChildMainNotFound) {
     65   MultiprocessTestHelper helper;
     66   helper.StartChild("NoSuchTestChildMain");
     67   int result = helper.WaitForChildShutdown();
     68   EXPECT_FALSE(result >= 0 && result <= 127);
     69 }
     70 
     71 TEST_F(MultiprocessTestHelperTest, PassedChannel) {
     72   MultiprocessTestHelper helper;
     73   EXPECT_TRUE(helper.server_platform_handle.is_valid());
     74   helper.StartChild("PassedChannel");
     75 
     76   // Take ownership of the handle.
     77   ScopedPlatformHandle handle = std::move(helper.server_platform_handle);
     78 
     79   // The handle should be non-blocking.
     80   EXPECT_TRUE(IsNonBlocking(handle.get()));
     81 
     82   // Write a byte.
     83   const char c = 'X';
     84   EXPECT_TRUE(WriteByte(handle.get(), c));
     85 
     86   // It'll echo it back to us, incremented.
     87   char d = 0;
     88   EXPECT_TRUE(ReadByte(handle.get(), &d));
     89   EXPECT_EQ(c + 1, d);
     90 
     91   // And return it, incremented again.
     92   EXPECT_EQ(c + 2, helper.WaitForChildShutdown());
     93 }
     94 
     95 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel) {
     96   CHECK(MultiprocessTestHelper::client_platform_handle.is_valid());
     97 
     98   // Take ownership of the handle.
     99   ScopedPlatformHandle handle =
    100       std::move(MultiprocessTestHelper::client_platform_handle);
    101 
    102   // The handle should be non-blocking.
    103   EXPECT_TRUE(IsNonBlocking(handle.get()));
    104 
    105   // Read a byte.
    106   char c = 0;
    107   EXPECT_TRUE(ReadByte(handle.get(), &c));
    108 
    109   // Write it back, incremented.
    110   c++;
    111   EXPECT_TRUE(WriteByte(handle.get(), c));
    112 
    113   // And return it, incremented again.
    114   c++;
    115   return static_cast<int>(c);
    116 }
    117 
    118 TEST_F(MultiprocessTestHelperTest, ChildTestPasses) {
    119   MultiprocessTestHelper helper;
    120   EXPECT_TRUE(helper.server_platform_handle.is_valid());
    121   helper.StartChild("ChildTestPasses");
    122   EXPECT_TRUE(helper.WaitForChildTestShutdown());
    123 }
    124 
    125 MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestPasses) {
    126   ASSERT_TRUE(MultiprocessTestHelper::client_platform_handle.is_valid());
    127   EXPECT_TRUE(
    128       IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get()));
    129 }
    130 
    131 TEST_F(MultiprocessTestHelperTest, ChildTestFailsAssert) {
    132   MultiprocessTestHelper helper;
    133   EXPECT_TRUE(helper.server_platform_handle.is_valid());
    134   helper.StartChild("ChildTestFailsAssert");
    135   EXPECT_FALSE(helper.WaitForChildTestShutdown());
    136 }
    137 
    138 MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsAssert) {
    139   ASSERT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid())
    140       << "DISREGARD: Expected failure in child process";
    141   ASSERT_FALSE(
    142       IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get()))
    143       << "Not reached";
    144   CHECK(false) << "Not reached";
    145 }
    146 
    147 TEST_F(MultiprocessTestHelperTest, ChildTestFailsExpect) {
    148   MultiprocessTestHelper helper;
    149   EXPECT_TRUE(helper.server_platform_handle.is_valid());
    150   helper.StartChild("ChildTestFailsExpect");
    151   EXPECT_FALSE(helper.WaitForChildTestShutdown());
    152 }
    153 
    154 MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsExpect) {
    155   EXPECT_FALSE(MultiprocessTestHelper::client_platform_handle.is_valid())
    156       << "DISREGARD: Expected failure #1 in child process";
    157   EXPECT_FALSE(
    158       IsNonBlocking(MultiprocessTestHelper::client_platform_handle.get()))
    159       << "DISREGARD: Expected failure #2 in child process";
    160 }
    161 
    162 }  // namespace
    163 }  // namespace test
    164 }  // namespace edk
    165 }  // namespace mojo
    166