initial integrations of socket_transport into async_socket (#354)

* initial integrations of socket_transport into async_socket

---------

Co-authored-by: Jelani Brandon <jebrando@microsoft.com>
This commit is contained in:
samrach9 2024-10-16 10:27:20 -07:00 коммит произвёл GitHub
Родитель fd1c0a2c6c
Коммит ab26b45658
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
22 изменённых файлов: 690 добавлений и 890 удалений

Просмотреть файл

@ -4,8 +4,10 @@
#define ASYNC_SOCKET_H
#include "macro_utils/macro_utils.h"
#include "c_pal/execution_engine.h"
#include "socket_handle.h"
#include "c_pal/socket_transport.h"
#include "umock_c/umock_c_prod.h"
#ifdef __cplusplus
@ -78,7 +80,7 @@ MOCKABLE_FUNCTION(, ASYNC_SOCKET_HANDLE, async_socket_create, EXECUTION_ENGINE_H
MOCKABLE_FUNCTION(, ASYNC_SOCKET_HANDLE, async_socket_create_with_transport, EXECUTION_ENGINE_HANDLE, execution_engine, ON_ASYNC_SOCKET_SEND, on_send, void*, on_send_context, ON_ASYNC_SOCKET_RECV, on_recv, void*, on_recv_context);
MOCKABLE_FUNCTION(, void, async_socket_destroy, ASYNC_SOCKET_HANDLE, async_socket);
MOCKABLE_FUNCTION(, int, async_socket_open_async, ASYNC_SOCKET_HANDLE, async_socket, SOCKET_HANDLE, socket_handle, ON_ASYNC_SOCKET_OPEN_COMPLETE, on_open_complete, void*, on_open_complete_context);
MOCKABLE_FUNCTION(, int, async_socket_open_async, ASYNC_SOCKET_HANDLE, async_socket, SOCKET_TRANSPORT_HANDLE, socket_transport, ON_ASYNC_SOCKET_OPEN_COMPLETE, on_open_complete, void*, on_open_complete_context);
MOCKABLE_FUNCTION(, void, async_socket_close, ASYNC_SOCKET_HANDLE, async_socket);
MOCKABLE_FUNCTION(, ASYNC_SOCKET_SEND_SYNC_RESULT, async_socket_send_async, ASYNC_SOCKET_HANDLE, async_socket, const ASYNC_SOCKET_BUFFER*, payload, uint32_t, buffer_count, ON_ASYNC_SOCKET_SEND_COMPLETE, on_send_complete, void*, on_send_complete_context);
MOCKABLE_FUNCTION(, int, async_socket_receive_async, ASYNC_SOCKET_HANDLE, async_socket, ASYNC_SOCKET_BUFFER*, payload, uint32_t, buffer_count, ON_ASYNC_SOCKET_RECEIVE_COMPLETE, on_receive_complete, void*, on_receive_complete_context);

Просмотреть файл

@ -3,12 +3,6 @@
#ifndef SOCKET_TRANSPORT_H
#define SOCKET_TRANSPORT_H
#include "macro_utils/macro_utils.h"
#include "umock_c/umock_c_prod.h"
#include "socket_handle.h"
#ifdef __cplusplus
#include <cstdint>
extern "C" {
@ -17,6 +11,12 @@ extern "C" {
#include <stdint.h>
#endif
#include "macro_utils/macro_utils.h"
#include "umock_c/umock_c_prod.h"
#include "c_pal/socket_handle.h"
typedef struct SOCKET_TRANSPORT_TAG* SOCKET_TRANSPORT_HANDLE;
#define SOCKET_SEND_RESULT_VALUES \

Просмотреть файл

@ -1,6 +1,7 @@
#Copyright (C) Microsoft Corporation. All rights reserved.
if(${run_int_tests})
build_test_folder(async_socket_int)
build_test_folder(pipe_int)
build_test_folder(timer_int)
build_test_folder(socket_transport_int)

Просмотреть файл

@ -0,0 +1,25 @@
#Copyright (c) Microsoft. All rights reserved.
set(theseTestsName async_socket_int)
set(${theseTestsName}_test_files
${theseTestsName}.c
)
set(${theseTestsName}_c_files
)
set(${theseTestsName}_h_files
)
build_test_artifacts(${theseTestsName} "tests/c_pal/int" ADDITIONAL_LIBS pal_interfaces c_pal c_pal_ll)
if(WIN32)
if("${building}" STREQUAL "exe")
set_target_properties(${theseTestsName}_exe_${CMAKE_PROJECT_NAME} PROPERTIES LINK_FLAGS "/ignore:4217")
endif()
if("${building}" STREQUAL "dll")
set_target_properties(${theseTestsName}_dll_${CMAKE_PROJECT_NAME} PROPERTIES LINK_FLAGS "/ignore:4217")
endif()
endif()

Просмотреть файл

@ -1,29 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
#include <stdlib.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include "testrunnerswitcher.h"
#include "macro_utils/macro_utils.h" // IWYU pragma: keep
#include "macro_utils/macro_utils.h"
#include "c_pal/async_socket.h"
#include "c_pal/execution_engine.h"
#include "c_pal/gballoc_hl.h"
#include "c_pal/interlocked.h"
#include "c_pal/sync.h"
#include "c_pal/socket_handle.h"
#include "c_pal/gballoc_hl.h"
#include "c_pal/platform.h"
#include "c_pal/socket_transport.h"
#include "c_pal/socket_handle.h"
#include "c_pal/sync.h"
#define TEST_PORT 2244
static int g_port_num = TEST_PORT;
#define XTEST_FUNCTION(x) void x(void)
#define TEST_PORT 4466
#define TEST_CONN_TIMEOUT 10000
static uint16_t g_port_num = TEST_PORT;
TEST_DEFINE_ENUM_TYPE(ASYNC_SOCKET_OPEN_RESULT, ASYNC_SOCKET_OPEN_RESULT_VALUES);
TEST_DEFINE_ENUM_TYPE(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_RESULT_VALUES)
@ -50,6 +48,7 @@ static void on_send_complete(void* context, ASYNC_SOCKET_SEND_RESULT send_result
static void on_receive_complete(void* context, ASYNC_SOCKET_RECEIVE_RESULT receive_result, uint32_t bytes_received)
{
(void)bytes_received;
volatile_atomic int32_t* thread_counter = (volatile_atomic int32_t*)context;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_OK, receive_result);
@ -59,6 +58,8 @@ static void on_receive_complete(void* context, ASYNC_SOCKET_RECEIVE_RESULT recei
static void on_receive_abandoned_complete(void* context, ASYNC_SOCKET_RECEIVE_RESULT receive_result, uint32_t bytes_received)
{
(void)context;
(void)bytes_received;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_ABANDONED, receive_result);
}
@ -73,6 +74,7 @@ static void on_receive_and_accumulate_complete(void* context, ASYNC_SOCKET_RECEI
static void on_receive_complete_with_error(void* context, ASYNC_SOCKET_RECEIVE_RESULT receive_result, uint32_t bytes_received)
{
(void)bytes_received;
volatile_atomic int32_t* thread_counter = (volatile_atomic int32_t*)context;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_ABANDONED, receive_result);
@ -80,78 +82,6 @@ static void on_receive_complete_with_error(void* context, ASYNC_SOCKET_RECEIVE_R
wake_by_address_single(thread_counter);
}
static void set_nonblocking(SOCKET_HANDLE socket)
{
int opts = fcntl(socket, F_GETFL);
ASSERT_IS_TRUE(opts >= 0, "Failure getting socket option");
opts = fcntl(socket, F_SETFL, opts|O_NONBLOCK);
ASSERT_IS_TRUE(opts >= 0, "Failure setting socket option");
}
static void setup_server_socket(SOCKET_HANDLE* listen_socket)
{
// create a listening socket
*listen_socket = socket(AF_INET, SOCK_STREAM, 0);
ASSERT_ARE_NOT_EQUAL(int, INVALID_SOCKET, *listen_socket);
const int enable = 1;
ASSERT_ARE_EQUAL(int, 0, setsockopt(*listen_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)));
int bind_res;
uint32_t counter = 0;
// The gate machines fails on bind due to 3 different
// Process running, so we have to figure out the proper
// address to bind to by going through ports looking for an open one
do
{
struct sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(g_port_num);
service.sin_addr.s_addr = htonl(INADDR_ANY);
bind_res = bind(*listen_socket, (struct sockaddr*)&service, sizeof(service));
if (bind_res != 0)
{
g_port_num++;
}
counter++;
} while (bind_res != 0 && counter < 10);
ASSERT_ARE_EQUAL(int, 0, bind_res, "Failure attempting to bind (%d) to socket %d error (%d): %s", bind_res, g_port_num, errno, strerror(errno));
// set it to async IO
set_nonblocking(*listen_socket);
// start listening
ASSERT_ARE_EQUAL(int, 0, listen(*listen_socket, SOMAXCONN), "Failure on listen socket error (%d): port: %d", errno, g_port_num);
}
static void setup_test_socket(int port_num, SOCKET_HANDLE* client_socket, SOCKET_HANDLE* listen_socket, SOCKET_HANDLE* accept_socket)
{
// create a client socket
*client_socket = socket(AF_INET, SOCK_STREAM, 0);
ASSERT_ARE_NOT_EQUAL(int, INVALID_SOCKET, *client_socket);
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port_num);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ASSERT_ARE_NOT_EQUAL(int, INVALID_SOCKET, connect(*client_socket, (struct sockaddr*)&serv_addr, sizeof(struct sockaddr)), "Unable to connect client");
// set it to async IO
set_nonblocking(*client_socket);
do
{
*accept_socket = accept(*listen_socket, NULL, NULL);
} while (*accept_socket == INVALID_SOCKET && errno == 11);
ASSERT_ARE_NOT_EQUAL(int, INVALID_SOCKET, *accept_socket, "Failure accepting socket. Error No: %s", strerror(errno));
set_nonblocking(*accept_socket);
}
static void wait_for_value(volatile_atomic int32_t* counter, int32_t target_value)
{
int32_t value;
@ -161,7 +91,7 @@ static void wait_for_value(volatile_atomic int32_t* counter, int32_t target_valu
}
}
static void open_async_handle(ASYNC_SOCKET_HANDLE handle, SOCKET_HANDLE socket)
static void open_async_handle(ASYNC_SOCKET_HANDLE handle, SOCKET_TRANSPORT_HANDLE socket)
{
volatile_atomic int32_t counter = 0;
@ -170,6 +100,16 @@ static void open_async_handle(ASYNC_SOCKET_HANDLE handle, SOCKET_HANDLE socket)
wait_for_value(&counter, 1);
}
void set_up_listen_socket(SOCKET_TRANSPORT_HANDLE listen_socket)
{
int result = socket_transport_listen(listen_socket, g_port_num);
if(result != 0)
{
g_port_num++;
ASSERT_ARE_EQUAL(int, 0, socket_transport_listen(listen_socket, g_port_num), "failed listening on port %" PRIu16 "", g_port_num);
}
}
static void dump_bytes(const char* msg, uint8_t data_payload[], uint32_t length)
{
printf("%s %" PRIu32 " data: ", msg, length);
@ -213,12 +153,23 @@ TEST_FUNCTION(connect_no_send_succeeds)
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET_HANDLE client_socket;
SOCKET_HANDLE accept_socket;
SOCKET_HANDLE listen_socket;
SOCKET_TRANSPORT_HANDLE client_socket;
SOCKET_TRANSPORT_HANDLE server_socket;
SOCKET_TRANSPORT_HANDLE listen_socket;
setup_server_socket(&listen_socket);
setup_test_socket(g_port_num, &client_socket, &listen_socket, &accept_socket);
listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
set_up_listen_socket(listen_socket);
// create the async socket object
client_socket = socket_transport_create_client();
ASSERT_IS_NOT_NULL(client_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(client_socket, "localhost", g_port_num, TEST_CONN_TIMEOUT));
socket_transport_accept(listen_socket, &server_socket, TEST_CONN_TIMEOUT);
ASSERT_IS_NOT_NULL(server_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE server_async_socket = async_socket_create(execution_engine);
@ -227,7 +178,7 @@ TEST_FUNCTION(connect_no_send_succeeds)
ASSERT_IS_NOT_NULL(client_async_socket);
// wait for open to complete
open_async_handle(server_async_socket, accept_socket);
open_async_handle(server_async_socket, server_socket);
open_async_handle(client_async_socket, client_socket);
uint8_t receive_buffer[2];
@ -238,12 +189,26 @@ TEST_FUNCTION(connect_no_send_succeeds)
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(client_async_socket, receive_payload_buffers, 1, on_receive_abandoned_complete, NULL));
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(server_async_socket, receive_payload_buffers, 1, on_receive_abandoned_complete, NULL));
#ifdef _MSC_VER // only for windows
socket_transport_disconnect(server_socket);
async_socket_close(server_async_socket);
socket_transport_disconnect(client_socket);
async_socket_close(client_async_socket);
#else
async_socket_close(server_async_socket);
socket_transport_disconnect(server_socket);
async_socket_close(client_async_socket);
socket_transport_disconnect(client_socket);
#endif
socket_transport_disconnect(listen_socket);
socket_transport_destroy(listen_socket);
socket_transport_destroy(server_socket);
socket_transport_destroy(client_socket);
async_socket_destroy(server_async_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
close(listen_socket);
}
TEST_FUNCTION(send_and_receive_1_byte_succeeds)
@ -254,12 +219,24 @@ TEST_FUNCTION(send_and_receive_1_byte_succeeds)
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET_HANDLE client_socket;
SOCKET_HANDLE accept_socket;
SOCKET_HANDLE listen_socket;
SOCKET_TRANSPORT_HANDLE client_socket;
// server socket is same as accept socket
SOCKET_TRANSPORT_HANDLE server_socket;
SOCKET_TRANSPORT_HANDLE listen_socket;
setup_server_socket(&listen_socket);
setup_test_socket(g_port_num, &client_socket, &listen_socket, &accept_socket);
listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
set_up_listen_socket(listen_socket);
// create the async socket object
client_socket = socket_transport_create_client();
ASSERT_IS_NOT_NULL(client_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(client_socket, "localhost", g_port_num, TEST_CONN_TIMEOUT));
socket_transport_accept(listen_socket, &server_socket, TEST_CONN_TIMEOUT);
ASSERT_IS_NOT_NULL(server_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE server_async_socket = async_socket_create(execution_engine);
@ -268,7 +245,7 @@ TEST_FUNCTION(send_and_receive_1_byte_succeeds)
ASSERT_IS_NOT_NULL(client_async_socket);
// wait for open to complete
open_async_handle(server_async_socket, accept_socket);
open_async_handle(server_async_socket, server_socket);
open_async_handle(client_async_socket, client_socket);
uint8_t data_payload[] = { 0x42, 0x43 };
@ -296,9 +273,21 @@ TEST_FUNCTION(send_and_receive_1_byte_succeeds)
ASSERT_ARE_EQUAL(int, 0, memcmp(receive_payload_buffers[0].buffer, send_payload_buffers[0].buffer, sizeof(data_payload)));
#ifdef _MSC_VER // only for windows
socket_transport_disconnect(server_socket);
async_socket_close(server_async_socket);
socket_transport_disconnect(client_socket);
async_socket_close(client_async_socket);
close(listen_socket);
#else
async_socket_close(server_async_socket);
socket_transport_disconnect(server_socket);
async_socket_close(client_async_socket);
socket_transport_disconnect(client_socket);
#endif
socket_transport_disconnect(listen_socket);
socket_transport_destroy(listen_socket);
socket_transport_destroy(server_socket);
socket_transport_destroy(client_socket);
async_socket_destroy(server_async_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
@ -312,12 +301,24 @@ TEST_FUNCTION(receive_and_send_2_buffers_succeeds)
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET_HANDLE client_socket;
SOCKET_HANDLE accept_socket;
SOCKET_HANDLE listen_socket;
SOCKET_TRANSPORT_HANDLE client_socket;
// server socket is same as accept socket
SOCKET_TRANSPORT_HANDLE server_socket;
SOCKET_TRANSPORT_HANDLE listen_socket;
setup_server_socket(&listen_socket);
setup_test_socket(g_port_num, &client_socket, &listen_socket, &accept_socket);
listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
set_up_listen_socket(listen_socket);
// create the async socket object
client_socket = socket_transport_create_client();
ASSERT_IS_NOT_NULL(client_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(client_socket, "localhost", g_port_num, TEST_CONN_TIMEOUT));
socket_transport_accept(listen_socket, &server_socket, TEST_CONN_TIMEOUT);
ASSERT_IS_NOT_NULL(server_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE server_async_socket = async_socket_create(execution_engine);
@ -326,7 +327,7 @@ TEST_FUNCTION(receive_and_send_2_buffers_succeeds)
ASSERT_IS_NOT_NULL(client_async_socket);
// wait for open to complete
open_async_handle(server_async_socket, accept_socket);
open_async_handle(server_async_socket, server_socket);
open_async_handle(client_async_socket, client_socket);
uint8_t data_payload_1[] = { 0x42, 0x43 };
@ -359,9 +360,21 @@ TEST_FUNCTION(receive_and_send_2_buffers_succeeds)
wait_for_value(&recv_counter, 1);
// cleanup
#ifdef _MSC_VER // only for windows
socket_transport_disconnect(server_socket);
async_socket_close(server_async_socket);
socket_transport_disconnect(client_socket);
async_socket_close(client_async_socket);
close(listen_socket);
#else
async_socket_close(server_async_socket);
socket_transport_disconnect(server_socket);
async_socket_close(client_async_socket);
socket_transport_disconnect(client_socket);
#endif
socket_transport_disconnect(listen_socket);
socket_transport_destroy(listen_socket);
socket_transport_destroy(server_socket);
socket_transport_destroy(client_socket);
async_socket_destroy(server_async_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
@ -375,12 +388,24 @@ TEST_FUNCTION(when_server_socket_is_closed_receive_errors_on_client_side)
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET_HANDLE client_socket;
SOCKET_HANDLE accept_socket;
SOCKET_HANDLE listen_socket;
SOCKET_TRANSPORT_HANDLE client_socket;
// server socket is same as accept socket
SOCKET_TRANSPORT_HANDLE server_socket;
SOCKET_TRANSPORT_HANDLE listen_socket;
setup_server_socket(&listen_socket);
setup_test_socket(g_port_num, &client_socket, &listen_socket, &accept_socket);
listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
set_up_listen_socket(listen_socket);
// create the async socket object
client_socket = socket_transport_create_client();
ASSERT_IS_NOT_NULL(client_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(client_socket, "localhost", g_port_num, TEST_CONN_TIMEOUT));
socket_transport_accept(listen_socket, &server_socket, TEST_CONN_TIMEOUT);
ASSERT_IS_NOT_NULL(server_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE client_async_socket = async_socket_create(execution_engine);
@ -397,7 +422,7 @@ TEST_FUNCTION(when_server_socket_is_closed_receive_errors_on_client_side)
volatile_atomic int32_t recv_counter;
interlocked_exchange(&recv_counter, 0);
close(accept_socket);
socket_transport_disconnect(server_socket);
// act (send one byte and receive it)
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(client_async_socket, receive_payload_buffers, 1, on_receive_complete_with_error, (void*)&recv_counter));
@ -406,8 +431,19 @@ TEST_FUNCTION(when_server_socket_is_closed_receive_errors_on_client_side)
wait_for_value(&recv_counter, 1);
// cleanup
#ifdef _MSC_VER // only for windows
socket_transport_disconnect(client_socket);
async_socket_close(client_async_socket);
close(listen_socket);
#else
async_socket_close(client_async_socket);
socket_transport_disconnect(client_socket);
#endif
async_socket_close(client_async_socket);
socket_transport_destroy(client_socket);
socket_transport_destroy(server_socket);
socket_transport_disconnect(listen_socket);
socket_transport_destroy(listen_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
}
@ -420,12 +456,23 @@ TEST_FUNCTION(multiple_sends_and_receives_succeeds)
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET_HANDLE client_socket;
SOCKET_HANDLE accept_socket;
SOCKET_HANDLE listen_socket;
SOCKET_TRANSPORT_HANDLE client_socket;
SOCKET_TRANSPORT_HANDLE server_socket;
SOCKET_TRANSPORT_HANDLE listen_socket;
setup_server_socket(&listen_socket);
setup_test_socket(g_port_num, &client_socket, &listen_socket, &accept_socket);
listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
set_up_listen_socket(listen_socket);
// create the async socket object
client_socket = socket_transport_create_client();
ASSERT_IS_NOT_NULL(client_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(client_socket, "localhost", g_port_num, TEST_CONN_TIMEOUT));
socket_transport_accept(listen_socket, &server_socket, TEST_CONN_TIMEOUT);
ASSERT_IS_NOT_NULL(server_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE server_async_socket = async_socket_create(execution_engine);
@ -434,7 +481,7 @@ TEST_FUNCTION(multiple_sends_and_receives_succeeds)
ASSERT_IS_NOT_NULL(client_async_socket);
// wait for open to complete
open_async_handle(server_async_socket, accept_socket);
open_async_handle(server_async_socket, server_socket);
open_async_handle(client_async_socket, client_socket);
uint8_t data_payload[] = { 0x42, 0x43, 0x44, 0x45 };
@ -469,15 +516,27 @@ TEST_FUNCTION(multiple_sends_and_receives_succeeds)
wait_for_value(&send_counter, 3);
wait_for_value(&recv_counter, expected_recv_size);
#ifdef _MSC_VER // only for windows
socket_transport_disconnect(server_socket);
async_socket_close(server_async_socket);
socket_transport_disconnect(client_socket);
async_socket_close(client_async_socket);
close(listen_socket);
#else
async_socket_close(server_async_socket);
socket_transport_disconnect(server_socket);
async_socket_close(client_async_socket);
socket_transport_disconnect(client_socket);
#endif
socket_transport_disconnect(listen_socket);
socket_transport_destroy(listen_socket);
socket_transport_destroy(server_socket);
socket_transport_destroy(client_socket);
async_socket_destroy(server_async_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
}
#define N_WORK_ITEMS 1000
#define N_WORK_ITEMS 100
TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _sockets_items))
{
@ -486,27 +545,39 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _sockets_items))
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET_HANDLE listen_socket;
SOCKET_TRANSPORT_HANDLE listen_socket;
listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
set_up_listen_socket(listen_socket);
ASYNC_SOCKET_HANDLE server_async_socket[N_WORK_ITEMS];
ASYNC_SOCKET_HANDLE client_async_socket[N_WORK_ITEMS];
setup_server_socket(&listen_socket);
SOCKET_TRANSPORT_HANDLE client_socket[N_WORK_ITEMS];
SOCKET_TRANSPORT_HANDLE server_socket[N_WORK_ITEMS];
uint32_t socket_count = N_WORK_ITEMS;
for (uint32_t index = 0; index < socket_count; index++)
{
SOCKET_HANDLE accept_socket;
SOCKET_HANDLE client_socket;
setup_test_socket(g_port_num, &client_socket, &listen_socket, &accept_socket);
client_socket[index] = socket_transport_create_client();
ASSERT_IS_NOT_NULL(client_socket[index]);
ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(client_socket[index], "localhost", g_port_num, TEST_CONN_TIMEOUT));
socket_transport_accept(listen_socket, &server_socket[index], TEST_CONN_TIMEOUT);
ASSERT_IS_NOT_NULL(server_socket[index]);
// create the async socket object
ASSERT_IS_NOT_NULL(server_async_socket[index] = async_socket_create(execution_engine));
ASSERT_IS_NOT_NULL(client_async_socket[index] = async_socket_create(execution_engine));
// wait for open to complete
open_async_handle(server_async_socket[index], accept_socket);
open_async_handle(client_async_socket[index], client_socket);
open_async_handle(server_async_socket[index], server_socket[index]);
open_async_handle(client_async_socket[index], client_socket[index]);
}
uint8_t data_payload[] = { 0x42, 0x43, 0x44, 0x45 };
@ -537,11 +608,25 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _sockets_items))
wait_for_value(&send_counter, socket_count);
wait_for_value(&recv_size, expected_recv_size);
close(listen_socket);
socket_transport_disconnect(listen_socket);
socket_transport_destroy(listen_socket);
for (uint32_t index = 0; index < socket_count; index++)
{
#ifdef _MSC_VER // only for windows
socket_transport_disconnect(server_socket[index]);
async_socket_close(server_async_socket[index]);
socket_transport_disconnect(client_socket[index]);
async_socket_close(client_async_socket[index]);
#else
async_socket_close(server_async_socket[index]);
socket_transport_disconnect(server_socket[index]);
async_socket_close(client_async_socket[index]);
socket_transport_disconnect(client_socket[index]);
#endif
socket_transport_destroy(client_socket[index]);
socket_transport_destroy(server_socket[index]);
async_socket_destroy(server_async_socket[index]);
async_socket_destroy(client_async_socket[index]);
}

Просмотреть файл

@ -25,8 +25,6 @@
#endif // !WIN32
#define XTEST_FUNCTION(x) void x(void)
#define TEST_PORT 4466
#define TEST_CONN_TIMEOUT 10000
@ -72,6 +70,16 @@ TEST_FUNCTION_CLEANUP(method_cleanup)
{
}
static void set_up_listen_socket(SOCKET_TRANSPORT_HANDLE listen_socket)
{
int result = socket_transport_listen(listen_socket, g_port_num);
if(result != 0)
{
g_port_num++;
ASSERT_ARE_EQUAL(int, 0, socket_transport_listen(listen_socket, g_port_num), "failed listening on port %" PRIu16 "", g_port_num);
}
}
#if WIN32
TEST_FUNCTION(connect_to_endpoint_timesout)
{
@ -132,7 +140,7 @@ TEST_FUNCTION(send_and_receive_2_buffer_of_2_byte_succeeds)
SOCKET_TRANSPORT_HANDLE listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_listen(listen_socket, g_port_num), "failed listening on port %" PRIu16 "", g_port_num);
set_up_listen_socket(listen_socket);
// create the async socket object
SOCKET_TRANSPORT_HANDLE client_socket = socket_transport_create_client();
@ -237,7 +245,7 @@ TEST_FUNCTION(send_and_receive_random_buffer_of_random_byte_succeeds)
SOCKET_TRANSPORT_HANDLE listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(listen_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_listen(listen_socket, g_port_num));
set_up_listen_socket(listen_socket);
// create the async socket object
SOCKET_TRANSPORT_HANDLE client_socket = socket_transport_create_client();
@ -298,7 +306,7 @@ static int connect_and_listen_func(void* parameter)
chaos_knight_test->listen_socket = socket_transport_create_server();
ASSERT_IS_NOT_NULL(chaos_knight_test->listen_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_listen(chaos_knight_test->listen_socket, g_port_num));
set_up_listen_socket(chaos_knight_test->listen_socket);
for (i = 0; i < CHAOS_THREAD_COUNT; i++)
{

Просмотреть файл

@ -160,7 +160,7 @@ MOCKABLE_FUNCTION(, int, async_socket_open_async, ASYNC_SOCKET_HANDLE, async_soc
**SRS_ASYNC_SOCKET_LINUX_11_026: [** `on_open_complete_context` shall be allowed to be `NULL`. **]**
**SRS_ASYNC_SOCKET_LINUX_11_003: [** If `socket_handle` is `INVALID_SOCKET`, `async_socket_open_async` shall fail and return non-zero value. **]**
**SRS_ASYNC_SOCKET_LINUX_11_003: [** If `socket_transport_handle` is `NULL`, `async_socket_open_async` shall fail and return non-zero value. **]**
**SRS_ASYNC_SOCKET_LINUX_11_027: [** Otherwise, `async_socket_open_async` shall switch the state to `OPENING`. **]**
@ -190,8 +190,6 @@ MOCKABLE_FUNCTION(, void, async_socket_close, ASYNC_SOCKET_HANDLE, async_socket)
**SRS_ASYNC_SOCKET_LINUX_11_037: [** `async_socket_close` shall wait for all executing `async_socket_send_async` and `async_socket_receive_async` APIs. **]**
**SRS_ASYNC_SOCKET_LINUX_11_039: [** `async_socket_close` shall call `close` on the underlying socket. **]**
**SRS_ASYNC_SOCKET_LINUX_11_041: [** `async_socket_close` shall set the state to CLOSED. **]**
**SRS_ASYNC_SOCKET_LINUX_11_042: [** If `async_socket` is not OPEN, `async_socket_close` shall return. **]**
@ -236,7 +234,7 @@ MOCKABLE_FUNCTION(, ASYNC_SOCKET_SEND_SYNC_RESULT, async_socket_send_async, ASYN
**SRS_ASYNC_SOCKET_LINUX_11_053: [** `async_socket_send_async` shall continue to send the data until the payload length has been sent. **]**
**SRS_ASYNC_SOCKET_LINUX_11_054: [** If the `send` fails to send the data, `async_socket_send_async` shall do the following: **]**
**SRS_ASYNC_SOCKET_LINUX_11_054: [** If `socket_transport_send` fails to send the data, `async_socket_send_async` shall do the following: **]**
- **SRS_ASYNC_SOCKET_LINUX_11_055: [** If the `errno` value is `EAGAIN` or `EWOULDBLOCK`. **]**

Просмотреть файл

@ -24,7 +24,8 @@
#include "c_pal/interlocked.h"
#include "c_pal/platform_linux.h"
#include "c_pal/sync.h"
#include "c_pal/socket_handle.h"
#include "c_pal/socket_transport.h"
#include "c_pal/socket_handle.h" // IWYU pragma: keep
#ifdef ENABLE_SOCKET_LOGGING
#include "c_pal/timer.h"
@ -57,7 +58,7 @@ MU_DEFINE_ENUM_STRINGS(ASYNC_SOCKET_NOTIFY_IO_RESULT, ASYNC_SOCKET_NOTIFY_IO_RES
typedef struct ASYNC_SOCKET_TAG
{
int socket_handle;
SOCKET_TRANSPORT_HANDLE socket_transport_handle;
volatile_atomic int32_t state;
volatile_atomic int32_t pending_api_calls;
COMPLETION_PORT_HANDLE completion_port;
@ -108,28 +109,66 @@ static int on_socket_send(void* context, ASYNC_SOCKET_HANDLE async_socket, const
}
else
{
// Codes_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
result = send(async_socket->socket_handle, buf, len, MSG_NOSIGNAL);
}
// Codes_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling socket_transport_send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
SOCKET_BUFFER input_buf;
input_buf.buffer = (unsigned char*)buf;
input_buf.length = len;
uint32_t bytes_sent;
if(socket_transport_send(async_socket->socket_transport_handle, &input_buf, 1, &bytes_sent, MSG_NOSIGNAL, NULL) != SOCKET_SEND_OK)
{
result = -1;
LogError("socket_transport_send failed input_buf.buffer: %p, input_buf.length: %" PRIu32 ".", input_buf.buffer, input_buf.length);
}
else
{
result = bytes_sent;
}
}
return result;
}
static int on_socket_recv(void* context, ASYNC_SOCKET_HANDLE async_socket, void* buf, size_t len)
{
int result;
(void)context;
if (async_socket == NULL)
{
LogCritical("Invalid argument on_recv void* context, ASYNC_SOCKET_HANDLE async_socket, const void* buf, size_t len");
result = -1;
LogCritical("Invalid argument on_recv void* context, ASYNC_SOCKET_HANDLE async_socket, const void* buf, size_t len");
}
else
{
// Codes_SRS_ASYNC_SOCKET_LINUX_04_007: [ on_socket_recv shall attempt to receive data by calling the system recv socket API. ]
result = recv(async_socket->socket_handle, buf, len, 0);
// Codes_SRS_ASYNC_SOCKET_LINUX_04_007: [ on_socket_recv shall attempt to receive data by calling the socket_transport_receive API. ]
SOCKET_BUFFER input_buf;
input_buf.buffer = buf;
input_buf.length = len;
uint32_t bytes_recv;
SOCKET_RECEIVE_RESULT recv_result = socket_transport_receive(async_socket->socket_transport_handle, &input_buf, 1, &bytes_recv, 0, NULL);
if (recv_result != SOCKET_RECEIVE_OK && recv_result != SOCKET_RECEIVE_WOULD_BLOCK && recv_result != SOCKET_RECEIVE_SHUTDOWN)
{
result = -1;
LogError("socket_transport_receive failed input_buf.buffer: %p, input_buf.length: %" PRIu32 ".", input_buf.buffer, input_buf.length);
}
else if (recv_result == SOCKET_RECEIVE_WOULD_BLOCK)
{
result = -1;
LogInfo("Not enough space in send buffer of nonblocking socket. bytes sent: %" PRIu32 " input_buf.buffer: %p, input_buf.length: %" PRIu32 ".", bytes_recv, input_buf.buffer, input_buf.length);
}
else if (recv_result == SOCKET_RECEIVE_SHUTDOWN)
{
result = 0;
LogError("Socket received 0 bytes. bytes sent: %" PRIu32 " input_buf.buffer: %p, input_buf.length: %" PRIu32 ".", bytes_recv, input_buf.buffer, input_buf.length);
}
else
{
result = bytes_recv;
}
}
return result;
@ -263,7 +302,7 @@ static void event_complete_callback(void* context, COMPLETION_PORT_EPOLL_ACTION
}
else if (recv_size == 0)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_11_091: [ If the recv size equals 0, then event_complete_callback shall call on_receive_complete callback with the on_receive_complete_context and ASYNC_SOCKET_RECEIVE_ABANDONED. ]
// Codes_SRS_ASYNC_SOCKET_LINUX_11_091: [ If the socket_transport_receive size equals 0, then event_complete_callback shall call on_receive_complete callback with the on_receive_complete_context and ASYNC_SOCKET_RECEIVE_ABANDONED. ]
LogError("Socket received 0 bytes, assuming socket is closed");
receive_result = ASYNC_SOCKET_RECEIVE_ABANDONED;
break;
@ -280,7 +319,7 @@ static void event_complete_callback(void* context, COMPLETION_PORT_EPOLL_ACTION
}
else
{
// Codes_SRS_ASYNC_SOCKET_LINUX_11_092: [ If the recv size > 0, if we have another buffer to fill then we will attempt another read, otherwise we shall call on_receive_complete callback with the on_receive_complete_context and ASYNC_SOCKET_RECEIVE_OK ]
// Codes_SRS_ASYNC_SOCKET_LINUX_11_092: [ If the socket_transport_receive size > 0, if we have another buffer to fill then we will attempt another read, otherwise we shall call on_receive_complete callback with the on_receive_complete_context and ASYNC_SOCKET_RECEIVE_OK ]
total_recv_size += recv_size;
if (index + 1 >= io_context->data.recv_ctx.total_buffer_count || recv_size <= io_context->data.recv_ctx.recv_buffers[index].length)
{
@ -323,7 +362,7 @@ static void event_complete_callback(void* context, COMPLETION_PORT_EPOLL_ACTION
// Codes_SRS_ASYNC_SOCKET_LINUX_11_096: [ event_complete_callback shall call send on the data in the ASYNC_SOCKET_SEND_CONTEXT buffer. ]
if (send_data(io_context->async_socket, &io_context->data.send_ctx.socket_buffer, &total_data_sent, &error_no) != 0)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_11_097: [ If send returns value is < 0 event_complete_callback shall do the following: ]
// Codes_SRS_ASYNC_SOCKET_LINUX_11_097: [ If socket_transport_send returns value is < 0 event_complete_callback shall do the following: ]
if (error_no == ECONNRESET)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_11_098: [ if errno is ECONNRESET, then on_send_complete shall be called with ASYNC_SOCKET_SEND_ABANDONED. ]
@ -392,13 +431,9 @@ static void internal_close(ASYNC_SOCKET_HANDLE async_socket)
if (interlocked_add(&async_socket->added_to_completion_port, 0) > 0)
{
completion_port_remove(async_socket->completion_port, async_socket->socket_handle);
completion_port_remove(async_socket->completion_port, socket_transport_get_underlying_socket(async_socket->socket_transport_handle));
}
// Codes_SRS_ASYNC_SOCKET_LINUX_11_039: [ async_socket_close shall call close on the underlying socket. ]
(void)close(async_socket->socket_handle);
async_socket->socket_handle = INVALID_SOCKET;
// Codes_SRS_ASYNC_SOCKET_LINUX_11_041: [ async_socket_close shall set the state to closed. ]
(void)interlocked_exchange(&async_socket->state, ASYNC_SOCKET_LINUX_STATE_CLOSED);
wake_by_address_single(&async_socket->state);
@ -493,7 +528,7 @@ void async_socket_destroy(ASYNC_SOCKET_HANDLE async_socket)
}
}
int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE socket_handle, ON_ASYNC_SOCKET_OPEN_COMPLETE on_open_complete, void* on_open_complete_context)
int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_TRANSPORT_HANDLE socket_transport_handle, ON_ASYNC_SOCKET_OPEN_COMPLETE on_open_complete, void* on_open_complete_context)
{
int result;
// Codes_SRS_ASYNC_SOCKET_LINUX_11_026: [ on_open_complete_context shall be allowed to be NULL. ]
@ -502,8 +537,8 @@ int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE sock
async_socket == NULL ||
// Codes_SRS_ASYNC_SOCKET_LINUX_11_025: [ If on_open_complete is NULL, async_socket_open_async shall fail and return a non-zero value. ]
on_open_complete == NULL ||
// Codes_SRS_ASYNC_SOCKET_LINUX_11_003: [ If socket_handle is INVALID_SOCKET, async_socket_open_async shall fail and return a non-zero value. ]
socket_handle == INVALID_SOCKET
// Codes_SRS_ASYNC_SOCKET_LINUX_11_003: [ If socket_transport_handle is NULL, async_socket_open_async shall fail and return a non-zero value. ]
socket_transport_handle == NULL
)
{
LogError("ASYNC_SOCKET_HANDLE async_socket=%p, ON_ASYNC_SOCKET_OPEN_COMPLETE on_open_complete=%p, void* on_open_complete_context=%p",
@ -523,7 +558,7 @@ int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE sock
}
else
{
async_socket->socket_handle = socket_handle;
async_socket->socket_transport_handle = socket_transport_handle;
// Codes_SRS_ASYNC_SOCKET_LINUX_11_031: [ async_socket_open_async shall add the socket to the epoll system by calling epoll_ctl with EPOLL_CTL_ADD. ]
// Codes_SRS_ASYNC_SOCKET_LINUX_11_032: [ async_socket_open_async shall set the state to OPEN. ]
@ -642,7 +677,7 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
{
int error_no;
ssize_t total_data_sent;
// Codes_SRS_ASYNC_SOCKET_LINUX_11_054: [ If the send fails to send the data, async_socket_send_async shall do the following: ]
// Codes_SRS_ASYNC_SOCKET_LINUX_11_054: [ If socket_transport_send fails to send the data, async_socket_send_async shall do the following: ]
if (send_data(async_socket, &buffers[index], &total_data_sent, &error_no) != 0)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_11_055: [ If the errno value is EAGAIN or EWOULDBLOCK. ]
@ -670,7 +705,7 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
io_context->data.send_ctx.socket_buffer.length = buffers[index].length - total_data_sent;
// Codes_SRS_ASYNC_SOCKET_LINUX_11_057: [ The context shall then be added to the completion port system by calling completion_port_add with EPOLL_CTL_MOD and `event_complete_callback` as the callback. ]
if (completion_port_add(async_socket->completion_port, EPOLLOUT, async_socket->socket_handle, event_complete_callback, io_context) != 0)
if (completion_port_add(async_socket->completion_port, EPOLLOUT, socket_transport_get_underlying_socket(async_socket->socket_transport_handle), event_complete_callback, io_context) != 0)
{
LogError("failure with completion_port_add");
result = ASYNC_SOCKET_SEND_SYNC_ERROR;
@ -826,7 +861,7 @@ int async_socket_receive_async(ASYNC_SOCKET_HANDLE async_socket, ASYNC_SOCKET_BU
#endif
// Codes_SRS_ASYNC_SOCKET_LINUX_11_102: [ Then the context shall then be added to the completion port system by calling completion_port_add with EPOLLIN and event_complete_callback as the callback. ]
if (completion_port_add(async_socket->completion_port, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT, async_socket->socket_handle, event_complete_callback, io_context) != 0)
if (completion_port_add(async_socket->completion_port, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT, socket_transport_get_underlying_socket(async_socket->socket_transport_handle), event_complete_callback, io_context) != 0)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_11_078: [ If any error occurs, async_socket_receive_async shall fail and return a non-zero value. ]
LogWarning("failure with completion_port_add");
@ -899,7 +934,7 @@ int async_socket_notify_io_async(ASYNC_SOCKET_HANDLE async_socket, ASYNC_SOCKET_
int epoll_op = (io_type == ASYNC_SOCKET_NOTIFY_IO_TYPE_IN) ? EPOLLIN : EPOLLOUT;
// Codes_SRS_ASYNC_SOCKET_LINUX_04_018: [ Then the context shall then be added to the completion port system by calling completion_port_add with EPOLLIN if io_type is ASYNC_SOCKET_NOTIFY_IO_TYPE_IN and EPOLLOUT otherwise and event_complete_callback as the callback. ]
if (completion_port_add(async_socket->completion_port, epoll_op, async_socket->socket_handle, event_complete_callback, io_context) != 0)
if (completion_port_add(async_socket->completion_port, epoll_op, socket_transport_get_underlying_socket(async_socket->socket_transport_handle), event_complete_callback, io_context) != 0)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_04_020: [ If any error occurs, async_socket_notify_io_async shall fail and return a non-zero value. ]
LogWarning("failure with completion_port_add");

Просмотреть файл

@ -22,7 +22,6 @@ if(${run_unittests})
endif()
if(${run_int_tests})
build_test_folder(async_socket_linux_int)
build_test_folder(gballoc_ll_passthrough_int)
build_test_folder(string_utils_int)
build_test_folder(threadpool_linux_int)

Просмотреть файл

@ -1,15 +0,0 @@
#Copyright (c) Microsoft. All rights reserved.
set(theseTestsName async_socket_linux_int)
set(${theseTestsName}_test_files
${theseTestsName}.c
)
set(${theseTestsName}_c_files
)
set(${theseTestsName}_h_files
)
build_test_artifacts(${theseTestsName} "tests/c_pal/linux" ADDITIONAL_LIBS pal_interfaces c_pal)

Просмотреть файл

@ -7,7 +7,7 @@ set(${theseTestsName}_test_files
)
set(${theseTestsName}_c_files
async_socket_linux_mocked.c
../../src/async_socket_linux.c
)
set(${theseTestsName}_h_files

Просмотреть файл

@ -1,14 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
#include <stddef.h> // for size_t
#include <sys/types.h> // for ssize_t
#define close mocked_close
#define send mocked_send
#define recv mocked_recv
int mocked_close(int s);
ssize_t mocked_send(int fd, const void* buf, size_t n, int flags);
ssize_t mocked_recv(int fd, void* buf, size_t n, int flags);
#include "../../src/async_socket_linux.c"

Просмотреть файл

@ -5,7 +5,7 @@
#include <sys/epoll.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h> // for ssize_t
#include <sys/types.h> // for ssize_t
#include "macro_utils/macro_utils.h" // IWYU pragma: keep
@ -17,6 +17,7 @@
#include "umock_c/umocktypes_stdint.h"
#include "umock_c/umocktypes_charptr.h"
#include "umock_c/umock_c_negative_tests.h"
#include "c_logging/logger.h"
#define ENABLE_MOCKS
@ -28,6 +29,7 @@
#include "c_pal/platform_linux.h"
#include "c_pal/sync.h"
#include "c_pal/socket_handle.h"
#include "c_pal/socket_transport.h"
#undef ENABLE_MOCKS
@ -38,7 +40,12 @@
#define TEST_MAX_EVENTS_NUM 64
static SOCKET_HANDLE test_socket = (SOCKET_HANDLE)0x4242;
static SOCKET_TRANSPORT_HANDLE test_socket = (SOCKET_TRANSPORT_HANDLE)0x4242;
static SOCKET_HANDLE test_handle = (SOCKET_HANDLE)0x4242;
#define TEST_PORT 4466
#define TEST_CONN_TIMEOUT 10000
static EXECUTION_ENGINE_HANDLE test_execution_engine = (EXECUTION_ENGINE_HANDLE)0x4243;
static void* test_callback_ctx = (void*)0x4244;
static void* test_send_ctx = (void*)0x4245;
@ -67,6 +74,11 @@ IMPLEMENT_UMOCK_C_ENUM_TYPE(ASYNC_SOCKET_NOTIFY_IO_RESULT, ASYNC_SOCKET_NOTIFY_I
MU_DEFINE_ENUM_STRINGS(COMPLETION_PORT_EPOLL_ACTION, COMPLETION_PORT_EPOLL_ACTION_VALUES)
TEST_DEFINE_ENUM_TYPE(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT_VALUES)
IMPLEMENT_UMOCK_C_ENUM_TYPE(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT_VALUES)
TEST_DEFINE_ENUM_TYPE(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES)
IMPLEMENT_UMOCK_C_ENUM_TYPE(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES)
static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code)
{
ASSERT_FAIL("umock_c reported error :%" PRI_MU_ENUM "", MU_ENUM_VALUE(UMOCK_C_ERROR_CODE, error_code));
@ -83,14 +95,6 @@ static int my_completion_port_add(COMPLETION_PORT_HANDLE completion_port, int ep
return 0;
}
MOCK_FUNCTION_WITH_CODE(, int, mocked_close, int, s)
MOCK_FUNCTION_END(0)
MOCK_FUNCTION_WITH_CODE(, ssize_t, mocked_send, int, fd, const void*, buf, size_t, n, int, flags)
MOCK_FUNCTION_END(n)
MOCK_FUNCTION_WITH_CODE(, ssize_t, mocked_recv, int, fd, void*, buf, size_t, n, int, flags)
MOCK_FUNCTION_END(n)
MOCK_FUNCTION_WITH_CODE(, int, mocked_on_send, void*, context, ASYNC_SOCKET_HANDLE, async_socket, const void*, buf, size_t, n)
ASSERT_IS_NOT_NULL(context);
ASSERT_ARE_EQUAL(void_ptr, test_send_ctx, context);
@ -120,7 +124,6 @@ static void mock_internal_close_setup(void)
{
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_close(test_socket));
STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG))
.CallCannotFail();
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
@ -145,7 +148,9 @@ static void setup_async_socket_receive_async_mocks(void)
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0))
.CallCannotFail();
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(ASYNC_SOCKET_BUFFER)));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket))
.SetReturn((SOCKET_HANDLE)0x4242);
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT, test_handle, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG))
.CallCannotFail();
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG))
@ -160,7 +165,9 @@ static void setup_async_socket_notify_io_async_mocks(ASYNC_SOCKET_NOTIFY_IO_TYPE
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0))
.CallCannotFail();
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, (io_type == ASYNC_SOCKET_NOTIFY_IO_TYPE_IN) ? EPOLLIN : EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket))
.SetReturn((SOCKET_HANDLE)0x4242);
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, (io_type == ASYNC_SOCKET_NOTIFY_IO_TYPE_IN) ? EPOLLIN : EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG))
.CallCannotFail();
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG))
@ -199,12 +206,16 @@ TEST_SUITE_INITIALIZE(suite_init)
REGISTER_UMOCK_ALIAS_TYPE(COMPLETION_PORT_HANDLE, void*);
REGISTER_UMOCK_ALIAS_TYPE(ON_COMPLETION_PORT_EVENT_COMPLETE, void*);
REGISTER_UMOCK_ALIAS_TYPE(ssize_t, long);
REGISTER_UMOCK_ALIAS_TYPE(SOCKET_TRANSPORT_HANDLE, void*);
REGISTER_UMOCK_ALIAS_TYPE(SOCKET_HANDLE, int);
REGISTER_TYPE(ASYNC_SOCKET_OPEN_RESULT, ASYNC_SOCKET_OPEN_RESULT);
REGISTER_TYPE(ASYNC_SOCKET_SEND_RESULT, ASYNC_SOCKET_SEND_RESULT);
REGISTER_TYPE(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_RESULT);
REGISTER_TYPE(ASYNC_SOCKET_NOTIFY_IO_RESULT, ASYNC_SOCKET_NOTIFY_IO_RESULT);
REGISTER_TYPE(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT);
REGISTER_TYPE(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT);
}
TEST_SUITE_CLEANUP(suite_cleanup)
@ -417,7 +428,7 @@ TEST_FUNCTION(async_socket_open_async_with_NULL_async_socket_fails)
}
// Tests_SRS_ASYNC_SOCKET_LINUX_11_003: [ If socket_handle is INVALID_SOCKET, async_socket_open_async shall fail and return NULL. ]
TEST_FUNCTION(async_socket_open_async_with_INVALID_SOCKET_fails)
TEST_FUNCTION(async_socket_open_async_with_NULL_socket_fails)
{
// arrange
ASYNC_SOCKET_HANDLE async_socket = async_socket_create(test_execution_engine);
@ -425,7 +436,7 @@ TEST_FUNCTION(async_socket_open_async_with_INVALID_SOCKET_fails)
umock_c_reset_all_calls();
// act
int result = async_socket_open_async(async_socket, INVALID_SOCKET, test_on_open_complete, test_callback_ctx);
int result = async_socket_open_async(async_socket, NULL, test_on_open_complete, test_callback_ctx);
// assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
@ -584,7 +595,6 @@ TEST_FUNCTION(async_socket_close_with_NULL_returns)
// Tests_SRS_ASYNC_SOCKET_LINUX_11_036: [ Otherwise, async_socket_close shall switch the state to CLOSING. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_037: [ async_socket_close shall wait for all executing async_socket_send_async and async_socket_receive_async APIs. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_039: [ async_socket_close shall call close on the underlying socket. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_041: [ async_socket_close shall set the state to closed. ]
TEST_FUNCTION(async_socket_close_reverses_the_actions_from_open)
{
@ -649,7 +659,6 @@ TEST_FUNCTION(async_socket_close_after_close_returns)
async_socket_destroy(async_socket);
}
// Tests_SRS_ASYNC_SOCKET_LINUX_11_039: [ async_socket_close shall call close on the underlying socket. ]
TEST_FUNCTION(async_socket_close_after_open_and_recv)
{
// arrange
@ -667,8 +676,9 @@ TEST_FUNCTION(async_socket_close_after_open_and_recv)
STRICT_EXPECTED_CALL(interlocked_compare_exchange(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket))
.SetReturn((SOCKET_HANDLE)0x4242);
STRICT_EXPECTED_CALL(completion_port_remove(IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_close(test_socket));
STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
@ -979,7 +989,7 @@ TEST_FUNCTION(async_socket_send_async_after_close_fails)
}
// Tests_SRS_ASYNC_SOCKET_LINUX_04_004: [ async_socket_send_async shall call the on_send callback to send the buffer. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling socket_transport_send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_053: [ async_socket_send_async shall continue to send the data until the payload length has been sent. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_062: [ On success, async_socket_send_async shall return ASYNC_SOCKET_SEND_SYNC_OK. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_061: [ If the send is successful, async_socket_send_async shall call the on_send_complete with on_send_complete_context and ASYNC_SOCKET_SEND_SYNC_OK. ]
@ -995,19 +1005,21 @@ TEST_FUNCTION(async_socket_send_async_succeeds)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = payload_buffers[0].length;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL));
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(test_on_send_complete(test_callback_ctx, ASYNC_SOCKET_SEND_OK));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
// act
ASYNC_SOCKET_SEND_SYNC_RESULT result;
result = async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx);
result = async_socket_send_async(async_socket, payload_buffers, 1, test_on_send_complete, test_callback_ctx);
// assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
@ -1018,7 +1030,7 @@ TEST_FUNCTION(async_socket_send_async_succeeds)
}
// Tests_SRS_ASYNC_SOCKET_LINUX_04_004: [ async_socket_send_async shall call the on_send callback to send the buffer. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling socket_transport_send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_053: [ async_socket_send_async shall continue to send the data until the payload length has been sent. ]
TEST_FUNCTION(async_socket_send_async_multiple_sends_succeeds)
{
@ -1031,21 +1043,26 @@ TEST_FUNCTION(async_socket_send_async_multiple_sends_succeeds)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
ssize_t send_amt = payload_buffers[0].length/2;
uint32_t send_amt = payload_buffers[0].length/2;
uint32_t other_amt = payload_buffers[0].length - send_amt;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(send_amt);
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL));
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&other_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(test_on_send_complete(test_callback_ctx, ASYNC_SOCKET_SEND_OK));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
// act
ASYNC_SOCKET_SEND_SYNC_RESULT result;
result = async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx);
result = async_socket_send_async(async_socket, payload_buffers, 1, test_on_send_complete, test_callback_ctx);
// assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
@ -1056,7 +1073,7 @@ TEST_FUNCTION(async_socket_send_async_multiple_sends_succeeds)
}
// Tests_SRS_ASYNC_SOCKET_LINUX_04_004: [ async_socket_send_async shall call the on_send callback to send the buffer. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_052: [ on_socket_send shall attempt to send the data by calling socket_transport_send with the MSG_NOSIGNAL flag to ensure SIGPIPE is not generated on errors. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_053: [ async_socket_send_async shall continue to send the data until the payload length has been sent. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_057: [ The context shall then be added to the epoll system by calling epoll_ctl with EPOLL_CTL_MOD and `event_complete_callback` as the callback. ]
TEST_FUNCTION(async_socket_send_async_multiple_sends_WOULDBLOCK_succeeds)
@ -1070,17 +1087,22 @@ TEST_FUNCTION(async_socket_send_async_multiple_sends_WOULDBLOCK_succeeds)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
ssize_t send_amt = payload_buffers[0].length/2;
uint32_t send_amt = payload_buffers[0].length/2;
uint32_t other_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, payload_buffers[0].buffer, payload_buffers[0].length, MSG_NOSIGNAL))
.SetReturn(send_amt);
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, payload_buffers[0].buffer + send_amt, payload_buffers[0].length - send_amt, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&other_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(IGNORED_ARG))
.SetReturn((SOCKET_HANDLE)0x4242);
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
@ -1088,7 +1110,7 @@ TEST_FUNCTION(async_socket_send_async_multiple_sends_WOULDBLOCK_succeeds)
// act
errno = EWOULDBLOCK;
ASYNC_SOCKET_SEND_SYNC_RESULT result;
result = async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx);
result = async_socket_send_async(async_socket, payload_buffers, 1, test_on_send_complete, test_callback_ctx);
// assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
@ -1111,20 +1133,22 @@ TEST_FUNCTION(async_socket_send_async_with_NULL_on_send_complete_context_succeed
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = payload_buffers[0].length;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL));
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(test_on_send_complete(NULL, ASYNC_SOCKET_SEND_OK));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
// act
ASYNC_SOCKET_SEND_SYNC_RESULT result;
result = async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, NULL);
result = async_socket_send_async(async_socket, payload_buffers, 1, test_on_send_complete, NULL);
LogInfo("the result of socket send %d", result);
// assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, result);
@ -1133,6 +1157,7 @@ TEST_FUNCTION(async_socket_send_async_with_NULL_on_send_complete_context_succeed
async_socket_destroy(async_socket);
}
// Tests_SRS_ASYNC_SOCKET_LINUX_11_063: [ If any error occurs, async_socket_send_async shall fail and return ASYNC_SOCKET_SEND_SYNC_ERROR. ]
TEST_FUNCTION(when_underlying_calls_fail_async_socket_send_async_fails)
{
@ -1145,12 +1170,13 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_send_async_fails)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
@ -1166,7 +1192,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_send_async_fails)
async_socket_destroy(async_socket);
}
// Tests_SRS_ASYNC_SOCKET_LINUX_11_054: [ If the send fails to send the data, async_socket_send_async shall do the following: ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_054: [ If socket_transport_send fails to send the data, async_socket_send_async shall do the following: ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_055: [ If the errno value is EAGAIN or EWOULDBLOCK. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_056: [ async_socket_send_async shall create a context for the send where the payload, on_send_complete and on_send_complete_context shall be stored. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_057: [ The context shall then be added to the completion port system by calling completion_port_add with EPOLL_CTL_MOD and `event_complete_callback` as the callback. ]
@ -1182,14 +1208,17 @@ TEST_FUNCTION(when_errno_for_send_returns_EWOULDBLOCK_it_uses_completion_port_tr
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t));
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket))
.SetReturn((SOCKET_HANDLE)0x4242);
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
@ -1219,12 +1248,13 @@ TEST_FUNCTION(when_errno_for_send_returns_ECONNRESET_async_socket_send_async_ret
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
@ -1253,12 +1283,13 @@ TEST_FUNCTION(when_errno_for_send_returns_error_async_socket_send_async_returns_
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
@ -1640,7 +1671,7 @@ TEST_FUNCTION(async_socket_receive_async_with_NULL_on_recv_complete_context_succ
setup_async_socket_receive_async_mocks();
// act
int result = async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, NULL);
int result = async_socket_receive_async(async_socket, payload_buffers, 1, test_on_receive_complete, NULL);
// assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
@ -1665,7 +1696,18 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_receive_async_fails)
payload_buffers[0].length = sizeof(payload_bytes);
umock_c_reset_all_calls();
setup_async_socket_receive_async_mocks();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG))
.CallCannotFail();
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0))
.CallCannotFail();
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(ASYNC_SOCKET_BUFFER)))
.CallCannotFail();
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLIN | EPOLLRDHUP | EPOLLONESHOT, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG))
.CallCannotFail();
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG))
.CallCannotFail();
STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG));
umock_c_negative_tests_snapshot();
errno = 0;
@ -1678,7 +1720,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_receive_async_fails)
umock_c_negative_tests_fail_call(index);
// act
int result = async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, NULL);
int result = async_socket_receive_async(async_socket, payload_buffers, 1, test_on_receive_complete, NULL);
// assert
ASSERT_ARE_NOT_EQUAL(int, 0, result, "On failed call %zu", index);
@ -1721,7 +1763,7 @@ TEST_FUNCTION(event_complete_func_context_NULL_fail)
// Tests_SRS_ASYNC_SOCKET_LINUX_11_082: [ If COMPLETION_PORT_EPOLL_ACTION is COMPLETION_PORT_EPOLL_EPOLLIN, event_complete_callback shall do the following: ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_083: [ Otherwise event_complete_callback shall call the on_recv callback with the recv_buffer buffer and length and do the following: ]
// Tests_SRS_ASYNC_SOCKET_LINUX_04_007: [ on_socket_recv shall attempt to receive data by calling the system recv socket API. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_04_007: [ on_socket_recv shall attempt to receive data by calling the socket_transport_receive API. ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_088: [ If the recv size < 0, then: ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_092: [ If the recv size > 0, if we have another buffer to fill then we will attempt another read, otherwise we shall call on_receive_complete callback with the on_receive_complete_context and ASYNC_SOCKET_RECEIVE_OK ]
// Tests_SRS_ASYNC_SOCKET_LINUX_11_093: [ event_complete_callback shall then free the io_context memory. ]
@ -1741,8 +1783,9 @@ TEST_FUNCTION(event_complete_func_EPOLLIN_action)
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(async_socket, payload_buffers, payload_count, test_on_receive_complete, test_callback_ctx));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_recv(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(payload_size);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, IGNORED_ARG, 0, IGNORED_ARG))
.CopyOutArgumentBuffer_bytes_recv(&payload_size, sizeof(uint32_t))
.SetReturn(SOCKET_RECEIVE_OK);
STRICT_EXPECTED_CALL(test_on_receive_complete(test_callback_ctx, ASYNC_SOCKET_RECEIVE_OK, payload_size));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -1770,11 +1813,12 @@ TEST_FUNCTION(event_complete_func_recv_returns_EWOULDBLOCK)
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t payload_count = sizeof(payload_buffers) / sizeof(payload_buffers[0]);
uint32_t payload_size = -1;
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(async_socket, payload_buffers, payload_count, test_on_receive_complete, test_callback_ctx));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_recv(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, IGNORED_ARG, 0, IGNORED_ARG))
.CopyOutArgumentBuffer_bytes_recv(&payload_size, sizeof(uint32_t));
STRICT_EXPECTED_CALL(test_on_receive_complete(test_callback_ctx, ASYNC_SOCKET_RECEIVE_OK, 0));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -1803,11 +1847,12 @@ TEST_FUNCTION(event_complete_func_recv_returns_ECONNRESET)
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t payload_count = sizeof(payload_buffers) / sizeof(payload_buffers[0]);
uint32_t payload_size = -1;
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(async_socket, payload_buffers, payload_count, test_on_receive_complete, test_callback_ctx));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_recv(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, IGNORED_ARG, 0, IGNORED_ARG))
.CopyOutArgumentBuffer_bytes_recv(&payload_size, sizeof(uint32_t));
STRICT_EXPECTED_CALL(test_on_receive_complete(test_callback_ctx, ASYNC_SOCKET_RECEIVE_ABANDONED, 0));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -1837,10 +1882,11 @@ TEST_FUNCTION(event_complete_callback_recv_returns_any_random_error_no)
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t payload_count = sizeof(payload_buffers) / sizeof(payload_buffers[0]);
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(async_socket, payload_buffers, payload_count, test_on_receive_complete, test_callback_ctx));
uint32_t payload_size = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_recv(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, IGNORED_ARG, 0, IGNORED_ARG))
.CopyOutArgumentBuffer_bytes_recv(&payload_size, sizeof(uint32_t));
STRICT_EXPECTED_CALL(test_on_receive_complete(test_callback_ctx, ASYNC_SOCKET_RECEIVE_ERROR, 0));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -1870,10 +1916,12 @@ TEST_FUNCTION(event_complete_func_recv_returns_0_bytes_success)
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t payload_count = sizeof(payload_buffers) / sizeof(payload_buffers[0]);
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(async_socket, payload_buffers, payload_count, test_on_receive_complete, test_callback_ctx));
uint32_t payload_size = 0;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_recv(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(0);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, IGNORED_ARG, 0, IGNORED_ARG))
.CopyOutArgumentBuffer_bytes_recv(&payload_size, sizeof(uint32_t))
.SetReturn(SOCKET_RECEIVE_OK);
STRICT_EXPECTED_CALL(test_on_receive_complete(test_callback_ctx, ASYNC_SOCKET_RECEIVE_ABANDONED, 0));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -2141,14 +2189,15 @@ TEST_FUNCTION(event_complete_func_send_EPOLLRDHUP_and_abandons_the_connection)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t));
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
errno = EWOULDBLOCK;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx));
umock_c_reset_all_calls();
@ -2213,14 +2262,15 @@ TEST_FUNCTION(event_complete_func_send_ABANDONED_and_abandons_the_connection)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t));
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
errno = EWOULDBLOCK;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx));
umock_c_reset_all_calls();
@ -2253,19 +2303,24 @@ TEST_FUNCTION(event_complete_func_send_EPOLLOUT_success)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
errno = EWOULDBLOCK;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx));
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, 1, test_on_send_complete, test_callback_ctx));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL));
send_amt = 2;
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(test_on_send_complete(test_callback_ctx, ASYNC_SOCKET_SEND_OK));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -2293,20 +2348,23 @@ TEST_FUNCTION(event_complete_func_send_EPOLLOUT_abandoned)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
errno = EWOULDBLOCK;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(test_on_send_complete(test_callback_ctx, ASYNC_SOCKET_SEND_ABANDONED));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -2334,20 +2392,23 @@ TEST_FUNCTION(event_complete_func_send_EPOLLOUT_error)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
errno = EWOULDBLOCK;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(test_on_send_complete(test_callback_ctx, ASYNC_SOCKET_SEND_ERROR));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -2375,22 +2436,27 @@ TEST_FUNCTION(event_complete_func_EPOLLOUT_multiple_sends_success)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t payload_size = sizeof(payload_bytes) / sizeof(payload_bytes[0]);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, payload_size, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
errno = EWOULDBLOCK;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, payload_size, MSG_NOSIGNAL))
.SetReturn(2);
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, payload_size-2, MSG_NOSIGNAL));
send_amt = 2;
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t))
.SetReturn(SOCKET_SEND_OK);
STRICT_EXPECTED_CALL(test_on_send_complete(test_callback_ctx, ASYNC_SOCKET_SEND_OK));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
@ -2449,14 +2515,15 @@ TEST_FUNCTION(event_complete_func_send_ERROR_and_error_the_connection)
ASYNC_SOCKET_BUFFER payload_buffers[1];
payload_buffers[0].buffer = payload_bytes;
payload_buffers[0].length = sizeof(payload_bytes);
uint32_t send_amt = -1;
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(mocked_send(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, MSG_NOSIGNAL))
.SetReturn(-1);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, IGNORED_ARG, MSG_NOSIGNAL, NULL))
.CopyOutArgumentBuffer_bytes_sent(&send_amt, sizeof(uint32_t));
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG));
errno = EWOULDBLOCK;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, test_callback_ctx));
umock_c_reset_all_calls();
@ -2654,6 +2721,7 @@ TEST_FUNCTION(async_socket_notify_io_async_succeeds_for_OUT)
// cleanup
async_socket_destroy(async_socket);
free(g_event_callback_ctx);
}
// Tests_SRS_ASYNC_SOCKET_LINUX_04_020: [ If any error occurs, async_socket_notify_io_async shall fail and return a non-zero value. ]
@ -2668,7 +2736,9 @@ TEST_FUNCTION(async_socket_notify_io_async_fails_when_completion_port_add_fails)
STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0));
STRICT_EXPECTED_CALL(malloc(IGNORED_ARG));
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_socket, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket))
.SetReturn((SOCKET_HANDLE)0x4242);
STRICT_EXPECTED_CALL(completion_port_add(test_completion_port, EPOLLOUT, test_handle, IGNORED_ARG, IGNORED_ARG))
.SetReturn(-1);
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG));
@ -2683,6 +2753,7 @@ TEST_FUNCTION(async_socket_notify_io_async_fails_when_completion_port_add_fails)
// cleanup
async_socket_destroy(async_socket);
}
END_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE)

Просмотреть файл

@ -9,7 +9,7 @@
`async_socket_win32` is using the WSA Windows functions with a `PTP_POOL` in order to perform asynchronous socket send and receives.
`async_socket_win32` creates its own threadpool environment.
The `async_socket_win32` takes ownership of the provided `SOCKET_HANDLE` and is responsible for closing it. For that reason, it is not possible to re-open the `async_socket` after closing it. This is due to the fact that the socket is created by some external event, such as accepting an incoming connection and closing the underlying socket is not reversible.
The `async_socket_win32` takes ownership of the provided `SOCKET_TRANSPORT_HANDLE` and is responsible for closing it. For that reason, it is not possible to re-open the `async_socket` after closing it. This is due to the fact that the socket is created by some external event, such as accepting an incoming connection and closing the underlying socket is not reversible.
## Exposed API
@ -155,7 +155,7 @@ MOCKABLE_FUNCTION(, int, async_socket_open_async, ASYNC_SOCKET_HANDLE, async_soc
**SRS_ASYNC_SOCKET_WIN32_01_036: [** `async_socket_open_async` shall set the thread pool for the environment to the pool obtained from the execution engine by calling `SetThreadpoolCallbackPool`. **]**
**SRS_ASYNC_SOCKET_WIN32_01_058: [** `async_socket_open_async` shall create a threadpool IO by calling `CreateThreadpoolIo` and passing `socket_handle`, the callback environment to it and `on_io_complete` as callback. **]**
**SRS_ASYNC_SOCKET_WIN32_01_058: [** `async_socket_open_async` shall create a threadpool IO by calling `CreateThreadpoolIo` and passing `socket_transport_get_underlying_socket`, the callback environment to it and `on_io_complete` as callback. **]**
**SRS_ASYNC_SOCKET_WIN32_01_094: [** `async_socket_open_async` shall set the state to OPEN. **]**
@ -175,8 +175,6 @@ MOCKABLE_FUNCTION(, void, async_socket_close, ASYNC_SOCKET_HANDLE, async_socket)
**SRS_ASYNC_SOCKET_WIN32_01_019: [** Otherwise, `async_socket_close` shall switch the state to CLOSING. **]**
**SRS_ASYNC_SOCKET_WIN32_42_006: [** `async_socket_close` shall call `closesocket` on the underlying socket. **]**
**SRS_ASYNC_SOCKET_WIN32_01_020: [** `async_socket_close` shall wait for all executing `async_socket_send_async` and `async_socket_receive_async` APIs. **]**
**SRS_ASYNC_SOCKET_WIN32_01_021: [** Then `async_socket_close` shall close the async socket. **]**
@ -227,7 +225,7 @@ MOCKABLE_FUNCTION(, ASYNC_SOCKET_SEND_SYNC_RESULT, async_socket_send_async, ASYN
**SRS_ASYNC_SOCKET_WIN32_01_060: [** An asynchronous IO shall be started by calling `StartThreadpoolIo`. **]**
**SRS_ASYNC_SOCKET_WIN32_01_061: [** The `SOCKET_BUFFER` array associated with the context shall be sent by calling `socket_transport_send` and passing to it the `OVERLAPPED` structure with the event that was just created, `dwFlags` set to 0, `lpNumberOfBytesSent` set to NULL and `lpCompletionRoutine` set to NULL. **]**
**SRS_ASYNC_SOCKET_WIN32_01_061: [** The `SOCKET_BUFFER` array associated with the context shall be sent by calling `socket_transport_send` and passing to it the `OVERLAPPED` structure with the event that was just created, `flags` set to 0, and `bytes_sent` set to NULL. **]**
**SRS_ASYNC_SOCKET_WIN32_01_062: [** If `socket_transport_send` fails, `async_socket_send_async` shall call `WSAGetLastError`. **]**
@ -279,7 +277,7 @@ MOCKABLE_FUNCTION(, int, async_socket_receive_async, ASYNC_SOCKET_HANDLE, async_
**SRS_ASYNC_SOCKET_WIN32_01_081: [** An asynchronous IO shall be started by calling `StartThreadpoolIo`. **]**
**SRS_ASYNC_SOCKET_WIN32_01_082: [** A receive shall be started for the `WSABUF` array associated with the context calling `socket_transport_receive` and passing to it the `OVERLAPPED` structure with the event that was just created, `dwFlags` set to 0, `lpNumberOfBytesSent` set to NULL and `lpCompletionRoutine` set to NULL.. **]**
**SRS_ASYNC_SOCKET_WIN32_01_082: [** A receive shall be started for the `WSABUF` array associated with the context calling `socket_transport_receive` and passing to it the `OVERLAPPED` structure with the event that was just created, `flags` set to 0, and `bytes_sent` set to NULL. **]**
**SRS_ASYNC_SOCKET_WIN32_01_054: [** If `socket_transport_receive` fails with `SOCKET_RECEIVE_ERROR`, `async_socket_receive_async` shall call `WSAGetLastError`. **]**

Просмотреть файл

@ -202,8 +202,6 @@ MOCKABLE_FUNCTION(, void, socket_transport_disconnect, SOCKET_TRANSPORT_HANDLE,
**SOCKET_TRANSPORT_WIN32_09_029: [** If `sm_close_begin` does not return `SM_EXEC_GRANTED`, `socket_transport_disconnect` shall fail and return. **]**
**SOCKET_TRANSPORT_WIN32_09_083: [** If `shutdown` does not return 0 on a socket that is not a binding socket, the socket is not valid therefore `socket_transport_disconnect` shall not call `close` **]**
**SOCKET_TRANSPORT_WIN32_09_030: [** `socket_transport_disconnect` shall call `closesocket` to disconnect the connected socket. **]**
**SOCKET_TRANSPORT_WIN32_09_031: [** `socket_transport_disconnect` shall call `sm_close_end`. **]**

Просмотреть файл

@ -16,6 +16,8 @@
#include "c_pal/execution_engine.h"
#include "c_pal/execution_engine_win32.h"
#include "c_pal/timer.h"
#include "c_pal/socket_transport.h"
#include "c_pal/sm.h"
#include "c_pal/async_socket.h"
@ -43,7 +45,7 @@ MU_DEFINE_ENUM_STRINGS(ASYNC_SOCKET_NOTIFY_IO_RESULT, ASYNC_SOCKET_NOTIFY_IO_RES
typedef struct ASYNC_SOCKET_TAG
{
SOCKET_HANDLE socket_handle;
SOCKET_TRANSPORT_HANDLE socket_transport_handle;
EXECUTION_ENGINE_HANDLE execution_engine;
volatile LONG state;
PTP_POOL pool;
@ -78,7 +80,7 @@ typedef struct ASYNC_SOCKET_IO_CONTEXT_TAG
ASYNC_SOCKET_IO_TYPE io_type;
uint32_t total_buffer_bytes;
ASYNC_SOCKET_IO_CONTEXT_UNION io;
WSABUF wsa_buffers[];
SOCKET_BUFFER wsa_buffers[];
} ASYNC_SOCKET_IO_CONTEXT;
static VOID WINAPI on_io_complete(PTP_CALLBACK_INSTANCE instance, PVOID context, PVOID overlapped, ULONG io_result, ULONG_PTR number_of_bytes_transferred, PTP_IO io)
@ -152,6 +154,7 @@ static VOID WINAPI on_io_complete(PTP_CALLBACK_INSTANCE instance, PVOID context,
}
case ERROR_NETNAME_DELETED:
case ERROR_CONNECTION_ABORTED:
case ERROR_OPERATION_ABORTED:
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_42_001: [ If io_result is ERROR_NETNAME_DELETED or ERROR_CONNECTION_ABORTED, the on_receive_complete callback passed to async_socket_receive_async shall be called with on_receive_complete_context as context, ASYNC_SOCKET_RECEIVE_ABANDONED as result and 0 for bytes_received. ]*/
LogError("Receive IO completed with error %lu (socket seems to be closed)", io_result);
@ -220,15 +223,6 @@ static void internal_close(ASYNC_SOCKET_HANDLE async_socket)
(void)WaitOnAddress(&async_socket->pending_api_calls, &current_pending_api_calls, sizeof(current_pending_api_calls), INFINITE);
} while (1);
// Close socket must happen after changing state of the async_socket to not allow any more calls on the socket
// but before the call to WaitForThreadpoolIoCallbacks
LogInfo("async socket is closing, closesocket(%p);", async_socket->socket_handle);
/* Codes_SRS_ASYNC_SOCKET_WIN32_42_006: [ async_socket_close shall call closesocket on the underlying socket. ]*/
(void)closesocket((SOCKET)async_socket->socket_handle);
async_socket->socket_handle = (SOCKET_HANDLE)INVALID_SOCKET;
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_040: [ async_socket_close shall wait for any executing callbacks by calling WaitForThreadpoolIoCallbacks, passing FALSE as fCancelPendingCallbacks. ]*/
WaitForThreadpoolIoCallbacks(async_socket->tp_io, FALSE);
@ -285,6 +279,7 @@ ASYNC_SOCKET_HANDLE async_socket_create(EXECUTION_ENGINE_HANDLE execution_engine
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_035: [ async_socket_create shall obtain the PTP_POOL from the execution engine passed to async_socket_create by calling execution_engine_win32_get_threadpool. ]*/
result->pool = execution_engine_win32_get_threadpool(execution_engine);
result->socket_transport_handle = NULL;
(void)InterlockedExchange(&result->pending_api_calls, 0);
(void)InterlockedExchange(&result->state, (LONG)ASYNC_SOCKET_WIN32_STATE_CLOSED);
@ -334,7 +329,7 @@ void async_socket_destroy(ASYNC_SOCKET_HANDLE async_socket)
}
}
int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE socket_handle, ON_ASYNC_SOCKET_OPEN_COMPLETE on_open_complete, void* on_open_complete_context)
int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_TRANSPORT_HANDLE socket_transport, ON_ASYNC_SOCKET_OPEN_COMPLETE on_open_complete, void* on_open_complete_context)
{
int result;
@ -345,8 +340,8 @@ int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE sock
(async_socket == NULL) ||
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_008: [ If on_open_complete is NULL, async_socket_open_async shall fail and return a non-zero value. ]*/
(on_open_complete == NULL) ||
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_034: [ If socket_handle is INVALID_SOCKET, async_socket_create shall fail and return NULL. ]*/
(SOCKET)socket_handle == INVALID_SOCKET
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_034: [ If socket_transport is NULL, async_socket_open_async shall fail and return a non-zero value. ]*/
(socket_transport == NULL)
)
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_039: [ If any error occurs, async_socket_open_async shall fail and return a non-zero value. ]*/
@ -366,7 +361,7 @@ int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE sock
}
else
{
async_socket->socket_handle = socket_handle;
async_socket->socket_transport_handle = socket_transport;
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_016: [ Otherwise async_socket_open_async shall initialize a thread pool environment by calling InitializeThreadpoolEnvironment. ]*/
InitializeThreadpoolEnvironment(&async_socket->tp_environment);
@ -374,8 +369,8 @@ int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE sock
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_036: [ async_socket_open_async shall set the thread pool for the environment to the pool obtained from the execution engine by calling SetThreadpoolCallbackPool. ]*/
SetThreadpoolCallbackPool(&async_socket->tp_environment, async_socket->pool);
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_058: [ async_socket_open_async shall create a threadpool IO by calling CreateThreadpoolIo and passing socket_handle, the callback environment to it and on_io_complete as callback. ]*/
async_socket->tp_io = CreateThreadpoolIo(async_socket->socket_handle, on_io_complete, NULL, &async_socket->tp_environment);
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_058: [ async_socket_open_async shall create a threadpool IO by calling CreateThreadpoolIo and passing socket_transport_get_underlying_socket, the callback environment to it and on_io_complete as callback. ]*/
async_socket->tp_io = CreateThreadpoolIo((HANDLE)socket_transport_get_underlying_socket(async_socket->socket_transport_handle), on_io_complete, NULL, &async_socket->tp_environment);
if (async_socket->tp_io == NULL)
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_039: [ If any error occurs, async_socket_open_async shall fail and return a non-zero value. ]*/
@ -396,9 +391,6 @@ int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE sock
goto all_ok;
}
async_socket->socket_handle = (SOCKET_HANDLE)INVALID_SOCKET;
DestroyThreadpoolEnvironment(&async_socket->tp_environment);
(void)InterlockedExchange(&async_socket->state, (LONG)ASYNC_SOCKET_WIN32_STATE_CLOSED);
@ -528,13 +520,13 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_056: [ async_socket_send_async shall set the WSABUF items to point to the memory/length of the buffers in payload. ]*/
for (i = 0; i < buffer_count; i++)
{
send_context->wsa_buffers[i].buf = buffers[i].buffer;
send_context->wsa_buffers[i].len = buffers[i].length;
send_context->wsa_buffers[i].buffer = buffers[i].buffer;
send_context->wsa_buffers[i].length = buffers[i].length;
}
(void)memset(&send_context->overlapped, 0, sizeof(send_context->overlapped));
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_057: [ An event to be used for the OVERLAPPED structure passed to WSASend shall be created and stored in the context. ]*/
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_057: [ An event to be used for the OVERLAPPED structure passed to socket_transport_send shall be created and stored in the context. ]*/
send_context->overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (send_context->overlapped.hEvent == NULL)
{
@ -544,7 +536,7 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
}
else
{
int wsa_send_result;
SOCKET_SEND_RESULT socket_transport_send_result;
int wsa_last_error;
send_context->io_type = ASYNC_SOCKET_IO_TYPE_SEND;
@ -558,22 +550,23 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
LogVerbose("Starting send of %" PRIu32 " bytes at %lf", total_buffer_bytes, timer_global_get_elapsed_us());
#endif
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_061: [ The WSABUF array associated with the context shall be sent by calling WSASend and passing to it the OVERLAPPED structure with the event that was just created, dwFlags set to 0, lpNumberOfBytesSent set to NULL and lpCompletionRoutine set to NULL. ]*/
wsa_send_result = WSASend((SOCKET)async_socket->socket_handle, send_context->wsa_buffers, buffer_count, NULL, 0, &send_context->overlapped, NULL);
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_061: [ The SOCKET_BUFFER array associated with the context shall be sent by calling socket_transport_send and passing to it the OVERLAPPED structure with the event that was just created, flags set to 0, and bytes_sent set to NULL. ]*/
socket_transport_send_result = socket_transport_send(async_socket->socket_transport_handle, send_context->wsa_buffers, buffer_count, NULL, 0, &send_context->overlapped);
switch (wsa_send_result)
switch (socket_transport_send_result)
{
default:
case SOCKET_SEND_ERROR:
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_106: [ If WSASend fails with any other error, async_socket_send_async shall call CancelThreadpoolIo and return ASYNC_SOCKET_SEND_SYNC_ERROR. ]*/
LogLastError("WSASend failed with %d", wsa_send_result);
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_106: [ If socket_transport_send fails with any other error, async_socket_send_async shall call CancelThreadpoolIo and return ASYNC_SOCKET_SEND_SYNC_ERROR. ]*/
LogLastError("socket_transport_send failed with %d", socket_transport_send_result);
result = ASYNC_SOCKET_SEND_SYNC_ERROR;
break;
}
case SOCKET_ERROR:
case SOCKET_SEND_FAILED:
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_062: [ If WSASend fails, async_socket_send_async shall call WSAGetLastError. ]*/
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_062: [ If socket_transport_send fails, async_socket_send_async shall call WSAGetLastError. ]*/
wsa_last_error = WSAGetLastError();
switch (wsa_last_error)
@ -581,7 +574,7 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
default:
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_029: [ If any error occurs, async_socket_send_async shall fail and return ASYNC_SOCKET_SEND_SYNC_ERROR. ]*/
LogLastError("WSASend failed with %d, WSAGetLastError returned %lu", wsa_send_result, (unsigned long)wsa_last_error);
LogLastError("socket_transport_send failed with %d, WSAGetLastError returned %lu", socket_transport_send_result, (unsigned long)wsa_last_error);
result = ASYNC_SOCKET_SEND_SYNC_ERROR;
break;
@ -589,7 +582,7 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
case WSAECONNRESET:
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_42_002: [ If WSAGetLastError returns WSAECONNRESET, async_socket_send_async shall fail and return ASYNC_SOCKET_SEND_SYNC_NOT_OPEN. ]*/
LogLastError("WSASend failed with %d, WSAGetLastError returned %lu", wsa_send_result, (unsigned long)wsa_last_error);
LogLastError("socket_transport_send failed with %d, WSAGetLastError returned %lu", socket_transport_send_result, (unsigned long)wsa_last_error);
result = ASYNC_SOCKET_SEND_SYNC_NOT_OPEN;
break;
@ -604,7 +597,7 @@ ASYNC_SOCKET_SEND_SYNC_RESULT async_socket_send_async(ASYNC_SOCKET_HANDLE async_
}
break;
}
case 0:
case SOCKET_SEND_OK:
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_045: [ On success, async_socket_send_async shall return ASYNC_SOCKET_SEND_SYNC_OK. ]*/
#ifdef ENABLE_SOCKET_LOGGING
@ -735,8 +728,8 @@ int async_socket_receive_async(ASYNC_SOCKET_HANDLE async_socket, ASYNC_SOCKET_BU
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_079: [ async_socket_receive_async shall set the WSABUF items to point to the memory/length of the buffers in payload. ]*/
for (i = 0; i < buffer_count; i++)
{
receive_context->wsa_buffers[i].buf = payload[i].buffer;
receive_context->wsa_buffers[i].len = payload[i].length;
receive_context->wsa_buffers[i].buffer = payload[i].buffer;
receive_context->wsa_buffers[i].length = payload[i].length;
}
(void)memset(&receive_context->overlapped, 0, sizeof(receive_context->overlapped));
@ -751,7 +744,7 @@ int async_socket_receive_async(ASYNC_SOCKET_HANDLE async_socket, ASYNC_SOCKET_BU
}
else
{
int wsa_receive_result;
SOCKET_RECEIVE_RESULT socket_transport_receive_result;
int wsa_last_error;
DWORD flags = 0;
@ -766,23 +759,23 @@ int async_socket_receive_async(ASYNC_SOCKET_HANDLE async_socket, ASYNC_SOCKET_BU
LogVerbose("Starting receive at %lf", timer_global_get_elapsed_us());
#endif
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_082: [ A receive shall be started for the WSABUF array associated with the context calling WSARecv and passing to it the OVERLAPPED structure with the event that was just created, dwFlags set to 0, lpNumberOfBytesSent set to NULL and lpCompletionRoutine set to NULL. ]*/
wsa_receive_result = WSARecv((SOCKET)async_socket->socket_handle, receive_context->wsa_buffers, buffer_count, NULL, &flags, &receive_context->overlapped, NULL);
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_082: [ A receive shall be started for the WSABUF array associated with the context calling socket_transport_receive and passing to it the OVERLAPPED structure with the event that was just created, flags set to 0, and bytes_sent set to NULL. ]*/
socket_transport_receive_result = socket_transport_receive(async_socket->socket_transport_handle, receive_context->wsa_buffers, buffer_count, 0, flags, &receive_context->overlapped);
if ((wsa_receive_result != 0) && (wsa_receive_result != SOCKET_ERROR))
if ((socket_transport_receive_result != SOCKET_RECEIVE_OK) && (socket_transport_receive_result != SOCKET_RECEIVE_ERROR) && (socket_transport_receive_result != SOCKET_RECEIVE_WOULD_BLOCK))
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_105: [ If WSARecv fails with any other error, async_socket_receive_async shall call CancelThreadpoolIo and return a non-zero value. ]*/
LogLastError("WSARecv failed with %d", wsa_receive_result);
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_105: [ If socket_transport_receive fails with any other error, async_socket_receive_async shall call CancelThreadpoolIo and return a non-zero value. ]*/
LogLastError("socket_transport_receive failed with %d", socket_transport_receive_result);
CancelThreadpoolIo(async_socket->tp_io);
result = MU_FAILURE;
}
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_054: [ If WSARecv fails with SOCKET_ERROR, async_socket_receive_async shall call WSAGetLastError. ]*/
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_054: [ If socket_transport_receive fails with SOCKET_RECEIVE_ERROR, async_socket_receive_async shall call WSAGetLastError. ]*/
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_055: [ If WSAGetLastError returns IO_PENDING, it shall be not treated as an error. ]*/
else if ((wsa_receive_result == SOCKET_ERROR) && ((wsa_last_error = WSAGetLastError()) != WSA_IO_PENDING))
else if ((socket_transport_receive_result == SOCKET_RECEIVE_ERROR) && ((wsa_last_error = WSAGetLastError()) != WSA_IO_PENDING))
{
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_084: [ If any error occurs, async_socket_receive_async shall fail and return a non-zero value. ]*/
LogLastError("WSARecv failed with %d, WSAGetLastError returned %lu", wsa_receive_result, wsa_last_error);
LogLastError("socket_transport_receive failed with %d, WSAGetLastError returned %lu", socket_transport_receive_result, wsa_last_error);
/* Codes_SRS_ASYNC_SOCKET_WIN32_01_099: [ If WSAGetLastError returns any other error, async_socket_receive_async shall call CancelThreadpoolIo. ]*/
CancelThreadpoolIo(async_socket->tp_io);

Просмотреть файл

@ -381,18 +381,10 @@ void socket_transport_disconnect(SOCKET_TRANSPORT_HANDLE socket_transport)
SM_RESULT close_result = sm_close_begin(socket_transport->sm);
if (close_result == SM_EXEC_GRANTED)
{
// Codes_SOCKET_TRANSPORT_WIN32_09_083: [ If shutdown does not return 0 on a socket that is not a binding socket, the socket is not valid therefore socket_transport_disconnect shall not call close ]
if (socket_transport->type != SOCKET_BINDING && shutdown(socket_transport->socket, SD_BOTH) != 0)
// Codes_SOCKET_TRANSPORT_WIN32_09_030: [ socket_transport_disconnect shall call closesocket to disconnect the connected socket. ]
if (closesocket(socket_transport->socket) != 0)
{
LogLastError("shutdown failed on socket: %" PRI_SOCKET "", socket_transport->socket);
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_030: [ socket_transport_disconnect shall call closesocket to disconnect the connected socket. ]
if (closesocket(socket_transport->socket) != 0)
{
LogLastError("Failure in closesocket %" PRI_SOCKET "", socket_transport->socket);
}
LogLastError("Failure in closesocket %" PRI_SOCKET "", socket_transport->socket);
}
// Codes_SOCKET_TRANSPORT_WIN32_09_031: [ socket_transport_disconnect shall call sm_close_end. ]
sm_close_end(socket_transport->sm);

Просмотреть файл

@ -1,23 +0,0 @@
#Copyright (c) Microsoft. All rights reserved.
set(theseTestsName async_socket_win32_int)
set(${theseTestsName}_test_files
${theseTestsName}.c
)
set(${theseTestsName}_c_files
)
set(${theseTestsName}_h_files
)
build_test_artifacts(${theseTestsName} "tests/c_pal/win32" ADDITIONAL_LIBS pal_interfaces c_pal)
if("${building}" STREQUAL "exe")
set_target_properties(${theseTestsName}_exe_${CMAKE_PROJECT_NAME} PROPERTIES LINK_FLAGS "/ignore:4217")
endif()
if("${building}" STREQUAL "dll")
set_target_properties(${theseTestsName}_dll_${CMAKE_PROJECT_NAME} PROPERTIES LINK_FLAGS "/ignore:4217")
endif()

Просмотреть файл

@ -1,331 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
#include <stdlib.h>
#include <inttypes.h>
#include "winsock2.h"
#include "ws2tcpip.h"
#include "windows.h"
#include "testrunnerswitcher.h"
#include "macro_utils/macro_utils.h"
#include "c_pal/async_socket.h"
#include "c_pal/execution_engine.h"
#include "c_pal/gballoc_hl.h"
#include "c_pal/execution_engine_win32.h"
#define TEST_PORT 4266
TEST_DEFINE_ENUM_TYPE(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_RESULT_VALUES)
TEST_DEFINE_ENUM_TYPE(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_RESULT_VALUES)
static void on_open_complete(void* context, ASYNC_SOCKET_OPEN_RESULT open_result)
{
HANDLE* event = (HANDLE*)context;
(void)SetEvent(*event);
(void)open_result;
}
static void on_send_complete(void* context, ASYNC_SOCKET_SEND_RESULT send_result)
{
HANDLE* event = (HANDLE*)context;
(void)SetEvent(*event);
(void)send_result;
}
static void on_receive_complete(void* context, ASYNC_SOCKET_RECEIVE_RESULT receive_result, uint32_t bytes_received)
{
HANDLE* event = (HANDLE*)context;
(void)SetEvent(*event);
(void)receive_result;
(void)bytes_received;
}
static void on_receive_complete_with_error(void* context, ASYNC_SOCKET_RECEIVE_RESULT receive_result, uint32_t bytes_received)
{
HANDLE* event = (HANDLE*)context;
ASSERT_ARE_EQUAL(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_ABANDONED, receive_result);
(void)SetEvent(*event);
(void)receive_result;
(void)bytes_received;
}
static void setup_sockets(SOCKET* client_socket, SOCKET* server_socket, SOCKET* listen_socket)
{
// create a server socket
*listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ASSERT_ARE_NOT_EQUAL(void_ptr, INVALID_SOCKET, listen_socket);
struct sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = INADDR_ANY;
service.sin_port = htons((u_short)TEST_PORT);
// bind it
ASSERT_ARE_EQUAL(int, 0, bind(*listen_socket, (SOCKADDR *)&service, sizeof(service)));
// set it to async IO
u_long mode = 1;
ASSERT_ARE_EQUAL(int, 0, ioctlsocket(*listen_socket, FIONBIO, &mode));
// start listening
ASSERT_ARE_EQUAL(int, 0, listen(*listen_socket, SOMAXCONN));
// create a client socket
*client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ASSERT_ARE_NOT_EQUAL(void_ptr, INVALID_SOCKET, *client_socket);
char portString[16];
ADDRINFO addrHint = { 0 };
ADDRINFO* addrInfo = NULL;
addrHint.ai_family = AF_INET;
addrHint.ai_socktype = SOCK_STREAM;
addrHint.ai_protocol = 0;
ASSERT_IS_TRUE(sprintf(portString, "%u", TEST_PORT) >= 0);
ASSERT_ARE_EQUAL(int, 0, getaddrinfo("localhost", portString, &addrHint, &addrInfo));
// connect
ASSERT_ARE_EQUAL(int, 0, connect(*client_socket, addrInfo->ai_addr, (int)addrInfo->ai_addrlen));
// set async
ASSERT_ARE_EQUAL(int, 0, ioctlsocket(*listen_socket, FIONBIO, &mode));
// accept it on the server side
fd_set read_fds;
int select_result;
struct timeval timeout;
read_fds.fd_array[0] = *listen_socket;
read_fds.fd_count = 1;
timeout.tv_usec = 1000 * 100;
timeout.tv_sec = 0;
select_result = select(0, &read_fds, NULL, NULL, &timeout);
ASSERT_ARE_NOT_EQUAL(int, SOCKET_ERROR, select_result);
*server_socket = accept(*listen_socket, NULL, NULL);
ASSERT_ARE_NOT_EQUAL(void_ptr, INVALID_SOCKET, *server_socket);
ASSERT_ARE_EQUAL(int, 0, ioctlsocket(*server_socket, FIONBIO, &mode));
}
BEGIN_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE)
TEST_SUITE_INITIALIZE(suite_init)
{
ASSERT_ARE_EQUAL(int, 0, gballoc_hl_init(NULL, NULL));
WSADATA wsaData;
ASSERT_ARE_EQUAL(int, 0, WSAStartup(MAKEWORD(2, 2), &wsaData));
}
TEST_SUITE_CLEANUP(suite_cleanup)
{
(void)WSACleanup();
gballoc_hl_deinit();
}
TEST_FUNCTION_INITIALIZE(method_init)
{
}
TEST_FUNCTION_CLEANUP(method_cleanup)
{
}
TEST_FUNCTION(send_and_receive_1_byte_succeeds)
{
// assert
// create an execution engine
EXECUTION_ENGINE_PARAMETERS execution_engine_parameters = { 4, 0 };
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET client_socket;
SOCKET server_socket;
SOCKET listen_socket;
setup_sockets(&client_socket, &server_socket, &listen_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE server_async_socket = async_socket_create(execution_engine);
ASYNC_SOCKET_HANDLE client_async_socket = async_socket_create(execution_engine);
// open
HANDLE server_open_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(server_open_event);
HANDLE client_open_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(client_open_event);
ASSERT_ARE_EQUAL(int, 0, async_socket_open_async(server_async_socket, (SOCKET_HANDLE)server_socket, on_open_complete, &server_open_event));
ASSERT_ARE_EQUAL(int, 0, async_socket_open_async(client_async_socket, (SOCKET_HANDLE)client_socket, on_open_complete, &client_open_event));
// wait for open to complete
ASSERT_IS_TRUE(WaitForSingleObject(server_open_event, INFINITE) == WAIT_OBJECT_0);
ASSERT_IS_TRUE(WaitForSingleObject(client_open_event, INFINITE) == WAIT_OBJECT_0);
uint8_t send_payload[] = { 0x42, 0x43 };
uint8_t receive_buffer[2];
ASYNC_SOCKET_BUFFER send_payload_buffers[1];
send_payload_buffers[0].buffer = send_payload;
send_payload_buffers[0].length = sizeof(send_payload);
ASYNC_SOCKET_BUFFER receive_payload_buffers[1];
receive_payload_buffers[0].buffer = receive_buffer;
receive_payload_buffers[0].length = sizeof(receive_buffer);
HANDLE send_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(send_event);
HANDLE receive_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(receive_event);
// act (send one byte and receive it)
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(server_async_socket, send_payload_buffers, 1, on_send_complete, &send_event));
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(client_async_socket, receive_payload_buffers, 1, on_receive_complete, &receive_event));
// assert
ASSERT_IS_TRUE(WaitForSingleObject(send_event, INFINITE) == WAIT_OBJECT_0);
ASSERT_IS_TRUE(WaitForSingleObject(receive_event, INFINITE) == WAIT_OBJECT_0);
// cleanup
(void)CloseHandle(send_event);
(void)CloseHandle(receive_event);
(void)CloseHandle(client_open_event);
(void)CloseHandle(server_open_event);
async_socket_close(server_async_socket);
async_socket_close(client_async_socket);
closesocket(server_socket);
closesocket(listen_socket);
closesocket(client_socket);
async_socket_destroy(server_async_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
}
TEST_FUNCTION(receive_and_send_2_buffers_succeeds)
{
// assert
// create an execution engine
EXECUTION_ENGINE_PARAMETERS execution_engine_parameters = { 4, 0 };
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET client_socket;
SOCKET server_socket;
SOCKET listen_socket;
setup_sockets(&client_socket, &server_socket, &listen_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE server_async_socket = async_socket_create(execution_engine);
ASYNC_SOCKET_HANDLE client_async_socket = async_socket_create(execution_engine);
// open
HANDLE server_open_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(server_open_event);
HANDLE client_open_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(client_open_event);
ASSERT_ARE_EQUAL(int, 0, async_socket_open_async(server_async_socket, (SOCKET_HANDLE)server_socket, on_open_complete, &server_open_event));
ASSERT_ARE_EQUAL(int, 0, async_socket_open_async(client_async_socket, (SOCKET_HANDLE)client_socket, on_open_complete, &client_open_event));
// wait for open to complete
ASSERT_IS_TRUE(WaitForSingleObject(server_open_event, INFINITE) == WAIT_OBJECT_0);
ASSERT_IS_TRUE(WaitForSingleObject(client_open_event, INFINITE) == WAIT_OBJECT_0);
uint8_t send_payload_1[] = { 0x42, 0x43 };
uint8_t send_payload_2[] = { 0x02 };
uint8_t receive_buffer_1[1];
uint8_t receive_buffer_2[2];
ASYNC_SOCKET_BUFFER send_payload_buffers[2];
send_payload_buffers[0].buffer = send_payload_1;
send_payload_buffers[0].length = sizeof(send_payload_1);
send_payload_buffers[1].buffer = send_payload_2;
send_payload_buffers[1].length = sizeof(send_payload_2);
ASYNC_SOCKET_BUFFER receive_payload_buffers[2];
receive_payload_buffers[0].buffer = receive_buffer_1;
receive_payload_buffers[0].length = sizeof(receive_buffer_1);
receive_payload_buffers[1].buffer = receive_buffer_2;
receive_payload_buffers[1].length = sizeof(receive_buffer_2);
HANDLE send_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(send_event);
HANDLE receive_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(receive_event);
// act (send one byte and receive it)
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(client_async_socket, receive_payload_buffers, 2, on_receive_complete, &receive_event));
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(server_async_socket, send_payload_buffers, 2, on_send_complete, &send_event));
// assert
ASSERT_IS_TRUE(WaitForSingleObject(send_event, INFINITE) == WAIT_OBJECT_0);
ASSERT_IS_TRUE(WaitForSingleObject(receive_event, INFINITE) == WAIT_OBJECT_0);
// cleanup
(void)CloseHandle(send_event);
(void)CloseHandle(receive_event);
(void)CloseHandle(client_open_event);
(void)CloseHandle(server_open_event);
async_socket_close(server_async_socket);
async_socket_close(client_async_socket);
closesocket(server_socket);
closesocket(listen_socket);
closesocket(client_socket);
async_socket_destroy(server_async_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
}
TEST_FUNCTION(when_server_socket_is_closed_receive_errors_on_client_side)
{
// assert
// create an execution engine
EXECUTION_ENGINE_PARAMETERS execution_engine_parameters = { 4, 0 };
EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(&execution_engine_parameters);
ASSERT_IS_NOT_NULL(execution_engine);
SOCKET client_socket;
SOCKET server_socket;
SOCKET listen_socket;
setup_sockets(&client_socket, &server_socket, &listen_socket);
// create the async socket object
ASYNC_SOCKET_HANDLE client_async_socket = async_socket_create(execution_engine);
// open
HANDLE client_open_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(client_open_event);
ASSERT_ARE_EQUAL(int, 0, async_socket_open_async(client_async_socket, (SOCKET_HANDLE)client_socket, on_open_complete, &client_open_event));
// wait for open to complete
ASSERT_IS_TRUE(WaitForSingleObject(client_open_event, INFINITE) == WAIT_OBJECT_0);
uint8_t receive_buffer_1[1];
ASYNC_SOCKET_BUFFER receive_payload_buffers[1];
receive_payload_buffers[0].buffer = receive_buffer_1;
receive_payload_buffers[0].length = sizeof(receive_buffer_1);
HANDLE receive_event = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT_IS_NOT_NULL(receive_event);
// act (send one byte and receive it)
ASSERT_ARE_EQUAL(int, 0, async_socket_receive_async(client_async_socket, receive_payload_buffers, 1, on_receive_complete_with_error, &receive_event));
closesocket(client_socket);
// assert
ASSERT_IS_TRUE(WaitForSingleObject(receive_event, INFINITE) == WAIT_OBJECT_0);
// cleanup
(void)CloseHandle(receive_event);
(void)CloseHandle(client_open_event);
async_socket_close(client_async_socket);
closesocket(server_socket);
closesocket(listen_socket);
async_socket_destroy(client_async_socket);
execution_engine_dec_ref(execution_engine);
}
END_TEST_SUITE(TEST_SUITE_NAME_FROM_CMAKE)

Просмотреть файл

@ -16,13 +16,10 @@
#define DestroyThreadpoolEnvironment mocked_DestroyThreadpoolEnvironment
#define CreateEventA mocked_CreateEventA
#define StartThreadpoolIo mocked_StartThreadpoolIo
#define WSASend mocked_WSASend
#define WSAGetLastError mocked_WSAGetLastError
#define CloseHandle mocked_CloseHandle
#define WSARecv mocked_WSARecv
#define WaitForThreadpoolIoCallbacks mocked_WaitForThreadpoolIoCallbacks
#define CancelThreadpoolIo mocked_CancelThreadpoolIo
#define closesocket mocked_closesocket
PTP_IO WINAPI mocked_CreateThreadpoolIo(HANDLE fl, PTP_WIN32_IO_CALLBACK pfnio, PVOID pv, PTP_CALLBACK_ENVIRON pcbe);
void mocked_InitializeThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe);
@ -34,12 +31,9 @@ void mocked_CloseThreadpoolCleanupGroup(PTP_CLEANUP_GROUP ptpcg);
void mocked_DestroyThreadpoolEnvironment(PTP_CALLBACK_ENVIRON pcbe);
HANDLE mocked_CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName);
void mocked_StartThreadpoolIo(PTP_IO pio);
int mocked_WSASend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
int mocked_WSAGetLastError(void);
BOOL mocked_CloseHandle(HANDLE hObject);
int mocked_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
void mocked_WaitForThreadpoolIoCallbacks(PTP_IO pio, BOOL fCancelPendingCallbacks);
void mocked_CancelThreadpoolIo(PTP_IO pio);
int WSAAPI mocked_closesocket(SOCKET s);
#include "../../src/async_socket_win32.c"

Просмотреть файл

@ -4,7 +4,6 @@
#include <stdlib.h>
#include <inttypes.h>
#include "winsock2.h"
#include "ws2tcpip.h"
#include "windows.h"
@ -17,6 +16,7 @@
#include "umock_c/umocktypes_stdint.h"
#include "umock_c/umocktypes_charptr.h"
#include "umock_c/umock_c_negative_tests.h"
#include "umock_c/umocktypes_windows.h"
#define ENABLE_MOCKS
@ -24,6 +24,9 @@
#include "c_pal/gballoc_hl_redirect.h"
#include "c_pal/execution_engine.h"
#include "c_pal/execution_engine_win32.h"
#include "c_pal/string_utils.h"
#include "c_pal/socket_transport.h"
#include "c_pal/socket_handle.h"
#undef ENABLE_MOCKS
@ -31,9 +34,14 @@
#include "c_pal/async_socket.h"
static SOCKET_HANDLE test_socket = (SOCKET_HANDLE)0x4242;
static EXECUTION_ENGINE_HANDLE test_execution_engine = (EXECUTION_ENGINE_HANDLE)0x4243;
static PTP_POOL test_pool = (PTP_POOL)0x4244;
static SOCKET_TRANSPORT_HANDLE test_socket = (SOCKET_TRANSPORT_HANDLE)0x4242;
#define TEST_PORT 4466
#define TEST_CONN_TIMEOUT 10000
static uint16_t g_port_num = TEST_PORT;
MU_DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES)
@ -49,6 +57,11 @@ IMPLEMENT_UMOCK_C_ENUM_TYPE(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYN
TEST_DEFINE_ENUM_TYPE(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_RESULT_VALUES)
IMPLEMENT_UMOCK_C_ENUM_TYPE(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_RESULT_VALUES)
TEST_DEFINE_ENUM_TYPE(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT_VALUES)
IMPLEMENT_UMOCK_C_ENUM_TYPE(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT_VALUES)
TEST_DEFINE_ENUM_TYPE(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES)
IMPLEMENT_UMOCK_C_ENUM_TYPE(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT_VALUES)
static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code)
{
ASSERT_FAIL("umock_c reported error :%" PRI_MU_ENUM "", MU_ENUM_VALUE(UMOCK_C_ERROR_CODE, error_code));
@ -78,21 +91,15 @@ MOCK_FUNCTION_WITH_CODE(, HANDLE, mocked_CreateEventA, LPSECURITY_ATTRIBUTES, lp
MOCK_FUNCTION_END((HANDLE)real_gballoc_hl_malloc(1))
MOCK_FUNCTION_WITH_CODE(, void, mocked_StartThreadpoolIo, PTP_IO, pio)
MOCK_FUNCTION_END()
MOCK_FUNCTION_WITH_CODE(, int, mocked_WSASend, SOCKET, s, LPWSABUF, lpBuffers, DWORD, dwBufferCount, LPDWORD, lpNumberOfBytesSent, DWORD, dwFlags, LPWSAOVERLAPPED, lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE, lpCompletionRoutine)
MOCK_FUNCTION_END(0)
MOCK_FUNCTION_WITH_CODE(, int, mocked_WSAGetLastError)
MOCK_FUNCTION_END(ERROR_SUCCESS)
MOCK_FUNCTION_WITH_CODE(, BOOL, mocked_CloseHandle, HANDLE, hObject)
real_gballoc_hl_free(hObject);
MOCK_FUNCTION_END(TRUE)
MOCK_FUNCTION_WITH_CODE(, BOOL, mocked_WSARecv, SOCKET, s, LPWSABUF, lpBuffers, DWORD, dwBufferCount, LPDWORD, lpNumberOfBytesRecvd, LPDWORD, lpFlags, LPWSAOVERLAPPED, lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE, lpCompletionRoutine)
MOCK_FUNCTION_END(0)
MOCK_FUNCTION_WITH_CODE(, void, mocked_WaitForThreadpoolIoCallbacks, PTP_IO, pio, BOOL, fCancelPendingCallbacks)
MOCK_FUNCTION_END()
MOCK_FUNCTION_WITH_CODE(, void, mocked_CancelThreadpoolIo, PTP_IO, pio)
MOCK_FUNCTION_END()
MOCK_FUNCTION_WITH_CODE(WSAAPI, int, mocked_closesocket, SOCKET, s)
MOCK_FUNCTION_END(0)
MOCK_FUNCTION_WITH_CODE(, void, test_on_open_complete, void*, context, ASYNC_SOCKET_OPEN_RESULT, open_result)
MOCK_FUNCTION_END()
@ -126,9 +133,6 @@ TEST_SUITE_INITIALIZE(suite_init)
REGISTER_GLOBAL_MOCK_FAIL_RETURN(mocked_CreateThreadpoolCleanupGroup, NULL);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(mocked_CreateThreadpoolIo, NULL);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(mocked_CreateEventA, NULL);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(mocked_WSASend, 1);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(mocked_WSARecv, 1);
REGISTER_GLOBAL_MOCK_FAIL_RETURN(mocked_closesocket, 1);
REGISTER_UMOCK_ALIAS_TYPE(PTP_IO, void*);
REGISTER_UMOCK_ALIAS_TYPE(PTP_CALLBACK_ENVIRON, void*);
@ -148,10 +152,14 @@ TEST_SUITE_INITIALIZE(suite_init)
REGISTER_UMOCK_ALIAS_TYPE(LPDWORD, void*);
REGISTER_UMOCK_ALIAS_TYPE(LPWSAOVERLAPPED, void*);
REGISTER_UMOCK_ALIAS_TYPE(LPWSAOVERLAPPED_COMPLETION_ROUTINE, void*);
REGISTER_UMOCK_ALIAS_TYPE(SOCKET_TRANSPORT_HANDLE, void*);
REGISTER_UMOCK_ALIAS_TYPE(SOCKET_HANDLE, void*);
REGISTER_TYPE(ASYNC_SOCKET_OPEN_RESULT, ASYNC_SOCKET_OPEN_RESULT);
REGISTER_TYPE(ASYNC_SOCKET_SEND_RESULT, ASYNC_SOCKET_SEND_RESULT);
REGISTER_TYPE(ASYNC_SOCKET_RECEIVE_RESULT, ASYNC_SOCKET_RECEIVE_RESULT);
REGISTER_TYPE(SOCKET_SEND_RESULT, SOCKET_SEND_RESULT);
REGISTER_TYPE(SOCKET_RECEIVE_RESULT, SOCKET_RECEIVE_RESULT);
}
TEST_SUITE_CLEANUP(suite_cleanup)
@ -188,9 +196,6 @@ TEST_FUNCTION(async_socket_create_with_NULL_execution_engine_fails)
ASSERT_IS_NULL(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_034: [ If socket_handle is INVALID_SOCKET, async_socket_create shall fail and return NULL. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_001: [ async_socket_create shall allocate a new async socket and on success shall return a non-NULL handle. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_42_004: [ async_socket_create shall increment the reference count on execution_engine. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_035: [ async_socket_create shall obtain the PTP_POOL from the execution engine passed to async_socket_create by calling execution_engine_win32_get_threadpool. ]*/
@ -214,6 +219,7 @@ TEST_FUNCTION(async_socket_create_succeeds)
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_04_001: [ async_socket_create_with_transport shall fail by returning NULL. ]*/
TEST_FUNCTION(async_socket_create_with_transport_fails)
{
@ -268,6 +274,7 @@ TEST_FUNCTION(async_socket_destroy_with_NULL_returns)
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_42_005: [ async_socket_destroy shall decrement the reference count on the execution engine. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_005: [ async_socket_destroy shall free all resources associated with async_socket. ]*/
TEST_FUNCTION(async_socket_destroy_frees_resources)
@ -299,13 +306,13 @@ TEST_FUNCTION(async_socket_destroy_closes_first_if_open)
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG))
.CaptureArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io);
ASSERT_ARE_EQUAL(int, 0, async_socket_open_async(async_socket, test_socket, test_on_open_complete, (void*)0x4242));
umock_c_reset_all_calls();
// close first
STRICT_EXPECTED_CALL(mocked_closesocket((SOCKET)test_socket));
STRICT_EXPECTED_CALL(mocked_WaitForThreadpoolIoCallbacks(test_ptp_io, FALSE));
STRICT_EXPECTED_CALL(mocked_CloseThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_DestroyThreadpoolEnvironment(cbe));
@ -313,7 +320,6 @@ TEST_FUNCTION(async_socket_destroy_closes_first_if_open)
STRICT_EXPECTED_CALL(execution_engine_dec_ref(test_execution_engine));
STRICT_EXPECTED_CALL(free(IGNORED_ARG));
// act
async_socket_destroy(async_socket);
// assert
@ -336,7 +342,8 @@ TEST_FUNCTION(async_socket_open_async_with_NULL_async_socket_fails)
ASSERT_ARE_NOT_EQUAL(int, 0, result);
}
TEST_FUNCTION(async_socket_open_async_with_INVALID_SOCKET_socket_fails)
/*Tests_SRS_ASYNC_SOCKET_WIN32_01_034: [ If socket_transport is NULL, async_socket_open_async shall fail and return a non-zero value. ]*/
TEST_FUNCTION(async_socket_open_async_with_NULL_socket_fails)
{
// arrange
ASYNC_SOCKET_HANDLE async_socket = async_socket_create(test_execution_engine);
@ -344,7 +351,7 @@ TEST_FUNCTION(async_socket_open_async_with_INVALID_SOCKET_socket_fails)
umock_c_reset_all_calls();
// act
result = async_socket_open_async(async_socket, (SOCKET_HANDLE)INVALID_SOCKET, test_on_open_complete, (void*)0x4242);
result = async_socket_open_async(async_socket, NULL, test_on_open_complete, (void*)0x4242);
// assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
@ -354,6 +361,7 @@ TEST_FUNCTION(async_socket_open_async_with_INVALID_SOCKET_socket_fails)
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_008: [ If on_open_complete is NULL, async_socket_open_async shall fail and return a non-zero value. ]*/
TEST_FUNCTION(async_socket_open_async_with_NULL_on_open_complete_fails)
{
@ -377,7 +385,7 @@ TEST_FUNCTION(async_socket_open_async_with_NULL_on_open_complete_fails)
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_014: [ On success, async_socket_open_async shall return 0. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_016: [ Otherwise async_socket_open_async shall initialize a thread pool environment by calling InitializeThreadpoolEnvironment. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_036: [ async_socket_open_async shall set the thread pool for the environment to the pool obtained from the execution engine by calling SetThreadpoolCallbackPool. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_058: [ async_socket_open_async shall create a threadpool IO by calling CreateThreadpoolIo and passing socket_handle, the callback environment to it and on_io_complete as callback. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_058: [ async_socket_open_async shall create a threadpool IO by calling CreateThreadpoolIo and passing socket_transport_get_underlying_socket, the callback environment to it and on_io_complete as callback. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_017: [ On success async_socket_open_async shall call on_open_complete_context with ASYNC_SOCKET_OPEN_OK. ]*/
TEST_FUNCTION(async_socket_open_async_succeeds)
{
@ -391,7 +399,8 @@ TEST_FUNCTION(async_socket_open_async_succeeds)
.CaptureArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool))
.ValidateArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.ValidateArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(test_on_open_complete((void*)0x4242, ASYNC_SOCKET_OPEN_OK));
@ -419,7 +428,8 @@ TEST_FUNCTION(async_socket_open_async_succeeds_with_NULL_context)
.CaptureArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool))
.ValidateArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.ValidateArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(test_on_open_complete(NULL, ASYNC_SOCKET_OPEN_OK));
@ -448,7 +458,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_open_async_fails)
.CaptureArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool))
.ValidateArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.ValidateArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(test_on_open_complete((void*)0x4242, ASYNC_SOCKET_OPEN_OK));
@ -508,7 +518,6 @@ TEST_FUNCTION(async_socket_close_with_NULL_returns)
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_019: [ Otherwise, async_socket_close shall switch the state to CLOSING. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_42_006: [ async_socket_close shall call closesocket on the underlying socket. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_040: [ async_socket_close shall wait for any executing callbacks by calling WaitForThreadpoolIoCallbacks, passing FALSE as fCancelPendingCallbacks. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_059: [ async_socket_close shall close the threadpool IO created in async_socket_open_async by calling CloseThreadpoolIo. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_042: [ async_socket_close shall destroy the thread pool environment created in async_socket_open_async. ]*/
@ -525,12 +534,13 @@ TEST_FUNCTION(async_socket_close_reverses_the_actions_from_open)
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG))
.CaptureArgumentValue_pcbe(&cbe);
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(socket_transport_get_underlying_socket(test_socket))
.SetReturn((SOCKET_HANDLE)0x4242);
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io);
(void)async_socket_open_async(async_socket, test_socket, test_on_open_complete, (void*)0x4242);
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_closesocket((SOCKET)test_socket));
STRICT_EXPECTED_CALL(mocked_WaitForThreadpoolIoCallbacks(test_ptp_io, FALSE));
STRICT_EXPECTED_CALL(mocked_CloseThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_DestroyThreadpoolEnvironment(cbe));
@ -823,6 +833,7 @@ TEST_FUNCTION(async_socket_send_async_when_not_open_fails)
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_097: [ If async_socket is not OPEN, async_socket_send_async shall fail and return ASYNC_SOCKET_SEND_SYNC_NOT_OPEN. ]*/
TEST_FUNCTION(async_socket_send_async_after_close_fails)
{
@ -851,9 +862,9 @@ TEST_FUNCTION(async_socket_send_async_after_close_fails)
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_028: [ Otherwise async_socket_send_async shall create a context for the send where the payload, on_send_complete and on_send_complete_context shall be stored. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_050: [ The context shall also allocate enough memory to keep an array of buffer_count WSABUF items. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_056: [ async_socket_send_async shall set the WSABUF items to point to the memory/length of the buffers in payload. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_057: [ An event to be used for the OVERLAPPED structure passed to WSASend shall be created and stored in the context. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_057: [ An event to be used for the OVERLAPPED structure passed to socket_transport_send shall be created and stored in the context. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_060: [ An asynchronous IO shall be started by calling StartThreadpoolIo. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_061: [ The WSABUF array associated with the context shall be sent by calling WSASend and passing to it the OVERLAPPED structure with the event that was just created, dwFlags set to 0, lpNumberOfBytesSent set to NULL and lpCompletionRoutine set to NULL. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_061: [ The SOCKET_BUFFER array associated with the context shall be sent by calling socket_transport_send and passing to it the OVERLAPPED structure with the event that was just created, flags set to 0, and bytes_sent set to NULL. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_045: [ On success, async_socket_send_async shall return ASYNC_SOCKET_SEND_SYNC_OK. ]*/
TEST_FUNCTION(async_socket_send_async_succeeds)
{
@ -871,7 +882,7 @@ TEST_FUNCTION(async_socket_send_async_succeeds)
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -881,8 +892,9 @@ TEST_FUNCTION(async_socket_send_async_succeeds)
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_OK);
// act
result = async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244);
@ -892,10 +904,11 @@ TEST_FUNCTION(async_socket_send_async_succeeds)
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, result);
// cleanup
test_on_io_complete(NULL, test_ptp_io_context, overlapped, NO_ERROR, (ULONG_PTR)1, test_ptp_io);
test_on_io_complete(0, test_ptp_io_context, overlapped, NO_ERROR, (ULONG_PTR)1, test_ptp_io);
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_027: [ on_send_complete_context shall be allowed to be NULL. ]*/
TEST_FUNCTION(async_socket_send_async_with_NULL_on_send_complete_context_succeeds)
{
@ -913,7 +926,7 @@ TEST_FUNCTION(async_socket_send_async_with_NULL_on_send_complete_context_succeed
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -923,8 +936,9 @@ TEST_FUNCTION(async_socket_send_async_with_NULL_on_send_complete_context_succeed
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_OK);
// act
result = async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, NULL);
@ -939,7 +953,7 @@ TEST_FUNCTION(async_socket_send_async_with_NULL_on_send_complete_context_succeed
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_029: [ If any error occurs, async_socket_send_async shall fail and return ASYNC_SOCKET_SEND_SYNC_ERROR. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_062: [ If WSASend fails, async_socket_send_async shall call WSAGetLastError. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_062: [ If socket_transport_send fails, async_socket_send_async shall call WSAGetLastError. ]*/
TEST_FUNCTION(when_underlying_calls_fail_async_socket_send_async_fails)
{
// arrange
@ -954,7 +968,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_send_async_fails)
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io);
(void)async_socket_open_async(async_socket, test_socket, test_on_open_complete, (void*)0x4242);
umock_c_reset_all_calls();
@ -962,7 +976,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_send_async_fails)
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL));
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSAEINVAL)
.CallCannotFail();
@ -988,7 +1002,8 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_send_async_fails)
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_062: [ If WSASend fails, async_socket_send_async shall call WSAGetLastError. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_062: [ If socket_transport_send fails, async_socket_send_async shall call WSAGetLastError. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_053: [ If WSAGetLastError returns WSA_IO_PENDING, it shall be not treated as an error. ]*/
TEST_FUNCTION(when_get_last_error_for_send_returns_WSA_IO_PENDING_it_is_treated_as_successfull)
{
@ -1007,7 +1022,7 @@ TEST_FUNCTION(when_get_last_error_for_send_returns_WSA_IO_PENDING_it_is_treated_
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1017,9 +1032,9 @@ TEST_FUNCTION(when_get_last_error_for_send_returns_WSA_IO_PENDING_it_is_treated_
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
@ -1054,7 +1069,7 @@ TEST_FUNCTION(when_get_last_error_for_send_returns_an_error_then_async_socket_se
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1065,9 +1080,9 @@ TEST_FUNCTION(when_get_last_error_for_send_returns_an_error_then_async_socket_se
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL))
.CaptureReturn(&overlapped_event);
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSAENOBUFS);
STRICT_EXPECTED_CALL(mocked_CancelThreadpoolIo(test_ptp_io));
@ -1105,7 +1120,7 @@ TEST_FUNCTION(when_get_last_error_for_send_returns_WSAGetLastError_then_async_so
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1116,9 +1131,9 @@ TEST_FUNCTION(when_get_last_error_for_send_returns_WSAGetLastError_then_async_so
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL))
.CaptureReturn(&overlapped_event);
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSAECONNRESET);
STRICT_EXPECTED_CALL(mocked_CancelThreadpoolIo(test_ptp_io));
@ -1137,8 +1152,8 @@ TEST_FUNCTION(when_get_last_error_for_send_returns_WSAGetLastError_then_async_so
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_106: [ If WSASend fails with any other error, async_socket_send_async shall call CancelThreadpoolIo and return ASYNC_SOCKET_SEND_SYNC_ERROR. ]*/
TEST_FUNCTION(when_WSASend_returns_an_error_different_than_SOCKET_ERROR_async_socket_send_async_cancels_the_IO)
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_106: [ If socket_transport_send fails with any other error, async_socket_send_async shall call CancelThreadpoolIo and return ASYNC_SOCKET_SEND_SYNC_ERROR. ]*/
TEST_FUNCTION(when_socket_transport_send_returns_an_error_different_than_SOCKET_ERROR_async_socket_send_async_cancels_the_IO)
{
// arrange
ASYNC_SOCKET_HANDLE async_socket = async_socket_create(test_execution_engine);
@ -1155,7 +1170,7 @@ TEST_FUNCTION(when_WSASend_returns_an_error_different_than_SOCKET_ERROR_async_so
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1166,8 +1181,8 @@ TEST_FUNCTION(when_WSASend_returns_an_error_different_than_SOCKET_ERROR_async_so
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL))
.CaptureReturn(&overlapped_event);
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(1);
STRICT_EXPECTED_CALL(mocked_CancelThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_CloseHandle(IGNORED_ARG))
@ -1486,10 +1501,12 @@ TEST_FUNCTION(async_socket_receive_async_after_close_fails)
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_077: [ Otherwise async_socket_receive_async shall create a context for the send where the payload, on_receive_complete and on_receive_complete_context shall be stored. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_078: [ The context shall also allocate enough memory to keep an array of buffer_count WSABUF items. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_079: [ async_socket_receive_async shall set the WSABUF items to point to the memory/length of the buffers in payload. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_080: [ An event to be used for the OVERLAPPED structure passed to WSARecv shall be created and stored in the context. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_080: [ An event to be used for the OVERLAPPED structure passed to socket_transport_receive shall be created and stored in the context. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_081: [ An asynchronous IO shall be started by calling StartThreadpoolIo. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_082: [ A receive shall be started for the WSABUF array associated with the context calling WSARecv and passing to it the OVERLAPPED structure with the event that was just created, dwFlags set to 0, lpNumberOfBytesSent set to NULL and lpCompletionRoutine set to NULL. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_082: [ A receive shall be started for the WSABUF array associated with the context calling socket_transport_receive and passing to it the OVERLAPPED structure with the event that was just created, flags set to 0, and bytes_sent set to NULL. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_083: [ On success, async_socket_receive_async shall return 0. ]*/
TEST_FUNCTION(async_socket_receive_async_succeeds)
{
// arrange
@ -1507,7 +1524,7 @@ TEST_FUNCTION(async_socket_receive_async_succeeds)
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1517,8 +1534,9 @@ TEST_FUNCTION(async_socket_receive_async_succeeds)
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_OK);
// act
result = async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);
@ -1550,7 +1568,7 @@ TEST_FUNCTION(async_socket_receive_async_with_NULL_on_send_complete_context_succ
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1560,9 +1578,9 @@ TEST_FUNCTION(async_socket_receive_async_with_NULL_on_send_complete_context_succ
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.ValidateArgumentBuffer(5, &expected_flags, sizeof(expected_flags))
.CaptureArgumentValue_lpOverlapped(&overlapped);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, expected_flags, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_OK);
// act
result = async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, NULL);
@ -1577,7 +1595,7 @@ TEST_FUNCTION(async_socket_receive_async_with_NULL_on_send_complete_context_succ
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_084: [ If any error occurs, async_socket_receive_async shall fail and return a non-zero value. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_054: [ If WSARecv fails with SOCKET_ERROR, async_socket_receive_async shall call WSAGetLastError. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_054: [ If socket_transport_receive fails with SOCKET_ERROR, async_socket_receive_async shall call WSAGetLastError. ]*/
TEST_FUNCTION(when_underlying_calls_fail_async_socket_receive_async_fails)
{
// arrange
@ -1592,7 +1610,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_receive_async_fails)
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io);
(void)async_socket_open_async(async_socket, test_socket, test_on_open_complete, (void*)0x4242);
umock_c_reset_all_calls();
@ -1600,7 +1618,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_receive_async_fails)
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL));
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSAEINVAL)
.CallCannotFail();
@ -1626,7 +1644,7 @@ TEST_FUNCTION(when_underlying_calls_fail_async_socket_receive_async_fails)
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_054: [ If WSARecv fails with SOCKET_ERROR, async_socket_receive_async shall call WSAGetLastError. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_054: [ If socket_transport_receive fails with SOCKET_RECEIVE_ERROR, async_socket_receive_async shall call WSAGetLastError. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_055: [ If WSAGetLastError returns IO_PENDING, it shall be not treated as an error. ]*/
TEST_FUNCTION(when_get_last_error_for_receive_returns_WSA_IO_PENDING_it_is_treated_as_successfull)
{
@ -1645,7 +1663,7 @@ TEST_FUNCTION(when_get_last_error_for_receive_returns_WSA_IO_PENDING_it_is_treat
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1655,10 +1673,9 @@ TEST_FUNCTION(when_get_last_error_for_receive_returns_WSA_IO_PENDING_it_is_treat
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.ValidateArgumentBuffer(5, &expected_flags, sizeof(expected_flags))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, expected_flags, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
@ -1674,7 +1691,7 @@ TEST_FUNCTION(when_get_last_error_for_receive_returns_WSA_IO_PENDING_it_is_treat
async_socket_destroy(async_socket);
}
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_105: [ If WSARecv fails with any other error, async_socket_receive_async shall call CancelThreadpoolIo and return a non-zero value. ]*/
/* Tests_SRS_ASYNC_SOCKET_WIN32_01_105: [ If socket_transport_receive fails with any other error, async_socket_receive_async shall call CancelThreadpoolIo and return a non-zero value. ]*/
TEST_FUNCTION(when_WSARecv_returns_an_error_different_than_SOCKET_ERROR_async_socket_receive_async_cancels_the_IO)
{
// arrange
@ -1693,7 +1710,7 @@ TEST_FUNCTION(when_WSARecv_returns_an_error_different_than_SOCKET_ERROR_async_so
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1704,9 +1721,8 @@ TEST_FUNCTION(when_WSARecv_returns_an_error_different_than_SOCKET_ERROR_async_so
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL))
.CaptureReturn(&overlapped_event);
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.ValidateArgumentBuffer(5, &expected_flags, sizeof(expected_flags))
.CaptureArgumentValue_lpOverlapped(&overlapped)
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, expected_flags, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(1);
STRICT_EXPECTED_CALL(mocked_CancelThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_CloseHandle(IGNORED_ARG))
@ -1743,7 +1759,7 @@ TEST_FUNCTION(when_get_last_error_for_receive_returns_an_error_then_async_socket
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1754,10 +1770,9 @@ TEST_FUNCTION(when_get_last_error_for_receive_returns_an_error_then_async_socket
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL))
.CaptureReturn(&overlapped_event);
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.ValidateArgumentBuffer(5, &expected_flags, sizeof(expected_flags))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, expected_flags, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSAECONNRESET);
STRICT_EXPECTED_CALL(mocked_CancelThreadpoolIo(test_ptp_io));
@ -1794,7 +1809,7 @@ TEST_FUNCTION(on_io_complete_with_NULL_overlapped_for_send_returns)
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1803,8 +1818,9 @@ TEST_FUNCTION(on_io_complete_with_NULL_overlapped_for_send_returns)
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_OK);
(void)async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244);
umock_c_reset_all_calls();
@ -1840,7 +1856,7 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_send_as_complete_with_O
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1850,12 +1866,12 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_send_as_complete_with_O
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244);
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(test_on_send_complete((void*)0x4244, ASYNC_SOCKET_SEND_OK));
@ -1892,7 +1908,7 @@ TEST_FUNCTION(on_io_complete_with_error_indicates_the_send_as_complete_with_ERRO
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1902,12 +1918,12 @@ TEST_FUNCTION(on_io_complete_with_error_indicates_the_send_as_complete_with_ERRO
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244);
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(test_on_send_complete((void*)0x4244, ASYNC_SOCKET_SEND_ERROR));
@ -1940,7 +1956,7 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_and_number_of_bytes_sent_less_than_ex
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1950,12 +1966,12 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_and_number_of_bytes_sent_less_than_ex
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_send(IGNORED_ARG, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244);
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(test_on_send_complete((void*)0x4244, ASYNC_SOCKET_SEND_ERROR));
@ -1988,7 +2004,7 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_and_number_of_bytes_sent_more_than_ex
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -1998,12 +2014,12 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_and_number_of_bytes_sent_more_than_ex
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG,1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSASend((SOCKET)test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_send(test_socket, IGNORED_ARG, 1, NULL, 0, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_FAILED);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244);
ASSERT_ARE_EQUAL(ASYNC_SOCKET_SEND_SYNC_RESULT, ASYNC_SOCKET_SEND_SYNC_OK, async_socket_send_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_send_complete, (void*)0x4244));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(test_on_send_complete((void*)0x4244, ASYNC_SOCKET_SEND_ERROR));
@ -2036,7 +2052,7 @@ TEST_FUNCTION(on_io_complete_with_NULL_overlapped_for_receive_returns)
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -2045,8 +2061,9 @@ TEST_FUNCTION(on_io_complete_with_NULL_overlapped_for_receive_returns)
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG,1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_SEND_OK);
(void)async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);
umock_c_reset_all_calls();
@ -2081,7 +2098,7 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -2091,9 +2108,9 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);
@ -2133,7 +2150,7 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -2143,9 +2160,9 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG,1,sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);
@ -2181,7 +2198,7 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -2191,9 +2208,9 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG,1,sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);
@ -2233,7 +2250,7 @@ TEST_FUNCTION(on_io_complete_with_error_indicates_the_receive_as_complete_with_E
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -2243,9 +2260,9 @@ TEST_FUNCTION(on_io_complete_with_error_indicates_the_receive_as_complete_with_E
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);
@ -2281,7 +2298,7 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -2291,9 +2308,9 @@ TEST_FUNCTION(on_io_complete_with_NO_ERROR_indicates_the_receive_as_complete_wit
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, 1, sizeof(WSABUF)));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);
@ -2328,7 +2345,7 @@ static void on_io_complete_with_error_indicates_the_receive_as_complete_with_ABA
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(mocked_InitializeThreadpoolEnvironment(IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_SetThreadpoolCallbackPool(IGNORED_ARG, test_pool));
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(test_socket, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
STRICT_EXPECTED_CALL(mocked_CreateThreadpoolIo(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.CaptureReturn(&test_ptp_io)
.CaptureArgumentValue_pv(&test_ptp_io_context)
.CaptureArgumentValue_pfnio(&test_on_io_complete);
@ -2338,9 +2355,9 @@ static void on_io_complete_with_error_indicates_the_receive_as_complete_with_ABA
STRICT_EXPECTED_CALL(malloc_flex(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(mocked_CreateEventA(NULL, FALSE, FALSE, NULL));
STRICT_EXPECTED_CALL(mocked_StartThreadpoolIo(test_ptp_io));
STRICT_EXPECTED_CALL(mocked_WSARecv((SOCKET)test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG, NULL))
.CaptureArgumentValue_lpOverlapped(&overlapped)
.SetReturn(SOCKET_ERROR);
STRICT_EXPECTED_CALL(socket_transport_receive(test_socket, IGNORED_ARG, 1, NULL, IGNORED_ARG, IGNORED_ARG))
.CaptureArgumentValue_data(&overlapped)
.SetReturn(SOCKET_RECEIVE_ERROR);
STRICT_EXPECTED_CALL(mocked_WSAGetLastError())
.SetReturn(WSA_IO_PENDING);
(void)async_socket_receive_async(async_socket, payload_buffers, sizeof(payload_buffers) / sizeof(payload_buffers[0]), test_on_receive_complete, (void*)0x4244);

Просмотреть файл

@ -686,36 +686,6 @@ TEST_FUNCTION(socket_transport_disconnect_invalid_arguments)
}
// Tests_SOCKET_TRANSPORT_WIN32_09_083: [ If shutdown does not return 0, the socket is not valid therefore socket_transport_disconnect shall not call close ]
TEST_FUNCTION(socket_transport_disconnect_shutdown_fail)
{
//arrange
SOCKET_TRANSPORT_HANDLE socket_handle = socket_transport_create_client();
ASSERT_IS_NOT_NULL(socket_handle);
umock_c_reset_all_calls();
int dummy_socket = 100;
STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(socket(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG))
.SetReturn(dummy_socket);
ASSERT_ARE_EQUAL(int, 0, socket_transport_connect(socket_handle, TEST_HOSTNAME, TEST_PORT, TEST_CONNECTION_TIMEOUT));
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(shutdown(IGNORED_ARG, 2))
.SetReturn(MU_FAILURE);
STRICT_EXPECTED_CALL(sm_close_end(IGNORED_ARG));
//act
socket_transport_disconnect(socket_handle);
//assert
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
//cleanup
socket_transport_destroy(socket_handle);
}
// Tests_SOCKET_TRANSPORT_WIN32_09_030: [ socket_transport_disconnect shall call closesocket to disconnect the connected socket. ]
TEST_FUNCTION(socket_transport_disconnect_failure_closesocket)
{
@ -733,7 +703,6 @@ TEST_FUNCTION(socket_transport_disconnect_failure_closesocket)
umock_c_negative_tests_snapshot();
STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(shutdown(IGNORED_ARG, SD_BOTH));
STRICT_EXPECTED_CALL(closesocket(IGNORED_ARG))
.SetReturn(1);
STRICT_EXPECTED_CALL(sm_close_end(IGNORED_ARG));
@ -748,7 +717,6 @@ TEST_FUNCTION(socket_transport_disconnect_failure_closesocket)
socket_transport_destroy(socket_handle);
}
// Tests_SOCKET_TRANSPORT_WIN32_09_083: [ If shutdown does not return 0 on a socket that is not a binding socket, the socket is not valid therefore socket_transport_disconnect shall not call close ]
TEST_FUNCTION(socket_transport_disconnect_binding_socket_closesocket)
{
//arrange
@ -814,7 +782,6 @@ TEST_FUNCTION(socket_transport_disconnect_succeed)
umock_c_reset_all_calls();
STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG));
STRICT_EXPECTED_CALL(shutdown(IGNORED_ARG, IGNORED_ARG));
STRICT_EXPECTED_CALL(closesocket(IGNORED_ARG));
STRICT_EXPECTED_CALL(sm_close_end(IGNORED_ARG));