blob: 88275cfe773439a55944df3edcb67d7717ca9e4f [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstring>
#include <string>
#include "ipcz/ipcz.h"
#include "reference_drivers/single_process_reference_driver_base.h"
#include "reference_drivers/sync_reference_driver.h"
#include "test/test.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ipcz {
namespace {
const IpczDriver& kDefaultDriver = reference_drivers::kSyncReferenceDriver;
using APITest = test::Test;
TEST_F(APITest, CloseInvalid) {
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Close(IPCZ_INVALID_HANDLE, IPCZ_NO_FLAGS, nullptr));
}
TEST_F(APITest, CreateNodeInvalid) {
IpczHandle node;
// Null driver.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().CreateNode(nullptr, IPCZ_INVALID_DRIVER_HANDLE,
IPCZ_NO_FLAGS, nullptr, &node));
// Null output handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().CreateNode(&kDefaultDriver, IPCZ_INVALID_DRIVER_HANDLE,
IPCZ_NO_FLAGS, nullptr, nullptr));
}
TEST_F(APITest, CreateNode) {
IpczHandle node;
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().CreateNode(&kDefaultDriver, IPCZ_INVALID_DRIVER_HANDLE,
IPCZ_NO_FLAGS, nullptr, &node));
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().Close(node, IPCZ_NO_FLAGS, nullptr));
}
TEST_F(APITest, ConnectNodeInvalid) {
IpczHandle node = CreateNode(kDefaultDriver);
IpczDriverHandle transport0, transport1;
ASSERT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.CreateTransports(
IPCZ_INVALID_DRIVER_HANDLE, IPCZ_INVALID_DRIVER_HANDLE,
IPCZ_NO_FLAGS, nullptr, &transport0, &transport1));
IpczHandle portal;
// Invalid node handle
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().ConnectNode(IPCZ_INVALID_HANDLE, transport0, 1,
IPCZ_NO_FLAGS, nullptr, &portal));
// Non-node handle
auto [a, b] = OpenPortals(node);
EXPECT_EQ(
IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().ConnectNode(a, transport0, 1, IPCZ_NO_FLAGS, nullptr, &portal));
CloseAll({a, b});
// Invalid transport
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().ConnectNode(node, IPCZ_INVALID_DRIVER_HANDLE, 1,
IPCZ_NO_FLAGS, nullptr, &portal));
// No initial portals
EXPECT_EQ(
IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().ConnectNode(node, transport0, 0, IPCZ_NO_FLAGS, nullptr, &portal));
// Null portal storage
EXPECT_EQ(
IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().ConnectNode(node, transport0, 0, IPCZ_NO_FLAGS, nullptr, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.Close(transport0, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.Close(transport1, IPCZ_NO_FLAGS, nullptr));
Close(node);
}
TEST_F(APITest, OpenPortalsInvalid) {
IpczHandle node = CreateNode(kDefaultDriver);
IpczHandle a, b;
// Invalid node.
EXPECT_EQ(
IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().OpenPortals(IPCZ_INVALID_HANDLE, IPCZ_NO_FLAGS, nullptr, &a, &b));
// Invalid portal handle(s).
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().OpenPortals(node, IPCZ_NO_FLAGS, nullptr, nullptr, &b));
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().OpenPortals(node, IPCZ_NO_FLAGS, nullptr, &a, nullptr));
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().OpenPortals(node, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr));
Close(node);
}
TEST_F(APITest, OpenPortals) {
IpczHandle node = CreateNode(kDefaultDriver);
IpczHandle a, b;
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().OpenPortals(node, IPCZ_NO_FLAGS, nullptr, &a, &b));
CloseAll({a, b, node});
}
TEST_F(APITest, QueryPortalStatusInvalid) {
IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
// Null portal.
IpczPortalStatus status = {.size = sizeof(status)};
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().QueryPortalStatus(IPCZ_INVALID_HANDLE, IPCZ_NO_FLAGS,
nullptr, &status));
// Not a portal.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().QueryPortalStatus(node, IPCZ_NO_FLAGS, nullptr, &status));
// Null output status.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().QueryPortalStatus(a, IPCZ_NO_FLAGS, nullptr, nullptr));
// Invalid status size.
status.size = 0;
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().QueryPortalStatus(a, IPCZ_NO_FLAGS, nullptr, &status));
CloseAll({a, b, node});
}
TEST_F(APITest, QueryPortalStatus) {
IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
IpczPortalStatus status = {.size = sizeof(status)};
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().QueryPortalStatus(a, IPCZ_NO_FLAGS, nullptr, &status));
EXPECT_EQ(0u, status.flags & IPCZ_PORTAL_STATUS_PEER_CLOSED);
EXPECT_EQ(0u, status.flags & IPCZ_PORTAL_STATUS_DEAD);
EXPECT_EQ(0u, status.num_local_parcels);
EXPECT_EQ(0u, status.num_local_bytes);
EXPECT_EQ(0u, status.num_remote_parcels);
EXPECT_EQ(0u, status.num_remote_bytes);
Close(b);
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().QueryPortalStatus(a, IPCZ_NO_FLAGS, nullptr, &status));
EXPECT_EQ(IPCZ_PORTAL_STATUS_PEER_CLOSED,
status.flags & IPCZ_PORTAL_STATUS_PEER_CLOSED);
EXPECT_EQ(IPCZ_PORTAL_STATUS_DEAD, status.flags & IPCZ_PORTAL_STATUS_DEAD);
CloseAll({a, node});
}
TEST_F(APITest, MergePortalsFailure) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
// Invalid portal handles.
EXPECT_EQ(
IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().MergePortals(a, IPCZ_INVALID_HANDLE, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(
IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().MergePortals(IPCZ_INVALID_HANDLE, a, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().MergePortals(IPCZ_INVALID_HANDLE, IPCZ_INVALID_HANDLE,
IPCZ_NO_FLAGS, nullptr));
// Can't merge into own peer.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().MergePortals(a, b, IPCZ_NO_FLAGS, nullptr));
// Can't merge into self.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().MergePortals(a, a, IPCZ_NO_FLAGS, nullptr));
auto [c, d] = OpenPortals(node);
// Can't merge a portal that's had parcels put into it.
EXPECT_EQ(IPCZ_RESULT_OK, Put(c, "!"));
EXPECT_EQ(IPCZ_RESULT_FAILED_PRECONDITION,
ipcz().MergePortals(a, c, IPCZ_NO_FLAGS, nullptr));
// Can't merge a portal that's had parcels retrieved from it.
std::string message;
EXPECT_EQ(IPCZ_RESULT_OK, Get(d, &message));
EXPECT_EQ(IPCZ_RESULT_FAILED_PRECONDITION,
ipcz().MergePortals(a, d, IPCZ_NO_FLAGS, nullptr));
CloseAll({a, b, c, d, node});
}
TEST_F(APITest, MergePortals) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
auto [c, d] = OpenPortals(node);
EXPECT_EQ(IPCZ_RESULT_OK, Put(a, "!"));
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().MergePortals(b, c, IPCZ_NO_FLAGS, nullptr));
// The message from `a` should be routed to `d`, since `b` and `c` have been
// merged.
std::string message;
EXPECT_EQ(IPCZ_RESULT_OK, Get(d, &message));
EXPECT_EQ("!", message);
CloseAll({a, d, node});
}
TEST_F(APITest, PutGet) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
// Get from an empty portal.
char data[4];
size_t num_bytes = 4;
EXPECT_EQ(IPCZ_RESULT_UNAVAILABLE,
ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, data, &num_bytes, nullptr,
nullptr, nullptr));
// A portal can't transfer itself or its peer.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Put(a, nullptr, 0, &a, 1, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Put(a, nullptr, 0, &b, 1, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Put(a, "hi", 2, nullptr, 0, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Put(a, "bye", 3, nullptr, 0, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Put(a, nullptr, 0, nullptr, 0, IPCZ_NO_FLAGS, nullptr));
auto [c, d] = OpenPortals(node);
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Put(a, nullptr, 0, &d, 1, IPCZ_NO_FLAGS, nullptr));
d = IPCZ_INVALID_HANDLE;
IpczPortalStatus status = {.size = sizeof(status)};
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().QueryPortalStatus(b, IPCZ_NO_FLAGS, nullptr, &status));
EXPECT_EQ(4u, status.num_local_parcels);
EXPECT_EQ(5u, status.num_local_bytes);
// Insufficient data storage.
num_bytes = 0;
EXPECT_EQ(IPCZ_RESULT_RESOURCE_EXHAUSTED,
ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, data, &num_bytes, nullptr,
nullptr, nullptr));
EXPECT_EQ(2u, num_bytes);
num_bytes = 4;
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, data,
&num_bytes, nullptr, nullptr, nullptr));
EXPECT_EQ(2u, num_bytes);
EXPECT_EQ("hi", std::string(data, 2));
num_bytes = 4;
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, data,
&num_bytes, nullptr, nullptr, nullptr));
EXPECT_EQ(3u, num_bytes);
EXPECT_EQ("bye", std::string(data, 3));
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().QueryPortalStatus(b, IPCZ_NO_FLAGS, nullptr, &status));
EXPECT_EQ(2u, status.num_local_parcels);
EXPECT_EQ(0u, status.num_local_bytes);
// Getting an empty parcel requires no storage.
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().QueryPortalStatus(b, IPCZ_NO_FLAGS, nullptr, &status));
EXPECT_EQ(1u, status.num_local_parcels);
EXPECT_EQ(0u, status.num_local_bytes);
// Insufficient handle storage.
EXPECT_EQ(IPCZ_RESULT_RESOURCE_EXHAUSTED,
ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr));
size_t num_handles = 1;
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, nullptr,
nullptr, &d, &num_handles, nullptr));
EXPECT_EQ(1u, num_handles);
Close(d);
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().QueryPortalStatus(c, IPCZ_NO_FLAGS, nullptr, &status));
EXPECT_EQ(IPCZ_PORTAL_STATUS_PEER_CLOSED,
status.flags & IPCZ_PORTAL_STATUS_PEER_CLOSED);
EXPECT_EQ(IPCZ_PORTAL_STATUS_DEAD, status.flags & IPCZ_PORTAL_STATUS_DEAD);
CloseAll({a, b, c, node});
}
TEST_F(APITest, BeginEndPutFailure) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
// Invalid portal.
constexpr size_t kPutSize = 64;
size_t num_bytes = kPutSize;
void* data;
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().BeginPut(IPCZ_INVALID_HANDLE, IPCZ_NO_FLAGS, nullptr,
&num_bytes, &data));
// Non-zero size but null data.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, &num_bytes, nullptr));
// Invalid options.
IpczBeginPutOptions options = {.size = 0};
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().BeginPut(a, IPCZ_NO_FLAGS, &options, &num_bytes, &data));
// Duplicate two-phase Put.
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr));
EXPECT_EQ(IPCZ_RESULT_ALREADY_EXISTS,
ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr));
// Invalid portal.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().EndPut(IPCZ_INVALID_HANDLE, 0, nullptr, 0, IPCZ_NO_FLAGS,
nullptr));
// Non-zero number of handles, but null handle buffer.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().EndPut(a, 0, nullptr, 1, IPCZ_NO_FLAGS, nullptr));
// Oversized data.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().EndPut(a, kPutSize * 2, nullptr, 0, IPCZ_NO_FLAGS, nullptr));
// Invalid handle attachment.
IpczHandle invalid_handle = IPCZ_INVALID_HANDLE;
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().EndPut(a, 0, &invalid_handle, 1, IPCZ_NO_FLAGS, nullptr));
// Two-phase Put not in progress.
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().EndPut(a, 0, nullptr, 0, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(IPCZ_RESULT_FAILED_PRECONDITION,
ipcz().EndPut(a, 0, nullptr, 0, IPCZ_NO_FLAGS, nullptr));
CloseAll({a, b, node});
}
TEST_F(APITest, BeginEndGetFailure) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
// No parcel yet.
EXPECT_EQ(
IPCZ_RESULT_UNAVAILABLE,
ipcz().BeginGet(a, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr, nullptr));
constexpr std::string_view kMessage = "ipcz";
EXPECT_EQ(IPCZ_RESULT_OK, Put(b, kMessage));
// Invalid portal.
const void* data;
size_t num_bytes;
size_t num_handles;
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().BeginGet(IPCZ_INVALID_HANDLE, IPCZ_NO_FLAGS, nullptr, &data,
&num_bytes, &num_handles));
// No storage for data.
EXPECT_EQ(
IPCZ_RESULT_RESOURCE_EXHAUSTED,
ipcz().BeginGet(a, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr, nullptr));
EXPECT_EQ(
IPCZ_RESULT_RESOURCE_EXHAUSTED,
ipcz().BeginGet(a, IPCZ_NO_FLAGS, nullptr, &data, nullptr, nullptr));
EXPECT_EQ(
IPCZ_RESULT_RESOURCE_EXHAUSTED,
ipcz().BeginGet(a, IPCZ_NO_FLAGS, nullptr, nullptr, &num_bytes, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().BeginGet(a, IPCZ_NO_FLAGS, nullptr, &data,
&num_bytes, nullptr));
// Invalid handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().EndGet(IPCZ_INVALID_HANDLE, 0, 0, IPCZ_NO_FLAGS, nullptr,
nullptr, nullptr));
// Non-zero handle count with null handle buffer.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().EndGet(a, 0, 1, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr));
// Data size out of range.
EXPECT_EQ(IPCZ_RESULT_OUT_OF_RANGE,
ipcz().EndGet(a, num_bytes + 1, 0, IPCZ_NO_FLAGS, nullptr, nullptr,
nullptr));
// Two-phase Get not in progress.
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().EndGet(a, num_bytes, 0, IPCZ_NO_FLAGS,
nullptr, nullptr, nullptr));
EXPECT_EQ(
IPCZ_RESULT_FAILED_PRECONDITION,
ipcz().EndGet(a, num_bytes, 0, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr));
CloseAll({a, b, node});
}
TEST_F(APITest, TwoPhasePutGet) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
constexpr std::string_view kMessage = "ipcz!";
size_t num_bytes = kMessage.size();
void* out_data;
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, &num_bytes, &out_data));
EXPECT_EQ(kMessage.size(), num_bytes);
memcpy(out_data, kMessage.data(), kMessage.size());
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().EndPut(a, num_bytes, nullptr, 0, IPCZ_NO_FLAGS, nullptr));
const void* in_data;
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().BeginGet(b, IPCZ_NO_FLAGS, nullptr, &in_data,
&num_bytes, nullptr));
EXPECT_EQ(kMessage[0], *reinterpret_cast<const char*>(in_data));
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().EndGet(b, 1, 0, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().BeginGet(b, IPCZ_NO_FLAGS, nullptr, &in_data,
&num_bytes, nullptr));
EXPECT_EQ(
kMessage.substr(1),
std::string_view(reinterpret_cast<const char*>(in_data), num_bytes));
EXPECT_EQ(IPCZ_RESULT_OK, ipcz().EndGet(b, num_bytes, 0, IPCZ_NO_FLAGS,
nullptr, nullptr, nullptr));
EXPECT_EQ(
IPCZ_RESULT_UNAVAILABLE,
ipcz().BeginGet(b, IPCZ_NO_FLAGS, nullptr, nullptr, nullptr, nullptr));
CloseAll({a, b, node});
}
TEST_F(APITest, TrapInvalid) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
const auto handler = [](const IpczTrapEvent* event) {};
// Null conditions.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Trap(b, nullptr, handler, 0, IPCZ_NO_FLAGS, nullptr, nullptr,
nullptr));
// Invalid conditions.
IpczTrapConditions conditions = {.size = sizeof(conditions) - 1};
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Trap(b, &conditions, handler, 0, IPCZ_NO_FLAGS, nullptr,
nullptr, nullptr));
// Null handler.
conditions = {.size = sizeof(conditions)};
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Trap(b, &conditions, nullptr, 0, IPCZ_NO_FLAGS, nullptr,
nullptr, nullptr));
// Invalid or non-portal handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Trap(IPCZ_INVALID_HANDLE, &conditions, handler, 0,
IPCZ_NO_FLAGS, nullptr, nullptr, nullptr));
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Trap(node, &conditions, handler, 0, IPCZ_NO_FLAGS, nullptr,
nullptr, nullptr));
// Invalid non-null output status.
IpczPortalStatus status = {.size = sizeof(status) - 1};
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Trap(b, &conditions, handler, 0, IPCZ_NO_FLAGS, nullptr,
nullptr, &status));
CloseAll({a, b, node});
}
TEST_F(APITest, RejectInvalid) {
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Reject(IPCZ_INVALID_HANDLE, 0, IPCZ_NO_FLAGS, nullptr));
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Reject(a, 0, IPCZ_NO_FLAGS, nullptr));
CloseAll({a, b, node});
}
TEST_F(APITest, RejectLocal) {
const IpczHandle node = CreateNode(kDefaultDriver);
auto [a, b] = OpenPortals(node);
Put(a, "!");
char byte;
size_t num_bytes = 1;
IpczHandle validator;
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, &byte, &num_bytes, nullptr,
nullptr, &validator));
EXPECT_EQ('!', byte);
EXPECT_EQ(IPCZ_RESULT_FAILED_PRECONDITION,
ipcz().Reject(validator, 0, IPCZ_NO_FLAGS, nullptr));
CloseAll({a, b, node, validator});
}
TEST_F(APITest, RejectRemote) {
const IpczHandle node_a =
CreateNode(kDefaultDriver, IPCZ_CREATE_NODE_AS_BROKER);
const IpczHandle node_b = CreateNode(kDefaultDriver);
IpczDriverHandle transport0, transport1;
ASSERT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.CreateTransports(
IPCZ_INVALID_DRIVER_HANDLE, IPCZ_INVALID_DRIVER_HANDLE,
IPCZ_NO_FLAGS, nullptr, &transport0, &transport1));
IpczHandle a;
ASSERT_EQ(IPCZ_RESULT_OK, ipcz().ConnectNode(node_a, transport0, 1,
IPCZ_NO_FLAGS, nullptr, &a));
IpczHandle b;
ASSERT_EQ(IPCZ_RESULT_OK,
ipcz().ConnectNode(node_b, transport1, 1,
IPCZ_CONNECT_NODE_TO_BROKER, nullptr, &b));
Put(a, "!");
char byte;
size_t num_bytes = 1;
IpczHandle validator;
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Get(b, IPCZ_NO_FLAGS, nullptr, &byte, &num_bytes, nullptr,
nullptr, &validator));
EXPECT_EQ('!', byte);
constexpr uintptr_t kTestContext = 42;
IpczDriverHandle error_transport = IPCZ_INVALID_DRIVER_HANDLE;
uintptr_t error_context = 0;
reference_drivers::SetBadTransportActivityCallback(
[&](IpczDriverHandle transport, uintptr_t context) {
error_transport = transport;
error_context = context;
});
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Reject(validator, kTestContext, IPCZ_NO_FLAGS, nullptr));
EXPECT_EQ(transport1, error_transport);
EXPECT_EQ(kTestContext, error_context);
reference_drivers::SetBadTransportActivityCallback(nullptr);
CloseAll({a, b, node_b, node_a, validator});
}
TEST_F(APITest, BoxInvalid) {
IpczDriverHandle transport0, transport1;
ASSERT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.CreateTransports(
IPCZ_INVALID_DRIVER_HANDLE, IPCZ_INVALID_DRIVER_HANDLE,
IPCZ_NO_FLAGS, nullptr, &transport0, &transport1));
EXPECT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.Close(transport1, IPCZ_NO_FLAGS, nullptr));
IpczHandle node = CreateNode(kDefaultDriver);
IpczHandle box;
// Invalid node handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Box(IPCZ_INVALID_HANDLE, transport0, IPCZ_NO_FLAGS, nullptr,
&box));
// Invalid driver handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Box(node, IPCZ_INVALID_DRIVER_HANDLE, IPCZ_NO_FLAGS, nullptr,
&box));
// Null output handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Box(node, transport0, IPCZ_NO_FLAGS, nullptr, nullptr));
EXPECT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.Close(transport0, IPCZ_NO_FLAGS, nullptr));
Close(node);
}
TEST_F(APITest, UnboxInvalid) {
IpczDriverHandle transport0, transport1;
ASSERT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.CreateTransports(
IPCZ_INVALID_DRIVER_HANDLE, IPCZ_INVALID_DRIVER_HANDLE,
IPCZ_NO_FLAGS, nullptr, &transport0, &transport1));
EXPECT_EQ(IPCZ_RESULT_OK,
kDefaultDriver.Close(transport1, IPCZ_NO_FLAGS, nullptr));
IpczHandle node = CreateNode(kDefaultDriver);
IpczHandle box;
EXPECT_EQ(IPCZ_RESULT_OK,
ipcz().Box(node, transport0, IPCZ_NO_FLAGS, nullptr, &box));
IpczDriverHandle handle;
// Null box handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Unbox(IPCZ_INVALID_HANDLE, IPCZ_NO_FLAGS, nullptr, &handle));
// Invalid box handle type (node instead of box).
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Unbox(node, IPCZ_NO_FLAGS, nullptr, &handle));
// Null output handle.
EXPECT_EQ(IPCZ_RESULT_INVALID_ARGUMENT,
ipcz().Unbox(box, IPCZ_NO_FLAGS, nullptr, nullptr));
CloseAll({box, node});
}
} // namespace
} // namespace ipcz