diff --git a/TESTS/netsocket/tcp/main.cpp b/TESTS/netsocket/tcp/main.cpp index ba1e587580..3988711f76 100644 --- a/TESTS/netsocket/tcp/main.cpp +++ b/TESTS/netsocket/tcp/main.cpp @@ -93,6 +93,7 @@ void greentea_teardown(const size_t passed, const size_t failed, const failure_t Case cases[] = { Case("Echo burst", test_tcpsocket_echotest_burst), Case("Echo burst non-block", test_tcpsocket_echotest_burst_nonblock), + Case("Open at least 4 sockets", test_tcpsocket_open_limit), Case("Receive 100k from CHARGEN service", test_tcpsocket_recv_100k), Case("Receive 100k from CHARGEN service non-block", test_tcpsocket_recv_100k_nonblock), Case("Receive in given time", test_tcpsocket_recv_timeout), diff --git a/TESTS/netsocket/tcp/tcp_tests.h b/TESTS/netsocket/tcp/tcp_tests.h index 623bc7b99f..a62f153141 100644 --- a/TESTS/netsocket/tcp/tcp_tests.h +++ b/TESTS/netsocket/tcp/tcp_tests.h @@ -28,6 +28,7 @@ void fill_tx_buffer_ascii(char *buff, size_t len); void test_tcpsocket_echotest_burst(); void test_tcpsocket_echotest_burst_nonblock(); void test_tcpsocket_endpoint_close(); +void test_tcpsocket_open_limit(); void test_tcpsocket_recv_100k(); void test_tcpsocket_recv_100k_nonblock(); void test_tcpsocket_recv_timeout(); diff --git a/TESTS/netsocket/tcp/tcpsocket_open_limit.cpp b/TESTS/netsocket/tcp/tcpsocket_open_limit.cpp new file mode 100644 index 0000000000..f2493d86c1 --- /dev/null +++ b/TESTS/netsocket/tcp/tcpsocket_open_limit.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "greentea-client/test_env.h" +#include "mbed.h" +#include MBED_CONF_APP_HEADER_FILE +#include "tcp_tests.h" +#include "TCPSocket.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + +namespace +{ + typedef struct TCPSocketItem { + TCPSocket *sock; + TCPSocketItem *next; + } SocketItem; +} + +void test_tcpsocket_open_limit() +{ + int open_sockets[2] = {0}; + + for (int i = 0; i < 2; i++) { + TCPSocketItem *socket_list_head = NULL; + TCPSocketItem *it; + + TCPSocket *sock; + int ret; + while (true) { + sock = new TCPSocket; + if (!sock) { + break; + } + ret = sock->open(get_interface()); + if (ret == NSAPI_ERROR_NO_MEMORY || ret == NSAPI_ERROR_NO_SOCKET) { + printf("[round#%02d] unable to open new socket, error: %d\n", i, ret); + delete sock; + break; + } + + // Hopefully this doesn't interfere when trying to allocate more sockets + it = new TCPSocketItem; + if (!it) { + delete sock; + break; + } + + it->sock = sock; + // Order of items in the list doesn't matter + it->next = socket_list_head; + socket_list_head = it; + } + + if (!socket_list_head) { + break; + } + + TCPSocketItem *tmp; + for(TCPSocketItem *it = socket_list_head; it;) { + ++open_sockets[i]; + tmp = it; + it = it->next; + socket_list_head = it; + delete tmp->sock; + delete tmp; + } + printf("[round#%02d] %d sockets opened\n", i, open_sockets[i]); + } + TEST_ASSERT_EQUAL(open_sockets[0], open_sockets[1]); + TEST_ASSERT(open_sockets[0] >= 4); +} diff --git a/TESTS/netsocket/udp/main.cpp b/TESTS/netsocket/udp/main.cpp index 86573d625d..4d86c96fbd 100644 --- a/TESTS/netsocket/udp/main.cpp +++ b/TESTS/netsocket/udp/main.cpp @@ -80,6 +80,7 @@ void greentea_teardown(const size_t passed, const size_t failed, const failure_t Case cases[] = { Case("Echo burst", test_udpsocket_echotest_burst), Case("Echo burst non-block", test_udpsocket_echotest_burst_nonblock), + Case("Open at least 3 sockets", test_udpsocket_open_limit), Case("Receive in given time", test_udpsocket_recv_timeout), Case("Send in given time", test_udpsocket_sendto_timeout), diff --git a/TESTS/netsocket/udp/udp_tests.h b/TESTS/netsocket/udp/udp_tests.h index a18e30ed9f..ba33fa41fc 100644 --- a/TESTS/netsocket/udp/udp_tests.h +++ b/TESTS/netsocket/udp/udp_tests.h @@ -26,6 +26,7 @@ void fill_tx_buffer_ascii(char *buff, size_t len); */ void test_udpsocket_echotest_burst(); void test_udpsocket_echotest_burst_nonblock(); +void test_udpsocket_open_limit(); void test_udpsocket_recv_timeout(); void test_udpsocket_sendto_timeout(); diff --git a/TESTS/netsocket/udp/udpsocket_open_limit.cpp b/TESTS/netsocket/udp/udpsocket_open_limit.cpp new file mode 100644 index 0000000000..d8cc96c458 --- /dev/null +++ b/TESTS/netsocket/udp/udpsocket_open_limit.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "greentea-client/test_env.h" +#include "mbed.h" +#include MBED_CONF_APP_HEADER_FILE +#include "udp_tests.h" +#include "UDPSocket.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + +namespace +{ + typedef struct UDPSocketItem { + UDPSocket *sock; + UDPSocketItem *next; + } SocketItem; +} + +void test_udpsocket_open_limit() +{ + int open_sockets[2] = {0}; + + for (int i = 0; i < 2; i++) { + UDPSocketItem *socket_list_head = NULL; + UDPSocketItem *it; + + UDPSocket *sock; + int ret; + while (true) { + sock = new UDPSocket; + if (!sock) { + break; + } + ret = sock->open(get_interface()); + if (ret == NSAPI_ERROR_NO_MEMORY || ret == NSAPI_ERROR_NO_SOCKET) { + printf("[round#%02d] unable to open new socket, error: %d\n", i, ret); + delete sock; + break; + } + + // Hopefully this doesn't interfere when trying to allocate more sockets + it = new UDPSocketItem; + if (!it) { + delete sock; + break; + } + + it->sock = sock; + // Order of items in the list doesn't matter + it->next = socket_list_head; + socket_list_head = it; + } + + if (!socket_list_head) { + break; + } + + UDPSocketItem *tmp; + for(UDPSocketItem *it = socket_list_head; it;) { + ++open_sockets[i]; + tmp = it; + it = it->next; + socket_list_head = it; + delete tmp->sock; + delete tmp; + } + printf("[round#%02d] %d sockets opened\n", i, open_sockets[i]); + } + TEST_ASSERT_EQUAL(open_sockets[0], open_sockets[1]); + // In case of lwIP one is taken by DHCP -> reduction by one to three + TEST_ASSERT(open_sockets[0] >= 3); +}