Merge pull request #8138 from michalpasztamobica/master

Unit tests for TCPSocket, TCPServer, UDPSocket, NetworkStack, InternetSocket
pull/7970/merge
Martin Kojtal 2018-09-26 09:38:20 +02:00 committed by GitHub
commit 4957dd537e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 936 additions and 38 deletions

View File

@ -19,17 +19,13 @@
#include "features/netsocket/InternetSocket.h"
#include "NetworkStack_stub.h"
extern std::list<uint32_t> eventFlagsStubNextRetval;
// InternetSocket is an abstract class, so we have to test it via its child.
class stubInternetSocket : public InternetSocket {
protected:
nsapi_error_t return_value = 0;
public:
virtual void event()
{
if (_callback) {
_callback.call();
}
}
virtual nsapi_error_t connect(const SocketAddress &address)
{
return return_value;
@ -60,6 +56,15 @@ public:
{
return return_value;
}
// Testing functions
void add_reader (void) { _readers++;}
void rem_reader (void) { _readers--;}
void add_writer (void) { _writers++;}
void rem_writer (void) { _writers--;}
void add_pending (void) { _pending++;}
void rem_pending (void) { _pending--;}
protected:
virtual nsapi_protocol_t get_proto()
{
@ -94,7 +99,6 @@ TEST_F(TestInternetSocket, constructor)
EXPECT_TRUE(socket);
}
TEST_F(TestInternetSocket, open_null_stack)
{
EXPECT_EQ(socket->open(NULL), NSAPI_ERROR_PARAMETER);
@ -126,34 +130,81 @@ TEST_F(TestInternetSocket, close)
EXPECT_EQ(socket->close(), NSAPI_ERROR_OK);
}
TEST_F(TestInternetSocket, close_no_open)
{
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->close(), NSAPI_ERROR_OK);
}
TEST_F(TestInternetSocket, close_during_read)
{
stack.return_value = NSAPI_ERROR_OK;
socket->open((NetworkStack *)&stack);
// when c++11 is available use something like the code below to test the blocking behavior
// socket->add_reader();
// std::async(c[](){std::this_thread::sleep_for(1ms); socket->rem_reader()});
EXPECT_EQ(socket->close(), NSAPI_ERROR_OK);
}
TEST_F(TestInternetSocket, modify_multicast_group)
{
SocketAddress a("127.0.0.1", 1024);
stack.return_value = NSAPI_ERROR_OK;
socket->open((NetworkStack *)&stack);
// when c++11 is available use something like the code below to test the blocking behavior
// socket->add_reader();
// std::async(c[](){std::this_thread::sleep_for(1ms); socket->rem_reader()});
EXPECT_EQ(socket->join_multicast_group(a), NSAPI_ERROR_UNSUPPORTED);
EXPECT_EQ(socket->leave_multicast_group(a), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestInternetSocket, set_blocking)
// set_blocking and set_timeout are tested within TCPSocket.
TEST_F(TestInternetSocket, bind_no_socket)
{
socket->set_blocking(false);
socket->set_blocking(true);
EXPECT_EQ(socket->bind(1), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestInternetSocket, bind)
{
socket->open((NetworkStack *)&stack);
EXPECT_EQ(socket->bind("127.0.0.1", 80), NSAPI_ERROR_OK);
}
TEST_F(TestInternetSocket, bind_nullstring)
{
socket->open((NetworkStack *)&stack);
EXPECT_EQ(socket->bind(NULL, 80), NSAPI_ERROR_OK);
}
// setsockopt and getsockopt are really just calling the underlying stack functions
TEST_F(TestInternetSocket, setsockopt_no_stack)
{
socket->close();
EXPECT_EQ(socket->setsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestInternetSocket, setsockopt)
{
socket->open((NetworkStack *)&stack);
EXPECT_EQ(socket->setsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestInternetSocket, getsockopt_no_stack)
{
EXPECT_EQ(socket->getsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestInternetSocket, getsockopt)
{
socket->open((NetworkStack *)&stack);
EXPECT_EQ(socket->getsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestInternetSocket, sigio)
{
callback_is_called = false;
// I'm calling sigio() through the DEPRECATED method, just to get coverage for both.
// Not sure if this is wise at all, we should not aim for 100%
socket->sigio(mbed::callback(my_callback));
socket->event();
socket->close(); // Trigger event;
EXPECT_EQ(callback_is_called, true);
}

View File

@ -17,6 +17,7 @@
#include "gtest/gtest.h"
#include "features/netsocket/NetworkInterface.h"
#include "NetworkStack_stub.h"
class stubNetworkInterface : public NetworkInterface {
virtual nsapi_error_t connect()
@ -29,8 +30,10 @@ class stubNetworkInterface : public NetworkInterface {
};
virtual NetworkStack *get_stack()
{
return NULL;
return &stack;
};
public:
NetworkStackstub stack;
};
class TestNetworkInterface : public testing::Test {
@ -53,8 +56,79 @@ TEST_F(TestNetworkInterface, constructor)
EXPECT_TRUE(iface);
}
// get_default_instance is tested along with the implementations of NetworkInterface.
TEST_F(TestNetworkInterface, get_mac_address)
{
char *n = 0;
EXPECT_EQ(iface->get_mac_address(), n);
}
TEST_F(TestNetworkInterface, get_ip_address)
{
char *n = 0;
EXPECT_EQ(iface->get_ip_address(), n);
}
TEST_F(TestNetworkInterface, get_netmask)
{
char *n = 0;
EXPECT_EQ(iface->get_netmask(), n);
}
TEST_F(TestNetworkInterface, get_gateway)
{
char *n = 0;
EXPECT_EQ(iface->get_gateway(), n);
}
TEST_F(TestNetworkInterface, set_network)
{
EXPECT_EQ(iface->set_network("127.0.0.1", "255.255.0.0", "127.0.0.1"), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestNetworkInterface, set_dhcp)
{
EXPECT_EQ(iface->set_dhcp(true), NSAPI_ERROR_OK);
EXPECT_EQ(iface->set_dhcp(false), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestNetworkInterface, gethostbyname)
{
SocketAddress a;
EXPECT_EQ(iface->gethostbyname("host", &a, NSAPI_UNSPEC), NSAPI_ERROR_OK);
}
static bool callback_is_called;
static void my_callback(nsapi_error_t result, SocketAddress *address)
{
(void)result;
(void)address;
callback_is_called = true;
}
TEST_F(TestNetworkInterface, gethostbyname_async)
{
SocketAddress a;
EXPECT_EQ(iface->gethostbyname_async("host", mbed::callback(my_callback), NSAPI_UNSPEC), NSAPI_ERROR_OK);
EXPECT_EQ(iface->gethostbyname_async_cancel(1), NSAPI_ERROR_OK);
}
TEST_F(TestNetworkInterface, add_dns_server)
{
SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(iface->add_dns_server(a), NSAPI_ERROR_OK);
}
TEST_F(TestNetworkInterface, get_connection_status)
{
EXPECT_EQ(iface->get_connection_status(), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestNetworkInterface, set_blocking)
{
EXPECT_EQ(iface->set_blocking(true), NSAPI_ERROR_UNSUPPORTED);
}
// No way to test attach as it doesn't do or return anything.

View File

@ -5,10 +5,21 @@
# Source files
set(unittest-sources
../features/netsocket/SocketAddress.cpp
../features/netsocket/NetworkStack.cpp
../features/netsocket/NetworkInterface.cpp
../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
)
# Test files
set(unittest-test-sources
stubs/Mutex_stub.cpp
stubs/mbed_assert_stub.c
stubs/equeue_stub.c
stubs/EventQueue_stub.cpp
stubs/mbed_shared_queues_stub.cpp
stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp
features/netsocket/NetworkInterface/test_NetworkInterface.cpp
)

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates
* 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.
*/
#include "gtest/gtest.h"
#include "features/netsocket/NetworkStack.h"
#include "netsocket/nsapi_dns.h"
#include "events/EventQueue.h"
#include <string>
// Control nsapi stub return value. See stubs/nsapi_dns_stub.cpp
extern nsapi_error_t nsapi_stub_return_value;
// For testing async calls which require callback
static bool callback_is_called;
static SocketAddress address_received;
static nsapi_error_t result_received;
static void my_callback(nsapi_error_t result, SocketAddress *address)
{
result_received = result;
address_received = *address;
callback_is_called = true;
}
static bool noarg_callback_is_called;
static void noarg_callback(void)
{
noarg_callback_is_called = true;
}
extern call_in_callback_cb_t callin_callback;
namespace mbed {
extern events::EventQueue *mbed_shared_queue_stub;
}
// NetworkStack is an abstract class we need to provide a child class for tests.
class NetworkStackChild : public NetworkStack {
virtual nsapi_error_t socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_error_t socket_close(nsapi_socket_t handle)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_error_t socket_bind(nsapi_socket_t handle, const SocketAddress &address)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
nsapi_socket_t *handle, SocketAddress *address = 0)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle,
const void *data, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle,
void *data, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t handle, const SocketAddress &address,
const void *data, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
void *buffer, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data)
{
}
public:
std::string ip_address;
const char *get_ip_address()
{
return ip_address.c_str();
}
};
class TestNetworkStack : public testing::Test {
protected:
NetworkStackChild *stack;
virtual void SetUp()
{
stack = new NetworkStackChild();
address_received = SocketAddress();
result_received = NSAPI_ERROR_OK;
callback_is_called = false;
noarg_callback_is_called = false;
mbed::mbed_shared_queue_stub = 0;
}
virtual void TearDown()
{
delete stack;
if (mbed::mbed_shared_queue_stub)
{
delete mbed::mbed_shared_queue_stub;
mbed::mbed_shared_queue_stub = 0;
}
}
void SetUpQueue()
{
mbed::mbed_shared_queue_stub = new events::EventQueue();
}
};
TEST_F(TestNetworkStack, constructor)
{
EXPECT_TRUE(stack);
}
TEST_F(TestNetworkStack, get_ip_address_default)
{
EXPECT_EQ(stack->NetworkStack::get_ip_address(), (char*)NULL);
}
/* gethostbyname */
TEST_F(TestNetworkStack, gethostbyname)
{
SocketAddress a;
stack->ip_address = std::string("127.0.0.1");
EXPECT_EQ(stack->gethostbyname("host", &a, NSAPI_UNSPEC), NSAPI_ERROR_DNS_FAILURE);
}
TEST_F(TestNetworkStack, gethostbyname_simple_address)
{
SocketAddress a;
EXPECT_EQ(stack->gethostbyname("127.0.0.1", &a, NSAPI_UNSPEC), NSAPI_ERROR_OK);
}
TEST_F(TestNetworkStack, gethostbyname_simple_address_right_version)
{
SocketAddress a;
EXPECT_EQ(stack->gethostbyname("127.0.0.1", &a, NSAPI_IPv4), NSAPI_ERROR_OK);
}
TEST_F(TestNetworkStack, gethostbyname_simple_address_wrong_version)
{
SocketAddress a;
EXPECT_EQ(stack->gethostbyname("127.0.0.1", &a, NSAPI_IPv6), NSAPI_ERROR_DNS_FAILURE);
}
TEST_F(TestNetworkStack, gethostbyname_empty_host)
{
SocketAddress a;
EXPECT_EQ(stack->gethostbyname("", &a, NSAPI_UNSPEC), NSAPI_ERROR_PARAMETER);
}
/* gethostbyname_async */
TEST_F(TestNetworkStack, gethostbyname_async_delay)
{
SocketAddress a;
stack->ip_address = std::string("127.0.0.1");
SetUpQueue();
EXPECT_EQ(stack->gethostbyname_async("localhost", mbed::callback(my_callback), NSAPI_UNSPEC), NSAPI_ERROR_DNS_FAILURE);
EXPECT_EQ(callin_callback(1, mbed::callback(noarg_callback)), NSAPI_ERROR_OK);
EXPECT_TRUE(noarg_callback_is_called);
EXPECT_FALSE(callback_is_called);
}
TEST_F(TestNetworkStack, gethostbyname_async)
{
SocketAddress a;
stack->ip_address = std::string("127.0.0.1");
SetUpQueue();
EXPECT_EQ(stack->gethostbyname_async("localhost", mbed::callback(my_callback), NSAPI_UNSPEC), NSAPI_ERROR_DNS_FAILURE);
EXPECT_EQ(callin_callback(0, mbed::callback(noarg_callback)), NSAPI_ERROR_OK);
EXPECT_TRUE(noarg_callback_is_called);
EXPECT_FALSE(callback_is_called);
}
TEST_F(TestNetworkStack, gethostbyname_async_eventqueue_simple_address)
{
SocketAddress a;
stack->ip_address = std::string("127.0.0.1");
EXPECT_EQ(stack->gethostbyname_async("127.0.0.1", mbed::callback(my_callback), NSAPI_IPv6), NSAPI_ERROR_DNS_FAILURE);
EXPECT_FALSE(callback_is_called);
EXPECT_EQ(stack->gethostbyname_async("127.0.0.1", mbed::callback(my_callback), NSAPI_IPv4), NSAPI_ERROR_OK);
EXPECT_TRUE(callback_is_called);
EXPECT_EQ(result_received, NSAPI_ERROR_OK);
EXPECT_EQ(std::string(address_received.get_ip_address()), stack->ip_address);
}
TEST_F(TestNetworkStack, gethostbyname_async_empty_host)
{
SocketAddress a;
EXPECT_EQ(stack->gethostbyname_async("", mbed::callback(my_callback), NSAPI_UNSPEC), NSAPI_ERROR_PARAMETER);
}
TEST_F(TestNetworkStack, getstackopt)
{
EXPECT_EQ(stack->getstackopt(0,0,0,0), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestNetworkStack, setstackopt)
{
EXPECT_EQ(stack->setstackopt(0,0,0,0), NSAPI_ERROR_UNSUPPORTED);
}

View File

@ -0,0 +1,28 @@
####################
# UNIT TESTS
####################
# Unit test suite name
set(TEST_SUITE_NAME "features_netsocket_NetworkStack")
# Source files
set(unittest-sources
../features/netsocket/SocketAddress.cpp
../features/netsocket/NetworkStack.cpp
../features/netsocket/NetworkInterface.cpp
../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
)
# Test files
set(unittest-test-sources
stubs/Mutex_stub.cpp
stubs/mbed_assert_stub.c
stubs/equeue_stub.c
stubs/EventQueue_stub.cpp
stubs/mbed_shared_queues_stub.cpp
stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp
features/netsocket/NetworkStack/test_NetworkStack.cpp
)

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates
* 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.
*/
#include "gtest/gtest.h"
#include "features/netsocket/TCPSocket.h"
#include "features/netsocket/TCPServer.h"
#include "NetworkStack_stub.h"
// Control the rtos EventFlags stub. See EventFlags_stub.cpp
extern std::list<uint32_t> eventFlagsStubNextRetval;
class TestTCPServer : public testing::Test {
public:
unsigned int dataSize = 10;
char dataBuf[10];
protected:
TCPSocket *socket;
TCPServer *server;
NetworkStackstub stack;
virtual void SetUp()
{
server = new TCPServer();
socket = new TCPSocket();
}
virtual void TearDown()
{
stack.return_values.clear();
eventFlagsStubNextRetval.clear();
delete socket;
delete server;
}
};
TEST_F(TestTCPServer, constructor)
{
EXPECT_TRUE(server);
}
TEST_F(TestTCPServer, constructor_parameters)
{
TCPServer serverParam = TCPServer(dynamic_cast<NetworkStack*>(&stack));
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(serverParam.connect(a), NSAPI_ERROR_OK);
}
TEST_F(TestTCPServer, accept)
{
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->open(static_cast<NetworkStack *>(&stack)), NSAPI_ERROR_OK);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_OK);
nsapi_error_t error;
EXPECT_EQ(server->open(static_cast<NetworkStack *>(&stack)), NSAPI_ERROR_OK);
EXPECT_EQ(server->bind(a), NSAPI_ERROR_OK);
server->listen(1);
SocketAddress client_addr;
EXPECT_EQ(server->accept(socket, &client_addr), NSAPI_ERROR_OK);
}
TEST_F(TestTCPServer, accept_no_socket)
{
SocketAddress client_addr;
EXPECT_EQ(server->accept(socket, &client_addr), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestTCPServer, accept_error)
{
SocketAddress client_addr;
EXPECT_EQ(server->open(static_cast<NetworkStack *>(&stack)), NSAPI_ERROR_OK);
stack.return_value = NSAPI_ERROR_AUTH_FAILURE;
EXPECT_EQ(server->accept(socket, &client_addr), NSAPI_ERROR_AUTH_FAILURE);
}
TEST_F(TestTCPServer, accept_error_would_block)
{
SocketAddress client_addr;
EXPECT_EQ(server->open(static_cast<NetworkStack *>(&stack)), NSAPI_ERROR_OK);
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
eventFlagsStubNextRetval.push_back(0);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(server->accept(socket, &client_addr), NSAPI_ERROR_WOULD_BLOCK);
}

View File

@ -0,0 +1,28 @@
####################
# UNIT TESTS
####################
# Unit test suite name
set(TEST_SUITE_NAME "features_netsocket_TCPServer")
set(unittest-sources
../features/netsocket/SocketAddress.cpp
../features/netsocket/NetworkStack.cpp
../features/netsocket/InternetSocket.cpp
../features/netsocket/TCPSocket.cpp
../features/netsocket/TCPServer.cpp
../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
)
set(unittest-test-sources
stubs/Mutex_stub.cpp
stubs/mbed_assert_stub.c
stubs/equeue_stub.c
stubs/EventQueue_stub.cpp
stubs/mbed_shared_queues_stub.cpp
stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp
features/netsocket/TCPServer/test_TCPServer.cpp
)

View File

@ -17,10 +17,24 @@
#include "gtest/gtest.h"
#include "features/netsocket/TCPSocket.h"
#include "NetworkStack_stub.h"
// Control the rtos EventFlags stub. See EventFlags_stub.cpp
extern std::list<uint32_t> eventFlagsStubNextRetval;
// To test protected functions
class TCPSocketFriend : public TCPSocket {
friend class TestTCPSocket;
FRIEND_TEST(TestTCPSocket, get_proto);
};
class TestTCPSocket : public testing::Test {
public:
unsigned int dataSize = 10;
char dataBuf[10];
protected:
TCPSocket *socket;
NetworkStackstub stack;
virtual void SetUp()
{
@ -29,11 +43,245 @@ protected:
virtual void TearDown()
{
stack.return_values.clear();
eventFlagsStubNextRetval.clear();
delete socket;
}
};
TEST_F(TestTCPSocket, get_proto)
{
TCPSocketFriend tcpFriend;
EXPECT_EQ(tcpFriend.get_proto(), NSAPI_TCP);
}
TEST_F(TestTCPSocket, constructor)
{
EXPECT_TRUE(socket);
}
TEST_F(TestTCPSocket, constructor_parameters)
{
TCPSocket socketParam = TCPSocket(dynamic_cast<NetworkStack*>(&stack));
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socketParam.connect(a), NSAPI_ERROR_OK);
}
/* connect */
TEST_F(TestTCPSocket, connect)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_OK;
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_OK);
}
TEST_F(TestTCPSocket, connect_no_open)
{
stack.return_value = NSAPI_ERROR_OK;
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestTCPSocket, connect_error_in_progress_no_timeout)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_IN_PROGRESS;
const SocketAddress a("127.0.0.1", 1024);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_IN_PROGRESS);
}
TEST_F(TestTCPSocket, connect_with_timeout)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_IN_PROGRESS;
const SocketAddress a("127.0.0.1", 1024);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
socket->set_blocking(true);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_IN_PROGRESS);
}
TEST_F(TestTCPSocket, connect_error_is_connected)
{
socket->open((NetworkStack *)&stack);
stack.return_values.push_back(NSAPI_ERROR_ALREADY);
stack.return_values.push_back(NSAPI_ERROR_IS_CONNECTED);
const SocketAddress a("127.0.0.1", 1024);
socket->set_timeout(1);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_OK);
}
TEST_F(TestTCPSocket, connect_by_name_and_port)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->connect("testhost", 80), NSAPI_ERROR_OK);
}
TEST_F(TestTCPSocket, connect_by_name_and_port_dns_fail)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_DNS_FAILURE;
EXPECT_EQ(socket->connect("testhost", 80), NSAPI_ERROR_DNS_FAILURE);
}
/* send */
TEST_F(TestTCPSocket, send_no_open)
{
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->send(dataBuf, dataSize), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestTCPSocket, send_in_one_chunk)
{
socket->open((NetworkStack *)&stack);
stack.return_value = dataSize;
EXPECT_EQ(socket->send(dataBuf, dataSize), dataSize);
}
TEST_F(TestTCPSocket, send_in_two_chunks)
{
socket->open((NetworkStack *)&stack);
stack.return_values.push_back(4);
stack.return_values.push_back(dataSize - 4);
EXPECT_EQ(socket->send(dataBuf, dataSize), dataSize);
}
TEST_F(TestTCPSocket, send_error_would_block)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(socket->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
}
TEST_F(TestTCPSocket, send_error_other)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_NO_MEMORY;
EXPECT_EQ(socket->send(dataBuf, dataSize), NSAPI_ERROR_NO_MEMORY);
}
TEST_F(TestTCPSocket, send_error_no_timeout)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
socket->set_blocking(false);
EXPECT_EQ(socket->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
}
TEST_F(TestTCPSocket, send_to)
{
socket->open((NetworkStack *)&stack);
stack.return_value = 10;
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->sendto(a, dataBuf, dataSize), dataSize);
}
/* recv */
TEST_F(TestTCPSocket, recv_no_open)
{
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->recv(dataBuf, dataSize), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestTCPSocket, recv_all_data)
{
socket->open((NetworkStack *)&stack);
stack.return_value = dataSize;
EXPECT_EQ(socket->recv(dataBuf, dataSize), dataSize);
}
TEST_F(TestTCPSocket, recv_less_than_expected)
{
socket->open((NetworkStack *)&stack);
unsigned int lessThanDataSize = dataSize -1;
stack.return_values.push_back(lessThanDataSize);
EXPECT_EQ(socket->recv(dataBuf, dataSize), lessThanDataSize);
}
TEST_F(TestTCPSocket, recv_would_block)
{
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
eventFlagsStubNextRetval.push_back(0);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(socket->recv(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
}
TEST_F(TestTCPSocket, recv_from_no_socket)
{
stack.return_value = NSAPI_ERROR_OK;
SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->recvfrom(&a, dataBuf, dataSize), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestTCPSocket, recv_from)
{
stack.return_value = NSAPI_ERROR_OK;
SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_OK);
SocketAddress b;
EXPECT_EQ(socket->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK);
EXPECT_EQ(a, b);
}
TEST_F(TestTCPSocket, recv_from_null)
{
stack.return_value = NSAPI_ERROR_OK;
SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_OK);
EXPECT_EQ(socket->recvfrom(NULL, dataBuf, dataSize), NSAPI_ERROR_OK);
}
/* listen */
TEST_F(TestTCPSocket, listen_no_open)
{
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->listen(1), NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestTCPSocket, listen)
{
stack.return_value = NSAPI_ERROR_OK;
socket->open((NetworkStack *)&stack);
EXPECT_EQ(socket->listen(1), NSAPI_ERROR_OK);
}
/* these tests will have to be readjusted after TCPServer is deprecated. */
TEST_F(TestTCPSocket, accept_no_open)
{
nsapi_error_t error;
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->accept(&error), static_cast<TCPSocket*>(NULL));
EXPECT_EQ(error, NSAPI_ERROR_NO_SOCKET);
}
TEST_F(TestTCPSocket, accept)
{
nsapi_error_t error;
stack.return_value = NSAPI_ERROR_OK;
socket->open((NetworkStack *)&stack);
EXPECT_NE(socket->accept(&error), static_cast<TCPSocket*>(NULL));
EXPECT_EQ(error, NSAPI_ERROR_OK);
}
TEST_F(TestTCPSocket, accept_would_block)
{
nsapi_error_t error;
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
eventFlagsStubNextRetval.push_back(0);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(socket->accept(&error), static_cast<TCPSocket*>(NULL));
EXPECT_EQ(error, NSAPI_ERROR_WOULD_BLOCK);
}

View File

@ -5,6 +5,7 @@
set(unittest-sources
../features/netsocket/SocketAddress.cpp
../features/netsocket/NetworkStack.cpp
../features/netsocket/InternetSocket.cpp
../features/netsocket/TCPSocket.cpp
../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
@ -15,6 +16,10 @@ set(unittest-test-sources
features/netsocket/TCPSocket/test_TCPSocket.cpp
stubs/Mutex_stub.cpp
stubs/mbed_assert_stub.c
stubs/equeue_stub.c
stubs/EventQueue_stub.cpp
stubs/mbed_shared_queues_stub.cpp
stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp
stubs/stoip4_stub.c
stubs/ip4tos_stub.c

View File

@ -26,21 +26,25 @@
* following the documentation of google test.
* [*](https://github.com/google/googletest/blob/master/googletest/docs/advanced.md)
*/
class stubUDPSocket : public UDPSocket {
class UDPSocketFriend : public UDPSocket {
friend class TestUDPSocket;
FRIEND_TEST(TestUDPSocket, get_proto);
};
// Control the rtos EventFlags stub. See EventFlags_stub.cpp
extern std::list<uint32_t> eventFlagsStubNextRetval;
class TestUDPSocket : public testing::Test {
protected:
stubUDPSocket *socket;
UDPSocket *socket;
NetworkStackstub stack;
unsigned int dataSize = 10;
char dataBuf[10];
virtual void SetUp()
{
socket = new stubUDPSocket;
socket = new UDPSocket;
stack.return_value = NSAPI_ERROR_OK;
socket->open((NetworkStack *)&stack);
}
virtual void TearDown()
@ -51,31 +55,97 @@ protected:
TEST_F(TestUDPSocket, get_proto)
{
EXPECT_EQ(socket->get_proto(), NSAPI_UDP);
UDPSocketFriend udpFriend;
EXPECT_EQ(udpFriend.get_proto(), NSAPI_UDP);
}
TEST_F(TestUDPSocket, sendto_addr_port)
{
// The code below causes a segfault. Should we add a check?
//EXPECT_EQ(socket->sendto("127.0.0.1", 0, 0, 0), NSAPI_ERROR_NO_SOCKET);
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socket->sendto(a, 0, 0), NSAPI_ERROR_NO_SOCKET);
socket->open((NetworkStack *)&stack);
stack.return_value = NSAPI_ERROR_PARAMETER;
EXPECT_EQ(socket->sendto("127.0.0.1", 0, 0, 0), NSAPI_ERROR_DNS_FAILURE);
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->sendto("127.0.0.1", 0, 0, 0), 0);
}
TEST_F(TestUDPSocket, sendto)
TEST_F(TestUDPSocket, connect)
{
SocketAddress addr("127.0.0.1", 1024);
stack.return_value = NSAPI_ERROR_OK;
const nsapi_addr_t addr = {NSAPI_IPv4, {127,0,0,1} };
const SocketAddress a(addr, 1024);
socket->open((NetworkStack *)&stack);
EXPECT_EQ(socket->send(dataBuf, dataSize), NSAPI_ERROR_NO_ADDRESS);
EXPECT_EQ(socket->connect(a), NSAPI_ERROR_OK);
stack.return_value = 100;
EXPECT_EQ(socket->send(dataBuf, dataSize), 100);
}
TEST_F(TestUDPSocket, sendto_timeout)
{
const nsapi_addr_t saddr = {NSAPI_IPv4, {127,0,0,1} };
const SocketAddress addr(saddr, 1024);
socket->open((NetworkStack *)&stack);
stack.return_value = 100;
EXPECT_EQ(socket->sendto(addr, 0, 100), 100);
socket->set_timeout(0);
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
eventFlagsStubNextRetval.push_back(0);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(socket->sendto(addr, 0, 100), NSAPI_ERROR_WOULD_BLOCK);
socket->set_timeout(-1);
stack.return_value = NSAPI_ERROR_NO_CONNECTION;
EXPECT_EQ(socket->sendto(addr, 0, 100), NSAPI_ERROR_NO_CONNECTION);
stack.return_value = NSAPI_ERROR_NO_MEMORY;
socket->set_timeout(1);
EXPECT_EQ(socket->sendto(addr, 0, 100), NSAPI_ERROR_NO_MEMORY);
}
TEST_F(TestUDPSocket, recv)
{
EXPECT_EQ(socket->recv(&dataBuf, dataSize), NSAPI_ERROR_NO_SOCKET);
socket->open((NetworkStack *)&stack);
stack.return_value = 100;
EXPECT_EQ(socket->recv(&dataBuf, dataSize), 100);
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
eventFlagsStubNextRetval.push_back(0);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(socket->recv(&dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
}
TEST_F(TestUDPSocket, recv_address_filtering)
{
socket->open((NetworkStack *)&stack);
const nsapi_addr_t addr1 = {NSAPI_IPv4, {127,0,0,1} };
const nsapi_addr_t addr2 = {NSAPI_IPv4, {127,0,0,2} };
SocketAddress a1(addr1, 1024);
SocketAddress a2(addr2, 1024);
EXPECT_EQ(socket->connect(a1), NSAPI_ERROR_OK);
stack.return_values.push_back(100); //This will not return, because wrong address is used.
stack.return_values.push_back(NSAPI_ERROR_NO_MEMORY); //Break the loop of waiting for data from a1.
EXPECT_EQ(socket->recvfrom(&a2, &dataBuf, dataSize), NSAPI_ERROR_NO_MEMORY);
stack.return_values.push_back(100);
EXPECT_EQ(socket->recvfrom(&a1, &dataBuf, dataSize), 100);
}
TEST_F(TestUDPSocket, unsupported_api)
{
nsapi_error_t error;
EXPECT_EQ(socket->accept(&error), static_cast<Socket *>(NULL));
EXPECT_EQ(error, NSAPI_ERROR_UNSUPPORTED);
EXPECT_EQ(socket->listen(1), NSAPI_ERROR_UNSUPPORTED);
}

View File

@ -17,6 +17,10 @@
#include <cstddef>
#include "rtos/EventFlags.h"
#include <list>
/** Store the next value to be returned by Event Flags member functions */
std::list<uint32_t> eventFlagsStubNextRetval;
rtos::EventFlags::EventFlags() {}
rtos::EventFlags::~EventFlags() {}
@ -38,5 +42,11 @@ uint32_t rtos::EventFlags::wait_all(uint32_t flags, uint32_t timeout, bool clear
}
uint32_t rtos::EventFlags::wait_any(uint32_t flags, uint32_t timeout, bool clear)
{
if (!eventFlagsStubNextRetval.empty())
{
uint32_t ret = eventFlagsStubNextRetval.front();
eventFlagsStubNextRetval.pop_front();
return ret;
}
return 0;
}

View File

@ -19,10 +19,11 @@
#define NETWORKSTACKSTUB_H
#include "netsocket/NetworkStack.h"
#include <list>
class NetworkStackstub : public NetworkStack {
public:
std::list<nsapi_error_t> return_values;
nsapi_error_t return_value = 0;
virtual const char *get_ip_address()
{
@ -46,6 +47,11 @@ public:
protected:
virtual nsapi_error_t socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
{
if (return_value == NSAPI_ERROR_OK && return_values.front() == NSAPI_ERROR_OK)
{
// Make sure a non-NULL value is returned if error is not expected
*handle = reinterpret_cast<nsapi_socket_t*>(1234);
}
return return_value;
};
virtual nsapi_error_t socket_close(nsapi_socket_t handle)
@ -62,6 +68,12 @@ protected:
};
virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address)
{
if (!return_values.empty())
{
nsapi_error_t ret = return_values.front();
return_values.pop_front();
return ret;
}
return return_value;
};
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
@ -72,11 +84,23 @@ protected:
virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle,
const void *data, nsapi_size_t size)
{
if (!return_values.empty())
{
nsapi_error_t ret = return_values.front();
return_values.pop_front();
return ret;
}
return return_value;
};
virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle,
void *data, nsapi_size_t size)
{
if (!return_values.empty())
{
nsapi_error_t ret = return_values.front();
return_values.pop_front();
return ret;
}
return return_value;
};
virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t handle, const SocketAddress &address,
@ -87,6 +111,12 @@ protected:
virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
void *buffer, nsapi_size_t size)
{
if (!return_values.empty())
{
nsapi_error_t ret = return_values.front();
return_values.pop_front();
return ret;
}
return return_value;
};
virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) {};

View File

@ -16,6 +16,7 @@
*/
#include "equeue.h"
#include <stdlib.h>
int equeue_create(equeue_t *queue, size_t size)
{
@ -47,11 +48,6 @@ int equeue_call(equeue_t *queue, void (*cb)(void *), void *data)
return 0;
}
int equeue_call_in(equeue_t *queue, int ms, void (*cb)(void *), void *data)
{
return 0;
}
int equeue_call_every(equeue_t *queue, int ms, void (*cb)(void *), void *data)
{
return 0;
@ -59,7 +55,7 @@ int equeue_call_every(equeue_t *queue, int ms, void (*cb)(void *), void *data)
void *equeue_alloc(equeue_t *queue, size_t size)
{
return NULL;
return malloc(size);
}
void equeue_dealloc(equeue_t *queue, void *event)
@ -84,6 +80,12 @@ void equeue_event_dtor(void *event, void (*dtor)(void *))
int equeue_post(equeue_t *queue, void (*cb)(void *), void *event)
{
if (cb)
{
cb(event);
free(event);
return 1; //Fake ID for calling cancel
}
return 0;
}
@ -102,3 +104,8 @@ void equeue_chain(equeue_t *queue, equeue_t *target)
{
}
int equeue_call_in(equeue_t *q, int ms, void (*cb)(void*), void *data) {
// The stub does not implement the delay mechanism.
return equeue_post(q, cb, data);
}

View File

@ -21,8 +21,9 @@ using namespace events;
namespace mbed {
EventQueue *mbed_shared_queue_stub;
EventQueue *mbed_event_queue()
{
return 0;
return mbed_shared_queue_stub;
}
} // namespace mbed

View File

@ -19,6 +19,8 @@
nsapi_error_t nsapi_stub_return_value = NSAPI_ERROR_DNS_FAILURE;
NetworkStack::hostbyname_cb_t query_callback;
call_in_callback_cb_t callin_callback;
nsapi_error_t nsapi_dns_query(NetworkStack *stack, const char *host,
SocketAddress *addr, nsapi_version_t version)
@ -30,6 +32,8 @@ nsapi_error_t nsapi_dns_query_async(NetworkStack *stack, const char *host,
NetworkStack::hostbyname_cb_t callback, call_in_callback_cb_t call_in_cb,
nsapi_version_t version)
{
query_callback = callback;
callin_callback = call_in_cb;
return nsapi_stub_return_value;
}