• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IsNonBlocking(const PlatformHandle & handle)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 
WriteByte(const PlatformHandle & handle,char c)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 
ReadByte(const PlatformHandle & handle,char * c)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 
TEST_F(MultiprocessTestHelperTest,RunChild)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 
MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild)59 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) {
60   CHECK(MultiprocessTestHelper::client_platform_handle.is_valid());
61   return 123;
62 }
63 
TEST_F(MultiprocessTestHelperTest,TestChildMainNotFound)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 
TEST_F(MultiprocessTestHelperTest,PassedChannel)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 
MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel)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 
TEST_F(MultiprocessTestHelperTest,ChildTestPasses)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 
MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestPasses)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 
TEST_F(MultiprocessTestHelperTest,ChildTestFailsAssert)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 
MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsAssert)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 
TEST_F(MultiprocessTestHelperTest,ChildTestFailsExpect)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 
MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsExpect)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