From 634b00adaf62535b09d1a09372124c5580669845 Mon Sep 17 00:00:00 2001 From: Mohammad Azim Khan Date: Sun, 21 Feb 2016 02:55:44 +0000 Subject: [PATCH 1/6] Ported tcp echo client test to use new greentea key value protocol --- module.json | 4 +- test/echo-tcp-client/main.cpp | 145 ++++++++++++++++-------- test/host_tests/tcpecho_client_auto.py | 149 +++++++++++++++++++++++++ 3 files changed, 253 insertions(+), 45 deletions(-) create mode 100644 test/host_tests/tcpecho_client_auto.py diff --git a/module.json b/module.json index 5cd39a3..ce25a55 100644 --- a/module.json +++ b/module.json @@ -21,7 +21,9 @@ "minar": "^1.0.0" }, "testDependencies": { - "mbed-drivers": "~0.11.1" + "mbed-drivers": "~0.11.1", + "unity": "^2.0.1", + "greentea-client": "^0.1.3" }, "scripts": { "testReporter": [ diff --git a/test/echo-tcp-client/main.cpp b/test/echo-tcp-client/main.cpp index ea13b6e..97f144e 100644 --- a/test/echo-tcp-client/main.cpp +++ b/test/echo-tcp-client/main.cpp @@ -15,13 +15,17 @@ * limitations under the License. */ #include "mbed-drivers/mbed.h" -#include "mbed-drivers/test_env.h" #include "sockets/TCPStream.h" #include "sal/test/ctest_env.h" #include "sal-stack-lwip/lwipv4_init.h" #include "sal-iface-eth/EthernetInterface.h" #include "minar/minar.h" #include "core-util/FunctionPointer.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" + +using namespace utest::v1; struct s_ip_address { int ip_1; @@ -41,6 +45,7 @@ void terminate(bool status, TCPEchoClient* client); char out_buffer[] = "Hello World\n"; char buffer[256]; +char out_success[] = "{{success}}\n{{end}}\n"; TCPEchoClient *client; int port; @@ -51,20 +56,31 @@ class TCPEchoClient { { _stream.setOnError(TCPStream::ErrorHandler_t(this, &TCPEchoClient::onError)); } + ~TCPEchoClient(){ + if (_stream.isConnected()) + _stream.close(); + } void onError(Socket *s, socket_error_t err) { (void) s; printf("MBED: Socket Error: %s (%d)\r\n", socket_strerror(err), err); _done = true; - minar::Scheduler::postCallback(fpterminate_t(terminate).bind(TEST_RESULT(),this)); + minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); } void start_test(char * host_addr, uint16_t port) { + printf("Trying to resolve address %s" NL, host_addr); _port = port; _done = false; _disconnected = true; - socket_error_t err = _stream.resolve(host_addr,TCPStream::DNSHandler_t(this, &TCPEchoClient::onDNS)); + socket_error_t err = _stream.open(SOCKET_AF_INET4); + if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { + printf("MBED: TCPClient unable to open socket" NL); + onError(&_stream, err); + } + + err = _stream.resolve(host_addr,TCPStream::DNSHandler_t(this, &TCPEchoClient::onDNS)); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: TCPClient unable to connect to %s:%d" NL, buffer, port); + printf("MBED: TCPClient unable to connect to %s:%d" NL, host_addr, port); onError(&_stream, err); } } @@ -76,14 +92,12 @@ class TCPEchoClient { /* Open the socket */ _resolvedAddr.fmtIPv6(buffer, sizeof(buffer)); printf("MBED: Resolved %s to %s\r\n", domain, buffer); - socket_error_t err = _stream.open(SOCKET_AF_INET4); - TEST_EQ(err, SOCKET_ERROR_NONE); /* Register the read handler */ _stream.setOnReadable(TCPStream::ReadableHandler_t(this, &TCPEchoClient::onRx)); _stream.setOnSent(TCPStream::SentHandler_t(this, &TCPEchoClient::onSent)); _stream.setOnDisconnect(TCPStream::DisconnectHandler_t(this, &TCPEchoClient::onDisconnect)); /* Send the query packet to the remote host */ - err = _stream.connect(_resolvedAddr, _port, TCPStream::ConnectHandler_t(this,&TCPEchoClient::onConnect)); + socket_error_t err = _stream.connect(_resolvedAddr, _port, TCPStream::ConnectHandler_t(this,&TCPEchoClient::onConnect)); if(!TEST_EQ(err, SOCKET_ERROR_NONE)) { printf("MBED: Expected %d, got %d (%s)\r\n", SOCKET_ERROR_NONE, err, socket_strerror(err)); onError(&_stream, err); @@ -93,10 +107,14 @@ class TCPEchoClient { { (void) s; _disconnected = false; - _unacked += sizeof(out_buffer) - 1; + _unacked = sizeof(out_buffer) - 1; + printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_buffer); socket_error_t err = _stream.send(out_buffer, sizeof(out_buffer) - 1); - TEST_EQ(err, SOCKET_ERROR_NONE); + if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { + printf("MBED: TCPClient unable to send data!" NL); + onError(&_stream, err); + } } void onRx(Socket* s) { @@ -105,36 +123,33 @@ class TCPEchoClient { socket_error_t err = _stream.recv(buffer, &n); TEST_EQ(err, SOCKET_ERROR_NONE); buffer[n] = 0; - char out_success[] = "{{success}}\n{{end}}\n"; - char out_failure[] = "{{failure}}\n{{end}}\n"; - int rc; - if (n > 0) + printf ("MBED: Rx (%d bytes) from host: %s" NL, n, buffer); + if (!_done && n > 0) { - buffer[n] = '\0'; - printf("%s\r\n", buffer); - rc = strncmp(out_buffer, buffer, sizeof(out_buffer) - 1); + int rc = strncmp(out_buffer, buffer, sizeof(out_buffer) - 1); if (TEST_EQ(rc, 0)) { _unacked += sizeof(out_success) - 1; + printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_success); err = _stream.send(out_success, sizeof(out_success) - 1); _done = true; - TEST_EQ(err, SOCKET_ERROR_NONE); - minar::Scheduler::postCallback(fpterminate_t(terminate).bind(TEST_RESULT(),this)); + if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { + printf("MBED: TCPClient unable to send data!" NL); + onError(&_stream, err); + } } } if (!_done) { - _unacked += sizeof(out_failure) - 1; - err = _stream.send(out_failure, sizeof(out_failure) - 1); - _done = true; - TEST_EQ(err, SOCKET_ERROR_NONE); - minar::Scheduler::postCallback(fpterminate_t(terminate).bind(TEST_RESULT(),this)); + // Failed to validate rceived data. Terminating... + minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); } } void onSent(Socket *s, uint16_t nbytes) { (void) s; _unacked -= nbytes; + printf ("MBED: Sent %d bytes" NL, nbytes); if (_done && (_unacked == 0)) { - _stream.close(); + minar::Scheduler::postCallback(fpterminate_t(terminate).bind(true,this)); } } void onDisconnect(TCPStream *s) @@ -151,40 +166,82 @@ class TCPEchoClient { volatile size_t _unacked; }; -void terminate(bool status, TCPEchoClient* client) +void terminate(bool status, TCPEchoClient* ) { - delete client; - eth.disconnect(); - MBED_HOSTTEST_RESULT(status); + if (client) { + printf("MBED: Test finished!"); + delete client; + client = NULL; + eth.disconnect(); + // utest has two different APIs for pass and fail. + if (status) { + Harness::validate_callback(); + } else { + Harness::raise_failure(REASON_CASES); + } + } } -void app_start(int argc, char *argv[]) { - (void)argc; - (void)argv; - MBED_HOSTTEST_TIMEOUT(20); - MBED_HOSTTEST_SELECT(tcpecho_client_auto); - MBED_HOSTTEST_DESCRIPTION(TCP echo client); - MBED_HOSTTEST_START("NET_4"); +control_t test_echo_tcp_client() +{ socket_error_t err = lwipv4_socket_init(); TEST_EQ(err, SOCKET_ERROR_NONE); - - memset(buffer, 0, sizeof(buffer)); - port = 0; - s_ip_address ip_addr = {0, 0, 0, 0}; - printf("TCPClient waiting for server IP and port..." NL); - scanf("%d.%d.%d.%d:%d", &ip_addr.ip_1, &ip_addr.ip_2, &ip_addr.ip_3, &ip_addr.ip_4, &port); - printf("Address received:%d.%d.%d.%d:%d" NL, ip_addr.ip_1, ip_addr.ip_2, ip_addr.ip_3, ip_addr.ip_4, port); - + eth.init(); //Use DHCP eth.connect(); printf("TCPClient IP Address is %s" NL, eth.getIPAddress()); - sprintf(buffer, "%d.%d.%d.%d", ip_addr.ip_1, ip_addr.ip_2, ip_addr.ip_3, ip_addr.ip_4); + greentea_send_kv("target_ip", eth.getIPAddress()); + + memset(buffer, 0, sizeof(buffer)); + port = 0; + + printf("TCPClient waiting for server IP and port..." NL); + char recv_key[] = "host_port"; + char port_value[] = "65325"; + + greentea_send_kv("host_ip", " "); + TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)) != 0); + + greentea_send_kv("host_port", " "); + TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)) != 0); + + sscanf(port_value, "%d", &port); + + client = new TCPEchoClient(SOCKET_STACK_LWIP_IPV4); { mbed::util::FunctionPointer2 fp(client, &TCPEchoClient::start_test); minar::Scheduler::postCallback(fp.bind(buffer, port)); } + return CaseTimeout(15000); } + +// Cases -------------------------------------------------------------------------------------------------------------- +Case cases[] = { + Case("Test Echo TCP Client", test_echo_tcp_client), +}; + +status_t greentea_setup(const size_t number_of_cases) +{ + // Handshake with greentea + // Host test timeout should be more than target utest timeout to let target cleanup the test and send test summary. + GREENTEA_SETUP(20, "tcpecho_client_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + greentea_test_teardown_handler(passed, failed, failure); + GREENTEA_TESTSUITE_RESULT(failed == 0); +} + +Specification specification(greentea_setup, cases, greentea_teardown); + +void app_start(int, char*[]) +{ + Harness::run(specification); +} + diff --git a/test/host_tests/tcpecho_client_auto.py b/test/host_tests/tcpecho_client_auto.py new file mode 100644 index 0000000..723f94d --- /dev/null +++ b/test/host_tests/tcpecho_client_auto.py @@ -0,0 +1,149 @@ +# 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 socket +import logging +from threading import Thread +from sys import stdout +from SocketServer import BaseRequestHandler, TCPServer +from mbed_host_tests import BaseHostTest + + +class TCPEchoClient_Handler(BaseRequestHandler): + def handle(self): + """ + One handle per connection + """ + print ("HOST: TCPEchoClient_Handler: Connection received...") + while True: + try: + data = self.request.recv(1024) + if not data: break + print ('HOST: TCPEchoClient_Handler: \n%s\n' % data) + + # If client finishes, sit on recv and terminate + # after client closes connection. + if '{{end}}' in data: continue + + # echo data back to the client + self.request.sendall(data) + except Exception as e: + print ('HOST: TCPEchoClient_Handler: %s' % str(e)) + break + + +class TCPEchoClientTest(BaseHostTest): + + __result = None + COUNT_MAX = 10 + count = 0 + uuid_sent = [] + uuid_recv = [] + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + super(BaseHostTest, self).__init__() + 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) + s.connect((target_ip, 0)) # Target IP, Any 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 = TCPServer((self.SERVER_IP, self.SERVER_PORT), TCPEchoClient_Handler) + 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() + + 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() + + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def setup(self): + self.register_callback("target_ip", self._callback_target_ip) + self.register_callback("host_ip", self._callback_host_ip) + self.register_callback("host_port", self._callback_host_port) + + def result(self): + self.__result = self.uuid_sent == self.uuid_recv + return self.__result + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join() From a25ea3f29c0fbc8425b3b0a975ddca2ed04c74a6 Mon Sep 17 00:00:00 2001 From: Mohammad Azim Khan Date: Mon, 22 Feb 2016 14:10:38 +0000 Subject: [PATCH 2/6] Ported UDP echo client to new utest/greentea framework --- test/echo-tcp-client/main.cpp | 11 +-- test/echo-udp-client/main.cpp | 131 ++++++++++++++++++------- test/host_tests/tcpecho_client_auto.py | 22 ++--- test/host_tests/udpecho_client_auto.py | 127 ++++++++++++++++++++++++ 4 files changed, 231 insertions(+), 60 deletions(-) create mode 100644 test/host_tests/udpecho_client_auto.py diff --git a/test/echo-tcp-client/main.cpp b/test/echo-tcp-client/main.cpp index 97f144e..0ffd3c1 100644 --- a/test/echo-tcp-client/main.cpp +++ b/test/echo-tcp-client/main.cpp @@ -26,15 +26,6 @@ #include "unity/unity.h" using namespace utest::v1; - -struct s_ip_address { - int ip_1; - int ip_2; - int ip_3; - int ip_4; -}; - - using namespace mbed::Sockets::v0; EthernetInterface eth; @@ -80,7 +71,7 @@ class TCPEchoClient { err = _stream.resolve(host_addr,TCPStream::DNSHandler_t(this, &TCPEchoClient::onDNS)); if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: TCPClient unable to connect to %s:%d" NL, host_addr, port); + printf("MBED: TCPClient unable to resolve address %s" NL, host_addr); onError(&_stream, err); } } diff --git a/test/echo-udp-client/main.cpp b/test/echo-udp-client/main.cpp index ac80cc7..d616102 100644 --- a/test/echo-udp-client/main.cpp +++ b/test/echo-udp-client/main.cpp @@ -15,7 +15,6 @@ * limitations under the License. */ #include "mbed-drivers/mbed.h" -#include "mbed-drivers/test_env.h" #include "sal/test/ctest_env.h" #include "sal/socket_api.h" #include @@ -24,11 +23,16 @@ #include "sal-stack-lwip/lwipv4_init.h" #include "minar/minar.h" #include "core-util/FunctionPointer.h" +#include "greentea-client/test_env.h" +#include "utest/utest.h" +#include "unity/unity.h" #define CHECK(RC, STEP) if (RC < 0) error(STEP": %d\r\n", RC) +using namespace utest::v1; using namespace mbed::Sockets::v0; + namespace { const int BUFFER_SIZE = 64; const int MAX_ECHO_LOOPS = 100; @@ -57,7 +61,7 @@ void terminate(bool status, UDPEchoClient* client); char buffer[BUFFER_SIZE] = {0}; int port = 0; -UDPEchoClient *ec; +UDPEchoClient *client; EthernetInterface eth; class UDPEchoClient { @@ -67,11 +71,22 @@ class UDPEchoClient { { _usock.setOnError(UDPSocket::ErrorHandler_t(this, &UDPEchoClient::onError)); } + ~UDPEchoClient(){ + if (_usock.isConnected()) + _usock.close(); + } void start_test(char * host_addr, uint16_t port) { loop_ctr = 0; _port = port; - socket_error_t err = _usock.resolve(host_addr,UDPSocket::DNSHandler_t(this, &UDPEchoClient::onDNS)); + + socket_error_t err = _usock.open(SOCKET_AF_INET4); + if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { + printf("MBED: UDPClient unable to open socket" NL); + onError(&_usock, err); + } + + err = _usock.resolve(host_addr,UDPSocket::DNSHandler_t(this, &UDPEchoClient::onDNS)); if(!TEST_EQ(err, SOCKET_ERROR_NONE)) { printf("MBED: Failed to resolve %s\r\n", host_addr); onError(&_usock, err); @@ -80,7 +95,7 @@ class UDPEchoClient { void onError(Socket *s, socket_error_t err) { (void) s; printf("MBED: Socket Error: %s (%d)\r\n", socket_strerror(err), err); - minar::Scheduler::postCallback(fpterminate_t(terminate).bind(TEST_RESULT(),this)); + minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); } void onDNS(Socket *s, struct socket_addr sa, const char * domain) { @@ -92,7 +107,11 @@ class UDPEchoClient { /* TODO: add support for getting AF from addr */ socket_error_t err = _usock.open(SOCKET_AF_INET4); - TEST_EQ(err, SOCKET_ERROR_NONE); + if (!TEST_EQ(err, SOCKET_ERROR_NONE)) + { + printf("MBED: UDPClient failed to open UDP socket" NL); + onError(&_usock, err); + } /* Register the read handler */ _usock.setOnReadable(UDPSocket::ReadableHandler_t(this, &UDPEchoClient::onRx)); /* Send the query packet to the remote host */ @@ -116,11 +135,8 @@ class UDPEchoClient { } if ((rc == 0) && (loop_ctr >= MAX_ECHO_LOOPS)) { - if (notify_completion_str(TEST_RESULT(), buffer)) { - _usock.send_to(buffer, strlen(buffer), &_resolvedAddr, _port); - _usock.close(); - minar::Scheduler::postCallback(fpterminate_t(terminate).bind(TEST_RESULT(),this)); - } + _usock.send_to(buffer, strlen(buffer), &_resolvedAddr, _port); + minar::Scheduler::postCallback(fpterminate_t(terminate).bind(true,this)); } } bool isDone() { @@ -146,44 +162,85 @@ class UDPEchoClient { volatile bool done; }; -void terminate(bool status, UDPEchoClient* client) +void terminate(bool status, UDPEchoClient* ) { - delete client; - eth.disconnect(); - MBED_HOSTTEST_RESULT(status); + if (client) { + printf("MBED: Test finished!"); + delete client; + client = NULL; + eth.disconnect(); + // utest has two different APIs for pass and fail. + if (status) { + Harness::validate_callback(); + } else { + Harness::raise_failure(REASON_CASES); + } + } } -void app_start(int argc, char *argv[]) { - (void) argc; - (void) argv; - MBED_HOSTTEST_TIMEOUT(20); - MBED_HOSTTEST_SELECT(udpecho_client_auto); - MBED_HOSTTEST_DESCRIPTION(UDP echo client); - MBED_HOSTTEST_START("NET_6"); + +control_t test_echo_udp_client() +{ socket_error_t err = lwipv4_socket_init(); TEST_EQ(err, SOCKET_ERROR_NONE); + + printf("MBED: Initializing ethernet connection." NL); + eth.init(); //Use DHCP + eth.connect(); + + printf("MBED: IP Address is %s" NL, eth.getIPAddress()); + greentea_send_kv("target_ip", eth.getIPAddress()); + + memset(buffer, 0, sizeof(buffer)); + port = 0; + + printf("UDPClient waiting for server IP and port..." NL); + char recv_key[] = "host_port"; + char port_value[] = "65325"; + + greentea_send_kv("host_ip", " "); + TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)) != 0); + + greentea_send_kv("host_port", " "); + TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)) != 0); + + sscanf(port_value, "%d", &port); + + + client = new UDPEchoClient(SOCKET_STACK_LWIP_IPV4); - s_ip_address ip_addr = {0, 0, 0, 0}; + { + mbed::util::FunctionPointer2 fp(client, &UDPEchoClient::start_test); + minar::Scheduler::postCallback(fp.bind(buffer, port)); + } + return CaseTimeout(15000); +} - printf("MBED: UDPCllient waiting for server IP and port...\r\n"); - scanf("%d.%d.%d.%d:%d", &ip_addr.ip_1, &ip_addr.ip_2, &ip_addr.ip_3, &ip_addr.ip_4, &port); - printf("MBED: Address received: %d.%d.%d.%d:%d\r\n", ip_addr.ip_1, ip_addr.ip_2, ip_addr.ip_3, ip_addr.ip_4, port); - int rc = eth.init(); //Use DHCP - CHECK(rc, "eth init"); +// Cases -------------------------------------------------------------------------------------------------------------- +Case cases[] = { + Case("Test Echo UDP Client", test_echo_udp_client), +}; - rc = eth.connect(); - CHECK(rc, "connect"); - printf("IP: %s\n", eth.getIPAddress()); +status_t greentea_setup(const size_t number_of_cases) +{ + // Handshake with greentea + // Host test timeout should be more than target utest timeout to let target cleanup the test and send test summary. + GREENTEA_SETUP(20, "udpecho_client_auto"); + return greentea_test_setup_handler(number_of_cases); +} - ec = new UDPEchoClient(SOCKET_STACK_LWIP_IPV4); +void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) +{ + greentea_test_teardown_handler(passed, failed, failure); + GREENTEA_TESTSUITE_RESULT(failed == 0); +} - printf("MBED: UDPClient IP Address is %s\r\n", eth.getIPAddress()); - sprintf(buffer, "%d.%d.%d.%d", ip_addr.ip_1, ip_addr.ip_2, ip_addr.ip_3, ip_addr.ip_4); +Specification specification(greentea_setup, cases, greentea_teardown); - { - mbed::util::FunctionPointer2 fp(ec, &UDPEchoClient::start_test); - minar::Scheduler::postCallback(fp.bind(buffer, port)); - } +void app_start(int, char*[]) +{ + Harness::run(specification); } + diff --git a/test/host_tests/tcpecho_client_auto.py b/test/host_tests/tcpecho_client_auto.py index 723f94d..cb69311 100644 --- a/test/host_tests/tcpecho_client_auto.py +++ b/test/host_tests/tcpecho_client_auto.py @@ -21,10 +21,16 @@ from mbed_host_tests import BaseHostTest -class TCPEchoClient_Handler(BaseRequestHandler): +class TCPEchoClientHandler(BaseRequestHandler): def handle(self): """ - One handle per connection + 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. """ print ("HOST: TCPEchoClient_Handler: Connection received...") while True: @@ -46,12 +52,6 @@ def handle(self): class TCPEchoClientTest(BaseHostTest): - __result = None - COUNT_MAX = 10 - count = 0 - uuid_sent = [] - uuid_recv = [] - def __init__(self): """ Initialise test parameters. @@ -90,7 +90,7 @@ def setup_tcp_server(self): self.notify_complete(False) # Returning none will suppress host test from printing success code - self.server = TCPServer((self.SERVER_IP, self.SERVER_PORT), TCPEchoClient_Handler) + self.server = TCPServer((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler) ip, port = self.server.server_address self.SERVER_PORT = port self.server.allow_reuse_address = True @@ -139,10 +139,6 @@ def setup(self): self.register_callback("host_ip", self._callback_host_ip) self.register_callback("host_port", self._callback_host_port) - def result(self): - self.__result = self.uuid_sent == self.uuid_recv - return self.__result - def teardown(self): if self.server: self.server.shutdown() diff --git a/test/host_tests/udpecho_client_auto.py b/test/host_tests/udpecho_client_auto.py new file mode 100644 index 0000000..51bea14 --- /dev/null +++ b/test/host_tests/udpecho_client_auto.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 + + +class UDPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ UDP packet handler. Echoes data back to sender's address. + """ + data, sock = self.request + print data + sock.sendto(data, self.client_address) + + +class UDPEchoClientTest(BaseHostTest): + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + super(BaseHostTest, self).__init__() + 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) + s.connect((target_ip, 0)) # Target IP, Any 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() + + 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() + + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def setup(self): + self.register_callback("target_ip", self._callback_target_ip) + self.register_callback("host_ip", self._callback_host_ip) + self.register_callback("host_port", self._callback_host_port) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join() From 1163577dacccbd959fed7912f8846b7db7cb32d6 Mon Sep 17 00:00:00 2001 From: Mohammad Azim Khan Date: Tue, 23 Feb 2016 10:34:38 +0000 Subject: [PATCH 3/6] Proper use of utest test asserts and removing use of old TEST_EQ --- test/echo-tcp-client/main.cpp | 69 +++++++++++---------------------- test/echo-udp-client/main.cpp | 73 +++++++++++------------------------ 2 files changed, 45 insertions(+), 97 deletions(-) diff --git a/test/echo-tcp-client/main.cpp b/test/echo-tcp-client/main.cpp index 0ffd3c1..f28d5ff 100644 --- a/test/echo-tcp-client/main.cpp +++ b/test/echo-tcp-client/main.cpp @@ -16,7 +16,6 @@ */ #include "mbed-drivers/mbed.h" #include "sockets/TCPStream.h" -#include "sal/test/ctest_env.h" #include "sal-stack-lwip/lwipv4_init.h" #include "sal-iface-eth/EthernetInterface.h" #include "minar/minar.h" @@ -53,6 +52,7 @@ class TCPEchoClient { } void onError(Socket *s, socket_error_t err) { (void) s; + TEST_ASSERT_NOT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, socket_strerror(err)); printf("MBED: Socket Error: %s (%d)\r\n", socket_strerror(err), err); _done = true; minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); @@ -64,16 +64,10 @@ class TCPEchoClient { _done = false; _disconnected = true; socket_error_t err = _stream.open(SOCKET_AF_INET4); - if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: TCPClient unable to open socket" NL); - onError(&_stream, err); - } + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to open socket!"); err = _stream.resolve(host_addr,TCPStream::DNSHandler_t(this, &TCPEchoClient::onDNS)); - if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: TCPClient unable to resolve address %s" NL, host_addr); - onError(&_stream, err); - } + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to resolve host address!"); } void onDNS(Socket *s, struct socket_addr sa, const char* domain) { @@ -89,10 +83,7 @@ class TCPEchoClient { _stream.setOnDisconnect(TCPStream::DisconnectHandler_t(this, &TCPEchoClient::onDisconnect)); /* Send the query packet to the remote host */ socket_error_t err = _stream.connect(_resolvedAddr, _port, TCPStream::ConnectHandler_t(this,&TCPEchoClient::onConnect)); - if(!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: Expected %d, got %d (%s)\r\n", SOCKET_ERROR_NONE, err, socket_strerror(err)); - onError(&_stream, err); - } + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to connect host server!"); } void onConnect(TCPStream *s) { @@ -101,33 +92,27 @@ class TCPEchoClient { _unacked = sizeof(out_buffer) - 1; printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_buffer); socket_error_t err = _stream.send(out_buffer, sizeof(out_buffer) - 1); - - if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: TCPClient unable to send data!" NL); - onError(&_stream, err); - } + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: TCPClient failed to send data!"); } void onRx(Socket* s) { (void) s; size_t n = sizeof(buffer)-1; socket_error_t err = _stream.recv(buffer, &n); - TEST_EQ(err, SOCKET_ERROR_NONE); + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: TCPClient failed to recv data!"); + buffer[n] = 0; printf ("MBED: Rx (%d bytes) from host: %s" NL, n, buffer); if (!_done && n > 0) { int rc = strncmp(out_buffer, buffer, sizeof(out_buffer) - 1); - if (TEST_EQ(rc, 0)) { - _unacked += sizeof(out_success) - 1; - printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_success); - err = _stream.send(out_success, sizeof(out_success) - 1); - _done = true; - if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: TCPClient unable to send data!" NL); - onError(&_stream, err); - } - } + TEST_ASSERT_EQUAL_MESSAGE(0, rc, "MBED: TCPClient round trip data validation failed!"); + + _unacked += sizeof(out_success) - 1; + printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_success); + err = _stream.send(out_success, sizeof(out_success) - 1); + _done = true; + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: TCPClient failed to send data!"); } if (!_done) { // Failed to validate rceived data. Terminating... @@ -164,22 +149,17 @@ void terminate(bool status, TCPEchoClient* ) delete client; client = NULL; eth.disconnect(); - // utest has two different APIs for pass and fail. - if (status) { - Harness::validate_callback(); - } else { - Harness::raise_failure(REASON_CASES); - } + TEST_ASSERT_TRUE_MESSAGE(status, "MBED: test failed!"); + Harness::validate_callback(); } } - control_t test_echo_tcp_client() { socket_error_t err = lwipv4_socket_init(); - TEST_EQ(err, SOCKET_ERROR_NONE); + TEST_ASSERT_EQUAL(SOCKET_ERROR_NONE, err); - eth.init(); //Use DHCP + TEST_ASSERT_EQUAL(0, eth.init()); //Use DHCP eth.connect(); printf("TCPClient IP Address is %s" NL, eth.getIPAddress()); @@ -193,10 +173,10 @@ control_t test_echo_tcp_client() char port_value[] = "65325"; greentea_send_kv("host_ip", " "); - TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)) != 0); + TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)), "MBED: Failed to recv/parse key value from host test!"); greentea_send_kv("host_port", " "); - TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)) != 0); + TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)), "MBED: Failed to recv/parse key value from host test!"); sscanf(port_value, "%d", &port); @@ -207,6 +187,7 @@ control_t test_echo_tcp_client() mbed::util::FunctionPointer2 fp(client, &TCPEchoClient::start_test); minar::Scheduler::postCallback(fp.bind(buffer, port)); } + return CaseTimeout(15000); } @@ -223,13 +204,7 @@ status_t greentea_setup(const size_t number_of_cases) return greentea_test_setup_handler(number_of_cases); } -void greentea_teardown(const size_t passed, const size_t failed, const failure_t failure) -{ - greentea_test_teardown_handler(passed, failed, failure); - GREENTEA_TESTSUITE_RESULT(failed == 0); -} - -Specification specification(greentea_setup, cases, greentea_teardown); +Specification specification(greentea_setup, cases); void app_start(int, char*[]) { diff --git a/test/echo-udp-client/main.cpp b/test/echo-udp-client/main.cpp index d616102..1de697e 100644 --- a/test/echo-udp-client/main.cpp +++ b/test/echo-udp-client/main.cpp @@ -15,7 +15,6 @@ * limitations under the License. */ #include "mbed-drivers/mbed.h" -#include "sal/test/ctest_env.h" #include "sal/socket_api.h" #include #include "sockets/UDPSocket.h" @@ -37,13 +36,6 @@ namespace { const int BUFFER_SIZE = 64; const int MAX_ECHO_LOOPS = 100; const char ASCII_MAX = '~' - ' '; - - struct s_ip_address { - int ip_1; - int ip_2; - int ip_3; - int ip_4; - }; } char char_rand() { @@ -81,19 +73,14 @@ class UDPEchoClient { _port = port; socket_error_t err = _usock.open(SOCKET_AF_INET4); - if (!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: UDPClient unable to open socket" NL); - onError(&_usock, err); - } - + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient unable to open socket" NL); + printf("MBED: Trying to resolve address %s" NL, host_addr); err = _usock.resolve(host_addr,UDPSocket::DNSHandler_t(this, &UDPEchoClient::onDNS)); - if(!TEST_EQ(err, SOCKET_ERROR_NONE)) { - printf("MBED: Failed to resolve %s\r\n", host_addr); - onError(&_usock, err); - } + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to resolve host server address" NL); } void onError(Socket *s, socket_error_t err) { (void) s; + TEST_ASSERT_NOT_EQUAL(SOCKET_ERROR_NONE, err); printf("MBED: Socket Error: %s (%d)\r\n", socket_strerror(err), err); minar::Scheduler::postCallback(fpterminate_t(terminate).bind(false,this)); } @@ -107,50 +94,39 @@ class UDPEchoClient { /* TODO: add support for getting AF from addr */ socket_error_t err = _usock.open(SOCKET_AF_INET4); - if (!TEST_EQ(err, SOCKET_ERROR_NONE)) - { - printf("MBED: UDPClient failed to open UDP socket" NL); - onError(&_usock, err); - } + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to open socket!" NL); + /* Register the read handler */ _usock.setOnReadable(UDPSocket::ReadableHandler_t(this, &UDPEchoClient::onRx)); /* Send the query packet to the remote host */ - err = send_test(); - TEST_EQ(err, SOCKET_ERROR_NONE); + send_test(); } void onRx(Socket *s) { (void) s; unsigned int n = sizeof(buffer); socket_error_t err = _usock.recv(buffer, &n); - TEST_EQ(err, SOCKET_ERROR_NONE); + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to recv data!" NL); int rc = memcmp(buffer, out_buffer, min(BUFFER_SIZE,n)); - TEST_EQ(rc, 0); + TEST_ASSERT_EQUAL_MESSAGE(0, rc, "MBED: UDPClient round trip data validation error!" NL); loop_ctr++; - if (!rc && (loop_ctr < MAX_ECHO_LOOPS)) { - err = send_test(); - TEST_EQ(err, SOCKET_ERROR_NONE); + if (loop_ctr < MAX_ECHO_LOOPS) { + send_test(); } - if ((rc == 0) && (loop_ctr >= MAX_ECHO_LOOPS)) { + if (loop_ctr >= MAX_ECHO_LOOPS) { _usock.send_to(buffer, strlen(buffer), &_resolvedAddr, _port); minar::Scheduler::postCallback(fpterminate_t(terminate).bind(true,this)); } } - bool isDone() { - return done; - } - bool isError() { - return !TEST_RESULT(); - } protected: - socket_error_t send_test() { + void send_test() { std::generate(out_buffer, out_buffer + BUFFER_SIZE, char_rand); socket_error_t err = _usock.send_to(out_buffer, sizeof(BUFFER_SIZE), &_resolvedAddr, _port); - return err; + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: UDPClient failed to send data!" NL); } protected: UDPSocket _usock; @@ -169,12 +145,8 @@ void terminate(bool status, UDPEchoClient* ) delete client; client = NULL; eth.disconnect(); - // utest has two different APIs for pass and fail. - if (status) { - Harness::validate_callback(); - } else { - Harness::raise_failure(REASON_CASES); - } + TEST_ASSERT_TRUE_MESSAGE(status, "MBED: test failed!"); + Harness::validate_callback(); } } @@ -183,10 +155,11 @@ void terminate(bool status, UDPEchoClient* ) control_t test_echo_udp_client() { socket_error_t err = lwipv4_socket_init(); - TEST_EQ(err, SOCKET_ERROR_NONE); + TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "Failed to init LWIPv4 socket!"); printf("MBED: Initializing ethernet connection." NL); - eth.init(); //Use DHCP + //Use DHCP + TEST_ASSERT_EQUAL_MESSAGE(0, eth.init(), "Failed to init LWIPv4 socket!"); eth.connect(); printf("MBED: IP Address is %s" NL, eth.getIPAddress()); @@ -200,10 +173,10 @@ control_t test_echo_udp_client() char port_value[] = "65325"; greentea_send_kv("host_ip", " "); - TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)) != 0); + TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, buffer, sizeof(recv_key), sizeof(buffer)), "MBED: Failed to recv/parse key value from host!"); greentea_send_kv("host_port", " "); - TEST_ASSERT_TRUE(greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)) != 0); + TEST_ASSERT_NOT_EQUAL_MESSAGE(0, greentea_parse_kv(recv_key, port_value, sizeof(recv_key), sizeof(port_value)), "MBED: Failed to recv/parse key value from host!"); sscanf(port_value, "%d", &port); @@ -214,7 +187,7 @@ control_t test_echo_udp_client() mbed::util::FunctionPointer2 fp(client, &UDPEchoClient::start_test); minar::Scheduler::postCallback(fp.bind(buffer, port)); } - return CaseTimeout(15000); + return CaseTimeout(25000); } @@ -227,7 +200,7 @@ status_t greentea_setup(const size_t number_of_cases) { // Handshake with greentea // Host test timeout should be more than target utest timeout to let target cleanup the test and send test summary. - GREENTEA_SETUP(20, "udpecho_client_auto"); + GREENTEA_SETUP(30, "udpecho_client_auto"); return greentea_test_setup_handler(number_of_cases); } From 95c43c0b32076d2fdec7f401006530227f914c48 Mon Sep 17 00:00:00 2001 From: Mohammad Azim Khan Date: Tue, 23 Feb 2016 13:25:10 +0000 Subject: [PATCH 4/6] Added TCPServerWrapper to manage server state accross test and server thread. It helps to close the connection when test tears down. --- test/host_tests/tcpecho_client_auto.py | 62 ++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/test/host_tests/tcpecho_client_auto.py b/test/host_tests/tcpecho_client_auto.py index cb69311..073a1bc 100644 --- a/test/host_tests/tcpecho_client_auto.py +++ b/test/host_tests/tcpecho_client_auto.py @@ -13,6 +13,7 @@ # limitations under the License. import sys +import select import socket import logging from threading import Thread @@ -33,9 +34,9 @@ def handle(self): fails raising a SocketError as client closes connection. """ print ("HOST: TCPEchoClient_Handler: Connection received...") - while True: + while self.server.isrunning(): try: - data = self.request.recv(1024) + data = self.recv() if not data: break print ('HOST: TCPEchoClient_Handler: \n%s\n' % data) @@ -44,10 +45,63 @@ def handle(self): if '{{end}}' in data: continue # echo data back to the client - self.request.sendall(data) + self.send(data) except Exception as e: print ('HOST: TCPEchoClient_Handler: %s' % str(e)) break + print 'Connection finshed' + + 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): @@ -90,7 +144,7 @@ def setup_tcp_server(self): self.notify_complete(False) # Returning none will suppress host test from printing success code - self.server = TCPServer((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler) + 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 From 9337384976010defa5054fcdac9a1bbde6c85cae Mon Sep 17 00:00:00 2001 From: Mohammad Azim Khan Date: Tue, 23 Feb 2016 18:17:05 +0000 Subject: [PATCH 5/6] Using event decorator instead of manually registering events in setup() --- test/host_tests/tcpecho_client_auto.py | 10 ++++------ test/host_tests/udpecho_client_auto.py | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/test/host_tests/tcpecho_client_auto.py b/test/host_tests/tcpecho_client_auto.py index 073a1bc..c1eb3ab 100644 --- a/test/host_tests/tcpecho_client_auto.py +++ b/test/host_tests/tcpecho_client_auto.py @@ -19,7 +19,7 @@ from threading import Thread from sys import stdout from SocketServer import BaseRequestHandler, TCPServer -from mbed_host_tests import BaseHostTest +from mbed_host_tests import BaseHostTest, event_callback class TCPEchoClientHandler(BaseRequestHandler): @@ -162,6 +162,7 @@ def server_thread_func(this): """ 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. @@ -175,6 +176,7 @@ def _callback_target_ip(self, key, value, timestamp): 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 @@ -182,17 +184,13 @@ def _callback_host_ip(self, key, value, timestamp): """ 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 setup(self): - self.register_callback("target_ip", self._callback_target_ip) - self.register_callback("host_ip", self._callback_host_ip) - self.register_callback("host_port", self._callback_host_port) - def teardown(self): if self.server: self.server.shutdown() diff --git a/test/host_tests/udpecho_client_auto.py b/test/host_tests/udpecho_client_auto.py index 51bea14..b6e637f 100644 --- a/test/host_tests/udpecho_client_auto.py +++ b/test/host_tests/udpecho_client_auto.py @@ -20,7 +20,7 @@ from sys import stdout from threading import Thread from SocketServer import BaseRequestHandler, UDPServer -from mbed_host_tests import BaseHostTest +from mbed_host_tests import BaseHostTest, event_callback class UDPEchoClientHandler(BaseRequestHandler): @@ -90,6 +90,7 @@ def server_thread_func(this): """ 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. @@ -103,6 +104,7 @@ def _callback_target_ip(self, key, value, timestamp): 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 @@ -110,17 +112,13 @@ def _callback_host_ip(self, key, value, timestamp): """ 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 setup(self): - self.register_callback("target_ip", self._callback_target_ip) - self.register_callback("host_ip", self._callback_host_ip) - self.register_callback("host_port", self._callback_host_port) - def teardown(self): if self.server: self.server.shutdown() From e9c9e71c31edd30f9c4a567b1488624d019a8942 Mon Sep 17 00:00:00 2001 From: Mohammad Azim Khan Date: Wed, 24 Feb 2016 16:02:34 +0000 Subject: [PATCH 6/6] Fix mbed-drivers version and using a TEST_ASSERT_ instead of strncmp --- module.json | 4 ++-- test/echo-tcp-client/main.cpp | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/module.json b/module.json index ce25a55..b3f1b7d 100644 --- a/module.json +++ b/module.json @@ -21,9 +21,9 @@ "minar": "^1.0.0" }, "testDependencies": { - "mbed-drivers": "~0.11.1", + "mbed-drivers": "~0.12.1", "unity": "^2.0.1", - "greentea-client": "^0.1.3" + "greentea-client": "^0.1.4" }, "scripts": { "testReporter": [ diff --git a/test/echo-tcp-client/main.cpp b/test/echo-tcp-client/main.cpp index f28d5ff..50277a1 100644 --- a/test/echo-tcp-client/main.cpp +++ b/test/echo-tcp-client/main.cpp @@ -105,9 +105,8 @@ class TCPEchoClient { printf ("MBED: Rx (%d bytes) from host: %s" NL, n, buffer); if (!_done && n > 0) { - int rc = strncmp(out_buffer, buffer, sizeof(out_buffer) - 1); - TEST_ASSERT_EQUAL_MESSAGE(0, rc, "MBED: TCPClient round trip data validation failed!"); - + TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(out_buffer, buffer, n, "MBED: TCPClient round trip data validation failed!"); + _unacked += sizeof(out_success) - 1; printf ("MBED: Sending (%d bytes) to host: %s" NL, _unacked, out_success); err = _stream.send(out_success, sizeof(out_success) - 1);