blob: c635a5ab49ff6798e6f91e33b8f57707937b4b13 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <assert.h>
#include <zircon/syscalls.h>
#include <unittest/unittest.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static zx_signals_t get_satisfied_signals(zx_handle_t handle) {
zx_signals_t pending = 0;
zx_object_wait_one(handle, 0u, 0u, &pending);
return pending;
}
static bool socket_basic(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_handle_t h[2];
uint32_t read_data[] = { 0, 0 };
status = zx_socket_create(0, h, h + 1);
ASSERT_EQ(status, ZX_OK, "");
status = zx_socket_read(h[0], 0u, read_data, sizeof(read_data), &count);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
static const uint32_t write_data[] = { 0xdeadbeef, 0xc0ffee };
status = zx_socket_write(h[0], 0u, &write_data[0], sizeof(write_data[0]), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(write_data[0]), "");
status = zx_socket_write(h[0], 0u, &write_data[1], sizeof(write_data[1]), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(write_data[1]), "");
status = zx_socket_read(h[1], 0u, read_data, sizeof(read_data), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(read_data), "");
EXPECT_EQ(read_data[0], write_data[0], "");
EXPECT_EQ(read_data[1], write_data[1], "");
status = zx_socket_write(h[0], 0u, write_data, sizeof(write_data), NULL);
EXPECT_EQ(status, ZX_OK, "");
memset(read_data, 0, sizeof(read_data));
status = zx_socket_read(h[1], 0u, read_data, sizeof(read_data), NULL);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(read_data[0], write_data[0], "");
EXPECT_EQ(read_data[1], write_data[1], "");
zx_handle_close(h[1]);
status = zx_socket_write(h[0], 0u, &write_data[1], sizeof(write_data[1]), &count);
EXPECT_EQ(status, ZX_ERR_PEER_CLOSED, "");
zx_handle_close(h[0]);
END_TEST;
}
static bool socket_signals(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_handle_t h0, h1;
status = zx_socket_create(0, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
zx_signals_t signals0 = get_satisfied_signals(h0);
zx_signals_t signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
const size_t kAllSize = 128 * 1024;
char* big_buf = (char*) malloc(kAllSize);
ASSERT_NONNULL(big_buf, "");
memset(big_buf, 0x66, kAllSize);
status = zx_socket_write(h0, 0u, big_buf, kAllSize / 16, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, kAllSize / 16, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_READABLE | ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_read(h1, 0u, big_buf, kAllSize, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, kAllSize / 16, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_object_signal_peer(h0, ZX_SOCKET_WRITABLE, 0u);
EXPECT_EQ(status, ZX_ERR_INVALID_ARGS, "");
status = zx_object_signal_peer(h0, 0u, ZX_USER_SIGNAL_1);
EXPECT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_USER_SIGNAL_1 | ZX_SIGNAL_LAST_HANDLE, "");
zx_handle_close(h1);
signals0 = get_satisfied_signals(h0);
EXPECT_EQ(signals0, ZX_SOCKET_PEER_CLOSED | ZX_SIGNAL_LAST_HANDLE, "");
zx_handle_close(h0);
free(big_buf);
END_TEST;
}
static bool socket_shutdown_write(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_signals_t signals0, signals1;
zx_handle_t h0, h1;
status = zx_socket_create(0, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "12345", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
status = zx_socket_write(h1, ZX_SOCKET_SHUTDOWN_WRITE, NULL, 0u, NULL);
EXPECT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0,
ZX_SOCKET_WRITABLE | ZX_SOCKET_READABLE | ZX_SIGNAL_LAST_HANDLE,
"");
EXPECT_EQ(signals1, ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h0, 0u, "abcde", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals1, ZX_SOCKET_READABLE | ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "fghij", 5u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
char rbuf[10] = {0};
status = zx_socket_read(h0, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "12345", 5), 0, "");
status = zx_socket_read(h0, 0u, rbuf, 1u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
signals0 = get_satisfied_signals(h0);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_READ_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_read(h1, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "abcde", 5), 0, "");
zx_handle_close(h0);
// Calling shutdown after the peer is closed is completely valid.
status = zx_socket_write(h1, ZX_SOCKET_SHUTDOWN_READ, NULL, 0u, NULL);
EXPECT_EQ(status, ZX_OK, "");
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals1, ZX_SOCKET_READ_DISABLED | ZX_SOCKET_WRITE_DISABLED | ZX_SOCKET_PEER_CLOSED | ZX_SIGNAL_LAST_HANDLE, "");
zx_handle_close(h1);
END_TEST;
}
static bool socket_shutdown_read(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_signals_t signals0, signals1;
zx_handle_t h0, h1;
status = zx_socket_create(0, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "12345", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
status = zx_socket_write(h0, ZX_SOCKET_SHUTDOWN_READ, NULL, 0u, NULL);
EXPECT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_READABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h0, 0u, "abcde", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals1, ZX_SOCKET_READABLE | ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "fghij", 5u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
char rbuf[10] = {0};
status = zx_socket_read(h0, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "12345", 5), 0, "");
status = zx_socket_read(h0, 0u, rbuf, 1u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
signals0 = get_satisfied_signals(h0);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_READ_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_read(h1, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "abcde", 5), 0, "");
zx_handle_close(h0);
zx_handle_close(h1);
END_TEST;
}
static bool socket_bytes_outstanding(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_handle_t h[2];
uint32_t read_data[] = { 0, 0 };
status = zx_socket_create(0, h, h + 1);
ASSERT_EQ(status, ZX_OK, "");
status = zx_socket_read(h[0], 0u, read_data, sizeof(read_data), &count);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
static const uint32_t write_data[] = { 0xdeadbeef, 0xc0ffee };
status = zx_socket_write(h[0], 0u, &write_data[0], sizeof(write_data[0]), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(write_data[0]), "");
status = zx_socket_write(h[0], 0u, &write_data[1], sizeof(write_data[1]), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(write_data[1]), "");
// Check the number of bytes outstanding.
size_t outstanding = 0u;
status = zx_socket_read(h[1], 0u, NULL, 0, &outstanding);
EXPECT_EQ(outstanding, sizeof(write_data), "");
// Check that the prior zx_socket_read call didn't disturb the pending data.
status = zx_socket_read(h[1], 0u, read_data, sizeof(read_data), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(read_data), "");
EXPECT_EQ(read_data[0], write_data[0], "");
EXPECT_EQ(read_data[1], write_data[1], "");
zx_handle_close(h[1]);
status = zx_socket_write(h[0], 0u, &write_data[1], sizeof(write_data[1]), &count);
EXPECT_EQ(status, ZX_ERR_PEER_CLOSED, "");
zx_handle_close(h[0]);
END_TEST;
}
static bool socket_bytes_outstanding_shutdown_write(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_signals_t signals0, signals1;
zx_handle_t h0, h1;
status = zx_socket_create(0, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "12345", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
status = zx_socket_write(h1, ZX_SOCKET_SHUTDOWN_WRITE, NULL, 0u, NULL);
EXPECT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0,
ZX_SOCKET_WRITABLE | ZX_SOCKET_READABLE | ZX_SIGNAL_LAST_HANDLE,
"");
EXPECT_EQ(signals1, ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h0, 0u, "abcde", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals1, ZX_SOCKET_READABLE | ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "fghij", 5u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
char rbuf[10] = {0};
status = zx_socket_read(h0, 0u, NULL, 0, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
count = 0;
status = zx_socket_read(h0, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "12345", 5), 0, "");
status = zx_socket_read(h0, 0u, rbuf, 1u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
signals0 = get_satisfied_signals(h0);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_READ_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_read(h1, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "abcde", 5), 0, "");
zx_handle_close(h0);
zx_handle_close(h1);
END_TEST;
}
static bool socket_bytes_outstanding_shutdown_read(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_signals_t signals0, signals1;
zx_handle_t h0, h1;
status = zx_socket_create(0, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "12345", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
status = zx_socket_write(h0, ZX_SOCKET_SHUTDOWN_READ, NULL, 0u, NULL);
EXPECT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_READABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h0, 0u, "abcde", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals1, ZX_SOCKET_READABLE | ZX_SOCKET_WRITE_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "fghij", 5u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
char rbuf[10] = {0};
status = zx_socket_read(h0, 0u, NULL, 0, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
count = 0;
status = zx_socket_read(h0, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "12345", 5), 0, "");
status = zx_socket_read(h0, 0u, rbuf, 1u, &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
signals0 = get_satisfied_signals(h0);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_READ_DISABLED | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_read(h1, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "abcde", 5), 0, "");
zx_handle_close(h0);
zx_handle_close(h1);
END_TEST;
}
static bool socket_short_write(void) {
BEGIN_TEST;
zx_status_t status;
zx_handle_t h0, h1;
status = zx_socket_create(0, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
// TODO(qsr): Request socket buffer and use (socket_buffer + 1).
const size_t buffer_size = 256 * 1024 + 1;
char* buffer = malloc(buffer_size);
size_t written = ~(size_t)0; // This should get overwritten by the syscall.
status = zx_socket_write(h0, 0u, buffer, buffer_size, &written);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_LT(written, buffer_size, "");
free(buffer);
zx_handle_close(h0);
zx_handle_close(h1);
END_TEST;
}
static bool socket_datagram(void) {
BEGIN_TEST;
size_t count;
zx_status_t status;
zx_handle_t h0, h1;
unsigned char rbuf[4096] = {0}; // bigger than an mbuf
status = zx_socket_create(ZX_SOCKET_DATAGRAM, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
status = zx_socket_write(h0, 0u, "packet1", 8u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 8u, "");
status = zx_socket_write(h0, 0u, "pkt2", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
rbuf[0] = 'a';
rbuf[1000] = 'b';
rbuf[2000] = 'c';
rbuf[3000] = 'd';
rbuf[4000] = 'e';
rbuf[4095] = 'f';
status = zx_socket_write(h0, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(rbuf), "");
status = zx_socket_read(h1, 0u, NULL, 0, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(rbuf) + 8u + 5u, "");
count = 0;
bzero(rbuf, sizeof(rbuf));
status = zx_socket_read(h1, 0u, rbuf, 3, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 3u, "");
EXPECT_EQ(memcmp(rbuf, "pac", 4), 0, ""); // short read "packet1"
count = 0;
status = zx_socket_read(h1, 0u, NULL, 0, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(rbuf) + 5u, "");
count = 0;
status = zx_socket_read(h1, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
EXPECT_EQ(memcmp(rbuf, "pkt2", 5), 0, "");
status = zx_socket_read(h1, 0u, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, sizeof(rbuf), "");
EXPECT_EQ(rbuf[0], 'a', "");
EXPECT_EQ(rbuf[1000], 'b', "");
EXPECT_EQ(rbuf[2000], 'c', "");
EXPECT_EQ(rbuf[3000], 'd', "");
EXPECT_EQ(rbuf[4000], 'e', "");
EXPECT_EQ(rbuf[4095], 'f', "");
status = zx_socket_read(h1, 0u, NULL, 0, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 0u, "");
END_TEST;
}
static bool socket_datagram_no_short_write(void) {
BEGIN_TEST;
zx_status_t status;
zx_handle_t h0, h1;
status = zx_socket_create(ZX_SOCKET_DATAGRAM, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
// TODO(qsr): Request socket buffer and use (socket_buffer + 1).
const size_t buffer_size = 256 * 1024 + 1;
char* buffer = malloc(buffer_size);
size_t written = 999;
status = zx_socket_write(h0, 0u, buffer, buffer_size, &written);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
// Since the syscall failed, it should not have overwritten this output
// parameter.
EXPECT_EQ(written, 999u, "");
free(buffer);
zx_handle_close(h0);
zx_handle_close(h1);
END_TEST;
}
static bool socket_control_plane_absent(void) {
BEGIN_TEST;
zx_status_t status;
zx_handle_t h0, h1;
status = zx_socket_create(0, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
status = zx_socket_write(h0, ZX_SOCKET_CONTROL, "hi", 2u, NULL);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
status = zx_socket_write(h1, ZX_SOCKET_CONTROL, "hi", 2u, NULL);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
size_t count;
char rbuf[10] = {0};
status = zx_socket_read(h0, ZX_SOCKET_CONTROL, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
status = zx_socket_read(h1, ZX_SOCKET_CONTROL, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_ERR_BAD_STATE, "");
END_TEST;
}
static bool socket_control_plane(void) {
BEGIN_TEST;
zx_status_t status;
zx_handle_t h0, h1;
status = zx_socket_create(ZX_SOCKET_HAS_CONTROL, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
zx_signals_t signals0 = get_satisfied_signals(h0);
zx_signals_t signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
// Write to the control plane.
size_t count;
status = zx_socket_write(h0, ZX_SOCKET_CONTROL, "hello1", 6u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 6u, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_READABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h0, ZX_SOCKET_CONTROL, "hi", 2u, NULL);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
status = zx_socket_write(h1, ZX_SOCKET_CONTROL, "hello0", 6u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 6u, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_READABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_READABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, ZX_SOCKET_CONTROL, "hi", 2u, NULL);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
char rbuf[10] = {0};
// The control plane is independent of normal reads and writes.
status = zx_socket_read(h0, 0, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
status = zx_socket_read(h1, 0, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
status = zx_socket_write(h0, 0, "normal", 7u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 7u, "");
status = zx_socket_read(h1, 0, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 7u, "");
EXPECT_EQ(memcmp(rbuf, "normal", 7), 0, "");
// Read from the control plane.
status = zx_socket_read(h0, ZX_SOCKET_CONTROL, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 6u, "");
EXPECT_EQ(memcmp(rbuf, "hello0", 6), 0, "");
status = zx_socket_read(h0, ZX_SOCKET_CONTROL, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
status = zx_socket_read(h1, ZX_SOCKET_CONTROL, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 6u, "");
EXPECT_EQ(memcmp(rbuf, "hello1", 6), 0, "");
status = zx_socket_read(h1, ZX_SOCKET_CONTROL, rbuf, sizeof(rbuf), &count);
EXPECT_EQ(status, ZX_ERR_SHOULD_WAIT, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
END_TEST;
}
static bool socket_control_plane_shutdown(void) {
BEGIN_TEST;
zx_status_t status;
size_t count;
zx_handle_t h0, h1;
status = zx_socket_create(ZX_SOCKET_HAS_CONTROL, &h0, &h1);
ASSERT_EQ(status, ZX_OK, "");
zx_signals_t signals0 = get_satisfied_signals(h0);
zx_signals_t signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h1, 0u, "12345", 5u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 5u, "");
status = zx_socket_write(h1, ZX_SOCKET_SHUTDOWN_WRITE, NULL, 0u, NULL);
EXPECT_EQ(status, ZX_OK, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_WRITABLE | ZX_SOCKET_READABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITE_DISABLED | ZX_SOCKET_CONTROL_WRITABLE | ZX_SIGNAL_LAST_HANDLE, "");
status = zx_socket_write(h0, ZX_SOCKET_CONTROL, "hello1", 6u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 6u, "");
status = zx_socket_write(h1, ZX_SOCKET_CONTROL, "hello0", 6u, &count);
EXPECT_EQ(status, ZX_OK, "");
EXPECT_EQ(count, 6u, "");
signals0 = get_satisfied_signals(h0);
signals1 = get_satisfied_signals(h1);
EXPECT_EQ(signals0, ZX_SOCKET_WRITABLE | ZX_SOCKET_CONTROL_READABLE | ZX_SOCKET_READABLE | ZX_SIGNAL_LAST_HANDLE, "");
EXPECT_EQ(signals1, ZX_SOCKET_WRITE_DISABLED | ZX_SOCKET_CONTROL_READABLE | ZX_SIGNAL_LAST_HANDLE, "");
END_TEST;
}
BEGIN_TEST_CASE(socket_tests)
RUN_TEST(socket_basic)
RUN_TEST(socket_signals)
RUN_TEST(socket_shutdown_write)
RUN_TEST(socket_shutdown_read)
RUN_TEST(socket_bytes_outstanding)
RUN_TEST(socket_bytes_outstanding_shutdown_write)
RUN_TEST(socket_bytes_outstanding_shutdown_read)
RUN_TEST(socket_short_write)
RUN_TEST(socket_datagram)
RUN_TEST(socket_datagram_no_short_write)
RUN_TEST(socket_control_plane_absent)
RUN_TEST(socket_control_plane)
RUN_TEST(socket_control_plane_shutdown)
END_TEST_CASE(socket_tests)
#ifndef BUILD_COMBINED_TESTS
int main(int argc, char** argv) {
return unittest_run_all_tests(argc, argv) ? 0 : -1;
}
#endif