Add socketstats stub functions for unittest and addressed reviews

pull/8592/head
deepikabhavnani 2018-11-18 20:41:03 -06:00
parent f6c1a40b29
commit 117eb0bc87
17 changed files with 151 additions and 62 deletions

View File

@ -183,18 +183,26 @@ void UDPSOCKET_ECHOTEST_NONBLOCK()
} }
free(stack_mem); free(stack_mem);
#ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
TEST_ASSERT_EQUAL(1, fetch_stats());
TEST_ASSERT_EQUAL(NSAPI_UDP, udp_stats[0].proto);
TEST_ASSERT(udp_stats[0].sent_bytes != 0);
TEST_ASSERT(udp_stats[0].recv_bytes != 0);
#endif
// Packet loss up to 30% tolerated // Packet loss up to 30% tolerated
if (packets_sent > 0) { if (packets_sent > 0) {
double loss_ratio = 1 - ((double)packets_recv / (double)packets_sent); double loss_ratio = 1 - ((double)packets_recv / (double)packets_sent);
printf("Packets sent: %d, packets received %d, loss ratio %.2lf\r\n", packets_sent, packets_recv, loss_ratio); printf("Packets sent: %d, packets received %d, loss ratio %.2lf\r\n", packets_sent, packets_recv, loss_ratio);
TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio); TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio);
#ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
count = fetch_stats();
for (j = 0; j < count; j++) {
if ((NSAPI_UDP == udp_stats[j].proto) && (SOCK_OPEN == udp_stats[j].state)) {
TEST_ASSERT(udp_stats[j].sent_bytes != 0);
TEST_ASSERT(udp_stats[j].recv_bytes != 0);
break;
}
}
loss_ratio = 1 - ((double)udp_stats[j].recv_bytes / (double)udp_stats[j].sent_bytes);
printf("Bytes sent: %d, bytes received %d, loss ratio %.2lf\r\n", udp_stats[j].sent_bytes, udp_stats[j].recv_bytes, loss_ratio);
TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio);
#endif
} }
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close()); TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
} }

View File

@ -33,4 +33,5 @@ set(unittest-test-sources
stubs/stoip4_stub.c stubs/stoip4_stub.c
stubs/ip4tos_stub.c stubs/ip4tos_stub.c
stubs/NetworkStack_stub.cpp stubs/NetworkStack_stub.cpp
stubs/SocketStats_Stub.cpp
) )

View File

@ -25,4 +25,5 @@ set(unittest-test-sources
stubs/EventFlags_stub.cpp stubs/EventFlags_stub.cpp
stubs/stoip4_stub.c stubs/stoip4_stub.c
stubs/ip4tos_stub.c stubs/ip4tos_stub.c
stubs/SocketStats_Stub.cpp
) )

View File

@ -25,4 +25,5 @@ set(unittest-test-sources
stubs/nsapi_dns_stub.cpp stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp stubs/EventFlags_stub.cpp
features/netsocket/NetworkInterface/test_NetworkInterface.cpp features/netsocket/NetworkInterface/test_NetworkInterface.cpp
stubs/SocketStats_Stub.cpp
) )

View File

@ -28,4 +28,5 @@ set(unittest-test-sources
stubs/nsapi_dns_stub.cpp stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp stubs/EventFlags_stub.cpp
features/netsocket/NetworkStack/test_NetworkStack.cpp features/netsocket/NetworkStack/test_NetworkStack.cpp
stubs/SocketStats_Stub.cpp
) )

View File

@ -28,4 +28,5 @@ set(unittest-test-sources
stubs/nsapi_dns_stub.cpp stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp stubs/EventFlags_stub.cpp
features/netsocket/TCPServer/test_TCPServer.cpp features/netsocket/TCPServer/test_TCPServer.cpp
stubs/SocketStats_Stub.cpp
) )

View File

@ -26,4 +26,5 @@ set(unittest-test-sources
stubs/EventFlags_stub.cpp stubs/EventFlags_stub.cpp
stubs/stoip4_stub.c stubs/stoip4_stub.c
stubs/ip4tos_stub.c stubs/ip4tos_stub.c
stubs/SocketStats_Stub.cpp
) )

View File

@ -26,4 +26,5 @@ set(unittest-test-sources
stubs/nsapi_dns_stub.cpp stubs/nsapi_dns_stub.cpp
stubs/stoip4_stub.c stubs/stoip4_stub.c
stubs/ip4tos_stub.c stubs/ip4tos_stub.c
stubs/SocketStats_Stub.cpp
) )

View File

@ -0,0 +1,61 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 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.
*/
#include "SocketStats.h"
int SocketStats::get_entry_position(const Socket *const reference_id)
{
return 0;
}
size_t SocketStats::mbed_stats_socket_get_each(mbed_stats_socket_t *stats, size_t count)
{
return 0;
}
SocketStats::SocketStats()
{
}
void SocketStats::stats_new_socket_entry(const Socket *const reference_id)
{
return;
}
void SocketStats::stats_update_socket_state(const Socket *const reference_id, socket_state state)
{
return;
}
void SocketStats::stats_update_peer(const Socket *const reference_id, const SocketAddress &peer)
{
return;
}
void SocketStats::stats_update_proto(const Socket *const reference_id, nsapi_protocol_t proto)
{
return;
}
void SocketStats::stats_update_sent_bytes(const Socket *const reference_id, size_t sent_bytes)
{
return;
}
void SocketStats::stats_update_recv_bytes(const Socket *const reference_id, size_t recv_bytes)
{
return;
}

View File

@ -24,6 +24,7 @@ InternetSocket::InternetSocket()
_readers(0), _writers(0), _pending(0), _readers(0), _writers(0), _pending(0),
_factory_allocated(false) _factory_allocated(false)
{ {
_socket_stats.stats_new_socket_entry(this);
} }
InternetSocket::~InternetSocket() InternetSocket::~InternetSocket()
@ -48,6 +49,7 @@ nsapi_error_t InternetSocket::open(NetworkStack *stack)
return err; return err;
} }
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
_socket = socket; _socket = socket;
_event = callback(this, &InternetSocket::event); _event = callback(this, &InternetSocket::event);
_stack->socket_attach(_socket, Callback<void()>::thunk, &_event); _stack->socket_attach(_socket, Callback<void()>::thunk, &_event);
@ -72,7 +74,7 @@ nsapi_error_t InternetSocket::close()
_socket = 0; _socket = 0;
ret = _stack->socket_close(socket); ret = _stack->socket_close(socket);
_stack = 0; // Invalidate the stack pointer - otherwise open() fails. _stack = 0; // Invalidate the stack pointer - otherwise open() fails.
_socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
// Wakeup anything in a blocking operation // Wakeup anything in a blocking operation
// on this socket // on this socket
event(); event();

View File

@ -140,7 +140,7 @@ void SocketStats::stats_update_sent_bytes(const Socket *const reference_id, size
#ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE #ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
_mutex->lock(); _mutex->lock();
int position = get_entry_position(reference_id); int position = get_entry_position(reference_id);
if ((position >= 0) && (sent_bytes > 0)) { if ((position >= 0) && ((int32_t)sent_bytes > 0)) {
_stats[position].sent_bytes += sent_bytes; _stats[position].sent_bytes += sent_bytes;
} }
_mutex->unlock(); _mutex->unlock();
@ -152,7 +152,7 @@ void SocketStats::stats_update_recv_bytes(const Socket *const reference_id, size
#ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE #ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
_mutex->lock(); _mutex->lock();
int position = get_entry_position(reference_id); int position = get_entry_position(reference_id);
if ((position >= 0) && (recv_bytes > 0)) { if ((position >= 0) && ((int32_t)recv_bytes > 0)) {
_stats[position].recv_bytes += recv_bytes; _stats[position].recv_bytes += recv_bytes;
} }
_mutex->unlock(); _mutex->unlock();

View File

@ -27,6 +27,12 @@
#define MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT 10 #define MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT 10
#endif #endif
/** Enum of socket states
*
* Can be used to specify current state of socket - Open / Close / Connected / Listen
*
* @enum socket_state
*/
typedef enum { typedef enum {
SOCK_CLOSED, /**< Socket is closed and does not exist anymore in the system */ SOCK_CLOSED, /**< Socket is closed and does not exist anymore in the system */
SOCK_OPEN, /**< Socket is open, but not associated to any peer address */ SOCK_OPEN, /**< Socket is open, but not associated to any peer address */
@ -34,6 +40,8 @@ typedef enum {
SOCK_LISTEN, /**< Socket is listening for incoming connections */ SOCK_LISTEN, /**< Socket is listening for incoming connections */
} socket_state; } socket_state;
/** Structure to parse socket statistics
*/
typedef struct { typedef struct {
Socket *reference_id; /**< Used for identifying socket */ Socket *reference_id; /**< Used for identifying socket */
SocketAddress peer; /**< Last associated peername of this socket (Destination address) */ SocketAddress peer; /**< Last associated peername of this socket (Destination address) */
@ -51,6 +59,7 @@ typedef struct {
class SocketStats { class SocketStats {
public: public:
#if !defined(DOXYGEN_ONLY)
/** Create an socket statictics object /** Create an socket statictics object
* *
* Application users must not create class objects. * Application users must not create class objects.
@ -62,7 +71,7 @@ public:
virtual ~SocketStats() virtual ~SocketStats()
{ {
} }
#endif
/** /**
* Fill the passed array of structures with the socket statistics for each created socket. * Fill the passed array of structures with the socket statistics for each created socket.
* *
@ -76,26 +85,62 @@ public:
*/ */
static size_t mbed_stats_socket_get_each(mbed_stats_socket_t *stats, size_t count); static size_t mbed_stats_socket_get_each(mbed_stats_socket_t *stats, size_t count);
#if !defined(DOXYGEN_ONLY)
/** Add entry of newly created socket in statistics array. /** Add entry of newly created socket in statistics array.
@Note: Entry in the array will be maintained even after socket is closed. * API used by socket (TCP / UDP) layers only, not to be used by application.
Entry will be over-written for sockets which were closed first, in case *
we socket creation count exceeds `MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT`. * @param reference_id Id to identify socket in data array.
*/ *
* @Note: Entry in the array will be maintained even after socket is closed.
* Entry will be over-written for sockets which were closed first, in case
* we socket creation count exceeds `MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT`.
*
*/
void stats_new_socket_entry(const Socket *const reference_id); void stats_new_socket_entry(const Socket *const reference_id);
/** Updates the state of socket and along with that records tick_last_change */ /** Updates the state of socket and along with that records tick_last_change.
* API used by socket (TCP / UDP) layers only, not to be used by application.
*
* @param reference_id Id to identify socket in data array.
* @param state Parameter to update current state of socket.
*
*/
void stats_update_socket_state(const Socket *const reference_id, socket_state state); void stats_update_socket_state(const Socket *const reference_id, socket_state state);
/** Update the peer information of the socket */ /** Update the peer information of the socket.
* API used by socket (TCP / UDP) layers only, not to be used by application.
*
* @param reference_id Id to identify socket in data array.
* @param peer Parameter to update destination peer information
*
*/
void stats_update_peer(const Socket *const reference_id, const SocketAddress &peer); void stats_update_peer(const Socket *const reference_id, const SocketAddress &peer);
/** Update socket protocol */ /** Update socket protocol.
* API used by socket (TCP / UDP) layers only, not to be used by application.
*
* @param reference_id Id to identify socket in data array.
* @param proto Parameter to update the protocol type of socket.
*
*/
void stats_update_proto(const Socket *const reference_id, nsapi_protocol_t proto); void stats_update_proto(const Socket *const reference_id, nsapi_protocol_t proto);
/** Update bytes sent on socket, which is cumulative count per socket */ /** Update bytes sent on socket, which is cumulative count per socket.
* API used by socket (TCP / UDP) layers only, not to be used by application.
*
* @param reference_id Id to identify socket in data array.
* @param sent_bytes Parameter to append bytes sent over the socket.
*
*/
void stats_update_sent_bytes(const Socket *const reference_id, size_t sent_bytes); void stats_update_sent_bytes(const Socket *const reference_id, size_t sent_bytes);
/** Update bytes received on socket, which is cumulative count per socket */ /** Update bytes received on socket, which is cumulative count per socket
* API used by socket (TCP / UDP) layers only, not to be used by application.
*
* @param reference_id Id to identify socket in data array.
* @param recv_bytes Parameter to append bytes received by the socket
*
*/
void stats_update_recv_bytes(const Socket *const reference_id, size_t recv_bytes); void stats_update_recv_bytes(const Socket *const reference_id, size_t recv_bytes);
#ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE #ifdef MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
@ -105,10 +150,13 @@ private:
static uint32_t _size; static uint32_t _size;
/** Internal function to scan the array and get position of element in the list. /** Internal function to scan the array and get position of element in the list.
This API locks the mutex and the next API call updating the entry in the array *
should release the lock */ * @param reference_id Id to identify socket in data array.
*
*/
int get_entry_position(const Socket *const reference_id); int get_entry_position(const Socket *const reference_id);
#endif #endif
#endif
}; };
#endif #endif

View File

@ -20,12 +20,11 @@ using mbed::Callback;
TCPServer::TCPServer() TCPServer::TCPServer()
{ {
_socket_stats.stats_new_socket_entry(this); _socket_stats.stats_update_proto(this, NSAPI_TCP);
} }
TCPServer::~TCPServer() TCPServer::~TCPServer()
{ {
_socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
} }
nsapi_error_t TCPServer::accept(TCPSocket *connection, SocketAddress *address) nsapi_error_t TCPServer::accept(TCPSocket *connection, SocketAddress *address)

View File

@ -20,7 +20,7 @@
TCPSocket::TCPSocket() TCPSocket::TCPSocket()
{ {
_socket_stats.stats_new_socket_entry(this); _socket_stats.stats_update_proto(this, NSAPI_TCP);
} }
TCPSocket::TCPSocket(TCPSocket *parent, nsapi_socket_t socket, SocketAddress address) TCPSocket::TCPSocket(TCPSocket *parent, nsapi_socket_t socket, SocketAddress address)
@ -36,19 +36,10 @@ TCPSocket::TCPSocket(TCPSocket *parent, nsapi_socket_t socket, SocketAddress add
TCPSocket::~TCPSocket() TCPSocket::~TCPSocket()
{ {
_socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
}
nsapi_error_t TCPSocket::close()
{
_socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
return InternetSocket::close();
} }
nsapi_protocol_t TCPSocket::get_proto() nsapi_protocol_t TCPSocket::get_proto()
{ {
_socket_stats.stats_update_proto(this, NSAPI_TCP);
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
return NSAPI_TCP; return NSAPI_TCP;
} }

View File

@ -61,15 +61,6 @@ public:
*/ */
virtual ~TCPSocket(); virtual ~TCPSocket();
/** Close the socket.
*
* Closes any open connection and deallocates any memory associated
* with the socket. Called from destructor if socket is not closed.
*
* @return NSAPI_ERROR_OK on success, negative error code on failure
*/
virtual nsapi_error_t close();
/** Override multicast functions to return error for TCP /** Override multicast functions to return error for TCP
* *
*/ */

View File

@ -20,24 +20,15 @@
UDPSocket::UDPSocket() UDPSocket::UDPSocket()
{ {
_socket_stats.stats_new_socket_entry(this); _socket_stats.stats_update_proto(this, NSAPI_UDP);
} }
UDPSocket::~UDPSocket() UDPSocket::~UDPSocket()
{ {
_socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
}
nsapi_error_t UDPSocket::close()
{
_socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
return InternetSocket::close();
} }
nsapi_protocol_t UDPSocket::get_proto() nsapi_protocol_t UDPSocket::get_proto()
{ {
_socket_stats.stats_update_proto(this, NSAPI_UDP);
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
return NSAPI_UDP; return NSAPI_UDP;
} }

View File

@ -59,15 +59,6 @@ public:
*/ */
virtual ~UDPSocket(); virtual ~UDPSocket();
/** Close the socket.
*
* Closes any open connection and deallocates any memory associated
* with the socket. Called from destructor if socket is not closed.
*
* @return NSAPI_ERROR_OK on success, negative error code on failure
*/
virtual nsapi_error_t close();
/** Send data to the specified host and port. /** Send data to the specified host and port.
* *
* By default, sendto blocks until data is sent. If socket is set to * By default, sendto blocks until data is sent. If socket is set to