From 392bccf8352f16d4525cb913ced03e4882ddb14c Mon Sep 17 00:00:00 2001 From: Michal Paszta Date: Thu, 8 Nov 2018 17:08:34 +0100 Subject: [PATCH] Add unit tests for TLSSocket and TLSSocketWrapper This also includes their Datagram counterparts: DTLSSocket and DTLSSocketWrapper. Coverage missing for timer-related functionality, but this would require more advanced stub development. The extra (d)tls_test_config.h is necessary for successful compilation without HW support for the mbedtls features in unittests. I reused the mbedtls stub found in features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c and amended it slightly with a few missing functions. --- .../netsocket/DTLSSocket/dtls_test_config.h | 11 + .../netsocket/DTLSSocket/test_DTLSSocket.cpp | 73 +++ .../netsocket/DTLSSocket/unittest.cmake | 39 ++ .../DTLSSocketWrapper/dtls_test_config.h | 11 + .../test_DTLSSocketWrapper.cpp | 406 +++++++++++++++++ .../DTLSSocketWrapper/unittest.cmake | 37 ++ .../netsocket/TLSSocket/test_TLSSocket.cpp | 71 +++ .../netsocket/TLSSocket/tls_test_config.h | 11 + .../netsocket/TLSSocket/unittest.cmake | 38 ++ .../test_TLSSocketWrapper.cpp | 420 ++++++++++++++++++ .../TLSSocketWrapper/tls_test_config.h | 11 + .../netsocket/TLSSocketWrapper/unittest.cmake | 36 ++ UNITTESTS/stubs/NetworkStack_stub.h | 5 + .../coap-service/unittest/stub/mbedtls_stub.c | 32 +- features/netsocket/TCPSocket.cpp | 3 + 15 files changed, 1203 insertions(+), 1 deletion(-) create mode 100644 UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h create mode 100644 UNITTESTS/features/netsocket/DTLSSocket/test_DTLSSocket.cpp create mode 100644 UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake create mode 100644 UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h create mode 100644 UNITTESTS/features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp create mode 100644 UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake create mode 100644 UNITTESTS/features/netsocket/TLSSocket/test_TLSSocket.cpp create mode 100644 UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h create mode 100644 UNITTESTS/features/netsocket/TLSSocket/unittest.cmake create mode 100644 UNITTESTS/features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp create mode 100644 UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h create mode 100644 UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake diff --git a/UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h b/UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h new file mode 100644 index 0000000000..4fd8a548ca --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h @@ -0,0 +1,11 @@ +/* + * dtls_test_config.h + */ + +#ifndef UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/DTLSSocket/test_DTLSSocket.cpp b/UNITTESTS/features/netsocket/DTLSSocket/test_DTLSSocket.cpp new file mode 100644 index 0000000000..cc4bdc2aec --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocket/test_DTLSSocket.cpp @@ -0,0 +1,73 @@ +/* + * 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/DTLSSocket.h" +#include "NetworkStack_stub.h" + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestDTLSSocket : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + DTLSSocket *socket; + NetworkStackstub stack; + + virtual void SetUp() + { + socket = new DTLSSocket(); + } + + virtual void TearDown() + { + stack.return_values.clear(); + eventFlagsStubNextRetval.clear(); + delete socket; + } +}; + +TEST_F(TestDTLSSocket, constructor) +{ + EXPECT_TRUE(socket); +} + +/* connect */ + +TEST_F(TestDTLSSocket, connect) +{ + socket->open((NetworkStack *)&stack); + + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocket, connect_error) +{ + socket->open((NetworkStack *)&stack); + + stack.return_value = NSAPI_ERROR_DNS_FAILURE; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_DNS_FAILURE); +} diff --git a/UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake b/UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake new file mode 100644 index 0000000000..3b2907f657 --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocket/unittest.cmake @@ -0,0 +1,39 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/UDPSocket.cpp + ../features/netsocket/DTLSSocket.cpp + ../features/netsocket/DTLSSocketWrapper.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/DTLSSocket/test_DTLSSocket.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_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 +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h\"") +set_source_files_properties(features/netsocket/DTLSSocket/test_DTLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/DTLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h b/UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h new file mode 100644 index 0000000000..8752bb8809 --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h @@ -0,0 +1,11 @@ +/* + * tls_test_config.h + */ + +#ifndef UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp b/UNITTESTS/features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp new file mode 100644 index 0000000000..521d8aca56 --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp @@ -0,0 +1,406 @@ +/* + * 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/UDPSocket.h" +#include "features/netsocket/DTLSSocketWrapper.h" +#include "NetworkStack_stub.h" +#include "features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h" +#include //memset + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestDTLSSocketWrapper : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + UDPSocket* transport; + DTLSSocketWrapper *wrapper; + NetworkStackstub stack; + + virtual void SetUp() + { + memset(mbedtls_stub.retArray, 0, sizeof(mbedtls_stub.retArray)); + mbedtls_stub.useCounter = false; + mbedtls_stub.counter = 0; + mbedtls_stub.crt_expected_int = 0; + mbedtls_stub.expected_int = 0; + transport = new UDPSocket(); + wrapper = new DTLSSocketWrapper(transport); + } + + virtual void TearDown() + { + mbedtls_stub.useCounter = false; + stack.return_values.clear(); + stack.return_socketAddress = SocketAddress(); + eventFlagsStubNextRetval.clear(); + delete wrapper; + } + + char* cert = "-----BEGIN CERTIFICATE-----\ + MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\ + MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\ + DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\ + SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\ + GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\ + AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\ + q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\ + SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\ + Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\ + a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\ + /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\ + AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\ + CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\ + bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\ + c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\ + VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\ + ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\ + MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\ + Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\ + AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\ + uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\ + wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\ + X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\ + PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\ + KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\ + -----END CERTIFICATE-----"; +}; + +static bool callback_is_called; +static void my_callback() +{ + callback_is_called = true; +} + +TEST_F(TestDTLSSocketWrapper, constructor) +{ + EXPECT_TRUE(wrapper); +} + +TEST_F(TestDTLSSocketWrapper, constructor_hostname) +{ + DTLSSocketWrapper *wrapper2 = new DTLSSocketWrapper(transport, "localhost"); +} + +/* connect */ + +TEST_F(TestDTLSSocketWrapper, connect) +{ + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IS_CONNECTED); +} + +TEST_F(TestDTLSSocketWrapper, connect_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); //UDP doesn't mind. +} + +/* connect: SSL-related errors */ + +TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_handshake) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[1] = -1; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_AUTH_FAILURE); +} + +TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_handshake_in_progress) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + wrapper->set_timeout(1); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + mbedtls_stub.retArray[1] = MBEDTLS_ERR_SSL_WANT_READ; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_get_verify_result) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.uint32_value = 1; // mbedtls_ssl_get_verify_result error + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, connect_fail_ctr_drbg_seed) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.crt_expected_int = 1; // mbedtls_ctr_drbg_seed error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); + mbedtls_stub.crt_expected_int = 0; +} + +TEST_F(TestDTLSSocketWrapper, connect_fail_ssl_setup) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 2; // mbedtls_ssl_setup error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); +} + +/* send */ + +TEST_F(TestDTLSSocketWrapper, send_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestDTLSSocketWrapper, send_in_one_chunk) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestDTLSSocketWrapper, send_in_two_chunks) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestDTLSSocketWrapper, send_error_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestDTLSSocketWrapper, send_to) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->sendto(a, dataBuf, dataSize), dataSize); +} + +/* recv */ + +TEST_F(TestDTLSSocketWrapper, recv_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestDTLSSocketWrapper, recv_all_data) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), dataSize); +} + +TEST_F(TestDTLSSocketWrapper, recv_less_than_expected) +{ + transport->open((NetworkStack *)&stack); + unsigned int lessThanDataSize = dataSize - 1; + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = lessThanDataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), lessThanDataSize); +} + +TEST_F(TestDTLSSocketWrapper, recv_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestDTLSSocketWrapper, recv_from_no_socket) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->recvfrom(&a, dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestDTLSSocketWrapper, recv_from) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + SocketAddress b; + EXPECT_EQ(wrapper->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, recv_from_null) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + stack.return_socketAddress = a; + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recvfrom(NULL, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +/* set_root_ca_cert */ + +TEST_F(TestDTLSSocketWrapper, set_root_ca_cert) +{ + EXPECT_EQ(wrapper->get_ca_chain(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_ca_chain(), static_cast(NULL)); +} + +TEST_F(TestDTLSSocketWrapper, set_root_ca_cert_nolen) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, set_root_ca_cert_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.counter = 0; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestDTLSSocketWrapper, set_client_cert_key) +{ + EXPECT_EQ(wrapper->get_own_cert(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_own_cert(), static_cast(NULL)); +} + +TEST_F(TestDTLSSocketWrapper, set_client_cert_key_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestDTLSSocketWrapper, set_client_cert_key_invalid_pem) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 0; // mbedtls_x509_crt_parse ok + mbedtls_stub.retArray[1] = 1; // mbedtls_pk_parse_key error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestDTLSSocketWrapper, bind) +{ + transport->open((NetworkStack *)&stack); + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_OK); +} + +TEST_F(TestDTLSSocketWrapper, bind_no_open) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestDTLSSocketWrapper, sigio) +{ + transport->open((NetworkStack *)&stack); + callback_is_called = false; + wrapper->sigio(mbed::callback(my_callback)); + SocketAddress a("127.0.0.1", 1024); + wrapper->close(); //trigger events. + EXPECT_EQ(callback_is_called, true); +} + +TEST_F(TestDTLSSocketWrapper, setsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->setsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestDTLSSocketWrapper, getsockopt_no_stack) +{ + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestDTLSSocketWrapper, getsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +/* unsupported */ + +TEST_F(TestDTLSSocketWrapper, listen_unsupported) +{ + EXPECT_EQ(wrapper->listen(1), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestDTLSSocketWrapper, accept_unsupported) +{ + nsapi_error_t error; + EXPECT_EQ(wrapper->accept(&error), static_cast(NULL)); + EXPECT_EQ(error, NSAPI_ERROR_UNSUPPORTED); +} + diff --git a/UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake b/UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake new file mode 100644 index 0000000000..ef2adfe7ce --- /dev/null +++ b/UNITTESTS/features/netsocket/DTLSSocketWrapper/unittest.cmake @@ -0,0 +1,37 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/UDPSocket.cpp + ../features/netsocket/DTLSSocketWrapper.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_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 +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h\"") +set_source_files_properties(features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/features/netsocket/TLSSocket/test_TLSSocket.cpp b/UNITTESTS/features/netsocket/TLSSocket/test_TLSSocket.cpp new file mode 100644 index 0000000000..0d278125fa --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocket/test_TLSSocket.cpp @@ -0,0 +1,71 @@ +/* + * 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/TLSSocket.h" +#include "NetworkStack_stub.h" + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestTLSSocket : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + TLSSocket *socket; + NetworkStackstub stack; + + virtual void SetUp() + { + socket = new TLSSocket(); + } + + virtual void TearDown() + { + stack.return_values.clear(); + eventFlagsStubNextRetval.clear(); + delete socket; + } +}; + +TEST_F(TestTLSSocket, constructor) +{ + EXPECT_TRUE(socket); +} + +/* connect */ + +TEST_F(TestTLSSocket, connect) +{ + socket->open((NetworkStack *)&stack); + + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocket, connect_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_NO_SOCKET); +} diff --git a/UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h b/UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h new file mode 100644 index 0000000000..35a88ad771 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h @@ -0,0 +1,11 @@ +/* + * tls_test_config.h + */ + +#ifndef UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/TLSSocket/unittest.cmake b/UNITTESTS/features/netsocket/TLSSocket/unittest.cmake new file mode 100644 index 0000000000..d6ccdc59e1 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocket/unittest.cmake @@ -0,0 +1,38 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/TCPSocket.cpp + ../features/netsocket/TLSSocket.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/TLSSocket/test_TLSSocket.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_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 +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h\"") +set_source_files_properties(features/netsocket/TLSSocket/test_TLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/TLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp b/UNITTESTS/features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp new file mode 100644 index 0000000000..746171149e --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp @@ -0,0 +1,420 @@ +/* + * 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/TLSSocketWrapper.h" +#include "NetworkStack_stub.h" +#include "features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h" +#include //memset + +#include "mbed_error.h" +mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) +{ + return 0; +} + +// Control the rtos EventFlags stub. See EventFlags_stub.cpp +extern std::list eventFlagsStubNextRetval; + +class TestTLSSocketWrapper : public testing::Test { +public: + unsigned int dataSize = 10; + char dataBuf[10]; +protected: + TCPSocket* transport; + TLSSocketWrapper *wrapper; + NetworkStackstub stack; + + virtual void SetUp() + { + memset(mbedtls_stub.retArray, 0, sizeof(mbedtls_stub.retArray)); + mbedtls_stub.useCounter = false; + mbedtls_stub.counter = 0; + mbedtls_stub.crt_expected_int = 0; + mbedtls_stub.expected_int = 0; + transport = new TCPSocket(); + wrapper = new TLSSocketWrapper(transport); + } + + virtual void TearDown() + { + stack.return_values.clear(); + eventFlagsStubNextRetval.clear(); + delete wrapper; + } + + char* cert = "-----BEGIN CERTIFICATE-----\ + MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\ + MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\ + DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\ + SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\ + GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\ + AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\ + q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\ + SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\ + Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\ + a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\ + /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\ + AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\ + CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\ + bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\ + c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\ + VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\ + ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\ + MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\ + Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\ + AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\ + uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\ + wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\ + X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\ + PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\ + KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\ + -----END CERTIFICATE-----"; +}; + +static bool callback_is_called; +static void my_callback() +{ + callback_is_called = true; +} + +TEST_F(TestTLSSocketWrapper, constructor) +{ + EXPECT_TRUE(wrapper); +} + +TEST_F(TestTLSSocketWrapper, constructor_hostname) +{ + TLSSocketWrapper *wrapper2 = new TLSSocketWrapper(transport, "localhost"); +} + +/* connect */ + +TEST_F(TestTLSSocketWrapper, connect) +{ + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IS_CONNECTED); +} + +/* connect: TCP-related errors */ + +TEST_F(TestTLSSocketWrapper, connect_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestTLSSocketWrapper, connect_error_in_progress_no_timeout) +{ + transport->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(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestTLSSocketWrapper, connect_with_timeout) +{ + transport->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 + wrapper->set_blocking(true); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestTLSSocketWrapper, connect_error_is_connected) +{ + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + wrapper->set_timeout(1); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_ctr_drbg_seed error +} + +/* connect: SSL-related errors */ + +TEST_F(TestTLSSocketWrapper, connect_fail_ctr_drbg_seed) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.crt_expected_int = 1; // mbedtls_ctr_drbg_seed error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); + mbedtls_stub.crt_expected_int = 0; +} + +TEST_F(TestTLSSocketWrapper, connect_fail_ssl_setup) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 0; // mbedtls_ssl_config_defaults ok + mbedtls_stub.retArray[1] = 2; // mbedtls_ssl_setup error + stack.return_value = NSAPI_ERROR_OK; + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_handshake) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[2] = -1; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_AUTH_FAILURE); +} + +TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_handshake_in_progress) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + wrapper->set_timeout(1); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_READ; // mbedtls_ssl_handshake error + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS); +} + +TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_get_verify_result) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.uint32_value = 1; // mbedtls_ssl_get_verify_result error + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); +} + +/* send */ + +TEST_F(TestTLSSocketWrapper, send_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestTLSSocketWrapper, send_in_one_chunk) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestTLSSocketWrapper, send_in_two_chunks) +{ + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + transport->open((NetworkStack *)&stack); + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize); +} + +TEST_F(TestTLSSocketWrapper, send_error_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestTLSSocketWrapper, send_to) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->sendto(a, dataBuf, dataSize), dataSize); +} + +/* recv */ + +TEST_F(TestTLSSocketWrapper, recv_no_open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestTLSSocketWrapper, recv_all_data) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), dataSize); +} + +TEST_F(TestTLSSocketWrapper, recv_less_than_expected) +{ + transport->open((NetworkStack *)&stack); + unsigned int lessThanDataSize = dataSize - 1; + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = lessThanDataSize; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), lessThanDataSize); +} + +TEST_F(TestTLSSocketWrapper, recv_would_block) +{ + transport->open((NetworkStack *)&stack); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write + const SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop + EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK); +} + +TEST_F(TestTLSSocketWrapper, recv_from_no_socket) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->recvfrom(&a, dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION); +} + +TEST_F(TestTLSSocketWrapper, recv_from) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + SocketAddress b; + EXPECT_EQ(wrapper->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocketWrapper, recv_from_null) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->recvfrom(NULL, dataBuf, dataSize), NSAPI_ERROR_OK); +} + +/* set_root_ca_cert */ + +TEST_F(TestTLSSocketWrapper, set_root_ca_cert) +{ + EXPECT_EQ(wrapper->get_ca_chain(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_ca_chain(), static_cast(NULL)); +} + +TEST_F(TestTLSSocketWrapper, set_root_ca_cert_nolen) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert(cert), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocketWrapper, set_root_ca_cert_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, set_client_cert_key) +{ + EXPECT_EQ(wrapper->get_own_cert(), static_cast(NULL)); + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_OK); + EXPECT_NE(wrapper->get_own_cert(), static_cast(NULL)); +} + +TEST_F(TestTLSSocketWrapper, set_client_cert_key_invalid) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, set_client_cert_key_invalid_pem) +{ + EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + mbedtls_stub.useCounter = true; + mbedtls_stub.retArray[0] = 0; // mbedtls_x509_crt_parse ok + mbedtls_stub.retArray[1] = 1; // mbedtls_pk_parse_key error + EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestTLSSocketWrapper, bind) +{ + transport->open((NetworkStack *)&stack); + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_OK); +} + +TEST_F(TestTLSSocketWrapper, bind_no_open) +{ + SocketAddress a("127.0.0.1", 1024); + EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestTLSSocketWrapper, sigio) +{ + transport->open((NetworkStack *)&stack); + callback_is_called = false; + wrapper->sigio(mbed::callback(my_callback)); + SocketAddress a("127.0.0.1", 1024); + wrapper->close(); //trigger events. + EXPECT_EQ(callback_is_called, true); +} + +TEST_F(TestTLSSocketWrapper, setsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->setsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestTLSSocketWrapper, getsockopt_no_stack) +{ + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET); +} + +TEST_F(TestTLSSocketWrapper, getsockopt) +{ + transport->open((NetworkStack *)&stack); + EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED); +} + +/* unsupported */ + +TEST_F(TestTLSSocketWrapper, listen_unsupported) +{ + EXPECT_EQ(wrapper->listen(1), NSAPI_ERROR_UNSUPPORTED); +} + +TEST_F(TestTLSSocketWrapper, accept_unsupported) +{ + nsapi_error_t error; + EXPECT_EQ(wrapper->accept(&error), static_cast(NULL)); + EXPECT_EQ(error, NSAPI_ERROR_UNSUPPORTED); +} + diff --git a/UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h b/UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h new file mode 100644 index 0000000000..35a88ad771 --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h @@ -0,0 +1,11 @@ +/* + * tls_test_config.h + */ + +#ifndef UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ +#define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ + +#define MBEDTLS_SSL_CLI_C + + +#endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */ diff --git a/UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake b/UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake new file mode 100644 index 0000000000..4676f1f9ac --- /dev/null +++ b/UNITTESTS/features/netsocket/TLSSocketWrapper/unittest.cmake @@ -0,0 +1,36 @@ + +#################### +# UNIT TESTS +#################### + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/TCPSocket.cpp + ../features/netsocket/TLSSocketWrapper.cpp + ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c + ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c + ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c + ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c + ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c +) + +set(unittest-test-sources + features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/equeue_stub.c + ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_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 +) + +set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h\"") +set_source_files_properties(features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) +set_source_files_properties(../features/netsocket/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH}) + diff --git a/UNITTESTS/stubs/NetworkStack_stub.h b/UNITTESTS/stubs/NetworkStack_stub.h index cb245ab46d..326bfa56aa 100644 --- a/UNITTESTS/stubs/NetworkStack_stub.h +++ b/UNITTESTS/stubs/NetworkStack_stub.h @@ -25,6 +25,7 @@ class NetworkStackstub : public NetworkStack { public: std::list return_values; nsapi_error_t return_value; + SocketAddress return_socketAddress; NetworkStackstub() { @@ -113,6 +114,10 @@ protected: virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, void *buffer, nsapi_size_t size) { + if (return_socketAddress != SocketAddress()) + { + *address = return_socketAddress; + } if (!return_values.empty()) { nsapi_error_t ret = return_values.front(); return_values.pop_front(); diff --git a/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c b/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c index f02fba1f9c..ba97c62e9f 100644 --- a/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c +++ b/features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c @@ -59,7 +59,12 @@ void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor } -void mbedtls_ssl_config_init(mbedtls_ssl_config *a) +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + +} + +void mbedtls_ssl_config_init( mbedtls_ssl_config *a ) { } @@ -198,6 +203,16 @@ int mbedtls_ssl_write(mbedtls_ssl_context *a, const unsigned char *b, size_t c) return mbedtls_stub.expected_int; } +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + return 0; +} + +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + return NULL; +} + //From crt_drbg.h @@ -252,6 +267,18 @@ int mbedtls_x509_crt_parse(mbedtls_x509_crt *a, const unsigned char *b, size_t c return mbedtls_stub.expected_int; } +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + return 0; +} + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + return 0; +} + //From entropy.h void mbedtls_entropy_init(mbedtls_entropy_context *a) { @@ -356,3 +383,6 @@ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl) } return mbedtls_stub.expected_int; } + +void mbedtls_strerror( int ret, char *buf, size_t buflen ){ +} diff --git a/features/netsocket/TCPSocket.cpp b/features/netsocket/TCPSocket.cpp index ce29384de9..6765d9d0bf 100644 --- a/features/netsocket/TCPSocket.cpp +++ b/features/netsocket/TCPSocket.cpp @@ -103,6 +103,9 @@ nsapi_error_t TCPSocket::connect(const SocketAddress &address) nsapi_error_t TCPSocket::connect(const char *host, uint16_t port) { SocketAddress address; + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } nsapi_error_t err = _stack->gethostbyname(host, &address); if (err) { return NSAPI_ERROR_DNS_FAILURE;