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

Devel Transport #64

Merged
merged 11 commits into from
Mar 2, 2016
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": "^1.0.0"
"mbed-drivers": "^1.0.0",
"unity": "^2.0.1",
"greentea-client": "^0.1.4"
Copy link
Contributor

Choose a reason for hiding this comment

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

"^0.1.4" means "==0.1.4" for major version 0, see the "dependencies" section in http://yottadocs.mbed.com/reference/module.html. Probably not the intention here.

},
"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";
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