From 8f9242fe409d3afc9ef7728a8fcb82d9964139c8 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Wed, 19 Jul 2017 17:10:15 -0500 Subject: [PATCH 01/13] Add netsocket tests --- TESTS/netsocket/connectivity/main.cpp | 54 +++ TESTS/netsocket/gethostbyname/main.cpp | 106 ++++++ TESTS/netsocket/host_tests/tcp_echo.py | 195 +++++++++++ TESTS/netsocket/host_tests/udp_echo.py | 127 +++++++ TESTS/netsocket/host_tests/udp_shotgun.py | 142 ++++++++ TESTS/netsocket/socket_sigio/main.cpp | 191 +++++++++++ TESTS/netsocket/tcp_echo/main.cpp | 99 ++++++ TESTS/netsocket/tcp_echo_parallel/main.cpp | 135 ++++++++ TESTS/netsocket/tcp_hello_world/main.cpp | 98 ++++++ TESTS/netsocket/tcp_packet_pressure/main.cpp | 228 +++++++++++++ .../tcp_packet_pressure_parallel/main.cpp | 289 ++++++++++++++++ TESTS/netsocket/udp_dtls_handshake/main.cpp | 144 ++++++++ TESTS/netsocket/udp_echo/main.cpp | 128 +++++++ TESTS/netsocket/udp_echo_parallel/main.cpp | 204 ++++++++++++ TESTS/netsocket/udp_packet_pressure/main.cpp | 247 ++++++++++++++ .../udp_packet_pressure_parallel/main.cpp | 312 ++++++++++++++++++ 16 files changed, 2699 insertions(+) create mode 100644 TESTS/netsocket/connectivity/main.cpp create mode 100644 TESTS/netsocket/gethostbyname/main.cpp create mode 100644 TESTS/netsocket/host_tests/tcp_echo.py create mode 100644 TESTS/netsocket/host_tests/udp_echo.py create mode 100644 TESTS/netsocket/host_tests/udp_shotgun.py create mode 100644 TESTS/netsocket/socket_sigio/main.cpp create mode 100644 TESTS/netsocket/tcp_echo/main.cpp create mode 100644 TESTS/netsocket/tcp_echo_parallel/main.cpp create mode 100644 TESTS/netsocket/tcp_hello_world/main.cpp create mode 100644 TESTS/netsocket/tcp_packet_pressure/main.cpp create mode 100644 TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp create mode 100644 TESTS/netsocket/udp_dtls_handshake/main.cpp create mode 100644 TESTS/netsocket/udp_echo/main.cpp create mode 100644 TESTS/netsocket/udp_echo_parallel/main.cpp create mode 100644 TESTS/netsocket/udp_packet_pressure/main.cpp create mode 100644 TESTS/netsocket/udp_packet_pressure_parallel/main.cpp diff --git a/TESTS/netsocket/connectivity/main.cpp b/TESTS/netsocket/connectivity/main.cpp new file mode 100644 index 00000000000..045aab40de5 --- /dev/null +++ b/TESTS/netsocket/connectivity/main.cpp @@ -0,0 +1,54 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include MBED_CONF_APP_HEADER_FILE + +using namespace utest::v1; + +// Bringing the network up and down +template +void test_bring_up_down() { + NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + + for (int i = 0; i < COUNT; i++) { + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: IP Address %s\r\n", net->get_ip_address()); + TEST_ASSERT(net->get_ip_address()); + + UDPSocket udp; + err = udp.open(net); + TEST_ASSERT_EQUAL(0, err); + err = udp.close(); + TEST_ASSERT_EQUAL(0, err); + + TCPSocket tcp; + err = tcp.open(net); + TEST_ASSERT_EQUAL(0, err); + err = tcp.close(); + TEST_ASSERT_EQUAL(0, err); + + err = net->disconnect(); + TEST_ASSERT_EQUAL(0, err); + } +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Bringing the network up and down", test_bring_up_down<1>), + Case("Bringing the network up and down twice", test_bring_up_down<2>), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/gethostbyname/main.cpp b/TESTS/netsocket/gethostbyname/main.cpp new file mode 100644 index 00000000000..9f54727f2c3 --- /dev/null +++ b/TESTS/netsocket/gethostbyname/main.cpp @@ -0,0 +1,106 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include MBED_CONF_APP_HEADER_FILE + +using namespace utest::v1; + +// Hostname for testing against +// Must have A and AAAA records +#ifndef MBED_DNS_TEST_HOST +#define MBED_DNS_TEST_HOST "connector.mbed.com" +#endif + + +// Address info from stack +const char *ip_literal; +nsapi_version_t ip_pref; +const char *ip_pref_repr; + +// Network setup +NetworkInterface *net; + +void net_bringup() { + net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + printf("MBED: Connected to network\n"); + printf("MBED: IP Address: %s\n", net->get_ip_address()); + + ip_literal = net->get_ip_address(); + ip_pref = SocketAddress(ip_literal).get_ip_version(); + ip_pref_repr = (ip_pref == NSAPI_IPv4) ? "ipv4" : + (ip_pref == NSAPI_IPv6) ? "ipv6" : "unspec"; +} + + +// DNS tests +void test_dns_query() { + SocketAddress addr; + int err = net->gethostbyname(MBED_DNS_TEST_HOST, &addr); + printf("DNS: query \"%s\" => \"%s\"\n", + MBED_DNS_TEST_HOST, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); +} + +void test_dns_query_pref() { + SocketAddress addr; + int err = net->gethostbyname(MBED_DNS_TEST_HOST, &addr, ip_pref); + printf("DNS: query %s \"%s\" => \"%s\"\n", + ip_pref_repr, MBED_DNS_TEST_HOST, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); +} + +void test_dns_literal() { + SocketAddress addr; + int err = net->gethostbyname(ip_literal, &addr); + printf("DNS: literal \"%s\" => \"%s\"\n", + ip_literal, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); +} + +void test_dns_literal_pref() { + SocketAddress addr; + int err = net->gethostbyname(ip_literal, &addr, ip_pref); + printf("DNS: literal %s \"%s\" => \"%s\"\n", + ip_pref_repr, ip_literal, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); + TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + net_bringup(); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("DNS query", test_dns_query), + Case("DNS preference query", test_dns_query_pref), + Case("DNS literal", test_dns_literal), + Case("DNS preference literal", test_dns_literal_pref), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/host_tests/tcp_echo.py b/TESTS/netsocket/host_tests/tcp_echo.py new file mode 100644 index 00000000000..8a528dbee90 --- /dev/null +++ b/TESTS/netsocket/host_tests/tcp_echo.py @@ -0,0 +1,195 @@ +# Copyright 2015 ARM Limited, All rights reserved +# +# 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. + +import sys +import select +import socket +import logging +from threading import Thread +from sys import stdout +from SocketServer import BaseRequestHandler, TCPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class TCPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ + Handles a connection. Test starts by client(i.e. mbed) connecting to server. + This connection handler receives data and echoes back to the client util + {{end}} is received. Then it sits on recv() for client to terminate the + connection. + + Note: reason for not echoing data back after receiving {{end}} is that send + fails raising a SocketError as client closes connection. + """ + while self.server.isrunning(): + try: + data = self.recv() + if not data: break + except Exception as e: + break + + try: + # echo data back to the client + self.send(data) + except Exception as e: + break + + def recv(self): + """ + Try to receive until server is shutdown + """ + while self.server.isrunning(): + rl, wl, xl = select.select([self.request], [], [], 1) + if len(rl): + return self.request.recv(1024) + + def send(self, data): + """ + Try to send until server is shutdown + """ + while self.server.isrunning(): + rl, wl, xl = select.select([], [self.request], [], 1) + if len(wl): + self.request.sendall(data) + break + + +class TCPServerWrapper(TCPServer): + """ + Wrapper over TCP server to implement server initiated shutdown. + Adds a flag:= running that a request handler can check and come out of + recv loop when shutdown is called. + """ + + def __init__(self, addr, request_handler): + # hmm, TCPServer is not sub-classed from object! + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).__init__(addr, request_handler) + else: + TCPServer.__init__(self, addr, request_handler) + self.running = False + + def serve_forever(self): + self.running = True + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).serve_forever() + else: + TCPServer.serve_forever(self) + + def shutdown(self): + self.running = False + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).shutdown() + else: + TCPServer.shutdown(self) + + def isrunning(self): + return self.running + + +class TCPEchoClientTest(BaseHostTest): + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_tcp_server(self): + """ + sets up a TCP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_tcp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_tcp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join() diff --git a/TESTS/netsocket/host_tests/udp_echo.py b/TESTS/netsocket/host_tests/udp_echo.py new file mode 100644 index 00000000000..e63195ae4ab --- /dev/null +++ b/TESTS/netsocket/host_tests/udp_echo.py @@ -0,0 +1,127 @@ +""" +mbed SDK +Copyright (c) 2011-2013 ARM Limited + +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. +""" + +import sys +import socket +from sys import stdout +from threading import Thread +from SocketServer import BaseRequestHandler, UDPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class UDPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ UDP packet handler. Echoes data back to sender's address. + """ + data, sock = self.request + sock.sendto(data, self.client_address) + + +class UDPEchoClientTest(BaseHostTest): + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_udp_server(self): + """ + sets up a UDP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_udp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_udp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join() diff --git a/TESTS/netsocket/host_tests/udp_shotgun.py b/TESTS/netsocket/host_tests/udp_shotgun.py new file mode 100644 index 00000000000..cdf18f963bf --- /dev/null +++ b/TESTS/netsocket/host_tests/udp_shotgun.py @@ -0,0 +1,142 @@ +""" +mbed SDK +Copyright (c) 2011-2013 ARM Limited + +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. +""" + +import sys +import socket +import json +import random +import itertools +import time +from sys import stdout +from threading import Thread +from SocketServer import BaseRequestHandler, UDPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class UDPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ UDP packet handler. Responds with multiple simultaneous packets + """ + data, sock = self.request + pattern = [ord(d) << 4 for d in data] + + # Each byte in request indicates size of packet to recieve + # Each packet size is shifted over by 4 to fit in a byte, which + # avoids any issues with endianess or decoding + for packet in pattern: + data = [random.randint(0, 255) for _ in range(packet-1)] + data.append(reduce(lambda a,b: a^b, data)) + data = ''.join(map(chr, data)) + sock.sendto(data, self.client_address) + + # Sleep a tiny bit to compensate for local network + time.sleep(0.01) + + +class UDPEchoClientTest(BaseHostTest): + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_udp_server(self): + """ + sets up a UDP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_udp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_udp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join() diff --git a/TESTS/netsocket/socket_sigio/main.cpp b/TESTS/netsocket/socket_sigio/main.cpp new file mode 100644 index 00000000000..0997b7db319 --- /dev/null +++ b/TESTS/netsocket/socket_sigio/main.cpp @@ -0,0 +1,191 @@ +#include +#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" + +using namespace utest::v1; + + +namespace { + // Test connection information + const char *HTTP_SERVER_NAME = "developer.mbed.org"; + const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt"; + const int HTTP_SERVER_PORT = 80; +#if defined(TARGET_VK_RZ_A1H) + const int RECV_BUFFER_SIZE = 300; +#else + const int RECV_BUFFER_SIZE = 512; +#endif + // Test related data + const char *HTTP_OK_STR = "200 OK"; + const char *HTTP_HELLO_STR = "Hello world!"; + + // Test buffers + char buffer[RECV_BUFFER_SIZE] = {0}; + + Semaphore recvd; + NetworkInterface *net; +} + +void net_bringup() { + net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); +} + +bool find_substring(const char *first, const char *last, const char *s_first, const char *s_last) { + const char *f = std::search(first, last, s_first, s_last); + return (f != last); +} + +void get_data(TCPSocket* sock){ + bool result = false; + // Server will respond with HTTP GET's success code + const int ret = sock->recv(buffer, sizeof(buffer) - 1); + if(ret <= 0) + return; + + buffer[ret] = '\0'; + + // Find 200 OK HTTP status in reply + bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR)); + // Find "Hello World!" string in reply + bool found_hello = find_substring(buffer, buffer + ret, HTTP_HELLO_STR, HTTP_HELLO_STR + strlen(HTTP_HELLO_STR)); + + TEST_ASSERT_TRUE(found_200_ok); + TEST_ASSERT_TRUE(found_hello); + + if (found_200_ok && found_hello) result = true; + + TEST_ASSERT_EQUAL(result, true); + + printf("HTTP: Received %d chars from server\r\n", ret); + printf("HTTP: Received 200 OK status ... %s\r\n", found_200_ok ? "[OK]" : "[FAIL]"); + printf("HTTP: Received '%s' status ... %s\r\n", HTTP_HELLO_STR, found_hello ? "[OK]" : "[FAIL]"); + printf("HTTP: Received message:\r\n"); + printf("%s", buffer); + // Signal that we have recvd + recvd.release(); +} + +void prep_buffer() { + memset(buffer, 0, sizeof(buffer)); + // We are constructing GET command like this: + // GET http://developer.mbed.org/media/uploads/mbed_official/hello.txt HTTP/1.0\n\n + strcpy(buffer, "GET http://"); + strcat(buffer, HTTP_SERVER_NAME); + strcat(buffer, HTTP_SERVER_FILE_PATH); + strcat(buffer, " HTTP/1.0\n\n"); +} + +void test_socket_attach() { + // Dispatch event queue + Thread eventThread; + EventQueue queue; + eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); + + printf("TCP client IP Address is %s\r\n", net->get_ip_address()); + + TCPSocket sock(net); + printf("HTTP: Connection to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT); + if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) { + printf("HTTP: OK\r\n"); + + prep_buffer(); + // Attach a sigio function that adds function to event queue + sock.sigio(queue.event(get_data, &sock)); + // Send GET command + sock.send(buffer, strlen(buffer)); + // wait for recv data + recvd.wait(); + } else { + printf("HTTP: ERROR\r\n"); + } + sock.close(); +} + +void cb_fail() { + TEST_ASSERT(false); +} + +void cb_pass() { + recvd.release(); +} + +void test_socket_detach() { + // Dispatch event queue + Thread eventThread; + EventQueue queue; + eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); + + printf("TCP client IP Address is %s\r\n", net->get_ip_address()); + + TCPSocket sock(net); + printf("HTTP: Connection to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT); + if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) { + printf("HTTP: OK\r\n"); + + prep_buffer(); + // Attach a sigio function that adds function to event queue + sock.sigio(queue.event(cb_fail)); + // Detach function + sock.sigio(NULL); + // Send GET command + sock.send(buffer, strlen(buffer)); + wait(5); + } else { + printf("HTTP: ERROR\r\n"); + } + sock.close(); +} + +void test_socket_reattach() { + // Dispatch event queue + Thread eventThread; + EventQueue queue; + eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); + + printf("TCP client IP Address is %s\r\n", net->get_ip_address()); + + TCPSocket sock(net); + printf("HTTP: Connection to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT); + if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) { + printf("HTTP: OK\r\n"); + + prep_buffer(); + // Attach a sigio function that adds function to event queue + sock.sigio(queue.event(cb_fail)); + // Override previous attach + sock.sigio(queue.event(cb_pass)); + // Send GET command + sock.send(buffer, strlen(buffer)); + recvd.wait(); + TEST_ASSERT(true); + } else { + printf("HTTP: ERROR\r\n"); + } + sock.close(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + net_bringup(); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Socket Attach Test", test_socket_attach), + Case("Socket Detach Test", test_socket_detach), + Case("Socket Reattach Test", test_socket_reattach), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/tcp_echo/main.cpp b/TESTS/netsocket/tcp_echo/main.cpp new file mode 100644 index 00000000000..1210776314a --- /dev/null +++ b/TESTS/netsocket/tcp_echo/main.cpp @@ -0,0 +1,99 @@ +#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" + +using namespace utest::v1; + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256 +#endif + +namespace { + char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + const char ASCII_MAX = '~' - ' '; +} + +void prep_buffer(char *tx_buffer, size_t tx_size) { + for (size_t i=0; iget_ip_address()); + + bool result = false; + + TCPSocket sock(net); + + SocketAddress tcp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); + + if (sock.connect(tcp_addr) == 0) { + printf("HTTP: Connected to %s:%d\r\n", MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); + printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer)); + printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer)); + + prep_buffer(tx_buffer, sizeof(tx_buffer)); + sock.recv(rx_buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX)); + const int ret = sock.send(tx_buffer, sizeof(tx_buffer)); + if (ret >= 0) { + printf("sent %d bytes - %.*s \n", ret, ret, tx_buffer); + } else { + printf("Network error %d\n", ret); + } + + int n = sock.recv(rx_buffer, sizeof(rx_buffer)); + if (n >= 0) { + printf("recv %d bytes - %.*s \n", n, n, rx_buffer); + } else { + printf("Network error %d\n", n); + } + + result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer)); + TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer)); + TEST_ASSERT_EQUAL(true, result); + } + + sock.close(); + net->disconnect(); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + char uuid[48] = {0}; + GREENTEA_SETUP(240, "tcp_echo"); + + // create mac address based on uuid + uint64_t mac = 0; + for (int i = 0; i < sizeof(uuid); i++) { + mac += uuid[i]; + } + //mbed_set_mac_address((const char*)mac, /*coerce control bits*/ 1); + + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP echo", test_tcp_echo), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/tcp_echo_parallel/main.cpp b/TESTS/netsocket/tcp_echo_parallel/main.cpp new file mode 100644 index 00000000000..ef3971a0071 --- /dev/null +++ b/TESTS/netsocket/tcp_echo_parallel/main.cpp @@ -0,0 +1,135 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel tests are not supported by default +#endif + +#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" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_THREADS +#define MBED_CFG_TCP_CLIENT_ECHO_THREADS 3 +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +NetworkInterface* net; +SocketAddress tcp_addr; +Mutex iomutex; + +void prep_buffer(char *tx_buffer, size_t tx_size) { + for (size_t i=0; iget_ip_address()); + + tcp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); + tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); + + // Startup echo threads in parallel + for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { + echoers[i] = new Echo; + echoers[i]->start(); + } + + for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { + echoers[i]->join(); + delete echoers[i]; + } + + net->disconnect(); +} + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP echo parallel", test_tcp_echo_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/tcp_hello_world/main.cpp b/TESTS/netsocket/tcp_hello_world/main.cpp new file mode 100644 index 00000000000..555638c16d6 --- /dev/null +++ b/TESTS/netsocket/tcp_hello_world/main.cpp @@ -0,0 +1,98 @@ +#include +#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" + +using namespace utest::v1; + + +namespace { + // Test connection information + const char *HTTP_SERVER_NAME = "developer.mbed.org"; + const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt"; + const int HTTP_SERVER_PORT = 80; +#if defined(TARGET_VK_RZ_A1H) + const int RECV_BUFFER_SIZE = 300; +#else + const int RECV_BUFFER_SIZE = 512; +#endif + // Test related data + const char *HTTP_OK_STR = "200 OK"; + const char *HTTP_HELLO_STR = "Hello world!"; + + // Test buffers + char buffer[RECV_BUFFER_SIZE] = {0}; +} + +bool find_substring(const char *first, const char *last, const char *s_first, const char *s_last) { + const char *f = std::search(first, last, s_first, s_last); + return (f != last); +} + +void test_tcp_hello_world() { + bool result = false; + NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + MBED_CONF_APP_CONNECT_STATEMENT; + printf("TCP client IP Address is %s\r\n", net->get_ip_address()); + + TCPSocket sock(net); + printf("HTTP: Connection to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT); + if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) { + printf("HTTP: OK\r\n"); + + // We are constructing GET command like this: + // GET http://developer.mbed.org/media/uploads/mbed_official/hello.txt HTTP/1.0\n\n + strcpy(buffer, "GET http://"); + strcat(buffer, HTTP_SERVER_NAME); + strcat(buffer, HTTP_SERVER_FILE_PATH); + strcat(buffer, " HTTP/1.0\n\n"); + // Send GET command + sock.send(buffer, strlen(buffer)); + + // Server will respond with HTTP GET's success code + const int ret = sock.recv(buffer, sizeof(buffer) - 1); + buffer[ret] = '\0'; + + // Find 200 OK HTTP status in reply + bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR)); + // Find "Hello World!" string in reply + bool found_hello = find_substring(buffer, buffer + ret, HTTP_HELLO_STR, HTTP_HELLO_STR + strlen(HTTP_HELLO_STR)); + + TEST_ASSERT_TRUE(found_200_ok); + TEST_ASSERT_TRUE(found_hello); + + if (found_200_ok && found_hello) result = true; + + printf("HTTP: Received %d chars from server\r\n", ret); + printf("HTTP: Received 200 OK status ... %s\r\n", found_200_ok ? "[OK]" : "[FAIL]"); + printf("HTTP: Received '%s' status ... %s\r\n", HTTP_HELLO_STR, found_hello ? "[OK]" : "[FAIL]"); + printf("HTTP: Received message:\r\n"); + printf("%s", buffer); + sock.close(); + } else { + printf("HTTP: ERROR\r\n"); + } + + net->disconnect(); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP hello world", test_tcp_hello_world), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/tcp_packet_pressure/main.cpp b/TESTS/netsocket/tcp_packet_pressure/main.cpp new file mode 100644 index 00000000000..f14ed5dc018 --- /dev/null +++ b/TESTS/netsocket/tcp_packet_pressure/main.cpp @@ -0,0 +1,228 @@ +#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 "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t *buffer; +size_t buffer_size; + +// 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 +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +void test_tcp_packet_pressure() { + generate_buffer(&buffer, &buffer_size, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); + printf("MBED: Generated buffer %d\r\n", buffer_size); + + NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address()); + + TCPSocket sock; + SocketAddress tcp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); + + Timer timer; + timer.start(); + + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(net); + TEST_ASSERT_EQUAL(0, err); + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + printf("TCP: %s:%d streaming %d bytes\r\n", + tcp_addr.get_ip_address(), tcp_addr.get_port(), size); + + //recv connection prefix message + sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX)); + memset(buffer, 0, sizeof(buffer)); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out data + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.send(buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: tx -> %d\r\n", td); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, + // cut buffer in half + if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: Not sent (%d), window = %d\r\n", td, window); + } + } + } + + // Verify recieved data + while (rx_count < size) { + int rd = sock.recv(buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + if (rd > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: rx <- %d\r\n", rd); + } + int diff = rx_seq.cmp(buffer, rd); + TEST_ASSERT_EQUAL(0, diff); + rx_seq.skip(rd); + rx_count += rd; + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net->disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP packet pressure", test_tcp_packet_pressure), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp b/TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp new file mode 100644 index 00000000000..2c6e97124cf --- /dev/null +++ b/TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp @@ -0,0 +1,289 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default +#endif + +#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" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 3 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + + +// 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 +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +// Global variables shared between pressure tests +NetworkInterface* net; +SocketAddress tcp_addr; +Timer timer; +Mutex iomutex; + +// Single instance of a pressure test +class PressureTest { +private: + uint8_t *buffer; + size_t buffer_size; + + TCPSocket sock; + Thread thread; + +public: + PressureTest(uint8_t *buffer, size_t buffer_size) + : buffer(buffer), buffer_size(buffer_size) { + } + + void start() { + osStatus status = thread.start(callback(this, &PressureTest::run)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void run() { + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + int err = sock.open(net); + TEST_ASSERT_EQUAL(0, err); + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + sock.recv(buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX)); + + iomutex.lock(); + printf("TCP: %s:%d streaming %d bytes\r\n", + tcp_addr.get_ip_address(), tcp_addr.get_port(), size); + iomutex.unlock(); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out data + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.send(buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: tx -> %d\r\n", td); + iomutex.unlock(); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, + // cut buffer in half + if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: Not sent (%d), window = %d\r\n", td, window); + iomutex.unlock(); + } + } + } + + // Verify recieved data + while (rx_count < size) { + int rd = sock.recv(buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + if (rd > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: rx <- %d\r\n", rd); + iomutex.unlock(); + } + int diff = rx_seq.cmp(buffer, rd); + TEST_ASSERT_EQUAL(0, diff); + rx_seq.skip(rd); + rx_count += rd; + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + } +}; + +PressureTest *pressure_tests[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS]; + + +void test_tcp_packet_pressure_parallel() { + uint8_t *buffer; + size_t buffer_size; + generate_buffer(&buffer, &buffer_size, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); + + size_t buffer_subsize = buffer_size / MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; + printf("MBED: Generated buffer %d\r\n", buffer_size); + printf("MBED: Split into %d buffers %d\r\n", + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS, + buffer_subsize); + + net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net->get_ip_address()); + + tcp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); + tcp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); + + timer.start(); + + // Startup pressure tests in parallel + for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); + pressure_tests[i]->start(); + } + + for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i]->join(); + delete pressure_tests[i]; + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS* + 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net->disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP packet pressure parallel", test_tcp_packet_pressure_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/udp_dtls_handshake/main.cpp b/TESTS/netsocket/udp_dtls_handshake/main.cpp new file mode 100644 index 00000000000..d20138f39e5 --- /dev/null +++ b/TESTS/netsocket/udp_dtls_handshake/main.cpp @@ -0,0 +1,144 @@ +#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" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE +#define MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE 512 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES +#define MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES 16 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN +#define MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN 112, 384, 200, 219, 25 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT +#define MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT 1500 +#endif + + +uint8_t buffer[MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE] = {0}; +int udp_dtls_handshake_pattern[] = {MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN}; +const int udp_dtls_handshake_count = sizeof(udp_dtls_handshake_pattern) / sizeof(int); + +void test_udp_dtls_handshake() { + NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net->get_ip_address()); + + bool result = false; + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + 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("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); + + // align each size to 4-bits + for (int i = 0; i < udp_dtls_handshake_count; i++) { + udp_dtls_handshake_pattern[i] = (~0xf & udp_dtls_handshake_pattern[i]) + 0x10; + } + + printf("MBED: DTLS pattern ["); + for (int i = 0; i < udp_dtls_handshake_count; i++) { + printf("%d", udp_dtls_handshake_pattern[i]); + if (i != udp_dtls_handshake_count-1) { + printf(", "); + } + } + printf("]\r\n"); + + UDPSocket sock; + SocketAddress udp_addr(ipbuf, port); + sock.set_timeout(MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT); + + for (int attempt = 0; attempt < MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES; attempt++) { + err = sock.open(net); + TEST_ASSERT_EQUAL(0, err); + + for (int i = 0; i < udp_dtls_handshake_count; i++) { + buffer[i] = udp_dtls_handshake_pattern[i] >> 4; + } + + err = sock.sendto(udp_addr, buffer, udp_dtls_handshake_count); + printf("UDP: tx -> %d\r\n", err); + TEST_ASSERT_EQUAL(udp_dtls_handshake_count, err); + + int step = 0; + while (step < udp_dtls_handshake_count) { + err = sock.recvfrom(NULL, buffer, sizeof(buffer)); + printf("UDP: rx <- %d ", err); + + // check length + if (err != udp_dtls_handshake_pattern[step]) { + printf("x (expected %d)\r\n", udp_dtls_handshake_pattern[step]); + break; + } + + // check quick xor of packet + uint8_t check = 0; + for (int j = 0; j < udp_dtls_handshake_pattern[step]; j++) { + check ^= buffer[j]; + } + + if (check != 0) { + printf("x (checksum 0x%02x)\r\n", check); + break; + } + + // successfully got a packet + printf("\r\n"); + step += 1; + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + + // got through all steps, test passed + if (step == udp_dtls_handshake_count) { + result = true; + break; + } + } + + net->disconnect(); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_shotgun"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP DTLS handshake", test_udp_dtls_handshake), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/udp_echo/main.cpp b/TESTS/netsocket/udp_echo/main.cpp new file mode 100644 index 00000000000..f5b65830e85 --- /dev/null +++ b/TESTS/netsocket/udp_echo/main.cpp @@ -0,0 +1,128 @@ +#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" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT +#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 +#endif + +namespace { + char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + const char ASCII_MAX = '~' - ' '; + const int ECHO_LOOPS = 16; + char uuid[48] = {0}; +} + +void prep_buffer(char *uuid, char *tx_buffer, size_t tx_size) { + size_t i = 0; + + memcpy(tx_buffer, uuid, strlen(uuid)); + i += strlen(uuid); + + tx_buffer[i++] = ' '; + + for (; iget_ip_address()); + + UDPSocket sock; + sock.open(net); + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + + SocketAddress udp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); + + int success = 0; + for (int i = 0; success < ECHO_LOOPS; i++) { + prep_buffer(uuid, tx_buffer, sizeof(tx_buffer)); + const int ret = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer)); + if (ret >= 0) { + printf("[%02d] sent %d bytes - %.*s \n", i, ret, ret, tx_buffer); + } else { + printf("[%02d] Network error %d\n", i, ret); + continue; + } + + SocketAddress temp_addr; + const int n = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); + if (n >= 0) { + printf("[%02d] recv %d bytes - %.*s \n", i, n, n, rx_buffer); + } else { + printf("[%02d] Network error %d\n", i, n); + continue; + } + + if ((temp_addr == udp_addr && + n == sizeof(tx_buffer) && + memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { + success += 1; + + printf("[%02d] success #%d\n", i, success); + continue; + } + + // failed, clean out any remaining bad packets + 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); + } + + sock.close(); + net->disconnect(); + TEST_ASSERT_EQUAL(ECHO_LOOPS, success); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(240, "udp_echo"); + + // create mac address based on uuid + uint64_t mac = 0; + for (int i = 0; i < sizeof(uuid); i++) { + mac += uuid[i]; + } + //mbed_set_mac_address((const char*)mac, /*coerce control bits*/ 1); + + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP echo", test_udp_echo), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/udp_echo_parallel/main.cpp b/TESTS/netsocket/udp_echo_parallel/main.cpp new file mode 100644 index 00000000000..589fc76a135 --- /dev/null +++ b/TESTS/netsocket/udp_echo_parallel/main.cpp @@ -0,0 +1,204 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel tests are not supported by default +#endif + +#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" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT +#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_THREADS +#define MBED_CFG_UDP_CLIENT_ECHO_THREADS 3 +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +const int ECHO_LOOPS = 16; +NetworkInterface* net; +SocketAddress udp_addr; +Mutex iomutex; +char uuid[48] = {0}; + +// NOTE: assuming that "id" stays in the single digits +void prep_buffer(int id, char *uuid, char *tx_buffer, size_t tx_size) { + size_t i = 0; + + tx_buffer[i++] = '0' + id; + tx_buffer[i++] = ' '; + + memcpy(tx_buffer+i, uuid, strlen(uuid)); + i += strlen(uuid); + + tx_buffer[i++] = ' '; + + for (; iid = id; + this->uuid = uuid; + osStatus status = thread.start(callback(this, &Echo::echo)); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void echo() { + int success = 0; + + int err = sock.open(net); + TEST_ASSERT_EQUAL(0, err); + + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + + for (int i = 0; success < ECHO_LOOPS; i++) { + prep_buffer(id, uuid, tx_buffer, sizeof(tx_buffer)); + const int ret = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer)); + if (ret >= 0) { + iomutex.lock(); + printf("[ID:%01d][%02d] sent %d bytes - %.*s \n", id, i, ret, ret, tx_buffer); + iomutex.unlock(); + } else { + iomutex.lock(); + printf("[ID:%01d][%02d] Network error %d\n", id, i, ret); + iomutex.unlock(); + continue; + } + + SocketAddress temp_addr; + const int n = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); + if (n >= 0) { + iomutex.lock(); + printf("[ID:%01d][%02d] recv %d bytes - %.*s \n", id, i, n, n, tx_buffer); + iomutex.unlock(); + } else { + iomutex.lock(); + printf("[ID:%01d][%02d] Network error %d\n", id, i, n); + iomutex.unlock(); + continue; + } + + if ((temp_addr == udp_addr && + n == sizeof(tx_buffer) && + memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { + success += 1; + iomutex.lock(); + printf("[ID:%01d][%02d] success #%d\n", id, i, success); + iomutex.unlock(); + continue; + } + + // failed, clean out any remaining bad packets + 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); + } + + result = success == ECHO_LOOPS; + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + if (err) { + result = false; + } + } + + bool get_result() { + return result; + } +}; + +Echo *echoers[MBED_CFG_UDP_CLIENT_ECHO_THREADS]; + + +void test_udp_echo_parallel() { + net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + if (err) { + printf("MBED: failed to connect with an error of %d\r\n", err); + GREENTEA_TESTSUITE_RESULT(false); + } else { + printf("UDP client IP Address is %s\n", net->get_ip_address()); + + udp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); + udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); + + // Startup echo threads in parallel + for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { + echoers[i] = new Echo; + echoers[i]->start(i, uuid); + } + + bool result = true; + + for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { + echoers[i]->join(); + result = result && echoers[i]->get_result(); + delete echoers[i]; + } + + net->disconnect(); + TEST_ASSERT_EQUAL(true, result); + } +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP echo parallel", test_udp_echo_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/udp_packet_pressure/main.cpp b/TESTS/netsocket/udp_packet_pressure/main.cpp new file mode 100644 index 00000000000..a5eee249541 --- /dev/null +++ b/TESTS/netsocket/udp_packet_pressure/main.cpp @@ -0,0 +1,247 @@ +#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 "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t *buffer; +size_t buffer_size; + +// 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 +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + +void test_udp_packet_pressure() { + generate_buffer(&buffer, &buffer_size, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); + printf("MBED: Generated buffer %d\r\n", buffer_size); + + NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address()); + + UDPSocket sock; + SocketAddress udp_addr(MBED_CONF_APP_ECHO_SERVER_ADDR, MBED_CONF_APP_ECHO_SERVER_PORT); + + Timer timer; + timer.start(); + + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(net); + TEST_ASSERT_EQUAL(0, err); + printf("UDP: %s:%d streaming %d bytes\r\n", + udp_addr.get_ip_address(), udp_addr.get_port(), size); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + int known_time = timer.read_ms(); + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out packets + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.sendto(udp_addr, buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: tx -> %d\r\n", td); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, revert to + // last good sequence and cut buffer in half + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: Not sent (%d), window = %d\r\n", td, window); + } + } + } + + // Prioritize recieving over sending packets to avoid flooding + // the network while handling erronous packets + while (rx_count < size) { + int rd = sock.recvfrom(NULL, buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + + if (rd > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: rx <- %d\r\n", rd); + } + + if (rx_seq.cmp(buffer, rd) == 0) { + rx_seq.skip(rd); + rx_count += rd; + known_time = timer.read_ms(); + if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { + window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + } + } + } else if (timer.read_ms() - known_time > + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { + // Dropped packet or out of order, revert to last good sequence + // and cut buffer in half + tx_seq = rx_seq; + tx_count = rx_count; + known_time = timer.read_ms(); + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: Dropped, window = %d\r\n", window); + } + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net->disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP packet pressure", test_udp_packet_pressure), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/netsocket/udp_packet_pressure_parallel/main.cpp b/TESTS/netsocket/udp_packet_pressure_parallel/main.cpp new file mode 100644 index 00000000000..24ae50af204 --- /dev/null +++ b/TESTS/netsocket/udp_packet_pressure_parallel/main.cpp @@ -0,0 +1,312 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default +#endif + +#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" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS 3 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// 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 +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 8; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +// Global variables shared between pressure tests +NetworkInterface* net; +SocketAddress udp_addr; +Timer timer; +Mutex iomutex; + +// Single instance of a pressure test +class PressureTest { +private: + uint8_t *buffer; + size_t buffer_size; + + UDPSocket sock; + Thread thread; + +public: + PressureTest(uint8_t *buffer, size_t buffer_size) + : buffer(buffer), buffer_size(buffer_size) { + } + + void start() { + osStatus status = thread.start(callback(this, &PressureTest::run)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void run() { + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + int err = sock.open(net); + TEST_ASSERT_EQUAL(0, err); + iomutex.lock(); + printf("UDP: %s:%d streaming %d bytes\r\n", + udp_addr.get_ip_address(), udp_addr.get_port(), size); + iomutex.unlock(); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + int known_time = timer.read_ms(); + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out packets + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.sendto(udp_addr, buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: tx -> %d\r\n", td); + iomutex.unlock(); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, revert to + // last good sequence and cut buffer in half + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: Not sent (%d), window = %d\r\n", td, window); + iomutex.unlock(); + } + } + } + + // Prioritize recieving over sending packets to avoid flooding + // the network while handling erronous packets + while (rx_count < size) { + int rd = sock.recvfrom(NULL, buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + + if (rd > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: rx <- %d\r\n", rd); + iomutex.unlock(); + } + + if (rx_seq.cmp(buffer, rd) == 0) { + rx_seq.skip(rd); + rx_count += rd; + known_time = timer.read_ms(); + if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { + window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + } + } + } else if (timer.read_ms() - known_time > + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { + // Dropped packet or out of order, revert to last good sequence + // and cut buffer in half + tx_seq = rx_seq; + tx_count = rx_count; + known_time = timer.read_ms(); + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: Dropped, window = %d\r\n", window); + iomutex.unlock(); + } + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + } +}; + +PressureTest *pressure_tests[MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS]; + + +void test_udp_packet_pressure_parallel() { + uint8_t *buffer; + size_t buffer_size; + generate_buffer(&buffer, &buffer_size, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); + + size_t buffer_subsize = buffer_size / MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; + printf("MBED: Generated buffer %d\r\n", buffer_size); + printf("MBED: Split into %d buffers %d\r\n", + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS, + buffer_subsize); + + net = MBED_CONF_APP_OBJECT_CONSTRUCTION; + int err = MBED_CONF_APP_CONNECT_STATEMENT; + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net->get_ip_address()); + + udp_addr.set_ip_address(MBED_CONF_APP_ECHO_SERVER_ADDR); + udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT); + + timer.start(); + + // Startup pressure tests in parallel + for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); + pressure_tests[i]->start(); + } + + for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i]->join(); + delete pressure_tests[i]; + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS* + 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net->disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP packet pressure parallel", test_udp_packet_pressure_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} From 8c0bc781d938116457d58d03535c352301f22ae7 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Wed, 19 Jul 2017 17:10:34 -0500 Subject: [PATCH 02/13] Allow tools to use networkinterface configs in tests --- targets/targets.json | 3 +++ tools/test.py | 20 +++++++++++--- .../EthernetInterface.json | 27 +++++++++++++++++++ tools/test_api.py | 9 +++++++ 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tools/test/network_test_configs/EthernetInterface.json diff --git a/targets/targets.json b/targets/targets.json index 452e29db014..1b315a3335b 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -608,6 +608,9 @@ "detect_code": ["0240"], "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], "features": ["LWIP", "STORAGE"], + "network_test_configurations" : { + "EthernetInterface" : "mbed-os/tools/test/network_test_configs/EthernetInterface.json" + }, "release_versions": ["2", "5"], "device_name": "MK64FN1M0xxx12", "bootloader_supported": true diff --git a/tools/test.py b/tools/test.py index 91fad7ed50a..6470360a47a 100644 --- a/tools/test.py +++ b/tools/test.py @@ -27,7 +27,7 @@ sys.path.insert(0, ROOT) from tools.config import ConfigException -from tools.test_api import test_path_to_name, find_tests, print_tests, build_tests, test_spec_from_test_builds +from tools.test_api import test_path_to_name, find_tests, find_configs, print_tests, build_tests, test_spec_from_test_builds from tools.options import get_default_options_parser, extract_profile, extract_mcus from tools.build_api import build_project, build_library from tools.build_api import print_build_memory_usage @@ -84,6 +84,9 @@ parser.add_argument("-n", "--names", dest="names", type=argparse_many(str), default=None, help="Limit the tests to a comma separated list of names") + parser.add_argument("--net-config", dest="net_config", type=str, + default="EthernetInterface", help="Limit the tests to a networkinterface") + parser.add_argument("--test-spec", dest="test_spec", default=None, help="Destination path for a test spec file that can be used by the Greentea automated test tool") @@ -133,10 +136,19 @@ "Currently set search path: %s" % (toolchain, search_path)) + net_configs = find_configs(mcu) # will be {} if target has no network configs + # If there is no app config and the target has network configs + # TODO: merge app_config and net_config if there is both + if net_configs and not options.app_config: + # use a specified network config + config = net_configs[options.net_config] + else: + config = options.app_config + # Find all tests in the relevant paths for path in all_paths: all_tests.update(find_tests(path, mcu, toolchain, - app_config=options.app_config)) + app_config=config)) # Filter tests by name if specified if options.names: @@ -192,7 +204,7 @@ properties=build_properties, name="mbed-build", macros=options.macros, verbose=options.verbose, notify=notify, archive=False, - app_config=options.app_config, + app_config=config, build_profile=profile) library_build_success = True @@ -220,7 +232,7 @@ notify=notify, jobs=options.jobs, continue_on_build_fail=options.continue_on_build_fail, - app_config=options.app_config, + app_config=config, build_profile=profile, stats_depth=options.stats_depth) diff --git a/tools/test/network_test_configs/EthernetInterface.json b/tools/test/network_test_configs/EthernetInterface.json new file mode 100644 index 00000000000..69bbac0b3a5 --- /dev/null +++ b/tools/test/network_test_configs/EthernetInterface.json @@ -0,0 +1,27 @@ +{ + "config": { + "header-file": { + "help" : "String for including your driver header file", + "value" : "\"EthernetInterface.h\"" + }, + "object-construction" : { + "value" : "new EthernetInterface()" + }, + "connect-statement" : { + "help" : "Must use 'net' variable name", + "value" : "((EthernetInterface *)net)->connect()" + }, + "echo-server-addr" : { + "help" : "IP address of echo server", + "value" : "\"195.34.89.241\"" + }, + "echo-server-port" : { + "help" : "Port of echo server", + "value" : "7" + }, + "tcp-echo-prefix" : { + "help" : "Some servers send a prefix before echoed message", + "value" : "\"u-blox AG TCP/UDP test service\\n\"" + } + } +} diff --git a/tools/test_api.py b/tools/test_api.py index 985c318e851..564c3496037 100644 --- a/tools/test_api.py +++ b/tools/test_api.py @@ -1999,6 +1999,13 @@ def test_path_to_name(path, base): return "-".join(name_parts).lower() +def find_configs(target_name): + target = TARGET_MAP[target_name] + try: + return target.network_test_configurations + except AttributeError: + return {} + def find_tests(base_dir, target_name, toolchain_name, app_config=None): """ Finds all tests in a directory recursively base_dir: path to the directory to scan for tests (ex. 'path/to/project') @@ -2010,6 +2017,8 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None): tests = {} + configs = find_configs(target_name) + # Prepare the toolchain toolchain = prepare_toolchain([base_dir], None, target_name, toolchain_name, silent=True, app_config=app_config) From e982eed4ad49c976bc1b549af4f3ef34133b4e34 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Thu, 20 Jul 2017 16:00:18 -0500 Subject: [PATCH 03/13] Add option to add a configuration file for modules --- tools/test.py | 17 +++++++++++------ tools/test_api.py | 7 ++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tools/test.py b/tools/test.py index 6470360a47a..ae87da04323 100644 --- a/tools/test.py +++ b/tools/test.py @@ -87,6 +87,9 @@ parser.add_argument("--net-config", dest="net_config", type=str, default="EthernetInterface", help="Limit the tests to a networkinterface") + parser.add_argument("--module-config", dest="module_config", type=str, + default=None, help="Test config for a module") + parser.add_argument("--test-spec", dest="test_spec", default=None, help="Destination path for a test spec file that can be used by the Greentea automated test tool") @@ -136,11 +139,12 @@ "Currently set search path: %s" % (toolchain, search_path)) - net_configs = find_configs(mcu) # will be {} if target has no network configs - # If there is no app config and the target has network configs - # TODO: merge app_config and net_config if there is both - if net_configs and not options.app_config: - # use a specified network config + # Assign config file. Precedence: module_config>net_config>app_config + # TODO: merge configs if there are multiple + if options.module_config: + config = options.module_config + elif find_configs(mcu): + net_configs = find_configs(mcu) # will be {} if target has no network configs config = net_configs[options.net_config] else: config = options.app_config @@ -148,7 +152,8 @@ # Find all tests in the relevant paths for path in all_paths: all_tests.update(find_tests(path, mcu, toolchain, - app_config=config)) + app_config=config, + module_config=options.module_config)) # Filter tests by name if specified if options.names: diff --git a/tools/test_api.py b/tools/test_api.py index 564c3496037..b889667e45c 100644 --- a/tools/test_api.py +++ b/tools/test_api.py @@ -2006,7 +2006,7 @@ def find_configs(target_name): except AttributeError: return {} -def find_tests(base_dir, target_name, toolchain_name, app_config=None): +def find_tests(base_dir, target_name, toolchain_name, app_config=None, module_config=None): """ Finds all tests in a directory recursively base_dir: path to the directory to scan for tests (ex. 'path/to/project') target_name: name of the target to use for scanning (ex. 'K64F') @@ -2046,6 +2046,11 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None): test_group_directory_path, test_case_directory = os.path.split(d) test_group_directory = os.path.basename(test_group_directory_path) + # If the target has no network interface configuration, netsocket tests fail to compile + if not module_config and not configs and \ + (test_case_directory == 'netsocket' or test_group_directory == 'netsocket'): + continue + # Check to make sure discoverd folder is not in a host test directory if test_case_directory != 'host_tests' and test_group_directory != 'host_tests': test_name = test_path_to_name(d, base_dir) From ba6eb98b5c4f64785c2ce1068a2386605cfdfae9 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Fri, 21 Jul 2017 15:07:07 -0500 Subject: [PATCH 04/13] Use only one flag for test configuration file Tools will figure out if user passed in a custom path (to indicate configration file for module) or whether they used a keyword (to indicate they'd like to use an mbed OS configuration) --- targets/targets.json | 3 --- tools/test.py | 25 +++++++++---------- tools/test_api.py | 21 ++++++++++------ .../EthernetInterface.json | 0 tools/test_configs/__init__.py | 25 +++++++++++++++++++ tools/test_configs/config_paths.json | 4 +++ 6 files changed, 55 insertions(+), 23 deletions(-) rename tools/{test/network_test_configs => test_configs}/EthernetInterface.json (100%) create mode 100644 tools/test_configs/__init__.py create mode 100644 tools/test_configs/config_paths.json diff --git a/targets/targets.json b/targets/targets.json index 1b315a3335b..452e29db014 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -608,9 +608,6 @@ "detect_code": ["0240"], "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], "features": ["LWIP", "STORAGE"], - "network_test_configurations" : { - "EthernetInterface" : "mbed-os/tools/test/network_test_configs/EthernetInterface.json" - }, "release_versions": ["2", "5"], "device_name": "MK64FN1M0xxx12", "bootloader_supported": true diff --git a/tools/test.py b/tools/test.py index ae87da04323..1434329cfe6 100644 --- a/tools/test.py +++ b/tools/test.py @@ -27,7 +27,7 @@ sys.path.insert(0, ROOT) from tools.config import ConfigException -from tools.test_api import test_path_to_name, find_tests, find_configs, print_tests, build_tests, test_spec_from_test_builds +from tools.test_api import test_path_to_name, find_tests, get_test_config, print_tests, build_tests, test_spec_from_test_builds from tools.options import get_default_options_parser, extract_profile, extract_mcus from tools.build_api import build_project, build_library from tools.build_api import print_build_memory_usage @@ -84,10 +84,7 @@ parser.add_argument("-n", "--names", dest="names", type=argparse_many(str), default=None, help="Limit the tests to a comma separated list of names") - parser.add_argument("--net-config", dest="net_config", type=str, - default="EthernetInterface", help="Limit the tests to a networkinterface") - - parser.add_argument("--module-config", dest="module_config", type=str, + parser.add_argument("--test-config", dest="test_config", type=str, default=None, help="Test config for a module") parser.add_argument("--test-spec", dest="test_spec", @@ -139,13 +136,15 @@ "Currently set search path: %s" % (toolchain, search_path)) - # Assign config file. Precedence: module_config>net_config>app_config - # TODO: merge configs if there are multiple - if options.module_config: - config = options.module_config - elif find_configs(mcu): - net_configs = find_configs(mcu) # will be {} if target has no network configs - config = net_configs[options.net_config] + # boolean, true if test configuration file is for module false if mbed-os interface + module_conf = False + + # Assign config file. Precedence: test_config>app_config + # TODO: merge configs if both given + if options.test_config: + config, module_conf = get_test_config(options.test_config, mcu) + if not config: + args_error(parser, "argument --test-config contains invalid path or identifier") else: config = options.app_config @@ -153,7 +152,7 @@ for path in all_paths: all_tests.update(find_tests(path, mcu, toolchain, app_config=config, - module_config=options.module_config)) + module_config=module_conf)) # Filter tests by name if specified if options.names: diff --git a/tools/test_api.py b/tools/test_api.py index b889667e45c..e5f915f16fa 100644 --- a/tools/test_api.py +++ b/tools/test_api.py @@ -50,6 +50,7 @@ from tools.utils import construct_enum from tools.memap import MemapParser from tools.targets import TARGET_MAP +from tools.test_configs import TestConfig from tools.test_db import BaseDBAccess from tools.build_api import build_project, build_mbed_libs, build_lib from tools.build_api import get_target_supported_toolchains @@ -1999,12 +2000,18 @@ def test_path_to_name(path, base): return "-".join(name_parts).lower() -def find_configs(target_name): - target = TARGET_MAP[target_name] - try: - return target.network_test_configurations - except AttributeError: - return {} +def get_test_config(config_name, target_name): + """Finds the path to a test configuration file + config_name: path to a custom configuration file OR mbed OS interface "ethernet, wifi_odin, etc" + target_name: name of target to determing if mbed OS interface given is valid + returns path to config, boolean of whether it is a module or mbed OS interface + """ + # If they passed in a full path + if exists(config_name): + # This is a module config + return config_name, True + # Otherwise find the path to configuration file based on mbed OS interface + return TestConfig.get_config_path(config_name, target_name), False def find_tests(base_dir, target_name, toolchain_name, app_config=None, module_config=None): """ Finds all tests in a directory recursively @@ -2017,7 +2024,7 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None, module_co tests = {} - configs = find_configs(target_name) + configs = TestConfig.get_valid_configs(target_name) # Prepare the toolchain toolchain = prepare_toolchain([base_dir], None, target_name, toolchain_name, diff --git a/tools/test/network_test_configs/EthernetInterface.json b/tools/test_configs/EthernetInterface.json similarity index 100% rename from tools/test/network_test_configs/EthernetInterface.json rename to tools/test_configs/EthernetInterface.json diff --git a/tools/test_configs/__init__.py b/tools/test_configs/__init__.py new file mode 100644 index 00000000000..86de0e37446 --- /dev/null +++ b/tools/test_configs/__init__.py @@ -0,0 +1,25 @@ +from os.path import dirname, abspath, join + +from tools.utils import json_file_to_dict +from tools.targets import TARGET_MAP + +class TestConfig: + CONFIG_DIR = dirname(abspath(__file__)) + CONFIG_MAP = json_file_to_dict(join(CONFIG_DIR, "config_paths.json")) + + @classmethod + def get_valid_configs(cls, target_name): + target = TARGET_MAP[target_name] + config_dict = {} + for attr in cls.CONFIG_MAP: + if attr in target.device_has: + config_dict[attr] = cls.CONFIG_MAP[attr] + return config_dict + + @classmethod + def get_config_path(cls, conf_name, target_name): + configs = cls.get_valid_configs(target_name) + if configs and conf_name.upper() in configs: + return join(cls.CONFIG_DIR, configs[conf_name.upper()]) + else: + return None diff --git a/tools/test_configs/config_paths.json b/tools/test_configs/config_paths.json new file mode 100644 index 00000000000..e75864e08da --- /dev/null +++ b/tools/test_configs/config_paths.json @@ -0,0 +1,4 @@ +{ + "ETHERNET" : "EthernetInterface.json", + "ODIN_WIFI" : "OdinInterface.json" +} From dee8e7f0eaa35abe96e6560194b0d0a88a19a992 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Fri, 21 Jul 2017 16:09:15 -0500 Subject: [PATCH 05/13] Use default mbed-os test configuration if no app_config is supplied --- tools/test.py | 3 +++ tools/test_configs/__init__.py | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/tools/test.py b/tools/test.py index 1434329cfe6..81b0c1b2c80 100644 --- a/tools/test.py +++ b/tools/test.py @@ -28,6 +28,7 @@ from tools.config import ConfigException from tools.test_api import test_path_to_name, find_tests, get_test_config, print_tests, build_tests, test_spec_from_test_builds +from tools.test_configs import TestConfig from tools.options import get_default_options_parser, extract_profile, extract_mcus from tools.build_api import build_project, build_library from tools.build_api import print_build_memory_usage @@ -145,6 +146,8 @@ config, module_conf = get_test_config(options.test_config, mcu) if not config: args_error(parser, "argument --test-config contains invalid path or identifier") + elif not options.app_config: + config = TestConfig.get_default_config(mcu) else: config = options.app_config diff --git a/tools/test_configs/__init__.py b/tools/test_configs/__init__.py index 86de0e37446..07e0a170fa0 100644 --- a/tools/test_configs/__init__.py +++ b/tools/test_configs/__init__.py @@ -23,3 +23,12 @@ def get_config_path(cls, conf_name, target_name): return join(cls.CONFIG_DIR, configs[conf_name.upper()]) else: return None + + @classmethod + def get_default_config(cls, target_name): + configs = cls.get_valid_configs(target_name) + if configs: + keys = configs.keys() + return join(cls.CONFIG_DIR, configs[keys[0]]) + else: + return None From e48f9948a748e2bf08843b0941d157905cc47eda Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Fri, 21 Jul 2017 16:09:59 -0500 Subject: [PATCH 06/13] Add ETHERNET and ODIN_WIFI to odin device has. Add odin WiFi test configuration --- targets/targets.json | 5 +++++ tools/test_configs/OdinInterface.json | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tools/test_configs/OdinInterface.json diff --git a/targets/targets.json b/targets/targets.json index 452e29db014..25d315ba2aa 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -1688,8 +1688,13 @@ "supported_form_factors": ["ARDUINO"], "core": "Cortex-M4F", "extra_labels_add": ["STM32F4", "STM32F439", "STM32F439ZI","STM32F439xx", "STM32F439xI"], +<<<<<<< HEAD "macros": ["MBEDTLS_CONFIG_HW_SUPPORT", "HSE_VALUE=24000000", "HSE_STARTUP_TIMEOUT=5000", "CB_INTERFACE_SDIO","CB_CHIP_WL18XX","SUPPORT_80211D_ALWAYS","WLAN_ENABLED","MBEDTLS_ARC4_C","MBEDTLS_DES_C","MBEDTLS_MD4_C","MBEDTLS_MD5_C","MBEDTLS_SHA1_C"], "device_has_add": ["CAN", "EMAC", "TRNG", "FLASH"], +======= + "macros": ["HSE_VALUE=24000000", "HSE_STARTUP_TIMEOUT=5000", "CB_INTERFACE_SDIO","CB_CHIP_WL18XX","SUPPORT_80211D_ALWAYS","WLAN_ENABLED","MBEDTLS_ARC4_C","MBEDTLS_DES_C","MBEDTLS_MD4_C","MBEDTLS_MD5_C","MBEDTLS_SHA1_C"], + "device_has_add": ["CAN", "EMAC", "TRNG", "FLASH", "ETHERNET", "ODIN_WIFI"], +>>>>>>> Add ETHERNET and ODIN_WIFI to odin device has. Add odin WiFi test configuration "device_has_remove": ["RTC", "SLEEP"], "features": ["LWIP"], "release_versions": ["5"], diff --git a/tools/test_configs/OdinInterface.json b/tools/test_configs/OdinInterface.json new file mode 100644 index 00000000000..3ebac83f0ef --- /dev/null +++ b/tools/test_configs/OdinInterface.json @@ -0,0 +1,27 @@ +{ + "config": { + "header-file": { + "help" : "String for including your driver header file", + "value" : "\"OdinWiFiInterface.h\"" + }, + "object-construction" : { + "value" : "new OdinWiFiInterface()" + }, + "connect-statement" : { + "help" : "Must use 'net' variable name", + "value" : "((OdinWiFiInterface *)net)->connect(WIFI_SSID, WIFI_PASSWORD)" + }, + "echo-server-addr" : { + "help" : "IP address of echo server", + "value" : "\"195.34.89.241\"" + }, + "echo-server-port" : { + "help" : "Port of echo server", + "value" : "7" + }, + "tcp-echo-prefix" : { + "help" : "Some servers send a prefix before echoed message", + "value" : "\"u-blox AG TCP/UDP test service\\n\"" + } + } +} From 4161e5c48d7f6ab5cecfa69f3d71f7f7df2f844b Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Fri, 4 Aug 2017 16:30:17 -0500 Subject: [PATCH 07/13] Move test config keys out of targets.json Change TestConfig class methods to module methods --- targets/targets.json | 5 --- tools/test.py | 2 +- tools/test_api.py | 2 +- tools/test_configs/__init__.py | 53 +++++++++++++------------- tools/test_configs/target_configs.json | 10 +++++ 5 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 tools/test_configs/target_configs.json diff --git a/targets/targets.json b/targets/targets.json index 25d315ba2aa..452e29db014 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -1688,13 +1688,8 @@ "supported_form_factors": ["ARDUINO"], "core": "Cortex-M4F", "extra_labels_add": ["STM32F4", "STM32F439", "STM32F439ZI","STM32F439xx", "STM32F439xI"], -<<<<<<< HEAD "macros": ["MBEDTLS_CONFIG_HW_SUPPORT", "HSE_VALUE=24000000", "HSE_STARTUP_TIMEOUT=5000", "CB_INTERFACE_SDIO","CB_CHIP_WL18XX","SUPPORT_80211D_ALWAYS","WLAN_ENABLED","MBEDTLS_ARC4_C","MBEDTLS_DES_C","MBEDTLS_MD4_C","MBEDTLS_MD5_C","MBEDTLS_SHA1_C"], "device_has_add": ["CAN", "EMAC", "TRNG", "FLASH"], -======= - "macros": ["HSE_VALUE=24000000", "HSE_STARTUP_TIMEOUT=5000", "CB_INTERFACE_SDIO","CB_CHIP_WL18XX","SUPPORT_80211D_ALWAYS","WLAN_ENABLED","MBEDTLS_ARC4_C","MBEDTLS_DES_C","MBEDTLS_MD4_C","MBEDTLS_MD5_C","MBEDTLS_SHA1_C"], - "device_has_add": ["CAN", "EMAC", "TRNG", "FLASH", "ETHERNET", "ODIN_WIFI"], ->>>>>>> Add ETHERNET and ODIN_WIFI to odin device has. Add odin WiFi test configuration "device_has_remove": ["RTC", "SLEEP"], "features": ["LWIP"], "release_versions": ["5"], diff --git a/tools/test.py b/tools/test.py index 81b0c1b2c80..48b7a92349a 100644 --- a/tools/test.py +++ b/tools/test.py @@ -28,7 +28,7 @@ from tools.config import ConfigException from tools.test_api import test_path_to_name, find_tests, get_test_config, print_tests, build_tests, test_spec_from_test_builds -from tools.test_configs import TestConfig +import tools.test_configs as TestConfig from tools.options import get_default_options_parser, extract_profile, extract_mcus from tools.build_api import build_project, build_library from tools.build_api import print_build_memory_usage diff --git a/tools/test_api.py b/tools/test_api.py index e5f915f16fa..302cbbd06f2 100644 --- a/tools/test_api.py +++ b/tools/test_api.py @@ -50,7 +50,7 @@ from tools.utils import construct_enum from tools.memap import MemapParser from tools.targets import TARGET_MAP -from tools.test_configs import TestConfig +import tools.test_configs as TestConfig from tools.test_db import BaseDBAccess from tools.build_api import build_project, build_mbed_libs, build_lib from tools.build_api import get_target_supported_toolchains diff --git a/tools/test_configs/__init__.py b/tools/test_configs/__init__.py index 07e0a170fa0..4242819fa0a 100644 --- a/tools/test_configs/__init__.py +++ b/tools/test_configs/__init__.py @@ -1,34 +1,33 @@ from os.path import dirname, abspath, join from tools.utils import json_file_to_dict -from tools.targets import TARGET_MAP -class TestConfig: - CONFIG_DIR = dirname(abspath(__file__)) - CONFIG_MAP = json_file_to_dict(join(CONFIG_DIR, "config_paths.json")) +CONFIG_DIR = dirname(abspath(__file__)) +CONFIG_MAP = json_file_to_dict(join(CONFIG_DIR, "config_paths.json")) +TARGET_CONFIGS = json_file_to_dict(join(CONFIG_DIR, "target_configs.json")) - @classmethod - def get_valid_configs(cls, target_name): - target = TARGET_MAP[target_name] - config_dict = {} - for attr in cls.CONFIG_MAP: - if attr in target.device_has: - config_dict[attr] = cls.CONFIG_MAP[attr] - return config_dict +def get_valid_configs(target_name): + if target_name in TARGET_CONFIGS: + target_config = TARGET_CONFIGS[target_name] + else: + return {} - @classmethod - def get_config_path(cls, conf_name, target_name): - configs = cls.get_valid_configs(target_name) - if configs and conf_name.upper() in configs: - return join(cls.CONFIG_DIR, configs[conf_name.upper()]) - else: - return None + config_dict = {} + for attr in CONFIG_MAP: + if attr in target_config['test_configurations']: + config_dict[attr] = CONFIG_MAP[attr] + return config_dict - @classmethod - def get_default_config(cls, target_name): - configs = cls.get_valid_configs(target_name) - if configs: - keys = configs.keys() - return join(cls.CONFIG_DIR, configs[keys[0]]) - else: - return None +def get_config_path(conf_name, target_name): + configs = get_valid_configs(target_name) + if configs and conf_name.upper() in configs: + return join(CONFIG_DIR, configs[conf_name.upper()]) + else: + return None + +def get_default_config(target_name): + if target_name in TARGET_CONFIGS: + config_name = TARGET_CONFIGS[target_name]['default_test_configuration'] + return join(CONFIG_DIR, CONFIG_MAP[config_name]) + else: + return None diff --git a/tools/test_configs/target_configs.json b/tools/test_configs/target_configs.json new file mode 100644 index 00000000000..ba615ddb8f7 --- /dev/null +++ b/tools/test_configs/target_configs.json @@ -0,0 +1,10 @@ +{ + "UBLOX_EVK_ODIN_W2": { + "default_test_configuration": "ODIN_WIFI", + "test_configurations": ["ODIN_WIFI", "ETHERNET"] + }, + "K64F": { + "default_test_configuration": "ETHERNET", + "test_configurations": ["ETHERNET"] + } +} From c68b5a6c93218defe304155b3ab3427ad86289db Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Fri, 4 Aug 2017 16:31:55 -0500 Subject: [PATCH 08/13] Remove LWIP tests --- .../TESTS/mbedmicro-net/.mbedignore | 1 - .../TESTS/mbedmicro-net/connectivity/main.cpp | 82 ----- .../mbedmicro-net/gethostbyname/main.cpp | 125 ------- .../mbedmicro-net/host_tests/tcp_echo.py | 195 ---------- .../mbedmicro-net/host_tests/udp_echo.py | 127 ------- .../mbedmicro-net/host_tests/udp_shotgun.py | 142 ------- .../TESTS/mbedmicro-net/tcp_echo/main.cpp | 118 ------ .../mbedmicro-net/tcp_echo_parallel/main.cpp | 160 -------- .../mbedmicro-net/tcp_hello_world/main.cpp | 121 ------ .../tcp_packet_pressure/main.cpp | 258 ------------- .../tcp_packet_pressure_parallel/main.cpp | 320 ---------------- .../mbedmicro-net/udp_dtls_handshake/main.cpp | 165 --------- .../TESTS/mbedmicro-net/udp_echo/main.cpp | 159 -------- .../mbedmicro-net/udp_echo_parallel/main.cpp | 242 ------------ .../udp_packet_pressure/main.cpp | 281 -------------- .../udp_packet_pressure_parallel/main.cpp | 345 ------------------ 16 files changed, 2841 deletions(-) delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/.mbedignore delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo.py delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo.py delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_shotgun.py delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo_parallel/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp delete mode 100644 features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/.mbedignore b/features/FEATURE_LWIP/TESTS/mbedmicro-net/.mbedignore deleted file mode 100644 index 709fc036051..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/.mbedignore +++ /dev/null @@ -1 +0,0 @@ -host_tests/* \ No newline at end of file diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp deleted file mode 100644 index 67119ea20fb..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/connectivity/main.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" - -#include "EthernetInterface.h" - -using namespace utest::v1; - - -// Bringing the network up and down -template -void test_bring_up_down() { - EthernetInterface eth; - - for (int i = 0; i < COUNT; i++) { - int err = eth.connect(); - TEST_ASSERT_EQUAL(0, err); - - printf("MBED: IP Address %s\r\n", eth.get_ip_address()); - printf("MBED: Netmask %s\r\n", eth.get_netmask()); - printf("MBED: Gateway %s\r\n", eth.get_gateway()); - TEST_ASSERT(eth.get_ip_address()); - TEST_ASSERT(eth.get_netmask()); - TEST_ASSERT(eth.get_gateway()); - - UDPSocket udp; - err = udp.open(ð); - TEST_ASSERT_EQUAL(0, err); - err = udp.close(); - TEST_ASSERT_EQUAL(0, err); - - TCPSocket tcp; - err = tcp.open(ð); - TEST_ASSERT_EQUAL(0, err); - err = tcp.close(); - TEST_ASSERT_EQUAL(0, err); - - err = eth.disconnect(); - TEST_ASSERT_EQUAL(0, err); - } -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("Bringing the network up and down", test_bring_up_down<1>), - Case("Bringing the network up and down twice", test_bring_up_down<2>), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp deleted file mode 100644 index b0a5d4eb7b7..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/gethostbyname/main.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include "EthernetInterface.h" - -using namespace utest::v1; - -// Hostname for testing against -// Must have A and AAAA records -#ifndef MBED_DNS_TEST_HOST -#define MBED_DNS_TEST_HOST "connector.mbed.com" -#endif - -// Address info from stack -const char *ip_literal; -nsapi_version_t ip_pref; -const char *ip_pref_repr; - -// Network setup -EthernetInterface net; -void net_bringup() { - int err = net.connect(); - TEST_ASSERT_EQUAL(0, err); - printf("MBED: Connected to network\n"); - printf("MBED: IP Address: %s\n", net.get_ip_address()); - - ip_literal = net.get_ip_address(); - ip_pref = SocketAddress(ip_literal).get_ip_version(); - ip_pref_repr = (ip_pref == NSAPI_IPv4) ? "ipv4" : - (ip_pref == NSAPI_IPv6) ? "ipv6" : "unspec"; -} - - -// DNS tests -void test_dns_query() { - SocketAddress addr; - int err = net.gethostbyname(MBED_DNS_TEST_HOST, &addr); - printf("DNS: query \"%s\" => \"%s\"\n", - MBED_DNS_TEST_HOST, addr.get_ip_address()); - - TEST_ASSERT_EQUAL(0, err); - TEST_ASSERT((bool)addr); - TEST_ASSERT(strlen(addr.get_ip_address()) > 1); -} - -void test_dns_query_pref() { - SocketAddress addr; - int err = net.gethostbyname(MBED_DNS_TEST_HOST, &addr, ip_pref); - printf("DNS: query %s \"%s\" => \"%s\"\n", - ip_pref_repr, MBED_DNS_TEST_HOST, addr.get_ip_address()); - - TEST_ASSERT_EQUAL(0, err); - TEST_ASSERT((bool)addr); - TEST_ASSERT(strlen(addr.get_ip_address()) > 1); - TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); -} - -void test_dns_literal() { - SocketAddress addr; - int err = net.gethostbyname(ip_literal, &addr); - printf("DNS: literal \"%s\" => \"%s\"\n", - ip_literal, addr.get_ip_address()); - - TEST_ASSERT_EQUAL(0, err); - TEST_ASSERT((bool)addr); - TEST_ASSERT(strlen(addr.get_ip_address()) > 1); - TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); -} - -void test_dns_literal_pref() { - SocketAddress addr; - int err = net.gethostbyname(ip_literal, &addr, ip_pref); - printf("DNS: literal %s \"%s\" => \"%s\"\n", - ip_pref_repr, ip_literal, addr.get_ip_address()); - - TEST_ASSERT_EQUAL(0, err); - TEST_ASSERT((bool)addr); - TEST_ASSERT(strlen(addr.get_ip_address()) > 1); - TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); - TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "default_auto"); - net_bringup(); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("DNS query", test_dns_query), - Case("DNS preference query", test_dns_query_pref), - Case("DNS literal", test_dns_literal), - Case("DNS preference literal", test_dns_literal_pref), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo.py b/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo.py deleted file mode 100644 index 8a528dbee90..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo.py +++ /dev/null @@ -1,195 +0,0 @@ -# Copyright 2015 ARM Limited, All rights reserved -# -# 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. - -import sys -import select -import socket -import logging -from threading import Thread -from sys import stdout -from SocketServer import BaseRequestHandler, TCPServer -from mbed_host_tests import BaseHostTest, event_callback - - -class TCPEchoClientHandler(BaseRequestHandler): - def handle(self): - """ - Handles a connection. Test starts by client(i.e. mbed) connecting to server. - This connection handler receives data and echoes back to the client util - {{end}} is received. Then it sits on recv() for client to terminate the - connection. - - Note: reason for not echoing data back after receiving {{end}} is that send - fails raising a SocketError as client closes connection. - """ - while self.server.isrunning(): - try: - data = self.recv() - if not data: break - except Exception as e: - break - - try: - # echo data back to the client - self.send(data) - except Exception as e: - break - - def recv(self): - """ - Try to receive until server is shutdown - """ - while self.server.isrunning(): - rl, wl, xl = select.select([self.request], [], [], 1) - if len(rl): - return self.request.recv(1024) - - def send(self, data): - """ - Try to send until server is shutdown - """ - while self.server.isrunning(): - rl, wl, xl = select.select([], [self.request], [], 1) - if len(wl): - self.request.sendall(data) - break - - -class TCPServerWrapper(TCPServer): - """ - Wrapper over TCP server to implement server initiated shutdown. - Adds a flag:= running that a request handler can check and come out of - recv loop when shutdown is called. - """ - - def __init__(self, addr, request_handler): - # hmm, TCPServer is not sub-classed from object! - if issubclass(TCPServer, object): - super(TCPServerWrapper, self).__init__(addr, request_handler) - else: - TCPServer.__init__(self, addr, request_handler) - self.running = False - - def serve_forever(self): - self.running = True - if issubclass(TCPServer, object): - super(TCPServerWrapper, self).serve_forever() - else: - TCPServer.serve_forever(self) - - def shutdown(self): - self.running = False - if issubclass(TCPServer, object): - super(TCPServerWrapper, self).shutdown() - else: - TCPServer.shutdown(self) - - def isrunning(self): - return self.running - - -class TCPEchoClientTest(BaseHostTest): - - def __init__(self): - """ - Initialise test parameters. - - :return: - """ - BaseHostTest.__init__(self) - self.SERVER_IP = None # Will be determined after knowing the target IP - self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port - self.server = None - self.server_thread = None - self.target_ip = None - - @staticmethod - def find_interface_to_target_addr(target_ip): - """ - Finds IP address of the interface through which it is connected to the target. - - :return: - """ - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - s.connect((target_ip, 0)) # Target IP, any port - except socket.error: - s.connect((target_ip, 8000)) # Target IP, 'random' port - ip = s.getsockname()[0] - s.close() - return ip - - def setup_tcp_server(self): - """ - sets up a TCP server for target to connect and send test data. - - :return: - """ - # !NOTE: There should mechanism to assert in the host test - if self.SERVER_IP is None: - self.log("setup_tcp_server() called before determining server IP!") - self.notify_complete(False) - - # Returning none will suppress host test from printing success code - self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler) - ip, port = self.server.server_address - self.SERVER_PORT = port - self.server.allow_reuse_address = True - self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) - self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,)) - self.server_thread.start() - - @staticmethod - def server_thread_func(this): - """ - Thread function to run TCP server forever. - - :param this: - :return: - """ - this.server.serve_forever() - - @event_callback("target_ip") - def _callback_target_ip(self, key, value, timestamp): - """ - Callback to handle reception of target's IP address. - - :param key: - :param value: - :param timestamp: - :return: - """ - self.target_ip = value - self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) - self.setup_tcp_server() - - @event_callback("host_ip") - def _callback_host_ip(self, key, value, timestamp): - """ - Callback for request for host IP Addr - - """ - self.send_kv("host_ip", self.SERVER_IP) - - @event_callback("host_port") - def _callback_host_port(self, key, value, timestamp): - """ - Callback for request for host port - """ - self.send_kv("host_port", self.SERVER_PORT) - - def teardown(self): - if self.server: - self.server.shutdown() - self.server_thread.join() diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo.py b/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo.py deleted file mode 100644 index e63195ae4ab..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo.py +++ /dev/null @@ -1,127 +0,0 @@ -""" -mbed SDK -Copyright (c) 2011-2013 ARM Limited - -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. -""" - -import sys -import socket -from sys import stdout -from threading import Thread -from SocketServer import BaseRequestHandler, UDPServer -from mbed_host_tests import BaseHostTest, event_callback - - -class UDPEchoClientHandler(BaseRequestHandler): - def handle(self): - """ UDP packet handler. Echoes data back to sender's address. - """ - data, sock = self.request - sock.sendto(data, self.client_address) - - -class UDPEchoClientTest(BaseHostTest): - - def __init__(self): - """ - Initialise test parameters. - - :return: - """ - BaseHostTest.__init__(self) - self.SERVER_IP = None # Will be determined after knowing the target IP - self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port - self.server = None - self.server_thread = None - self.target_ip = None - - @staticmethod - def find_interface_to_target_addr(target_ip): - """ - Finds IP address of the interface through which it is connected to the target. - - :return: - """ - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - s.connect((target_ip, 0)) # Target IP, any port - except socket.error: - s.connect((target_ip, 8000)) # Target IP, 'random' port - ip = s.getsockname()[0] - s.close() - return ip - - def setup_udp_server(self): - """ - sets up a UDP server for target to connect and send test data. - - :return: - """ - # !NOTE: There should mechanism to assert in the host test - if self.SERVER_IP is None: - self.log("setup_udp_server() called before determining server IP!") - self.notify_complete(False) - - # Returning none will suppress host test from printing success code - self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) - ip, port = self.server.server_address - self.SERVER_PORT = port - self.server.allow_reuse_address = True - self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) - self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) - self.server_thread.start() - - @staticmethod - def server_thread_func(this): - """ - Thread function to run TCP server forever. - - :param this: - :return: - """ - this.server.serve_forever() - - @event_callback("target_ip") - def _callback_target_ip(self, key, value, timestamp): - """ - Callback to handle reception of target's IP address. - - :param key: - :param value: - :param timestamp: - :return: - """ - self.target_ip = value - self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) - self.setup_udp_server() - - @event_callback("host_ip") - def _callback_host_ip(self, key, value, timestamp): - """ - Callback for request for host IP Addr - - """ - self.send_kv("host_ip", self.SERVER_IP) - - @event_callback("host_port") - def _callback_host_port(self, key, value, timestamp): - """ - Callback for request for host port - """ - self.send_kv("host_port", self.SERVER_PORT) - - def teardown(self): - if self.server: - self.server.shutdown() - self.server_thread.join() diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_shotgun.py b/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_shotgun.py deleted file mode 100644 index cdf18f963bf..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_shotgun.py +++ /dev/null @@ -1,142 +0,0 @@ -""" -mbed SDK -Copyright (c) 2011-2013 ARM Limited - -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. -""" - -import sys -import socket -import json -import random -import itertools -import time -from sys import stdout -from threading import Thread -from SocketServer import BaseRequestHandler, UDPServer -from mbed_host_tests import BaseHostTest, event_callback - - -class UDPEchoClientHandler(BaseRequestHandler): - def handle(self): - """ UDP packet handler. Responds with multiple simultaneous packets - """ - data, sock = self.request - pattern = [ord(d) << 4 for d in data] - - # Each byte in request indicates size of packet to recieve - # Each packet size is shifted over by 4 to fit in a byte, which - # avoids any issues with endianess or decoding - for packet in pattern: - data = [random.randint(0, 255) for _ in range(packet-1)] - data.append(reduce(lambda a,b: a^b, data)) - data = ''.join(map(chr, data)) - sock.sendto(data, self.client_address) - - # Sleep a tiny bit to compensate for local network - time.sleep(0.01) - - -class UDPEchoClientTest(BaseHostTest): - def __init__(self): - """ - Initialise test parameters. - - :return: - """ - BaseHostTest.__init__(self) - self.SERVER_IP = None # Will be determined after knowing the target IP - self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port - self.server = None - self.server_thread = None - self.target_ip = None - - @staticmethod - def find_interface_to_target_addr(target_ip): - """ - Finds IP address of the interface through which it is connected to the target. - - :return: - """ - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - s.connect((target_ip, 0)) # Target IP, any port - except socket.error: - s.connect((target_ip, 8000)) # Target IP, 'random' port - ip = s.getsockname()[0] - s.close() - return ip - - def setup_udp_server(self): - """ - sets up a UDP server for target to connect and send test data. - - :return: - """ - # !NOTE: There should mechanism to assert in the host test - if self.SERVER_IP is None: - self.log("setup_udp_server() called before determining server IP!") - self.notify_complete(False) - - # Returning none will suppress host test from printing success code - self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) - ip, port = self.server.server_address - self.SERVER_PORT = port - self.server.allow_reuse_address = True - self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) - self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) - self.server_thread.start() - - @staticmethod - def server_thread_func(this): - """ - Thread function to run TCP server forever. - - :param this: - :return: - """ - this.server.serve_forever() - - @event_callback("target_ip") - def _callback_target_ip(self, key, value, timestamp): - """ - Callback to handle reception of target's IP address. - - :param key: - :param value: - :param timestamp: - :return: - """ - self.target_ip = value - self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) - self.setup_udp_server() - - @event_callback("host_ip") - def _callback_host_ip(self, key, value, timestamp): - """ - Callback for request for host IP Addr - - """ - self.send_kv("host_ip", self.SERVER_IP) - - @event_callback("host_port") - def _callback_host_port(self, key, value, timestamp): - """ - Callback for request for host port - """ - self.send_kv("host_port", self.SERVER_PORT) - - def teardown(self): - if self.server: - self.server.shutdown() - self.server_thread.join() diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp deleted file mode 100644 index 6324e6d1043..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "TCPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE -#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256 -#endif - -namespace { - char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; - char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; - const char ASCII_MAX = '~' - ' '; -} - -void prep_buffer(char *tx_buffer, size_t tx_size) { - for (size_t i=0; istart(); - } - - for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { - echoers[i]->join(); - delete echoers[i]; - } - - net.disconnect(); -} - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "tcp_echo"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("TCP echo parallel", test_tcp_echo_parallel), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp deleted file mode 100644 index 73920a8518e..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif - -#include -#include "mbed.h" -#include "EthernetInterface.h" -#include "TCPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -namespace { - // Test connection information - const char *HTTP_SERVER_NAME = "os.mbed.com"; - const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt"; - const int HTTP_SERVER_PORT = 80; -#if defined(TARGET_VK_RZ_A1H) - const int RECV_BUFFER_SIZE = 300; -#else - const int RECV_BUFFER_SIZE = 512; -#endif - // Test related data - const char *HTTP_OK_STR = "200 OK"; - const char *HTTP_HELLO_STR = "Hello world!"; - - // Test buffers - char buffer[RECV_BUFFER_SIZE] = {0}; -} - -bool find_substring(const char *first, const char *last, const char *s_first, const char *s_last) { - const char *f = std::search(first, last, s_first, s_last); - return (f != last); -} - -void test_tcp_hello_world() { - bool result = false; - EthernetInterface eth; - //eth.init(); //Use DHCP - eth.connect(); - printf("TCP client IP Address is %s\r\n", eth.get_ip_address()); - - TCPSocket sock(ð); - printf("HTTP: Connection to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT); - if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) { - printf("HTTP: OK\r\n"); - - // We are constructing GET command like this: - // GET http://developer.mbed.org/media/uploads/mbed_official/hello.txt HTTP/1.0\n\n - strcpy(buffer, "GET http://"); - strcat(buffer, HTTP_SERVER_NAME); - strcat(buffer, HTTP_SERVER_FILE_PATH); - strcat(buffer, " HTTP/1.0\n\n"); - // Send GET command - sock.send(buffer, strlen(buffer)); - - // Server will respond with HTTP GET's success code - const int ret = sock.recv(buffer, sizeof(buffer) - 1); - buffer[ret] = '\0'; - - // Find 200 OK HTTP status in reply - bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR)); - // Find "Hello World!" string in reply - bool found_hello = find_substring(buffer, buffer + ret, HTTP_HELLO_STR, HTTP_HELLO_STR + strlen(HTTP_HELLO_STR)); - - TEST_ASSERT(found_200_ok); - TEST_ASSERT(found_hello); - - if (found_200_ok && found_hello) result = true; - - printf("HTTP: Received %d chars from server\r\n", ret); - printf("HTTP: Received 200 OK status ... %s\r\n", found_200_ok ? "[OK]" : "[FAIL]"); - printf("HTTP: Received '%s' status ... %s\r\n", HTTP_HELLO_STR, found_hello ? "[OK]" : "[FAIL]"); - printf("HTTP: Received message:\r\n"); - printf("%s", buffer); - sock.close(); - } else { - printf("HTTP: ERROR\r\n"); - } - - eth.disconnect(); - TEST_ASSERT(result); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("TCP hello world", test_tcp_hello_world), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp deleted file mode 100644 index ec0731c9c78..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif -#ifndef MBED_EXTENDED_TESTS - #error [NOT_SUPPORTED] Pressure tests are not supported by default -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "TCPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 -#endif - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 -#endif - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 -#endif - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false -#endif - - -// Simple xorshift pseudorandom number generator -class RandSeq { -private: - uint32_t x; - uint32_t y; - static const int A = 15; - static const int B = 18; - static const int C = 11; - -public: - RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) - : x(seed), y(seed) {} - - uint32_t next(void) { - x ^= x << A; - x ^= x >> B; - x ^= y ^ (y >> C); - return x + y; - } - - void skip(size_t size) { - for (size_t i = 0; i < size; i++) { - next(); - } - } - - void buffer(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - buffer[i] = lookahead.next() & 0xff; - } - } - - int cmp(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - int diff = buffer[i] - (lookahead.next() & 0xff); - if (diff != 0) { - return diff; - } - } - return 0; - } -}; - -// Shared buffer for network transactions -uint8_t *buffer; -size_t buffer_size; - -// 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 -// space for the rest of the program -void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { - size_t i = min; - while (i < max) { - void *b = malloc(i); - if (!b) { - i /= 4; - if (i < min) { - i = min; - } - break; - } - free(b); - i *= 2; - } - - *buffer = (uint8_t *)malloc(i); - *size = i; - TEST_ASSERT(buffer); -} - - -void test_tcp_packet_pressure() { - generate_buffer(&buffer, &buffer_size, - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); - printf("MBED: Generated buffer %d\r\n", buffer_size); - - EthernetInterface eth; - int err = eth.connect(); - TEST_ASSERT_EQUAL(0, err); - - printf("MBED: TCPClient IP address is '%s'\n", eth.get_ip_address()); - printf("MBED: TCPClient waiting for server IP and port...\n"); - - greentea_send_kv("target_ip", eth.get_ip_address()); - - char recv_key[] = "host_port"; - char ipbuf[60] = {0}; - char portbuf[16] = {0}; - unsigned int port = 0; - - 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("MBED: Server IP address received: %s:%d \n", ipbuf, port); - - TCPSocket sock; - SocketAddress tcp_addr(ipbuf, port); - - Timer timer; - timer.start(); - - // Tests exponentially growing sequences - for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; - size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; - size *= 2) { - err = sock.open(ð); - TEST_ASSERT_EQUAL(0, err); - err = sock.connect(tcp_addr); - TEST_ASSERT_EQUAL(0, err); - printf("TCP: %s:%d streaming %d bytes\r\n", ipbuf, port, size); - - sock.set_blocking(false); - - // Loop to send/recv all data - RandSeq tx_seq; - RandSeq rx_seq; - size_t rx_count = 0; - size_t tx_count = 0; - size_t window = buffer_size; - - while (tx_count < size || rx_count < size) { - // Send out data - if (tx_count < size) { - size_t chunk_size = size - tx_count; - if (chunk_size > window) { - chunk_size = window; - } - - tx_seq.buffer(buffer, chunk_size); - int td = sock.send(buffer, chunk_size); - - if (td > 0) { - if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { - printf("TCP: tx -> %d\r\n", td); - } - tx_seq.skip(td); - tx_count += td; - } else if (td != NSAPI_ERROR_WOULD_BLOCK) { - // We may fail to send because of buffering issues, - // cut buffer in half - if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { - window /= 2; - } - - if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { - printf("TCP: Not sent (%d), window = %d\r\n", td, window); - } - } - } - - // Verify recieved data - while (rx_count < size) { - int rd = sock.recv(buffer, buffer_size); - TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); - if (rd > 0) { - if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { - printf("TCP: rx <- %d\r\n", rd); - } - int diff = rx_seq.cmp(buffer, rd); - TEST_ASSERT_EQUAL(0, diff); - rx_seq.skip(rd); - rx_count += rd; - } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { - break; - } - } - } - - err = sock.close(); - TEST_ASSERT_EQUAL(0, err); - } - - timer.stop(); - printf("MBED: Time taken: %fs\r\n", timer.read()); - printf("MBED: Speed: %.3fkb/s\r\n", - 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); - - eth.disconnect(); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "tcp_echo"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("TCP packet pressure", test_tcp_packet_pressure), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp deleted file mode 100644 index 847e40ae15d..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure_parallel/main.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif -#ifndef MBED_EXTENDED_TESTS - #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "TCPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 -#endif - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 -#endif - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 -#endif - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 3 -#endif - -#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG -#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false -#endif - - -// Simple xorshift pseudorandom number generator -class RandSeq { -private: - uint32_t x; - uint32_t y; - static const int A = 15; - static const int B = 18; - static const int C = 11; - -public: - RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) - : x(seed), y(seed) {} - - uint32_t next(void) { - x ^= x << A; - x ^= x >> B; - x ^= y ^ (y >> C); - return x + y; - } - - void skip(size_t size) { - for (size_t i = 0; i < size; i++) { - next(); - } - } - - void buffer(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - buffer[i] = lookahead.next() & 0xff; - } - } - - int cmp(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - int diff = buffer[i] - (lookahead.next() & 0xff); - if (diff != 0) { - return diff; - } - } - return 0; - } -}; - - -// 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 -// space for the rest of the program -void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { - size_t i = min; - while (i < max) { - void *b = malloc(i); - if (!b) { - i /= 4; - if (i < min) { - i = min; - } - break; - } - free(b); - i *= 2; - } - - *buffer = (uint8_t *)malloc(i); - *size = i; - TEST_ASSERT(buffer); -} - - -// Global variables shared between pressure tests -EthernetInterface net; -SocketAddress tcp_addr; -Timer timer; -Mutex iomutex; - -// Single instance of a pressure test -class PressureTest { -private: - uint8_t *buffer; - size_t buffer_size; - - TCPSocket sock; - Thread thread; - -public: - PressureTest(uint8_t *buffer, size_t buffer_size) - : buffer(buffer), buffer_size(buffer_size) { - } - - void start() { - osStatus status = thread.start(callback(this, &PressureTest::run)); - TEST_ASSERT_EQUAL(osOK, status); - } - - void join() { - osStatus status = thread.join(); - TEST_ASSERT_EQUAL(osOK, status); - } - - void run() { - // Tests exponentially growing sequences - for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; - size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; - size *= 2) { - int err = sock.open(&net); - TEST_ASSERT_EQUAL(0, err); - err = sock.connect(tcp_addr); - TEST_ASSERT_EQUAL(0, err); - iomutex.lock(); - printf("TCP: %s:%d streaming %d bytes\r\n", - tcp_addr.get_ip_address(), tcp_addr.get_port(), size); - iomutex.unlock(); - - sock.set_blocking(false); - - // Loop to send/recv all data - RandSeq tx_seq; - RandSeq rx_seq; - size_t rx_count = 0; - size_t tx_count = 0; - size_t window = buffer_size; - - while (tx_count < size || rx_count < size) { - // Send out data - if (tx_count < size) { - size_t chunk_size = size - tx_count; - if (chunk_size > window) { - chunk_size = window; - } - - tx_seq.buffer(buffer, chunk_size); - int td = sock.send(buffer, chunk_size); - - if (td > 0) { - if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { - iomutex.lock(); - printf("TCP: tx -> %d\r\n", td); - iomutex.unlock(); - } - tx_seq.skip(td); - tx_count += td; - } else if (td != NSAPI_ERROR_WOULD_BLOCK) { - // We may fail to send because of buffering issues, - // cut buffer in half - if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { - window /= 2; - } - - if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { - iomutex.lock(); - printf("TCP: Not sent (%d), window = %d\r\n", td, window); - iomutex.unlock(); - } - } - } - - // Verify recieved data - while (rx_count < size) { - int rd = sock.recv(buffer, buffer_size); - TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); - if (rd > 0) { - if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { - iomutex.lock(); - printf("TCP: rx <- %d\r\n", rd); - iomutex.unlock(); - } - int diff = rx_seq.cmp(buffer, rd); - TEST_ASSERT_EQUAL(0, diff); - rx_seq.skip(rd); - rx_count += rd; - } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { - break; - } - } - } - - err = sock.close(); - TEST_ASSERT_EQUAL(0, err); - } - } -}; - -PressureTest *pressure_tests[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS]; - - -void test_tcp_packet_pressure_parallel() { - uint8_t *buffer; - size_t buffer_size; - generate_buffer(&buffer, &buffer_size, - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); - - size_t buffer_subsize = buffer_size / MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; - printf("MBED: Generated buffer %d\r\n", buffer_size); - printf("MBED: Split into %d buffers %d\r\n", - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS, - buffer_subsize); - - int err = net.connect(); - TEST_ASSERT_EQUAL(0, err); - - printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); - printf("MBED: TCPClient waiting for server IP and port...\n"); - - greentea_send_kv("target_ip", net.get_ip_address()); - - char recv_key[] = "host_port"; - char ipbuf[60] = {0}; - char portbuf[16] = {0}; - unsigned int port = 0; - - 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("MBED: Server IP address received: %s:%d \n", ipbuf, port); - tcp_addr.set_ip_address(ipbuf); - tcp_addr.set_port(port); - - timer.start(); - - // Startup pressure tests in parallel - for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { - pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); - pressure_tests[i]->start(); - } - - for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { - pressure_tests[i]->join(); - delete pressure_tests[i]; - } - - timer.stop(); - printf("MBED: Time taken: %fs\r\n", timer.read()); - printf("MBED: Speed: %.3fkb/s\r\n", - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS* - 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - - MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); - - net.disconnect(); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "tcp_echo"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("TCP packet pressure parallel", test_tcp_packet_pressure_parallel), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp deleted file mode 100644 index 2563bc2dfae..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_dtls_handshake/main.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "UDPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE -#define MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE 512 -#endif - -#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES -#define MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES 16 -#endif - -#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN -#define MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN 112, 384, 200, 219, 25 -#endif - -#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT -#define MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT 1500 -#endif - -uint8_t buffer[MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE] = {0}; -int udp_dtls_handshake_pattern[] = {MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN}; -const int udp_dtls_handshake_count = sizeof(udp_dtls_handshake_pattern) / sizeof(int); - -void test_udp_dtls_handshake() { - EthernetInterface eth; - int err = eth.connect(); - TEST_ASSERT_EQUAL(0, err); - - printf("MBED: UDPClient IP address is '%s'\n", eth.get_ip_address()); - printf("MBED: UDPClient waiting for server IP and port...\n"); - - greentea_send_kv("target_ip", eth.get_ip_address()); - - bool result = false; - - char recv_key[] = "host_port"; - char ipbuf[60] = {0}; - char portbuf[16] = {0}; - unsigned int port = 0; - - 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("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); - - // align each size to 4-bits - for (int i = 0; i < udp_dtls_handshake_count; i++) { - udp_dtls_handshake_pattern[i] = (~0xf & udp_dtls_handshake_pattern[i]) + 0x10; - } - - printf("MBED: DTLS pattern ["); - for (int i = 0; i < udp_dtls_handshake_count; i++) { - printf("%d", udp_dtls_handshake_pattern[i]); - if (i != udp_dtls_handshake_count-1) { - printf(", "); - } - } - printf("]\r\n"); - - UDPSocket sock; - SocketAddress udp_addr(ipbuf, port); - sock.set_timeout(MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT); - - for (int attempt = 0; attempt < MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES; attempt++) { - err = sock.open(ð); - TEST_ASSERT_EQUAL(0, err); - - for (int i = 0; i < udp_dtls_handshake_count; i++) { - buffer[i] = udp_dtls_handshake_pattern[i] >> 4; - } - - err = sock.sendto(udp_addr, buffer, udp_dtls_handshake_count); - printf("UDP: tx -> %d\r\n", err); - TEST_ASSERT_EQUAL(udp_dtls_handshake_count, err); - - int step = 0; - while (step < udp_dtls_handshake_count) { - err = sock.recvfrom(NULL, buffer, sizeof(buffer)); - printf("UDP: rx <- %d ", err); - - // check length - if (err != udp_dtls_handshake_pattern[step]) { - printf("x (expected %d)\r\n", udp_dtls_handshake_pattern[step]); - break; - } - - // check quick xor of packet - uint8_t check = 0; - for (int j = 0; j < udp_dtls_handshake_pattern[step]; j++) { - check ^= buffer[j]; - } - - if (check != 0) { - printf("x (checksum 0x%02x)\r\n", check); - break; - } - - // successfully got a packet - printf("\r\n"); - step += 1; - } - - err = sock.close(); - TEST_ASSERT_EQUAL(0, err); - - // got through all steps, test passed - if (step == udp_dtls_handshake_count) { - result = true; - break; - } - } - - eth.disconnect(); - TEST_ASSERT(result); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "udp_shotgun"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("UDP DTLS handshake", test_udp_dtls_handshake), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp deleted file mode 100644 index ab07f52f038..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "UDPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE -#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT -#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 -#endif - - -namespace { - char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; - char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; - const char ASCII_MAX = '~' - ' '; - const int ECHO_LOOPS = 16; - char uuid[GREENTEA_UUID_LENGTH] = {0}; -} - -// Creates a buffer that contains the test's UUID in the first part of the contents -// so the output can be associated with individual test runs. The rest of the -// buffer is filled with random data so it is unique within the CURRENT test run. -// -// Ex. A test with UUID of `33e5002c-9722-4685-817a-709cc69c4701` would have a -// buffer filled with something like `33e5002c-9722-4685-817a-709cc69c4701 12594387` -// where `33e5002c-9722-4685-817a-709cc69c4701` is the UUID and `12594387` is the random data -void prep_buffer(char *uuid, char *tx_buffer, size_t tx_size) { - size_t i = 0; - - memcpy(tx_buffer, uuid, strlen(uuid)); - i += strlen(uuid); - - tx_buffer[i++] = ' '; - - for (; i= 0) { - printf("[%02u] sent %d bytes - %.*s \n", i, ret, ret, tx_buffer); - } else { - printf("[%02u] Network error %d\n", i, ret); - continue; - } - - SocketAddress temp_addr; - ret = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); - if (ret >= 0) { - printf("[%02u] recv %d bytes - %.*s \n", i, ret, ret, tx_buffer); - } else { - printf("[%02u] Network error %d\n", i, ret); - continue; - } - - if ((temp_addr == udp_addr && - ret == sizeof(tx_buffer) && - memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { - success += 1; - - printf("[%02u] success #%d\n", i, success); - continue; - } - - // failed, clean out any remaining bad packets - 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); - } - - sock.close(); - eth.disconnect(); - TEST_ASSERT_EQUAL(ECHO_LOOPS, success); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP_UUID(120, "udp_echo", uuid, GREENTEA_UUID_LENGTH); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("UDP echo", test_udp_echo), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp deleted file mode 100644 index 8e8c19ccf11..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_parallel/main.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "UDPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE -#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT -#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_ECHO_THREADS -#define MBED_CFG_UDP_CLIENT_ECHO_THREADS 3 -#endif - - -const int ECHO_LOOPS = 16; -EthernetInterface net; -SocketAddress udp_addr; -Mutex iomutex; -char uuid[GREENTEA_UUID_LENGTH] = {0}; - -// Thread safe printf macro -#define TS_PRINTF(...) {\ - iomutex.lock();\ - printf(__VA_ARGS__);\ - iomutex.unlock();\ -} - -// NOTE: assuming that "id" stays in the single digits -// -// Creates a buffer that first contains the thread's id. -// -// The second part of the buffer contains the test's UUID so the output can be -// associated with individual test runs. -// -// The rest of the buffer is filled with random data so it is unique within the -// CURRENT test run. -// -// Ex. A thread with id "2" and a test with UUID of `33e5002c-9722-4685-817a-709cc69c4701` -// would have a buffer filled with something like `2 33e5002c-9722-4685-817a-709cc69c4701 12594387` -// where `2` is the thread id, `33e5002c-9722-4685-817a-709cc69c4701` is the UUID -// and `12594387` is the random data -void prep_buffer(unsigned int id, char *uuid, char *tx_buffer, size_t tx_size) { - size_t i = 0; - - tx_buffer[i++] = '0' + id; - tx_buffer[i++] = ' '; - - memcpy(tx_buffer+i, uuid, strlen(uuid)); - i += strlen(uuid); - - tx_buffer[i++] = ' '; - - for (; iid = id; - this->uuid = uuid; - osStatus status = thread.start(callback(this, &Echo::echo)); - } - - void join() { - osStatus status = thread.join(); - TEST_ASSERT_EQUAL(osOK, status); - } - - void echo() { - int success = 0; - - int err = sock.open(&net); - TEST_ASSERT_EQUAL(0, err); - - sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); - - for (unsigned int i = 0; success < ECHO_LOOPS; i++) { - prep_buffer(id, uuid, tx_buffer, sizeof(tx_buffer)); - int ret = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer)); - if (ret >= 0) { - TS_PRINTF("[ID:%01u][%02u] sent %d bytes - %.*s \n", id, i, ret, ret, tx_buffer); - } else { - TS_PRINTF("[ID:%01u][%02u] Network error %d\n", id, i, ret); - continue; - } - - SocketAddress temp_addr; - ret = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); - if (ret >= 0) { - TS_PRINTF("[ID:%01u][%02u] recv %d bytes - %.*s \n", id, i, ret, ret, tx_buffer); - } else { - TS_PRINTF("[ID:%01u][%02u] Network error %d\n", id, i, ret); - continue; - } - - if ((temp_addr == udp_addr && - ret == sizeof(tx_buffer) && - memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { - success += 1; - TS_PRINTF("[ID:%01u][%02u] success #%d\n", id, i, success); - continue; - } - - // failed, clean out any remaining bad packets - 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); - } - - result = success == ECHO_LOOPS; - - if (result) { - TS_PRINTF("[ID:%01u] Succeeded all %d times!\n", id, success); - } else { - TS_PRINTF("[ID:%01u] Only succeeded %d times out of a required %d.\n", id, success, ECHO_LOOPS); - } - - err = sock.close(); - if (err) { - TS_PRINTF("[ID:%01u] Failed to close socket!\n", id); - result = false; - } - } - - bool get_result() { - return result; - } -}; - -Echo *echoers[MBED_CFG_UDP_CLIENT_ECHO_THREADS]; - -void test_udp_echo_parallel() { - int err = net.connect(); - TEST_ASSERT_EQUAL(0, err); - - printf("UDP client IP Address is %s\n", net.get_ip_address()); - - greentea_send_kv("target_ip", net.get_ip_address()); - - char recv_key[] = "host_port"; - char ipbuf[60] = {0}; - char portbuf[16] = {0}; - unsigned int port = 0; - - 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("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); - udp_addr.set_ip_address(ipbuf); - udp_addr.set_port(port); - - // Startup echo threads in parallel - for (unsigned int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { - echoers[i] = new Echo; - echoers[i]->start(i, uuid); - } - - bool result = true; - - for (unsigned int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { - echoers[i]->join(); - result = result && echoers[i]->get_result(); - delete echoers[i]; - } - - net.disconnect(); - TEST_ASSERT(result); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP_UUID(120, "udp_echo", uuid, GREENTEA_UUID_LENGTH); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("UDP echo parallel", test_udp_echo_parallel), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp deleted file mode 100644 index 3faa23b4669..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif -#ifndef MBED_EXTENDED_TESTS - #error [NOT_SUPPORTED] Pressure tests are not supported by default -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "UDPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false -#endif - - -// Simple xorshift pseudorandom number generator -class RandSeq { -private: - uint32_t x; - uint32_t y; - static const int A = 15; - static const int B = 18; - static const int C = 11; - -public: - RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) - : x(seed), y(seed) {} - - uint32_t next(void) { - x ^= x << A; - x ^= x >> B; - x ^= y ^ (y >> C); - return x + y; - } - - void skip(size_t size) { - for (size_t i = 0; i < size; i++) { - next(); - } - } - - void buffer(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - buffer[i] = lookahead.next() & 0xff; - } - } - - int cmp(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - int diff = buffer[i] - (lookahead.next() & 0xff); - if (diff != 0) { - return diff; - } - } - return 0; - } -}; - -// Shared buffer for network transactions -uint8_t *buffer; -size_t buffer_size; - -// 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 -// space for the rest of the program -void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { - size_t i = min; - while (i < max) { - void *b = malloc(i); - if (!b) { - i /= 4; - if (i < min) { - i = min; - } - break; - } - free(b); - i *= 2; - } - - *buffer = (uint8_t *)malloc(i); - *size = i; - TEST_ASSERT(buffer); -} - -void test_udp_packet_pressure() { - generate_buffer(&buffer, &buffer_size, - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); - printf("MBED: Generated buffer %d\r\n", buffer_size); - - EthernetInterface eth; - int err = eth.connect(); - TEST_ASSERT_EQUAL(0, err); - - printf("MBED: UDPClient IP address is '%s'\n", eth.get_ip_address()); - printf("MBED: UDPClient waiting for server IP and port...\n"); - - greentea_send_kv("target_ip", eth.get_ip_address()); - - char recv_key[] = "host_port"; - char ipbuf[60] = {0}; - char portbuf[16] = {0}; - unsigned int port = 0; - - 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("MBED: Server IP address received: %s:%d \n", ipbuf, port); - - UDPSocket sock; - SocketAddress udp_addr(ipbuf, port); - - Timer timer; - timer.start(); - - // Tests exponentially growing sequences - for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; - size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; - size *= 2) { - err = sock.open(ð); - TEST_ASSERT_EQUAL(0, err); - printf("UDP: %s:%d streaming %d bytes\r\n", ipbuf, port, size); - - sock.set_blocking(false); - - // Loop to send/recv all data - RandSeq tx_seq; - RandSeq rx_seq; - size_t rx_count = 0; - size_t tx_count = 0; - int known_time = timer.read_ms(); - size_t window = buffer_size; - - while (tx_count < size || rx_count < size) { - // Send out packets - if (tx_count < size) { - size_t chunk_size = size - tx_count; - if (chunk_size > window) { - chunk_size = window; - } - - tx_seq.buffer(buffer, chunk_size); - int td = sock.sendto(udp_addr, buffer, chunk_size); - - if (td > 0) { - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - printf("UDP: tx -> %d\r\n", td); - } - tx_seq.skip(td); - tx_count += td; - } else if (td != NSAPI_ERROR_WOULD_BLOCK) { - // We may fail to send because of buffering issues, revert to - // last good sequence and cut buffer in half - if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { - window /= 2; - } - - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - printf("UDP: Not sent (%d), window = %d\r\n", td, window); - } - } - } - - // Prioritize recieving over sending packets to avoid flooding - // the network while handling erronous packets - while (rx_count < size) { - int rd = sock.recvfrom(NULL, buffer, buffer_size); - TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); - - if (rd > 0) { - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - printf("UDP: rx <- %d\r\n", rd); - } - - if (rx_seq.cmp(buffer, rd) == 0) { - rx_seq.skip(rd); - rx_count += rd; - known_time = timer.read_ms(); - if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { - window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; - } - } - } else if (timer.read_ms() - known_time > - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { - // Dropped packet or out of order, revert to last good sequence - // and cut buffer in half - tx_seq = rx_seq; - tx_count = rx_count; - known_time = timer.read_ms(); - if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { - window /= 2; - } - - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - printf("UDP: Dropped, window = %d\r\n", window); - } - } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { - break; - } - } - } - - err = sock.close(); - TEST_ASSERT_EQUAL(0, err); - } - - timer.stop(); - printf("MBED: Time taken: %fs\r\n", timer.read()); - printf("MBED: Speed: %.3fkb/s\r\n", - 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); - - eth.disconnect(); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "udp_echo"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("UDP packet pressure", test_udp_packet_pressure), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp deleted file mode 100644 index acb543b4bb3..00000000000 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure_parallel/main.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * 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. - */ -#if !FEATURE_LWIP - #error [NOT_SUPPORTED] LWIP not supported for this target -#endif -#if DEVICE_EMAC - #error [NOT_SUPPORTED] Not supported for WiFi targets -#endif -#ifndef MBED_EXTENDED_TESTS - #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default -#endif - -#include "mbed.h" -#include "EthernetInterface.h" -#include "UDPSocket.h" -#include "greentea-client/test_env.h" -#include "unity/unity.h" -#include "utest.h" - -using namespace utest::v1; - - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS 3 -#endif - -#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG -#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false -#endif - - -// Simple xorshift pseudorandom number generator -class RandSeq { -private: - uint32_t x; - uint32_t y; - static const int A = 15; - static const int B = 18; - static const int C = 11; - -public: - RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) - : x(seed), y(seed) {} - - uint32_t next(void) { - x ^= x << A; - x ^= x >> B; - x ^= y ^ (y >> C); - return x + y; - } - - void skip(size_t size) { - for (size_t i = 0; i < size; i++) { - next(); - } - } - - void buffer(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - buffer[i] = lookahead.next() & 0xff; - } - } - - int cmp(uint8_t *buffer, size_t size) { - RandSeq lookahead = *this; - - for (size_t i = 0; i < size; i++) { - int diff = buffer[i] - (lookahead.next() & 0xff); - if (diff != 0) { - return diff; - } - } - return 0; - } -}; - -// 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 -// space for the rest of the program -void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { - size_t i = min; - while (i < max) { - void *b = malloc(i); - if (!b) { - i /= 8; - if (i < min) { - i = min; - } - break; - } - free(b); - i *= 2; - } - - *buffer = (uint8_t *)malloc(i); - *size = i; - TEST_ASSERT(buffer); -} - - -// Global variables shared between pressure tests -EthernetInterface net; -SocketAddress udp_addr; -Timer timer; -Mutex iomutex; - -// Single instance of a pressure test -class PressureTest { -private: - uint8_t *buffer; - size_t buffer_size; - - UDPSocket sock; - Thread thread; - -public: - PressureTest(uint8_t *buffer, size_t buffer_size) - : buffer(buffer), buffer_size(buffer_size) { - } - - void start() { - osStatus status = thread.start(callback(this, &PressureTest::run)); - TEST_ASSERT_EQUAL(osOK, status); - } - - void join() { - osStatus status = thread.join(); - TEST_ASSERT_EQUAL(osOK, status); - } - - void run() { - // Tests exponentially growing sequences - for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; - size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; - size *= 2) { - int err = sock.open(&net); - TEST_ASSERT_EQUAL(0, err); - iomutex.lock(); - printf("UDP: %s:%d streaming %d bytes\r\n", - udp_addr.get_ip_address(), udp_addr.get_port(), size); - iomutex.unlock(); - - sock.set_blocking(false); - - // Loop to send/recv all data - RandSeq tx_seq; - RandSeq rx_seq; - size_t rx_count = 0; - size_t tx_count = 0; - int known_time = timer.read_ms(); - size_t window = buffer_size; - - while (tx_count < size || rx_count < size) { - // Send out packets - if (tx_count < size) { - size_t chunk_size = size - tx_count; - if (chunk_size > window) { - chunk_size = window; - } - - tx_seq.buffer(buffer, chunk_size); - int td = sock.sendto(udp_addr, buffer, chunk_size); - - if (td > 0) { - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - iomutex.lock(); - printf("UDP: tx -> %d\r\n", td); - iomutex.unlock(); - } - tx_seq.skip(td); - tx_count += td; - } else if (td != NSAPI_ERROR_WOULD_BLOCK) { - // We may fail to send because of buffering issues, revert to - // last good sequence and cut buffer in half - if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { - window /= 2; - } - - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - iomutex.lock(); - printf("UDP: Not sent (%d), window = %d\r\n", td, window); - iomutex.unlock(); - } - } - } - - // Prioritize recieving over sending packets to avoid flooding - // the network while handling erronous packets - while (rx_count < size) { - int rd = sock.recvfrom(NULL, buffer, buffer_size); - TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); - - if (rd > 0) { - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - iomutex.lock(); - printf("UDP: rx <- %d\r\n", rd); - iomutex.unlock(); - } - - if (rx_seq.cmp(buffer, rd) == 0) { - rx_seq.skip(rd); - rx_count += rd; - known_time = timer.read_ms(); - if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { - window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; - } - } - } else if (timer.read_ms() - known_time > - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { - // Dropped packet or out of order, revert to last good sequence - // and cut buffer in half - tx_seq = rx_seq; - tx_count = rx_count; - known_time = timer.read_ms(); - if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { - window /= 2; - } - - if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { - iomutex.lock(); - printf("UDP: Dropped, window = %d\r\n", window); - iomutex.unlock(); - } - } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { - break; - } - } - } - - err = sock.close(); - TEST_ASSERT_EQUAL(0, err); - } - } -}; - -PressureTest *pressure_tests[MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS]; - - -void test_udp_packet_pressure_parallel() { - uint8_t *buffer; - size_t buffer_size; - generate_buffer(&buffer, &buffer_size, - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); - - size_t buffer_subsize = buffer_size / MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; - printf("MBED: Generated buffer %d\r\n", buffer_size); - printf("MBED: Split into %d buffers %d\r\n", - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS, - buffer_subsize); - - int err = net.connect(); - TEST_ASSERT_EQUAL(0, err); - - printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address()); - printf("MBED: UDPClient waiting for server IP and port...\n"); - - greentea_send_kv("target_ip", net.get_ip_address()); - - char recv_key[] = "host_port"; - char ipbuf[60] = {0}; - char portbuf[16] = {0}; - unsigned int port = 0; - - 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("MBED: Server IP address received: %s:%d \n", ipbuf, port); - udp_addr.set_ip_address(ipbuf); - udp_addr.set_port(port); - - timer.start(); - - // Startup pressure tests in parallel - for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { - pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); - pressure_tests[i]->start(); - } - - for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { - pressure_tests[i]->join(); - delete pressure_tests[i]; - } - - timer.stop(); - printf("MBED: Time taken: %fs\r\n", timer.read()); - printf("MBED: Speed: %.3fkb/s\r\n", - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS* - 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - - MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); - - net.disconnect(); -} - - -// Test setup -utest::v1::status_t test_setup(const size_t number_of_cases) { - GREENTEA_SETUP(120, "udp_echo"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("UDP packet pressure parallel", test_udp_packet_pressure_parallel), -}; - -Specification specification(test_setup, cases); - -int main() { - return !Harness::run(specification); -} From 6a44ceb094fa35512a314b44b7d7ed7fa9959a92 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Mon, 7 Aug 2017 13:13:03 -0500 Subject: [PATCH 09/13] Add copyright headers and use mbed error to skip tests without network config files --- TESTS/netsocket/connectivity/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/gethostbyname/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/ip_parsing/main.cpp | 20 +++++++++++------- TESTS/netsocket/socket_sigio/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/tcp_echo/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/tcp_echo_parallel/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/tcp_hello_world/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/tcp_packet_pressure/main.cpp | 21 +++++++++++++++++++ .../tcp_packet_pressure_parallel/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/udp_dtls_handshake/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/udp_echo/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/udp_echo_parallel/main.cpp | 21 +++++++++++++++++++ TESTS/netsocket/udp_packet_pressure/main.cpp | 21 +++++++++++++++++++ .../udp_packet_pressure_parallel/main.cpp | 21 +++++++++++++++++++ tools/test.py | 8 ++----- tools/test_api.py | 13 +++--------- 16 files changed, 291 insertions(+), 23 deletions(-) diff --git a/TESTS/netsocket/connectivity/main.cpp b/TESTS/netsocket/connectivity/main.cpp index 045aab40de5..3330d2bbc37 100644 --- a/TESTS/netsocket/connectivity/main.cpp +++ b/TESTS/netsocket/connectivity/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 + #include "mbed.h" #include "greentea-client/test_env.h" #include "unity.h" diff --git a/TESTS/netsocket/gethostbyname/main.cpp b/TESTS/netsocket/gethostbyname/main.cpp index 9f54727f2c3..23eabc9be33 100644 --- a/TESTS/netsocket/gethostbyname/main.cpp +++ b/TESTS/netsocket/gethostbyname/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 + #include "mbed.h" #include "greentea-client/test_env.h" #include "unity.h" diff --git a/TESTS/netsocket/ip_parsing/main.cpp b/TESTS/netsocket/ip_parsing/main.cpp index 6d00816256f..1ffe8058987 100644 --- a/TESTS/netsocket/ip_parsing/main.cpp +++ b/TESTS/netsocket/ip_parsing/main.cpp @@ -1,18 +1,24 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited +/* + * Copyright (c) 2013-2017, 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. + * 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 + * 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. + * 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 + #include "mbed.h" #include "greentea-client/test_env.h" #include "unity.h" diff --git a/TESTS/netsocket/socket_sigio/main.cpp b/TESTS/netsocket/socket_sigio/main.cpp index 0997b7db319..23f83dc59a9 100644 --- a/TESTS/netsocket/socket_sigio/main.cpp +++ b/TESTS/netsocket/socket_sigio/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 + #include #include "mbed.h" #include MBED_CONF_APP_HEADER_FILE diff --git a/TESTS/netsocket/tcp_echo/main.cpp b/TESTS/netsocket/tcp_echo/main.cpp index 1210776314a..90124a28711 100644 --- a/TESTS/netsocket/tcp_echo/main.cpp +++ b/TESTS/netsocket/tcp_echo/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 + #include "mbed.h" #include MBED_CONF_APP_HEADER_FILE #include "TCPSocket.h" diff --git a/TESTS/netsocket/tcp_echo_parallel/main.cpp b/TESTS/netsocket/tcp_echo_parallel/main.cpp index ef3971a0071..c5b6ca0b63b 100644 --- a/TESTS/netsocket/tcp_echo_parallel/main.cpp +++ b/TESTS/netsocket/tcp_echo_parallel/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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] Parallel tests are not supported by default #endif diff --git a/TESTS/netsocket/tcp_hello_world/main.cpp b/TESTS/netsocket/tcp_hello_world/main.cpp index 555638c16d6..e4b440dedf1 100644 --- a/TESTS/netsocket/tcp_hello_world/main.cpp +++ b/TESTS/netsocket/tcp_hello_world/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 + #include #include "mbed.h" #include MBED_CONF_APP_HEADER_FILE diff --git a/TESTS/netsocket/tcp_packet_pressure/main.cpp b/TESTS/netsocket/tcp_packet_pressure/main.cpp index f14ed5dc018..48980bcf68c 100644 --- a/TESTS/netsocket/tcp_packet_pressure/main.cpp +++ b/TESTS/netsocket/tcp_packet_pressure/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 diff --git a/TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp b/TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp index 2c6e97124cf..2c438a92d6f 100644 --- a/TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp +++ b/TESTS/netsocket/tcp_packet_pressure_parallel/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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] Parallel pressure tests are not supported by default #endif diff --git a/TESTS/netsocket/udp_dtls_handshake/main.cpp b/TESTS/netsocket/udp_dtls_handshake/main.cpp index d20138f39e5..b36191fa3fd 100644 --- a/TESTS/netsocket/udp_dtls_handshake/main.cpp +++ b/TESTS/netsocket/udp_dtls_handshake/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 + #include "mbed.h" #include MBED_CONF_APP_HEADER_FILE #include "UDPSocket.h" diff --git a/TESTS/netsocket/udp_echo/main.cpp b/TESTS/netsocket/udp_echo/main.cpp index f5b65830e85..a5ab9bef4df 100644 --- a/TESTS/netsocket/udp_echo/main.cpp +++ b/TESTS/netsocket/udp_echo/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 + #include "mbed.h" #include MBED_CONF_APP_HEADER_FILE #include "UDPSocket.h" diff --git a/TESTS/netsocket/udp_echo_parallel/main.cpp b/TESTS/netsocket/udp_echo_parallel/main.cpp index 589fc76a135..2a47f5b9658 100644 --- a/TESTS/netsocket/udp_echo_parallel/main.cpp +++ b/TESTS/netsocket/udp_echo_parallel/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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] Parallel tests are not supported by default #endif diff --git a/TESTS/netsocket/udp_packet_pressure/main.cpp b/TESTS/netsocket/udp_packet_pressure/main.cpp index a5eee249541..f3c72b959da 100644 --- a/TESTS/netsocket/udp_packet_pressure/main.cpp +++ b/TESTS/netsocket/udp_packet_pressure/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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 diff --git a/TESTS/netsocket/udp_packet_pressure_parallel/main.cpp b/TESTS/netsocket/udp_packet_pressure_parallel/main.cpp index 24ae50af204..e26b8d53fee 100644 --- a/TESTS/netsocket/udp_packet_pressure_parallel/main.cpp +++ b/TESTS/netsocket/udp_packet_pressure_parallel/main.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (c) 2013-2017, 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] Parallel pressure tests are not supported by default #endif diff --git a/tools/test.py b/tools/test.py index 48b7a92349a..7b4f631b3f2 100644 --- a/tools/test.py +++ b/tools/test.py @@ -137,13 +137,10 @@ "Currently set search path: %s" % (toolchain, search_path)) - # boolean, true if test configuration file is for module false if mbed-os interface - module_conf = False - # Assign config file. Precedence: test_config>app_config # TODO: merge configs if both given if options.test_config: - config, module_conf = get_test_config(options.test_config, mcu) + config = get_test_config(options.test_config, mcu) if not config: args_error(parser, "argument --test-config contains invalid path or identifier") elif not options.app_config: @@ -154,8 +151,7 @@ # Find all tests in the relevant paths for path in all_paths: all_tests.update(find_tests(path, mcu, toolchain, - app_config=config, - module_config=module_conf)) + app_config=config)) # Filter tests by name if specified if options.names: diff --git a/tools/test_api.py b/tools/test_api.py index 302cbbd06f2..7bebb8da755 100644 --- a/tools/test_api.py +++ b/tools/test_api.py @@ -2009,11 +2009,11 @@ def get_test_config(config_name, target_name): # If they passed in a full path if exists(config_name): # This is a module config - return config_name, True + return config_name # Otherwise find the path to configuration file based on mbed OS interface - return TestConfig.get_config_path(config_name, target_name), False + return TestConfig.get_config_path(config_name, target_name) -def find_tests(base_dir, target_name, toolchain_name, app_config=None, module_config=None): +def find_tests(base_dir, target_name, toolchain_name, app_config=None): """ Finds all tests in a directory recursively base_dir: path to the directory to scan for tests (ex. 'path/to/project') target_name: name of the target to use for scanning (ex. 'K64F') @@ -2024,8 +2024,6 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None, module_co tests = {} - configs = TestConfig.get_valid_configs(target_name) - # Prepare the toolchain toolchain = prepare_toolchain([base_dir], None, target_name, toolchain_name, silent=True, app_config=app_config) @@ -2053,11 +2051,6 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None, module_co test_group_directory_path, test_case_directory = os.path.split(d) test_group_directory = os.path.basename(test_group_directory_path) - # If the target has no network interface configuration, netsocket tests fail to compile - if not module_config and not configs and \ - (test_case_directory == 'netsocket' or test_group_directory == 'netsocket'): - continue - # Check to make sure discoverd folder is not in a host test directory if test_case_directory != 'host_tests' and test_group_directory != 'host_tests': test_name = test_path_to_name(d, base_dir) From 26aa4eaa6a93df383f8ff77431e61b8696905edf Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Wed, 16 Aug 2017 10:14:23 -0500 Subject: [PATCH 10/13] Use ethernet as default test configuration for Odin netsocket tests --- tools/test_configs/target_configs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/test_configs/target_configs.json b/tools/test_configs/target_configs.json index ba615ddb8f7..8c16695e194 100644 --- a/tools/test_configs/target_configs.json +++ b/tools/test_configs/target_configs.json @@ -1,6 +1,6 @@ { "UBLOX_EVK_ODIN_W2": { - "default_test_configuration": "ODIN_WIFI", + "default_test_configuration": "ETHERNET", "test_configurations": ["ODIN_WIFI", "ETHERNET"] }, "K64F": { From 8ef849da796d8f2701eab7dd18b4bd465579e4c3 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Thu, 24 Aug 2017 17:30:30 -0500 Subject: [PATCH 11/13] Add new Odin configuraiton to remove emac device_has --- .../test_configs/Odin_EthernetInterface.json | 32 +++++++++++++++++++ tools/test_configs/config_paths.json | 3 +- tools/test_configs/target_configs.json | 4 +-- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 tools/test_configs/Odin_EthernetInterface.json diff --git a/tools/test_configs/Odin_EthernetInterface.json b/tools/test_configs/Odin_EthernetInterface.json new file mode 100644 index 00000000000..24f48e212ca --- /dev/null +++ b/tools/test_configs/Odin_EthernetInterface.json @@ -0,0 +1,32 @@ +{ + "config": { + "header-file": { + "help" : "String for including your driver header file", + "value" : "\"EthernetInterface.h\"" + }, + "object-construction" : { + "value" : "new EthernetInterface()" + }, + "connect-statement" : { + "help" : "Must use 'net' variable name", + "value" : "((EthernetInterface *)net)->connect()" + }, + "echo-server-addr" : { + "help" : "IP address of echo server", + "value" : "\"195.34.89.241\"" + }, + "echo-server-port" : { + "help" : "Port of echo server", + "value" : "7" + }, + "tcp-echo-prefix" : { + "help" : "Some servers send a prefix before echoed message", + "value" : "\"u-blox AG TCP/UDP test service\\n\"" + } + }, + "target_overrides": { + "UBLOX_EVK_ODIN_W2": { + "target.device_has_remove": ["EMAC"] + } + } +} diff --git a/tools/test_configs/config_paths.json b/tools/test_configs/config_paths.json index e75864e08da..c543176906c 100644 --- a/tools/test_configs/config_paths.json +++ b/tools/test_configs/config_paths.json @@ -1,4 +1,5 @@ { "ETHERNET" : "EthernetInterface.json", - "ODIN_WIFI" : "OdinInterface.json" + "ODIN_WIFI" : "OdinInterface.json", + "ODIN_ETHERNET" : "Odin_EthernetInterface.json" } diff --git a/tools/test_configs/target_configs.json b/tools/test_configs/target_configs.json index 8c16695e194..1bc54602919 100644 --- a/tools/test_configs/target_configs.json +++ b/tools/test_configs/target_configs.json @@ -1,7 +1,7 @@ { "UBLOX_EVK_ODIN_W2": { - "default_test_configuration": "ETHERNET", - "test_configurations": ["ODIN_WIFI", "ETHERNET"] + "default_test_configuration": "ODIN_ETHERNET", + "test_configurations": ["ODIN_WIFI", "ODIN_ETHERNET"] }, "K64F": { "default_test_configuration": "ETHERNET", From 92a642bc5ea656e3c2d86b457c720da9d2566506 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Tue, 5 Sep 2017 12:22:25 -0500 Subject: [PATCH 12/13] Turn off Odin testing by default --- tools/test_configs/__init__.py | 2 ++ tools/test_configs/target_configs.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/test_configs/__init__.py b/tools/test_configs/__init__.py index 4242819fa0a..85ea5c92aee 100644 --- a/tools/test_configs/__init__.py +++ b/tools/test_configs/__init__.py @@ -28,6 +28,8 @@ def get_config_path(conf_name, target_name): def get_default_config(target_name): if target_name in TARGET_CONFIGS: config_name = TARGET_CONFIGS[target_name]['default_test_configuration'] + if config_name == "NONE": + return None return join(CONFIG_DIR, CONFIG_MAP[config_name]) else: return None diff --git a/tools/test_configs/target_configs.json b/tools/test_configs/target_configs.json index 1bc54602919..eaff8b55b99 100644 --- a/tools/test_configs/target_configs.json +++ b/tools/test_configs/target_configs.json @@ -1,6 +1,6 @@ { "UBLOX_EVK_ODIN_W2": { - "default_test_configuration": "ODIN_ETHERNET", + "default_test_configuration": "NONE", "test_configurations": ["ODIN_WIFI", "ODIN_ETHERNET"] }, "K64F": { From fbe8dfae19d16ea6917f4ec2ce5657d7fcda4e43 Mon Sep 17 00:00:00 2001 From: Sarah Marsh Date: Wed, 20 Sep 2017 18:26:52 -0500 Subject: [PATCH 13/13] update domain name to os.mbed.com --- TESTS/netsocket/socket_sigio/main.cpp | 2 +- TESTS/netsocket/tcp_hello_world/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TESTS/netsocket/socket_sigio/main.cpp b/TESTS/netsocket/socket_sigio/main.cpp index 23f83dc59a9..dcce008a448 100644 --- a/TESTS/netsocket/socket_sigio/main.cpp +++ b/TESTS/netsocket/socket_sigio/main.cpp @@ -32,7 +32,7 @@ using namespace utest::v1; namespace { // Test connection information - const char *HTTP_SERVER_NAME = "developer.mbed.org"; + const char *HTTP_SERVER_NAME = "os.mbed.com"; const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt"; const int HTTP_SERVER_PORT = 80; #if defined(TARGET_VK_RZ_A1H) diff --git a/TESTS/netsocket/tcp_hello_world/main.cpp b/TESTS/netsocket/tcp_hello_world/main.cpp index e4b440dedf1..9e42e21c046 100644 --- a/TESTS/netsocket/tcp_hello_world/main.cpp +++ b/TESTS/netsocket/tcp_hello_world/main.cpp @@ -32,7 +32,7 @@ using namespace utest::v1; namespace { // Test connection information - const char *HTTP_SERVER_NAME = "developer.mbed.org"; + const char *HTTP_SERVER_NAME = "os.mbed.com"; const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt"; const int HTTP_SERVER_PORT = 80; #if defined(TARGET_VK_RZ_A1H)