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