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