• Home
  • 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/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 
17 namespace mojo {
18 namespace test {
19 namespace {
20 
IsNonBlocking(const embedder::PlatformHandle & handle)21 bool 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 
WriteByte(const embedder::PlatformHandle & handle,char c)31 bool 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 
ReadByte(const embedder::PlatformHandle & handle,char * c)37 bool 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 
43 typedef testing::Test MultiprocessTestHelperTest;
44 
TEST_F(MultiprocessTestHelperTest,RunChild)45 TEST_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 
MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild)53 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(RunChild) {
54   CHECK(MultiprocessTestHelper::client_platform_handle.is_valid());
55   return 123;
56 }
57 
TEST_F(MultiprocessTestHelperTest,TestChildMainNotFound)58 TEST_F(MultiprocessTestHelperTest, TestChildMainNotFound) {
59   MultiprocessTestHelper helper;
60   helper.StartChild("NoSuchTestChildMain");
61   int result = helper.WaitForChildShutdown();
62   EXPECT_FALSE(result >= 0 && result <= 127);
63 }
64 
TEST_F(MultiprocessTestHelperTest,PassedChannel)65 TEST_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 
MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PassedChannel)89 MOJO_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 
TEST_F(MultiprocessTestHelperTest,ChildTestPasses)112 TEST_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 
MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestPasses)119 MOJO_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 
TEST_F(MultiprocessTestHelperTest,ChildTestFailsAssert)125 TEST_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 
MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsAssert)132 MOJO_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 
TEST_F(MultiprocessTestHelperTest,ChildTestFailsExpect)140 TEST_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 
MOJO_MULTIPROCESS_TEST_CHILD_TEST(ChildTestFailsExpect)147 MOJO_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