Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Porting tests to new utest-greentea framework #62

Merged
merged 6 commits into from
Feb 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion module.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +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.4"
},
"scripts": {
"testReporter": [
Expand Down
160 changes: 91 additions & 69 deletions test/echo-tcp-client/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,16 @@
* 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"

struct s_ip_address {
int ip_1;
int ip_2;
int ip_3;
int ip_4;
};


using namespace utest::v1;
using namespace mbed::Sockets::v0;

EthernetInterface eth;
Expand All @@ -41,6 +35,7 @@ void terminate(bool status, TCPEchoClient* client);

char out_buffer[] = "Hello World\n";
char buffer[256];
char out_success[] = "{{success}}\n{{end}}\n";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string is confusing, is this just a payload used for test or actual control command?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved it outside from onRx() in original code to sit with other strings. It indicates to the host test that target test has validated a round trip (echo) data and now terminating. It is good stop to host test from echoing back as target client closes the connection right after sending this string.
But it should not be confused with serial k,v command.

TCPEchoClient *client;
int port;

Expand All @@ -51,22 +46,28 @@ 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;
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(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));
if (!TEST_EQ(err, SOCKET_ERROR_NONE)) {
printf("MBED: TCPClient unable to connect to %s:%d" NL, buffer, port);
onError(&_stream, err);
}
socket_error_t err = _stream.open(SOCKET_AF_INET4);
TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to open socket!");

err = _stream.resolve(host_addr,TCPStream::DNSHandler_t(this, &TCPEchoClient::onDNS));
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)
{
Expand All @@ -76,65 +77,54 @@ 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));
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);
}
socket_error_t err = _stream.connect(_resolvedAddr, _port, TCPStream::ConnectHandler_t(this,&TCPEchoClient::onConnect));
TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: Failed to connect host server!");
}
void onConnect(TCPStream *s)
{
(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);
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;
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);
if (TEST_EQ(rc, 0)) {
_unacked += sizeof(out_success) - 1;
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));
}
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);
_done = true;
TEST_ASSERT_EQUAL_MESSAGE(SOCKET_ERROR_NONE, err, "MBED: TCPClient failed to send data!");
}
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)
Expand All @@ -151,40 +141,72 @@ 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();
TEST_ASSERT_TRUE_MESSAGE(status, "MBED: test failed!");
Harness::validate_callback();
}
}


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);
TEST_ASSERT_EQUAL(SOCKET_ERROR_NONE, err);

TEST_ASSERT_EQUAL(0, eth.init()); //Use DHCP
eth.connect();

printf("TCPClient IP Address is %s" NL, eth.getIPAddress());
greentea_send_kv("target_ip", eth.getIPAddress());

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);
char recv_key[] = "host_port";
char port_value[] = "65325";

greentea_send_kv("host_ip", " ");
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_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);


client = new TCPEchoClient(SOCKET_STACK_LWIP_IPV4);

{
mbed::util::FunctionPointer2<void, char *, uint16_t> 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);
}

Specification specification(greentea_setup, cases);

void app_start(int, char*[])
{
Harness::run(specification);
}

Loading