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