NETSOCKET pressure tests configuration

pull/6093/head
jeromecoutant 2018-02-14 13:46:56 +01:00
parent ccff46d9a3
commit d25d457652
7 changed files with 428 additions and 244 deletions

View File

@ -16,7 +16,7 @@
*/ */
#ifndef MBED_CONF_APP_CONNECT_STATEMENT #ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target. #error [NOT_SUPPORTED] No network configuration found for this target.
#endif #endif
#include "mbed.h" #include "mbed.h"
@ -32,18 +32,21 @@ using namespace utest::v1;
#define MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE 256 #define MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE 256
#endif #endif
namespace { namespace
char tx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; {
char rx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; char tx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
char rx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
} }
void prep_buffer(char *tx_buffer, size_t tx_size) { void prep_buffer(char *tx_buffer, size_t tx_size)
for (size_t i=0; i<tx_size; ++i) { {
for (size_t i = 0; i < tx_size; ++i) {
tx_buffer[i] = (rand() % 10) + '0'; tx_buffer[i] = (rand() % 10) + '0';
} }
} }
void test_tcp_echo() { void test_tcp_echo()
{
int n = 0; int n = 0;
NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
int err = MBED_CONF_APP_CONNECT_STATEMENT; int err = MBED_CONF_APP_CONNECT_STATEMENT;
@ -119,7 +122,8 @@ void test_tcp_echo() {
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(240, "tcp_echo"); GREENTEA_SETUP(240, "tcp_echo");
return verbose_test_setup_handler(number_of_cases); return verbose_test_setup_handler(number_of_cases);
} }
@ -130,6 +134,7 @@ Case cases[] = {
Specification specification(test_setup, cases); Specification specification(test_setup, cases);
int main() { int main()
{
return !Harness::run(specification); return !Harness::run(specification);
} }

View File

@ -15,12 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef MBED_CONF_APP_CONNECT_STATEMENT #ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target. #error [NOT_SUPPORTED] No network configuration found for this target.
#endif #endif
#ifndef MBED_EXTENDED_TESTS #ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Parallel tests are not supported by default #error [NOT_SUPPORTED] Parallel tests are not supported by default
#endif #endif
#include "mbed.h" #include "mbed.h"
@ -33,12 +33,12 @@
using namespace utest::v1; using namespace utest::v1;
#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE #ifndef MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE
#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 64 #define MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE 64
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_ECHO_THREADS #ifndef MBED_CONF_APP_TCP_CLIENT_ECHO_THREADS
#define MBED_CFG_TCP_CLIENT_ECHO_THREADS 3 #define MBED_CONF_APP_TCP_CLIENT_ECHO_THREADS 3
#endif #endif
#define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE(x) STRINGIZE2(x)
@ -49,51 +49,59 @@ NetworkInterface* net;
SocketAddress tcp_addr; SocketAddress tcp_addr;
Mutex iomutex; Mutex iomutex;
void prep_buffer(char *tx_buffer, size_t tx_size) { void prep_buffer(char *tx_buffer, size_t tx_size)
for (size_t i=0; i<tx_size; ++i) { {
for (size_t i = 0; i < tx_size; ++i) {
tx_buffer[i] = (rand() % 10) + '0'; tx_buffer[i] = (rand() % 10) + '0';
} }
} }
// Each echo class is in charge of one parallel transaction // Each echo class is in charge of one parallel transaction
class Echo { class Echo
{
private: private:
char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE]; char tx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE];
char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE]; char rx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE];
TCPSocket sock; TCPSocket sock;
Thread thread; Thread thread;
public: public:
// Limiting stack size to 1k // Limiting stack size to 1k
Echo(): thread(osPriorityNormal, 1024) { Echo(): thread(osPriorityNormal, 1024)
{
} }
void start() { void start()
{
osStatus status = thread.start(callback(this, &Echo::echo)); osStatus status = thread.start(callback(this, &Echo::echo));
TEST_ASSERT_EQUAL(osOK, status); TEST_ASSERT_EQUAL(osOK, status);
} }
void join() { void join()
{
osStatus status = thread.join(); osStatus status = thread.join();
TEST_ASSERT_EQUAL(osOK, status); TEST_ASSERT_EQUAL(osOK, status);
} }
void echo() { void echo()
{
int err = sock.open(net); int err = sock.open(net);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
err = sock.connect(tcp_addr); err = sock.connect(tcp_addr);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
#if defined(MBED_CONF_APP_TCP_ECHO_PREFIX)
//recv connection prefix message //recv connection prefix message
sock.recv(rx_buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX)); sock.recv(rx_buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX));
#endif /* MBED_CONF_APP_TCP_ECHO_PREFIX */
memset(rx_buffer, 0, sizeof(rx_buffer)); memset(rx_buffer, 0, sizeof(rx_buffer));
iomutex.lock(); iomutex.lock();
printf("HTTP: Connected to %s:%d\r\n", printf("HTTP: Connected to %s:%d\r\n",
tcp_addr.get_ip_address(), tcp_addr.get_port()); tcp_addr.get_ip_address(), tcp_addr.get_port());
printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer)); printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer));
printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer)); printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer));
iomutex.unlock(); iomutex.unlock();
@ -112,26 +120,45 @@ public:
} }
}; };
Echo *echoers[MBED_CFG_TCP_CLIENT_ECHO_THREADS]; Echo *echoers[MBED_CONF_APP_TCP_CLIENT_ECHO_THREADS];
void test_tcp_echo_parallel() { void test_tcp_echo_parallel()
{
net = MBED_CONF_APP_OBJECT_CONSTRUCTION; net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
int err = MBED_CONF_APP_CONNECT_STATEMENT; int err = MBED_CONF_APP_CONNECT_STATEMENT;
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address()); printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address());
#if defined(MBED_CONF_APP_ECHO_SERVER_ADDR) && defined(MBED_CONF_APP_ECHO_SERVER_PORT)
tcp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); tcp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR);
tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
#else /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
char recv_key[] = "host_port";
char ipbuf[60] = {0};
char portbuf[16] = {0};
unsigned int port = 0;
greentea_send_kv("target_ip", net->get_ip_address());
greentea_send_kv("host_ip", " ");
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
greentea_send_kv("host_port", " ");
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
sscanf(portbuf, "%u", &port);
tcp_addr.set_ip_address(ipbuf);
tcp_addr.set_port(port);
#endif /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
// Startup echo threads in parallel // Startup echo threads in parallel
for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_TCP_CLIENT_ECHO_THREADS; i++) {
echoers[i] = new Echo; echoers[i] = new Echo;
echoers[i]->start(); echoers[i]->start();
} }
for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_TCP_CLIENT_ECHO_THREADS; i++) {
echoers[i]->join(); echoers[i]->join();
delete echoers[i]; delete echoers[i];
} }
@ -140,7 +167,8 @@ void test_tcp_echo_parallel() {
} }
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "tcp_echo"); GREENTEA_SETUP(120, "tcp_echo");
return verbose_test_setup_handler(number_of_cases); return verbose_test_setup_handler(number_of_cases);
} }
@ -151,6 +179,7 @@ Case cases[] = {
Specification specification(test_setup, cases); Specification specification(test_setup, cases);
int main() { int main()
{
return !Harness::run(specification); return !Harness::run(specification);
} }

View File

@ -15,12 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef MBED_CONF_APP_CONNECT_STATEMENT #ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target. #error [NOT_SUPPORTED] No network configuration found for this target.
#endif #endif
#ifndef MBED_EXTENDED_TESTS #ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Pressure tests are not supported by default #error [NOT_SUPPORTED] Pressure tests are not supported by default
#endif #endif
#include "mbed.h" #include "mbed.h"
@ -33,20 +33,20 @@
using namespace utest::v1; using namespace utest::v1;
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN 64
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_SEED
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG false
#endif #endif
#define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE(x) STRINGIZE2(x)
@ -54,7 +54,8 @@ using namespace utest::v1;
// Simple xorshift pseudorandom number generator // Simple xorshift pseudorandom number generator
class RandSeq { class RandSeq
{
private: private:
uint32_t x; uint32_t x;
uint32_t y; uint32_t y;
@ -63,23 +64,26 @@ private:
static const int C = 11; static const int C = 11;
public: public:
RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) RandSeq(uint32_t seed = MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_SEED)
: x(seed), y(seed) {} : x(seed), y(seed) {}
uint32_t next(void) { uint32_t next(void)
{
x ^= x << A; x ^= x << A;
x ^= x >> B; x ^= x >> B;
x ^= y ^ (y >> C); x ^= y ^ (y >> C);
return x + y; return x + y;
} }
void skip(size_t size) { void skip(size_t size)
{
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
next(); next();
} }
} }
void buffer(uint8_t *buffer, size_t size) { void buffer(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -87,7 +91,8 @@ public:
} }
} }
int cmp(uint8_t *buffer, size_t size) { int cmp(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -107,7 +112,8 @@ size_t buffer_size;
// Tries to get the biggest buffer possible on the device. Exponentially // Tries to get the biggest buffer possible on the device. Exponentially
// grows a buffer until heap runs out of space, and uses half to leave // grows a buffer until heap runs out of space, and uses half to leave
// space for the rest of the program // space for the rest of the program
void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max)
{
size_t i = min; size_t i = min;
while (i < max) { while (i < max) {
void *b = malloc(i); void *b = malloc(i);
@ -128,10 +134,11 @@ void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) {
} }
void test_tcp_packet_pressure() { void test_tcp_packet_pressure()
{
generate_buffer(&buffer, &buffer_size, generate_buffer(&buffer, &buffer_size,
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN,
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX);
printf("MBED: Generated buffer %d\r\n", buffer_size); printf("MBED: Generated buffer %d\r\n", buffer_size);
NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
@ -141,24 +148,43 @@ void test_tcp_packet_pressure() {
printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address()); printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address());
TCPSocket sock; TCPSocket sock;
#if defined(MBED_CONF_APP_ECHO_SERVER_ADDR) && defined(MBED_CONF_APP_ECHO_SERVER_PORT)
SocketAddress tcp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); SocketAddress tcp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT);
#else /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
char recv_key[] = "host_port";
char ipbuf[60] = {0};
char portbuf[16] = {0};
unsigned int port = 0;
greentea_send_kv("target_ip", net->get_ip_address());
greentea_send_kv("host_ip", " ");
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
greentea_send_kv("host_port", " ");
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
sscanf(portbuf, "%u", &port);
SocketAddress tcp_addr(ipbuf, port);
#endif /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
Timer timer; Timer timer;
timer.start(); timer.start();
// Tests exponentially growing sequences // Tests exponentially growing sequences
for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; for (size_t size = MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN;
size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; size < MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX;
size *= 2) { size *= 2) {
err = sock.open(net); err = sock.open(net);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
err = sock.connect(tcp_addr); err = sock.connect(tcp_addr);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
printf("TCP: %s:%d streaming %d bytes\r\n", printf("TCP: %s:%d streaming %d bytes\r\n",
tcp_addr.get_ip_address(), tcp_addr.get_port(), size); tcp_addr.get_ip_address(), tcp_addr.get_port(), size);
#if defined(MBED_CONF_APP_TCP_ECHO_PREFIX)
//recv connection prefix message //recv connection prefix message
sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX)); sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX));
#endif /* MBED_CONF_APP_TCP_ECHO_PREFIX */
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
sock.set_blocking(false); sock.set_blocking(false);
@ -182,7 +208,7 @@ void test_tcp_packet_pressure() {
int td = sock.send(buffer, chunk_size); int td = sock.send(buffer, chunk_size);
if (td > 0) { if (td > 0) {
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
printf("TCP: tx -> %d\r\n", td); printf("TCP: tx -> %d\r\n", td);
} }
tx_seq.skip(td); tx_seq.skip(td);
@ -190,11 +216,11 @@ void test_tcp_packet_pressure() {
} else if (td != NSAPI_ERROR_WOULD_BLOCK) { } else if (td != NSAPI_ERROR_WOULD_BLOCK) {
// We may fail to send because of buffering issues, // We may fail to send because of buffering issues,
// cut buffer in half // cut buffer in half
if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { if (window > MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN) {
window /= 2; window /= 2;
} }
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
printf("TCP: Not sent (%d), window = %d\r\n", td, window); printf("TCP: Not sent (%d), window = %d\r\n", td, window);
} }
} }
@ -205,7 +231,7 @@ void test_tcp_packet_pressure() {
int rd = sock.recv(buffer, buffer_size); int rd = sock.recv(buffer, buffer_size);
TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK);
if (rd > 0) { if (rd > 0) {
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
printf("TCP: rx <- %d\r\n", rd); printf("TCP: rx <- %d\r\n", rd);
} }
int diff = rx_seq.cmp(buffer, rd); int diff = rx_seq.cmp(buffer, rd);
@ -225,15 +251,16 @@ void test_tcp_packet_pressure() {
timer.stop(); timer.stop();
printf("MBED: Time taken: %fs\r\n", timer.read()); printf("MBED: Time taken: %fs\r\n", timer.read());
printf("MBED: Speed: %.3fkb/s\r\n", printf("MBED: Speed: %.3fkb/s\r\n",
8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - 8 * (2 * MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX -
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000 * timer.read()));
net->disconnect(); net->disconnect();
} }
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "tcp_echo"); GREENTEA_SETUP(120, "tcp_echo");
return verbose_test_setup_handler(number_of_cases); return verbose_test_setup_handler(number_of_cases);
} }
@ -244,6 +271,7 @@ Case cases[] = {
Specification specification(test_setup, cases); Specification specification(test_setup, cases);
int main() { int main()
{
return !Harness::run(specification); return !Harness::run(specification);
} }

View File

@ -15,12 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef MBED_CONF_APP_CONNECT_STATEMENT #ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target. #error [NOT_SUPPORTED] No network configuration found for this target.
#endif #endif
#ifndef MBED_EXTENDED_TESTS #ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Parallel pressure tests are not supported by default #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default
#endif #endif
#include "mbed.h" #include "mbed.h"
@ -33,24 +33,24 @@
using namespace utest::v1; using namespace utest::v1;
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN 64
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_SEED
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 3 #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS 3
#endif #endif
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG #ifndef MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false #define MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG false
#endif #endif
#define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE(x) STRINGIZE2(x)
@ -58,7 +58,8 @@ using namespace utest::v1;
// Simple xorshift pseudorandom number generator // Simple xorshift pseudorandom number generator
class RandSeq { class RandSeq
{
private: private:
uint32_t x; uint32_t x;
uint32_t y; uint32_t y;
@ -67,23 +68,26 @@ private:
static const int C = 11; static const int C = 11;
public: public:
RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) RandSeq(uint32_t seed = MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_SEED)
: x(seed), y(seed) {} : x(seed), y(seed) {}
uint32_t next(void) { uint32_t next(void)
{
x ^= x << A; x ^= x << A;
x ^= x >> B; x ^= x >> B;
x ^= y ^ (y >> C); x ^= y ^ (y >> C);
return x + y; return x + y;
} }
void skip(size_t size) { void skip(size_t size)
{
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
next(); next();
} }
} }
void buffer(uint8_t *buffer, size_t size) { void buffer(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -91,7 +95,8 @@ public:
} }
} }
int cmp(uint8_t *buffer, size_t size) { int cmp(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -108,7 +113,8 @@ public:
// Tries to get the biggest buffer possible on the device. Exponentially // Tries to get the biggest buffer possible on the device. Exponentially
// grows a buffer until heap runs out of space, and uses half to leave // grows a buffer until heap runs out of space, and uses half to leave
// space for the rest of the program // space for the rest of the program
void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max)
{
size_t i = min; size_t i = min;
while (i < max) { while (i < max) {
void *b = malloc(i); void *b = malloc(i);
@ -136,7 +142,8 @@ Timer timer;
Mutex iomutex; Mutex iomutex;
// Single instance of a pressure test // Single instance of a pressure test
class PressureTest { class PressureTest
{
private: private:
uint8_t *buffer; uint8_t *buffer;
size_t buffer_size; size_t buffer_size;
@ -146,33 +153,40 @@ private:
public: public:
PressureTest(uint8_t *buffer, size_t buffer_size) PressureTest(uint8_t *buffer, size_t buffer_size)
: buffer(buffer), buffer_size(buffer_size) { : buffer(buffer), buffer_size(buffer_size)
{
} }
void start() { void start()
{
osStatus status = thread.start(callback(this, &PressureTest::run)); osStatus status = thread.start(callback(this, &PressureTest::run));
TEST_ASSERT_EQUAL(osOK, status); TEST_ASSERT_EQUAL(osOK, status);
} }
void join() { void join()
{
osStatus status = thread.join(); osStatus status = thread.join();
TEST_ASSERT_EQUAL(osOK, status); TEST_ASSERT_EQUAL(osOK, status);
} }
void run() { void run()
{
// Tests exponentially growing sequences // Tests exponentially growing sequences
for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; for (size_t size = MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN;
size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; size < MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX;
size *= 2) { size *= 2) {
int err = sock.open(net); int err = sock.open(net);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
err = sock.connect(tcp_addr); err = sock.connect(tcp_addr);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
#if defined(MBED_CONF_APP_TCP_ECHO_PREFIX)
sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX)); sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX));
#endif /* MBED_CONF_APP_TCP_ECHO_PREFIX */
iomutex.lock(); iomutex.lock();
printf("TCP: %s:%d streaming %d bytes\r\n", printf("TCP: %s:%d streaming %d bytes\r\n",
tcp_addr.get_ip_address(), tcp_addr.get_port(), size); tcp_addr.get_ip_address(), tcp_addr.get_port(), size);
iomutex.unlock(); iomutex.unlock();
sock.set_blocking(false); sock.set_blocking(false);
@ -196,7 +210,7 @@ public:
int td = sock.send(buffer, chunk_size); int td = sock.send(buffer, chunk_size);
if (td > 0) { if (td > 0) {
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
iomutex.lock(); iomutex.lock();
printf("TCP: tx -> %d\r\n", td); printf("TCP: tx -> %d\r\n", td);
iomutex.unlock(); iomutex.unlock();
@ -206,11 +220,11 @@ public:
} else if (td != NSAPI_ERROR_WOULD_BLOCK) { } else if (td != NSAPI_ERROR_WOULD_BLOCK) {
// We may fail to send because of buffering issues, // We may fail to send because of buffering issues,
// cut buffer in half // cut buffer in half
if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { if (window > MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN) {
window /= 2; window /= 2;
} }
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
iomutex.lock(); iomutex.lock();
printf("TCP: Not sent (%d), window = %d\r\n", td, window); printf("TCP: Not sent (%d), window = %d\r\n", td, window);
iomutex.unlock(); iomutex.unlock();
@ -223,7 +237,7 @@ public:
int rd = sock.recv(buffer, buffer_size); int rd = sock.recv(buffer, buffer_size);
TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK);
if (rd > 0) { if (rd > 0) {
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
iomutex.lock(); iomutex.lock();
printf("TCP: rx <- %d\r\n", rd); printf("TCP: rx <- %d\r\n", rd);
iomutex.unlock(); iomutex.unlock();
@ -244,21 +258,22 @@ public:
} }
}; };
PressureTest *pressure_tests[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS]; PressureTest *pressure_tests[MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS];
void test_tcp_packet_pressure_parallel() { void test_tcp_packet_pressure_parallel()
{
uint8_t *buffer; uint8_t *buffer;
size_t buffer_size; size_t buffer_size;
generate_buffer(&buffer, &buffer_size, generate_buffer(&buffer, &buffer_size,
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN,
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX);
size_t buffer_subsize = buffer_size / MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; size_t buffer_subsize = buffer_size / MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS;
printf("MBED: Generated buffer %d\r\n", buffer_size); printf("MBED: Generated buffer %d\r\n", buffer_size);
printf("MBED: Split into %d buffers %d\r\n", printf("MBED: Split into %d buffers %d\r\n",
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS, MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS,
buffer_subsize); buffer_subsize);
net = MBED_CONF_APP_OBJECT_CONSTRUCTION; net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
int err = MBED_CONF_APP_CONNECT_STATEMENT; int err = MBED_CONF_APP_CONNECT_STATEMENT;
@ -266,18 +281,36 @@ void test_tcp_packet_pressure_parallel() {
printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address()); printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address());
#if defined(MBED_CONF_APP_ECHO_SERVER_ADDR) && defined(MBED_CONF_APP_ECHO_SERVER_PORT)
tcp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); tcp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR);
tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
#else /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
char recv_key[] = "host_port";
char ipbuf[60] = {0};
char portbuf[16] = {0};
unsigned int port = 0;
greentea_send_kv("target_ip", net->get_ip_address());
greentea_send_kv("host_ip", " ");
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
greentea_send_kv("host_port", " ");
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
sscanf(portbuf, "%u", &port);
tcp_addr.set_ip_address(ipbuf);
tcp_addr.set_port(port);
#endif /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
timer.start(); timer.start();
// Startup pressure tests in parallel // Startup pressure tests in parallel
for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) {
pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); pressure_tests[i] = new PressureTest(&buffer[i * buffer_subsize], buffer_subsize);
pressure_tests[i]->start(); pressure_tests[i]->start();
} }
for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) {
pressure_tests[i]->join(); pressure_tests[i]->join();
delete pressure_tests[i]; delete pressure_tests[i];
} }
@ -285,16 +318,17 @@ void test_tcp_packet_pressure_parallel() {
timer.stop(); timer.stop();
printf("MBED: Time taken: %fs\r\n", timer.read()); printf("MBED: Time taken: %fs\r\n", timer.read());
printf("MBED: Speed: %.3fkb/s\r\n", printf("MBED: Speed: %.3fkb/s\r\n",
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS* MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_THREADS *
8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - 8 * (2 * MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MAX -
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); MBED_CONF_APP_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000 * timer.read()));
net->disconnect(); net->disconnect();
} }
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "tcp_echo"); GREENTEA_SETUP(120, "tcp_echo");
return verbose_test_setup_handler(number_of_cases); return verbose_test_setup_handler(number_of_cases);
} }
@ -305,6 +339,7 @@ Case cases[] = {
Specification specification(test_setup, cases); Specification specification(test_setup, cases);
int main() { int main()
{
return !Harness::run(specification); return !Harness::run(specification);
} }

View File

@ -15,12 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef MBED_CONF_APP_CONNECT_STATEMENT #ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target. #error [NOT_SUPPORTED] No network configuration found for this target.
#endif #endif
#ifndef MBED_EXTENDED_TESTS #ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Parallel tests are not supported by default #error [NOT_SUPPORTED] Parallel tests are not supported by default
#endif #endif
#include "mbed.h" #include "mbed.h"
@ -33,16 +33,16 @@
using namespace utest::v1; using namespace utest::v1;
#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE #ifndef MBED_CONF_APP_UDP_CLIENT_ECHO_BUFFER_SIZE
#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 #define MBED_CONF_APP_UDP_CLIENT_ECHO_BUFFER_SIZE 64
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT #ifndef MBED_CONF_APP_UDP_CLIENT_ECHO_TIMEOUT
#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 #define MBED_CONF_APP_UDP_CLIENT_ECHO_TIMEOUT 500
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_ECHO_THREADS #ifndef MBED_CONF_APP_UDP_CLIENT_ECHO_THREADS
#define MBED_CFG_UDP_CLIENT_ECHO_THREADS 3 #define MBED_CONF_APP_UDP_CLIENT_ECHO_THREADS 3
#endif #endif
#define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE(x) STRINGIZE2(x)
@ -56,28 +56,30 @@ Mutex iomutex;
char uuid[48] = {0}; char uuid[48] = {0};
// NOTE: assuming that "id" stays in the single digits // NOTE: assuming that "id" stays in the single digits
void prep_buffer(int id, char *uuid, char *tx_buffer, size_t tx_size) { void prep_buffer(int id, char *uuid, char *tx_buffer, size_t tx_size)
{
size_t i = 0; size_t i = 0;
tx_buffer[i++] = '0' + id; tx_buffer[i++] = '0' + id;
tx_buffer[i++] = ' '; tx_buffer[i++] = ' ';
memcpy(tx_buffer+i, uuid, strlen(uuid)); memcpy(tx_buffer + i, uuid, strlen(uuid));
i += strlen(uuid); i += strlen(uuid);
tx_buffer[i++] = ' '; tx_buffer[i++] = ' ';
for (; i<tx_size; ++i) { for (; i < tx_size; ++i) {
tx_buffer[i] = (rand() % 10) + '0'; tx_buffer[i] = (rand() % 10) + '0';
} }
} }
// Each echo class is in charge of one parallel transaction // Each echo class is in charge of one parallel transaction
class Echo { class Echo
{
private: private:
char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE]; char tx_buffer[MBED_CONF_APP_UDP_CLIENT_ECHO_BUFFER_SIZE];
char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE]; char rx_buffer[MBED_CONF_APP_UDP_CLIENT_ECHO_BUFFER_SIZE];
UDPSocket sock; UDPSocket sock;
Thread thread; Thread thread;
@ -87,27 +89,31 @@ private:
public: public:
// Limiting stack size to 1k // Limiting stack size to 1k
Echo(): thread(osPriorityNormal, 1024), result(false) { Echo(): thread(osPriorityNormal, 1024), result(false)
{
} }
void start(int id, char *uuid) { void start(int id, char *uuid)
{
this->id = id; this->id = id;
this->uuid = uuid; this->uuid = uuid;
osStatus status = thread.start(callback(this, &Echo::echo)); osStatus status = thread.start(callback(this, &Echo::echo));
} }
void join() { void join()
{
osStatus status = thread.join(); osStatus status = thread.join();
TEST_ASSERT_EQUAL(osOK, status); TEST_ASSERT_EQUAL(osOK, status);
} }
void echo() { void echo()
{
int success = 0; int success = 0;
int err = sock.open(net); int err = sock.open(net);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); sock.set_timeout(MBED_CONF_APP_UDP_CLIENT_ECHO_TIMEOUT);
for (int i = 0; success < ECHO_LOOPS; i++) { for (int i = 0; success < ECHO_LOOPS; i++) {
prep_buffer(id, uuid, tx_buffer, sizeof(tx_buffer)); prep_buffer(id, uuid, tx_buffer, sizeof(tx_buffer));
@ -137,8 +143,8 @@ public:
} }
if ((temp_addr == udp_addr && if ((temp_addr == udp_addr &&
n == sizeof(tx_buffer) && n == sizeof(tx_buffer) &&
memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) {
success += 1; success += 1;
iomutex.lock(); iomutex.lock();
printf("[ID:%01d][%02d] success #%d\n", id, i, success); printf("[ID:%01d][%02d] success #%d\n", id, i, success);
@ -154,7 +160,7 @@ public:
break; break;
} }
} }
sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); sock.set_timeout(MBED_CONF_APP_UDP_CLIENT_ECHO_TIMEOUT);
} }
result = success == ECHO_LOOPS; result = success == ECHO_LOOPS;
@ -166,15 +172,17 @@ public:
} }
} }
bool get_result() { bool get_result()
{
return result; return result;
} }
}; };
Echo *echoers[MBED_CFG_UDP_CLIENT_ECHO_THREADS]; Echo *echoers[MBED_CONF_APP_UDP_CLIENT_ECHO_THREADS];
void test_udp_echo_parallel() { void test_udp_echo_parallel()
{
net = MBED_CONF_APP_OBJECT_CONSTRUCTION; net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
int err = MBED_CONF_APP_CONNECT_STATEMENT; int err = MBED_CONF_APP_CONNECT_STATEMENT;
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
@ -185,18 +193,37 @@ void test_udp_echo_parallel() {
} else { } else {
printf("UDP client IP Address is %s\n", net->get_ip_address()); printf("UDP client IP Address is %s\n", net->get_ip_address());
#if defined(MBED_CONF_APP_ECHO_SERVER_ADDR) && defined(MBED_CONF_APP_ECHO_SERVER_PORT)
udp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); udp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR);
udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
#else /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
char recv_key[] = "host_port";
char ipbuf[60] = {0};
char portbuf[16] = {0};
unsigned int port = 0;
greentea_send_kv("target_ip", net->get_ip_address());
greentea_send_kv("host_ip", " ");
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
greentea_send_kv("host_port", " ");
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
sscanf(portbuf, "%u", &port);
printf("UDP Connect to %s:%d\r\n", ipbuf, port);
udp_addr.set_ip_address(ipbuf);
udp_addr.set_port(port);
#endif /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
// Startup echo threads in parallel // Startup echo threads in parallel
for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_UDP_CLIENT_ECHO_THREADS; i++) {
echoers[i] = new Echo; echoers[i] = new Echo;
echoers[i]->start(i, uuid); echoers[i]->start(i, uuid);
} }
bool result = true; bool result = true;
for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_UDP_CLIENT_ECHO_THREADS; i++) {
echoers[i]->join(); echoers[i]->join();
result = result && echoers[i]->get_result(); result = result && echoers[i]->get_result();
delete echoers[i]; delete echoers[i];
@ -209,7 +236,8 @@ void test_udp_echo_parallel() {
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "udp_echo"); GREENTEA_SETUP(120, "udp_echo");
return verbose_test_setup_handler(number_of_cases); return verbose_test_setup_handler(number_of_cases);
} }
@ -220,6 +248,7 @@ Case cases[] = {
Specification specification(test_setup, cases); Specification specification(test_setup, cases);
int main() { int main()
{
return !Harness::run(specification); return !Harness::run(specification);
} }

View File

@ -15,12 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef MBED_CONF_APP_CONNECT_STATEMENT #ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target. #error [NOT_SUPPORTED] No network configuration found for this target.
#endif #endif
#ifndef MBED_EXTENDED_TESTS #ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Pressure tests are not supported by default #error [NOT_SUPPORTED] Pressure tests are not supported by default
#endif #endif
#include "mbed.h" #include "mbed.h"
@ -33,24 +33,24 @@
using namespace utest::v1; using namespace utest::v1;
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN 64
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG false
#endif #endif
#define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE(x) STRINGIZE2(x)
@ -58,7 +58,8 @@ using namespace utest::v1;
// Simple xorshift pseudorandom number generator // Simple xorshift pseudorandom number generator
class RandSeq { class RandSeq
{
private: private:
uint32_t x; uint32_t x;
uint32_t y; uint32_t y;
@ -67,23 +68,26 @@ private:
static const int C = 11; static const int C = 11;
public: public:
RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) RandSeq(uint32_t seed = MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED)
: x(seed), y(seed) {} : x(seed), y(seed) {}
uint32_t next(void) { uint32_t next(void)
{
x ^= x << A; x ^= x << A;
x ^= x >> B; x ^= x >> B;
x ^= y ^ (y >> C); x ^= y ^ (y >> C);
return x + y; return x + y;
} }
void skip(size_t size) { void skip(size_t size)
{
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
next(); next();
} }
} }
void buffer(uint8_t *buffer, size_t size) { void buffer(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -91,7 +95,8 @@ public:
} }
} }
int cmp(uint8_t *buffer, size_t size) { int cmp(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -111,7 +116,8 @@ size_t buffer_size;
// Tries to get the biggest buffer possible on the device. Exponentially // Tries to get the biggest buffer possible on the device. Exponentially
// grows a buffer until heap runs out of space, and uses half to leave // grows a buffer until heap runs out of space, and uses half to leave
// space for the rest of the program // space for the rest of the program
void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max)
{
size_t i = min; size_t i = min;
while (i < max) { while (i < max) {
void *b = malloc(i); void *b = malloc(i);
@ -131,10 +137,11 @@ void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) {
TEST_ASSERT(buffer); TEST_ASSERT(buffer);
} }
void test_udp_packet_pressure() { void test_udp_packet_pressure()
{
generate_buffer(&buffer, &buffer_size, generate_buffer(&buffer, &buffer_size,
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN,
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX);
printf("MBED: Generated buffer %d\r\n", buffer_size); printf("MBED: Generated buffer %d\r\n", buffer_size);
NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
@ -144,19 +151,36 @@ void test_udp_packet_pressure() {
printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address()); printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address());
UDPSocket sock; UDPSocket sock;
#if defined(MBED_CONF_APP_ECHO_SERVER_ADDR) && defined(MBED_CONF_APP_ECHO_SERVER_PORT)
SocketAddress udp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); SocketAddress udp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT);
#else /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
char recv_key[] = "host_port";
char ipbuf[60] = {0};
char portbuf[16] = {0};
unsigned int port = 0;
greentea_send_kv("target_ip", net->get_ip_address());
greentea_send_kv("host_ip", " ");
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
greentea_send_kv("host_port", " ");
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
sscanf(portbuf, "%u", &port);
SocketAddress udp_addr(ipbuf, port);
#endif /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
Timer timer; Timer timer;
timer.start(); timer.start();
// Tests exponentially growing sequences // Tests exponentially growing sequences
for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; for (size_t size = MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN;
size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; size < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX;
size *= 2) { size *= 2) {
err = sock.open(net); err = sock.open(net);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
printf("UDP: %s:%d streaming %d bytes\r\n", printf("UDP: %s:%d streaming %d bytes\r\n",
udp_addr.get_ip_address(), udp_addr.get_port(), size); udp_addr.get_ip_address(), udp_addr.get_port(), size);
sock.set_blocking(false); sock.set_blocking(false);
@ -180,7 +204,7 @@ void test_udp_packet_pressure() {
int td = sock.sendto(udp_addr, buffer, chunk_size); int td = sock.sendto(udp_addr, buffer, chunk_size);
if (td > 0) { if (td > 0) {
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
printf("UDP: tx -> %d\r\n", td); printf("UDP: tx -> %d\r\n", td);
} }
tx_seq.skip(td); tx_seq.skip(td);
@ -188,11 +212,11 @@ void test_udp_packet_pressure() {
} else if (td != NSAPI_ERROR_WOULD_BLOCK) { } else if (td != NSAPI_ERROR_WOULD_BLOCK) {
// We may fail to send because of buffering issues, revert to // We may fail to send because of buffering issues, revert to
// last good sequence and cut buffer in half // last good sequence and cut buffer in half
if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { if (window > MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) {
window /= 2; window /= 2;
} }
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
printf("UDP: Not sent (%d), window = %d\r\n", td, window); printf("UDP: Not sent (%d), window = %d\r\n", td, window);
} }
} }
@ -205,7 +229,7 @@ void test_udp_packet_pressure() {
TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK);
if (rd > 0) { if (rd > 0) {
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
printf("UDP: rx <- %d\r\n", rd); printf("UDP: rx <- %d\r\n", rd);
} }
@ -213,22 +237,22 @@ void test_udp_packet_pressure() {
rx_seq.skip(rd); rx_seq.skip(rd);
rx_count += rd; rx_count += rd;
known_time = timer.read_ms(); known_time = timer.read_ms();
if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { if (window < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX) {
window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; window += MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN;
} }
} }
} else if (timer.read_ms() - known_time > } else if (timer.read_ms() - known_time >
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) {
// Dropped packet or out of order, revert to last good sequence // Dropped packet or out of order, revert to last good sequence
// and cut buffer in half // and cut buffer in half
tx_seq = rx_seq; tx_seq = rx_seq;
tx_count = rx_count; tx_count = rx_count;
known_time = timer.read_ms(); known_time = timer.read_ms();
if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { if (window > MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) {
window /= 2; window /= 2;
} }
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
printf("UDP: Dropped, window = %d\r\n", window); printf("UDP: Dropped, window = %d\r\n", window);
} }
} else if (rd == NSAPI_ERROR_WOULD_BLOCK) { } else if (rd == NSAPI_ERROR_WOULD_BLOCK) {
@ -244,15 +268,16 @@ void test_udp_packet_pressure() {
timer.stop(); timer.stop();
printf("MBED: Time taken: %fs\r\n", timer.read()); printf("MBED: Time taken: %fs\r\n", timer.read());
printf("MBED: Speed: %.3fkb/s\r\n", printf("MBED: Speed: %.3fkb/s\r\n",
8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - 8 * (2 * MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX -
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000 * timer.read()));
net->disconnect(); net->disconnect();
} }
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "udp_echo"); GREENTEA_SETUP(120, "udp_echo");
return verbose_test_setup_handler(number_of_cases); return verbose_test_setup_handler(number_of_cases);
} }
@ -263,6 +288,7 @@ Case cases[] = {
Specification specification(test_setup, cases); Specification specification(test_setup, cases);
int main() { int main()
{
return !Harness::run(specification); return !Harness::run(specification);
} }

View File

@ -15,12 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef MBED_CONF_APP_CONNECT_STATEMENT #ifndef MBED_CONF_APP_CONNECT_STATEMENT
#error [NOT_SUPPORTED] No network configuration found for this target. #error [NOT_SUPPORTED] No network configuration found for this target.
#endif #endif
#ifndef MBED_EXTENDED_TESTS #ifndef MBED_EXTENDED_TESTS
#error [NOT_SUPPORTED] Parallel pressure tests are not supported by default #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default
#endif #endif
#include "mbed.h" #include "mbed.h"
@ -33,28 +33,28 @@
using namespace utest::v1; using namespace utest::v1;
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN 64
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS 3 #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS 3
#endif #endif
#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG #ifndef MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG
#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false #define MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG false
#endif #endif
#define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE(x) STRINGIZE2(x)
@ -62,7 +62,8 @@ using namespace utest::v1;
// Simple xorshift pseudorandom number generator // Simple xorshift pseudorandom number generator
class RandSeq { class RandSeq
{
private: private:
uint32_t x; uint32_t x;
uint32_t y; uint32_t y;
@ -71,23 +72,26 @@ private:
static const int C = 11; static const int C = 11;
public: public:
RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) RandSeq(uint32_t seed = MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_SEED)
: x(seed), y(seed) {} : x(seed), y(seed) {}
uint32_t next(void) { uint32_t next(void)
{
x ^= x << A; x ^= x << A;
x ^= x >> B; x ^= x >> B;
x ^= y ^ (y >> C); x ^= y ^ (y >> C);
return x + y; return x + y;
} }
void skip(size_t size) { void skip(size_t size)
{
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
next(); next();
} }
} }
void buffer(uint8_t *buffer, size_t size) { void buffer(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -95,7 +99,8 @@ public:
} }
} }
int cmp(uint8_t *buffer, size_t size) { int cmp(uint8_t *buffer, size_t size)
{
RandSeq lookahead = *this; RandSeq lookahead = *this;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -111,7 +116,8 @@ public:
// Tries to get the biggest buffer possible on the device. Exponentially // Tries to get the biggest buffer possible on the device. Exponentially
// grows a buffer until heap runs out of space, and uses half to leave // grows a buffer until heap runs out of space, and uses half to leave
// space for the rest of the program // space for the rest of the program
void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max)
{
size_t i = min; size_t i = min;
while (i < max) { while (i < max) {
void *b = malloc(i); void *b = malloc(i);
@ -139,7 +145,8 @@ Timer timer;
Mutex iomutex; Mutex iomutex;
// Single instance of a pressure test // Single instance of a pressure test
class PressureTest { class PressureTest
{
private: private:
uint8_t *buffer; uint8_t *buffer;
size_t buffer_size; size_t buffer_size;
@ -149,29 +156,33 @@ private:
public: public:
PressureTest(uint8_t *buffer, size_t buffer_size) PressureTest(uint8_t *buffer, size_t buffer_size)
: buffer(buffer), buffer_size(buffer_size) { : buffer(buffer), buffer_size(buffer_size)
{
} }
void start() { void start()
{
osStatus status = thread.start(callback(this, &PressureTest::run)); osStatus status = thread.start(callback(this, &PressureTest::run));
TEST_ASSERT_EQUAL(osOK, status); TEST_ASSERT_EQUAL(osOK, status);
} }
void join() { void join()
{
osStatus status = thread.join(); osStatus status = thread.join();
TEST_ASSERT_EQUAL(osOK, status); TEST_ASSERT_EQUAL(osOK, status);
} }
void run() { void run()
{
// Tests exponentially growing sequences // Tests exponentially growing sequences
for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; for (size_t size = MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN;
size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; size < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX;
size *= 2) { size *= 2) {
int err = sock.open(net); int err = sock.open(net);
TEST_ASSERT_EQUAL(0, err); TEST_ASSERT_EQUAL(0, err);
iomutex.lock(); iomutex.lock();
printf("UDP: %s:%d streaming %d bytes\r\n", printf("UDP: %s:%d streaming %d bytes\r\n",
udp_addr.get_ip_address(), udp_addr.get_port(), size); udp_addr.get_ip_address(), udp_addr.get_port(), size);
iomutex.unlock(); iomutex.unlock();
sock.set_blocking(false); sock.set_blocking(false);
@ -196,7 +207,7 @@ public:
int td = sock.sendto(udp_addr, buffer, chunk_size); int td = sock.sendto(udp_addr, buffer, chunk_size);
if (td > 0) { if (td > 0) {
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
iomutex.lock(); iomutex.lock();
printf("UDP: tx -> %d\r\n", td); printf("UDP: tx -> %d\r\n", td);
iomutex.unlock(); iomutex.unlock();
@ -206,11 +217,11 @@ public:
} else if (td != NSAPI_ERROR_WOULD_BLOCK) { } else if (td != NSAPI_ERROR_WOULD_BLOCK) {
// We may fail to send because of buffering issues, revert to // We may fail to send because of buffering issues, revert to
// last good sequence and cut buffer in half // last good sequence and cut buffer in half
if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { if (window > MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) {
window /= 2; window /= 2;
} }
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
iomutex.lock(); iomutex.lock();
printf("UDP: Not sent (%d), window = %d\r\n", td, window); printf("UDP: Not sent (%d), window = %d\r\n", td, window);
iomutex.unlock(); iomutex.unlock();
@ -225,7 +236,7 @@ public:
TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK);
if (rd > 0) { if (rd > 0) {
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
iomutex.lock(); iomutex.lock();
printf("UDP: rx <- %d\r\n", rd); printf("UDP: rx <- %d\r\n", rd);
iomutex.unlock(); iomutex.unlock();
@ -235,22 +246,22 @@ public:
rx_seq.skip(rd); rx_seq.skip(rd);
rx_count += rd; rx_count += rd;
known_time = timer.read_ms(); known_time = timer.read_ms();
if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { if (window < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX) {
window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; window += MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN;
} }
} }
} else if (timer.read_ms() - known_time > } else if (timer.read_ms() - known_time >
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) {
// Dropped packet or out of order, revert to last good sequence // Dropped packet or out of order, revert to last good sequence
// and cut buffer in half // and cut buffer in half
tx_seq = rx_seq; tx_seq = rx_seq;
tx_count = rx_count; tx_count = rx_count;
known_time = timer.read_ms(); known_time = timer.read_ms();
if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { if (window > MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) {
window /= 2; window /= 2;
} }
if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { if (MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_DEBUG) {
iomutex.lock(); iomutex.lock();
printf("UDP: Dropped, window = %d\r\n", window); printf("UDP: Dropped, window = %d\r\n", window);
iomutex.unlock(); iomutex.unlock();
@ -267,21 +278,22 @@ public:
} }
}; };
PressureTest *pressure_tests[MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS]; PressureTest *pressure_tests[MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS];
void test_udp_packet_pressure_parallel() { void test_udp_packet_pressure_parallel()
{
uint8_t *buffer; uint8_t *buffer;
size_t buffer_size; size_t buffer_size;
generate_buffer(&buffer, &buffer_size, generate_buffer(&buffer, &buffer_size,
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN,
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX);
size_t buffer_subsize = buffer_size / MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; size_t buffer_subsize = buffer_size / MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS;
printf("MBED: Generated buffer %d\r\n", buffer_size); printf("MBED: Generated buffer %d\r\n", buffer_size);
printf("MBED: Split into %d buffers %d\r\n", printf("MBED: Split into %d buffers %d\r\n",
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS, MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS,
buffer_subsize); buffer_subsize);
net = MBED_CONF_APP_OBJECT_CONSTRUCTION; net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
int err = MBED_CONF_APP_CONNECT_STATEMENT; int err = MBED_CONF_APP_CONNECT_STATEMENT;
@ -289,18 +301,36 @@ void test_udp_packet_pressure_parallel() {
printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address()); printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address());
#if defined(MBED_CONF_APP_ECHO_SERVER_ADDR) && defined(MBED_CONF_APP_ECHO_SERVER_PORT)
udp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); udp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR);
udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
#else /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
char recv_key[] = "host_port";
char ipbuf[60] = {0};
char portbuf[16] = {0};
unsigned int port = 0;
greentea_send_kv("target_ip", net->get_ip_address());
greentea_send_kv("host_ip", " ");
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
greentea_send_kv("host_port", " ");
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
sscanf(portbuf, "%u", &port);
udp_addr.set_ip_address(ipbuf);
udp_addr.set_port(port);
#endif /* MBED_CONF_APP_ECHO_SERVER_ADDR && MBED_CONF_APP_ECHO_SERVER_PORT */
timer.start(); timer.start();
// Startup pressure tests in parallel // Startup pressure tests in parallel
for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) {
pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); pressure_tests[i] = new PressureTest(&buffer[i * buffer_subsize], buffer_subsize);
pressure_tests[i]->start(); pressure_tests[i]->start();
} }
for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { for (int i = 0; i < MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) {
pressure_tests[i]->join(); pressure_tests[i]->join();
delete pressure_tests[i]; delete pressure_tests[i];
} }
@ -308,16 +338,17 @@ void test_udp_packet_pressure_parallel() {
timer.stop(); timer.stop();
printf("MBED: Time taken: %fs\r\n", timer.read()); printf("MBED: Time taken: %fs\r\n", timer.read());
printf("MBED: Speed: %.3fkb/s\r\n", printf("MBED: Speed: %.3fkb/s\r\n",
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS* MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_THREADS *
8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - 8 * (2 * MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MAX -
MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); MBED_CONF_APP_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000 * timer.read()));
net->disconnect(); net->disconnect();
} }
// Test setup // Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) { utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "udp_echo"); GREENTEA_SETUP(120, "udp_echo");
return verbose_test_setup_handler(number_of_cases); return verbose_test_setup_handler(number_of_cases);
} }
@ -328,6 +359,7 @@ Case cases[] = {
Specification specification(test_setup, cases); Specification specification(test_setup, cases);
int main() { int main()
{
return !Harness::run(specification); return !Harness::run(specification);
} }