Starts adding more TCP and UDP performance tests

Starts splitting Greentea test suites to TCP and UDP suites and adds
more test cases like

	tcpsocket_echotest_burst
	tcpsocket_echotest_burst_nonblock
	tcpsocket_endpoint_close
	tcpsocket_recv_100k
	tcpsocket_recv_100k
	tcpsocket_recv_timeout
	tcpsocket_send_timeout
	tcpsocket_thread_per_socket_safety
	udpsocket_echotest_burst
	udpsocket_echotest_burst_nonblock
	udpsocket_recv_timeout
	udpsocket_sendto_timeout
pull/6665/head
Veijo Pesonen 2018-04-23 09:34:54 +03:00 committed by Seppo Takalo
parent 2f410b0ce2
commit f04f7c1773
13 changed files with 1282 additions and 0 deletions

View File

@ -0,0 +1,109 @@
/*
* 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.
*/
#ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target.
#endif
#ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Pressure tests are not supported by default
#endif
#include "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "utest/utest_stack_trace.h"
#include "tcp_tests.h"
using namespace utest::v1;
#ifndef MBED_CFG_TCP_CLIENT_ECHO_TIMEOUT
#define MBED_CFG_TCP_CLIENT_ECHO_TIMEOUT 500 //[ms]
#endif
static NetworkInterface* net;
NetworkInterface* get_interface()
{
return net;
}
void drop_bad_packets(TCPSocket& sock) {
nsapi_error_t err;
sock.set_timeout(0);
while (true) {
err = sock.recv(NULL, 0);
if (err == NSAPI_ERROR_WOULD_BLOCK) {
break;
}
}
sock.set_timeout(MBED_CFG_TCP_CLIENT_ECHO_TIMEOUT);
}
static void _ifup() {
net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
nsapi_error_t err = MBED_CONF_APP_CONNECT_STATEMENT;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address());
}
static void _ifdown() {
net->disconnect();
printf("MBED: ifdown\n");
}
void fill_tx_buffer_ascii(char *buff, size_t len)
{
for (size_t i = 0; i<len; ++i) {
buff[i] = (rand() % 43) + '0';
}
}
// Test setup
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(240, "default_auto");
_ifup();
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
_ifdown();
return greentea_test_teardown_handler(passed, failed, failure);
}
Case cases[] = {
Case("Echo burst", test_tcpsocket_echotest_burst),
Case("Echo burst non-block", test_tcpsocket_echotest_burst_nonblock),
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),
Case("Sending shall not take too long", test_tcpsocket_send_timeout),
Case("Parallel socket thread safety", test_tcpsocket_thread_per_socket_safety),
Case("Endpoint initiated close", test_tcpsocket_endpoint_close),
};
Specification specification(greentea_setup, cases, greentea_teardown);
int main()
{
return !Harness::run(specification);
}

View File

@ -0,0 +1,37 @@
/*
* 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.
*/
#ifndef TCP_TESTS_H
#define TCP_TESTS_H
NetworkInterface* get_interface();
void drop_bad_packets(TCPSocket& sock);
void fill_tx_buffer_ascii(char *buff, size_t len);
/*
* Test cases
*/
void test_tcpsocket_echotest_burst();
void test_tcpsocket_echotest_burst_nonblock();
void test_tcpsocket_endpoint_close();
void test_tcpsocket_recv_100k();
void test_tcpsocket_recv_100k_nonblock();
void test_tcpsocket_recv_timeout();
void test_tcpsocket_send_timeout();
void test_tcpsocket_thread_per_socket_safety();
#endif //TCP_TESTS_H

View File

@ -0,0 +1,154 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "TCPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "tcp_tests.h"
#define SIGNAL_SIGIO 0x1
#define SIGIO_TIMEOUT 5000 //[ms]
namespace
{
static const int BURST_CNT = 100;
static const int BURST_SIZE = 1220;
char rx_buffer[BURST_SIZE] = {0};
char tx_buffer[BURST_SIZE] = {0};
}
static void _sigio_handler(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO);
}
void test_tcpsocket_echotest_burst()
{
SocketAddress tcp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &tcp_addr);
tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
TCPSocket sock;
sock.open(get_interface());
sock.connect(tcp_addr);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
// TX buffer to be preserved for comparison
fill_tx_buffer_ascii(tx_buffer, BURST_SIZE);
int recvd;
int bt_left;
int sent;
for (int i = 0; i < BURST_CNT; i++) {
bt_left = BURST_SIZE;
while (bt_left > 0) {
sent = sock.send(&(tx_buffer[BURST_SIZE-bt_left]), bt_left);
if (sent == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) {
TEST_FAIL();
}
continue;
} else if (sent < 0) {
printf("[%02d] network error %d\n", i, sent);
TEST_FAIL();
}
bt_left -= sent;
}
bt_left = BURST_SIZE;
while (bt_left > 0) {
recvd = sock.recv(&(rx_buffer[BURST_SIZE-bt_left]), BURST_SIZE);
if (recvd < 0) {
printf("[%02d] network error %d\n", i, recvd);
break;
}
bt_left -= recvd;
}
if (bt_left != 0) {
drop_bad_packets(sock);
TEST_FAIL();
}
TEST_ASSERT_EQUAL(0, memcmp(tx_buffer, rx_buffer, BURST_SIZE));
}
sock.close();
}
void test_tcpsocket_echotest_burst_nonblock()
{
SocketAddress tcp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &tcp_addr);
tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
TCPSocket sock;
sock.open(get_interface());
sock.connect(tcp_addr);
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
// TX buffer to be preserved for comparison
fill_tx_buffer_ascii(tx_buffer, BURST_SIZE);
int sent;
int recvd;
int bt_left = 0;
for (int i = 0; i < BURST_CNT; i++) {
bt_left = BURST_SIZE;
while (bt_left > 0) {
sent = sock.send(&(tx_buffer[BURST_SIZE-bt_left]), bt_left);
if (sent == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) {
TEST_FAIL();
}
continue;
} else if (sent < 0) {
printf("[%02d] network error %d\n", i, sent);
TEST_FAIL();
}
bt_left -= sent;
}
TEST_ASSERT_EQUAL(0, bt_left);
bt_left = BURST_SIZE;
while (bt_left > 0) {
recvd = sock.recv(&(rx_buffer[BURST_SIZE-bt_left]), BURST_SIZE);
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) {
printf("[bt#%02d] packet timeout...", i);
break;
}
continue;
} else if (recvd < 0) {
printf("[%02d] network error %d\n", i, recvd);
break;
}
bt_left -= recvd;
}
if (bt_left != 0) {
printf("network error %d, missing %d bytes from a burst\n", recvd, bt_left);
drop_bad_packets(sock);
TEST_FAIL();
}
TEST_ASSERT_EQUAL(0, memcmp(tx_buffer, rx_buffer, BURST_SIZE));
}
sock.close();
}

View File

@ -0,0 +1,76 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "TCPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "tcp_tests.h"
using namespace utest::v1;
namespace
{
static const int SIGNAL_SIGIO = 0x1;
static const int SIGIO_TIMEOUT = 5000; //[ms]
}
static void _sigio_handler(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO);
}
static void _tcpsocket_connect_to_daytime_srv(TCPSocket& sock) {
SocketAddress tcp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &tcp_addr);
tcp_addr.set_port(13);
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.connect(tcp_addr));
}
void test_tcpsocket_endpoint_close()
{
static const int MORE_THAN_AVAILABLE = 30;
char buff[MORE_THAN_AVAILABLE];
TCPSocket sock;
_tcpsocket_connect_to_daytime_srv(sock);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
int recvd = 0;
int recvd_total = 0;
while (true) {
recvd = sock.recv(&(buff[recvd_total]), MORE_THAN_AVAILABLE);
if (recvd_total > 0 && recvd == 0) {
break; // Endpoint closed socket, success
} else if (recvd == 0) {
TEST_FAIL();
} else if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) {
TEST_FAIL();
}
continue;
}
recvd_total += recvd;
TEST_ASSERT(recvd_total < MORE_THAN_AVAILABLE);
}
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
}

View File

@ -0,0 +1,148 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "TCPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "tcp_tests.h"
using namespace utest::v1;
#define SIGNAL_SIGIO 0x1
#define SIGIO_TIMEOUT 20000 //[ms]
static void _tcpsocket_connect_to_chargen_srv(TCPSocket& sock) {
SocketAddress tcp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &tcp_addr);
tcp_addr.set_port(19);
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.connect(tcp_addr));
}
/** Generate RFC 864 example pattern.
*
* Pattern is 72 character lines of the ASCII printing characters ending with "\r\n".
* There are 95 printing characters in the ASCII character set.
* Example: `nc echo.mbedcloudtesting.com 19 | dd bs=1 count=222`
* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefg
* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh
* "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi
*
* NOTE: Pattern starts with space, not !
*
* \param offset Start pattern from offset
* \param len Length of pattern to generate.
*/
static void generate_RFC_864_pattern(size_t offset, uint8_t *buf, size_t len)
{
while (len--) {
if (offset % 74 == 72)
*buf++ = '\r';
else if (offset % 74 == 73)
*buf++ = '\n';
else
*buf++ = ' ' + (offset%74 + offset/74) % 95 ;
offset++;
}
}
static void check_RFC_864_pattern(void *rx_buff, const size_t len, const size_t offset)
{
void *ref_buff = malloc(len);
TEST_ASSERT_NOT_NULL(ref_buff);
generate_RFC_864_pattern(offset, (uint8_t*)ref_buff, len);
bool match = memcmp(ref_buff, rx_buff, len) == 0;
free(ref_buff);
TEST_ASSERT(match);
}
void rcv_n_chk_against_rfc864_pattern(TCPSocket& sock) {
static const size_t total_size = 1024 * 100;
static const size_t buff_size = 1220;
uint8_t buff[buff_size];
size_t recvd_size = 0;
// Verify received data
while (recvd_size < total_size) {
int rd = sock.recv(buff, buff_size);
TEST_ASSERT(rd > 0);
check_RFC_864_pattern(buff, rd, recvd_size);
recvd_size += rd;
}
}
void test_tcpsocket_recv_100k()
{
TCPSocket sock;
_tcpsocket_connect_to_chargen_srv(sock);
Timer timer;
timer.start();
rcv_n_chk_against_rfc864_pattern(sock);
timer.stop();
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
printf("MBED: Time taken: %fs\n", timer.read());
}
void rcv_n_chk_against_rfc864_pattern_nonblock(TCPSocket& sock) {
static const size_t total_size = 1024 * 100;
static const size_t buff_size = 1220;
uint8_t buff[buff_size];
size_t recvd_size = 0;
// Verify received data
while (recvd_size < total_size) {
int rd = sock.recv(buff, buff_size);
TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK);
if (rd > 0) {
check_RFC_864_pattern(buff, rd, recvd_size);
recvd_size += rd;
} else if (rd == NSAPI_ERROR_WOULD_BLOCK) {
TEST_ASSERT_NOT_EQUAL(osEventTimeout, osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status);
}
}
}
static void _sigio_handler(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO);
}
void test_tcpsocket_recv_100k_nonblock()
{
TCPSocket sock;
_tcpsocket_connect_to_chargen_srv(sock);
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
Timer timer;
timer.start();
rcv_n_chk_against_rfc864_pattern_nonblock(sock);
timer.stop();
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
printf("MBED: Time taken: %fs\n", timer.read());
}

View File

@ -0,0 +1,76 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "TCPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "tcp_tests.h"
#define SIGNAL_SIGIO 0x1
#define SIGIO_TIMEOUT 5000 //[ms]
static void _sigio_handler(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO);
}
void test_tcpsocket_recv_timeout()
{
SocketAddress tcp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &tcp_addr);
tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
static const int DATA_LEN = 100;
char buff[DATA_LEN] = {0};
TCPSocket sock;
sock.open(get_interface());
sock.connect(tcp_addr);
sock.set_timeout(100);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
int recvd = 0;
int pkt_unrecvd;
Timer timer;
for (int i = 0; i < 5; i++) {
pkt_unrecvd = DATA_LEN;
TEST_ASSERT_EQUAL(DATA_LEN, sock.send(buff, DATA_LEN));
while (pkt_unrecvd) {
timer.reset();
timer.start();
recvd = sock.recv(&(buff[DATA_LEN-pkt_unrecvd]), pkt_unrecvd);
timer.stop();
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) {
TEST_FAIL();
}
printf("MBED: recv() took: %dms\n", timer.read_ms());
TEST_ASSERT_INT_WITHIN(50, (100+200)/2, timer.read_ms());
continue;
} else if (recvd < 0) {
printf("[pkt#%02d] network error %d\n", i, recvd);
TEST_FAIL();
}
pkt_unrecvd -= recvd;
}
}
sock.close();
}

View File

@ -0,0 +1,46 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "TCPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "tcp_tests.h"
using namespace utest::v1;
void test_tcpsocket_send_timeout()
{
TCPSocket sock;
sock.open(get_interface());
sock.connect(MBED_CONF_APP_ECHO_SERVER_ADDR, 9);
int err;
Timer timer;
static const char tx_buffer[] = {'h','e','l','l','o'};
for (int i = 0; i < 10; i++) {
timer.reset();
timer.start();
err = sock.send(tx_buffer, sizeof(tx_buffer));
timer.stop();
TEST_ASSERT_EQUAL(sizeof(tx_buffer), err);
TEST_ASSERT(timer.read_ms() <= 800);
}
sock.close();
}

View File

@ -0,0 +1,159 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "TCPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "tcp_tests.h"
using namespace utest::v1;
#define SIGNAL_SIGIO1 0x1
#define SIGNAL_SIGIO2 0x2
#define SIGIO_TIMEOUT 5000 //[ms]
Thread thread;
static volatile bool running = true;
static void _sigio_handler1(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO1);
}
static void _sigio_handler2(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO2);
}
static void check_const_len_rand_sequence()
{
TCPSocket sock;
sock.open(get_interface());
sock.connect(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT);
sock.sigio(callback(_sigio_handler1, Thread::gettid()));
static const int BUFF_SIZE = 10;
char rx_buff[BUFF_SIZE] = {0};
char tx_buff[BUFF_SIZE] = {0};
int bytes2process;
int recvd;
int sent;
while (running) {
fill_tx_buffer_ascii(tx_buff, BUFF_SIZE);
bytes2process = BUFF_SIZE;
while (bytes2process > 0) {
sent = sock.send(&(tx_buff[BUFF_SIZE-bytes2process]), bytes2process);
if (sent == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO1, SIGIO_TIMEOUT).status == osEventTimeout) {
TEST_FAIL();
}
continue;
} else if (sent < 0) {
printf("network error %d\n", sent);
TEST_FAIL();
}
bytes2process -= sent;
}
bytes2process = BUFF_SIZE;
while (bytes2process > 0) {
recvd = sock.recv(&(rx_buff[BUFF_SIZE-bytes2process]), bytes2process);
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
continue;
} else if (recvd < 0) {
printf("network error %d\n", recvd);
TEST_FAIL();
}
bytes2process -= recvd;
}
if (bytes2process != 0) {
drop_bad_packets(sock);
TEST_FAIL();
}
TEST_ASSERT_EQUAL(0, memcmp(tx_buff, rx_buff, BUFF_SIZE));
}
sock.close();
}
static void check_var_len_rand_sequence()
{
TCPSocket sock;
sock.open(get_interface());
sock.connect(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT);
sock.sigio(callback(_sigio_handler2, Thread::gettid()));
static const int BUFF_SIZE = 1001;
char rx_buff[BUFF_SIZE];
char tx_buff[BUFF_SIZE];
static const int pkt_size_diff = 100;
int bytes2process;
int recvd;
int sent;
for (int i = BUFF_SIZE; i > 0; i -= pkt_size_diff) {
fill_tx_buffer_ascii(tx_buff, i);
bytes2process = i;
while (bytes2process > 0) {
sent = sock.send(&(tx_buff[i-bytes2process]), bytes2process);
if (sent == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO2, SIGIO_TIMEOUT).status == osEventTimeout) {
TEST_FAIL();
}
continue;
} else if (sent < 0) {
printf("[%02d] network error %d\n", i, sent);
TEST_FAIL();
}
bytes2process -= sent;
}
bytes2process = i;
while (bytes2process > 0) {
recvd = sock.recv(&(rx_buff[i-bytes2process]), bytes2process);
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
continue;
} else if (recvd < 0) {
printf("[%02d] network error %d\n", i, recvd);
TEST_FAIL();
}
bytes2process -= recvd;
}
if (bytes2process != 0) {
drop_bad_packets(sock);
TEST_FAIL();
}
TEST_ASSERT_EQUAL(0, memcmp(tx_buff, rx_buff, i));
}
sock.close();
}
void test_tcpsocket_thread_per_socket_safety()
{
thread.start(callback(check_const_len_rand_sequence));
check_var_len_rand_sequence();
running = false;
thread.join();
}

View File

@ -0,0 +1,93 @@
/*
* 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.
*/
#ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target.
#endif
#ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Pressure tests are not supported by default
#endif
#include "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "utest/utest_stack_trace.h"
#include "udp_tests.h"
using namespace utest::v1;
namespace
{
NetworkInterface* net;
}
NetworkInterface* get_interface()
{
return net;
}
static void _ifup() {
net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
nsapi_error_t err = MBED_CONF_APP_CONNECT_STATEMENT;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address());
}
static void _ifdown() {
net->disconnect();
printf("MBED: ifdown\n");
}
void fill_tx_buffer_ascii(char *buff, size_t len)
{
for (size_t i = 0; i<len; ++i) {
buff[i] = (rand() % 43) + '0';
}
}
// Test setup
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "default_auto");
_ifup();
return greentea_test_setup_handler(number_of_cases);
}
void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure)
{
_ifdown();
return greentea_test_teardown_handler(passed, failed, failure);
}
Case cases[] = {
Case("Echo burst", test_udpsocket_echotest_burst),
Case("Echo burst non-block", test_udpsocket_echotest_burst_nonblock),
Case("Receive in given time", test_udpsocket_recv_timeout),
Case("Send in given time", test_udpsocket_sendto_timeout),
};
Specification specification(greentea_setup, cases, greentea_teardown);
int main()
{
return !Harness::run(specification);
}

View File

@ -0,0 +1,32 @@
/*
* 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.
*/
#ifndef UDP_TESTS_H
#define UDP_TESTS_H
NetworkInterface* get_interface();
void fill_tx_buffer_ascii(char *buff, size_t len);
/*
* Test cases
*/
void test_udpsocket_echotest_burst();
void test_udpsocket_echotest_burst_nonblock();
void test_udpsocket_recv_timeout();
void test_udpsocket_sendto_timeout();
#endif //UDP_TESTS_H

View File

@ -0,0 +1,217 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "UDPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "udp_tests.h"
#define SIGNAL_SIGIO 0x1
#define SIGIO_TIMEOUT 5000 //[ms]
namespace
{
typedef struct pkg {
int len;
char *payload;
} pkg_t;
static const int BURST_CNT = 100;
static const int BURST_PKTS = 5;
static const int PKG_SIZES[BURST_PKTS] = {100, 200, 300, 120, 500};
static const int RECV_TOTAL = 1220;
pkg_t tx_buffers[BURST_PKTS];
char rx_buffer[500] = {0};
}
void prepare_tx_buffers() {
// TX buffers to be preserved for comparison
for (int x = 0; x < BURST_PKTS; x++) {
tx_buffers[x].len = PKG_SIZES[x];
tx_buffers[x].payload = (char*) (malloc(PKG_SIZES[x]));
TEST_ASSERT_NOT_NULL(tx_buffers[x].payload);
fill_tx_buffer_ascii(tx_buffers[x].payload, tx_buffers[x].len);
}
}
void free_tx_buffers() {
for (int x = 0; x < BURST_PKTS; x++) {
free(tx_buffers[x].payload);
}
}
void drop_bad_packets(UDPSocket& sock) {
nsapi_error_t err;
sock.set_timeout(0);
while (true) {
err = sock.recvfrom(NULL, NULL, 0);
if (err == NSAPI_ERROR_WOULD_BLOCK) {
break;
}
}
sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT);
}
void test_udpsocket_echotest_burst()
{
SocketAddress udp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr);
udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
UDPSocket sock;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
sock.set_timeout(5000);
// TX buffers to be preserved for comparison
prepare_tx_buffers();
int ok_bursts = 0;
int pkg_fail = 0;
SocketAddress temp_addr;
int recvd = 0;
int bt_total = 0;
for (int i = 0; i < BURST_CNT; i++) {
for (int x = 0; x < BURST_PKTS; x++) {
TEST_ASSERT_EQUAL(tx_buffers[x].len, sock.sendto(udp_addr, tx_buffers[x].payload, tx_buffers[x].len));
}
recvd = 0;
bt_total = 0;
for (int j = 0; j < BURST_PKTS; j++) {
recvd = sock.recvfrom(&temp_addr, rx_buffer, 500);
if (recvd < 0) {
pkg_fail++;
printf("[%02d] network error %d\n", i, recvd);
continue;
} else if (temp_addr != udp_addr) {
printf("[%02d] packet from wrong address\n", i);
continue;
}
// Packets might arrive unordered
for (int k = 0; k < BURST_PKTS; k++) {
if (tx_buffers[k].len == recvd &&
(memcmp(tx_buffers[k].payload, rx_buffer, recvd) == 0)) {
bt_total += recvd;
goto PKT_OK;
}
}
pkg_fail++;
break;
PKT_OK:
continue;
}
if (bt_total == RECV_TOTAL) {
ok_bursts++;
} else {
drop_bad_packets(sock);
printf("[%02d] burst failure\n", i);
}
}
free_tx_buffers();
// Packet loss up to 10% tolerated
TEST_ASSERT_INT_WITHIN((BURST_CNT*BURST_PKTS/10), BURST_CNT*BURST_PKTS, BURST_CNT*BURST_PKTS-pkg_fail);
// 90% of the bursts need to be successful
TEST_ASSERT_INT_WITHIN((BURST_CNT/10), BURST_CNT, ok_bursts);
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
}
static void _sigio_handler(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO);
}
void test_udpsocket_echotest_burst_nonblock()
{
SocketAddress udp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr);
udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
UDPSocket sock;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
// TX buffers to be preserved for comparison
prepare_tx_buffers();
int ok_bursts = 0;
int pkg_fail = 0;
SocketAddress temp_addr;
int recvd = 0;
int bt_total = 0;
for (int i = 0; i < BURST_CNT; i++) {
for (int x = 0; x < BURST_PKTS; x++) {
TEST_ASSERT_EQUAL(tx_buffers[x].len, sock.sendto(udp_addr, tx_buffers[x].payload, tx_buffers[x].len));
}
recvd = 0;
bt_total = 0;
for (int j = 0; j < BURST_PKTS; j++) {
recvd = sock.recvfrom(&temp_addr, rx_buffer, 500);
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) {
pkg_fail += BURST_PKTS-j;
break;
}
--j;
continue;
} else if (recvd < 0) {
pkg_fail++;
continue;
} else if (temp_addr != udp_addr) {
continue;
}
// Packets might arrive unordered
for (int k = 0; k < BURST_PKTS; k++) {
if (tx_buffers[k].len == recvd &&
(memcmp(tx_buffers[k].payload, rx_buffer, recvd) == 0)) {
bt_total += recvd;
goto PKT_OK;
}
}
printf("[bt#%02d] corrupted packet...", i);
pkg_fail++;
break;
PKT_OK:
continue;
}
if (bt_total == RECV_TOTAL) {
ok_bursts++;
} else {
drop_bad_packets(sock);
sock.set_blocking(false);
}
}
free_tx_buffers();
// Packet loss up to 10% tolerated
TEST_ASSERT_INT_WITHIN((BURST_CNT*BURST_PKTS/10), BURST_CNT*BURST_PKTS, BURST_CNT*BURST_PKTS-pkg_fail);
// 90% of the bursts need to be successful
TEST_ASSERT_INT_WITHIN((BURST_CNT/10), BURST_CNT, ok_bursts);
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
}

View File

@ -0,0 +1,81 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "UDPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "udp_tests.h"
using namespace utest::v1;
namespace
{
static const int SIGNAL_SIGIO = 0x1;
static const int SIGIO_TIMEOUT = 5000; //[ms]
}
static void _sigio_handler(osThreadId id) {
osSignalSet(id, SIGNAL_SIGIO);
}
void test_udpsocket_recv_timeout()
{
SocketAddress udp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr);
udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
static const int DATA_LEN = 100;
char buff[DATA_LEN] = {0};
UDPSocket sock;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
sock.set_timeout(100);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
int recvd;
Timer timer;
SocketAddress temp_addr;
int pkt_success = 0;
for (int i = 0; i < 10; i++) {
TEST_ASSERT_EQUAL(DATA_LEN, sock.sendto(udp_addr, buff, DATA_LEN));
timer.reset();
timer.start();
recvd = sock.recvfrom(&temp_addr, buff, sizeof(buff));
timer.stop();
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT);
printf("MBED: recvfrom() took: %dms\n", timer.read_ms());
TEST_ASSERT_INT_WITHIN(50, (100+200)/2, timer.read_ms());
continue;
} else if (recvd < 0) {
printf("[bt#%02d] network error %d\n", i, recvd);
continue;
} else if (temp_addr != udp_addr) {
printf("[bt#%02d] packet from wrong address\n", i);
continue;
}
TEST_ASSERT_EQUAL(DATA_LEN, recvd);
pkt_success++;
}
TEST_ASSERT(pkt_success >= 5);
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
}

View File

@ -0,0 +1,54 @@
/*
* 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 "mbed.h"
#include MBED_CONF_APP_HEADER_FILE
#include "UDPSocket.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "udp_tests.h"
void test_udpsocket_sendto_timeout()
{
char tx_buffer[100];
fill_tx_buffer_ascii(tx_buffer, sizeof(tx_buffer));
UDPSocket sock;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
SocketAddress udp_addr;
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr);
udp_addr.set_port(9);
Timer timer;
timer.start();
int sent = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer));
timer.stop();
TEST_ASSERT_EQUAL(sizeof(tx_buffer), sent);
TEST_ASSERT(timer.read_ms() <= 100);
timer.reset();
timer.start();
sent = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer));
timer.stop();
TEST_ASSERT_EQUAL(sizeof(tx_buffer), sent);
TEST_ASSERT(timer.read_ms() <= 100);
printf("MBED: Time taken: %fs\n", timer.read());
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
}