Index: mojo/public/platform/native/system_impl_private_unittest.cc |
diff --git a/mojo/public/platform/native/system_impl_private_unittest.cc b/mojo/public/platform/native/system_impl_private_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4d0e1bace6f68e51c90fff8f954bd696c2ef5107 |
--- /dev/null |
+++ b/mojo/public/platform/native/system_impl_private_unittest.cc |
@@ -0,0 +1,323 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// This file tests the C API, but using the explicit MojoSystemImpl parameter. |
+ |
+#include <string.h> |
+ |
+#include "mojo/public/c/system/core.h" |
+#include "mojo/public/platform/native/system_impl_private.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace mojo { |
+namespace { |
+ |
+const MojoHandleSignals kSignalReadadableWritable = |
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; |
+ |
+const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | |
+ MOJO_HANDLE_SIGNAL_WRITABLE | |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED; |
+ |
+TEST(SystemImplTest, GetTimeTicksNow) { |
+ MojoSystemImpl system = MojoSystemImplCreateImpl(); |
+ const MojoTimeTicks start = MojoSystemImplGetTimeTicksNow(system); |
+ EXPECT_NE(static_cast<MojoTimeTicks>(0), start) |
+ << "MojoGetTimeTicksNow should return nonzero value"; |
+ |
+ // SystemImpl is leaked... |
+} |
+ |
+TEST(SystemImplTest, BasicMessagePipe) { |
+ MojoSystemImpl sys0 = MojoSystemImplCreateImpl(); |
+ MojoSystemImpl sys1 = MojoSystemImplCreateImpl(); |
+ EXPECT_NE(sys0, sys1); |
+ |
+ MojoHandle h0, h1; |
+ MojoHandleSignals sig; |
+ char buffer[10] = {0}; |
+ uint32_t buffer_size; |
+ |
+ h0 = MOJO_HANDLE_INVALID; |
+ h1 = MOJO_HANDLE_INVALID; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplCreateMessagePipe(sys0, nullptr, &h0, &h1)); |
+ EXPECT_NE(h0, MOJO_HANDLE_INVALID); |
+ EXPECT_NE(h1, MOJO_HANDLE_INVALID); |
+ |
+ // Move the other end of the pipe to a different SystemImpl. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplTransferHandle(sys0, h1, sys1, &h1)); |
+ EXPECT_NE(h1, MOJO_HANDLE_INVALID); |
+ |
+ // Shouldn't be readable, we haven't written anything. |
+ MojoHandleSignalsState state; |
+ EXPECT_EQ( |
+ MOJO_RESULT_DEADLINE_EXCEEDED, |
+ MojoSystemImplWait(sys0, h0, MOJO_HANDLE_SIGNAL_READABLE, 0, &state)); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
+ EXPECT_EQ(kSignalAll, state.satisfiable_signals); |
+ |
+ // Should be writable. |
+ EXPECT_EQ( |
+ MOJO_RESULT_OK, |
+ MojoSystemImplWait(sys0, h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &state)); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
+ EXPECT_EQ(kSignalAll, state.satisfiable_signals); |
+ |
+ // Last parameter is optional. |
+ EXPECT_EQ( |
+ MOJO_RESULT_OK, |
+ MojoSystemImplWait(sys0, h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, nullptr)); |
+ |
+ // Try to read. |
+ buffer_size = static_cast<uint32_t>(sizeof(buffer)); |
+ EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
+ MojoSystemImplReadMessage(sys0, h0, buffer, &buffer_size, nullptr, |
+ nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); |
+ |
+ // Write to |h1|. |
+ static const char kHello[] = "hello"; |
+ buffer_size = static_cast<uint32_t>(sizeof(kHello)); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplWriteMessage(sys1, h1, kHello, buffer_size, nullptr, |
+ 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
+ |
+ // |h0| should be readable. |
+ uint32_t result_index = 1; |
+ MojoHandleSignalsState states[1]; |
+ sig = MOJO_HANDLE_SIGNAL_READABLE; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplWaitMany(sys0, &h0, &sig, 1, MOJO_DEADLINE_INDEFINITE, |
+ &result_index, states)); |
+ |
+ EXPECT_EQ(0u, result_index); |
+ EXPECT_EQ(kSignalReadadableWritable, states[0].satisfied_signals); |
+ EXPECT_EQ(kSignalAll, states[0].satisfiable_signals); |
+ |
+ // Read from |h0|. |
+ buffer_size = static_cast<uint32_t>(sizeof(buffer)); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplReadMessage(sys0, h0, buffer, &buffer_size, nullptr, |
+ nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); |
+ EXPECT_EQ(static_cast<uint32_t>(sizeof(kHello)), buffer_size); |
+ EXPECT_STREQ(kHello, buffer); |
+ |
+ // |h0| should no longer be readable. |
+ EXPECT_EQ( |
+ MOJO_RESULT_DEADLINE_EXCEEDED, |
+ MojoSystemImplWait(sys0, h0, MOJO_HANDLE_SIGNAL_READABLE, 10, &state)); |
+ |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
+ EXPECT_EQ(kSignalAll, state.satisfiable_signals); |
+ |
+ // Close |h0|. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplClose(sys0, h0)); |
+ |
+ // |h1| should no longer be readable or writable. |
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
+ MojoSystemImplWait(sys1, h1, MOJO_HANDLE_SIGNAL_READABLE | |
+ MOJO_HANDLE_SIGNAL_WRITABLE, |
+ 1000, &state)); |
+ |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); |
+ |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplClose(sys1, h1)); |
+ |
+ // 2 SystemImpls are leaked... |
+} |
+ |
+TEST(SystemImplTest, BasicDataPipe) { |
+ MojoSystemImpl sys0 = MojoSystemImplCreateImpl(); |
+ MojoSystemImpl sys1 = MojoSystemImplCreateImpl(); |
+ EXPECT_NE(sys0, sys1); |
+ |
+ MojoHandle hp, hc; |
+ MojoHandleSignals sig; |
+ char buffer[20] = {0}; |
+ uint32_t buffer_size; |
+ void* write_pointer; |
+ const void* read_pointer; |
+ |
+ hp = MOJO_HANDLE_INVALID; |
+ hc = MOJO_HANDLE_INVALID; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplCreateDataPipe(sys0, nullptr, &hp, &hc)); |
+ EXPECT_NE(hp, MOJO_HANDLE_INVALID); |
+ EXPECT_NE(hc, MOJO_HANDLE_INVALID); |
+ |
+ // Move the other end of the pipe to a different SystemImpl. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplTransferHandle(sys0, hc, sys1, &hc)); |
+ EXPECT_NE(hc, MOJO_HANDLE_INVALID); |
+ |
+ // The consumer |hc| shouldn't be readable. |
+ MojoHandleSignalsState state; |
+ EXPECT_EQ( |
+ MOJO_RESULT_DEADLINE_EXCEEDED, |
+ MojoSystemImplWait(sys1, hc, MOJO_HANDLE_SIGNAL_READABLE, 0, &state)); |
+ |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ state.satisfiable_signals); |
+ |
+ // The producer |hp| should be writable. |
+ EXPECT_EQ( |
+ MOJO_RESULT_OK, |
+ MojoSystemImplWait(sys0, hp, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &state)); |
+ |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ state.satisfiable_signals); |
+ |
+ // Try to read from |hc|. |
+ buffer_size = static_cast<uint32_t>(sizeof(buffer)); |
+ EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
+ MojoSystemImplReadData(sys1, hc, buffer, &buffer_size, |
+ MOJO_READ_DATA_FLAG_NONE)); |
+ |
+ // Try to begin a two-phase read from |hc|. |
+ read_pointer = nullptr; |
+ EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
+ MojoSystemImplBeginReadData(sys1, hc, &read_pointer, &buffer_size, |
+ MOJO_READ_DATA_FLAG_NONE)); |
+ |
+ // Write to |hp|. |
+ static const char kHello[] = "hello "; |
+ // Don't include terminating null. |
+ buffer_size = static_cast<uint32_t>(strlen(kHello)); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplWriteData(sys0, hp, kHello, &buffer_size, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE)); |
+ |
+ // |hc| should be(come) readable. |
+ uint32_t result_index = 1; |
+ MojoHandleSignalsState states[1]; |
+ sig = MOJO_HANDLE_SIGNAL_READABLE; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplWaitMany(sys1, &hc, &sig, 1, MOJO_DEADLINE_INDEFINITE, |
+ &result_index, states)); |
+ |
+ EXPECT_EQ(0u, result_index); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, states[0].satisfied_signals); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ states[0].satisfiable_signals); |
+ |
+ // Do a two-phase write to |hp|. |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplBeginWriteData(sys0, hp, &write_pointer, &buffer_size, |
+ MOJO_WRITE_DATA_FLAG_NONE)); |
+ static const char kWorld[] = "world"; |
+ ASSERT_GE(buffer_size, sizeof(kWorld)); |
+ // Include the terminating null. |
+ memcpy(write_pointer, kWorld, sizeof(kWorld)); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplEndWriteData(sys0, hp, |
+ static_cast<uint32_t>(sizeof(kWorld)))); |
+ |
+ // Read one character from |hc|. |
+ memset(buffer, 0, sizeof(buffer)); |
+ buffer_size = 1; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplReadData(sys1, hc, buffer, &buffer_size, |
+ MOJO_READ_DATA_FLAG_NONE)); |
+ |
+ // Close |hp|. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplClose(sys0, hp)); |
+ |
+ // |hc| should still be readable. |
+ EXPECT_EQ( |
+ MOJO_RESULT_OK, |
+ MojoSystemImplWait(sys1, hc, MOJO_HANDLE_SIGNAL_READABLE, 0, &state)); |
+ |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ state.satisfied_signals); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ state.satisfiable_signals); |
+ |
+ // Do a two-phase read from |hc|. |
+ read_pointer = nullptr; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplBeginReadData(sys1, hc, &read_pointer, &buffer_size, |
+ MOJO_READ_DATA_FLAG_NONE)); |
+ ASSERT_LE(buffer_size, sizeof(buffer) - 1); |
+ memcpy(&buffer[1], read_pointer, buffer_size); |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplEndReadData(sys1, hc, buffer_size)); |
+ EXPECT_STREQ("hello world", buffer); |
+ |
+ // |hc| should no longer be readable. |
+ EXPECT_EQ( |
+ MOJO_RESULT_FAILED_PRECONDITION, |
+ MojoSystemImplWait(sys1, hc, MOJO_HANDLE_SIGNAL_READABLE, 1000, &state)); |
+ |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); |
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); |
+ |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplClose(sys1, hc)); |
+ |
+ // TODO(vtl): Test the other way around -- closing the consumer should make |
+ // the producer never-writable? |
+ |
+ // 2 SystemImpls are leaked... |
+} |
+ |
+TEST(SystemImplTest, BasicSharedBuffer) { |
+ MojoSystemImpl sys0 = MojoSystemImplCreateImpl(); |
+ MojoSystemImpl sys1 = MojoSystemImplCreateImpl(); |
+ EXPECT_NE(sys0, sys1); |
+ |
+ MojoHandle h0, h1; |
+ void* pointer; |
+ |
+ // Create a shared buffer (|h0|). |
+ h0 = MOJO_HANDLE_INVALID; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplCreateSharedBuffer(sys0, nullptr, 100, &h0)); |
+ EXPECT_NE(h0, MOJO_HANDLE_INVALID); |
+ |
+ // Map everything. |
+ pointer = nullptr; |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplMapBuffer(sys0, h0, 0, 100, &pointer, |
+ MOJO_MAP_BUFFER_FLAG_NONE)); |
+ ASSERT_TRUE(pointer); |
+ static_cast<char*>(pointer)[50] = 'x'; |
+ |
+ // Duplicate |h0| to |h1|. |
+ h1 = MOJO_HANDLE_INVALID; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoSystemImplDuplicateBufferHandle(sys0, h0, nullptr, &h1)); |
+ EXPECT_NE(h1, MOJO_HANDLE_INVALID); |
+ |
+ // Move the other end of the pipe to a different SystemImpl. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplTransferHandle(sys0, h1, sys1, &h1)); |
+ EXPECT_NE(h1, MOJO_HANDLE_INVALID); |
+ |
+ // Close |h0|. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplClose(sys0, h0)); |
+ |
+ // The mapping should still be good. |
+ static_cast<char*>(pointer)[51] = 'y'; |
+ |
+ // Unmap it. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplUnmapBuffer(sys0, pointer)); |
+ |
+ // Map half of |h1|. |
+ pointer = nullptr; |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplMapBuffer(sys1, h1, 50, 50, &pointer, |
+ MOJO_MAP_BUFFER_FLAG_NONE)); |
+ ASSERT_TRUE(pointer); |
+ |
+ // It should have what we wrote. |
+ EXPECT_EQ('x', static_cast<char*>(pointer)[0]); |
+ EXPECT_EQ('y', static_cast<char*>(pointer)[1]); |
+ |
+ // Unmap it. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplUnmapBuffer(sys1, pointer)); |
+ |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoSystemImplClose(sys1, h1)); |
+ |
+ // 2 SystemImpls are leaked... |
+} |
+ |
+} // namespace |
+} // namespace mojo |