Merge remote-tracking branch 'origin/master' into ieee802154

This commit is contained in:
Gregory Nutt 2017-04-03 09:28:38 -06:00
commit 992694d2c2
26 changed files with 11671 additions and 2 deletions

14
examples/usrsocktest/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
/Make.dep
/.depend
/.built
/*.asm
/*.obj
/*.rel
/*.lst
/*.sym
/*.adb
/*.lib
/*.src
/*.hobj
/*.exe
/*.dSYM

View File

@ -0,0 +1,36 @@
#
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
config EXAMPLES_USRSOCKTEST
bool "USRSOCK test example"
default n
depends on NET && NET_USRSOCK && !DISABLE_POLL
select NET_USRSOCK_TCP
select NET_USRSOCK_UDP
select NET_SOCKOPTS
select PIPES
---help---
Enable the User Socket test example. This example application runs
unit-tests for /dev/usrsock.
if EXAMPLES_USRSOCKTEST
config EXAMPLES_USRSOCKTEST_PROGNAME
string "Program name"
default "usrsocktest"
depends on BUILD_KERNEL
---help---
This is the name of the program that will be use when the NSH ELF
program is installed.
config EXAMPLES_USRSOCKTEST_PRIORITY
int "usrsocktest task priority"
default 100
config EXAMPLES_USRSOCKTEST_STACKSIZE
int "usrsocktest stack size"
default 4096
endif

View File

@ -0,0 +1,39 @@
############################################################################
# examples/usrsocktest/Make.defs
# Adds selected applications to apps/ build
#
# Copyright (C) 2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
ifeq ($(CONFIG_EXAMPLES_USRSOCKTEST),y)
CONFIGURED_APPS += examples/usrsocktest
endif

View File

@ -0,0 +1,65 @@
############################################################################
# apps/examples/usrsocktest/Makefile
#
# Copyright (C) 2008, 2010-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
-include $(TOPDIR)/Make.defs
# USRSOCK Test built-in application info
CONFIG_EXAMPLES_USRSOCKTEST_PRIORITY ?= SCHED_PRIORITY_DEFAULT
CONFIG_EXAMPLES_USRSOCKTEST_STACKSIZE ?= 4096
APPNAME = usrsocktest
PRIORITY = $(CONFIG_EXAMPLES_USRSOCKTEST_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_USRSOCKTEST_STACKSIZE)
# NuttX USRSOCK Test
ASRCS =
CSRCS = usrsocktest_daemon.c usrsocktest_basic_connect.c
CSRCS += usrsocktest_basic_daemon.c usrsocktest_basic_getsockname.c
CSRCS += usrsocktest_basic_getsockopt.c usrsocktest_basic_send.c
CSRCS += usrsocktest_basic_setsockopt.c usrsocktest_block_recv.c
CSRCS += usrsocktest_block_send.c usrsocktest_chardev.c
CSRCS += usrsocktest_multi_thread.c usrsocktest_noblock_connect.c
CSRCS += usrsocktest_noblock_recv.c usrsocktest_noblock_send.c
CSRCS += usrsocktest_nodaemon.c usrsocktest_poll.c
CSRCS += usrsocktest_remote_disconnect.c usrsocktest_wake_with_signal.c
MAINSRC = usrsocktest_main.c
CONFIG_EXAMPLES_USRSOCKTEST_PROGNAME ?= usrsocktest$(EXEEXT)
PROGNAME = $(CONFIG_EXAMPLES_USRSOCKTEST_PROGNAME)
include $(APPDIR)/Application.mk

View File

@ -0,0 +1,212 @@
/****************************************************************************
* examples/usrsocktest/defines.h
* Common defines for all usrsock testcases
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __EXAMPLES_USRSOCKTEST_DEFINES_H
#define __EXAMPLES_USRSOCKTEST_DEFINES_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <assert.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define USRSOCK_NODE "/dev/usrsock"
#define USRSOCKTEST_DAEMON_CONF_DEFAULTS \
{ \
.max_sockets = UINT_MAX, \
.supported_domain = AF_INET, \
.supported_type = SOCK_STREAM, \
.supported_protocol = 0, \
.delay_all_responses = false, \
.endpoint_addr = "127.0.0.1", \
.endpoint_port = 255, \
.endpoint_block_connect = false, \
.endpoint_block_send = false, \
.endpoint_recv_avail_from_start = true, \
.endpoint_recv_avail = 4, \
}
/* Test case macros */
#define utest_match(type, should_be_value, test_value) do { \
type tmp_utest_test_value = (type)(test_value); \
type tmp_utest_should_value = (type)(should_be_value); \
if (!usrsocktest_assert_print_value(__func__, __LINE__, \
"(" #type ")(" #test_value ") == " \
"(" #type ")(" #should_be_value ")", \
tmp_utest_test_value, \
tmp_utest_should_value)) \
{ \
usrsocktest_test_failed = true; \
return; \
} \
} while(false)
#define utest_match_buf(should_be_valuebuf, test_valuebuf, test_valuebuflen) do { \
if (!usrsocktest_assert_print_buf(__func__, __LINE__, \
"memcmp(" #should_be_valuebuf ", " \
#test_valuebuf ", " \
#test_valuebuflen ") == 0", \
should_be_valuebuf, \
test_valuebuf, \
test_valuebuflen)) \
{ \
usrsocktest_test_failed = true; \
return; \
} \
} while(false)
#define RUN_TEST_CASE(g,t) do { \
if (usrsocktest_test_failed) \
{ \
return; \
} \
usrsocktest_group_##g##_setup(); \
usrsocktest_test_##g##_##t(); \
usrsocktest_group_##g##_teardown(); \
if (usrsocktest_test_failed) \
{ \
return; \
} \
} while (false)
#define RUN_TEST_GROUP(g) do { \
extern const char *usrsocktest_group_##g; \
void usrsocktest_group_##g##_run(void); \
run_tests(usrsocktest_group_##g, usrsocktest_group_##g##_run); \
} while (false)
#define TEST_GROUP(g) const char *usrsocktest_group_##g = #g; \
void usrsocktest_group_##g##_run(void)
#define TEST_SETUP(g) static void usrsocktest_group_##g##_setup(void)
#define TEST_TEAR_DOWN(g) static void usrsocktest_group_##g##_teardown(void)
#define TEST(g,t) static void usrsocktest_test_##g##_##t(void)
#define TEST_ASSERT_TRUE(v) utest_match(bool, true, (v))
#define TEST_ASSERT_FALSE(v) utest_match(bool, false, (v))
#define TEST_ASSERT_EQUAL(e,v) utest_match(ssize_t, (e), (v))
#define TEST_ASSERT_EQUAL_UINT8_ARRAY(e,v,s) utest_match_buf((e), (v), (s))
/****************************************************************************
* Public Types
****************************************************************************/
struct usrsocktest_daemon_conf_s
{
unsigned int max_sockets;
int8_t supported_domain:8;
int8_t supported_type:8;
int8_t supported_protocol:8;
bool delay_all_responses:1;
bool endpoint_block_connect:1;
bool endpoint_block_send:1;
bool endpoint_recv_avail_from_start:1;
uint8_t endpoint_recv_avail:8;
const char *endpoint_addr;
uint16_t endpoint_port;
};
/****************************************************************************
* Public Data
****************************************************************************/
extern int usrsocktest_endp_malloc_cnt;
extern int usrsocktest_dcmd_malloc_cnt;
extern const struct usrsocktest_daemon_conf_s usrsocktest_daemon_defconf;
extern struct usrsocktest_daemon_conf_s usrsocktest_daemon_config;
extern bool usrsocktest_test_failed;
/****************************************************************************
* Inline Functions
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
bool usrsocktest_assert_print_value(FAR const char *func,
const int line,
FAR const char *check_str,
long int test_value,
long int should_be);
bool usrsocktest_assert_print_buf(FAR const char *func,
const int line,
FAR const char *check_str,
FAR const void *test_buf,
FAR const void *expect_buf,
size_t buflen);
int usrsocktest_daemon_start(FAR const struct usrsocktest_daemon_conf_s *conf);
int usrsocktest_daemon_stop(void);
int usrsocktest_daemon_get_num_active_sockets(void);
int usrsocktest_daemon_get_num_connected_sockets(void);
int usrsocktest_daemon_get_num_waiting_connect_sockets(void);
int usrsocktest_daemon_get_num_recv_empty_sockets(void);
ssize_t usrsocktest_daemon_get_send_bytes(void);
ssize_t usrsocktest_daemon_get_recv_bytes(void);
int usrsocktest_daemon_get_num_unreachable_sockets(void);
int usrsocktest_daemon_get_num_remote_disconnected_sockets(void);
bool usrsocktest_daemon_establish_waiting_connections(void);
bool usrsocktest_send_delayed_command(char cmd, unsigned int delay_msec);
int usrsocktest_daemon_pause_usrsock_handling(bool pause);
#endif /* __EXAMPLES_USRSOCKTEST_DEFINES_H */

View File

@ -0,0 +1,488 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_basic_connect.c
* Basic connect tests with socket daemon
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: Setup
*
* Description:
* Run before every testcase
*
* Input Parameters:
* dconf - test daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Setup(FAR struct usrsocktest_daemon_conf_s *dconf)
{
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
}
/****************************************************************************
* Name: Teardown
*
* Description:
* Run after every testcase
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Teardown(void)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
/****************************************************************************
* Name: NotConnected
*
* Description:
* Opened socket is not connected
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void NotConnected(void)
{
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
}
/****************************************************************************
* Name: Connect
*
* Description:
* Open and connect the socket
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Connect(void)
{
int ret;
struct sockaddr_in addr;
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
/* Attempt reconnect to same address */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Attempt reconnect to different address */
inet_pton(AF_INET, "1.1.1.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(1);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: WrongAF
*
* Description:
* Open and connect the socket with wrong AF
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void WrongAF(void)
{
int ret;
struct sockaddr_in addr;
/* Try connect socket with wrong AF */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_UNIX;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAFNOSUPPORT, errno);
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: WrongPort
*
* Description:
* Open and connect the socket with wrong port
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void WrongPort(void)
{
int ret;
struct sockaddr_in addr;
/* Try connect socket to wrong port */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(127);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(ECONNREFUSED, errno);
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: WrongEndpoint
*
* Description:
* Open and connect the socket with wrong endpoint
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void WrongEndpoint(void)
{
int ret;
struct sockaddr_in addr;
/* Try connect socket to unreachable endpoint */
inet_pton(AF_INET, "1.1.1.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(1);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(ENETUNREACH, errno);
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Connect */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
TEST_SETUP(BasicConnect)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Setup(&usrsocktest_daemon_config);
}
TEST_TEAR_DOWN(BasicConnect)
{
Teardown();
}
TEST(BasicConnect, NotConnected)
{
NotConnected();
}
TEST(BasicConnect, Connect)
{
Connect();
}
TEST(BasicConnect, WrongAF)
{
WrongAF();
}
TEST(BasicConnect, WrongPort)
{
WrongPort();
}
TEST(BasicConnect, WrongEndpoint)
{
WrongEndpoint();
}
TEST_SETUP(BasicConnectDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Setup(&usrsocktest_daemon_config);
}
TEST_TEAR_DOWN(BasicConnectDelay)
{
Teardown();
}
TEST(BasicConnectDelay, NotConnected)
{
NotConnected();
}
TEST(BasicConnectDelay, Connect)
{
Connect();
}
TEST(BasicConnectDelay, WrongAF)
{
WrongAF();
}
TEST(BasicConnectDelay, WrongPort)
{
WrongPort();
}
TEST(BasicConnectDelay, WrongEndpoint)
{
WrongEndpoint();
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BasicConnect)
{
RUN_TEST_CASE(BasicConnect, NotConnected);
RUN_TEST_CASE(BasicConnect, Connect);
RUN_TEST_CASE(BasicConnect, WrongAF);
RUN_TEST_CASE(BasicConnect, WrongPort);
RUN_TEST_CASE(BasicConnect, WrongEndpoint);
}
TEST_GROUP(BasicConnectDelay)
{
RUN_TEST_CASE(BasicConnectDelay, NotConnected);
RUN_TEST_CASE(BasicConnectDelay, Connect);
RUN_TEST_CASE(BasicConnectDelay, WrongAF);
RUN_TEST_CASE(BasicConnectDelay, WrongPort);
RUN_TEST_CASE(BasicConnectDelay, WrongEndpoint);
}

View File

@ -0,0 +1,686 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_basic_daemon.c
* Basic tests with socket daemon
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd, sd2, sd3;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: NoActiveSockets
*
* Description:
* Checks there is no active sockets on daemon startup
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void NoActiveSockets(FAR struct usrsocktest_daemon_conf_s *dconf)
{
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
}
/****************************************************************************
* Name: OpenClose
*
* Description:
* Open and close AF_INET socket, check active socket counter updates
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void OpenClose(FAR struct usrsocktest_daemon_conf_s *dconf)
{
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: UnsupportedType
*
* Description:
* Try open socket for unsupported type
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void UnsupportedType(FAR struct usrsocktest_daemon_conf_s *dconf)
{
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_RDM, 0);
TEST_ASSERT_TRUE(sd < 0);
TEST_ASSERT_EQUAL(EPROTONOSUPPORT, errno);
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: UnsupportedProto
*
* Description:
* Try open socket for unsupported protocol
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void UnsupportedProto(FAR struct usrsocktest_daemon_conf_s *dconf)
{
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 1);
TEST_ASSERT_TRUE(sd < 0);
TEST_ASSERT_EQUAL(EPROTONOSUPPORT, errno);
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: OpenThree
*
* Description:
* Open multiple sockets
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void OpenThree(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
dconf->max_sockets = 3;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
sd2 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
sd3 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd3 >= 0);
TEST_ASSERT_EQUAL(3, usrsocktest_daemon_get_num_active_sockets());
ret = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_FALSE(ret >= 0);
TEST_ASSERT_EQUAL(3, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd2);
TEST_ASSERT_EQUAL(0, ret);
sd2 = -1;
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd);
TEST_ASSERT_EQUAL(0, ret);
sd = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd3);
TEST_ASSERT_EQUAL(0, ret);
sd3 = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: Dup
*
* Description:
* Dup opened socket
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Dup(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
sd2 = dup(sd);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
sd3 = dup(sd);
TEST_ASSERT_TRUE(sd3 >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd2);
TEST_ASSERT_EQUAL(0, ret);
sd2 = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd);
TEST_ASSERT_EQUAL(0, ret);
sd = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd3);
TEST_ASSERT_EQUAL(0, ret);
sd3 = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: Dup2
*
* Description:
* Clone opened socket with dup2
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Dup2(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
sd2 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
ret = dup2(sd2, sd);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd2);
TEST_ASSERT_EQUAL(0, ret);
sd2 = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
ret = close(sd);
TEST_ASSERT_EQUAL(0, ret);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: Stops
*
* Description:
* Daemon stops unexpectedly
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Stops(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
sd2 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
ret = usrsocktest_daemon_stop();
TEST_ASSERT_EQUAL(OK, ret);
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
TEST_ASSERT_EQUAL(0, close(sd));
sd = -1;
TEST_ASSERT_EQUAL(0, close(sd2));
sd2 = -1;
}
/****************************************************************************
* Name: StopsStarts
*
* Description:
* Daemon stops and restarts unexpectedly
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void StopsStarts(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
struct sockaddr_in addr;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
sd2 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = 255;
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EPIPE, errno);
ret = connect(sd2, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EPIPE, errno);
TEST_ASSERT_EQUAL(0, close(sd));
sd = -1;
TEST_ASSERT_EQUAL(0, close(sd2));
sd2 = -1;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: BasicDaemon test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(BasicDaemon)
{
sd = -1;
sd2 = -1;
sd3 = -1;
started = false;
}
/****************************************************************************
* Name: BasicDaemon test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(BasicDaemon)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (sd2 >= 0)
{
ret = close(sd2);
assert(ret >= 0);
}
if (sd3 >= 0)
{
ret = close(sd3);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(BasicDaemon, NoActiveSockets)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
NoActiveSockets(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, NoActiveSocketsDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
NoActiveSockets(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, OpenClose)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
OpenClose(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, OpenCloseDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
OpenClose(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, UnsupportedType)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
UnsupportedType(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, UnsupportedTypeDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
UnsupportedType(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, UnsupportedProto)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
UnsupportedProto(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, UnsupportedProtoDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
UnsupportedProto(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, OpenThree)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
OpenThree(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, OpenThreeDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
OpenThree(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, Dup)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Dup(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, DupDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Dup(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, Dup2)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Dup2(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, Dup2Delay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Dup2(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, Stops)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Stops(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, StopsDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Stops(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, StopsStarts)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
StopsStarts(&usrsocktest_daemon_config);
}
TEST(BasicDaemon, StopsStartsDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
StopsStarts(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BasicDaemon)
{
RUN_TEST_CASE(BasicDaemon, NoActiveSockets);
RUN_TEST_CASE(BasicDaemon, NoActiveSocketsDelay);
RUN_TEST_CASE(BasicDaemon, OpenClose);
RUN_TEST_CASE(BasicDaemon, OpenCloseDelay);
RUN_TEST_CASE(BasicDaemon, UnsupportedType);
RUN_TEST_CASE(BasicDaemon, UnsupportedTypeDelay);
RUN_TEST_CASE(BasicDaemon, UnsupportedProto);
RUN_TEST_CASE(BasicDaemon, UnsupportedProtoDelay);
RUN_TEST_CASE(BasicDaemon, OpenThree);
RUN_TEST_CASE(BasicDaemon, OpenThreeDelay);
RUN_TEST_CASE(BasicDaemon, Dup);
RUN_TEST_CASE(BasicDaemon, DupDelay);
RUN_TEST_CASE(BasicDaemon, Dup2);
RUN_TEST_CASE(BasicDaemon, Dup2Delay);
RUN_TEST_CASE(BasicDaemon, Stops);
RUN_TEST_CASE(BasicDaemon, StopsDelay);
RUN_TEST_CASE(BasicDaemon, StopsStarts);
RUN_TEST_CASE(BasicDaemon, StopsStartsDelay);
}

View File

@ -0,0 +1,287 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_basic_getsockname.c
* Basic getsockname tests
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: Open
*
* Description:
* Open and get socket options
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Open(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
socklen_t addrlen;
union {
struct sockaddr_storage storage;
struct sockaddr_in in;
} addr;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get socket name */
memset(&addr, 0xff, sizeof(addr));
addrlen = sizeof(addr.in);
ret = getsockname(sd, (FAR void *)&addr.in, &addrlen);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(sizeof(addr.in), addrlen);
TEST_ASSERT_EQUAL(AF_INET, addr.in.sin_family);
TEST_ASSERT_EQUAL(htons(12345), addr.in.sin_port);
TEST_ASSERT_EQUAL(htonl(0x7f000001), addr.in.sin_addr.s_addr);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get socket name, short buffer */
memset(&addr, 0xff, sizeof(addr));
addrlen = 1;
ret = getsockname(sd, (FAR void *)&addr.in, &addrlen);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(sizeof(addr.in), addrlen);
TEST_ASSERT_EQUAL(AF_INET, ((FAR uint8_t *)&addr.in.sin_family)[0]);
TEST_ASSERT_EQUAL(0xff, ((FAR uint8_t *)&addr.in.sin_family)[1]);
TEST_ASSERT_EQUAL(htons(0xffff), addr.in.sin_port);
TEST_ASSERT_EQUAL(htonl(0xffffffff), addr.in.sin_addr.s_addr);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get socket name, larger buffer */
memset(&addr, 0xff, sizeof(addr));
addrlen = sizeof(addr.storage);
ret = getsockname(sd, (FAR void *)&addr.in, &addrlen);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(sizeof(addr.in), addrlen);
TEST_ASSERT_EQUAL(AF_INET, addr.in.sin_family);
TEST_ASSERT_EQUAL(htons(12345), addr.in.sin_port);
TEST_ASSERT_EQUAL(htonl(0x7f000001), addr.in.sin_addr.s_addr);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get socket name, NULL addr */
memset(&addr, 0xff, sizeof(addr));
addrlen = sizeof(addr.in);
ret = getsockname(sd, NULL, &addrlen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINVAL, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get socket name, NULL addrlen */
memset(&addr, 0xff, sizeof(addr));
addrlen = sizeof(addr.in);
ret = getsockname(sd, (FAR void *)&addr.in, NULL);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINVAL, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get socket name, zero length buffer */
memset(&addr, 0xff, sizeof(addr));
addrlen = 0;
ret = getsockname(sd, (FAR void *)&addr.in, &addrlen);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(sizeof(addr.in), addrlen);
TEST_ASSERT_EQUAL(0xffff, addr.in.sin_family);
TEST_ASSERT_EQUAL(htons(0xffff), addr.in.sin_port);
TEST_ASSERT_EQUAL(htonl(0xffffffff), addr.in.sin_addr.s_addr);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: BasicGetSockName test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(BasicGetSockName)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: BasicGetSockName test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(BasicGetSockName)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(BasicGetSockName, Open)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Open(&usrsocktest_daemon_config);
}
TEST(BasicGetSockName, OpenDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Open(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BasicGetSockName)
{
RUN_TEST_CASE(BasicGetSockName, Open);
RUN_TEST_CASE(BasicGetSockName, OpenDelay);
}

View File

@ -0,0 +1,266 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_basic_getsockopt.c
* Basic getsockopt tests
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: Open
*
* Description:
* Open and get socket options
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Open(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
int value;
int valuelarge[2];
socklen_t valuelen;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get supported option (SO_TYPE handled by nuttx) */
value = -2;
valuelen = sizeof(value);
ret = getsockopt(sd, SOL_SOCKET, SO_TYPE, &value, &valuelen);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(sizeof(value), valuelen);
TEST_ASSERT_EQUAL(SOCK_STREAM, value);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get supported option */
value = -1;
valuelen = sizeof(value);
ret = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &value, &valuelen);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(sizeof(value), valuelen);
TEST_ASSERT_EQUAL(0, value);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get supported option, too short buffer */
value = -1;
valuelen = 1;
ret = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &value, &valuelen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINVAL, errno);
TEST_ASSERT_EQUAL(-1, value);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get supported option, larger buffer */
valuelarge[0] = -1;
valuelarge[1] = -1;
valuelen = sizeof(valuelarge);
ret = getsockopt(sd, SOL_SOCKET, SO_REUSEADDR, valuelarge, &valuelen);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(sizeof(value), valuelen);
TEST_ASSERT_EQUAL(0, valuelarge[0]);
TEST_ASSERT_EQUAL(-1, valuelarge[1]);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Get unsupported option */
value = -1;
valuelen = sizeof(value);
ret = getsockopt(sd, SOL_SOCKET, SO_BROADCAST, &value, &valuelen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(ENOPROTOOPT, errno);
TEST_ASSERT_EQUAL(-1, value);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: BasicGetSockOpt test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(BasicGetSockOpt)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: BasicGetSockOpt test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(BasicGetSockOpt)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(BasicGetSockOpt, Open)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Open(&usrsocktest_daemon_config);
}
TEST(BasicGetSockOpt, OpenDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Open(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BasicGetSockOpt)
{
RUN_TEST_CASE(BasicGetSockOpt, Open);
RUN_TEST_CASE(BasicGetSockOpt, OpenDelay);
}

View File

@ -0,0 +1,359 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_basic_send.c
* Basic sending tests
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: Send
*
* Description:
* Open socket and send
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Send(FAR struct usrsocktest_daemon_conf_s *dconf)
{
struct sockaddr_in addr;
ssize_t ret;
size_t datalen;
const void *data;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Send on non-connected socket */
data = "data";
datalen = strlen("data");
ret = send(sd, data, datalen, 0);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(ENOTCONN, errno);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Sendto with address */
data = "data";
datalen = strlen("data");
ret = sendto(sd, data, datalen, 0, (FAR const struct sockaddr *)&addr,
sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(ENOTCONN, errno);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Connect socket to available endpoint */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
/* Sendto with address */
data = "data";
datalen = strlen("data");
ret = sendto(sd, data, datalen, 0, (FAR const struct sockaddr *)&addr,
sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV,
usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_send_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: ConnectSend
*
* Description:
* Send over connected socket
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void ConnectSend(FAR struct usrsocktest_daemon_conf_s *dconf)
{
struct sockaddr_in addr;
ssize_t ret;
size_t datalen;
const void *data;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Connect socket to available endpoint */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Send data to remote */
data = "data";
datalen = strlen("data");
ret = send(sd, data, datalen, 0);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(datalen, usrsocktest_daemon_get_send_bytes());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(datalen, usrsocktest_daemon_get_send_bytes());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV,
usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: BasicSend test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(BasicSend)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: BasicSend test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(BasicSend)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(BasicSend, Send)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Send(&usrsocktest_daemon_config);
}
TEST(BasicSend, SendDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Send(&usrsocktest_daemon_config);
}
TEST(BasicSend, ConnectSend)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
ConnectSend(&usrsocktest_daemon_config);
}
TEST(BasicSend, ConnectSendDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
ConnectSend(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BasicSend)
{
RUN_TEST_CASE(BasicSend, Send);
RUN_TEST_CASE(BasicSend, SendDelay);
RUN_TEST_CASE(BasicSend, ConnectSend);
RUN_TEST_CASE(BasicSend, ConnectSendDelay);
}

View File

@ -0,0 +1,235 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_basic_setsockopt.c
* Basic setsockopt tests
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: Open
*
* Description:
* Open and set socket options
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Open(FAR struct usrsocktest_daemon_conf_s *dconf)
{
int ret;
int value;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Set supported option */
value = 1;
ret = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Set supported option, too small buffer */
value = 1;
ret = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &value, 1);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINVAL, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Set unsupported option */
value = 1;
ret = setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(ENOPROTOOPT, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: BasicSetSockOpt test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(BasicSetSockOpt)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: BasicSetSockOpt test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(BasicSetSockOpt)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(BasicSetSockOpt, Open)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Open(&usrsocktest_daemon_config);
}
TEST(BasicSetSockOpt, OpenDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Open(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BasicSetSockOpt)
{
RUN_TEST_CASE(BasicSetSockOpt, Open);
RUN_TEST_CASE(BasicSetSockOpt, OpenDelay);
}

View File

@ -0,0 +1,514 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_block_recv.c
* Receive from the socket in blocking mode
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ConnectReceive
*
* Description:
* Blocking connect and receive
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void ConnectReceive(FAR struct usrsocktest_daemon_conf_s *dconf)
{
ssize_t ret;
size_t datalen;
void *data;
struct sockaddr_in addr;
char databuf[5];
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_block_connect = true;
dconf->endpoint_block_send = true;
dconf->endpoint_recv_avail_from_start = false;
dconf->endpoint_recv_avail = 7;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Do connect, should succeed (after connect block released). */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('E', 100));
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote */
data = databuf;
datalen = sizeof(databuf);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('r', 100));
ret = recvfrom(sd, data, datalen, 0, NULL, 0);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(5, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abcde", data, 5);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(5, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, 0);
TEST_ASSERT_EQUAL(2, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("ab", data, 2);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(7, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: NoBlockConnect
*
* Description:
* Non-blocking connect and blocking receive
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void NoBlockConnect(FAR struct usrsocktest_daemon_conf_s *dconf)
{
ssize_t ret;
size_t datalen;
void *data;
struct sockaddr_in addr;
char databuf[5];
struct sockaddr_in remoteaddr;
socklen_t addrlen;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_block_connect = true;
dconf->endpoint_block_send = true;
dconf->endpoint_recv_avail_from_start = true;
dconf->endpoint_recv_avail = 6;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Do connect, should succeed (after connect block released). */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('W', 100));
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('E', 100));
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote */
data = databuf;
datalen = sizeof(databuf);
ret = read(sd, data, datalen);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(5, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abcde", data, 5);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(5, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote */
data = databuf;
datalen = sizeof(databuf);
addrlen = sizeof(remoteaddr);
ret = recvfrom(sd, data, datalen, 0, (FAR struct sockaddr *)&remoteaddr,
&addrlen);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("a", data, 1);
TEST_ASSERT_EQUAL(sizeof(remoteaddr), addrlen);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&remoteaddr, &addr, addrlen);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(6, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote */
data = databuf;
datalen = sizeof(databuf);
addrlen = sizeof(remoteaddr);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('r', 100));
ret = recvfrom(sd, data, datalen, 0, (FAR struct sockaddr *)&remoteaddr,
&addrlen);
TEST_ASSERT_EQUAL(5, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abcde", data, 5);
TEST_ASSERT_EQUAL(sizeof(remoteaddr), addrlen);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&remoteaddr, &addr, addrlen);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(11, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(11, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: ReceiveTimeout
*
* Description:
* Blocking connect and receive with SO_RCVTIMEO
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void ReceiveTimeout(FAR struct usrsocktest_daemon_conf_s *dconf)
{
ssize_t ret;
size_t datalen;
void *data;
struct sockaddr_in addr;
char databuf[5];
struct timeval tv;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_block_connect = true;
dconf->endpoint_block_send = true;
dconf->endpoint_recv_avail_from_start = false;
dconf->endpoint_recv_avail = 7;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Do connect, should succeed (after connect block released). */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('E', 100));
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Setup recv timeout. */
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (FAR const void *)&tv,
sizeof(tv));
TEST_ASSERT_EQUAL(0, ret);
/* Receive data from remote */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, 0);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: BlockRecv test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(BlockRecv)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: BlockRecv test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(BlockRecv)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(BlockRecv, ConnectReceive)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
ConnectReceive(&usrsocktest_daemon_config);
}
TEST(BlockRecv, ConnectReceiveDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
ConnectReceive(&usrsocktest_daemon_config);
}
TEST(BlockRecv, NoBlockConnect)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
NoBlockConnect(&usrsocktest_daemon_config);
}
TEST(BlockRecv, NoBlockConnectDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
NoBlockConnect(&usrsocktest_daemon_config);
}
TEST(BlockRecv, ReceiveTimeout)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
ReceiveTimeout(&usrsocktest_daemon_config);
}
TEST(BlockRecv, ReceiveTimeoutDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
ReceiveTimeout(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BlockRecv)
{
RUN_TEST_CASE(BlockRecv, ConnectReceive);
RUN_TEST_CASE(BlockRecv, ConnectReceiveDelay);
RUN_TEST_CASE(BlockRecv, NoBlockConnect);
RUN_TEST_CASE(BlockRecv, NoBlockConnectDelay);
RUN_TEST_CASE(BlockRecv, ReceiveTimeout);
RUN_TEST_CASE(BlockRecv, ReceiveTimeoutDelay);
}

View File

@ -0,0 +1,442 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_block_send.c
* Send through the socket in blocking mode
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/time.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ConnectSend
*
* Description:
* Open socket, connect in blocking mode and send
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void ConnectSend(FAR struct usrsocktest_daemon_conf_s *dconf)
{
ssize_t ret;
size_t datalen;
const void *data;
struct sockaddr_in addr;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_block_connect = true;
dconf->endpoint_block_send = true;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Do connect, should succeed (after connect block released). */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('E', 100));
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Send data to remote, */
data = "abcde";
datalen = strlen("abcde");
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('W', 100));
ret = sendto(sd, data, datalen, 0, NULL, 0);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(datalen, usrsocktest_daemon_get_send_bytes());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: NonBlockConnectSend
*
* Description:
* Open socket, connect in non-blocking mode and send
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void NonBlockConnectSend(FAR struct usrsocktest_daemon_conf_s *dconf)
{
ssize_t ret;
size_t datalen;
const void *data;
struct sockaddr_in addr;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_block_connect = true;
dconf->endpoint_block_send = false;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Do connect, should succeed (after connect block released). */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('W', 100));
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('E', 100));
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Send data to remote. */
data = "abcde";
datalen = strlen("abcde");
ret = write(sd, data, datalen);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(datalen, usrsocktest_daemon_get_send_bytes());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: SendTimeout
*
* Description:
* Open socket, connect in blocking mode and send with SO_SNDTIMEO
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void SendTimeout(FAR struct usrsocktest_daemon_conf_s *dconf)
{
ssize_t ret;
size_t datalen;
const void *data;
struct sockaddr_in addr;
struct timeval tv;
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_block_connect = true;
dconf->endpoint_block_send = true;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Do connect, should succeed (after connect block released). */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('E', 100));
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Setup send timeout. */
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
ret = setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (FAR const void *)&tv,
sizeof(tv));
TEST_ASSERT_EQUAL(0, ret);
/* Try send data to remote. */
data = "abcde";
datalen = strlen("abcde");
ret = sendto(sd, data, datalen, 0, NULL, 0);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: BlockSend test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(BlockSend)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: BlockSend test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(BlockSend)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(BlockSend, ConnectSend)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
ConnectSend(&usrsocktest_daemon_config);
}
TEST(BlockSend, ConnectSendDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
ConnectSend(&usrsocktest_daemon_config);
}
TEST(BlockSend, NonBlockConnectSend)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
NonBlockConnectSend(&usrsocktest_daemon_config);
}
TEST(BlockSend, NonBlockConnectSendDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
NonBlockConnectSend(&usrsocktest_daemon_config);
}
TEST(BlockSend, SendTimeout)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
SendTimeout(&usrsocktest_daemon_config);
}
TEST(BlockSend, SendTimeoutDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
SendTimeout(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(BlockSend)
{
RUN_TEST_CASE(BlockSend, ConnectSend);
RUN_TEST_CASE(BlockSend, ConnectSendDelay);
RUN_TEST_CASE(BlockSend, NonBlockConnectSend);
RUN_TEST_CASE(BlockSend, NonBlockConnectSendDelay);
RUN_TEST_CASE(BlockSend, SendTimeout);
RUN_TEST_CASE(BlockSend, SendTimeoutDelay);
}

View File

@ -0,0 +1,234 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_chardev.c
* Character device node tests
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <fcntl.h>
#include <errno.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static int us_fd;
static int us_fd_two;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: CharDev test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(CharDev)
{
us_fd = -1;
us_fd_two = -1;
}
/****************************************************************************
* Name: CharDev test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(CharDev)
{
int ret;
if (us_fd >= 0)
{
ret = close(us_fd);
assert(ret >= 0);
}
if (us_fd_two >= 0)
{
ret = close(us_fd_two);
assert(ret >= 0);
}
}
/****************************************************************************
* Name: OpenRw
*
* Description:
* Simple test for opening and closing usrsock node
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST(CharDev, OpenRw)
{
int ret;
us_fd = open(USRSOCK_NODE, O_RDWR);
TEST_ASSERT_TRUE(us_fd >= 0);
ret = close(us_fd);
TEST_ASSERT_TRUE(ret >= 0);
us_fd = -1;
}
/****************************************************************************
* Name: ReopenRw
*
* Description:
* Repeated simple test for opening and closing usrsock node, reopen should
* work
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST(CharDev, ReopenRw)
{
int ret;
us_fd = open(USRSOCK_NODE, O_RDWR);
TEST_ASSERT_TRUE(us_fd >= 0);
ret = close(us_fd);
TEST_ASSERT_TRUE(ret >= 0);
us_fd = -1;
us_fd = open(USRSOCK_NODE, O_RDWR);
TEST_ASSERT_TRUE(us_fd >= 0);
ret = close(us_fd);
TEST_ASSERT_TRUE(ret >= 0);
us_fd = -1;
}
/****************************************************************************
* Name: NoMultipleOpen
*
* Description:
* No permission for multiple access,
* first user should be only user.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST(CharDev, NoMultipleOpen)
{
us_fd = open(USRSOCK_NODE, O_RDWR);
TEST_ASSERT_TRUE(us_fd >= 0);
us_fd_two = open(USRSOCK_NODE, O_RDWR);
TEST_ASSERT_FALSE(us_fd_two >= 0);
TEST_ASSERT_EQUAL(EPERM, errno);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(CharDev)
{
RUN_TEST_CASE(CharDev, OpenRw);
RUN_TEST_CASE(CharDev, ReopenRw);
RUN_TEST_CASE(CharDev, NoMultipleOpen);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,284 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_main.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <debug.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <poll.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defines.h"
/****************************************************************************
* Definitions
****************************************************************************/
#ifndef dbg
#define dbg _warn
#endif
#define usrsocktest_dbg(...) ((void)0)
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static struct
{
unsigned int ok;
unsigned int failed;
unsigned int nchecks;
} overall;
/****************************************************************************
* Public Data
****************************************************************************/
int usrsocktest_endp_malloc_cnt = 0;
int usrsocktest_dcmd_malloc_cnt = 0;
bool usrsocktest_test_failed = false;
/****************************************************************************
* Private Functions
****************************************************************************/
static void get_mallinfo(struct mallinfo *mem)
{
#ifdef CONFIG_CAN_PASS_STRUCTS
*mem = mallinfo();
#else
(void)mallinfo(mem);
#endif
}
static void print_mallinfo(const struct mallinfo *mem, const char *title)
{
if (title)
printf("%s:\n", title);
printf(" %11s%11s%11s%11s\n", "total", "used", "free", "largest");
printf("Mem: %11d%11d%11d%11d\n",
mem->arena, mem->uordblks, mem->fordblks, mem->mxordblk);
}
static void utest_assert_print_head(FAR const char *func, const int line,
FAR const char *check_str)
{
printf("\t[TEST ASSERT FAILED!]\n"
"\t\tIn function \"%s\":\n"
"\t\tline %d: Assertion `%s' failed.\n", func, line, check_str);
}
static void run_tests(FAR const char *name, void (CODE *test_fn)(void))
{
printf("Testing group \"%s\" =>\n", name);
fflush(stdout);
fflush(stderr);
usrsocktest_test_failed = false;
test_fn();
if (!usrsocktest_test_failed)
{
printf("\tGroup \"%s\": [OK]\n", name);
overall.ok++;
}
else
{
printf("\tGroup \"%s\": [FAILED]\n", name);
overall.failed++;
}
fflush(stdout);
fflush(stderr);
}
/****************************************************************************
* Name: runAllTests
*
* Description:
* Sequentially runs all included test groups
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void runAllTests(void)
{
RUN_TEST_GROUP(CharDev);
RUN_TEST_GROUP(NoDaemon);
RUN_TEST_GROUP(BasicDaemon);
RUN_TEST_GROUP(BasicConnect);
RUN_TEST_GROUP(BasicConnectDelay);
RUN_TEST_GROUP(NoBlockConnect);
RUN_TEST_GROUP(BasicSend);
RUN_TEST_GROUP(NoBlockSend);
RUN_TEST_GROUP(BlockSend);
RUN_TEST_GROUP(NoBlockRecv);
RUN_TEST_GROUP(BlockRecv);
RUN_TEST_GROUP(RemoteDisconnect);
RUN_TEST_GROUP(BasicSetSockOpt);
RUN_TEST_GROUP(BasicGetSockOpt);
RUN_TEST_GROUP(BasicGetSockName);
RUN_TEST_GROUP(WakeWithSignal);
RUN_TEST_GROUP(MultiThread);
}
/****************************************************************************
* Public Functions
****************************************************************************/
bool usrsocktest_assert_print_value(FAR const char *func,
const int line,
FAR const char *check_str,
long int test_value,
long int should_be)
{
++overall.nchecks;
if (test_value == should_be)
{
int keep_errno = errno;
usrsocktest_dbg("%d => OK.\n", line);
errno = keep_errno;
return true;
}
utest_assert_print_head(func, line, check_str);
printf("\t\t\tgot value: %ld\n", test_value);
printf("\t\t\tshould be: %ld\n", should_be);
fflush(stdout);
fflush(stderr);
return false;
}
bool usrsocktest_assert_print_buf(FAR const char *func,
const int line,
FAR const char *check_str,
FAR const void *test_buf,
FAR const void *expect_buf,
size_t buflen)
{
++overall.nchecks;
if (memcmp(test_buf, expect_buf, buflen) == 0)
{
int keep_errno = errno;
usrsocktest_dbg("%d => OK.\n", line);
errno = keep_errno;
return true;
}
utest_assert_print_head(func, line, check_str);
fflush(stdout);
fflush(stderr);
return false;
}
/****************************************************************************
* usrsocktest_main
****************************************************************************/
#ifdef CONFIG_BUILD_KERNEL
int main(int argc, FAR char *argv[])
#else
int usrsocktest_main(int argc, char *argv[])
#endif
{
struct mallinfo mem_before, mem_after;
memset(&overall, 0, sizeof(overall));
printf("Starting unit-tests...\n");
fflush(stdout);
fflush(stderr);
get_mallinfo(&mem_before);
runAllTests();
printf("Unit-test groups done... OK:%d, FAILED:%d, TOTAL:%d\n",
overall.ok, overall.failed, overall.ok + overall.failed);
printf(" -- number of checks made: %d\n", overall.nchecks);
fflush(stdout);
fflush(stderr);
get_mallinfo(&mem_after);
print_mallinfo(&mem_before, "HEAP BEFORE TESTS");
print_mallinfo(&mem_after, "HEAP AFTER TESTS");
fflush(stdout);
fflush(stderr);
exit(0);
return 0;
}

View File

@ -0,0 +1,267 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_multi_thread.c
* Multi-threaded access to sockets
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static pthread_t tids[4];
static int sds[4];
static bool started;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
static void usrsock_socket_multitask_do_work(int *sd)
{
struct sockaddr_in addr;
int ret;
int i;
for (i = 0; i < 10; i++)
{
/* Simple test for opening socket with usrsock daemon running. */
*sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(*sd >= 0);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(*sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
/* Close socket */
TEST_ASSERT_TRUE(close(*sd) >= 0);
*sd = -1;
}
}
static FAR void *usrsock_socket_multitask_thread(FAR void *param)
{
usrsock_socket_multitask_do_work((int*)param);
return NULL;
}
/****************************************************************************
* Name: MultiThread test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(MultiThread)
{
int i;
for (i = 0; i < ARRAY_SIZE(sds); i++)
{
sds[i] = -1;
}
for (i = 0; i < ARRAY_SIZE(tids); i++)
{
tids[i] = -1;
}
started = false;
}
/****************************************************************************
* Name: MultiThread test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(MultiThread)
{
int ret;
int i;
for (i = 0; i < ARRAY_SIZE(tids); i++)
{
if (tids[i] != -1)
{
ret = pthread_cancel(tids[i]);
assert(ret == OK);
ret = pthread_join(tids[i], NULL);
assert(ret == OK);
}
}
for (i = 0; i < ARRAY_SIZE(sds); i++)
{
if (sds[i] != -1)
{
ret = close(sds[i]);
assert(ret >= 0);
}
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
/****************************************************************************
* Name: OpenClose
*
* Description:
* Open and close socket with multiple threads
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST(MultiThread, OpenClose)
{
int ret;
int i;
/* Start test daemon. */
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
usrsocktest_daemon_config.endpoint_block_send = false;
usrsocktest_daemon_config.endpoint_block_connect = false;
usrsocktest_daemon_config.endpoint_addr = "127.0.0.1";
usrsocktest_daemon_config.endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(&usrsocktest_daemon_config));
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Launch worker threads. */
for (i = 0; i < ARRAY_SIZE(tids); i++)
{
ret = pthread_create(&tids[i], NULL, usrsock_socket_multitask_thread,
sds + i);
TEST_ASSERT_EQUAL(OK, ret);
}
/* Wait threads to complete work. */
while (--i > -1)
{
pthread_addr_t tparam;
ret = pthread_join(tids[i], &tparam);
TEST_ASSERT_EQUAL(OK, ret);
tids[i] = -1;
/* This flag is set whenever a test fails, otherwise it is not touched
* No need for synchronization. Here we bail from main test thread on
* first failure in any thread.
*/
TEST_ASSERT_FALSE(usrsocktest_test_failed);
}
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(MultiThread)
{
RUN_TEST_CASE(MultiThread, OpenClose);
}

View File

@ -0,0 +1,816 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_noblock_connect.c
* Socket connect tests in non-blocking mode
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd, sd2;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
TEST_SETUP(NoBlockConnect)
{
sd = -1;
sd2 = -1;
started = false;
}
TEST_TEAR_DOWN(NoBlockConnect)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret == 0);
}
if (sd2 >= 0)
{
ret = close(sd2);
assert(ret == 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(NoBlockConnect, InstantConnect)
{
int flags;
int ret;
struct sockaddr_in addr;
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.endpoint_addr = "127.0.0.1";
usrsocktest_daemon_config.endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(&usrsocktest_daemon_config));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Do connect, should succeed instantly. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
TEST(NoBlockConnect, DelayedConnect)
{
int flags, ret, count;
struct sockaddr_in addr;
/* Start test daemon. */
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.endpoint_block_connect = true;
usrsocktest_daemon_config.endpoint_addr = "127.0.0.1";
usrsocktest_daemon_config.endpoint_port = 255;
usrsocktest_daemon_config.delay_all_responses = true;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(&usrsocktest_daemon_config));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempt, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Another connect attempt results EALREADY. */
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EALREADY, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Release delayed connect. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Another connect attempt results EISCONN. */
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
/* Close socket. */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
TEST(NoBlockConnect, CloseNotConnected)
{
int flags, ret;
struct sockaddr_in addr;
/* Start test daemon. */
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.endpoint_block_connect = true;
usrsocktest_daemon_config.endpoint_addr = "127.0.0.1";
usrsocktest_daemon_config.endpoint_port = 255;
usrsocktest_daemon_config.delay_all_responses = true;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(&usrsocktest_daemon_config));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempt, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Close socket. */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
TEST(NoBlockConnect, EarlyDrop)
{
int flags, ret;
struct sockaddr_in addr;
/* Start test daemon. */
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.endpoint_block_connect = true;
usrsocktest_daemon_config.endpoint_addr = "127.0.0.1";
usrsocktest_daemon_config.endpoint_port = 255;
usrsocktest_daemon_config.delay_all_responses = false;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(&usrsocktest_daemon_config));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempt, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
/* Close socket. */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_waiting_connect_sockets());
}
TEST(NoBlockConnect, Multiple)
{
int flags, ret, count;
struct sockaddr_in addr;
/* Start test daemon. */
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.endpoint_block_connect = true;
usrsocktest_daemon_config.endpoint_addr = "127.0.0.1";
usrsocktest_daemon_config.endpoint_port = 255;
usrsocktest_daemon_config.delay_all_responses = false;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(&usrsocktest_daemon_config));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open sockets */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
sd2 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
flags = fcntl(sd2, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd2, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd2, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempts, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd2, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Release delayed connections. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd2, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Release delayed connections. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0;
count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Close sockets. */
TEST_ASSERT_TRUE(close(sd2) >= 0);
sd2 = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Open sockets */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
sd2 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
flags = fcntl(sd2, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd2, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd2, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempts, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
ret = connect(sd2, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Release delayed connections. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Close sockets. */
TEST_ASSERT_TRUE(close(sd2) >= 0);
sd2 = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Open sockets */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
sd2 = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
flags = fcntl(sd2, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd2, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd2, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempt, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Release delayed connections. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Launch another connect attempt, daemon delays actual connection until triggered. */
ret = connect(sd2, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(2, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Close sockets. */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_TRUE(close(sd2) >= 0);
sd2 = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
TEST(NoBlockConnect, Dup2)
{
int flags, ret, count;
struct sockaddr_in addr;
/* Start test daemon. */
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.endpoint_block_connect = true;
usrsocktest_daemon_config.endpoint_addr = "127.0.0.1";
usrsocktest_daemon_config.endpoint_port = 255;
usrsocktest_daemon_config.delay_all_responses = true;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(&usrsocktest_daemon_config));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Duplicate socket */
sd2 = dup(sd);
TEST_ASSERT_TRUE(sd2 >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempt, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Another connect attempt results EALREADY. */
ret = connect(sd2, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EALREADY, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Release delayed connect. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Another connect attempt results EISCONN. */
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
/* Close sockets. */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_TRUE(close(sd2) >= 0);
sd2 = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(NoBlockConnect)
{
RUN_TEST_CASE(NoBlockConnect, InstantConnect);
RUN_TEST_CASE(NoBlockConnect, DelayedConnect);
RUN_TEST_CASE(NoBlockConnect, CloseNotConnected);
RUN_TEST_CASE(NoBlockConnect, EarlyDrop);
RUN_TEST_CASE(NoBlockConnect, Multiple);
RUN_TEST_CASE(NoBlockConnect, Dup2);
}

View File

@ -0,0 +1,521 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_noblock_recv.c
* Receive from the socket in non-blocking mode
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: Receive
*
* Description:
* Non-blocking & instant connect+recv
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Receive(struct usrsocktest_daemon_conf_s *dconf)
{
int flags;
int count;
ssize_t ret;
size_t datalen;
void *data;
struct sockaddr_in addr;
char databuf[4];
struct sockaddr_in remoteaddr;
socklen_t addrlen;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_recv_avail_from_start = true;
dconf->endpoint_recv_avail = 7;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Do connect, should succeed instantly. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
if (!dconf->delay_all_responses)
{
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0,
usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
}
else
{
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0,
usrsocktest_daemon_get_num_waiting_connect_sockets());
for (count = 0; usrsocktest_daemon_get_num_connected_sockets() != 1;
count++)
{
TEST_ASSERT_TRUE(count <= 3);
usleep(25 * 1000);
}
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
}
/* Receive data from remote, daemon returns 4 bytes. */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, NULL);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(4, datalen);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abcd", data, 4);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(4, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote with address, daemon returns 3 bytes. */
addrlen = sizeof(remoteaddr);
ret = recvfrom(sd, data, datalen, 0, (FAR struct sockaddr *)&remoteaddr,
&addrlen);
TEST_ASSERT_EQUAL(3, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abc", data, 3);
TEST_ASSERT_EQUAL(addrlen, sizeof(remoteaddr));
TEST_ASSERT_EQUAL_UINT8_ARRAY(&remoteaddr, &addr, addrlen);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(datalen + ret, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote, daemon has 0 bytes buffered => -EAGAIN */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, NULL);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(7, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote, daemon has 0 bytes buffered => -EAGAIN */
data = databuf;
datalen = sizeof(databuf);
ret = read(sd, data, datalen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(7, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Reset recv buffer for open sockets */
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('r', 0));
for (count = 0; usrsocktest_daemon_get_num_recv_empty_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(5 * 1000);
}
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Receive data from remote, daemon returns 4 bytes. */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, NULL);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(4, datalen);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abcd", data, 4);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(7 + 4, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(7 + 4, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: DelayedConnect
*
* Description:
* Non-blocking & delayed connect
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void DelayedConnect(struct usrsocktest_daemon_conf_s *dconf)
{
int flags;
int count;
ssize_t ret;
size_t datalen;
void *data;
struct sockaddr_in addr;
char databuf[4];
struct sockaddr_in remoteaddr;
socklen_t addrlen;
/* Start test daemon. */
dconf->endpoint_block_connect = true;
dconf->endpoint_recv_avail_from_start = false;
dconf->endpoint_recv_avail = 4;
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempt, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Try receive data, not connected yet. */
data = databuf;
datalen = sizeof(databuf);
ret = read(sd, data, datalen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
/* Release delayed connect. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0;
count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Try receive data, not received data yet. */
data = databuf;
datalen = sizeof(databuf);
addrlen = sizeof(remoteaddr);
ret = recvfrom(sd, data, datalen, 0, (FAR struct sockaddr *)&remoteaddr,
&addrlen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(0, addrlen);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Reset recv buffer for open sockets */
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('r', 0));
for (count = 0; usrsocktest_daemon_get_num_recv_empty_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(5 * 1000);
}
/* Receive data from remote, daemon returns 4 bytes. */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, NULL);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(4, datalen);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abcd", data, 4);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(4, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Close socket. */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV,
usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_recv_empty_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: NoBlockRecv test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(NoBlockRecv)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: NoBlockRecv test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(NoBlockRecv)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(NoBlockRecv, Receive)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Receive(&usrsocktest_daemon_config);
}
TEST(NoBlockRecv, ReceiveDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Receive(&usrsocktest_daemon_config);
}
TEST(NoBlockRecv, DelayedConnect)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
DelayedConnect(&usrsocktest_daemon_config);
}
TEST(NoBlockRecv, DelayedConnectDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
DelayedConnect(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(NoBlockRecv)
{
RUN_TEST_CASE(NoBlockRecv, Receive);
RUN_TEST_CASE(NoBlockRecv, ReceiveDelay);
RUN_TEST_CASE(NoBlockRecv, DelayedConnect);
RUN_TEST_CASE(NoBlockRecv, DelayedConnectDelay);
}

View File

@ -0,0 +1,414 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_noblock_send.c
* Send through the socket in non-blocking mode
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: Send
*
* Description:
* Open socket, connect instantly and send
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void Send(struct usrsocktest_daemon_conf_s *dconf)
{
int flags;
int count;
ssize_t ret;
size_t datalen;
const void *data;
struct sockaddr_in addr;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Do connect, should succeed instantly. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
if (!dconf->delay_all_responses)
{
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
}
else
{
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
for (count = 0; usrsocktest_daemon_get_num_connected_sockets() != 1;
count++)
{
TEST_ASSERT_TRUE(count <= 3);
usleep(25 * 1000);
}
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
}
/* Send data to remote */
data = "abcde";
datalen = strlen("abcde");
ret = sendto(sd, data, datalen, 0, NULL, 0);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(datalen, usrsocktest_daemon_get_send_bytes());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
}
/****************************************************************************
* Name: ConnectSend
*
* Description:
* Open socket, connect is delayed and send
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void ConnectSend(struct usrsocktest_daemon_conf_s *dconf)
{
int flags;
int count;
ssize_t ret;
size_t datalen;
const void *data;
struct sockaddr_in addr;
/* Start test daemon. */
dconf->endpoint_block_connect = true;
dconf->endpoint_block_send = true;
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Launch connect attempt, daemon delays actual connection until triggered. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Send data to remote, not connected yet. */
data = "abcde";
datalen = strlen("abcde");
ret = write(sd, data, datalen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
/* Release delayed connect. */
TEST_ASSERT_TRUE(usrsocktest_daemon_establish_waiting_connections());
for (count = 0; usrsocktest_daemon_get_num_waiting_connect_sockets() > 0;
count++)
{
TEST_ASSERT_TRUE(count <= 5);
usleep(10 * 1000);
}
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Send data to remote */
data = "abcde";
datalen = strlen("abcde");
ret = write(sd, data, datalen);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EAGAIN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_send_bytes());
/* Close socket. */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV,
usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: NoBlockSend test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(NoBlockSend)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: NoBlockSend test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(NoBlockSend)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(NoBlockSend, Send)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
Send(&usrsocktest_daemon_config);
}
TEST(NoBlockSend, SendDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
Send(&usrsocktest_daemon_config);
}
TEST(NoBlockSend, ConnectSend)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
ConnectSend(&usrsocktest_daemon_config);
}
TEST(NoBlockSend, ConnectSendDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
ConnectSend(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(NoBlockSend)
{
RUN_TEST_CASE(NoBlockSend, Send);
RUN_TEST_CASE(NoBlockSend, SendDelay);
RUN_TEST_CASE(NoBlockSend, ConnectSend);
RUN_TEST_CASE(NoBlockSend, ConnectSendDelay);
}

View File

@ -0,0 +1,154 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_nodaemon.c
* Tests without user socket daemon
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: NoDaemon test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(NoDaemon)
{
sd = -1;
}
/****************************************************************************
* Name: NoDaemon test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(NoDaemon)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
}
/****************************************************************************
* Name: NoSocket
*
* Description:
* Simple test for opening socket without usrsock daemon running
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST(NoDaemon, NoSocket)
{
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_EQUAL(-1, sd);
TEST_ASSERT_TRUE(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT || errno == ENETDOWN);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(NoDaemon)
{
RUN_TEST_CASE(NoDaemon, NoSocket);
}

View File

@ -0,0 +1,646 @@
/****************************************************************************
* examples/usrsocktest/usrsocktest_poll.c
* User socket polling tests
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Authors: Roman Saveljev <roman.saveljev@haltian.com>
* Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <errno.h>
#include <sys/types.h>
#include <stdbool.h>
#include <assert.h>
#include <fcntl.h>
#include <poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "defines.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static bool started;
static int sd;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ConnectReceive
*
* Description:
* Non-blocking connect and receive
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void ConnectReceive(struct usrsocktest_daemon_conf_s *dconf)
{
int flags;
int count;
ssize_t ret;
size_t datalen;
void *data;
struct sockaddr_in addr;
char databuf[4];
struct pollfd pfd;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_recv_avail_from_start = false;
dconf->endpoint_recv_avail = 3;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Poll for input (instant timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, 0);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLERR);
TEST_ASSERT_EQUAL(POLLHUP, pfd.revents & POLLHUP);
TEST_ASSERT_EQUAL(POLLIN, pfd.revents & POLLIN);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLOUT);
/* Do connect, should succeed instantly. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
if (!dconf->delay_all_responses)
{
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
}
else
{
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
for (count = 0; usrsocktest_daemon_get_num_connected_sockets() != 1; count++)
{
TEST_ASSERT_TRUE(count <= 3);
usleep(25 * 1000);
}
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
}
/* Poll for input (instant timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, 0);
TEST_ASSERT_EQUAL(0, ret);
/* Poll for input (with timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, 10);
TEST_ASSERT_EQUAL(0, ret);
/* Poll for input (no timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('r', 100));
ret = poll(&pfd, 1, -1);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(POLLIN, pfd.revents);
/* Receive data from remote, daemon returns 3 bytes. */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, NULL);
TEST_ASSERT_EQUAL(3, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abc", data, 3);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(3, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Poll for input (instant timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, 0);
TEST_ASSERT_EQUAL(0, ret);
/* Make more data avail */
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('r', 0));
for (count = 0; usrsocktest_daemon_get_num_recv_empty_sockets() > 0; count++)
{
TEST_ASSERT_TRUE(count <= 3);
usleep(5 * 1000);
}
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Poll for input (no timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, -1);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(POLLIN, pfd.revents);
/* Receive data from remote, daemon returns 3 bytes. */
data = databuf;
datalen = sizeof(databuf);
ret = recvfrom(sd, data, datalen, 0, NULL, NULL);
TEST_ASSERT_EQUAL(3, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY("abc", data, 3);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(6, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(6, usrsocktest_daemon_get_recv_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: ConnectSend
*
* Description:
* Non-blocking connect and receive
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void ConnectSend(struct usrsocktest_daemon_conf_s *dconf)
{
int flags;
ssize_t ret;
size_t datalen;
void *data;
struct sockaddr_in addr;
struct pollfd pfd;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_recv_avail_from_start = true;
dconf->endpoint_recv_avail = 3;
dconf->endpoint_block_send = false;
dconf->endpoint_block_connect = true;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Poll for input (instant timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, 0);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLERR);
TEST_ASSERT_EQUAL(POLLHUP, pfd.revents & POLLHUP);
TEST_ASSERT_EQUAL(POLLIN, pfd.revents & POLLIN);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLOUT);
/* Start non-blocking connect. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Poll for input (no timeout). As send is ready after established connection,
* poll will exit with POLLOUT. */
memset(&pfd, 0, sizeof(pfd));
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('E', 100));
pfd.fd = sd;
pfd.events = POLLOUT;
ret = poll(&pfd, 1, -1);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(POLLOUT, pfd.revents);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EISCONN, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Send data to remote. */
data = "abcdeFG";
datalen = strlen(data);
ret = write(sd, data, datalen);
TEST_ASSERT_EQUAL(datalen, ret);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(datalen, usrsocktest_daemon_get_send_bytes());
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(datalen, usrsocktest_daemon_get_send_bytes());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_recv_empty_sockets());
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
}
/****************************************************************************
* Name: DaemonAbort
*
* Description:
* Poll with daemon abort
*
* Input Parameters:
* dconf - socket daemon configuration
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
static void DaemonAbort(struct usrsocktest_daemon_conf_s *dconf)
{
int flags;
ssize_t ret;
struct sockaddr_in addr;
struct pollfd pfd;
/* Start test daemon. */
dconf->endpoint_addr = "127.0.0.1";
dconf->endpoint_port = 255;
dconf->endpoint_recv_avail_from_start = false;
dconf->endpoint_recv_avail = 3;
dconf->endpoint_block_send = false;
dconf->endpoint_block_connect = true;
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_start(dconf));
started = true;
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_active_sockets());
/* Open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
TEST_ASSERT_TRUE(sd >= 0);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Make socket non-blocking */
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(0, flags & O_NONBLOCK);
ret = fcntl(sd, F_SETFL, flags | O_NONBLOCK);
TEST_ASSERT_EQUAL(0, ret);
flags = fcntl(sd, F_GETFL, 0);
TEST_ASSERT_TRUE(flags >= 0);
TEST_ASSERT_EQUAL(O_RDWR, flags & O_RDWR);
TEST_ASSERT_EQUAL(O_NONBLOCK, flags & O_NONBLOCK);
/* Poll for input (instant timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, 0);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLERR);
TEST_ASSERT_EQUAL(POLLHUP, pfd.revents & POLLHUP);
TEST_ASSERT_EQUAL(POLLIN, pfd.revents & POLLIN);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLOUT);
/* Start non-blocking connect. */
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(255);
ret = connect(sd, (FAR const struct sockaddr *)&addr, sizeof(addr));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINPROGRESS, errno);
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(1, usrsocktest_daemon_get_num_waiting_connect_sockets());
/* Poll for input (no timeout). Stop daemon forcefully. */
memset(&pfd, 0, sizeof(pfd));
TEST_ASSERT_TRUE(usrsocktest_send_delayed_command('S', 100));
pfd.fd = sd;
pfd.events = POLLOUT;
ret = poll(&pfd, 1, -1);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(POLLERR, pfd.revents & POLLERR);
TEST_ASSERT_EQUAL(POLLHUP, pfd.revents & POLLHUP);
/* Stopping daemon should succeed. */
TEST_ASSERT_EQUAL(OK, usrsocktest_daemon_stop());
started = false;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(0, usrsocktest_endp_malloc_cnt);
TEST_ASSERT_EQUAL(0, usrsocktest_dcmd_malloc_cnt);
/* Poll for input (no timeout). */
memset(&pfd, 0, sizeof(pfd));
pfd.fd = sd;
pfd.events = POLLOUT;
ret = poll(&pfd, 1, -1);
TEST_ASSERT_EQUAL(1, ret);
TEST_ASSERT_EQUAL(POLLERR, pfd.revents & POLLERR);
TEST_ASSERT_EQUAL(POLLHUP, pfd.revents & POLLHUP);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLIN);
TEST_ASSERT_EQUAL(0, pfd.revents & POLLOUT);
/* Close socket */
TEST_ASSERT_TRUE(close(sd) >= 0);
sd = -1;
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_active_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_connected_sockets());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_send_bytes());
TEST_ASSERT_EQUAL(-ENODEV, usrsocktest_daemon_get_num_recv_empty_sockets());
}
/****************************************************************************
* Name: Poll test group setup
*
* Description:
* Setup function executed before each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_SETUP(Poll)
{
sd = -1;
started = false;
}
/****************************************************************************
* Name: Poll test group teardown
*
* Description:
* Setup function executed after each testcase in this test group
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions/Limitations:
* None
*
****************************************************************************/
TEST_TEAR_DOWN(Poll)
{
int ret;
if (sd >= 0)
{
ret = close(sd);
assert(ret >= 0);
}
if (started)
{
ret = usrsocktest_daemon_stop();
assert(ret == OK);
}
}
TEST(Poll, ConnectReceive)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
ConnectReceive(&usrsocktest_daemon_config);
}
TEST(Poll, ConnectReceiveDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
ConnectReceive(&usrsocktest_daemon_config);
}
TEST(Poll, ConnectSend)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
ConnectSend(&usrsocktest_daemon_config);
}
TEST(Poll, ConnectSendDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
ConnectSend(&usrsocktest_daemon_config);
}
TEST(Poll, DaemonAbort)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
DaemonAbort(&usrsocktest_daemon_config);
}
TEST(Poll, DaemonAbortDelay)
{
usrsocktest_daemon_config = usrsocktest_daemon_defconf;
usrsocktest_daemon_config.delay_all_responses = true;
DaemonAbort(&usrsocktest_daemon_config);
}
/****************************************************************************
* Public Functions
****************************************************************************/
TEST_GROUP(Poll)
{
RUN_TEST_CASE(Poll, ConnectReceive);
RUN_TEST_CASE(Poll, ConnectReceiveDelay);
RUN_TEST_CASE(Poll, ConnectSend);
RUN_TEST_CASE(Poll, ConnectSendDelay);
RUN_TEST_CASE(Poll, DaemonAbort);
RUN_TEST_CASE(Poll, DaemonAbortDelay);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,8 @@
#include <stdbool.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/ethernet.h>
#include <nuttx/net/ip.h>
/****************************************************************************
* Pre-processor Definitions

View File

@ -575,7 +575,7 @@ static int nsh_gethostip(FAR char *hostname, FAR union ip_addr_u *ipaddr,
static void wget_callback(FAR char **buffer, int offset, int datend,
FAR int *buflen, FAR void *arg)
{
(void)write((int)arg, &((*buffer)[offset]), datend - offset);
(void)write((int)((intptr_t)arg), &((*buffer)[offset]), datend - offset);
}
#endif
#endif
@ -1668,7 +1668,7 @@ int cmd_wget(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/* And perform the wget */
ret = wget(url, buffer, 512, wget_callback, (FAR void *)fd);
ret = wget(url, buffer, 512, wget_callback, (FAR void *)((intptr_t)fd));
if (ret < 0)
{
nsh_output(vtbl, g_fmtcmdfailed, argv[0], "wget", NSH_ERRNO);