diff --git a/UNITTESTS/.mbedignore b/UNITTESTS/.mbedignore new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/UNITTESTS/.mbedignore @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt new file mode 100644 index 0000000..29bcf92 --- /dev/null +++ b/UNITTESTS/CMakeLists.txt @@ -0,0 +1,169 @@ +cmake_minimum_required(VERSION 3.0.2) + +set(PROJECT_NAME unittests) +set(LIB_NAME MbedOS) + +project(${PROJECT_NAME}) + +# Setup c++ standard +macro(use_cxx14) + if (CMAKE_VERSION VERSION_LESS 3.1) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++98") + endif() + else() + set(CMAKE_CXX_STANDARD 98) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + endif() +endmacro() + +use_cxx14() + +#################### +# GTEST +#################### + +# Download and unpack googletest at configure time +configure_file(googletest-CMakeLists.txt.in googletest-download/CMakeLists.txt) +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download) +if (result) + message(FATAL_ERROR "CMake failed for google test: ${result}") +endif() +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download) +if (result) + message(FATAL_ERROR "Build failed for google test: ${result}") +endif() + +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Add googletest directly to our build. This defines +# the gtest and gtest_main targets. +add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src + ${CMAKE_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) + +# The gtest/gtest_main/gmock/gmock_main targets carry header search path +# dependencies automatically when using CMake 2.8.11 or +# later. +target_include_directories(gmock_main SYSTEM BEFORE INTERFACE + "${gtest_SOURCE_DIR}/include" + "${gmock_SOURCE_DIR}/include") + +#################### +# TESTING +#################### + +enable_testing() + +set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES + "${CMAKE_BINARY_DIR}/Testing" +) + +#################### +# CODE COVERAGE SETUP +#################### + +if (COVERAGE) + + if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(WARNING "Non-debug build may result misleading code coverage results.") + endif() + + # Append coverage compiler flags + set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}") + +endif(COVERAGE) + +#################### +# UNIT TESTS +#################### + +# Set include dirs. +set(unittest-includes-base + "${PROJECT_SOURCE_DIR}/target_h" + "${PROJECT_SOURCE_DIR}/target_h/events" + "${PROJECT_SOURCE_DIR}/stubs" + "${PROJECT_SOURCE_DIR}/.." + "${PROJECT_SOURCE_DIR}/../features" + "${PROJECT_SOURCE_DIR}/../platform" + "${PROJECT_SOURCE_DIR}/../drivers" + "${PROJECT_SOURCE_DIR}/../hal" + "${PROJECT_SOURCE_DIR}/../events" + "${PROJECT_SOURCE_DIR}/../rtos/TARGET_CORTEX" + "${PROJECT_SOURCE_DIR}/../rtos/TARGET_CORTEX/rtx5/Include" + "${PROJECT_SOURCE_DIR}/../cmsis" +) + +# Create a list for test suites. +set(TEST_SUITES) + +# Get all matched tests. +file(GLOB_RECURSE unittest-file-list + "unittest.cmake" +) + +if ("${unittest-file-list}" STREQUAL "") + message(FATAL_ERROR "No tests found. Exiting...") +endif() + +# Create unit test targets +foreach(testfile ${unittest-file-list}) + #################### + # DEFINE TARGETS + #################### + + # Init file lists. + set(unittest-includes ${unittest-includes-base}) + set(unittest-sources) + set(unittest-test-sources) + + # Get source files + include("${testfile}") + + if(TEST_SUITE_NAME) + set(TEST_SUITES ${TEST_SUITES} ${TEST_SUITE_NAME}) + else() + message(FATAL_ERROR "No TEST_SUITE_NAME found in test file. Add it to ${testfile}.") + endif() + + set(LIBS_TO_BE_LINKED gmock_main) + + # Build directories list + set(BUILD_DIRECTORIES) + + if (unittest-sources) + # Create the testable static library. + add_library("${TEST_SUITE_NAME}.${LIB_NAME}" STATIC ${unittest-sources}) + target_include_directories("${TEST_SUITE_NAME}.${LIB_NAME}" PRIVATE + ${unittest-includes}) + set(LIBS_TO_BE_LINKED ${LIBS_TO_BE_LINKED} "${TEST_SUITE_NAME}.${LIB_NAME}") + + # Append lib build directory to list + list(APPEND BUILD_DIRECTORIES "./CMakeFiles/${TEST_SUITE_NAME}.${LIB_NAME}.dir") + endif(unittest-sources) + + if (unittest-test-sources) + # Create the executable. + add_executable(${TEST_SUITE_NAME} ${unittest-test-sources}) + target_include_directories(${TEST_SUITE_NAME} PRIVATE + ${unittest-includes}) + + # Link the executable with the libraries. + target_link_libraries(${TEST_SUITE_NAME} ${LIBS_TO_BE_LINKED}) + + add_test(NAME "${TEST_SUITE_NAME}UnitTests" COMMAND ${TEST_SUITE_NAME}) + + # Append test build directory to list + list(APPEND BUILD_DIRECTORIES "./CMakeFiles/${TEST_SUITE_NAME}.dir") + else() + message(WARNING "No test source files found for ${TEST_SUITE_NAME}.\n") + endif(unittest-test-sources) +endforeach(testfile) diff --git a/UNITTESTS/CMakeSettings.json b/UNITTESTS/CMakeSettings.json new file mode 100644 index 0000000..e4355a6 --- /dev/null +++ b/UNITTESTS/CMakeSettings.json @@ -0,0 +1,30 @@ +{ + "configurations": [ + { + "name": "GNU-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "mingw64" ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "environments": [ + { + "environment": "mingw64" + } + ] + }, + { + "name": "GNU-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ "mingw64" ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "environments": [ + { + "environment": "mingw64" + } + ] + } + ] +} \ No newline at end of file diff --git a/UNITTESTS/README.md b/UNITTESTS/README.md new file mode 100644 index 0000000..2f8a7bc --- /dev/null +++ b/UNITTESTS/README.md @@ -0,0 +1,294 @@ +# Unit testing Mbed OS + +This document describes how to run and write unit tests for Mbed OS. + +## Prerequisites + +* GNU toolchains installed. + * GCC 6 or later + * MinGW-W64 GCC-6.4.0 or MinGW-W64 GCC-7.3.0 (Windows) +* CMake 3.0+ installed. +* Python 2.7.x or >3.5 and pip 10.0 (or newer) installed. +* gcovr >=4.1 + +### Installing dependencies on Debian/Ubuntu + +1. `sudo apt-get -y install build-essential cmake` +2. Install python and pip: +``` +sudo apt-get -y install python python-setuptools +sudo easy_install pip +``` +3. Install [gcovr](#installing-covr). +4. (Optional) Install [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html). + +### Installing dependencies on Mac OS + +1. Install [Homebrew](https://brew.sh/). +2. Install gcc compilers and cmake with: `brew install gcc cmake` +3. Install python and pip: +``` +brew install python +sudo easy_install pip +``` +3. Install [gcovr](#installing-covr). +4. (Optional) Install [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html). + +### Installing dependencies on Windows + +1. Download and install [MinGW-W64](http://mingw-w64.org/). +2. Download CMake binaries from https://cmake.org/download/ and run the installer. +3. Download Python2.7 or Python3 from https://www.python.org/getit/ and run the installer. +4. Add MinGW, CMake and Python into PATH. +5. Install [gcovr](#installing-covr). +6. (Optional) Install [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html). + +### Installing covr + +Install gcovr code coverage tool globally with `pip install 'gcovr>=4.1'` or using virtualenv: + +#### virtualenv + +1. Install virtualenv if not installed with `pip install virtualenv` +2. Install gcovr with: + +**[Debian/Linux/Mac OS]** +``` +virtualenv pyenv +. pyenv/bin/activate +pip install 'gcovr>=4.1' +``` +**[Windows]** +``` +virtualenv pyenv +pyenv\\Scripts\\activate +pip install "gcovr>=4.1" +``` + +## Building and running unit tests + +> In case of running into problems see [troubleshooting](#troubleshooting) section. + +`UNITTESTS/mbed_unittest.py` contains testing scripts for Mbed OS unit testing. Mbed CLI supports unit testing through `mbed unittest` command with the same arguments. + +### Testing with Mbed CLI + +``` +mbed unittest +``` + +A subset of tests can be run by providing `-r` flag for the tool which runs tests matching a regular expression. + +e.g. `mbed unittest --run -r features_netsocket` + +### Build manually without Python tools + +1. Create a build directory e.g. `mkdir UNITTESTS/build`. +2. Move to the build directory `cd UNITTESTS/build`. +3. Run CMake with `cmake [RELATIVE PATH TO UNITTESTS DIR] [OPTIONAL ARGUMENTS]` e.g. `cmake ..`: + * Add `-g [generator]` argument if target other than Unix Makefiles e.g. MinGW `-g "MinGW Makefiles"` +4. Run make program (make, gmake, mingw32-make, etc). + +##### Run CMake and build Unix Makefiles (GNU make) + +``` +cmake .. +make +``` + +##### Run CMake and build MinGW Makefiles (mingw32-make) + +``` +cmake -G "MinGW Makefiles" .. +mingw32-make +``` + +#### Custom CMake variables + +Usage: +`cmake [RELATIVE PATH TO UNITTESTS DIR] [OPTIONS]` + +Keyword variables (usage `cmake -D(:)=`: + +| Variable | Type | Accepted values | Description | +| -------- | ---- | --------------- | ----------- | +| COVERAGE | STRING | merged
separate | Generate merged or individual reports | + +### Run in terminal + +Unit tests can be run separately from each executable or by using ctest test runner. Run ctest with make program using target test. Options can be passed to ctest using ARGS argument. See [ctest manual](https://cmake.org/cmake/help/v3.0/manual/ctest.1.html) for more information. + +Run ctest on test suite level: +``` +{MAKE_PROGRAM} test -C [RELATIVE PATH TO BUILD DIRECTORY] +``` +e.g. `make test -C UNITTESTS/build` or `mingw32-make test -C UNITTESTS/build` + +Run ctest verbose (show each test case): +``` +{MAKE_PROGRAM} test -C UNITTESTS/build ARGS="-V" +``` + +Run ctest dashboard test and create test results: +``` +{MAKE_PROGRAM} test --C UNITTESTS/build ARGS="-D ExperimentalTest" +``` + +### Run with GUI test runner + +1. Build and/or install *gtest-runner* using the documentation: https://github.com/nholthaus/gtest-runner + +2. Run the application, add built test executables into the list and run it. + +### Get code coverage + +Python tools use gcovr to build code coverage reports. Generate html report `UNITTESTS/build/coverage/index.html` with: +``` +mbed unittest --coverage html +``` + +To get coverage for a single test suite, run gcovr separately for suite coverage data directory. See [gcovr documentation](https://gcovr.com/guide.html#filter-options) for more information. + +e.g. for features/netsocket/InternetSocket coverage: + +Debian/Ubuntu/Mac OS: +``` +mkdir UNITTESTS/build +cd UNITTESTS/build +cmake -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE:STRING=html .. +make +./features_netsocket_InternetSocket +gcovr -r ../.. --html --html-detail -o ./index.html ./CMakeFiles/features_netsocket_InternetSocket.MbedOS.dir/ +``` +Windows: +``` +mkdir UNITTESTS/build +cd UNITTESTS/build +cmake -DCMAKE_BUILD_TYPE=Debug -DCOVERAGE:STRING=html -g "MinGW Makefiles" .. +mingw32-make +features_netsocket_InternetSocket.exe +gcovr -r ..\.. --html --html-detail -o .\index.html .\CMakeFiles\features_netsocket_InternetSocket.MbedOS.dir\ +``` + +## The structure of unit tests + +The structure of the unit tests directory looks like this: +``` +UNITTESTS + ├── mbed_unittest.py Python tool for unit testing + ├── unit_test Python tool modules + ├── CMakeLists.txt CMake project definition file + ├── CMakeSettings.json CMake configurations for Visual Studio 2017 + ├── README.md + ├── googletest-CMakeLists.txt.in CMake project definition file for Google Test + │ + ├── features + │ └── netsocket Directory tree that mirrors Mbed OS root + │ ├── NetworkInterface Name of the class to be tested + │ │ ├── test_NetworkInterface.cpp + │ │ └── unittest.cmake CMake module for unit test + │ └── Socket + │ + ├── stubs Shared stubs which can be used for tests. + ├── target_h Shared headers which can be used for tests. + └── template Templates for creating new unittests +``` +Each unit test has an identical directory tree as seen in the Mbed OS root folder. This is not a mandatory requirement but helps to maintain tests. Each class to be tested have their own `unittest.cmake` which is found by `CMakeLists.txt`. + +## Creating a unit test + +Each class to be tested requires two files for unit testing: +1. C++ unit test source file (e.g. `test_NetworkInterface.cpp`) +2. CMake module file for unit test definition (`unittest.cmake`) + +A unit test definition file `unittest.cmake` requires variables to be set for a test to be configured. File source paths in `unittest.cmake` files need to be relative to the unit test folder and `CMakeLists.txt`. + +* **TEST_SUITE_NAME** - Identifier for the test suite. Use naming convention *PATH_TO_THE_TESTABLE_FILE* e.g. *features_netsocket_InternetSocket* +* **unittest-includes** - Include paths for headers needed to build the tests in addition to the base include paths listed in [CMakeLists.txt](CMakeLists.txt). Optional. +* **unittest-sources** - Mbed OS source files and stubs included for the build. +* **unittest-test-sources** - Unit test source files. + +#### Creating unit tests files with Mbed CLI + +``` +mbed unittest --new +``` + +E.g. `mbed unittest --new rtos/Semaphore.cpp` + +The generator script only creates the files required for a unit test. It does not write unit tests automatically nor does it handle source dependencies. + +#### Create files manually + +For example to create a unit test for `rtos/Semaphore.cpp`: + +1. Create a directory for unit test files in `UNITTESTS/rtos/Semaphore`. +2. Create a test definition file `UNITTESTS/rtos/Semaphore/unittest.cmake` with the following content: +``` +set(TEST_SUITE_NAME "rtos_Semaphore") + +set(unittest-sources + stubs/mbed_assert.c + ../rtos/Semaphore.cpp +) + +set(unittest-test-sources + rtos/Semaphore/test_Semaphore.cpp +) +``` +3. Create a test source file `UNITTESTS/rtos/Semaphore/test_Semaphore.cpp` with the following content: +``` +#include "gtest/gtest.h" +#include "rtos/Semaphore.h" + +static osStatus_t retval = osOK; +static uint32_t count = 0; + +// Test stubs +osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout) +{ + return retval; +} +osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) +{ + return retval; +} +osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) +{ + return retval; +} +uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id) +{ + return count; +} +osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) +{ + return (void *)&count; // Just a dymmy reference +} + +class TestSemaphore : public testing::Test { +protected: + rtos::Semaphore *sem; + + virtual void SetUp() + { + sem = new rtos::Semaphore(); + } + + virtual void TearDown() + { + delete sem; + } +}; + +TEST_F(TestSemaphore, constructor) +{ + EXPECT_TRUE(sem); +} +``` + +## Troubleshooting + +**Problem:** virus protection identifies files generated by CMake as malicious and quarantines the files on Windows. + +* **Solution**: restore the false positive files from the quarantine. \ No newline at end of file diff --git a/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/at_cellularbasetest.cpp b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/at_cellularbasetest.cpp new file mode 100644 index 0000000..08ec439 --- /dev/null +++ b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/at_cellularbasetest.cpp @@ -0,0 +1,49 @@ +/* + * 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 "test_at_cellularbase.h" +#include "AT_CellularBase.h" + +class TestAT_CellularBase : public testing::Test { +protected: + Test_AT_CellularBase *unit; + + virtual void SetUp() + { + unit = new Test_AT_CellularBase(); + } + + virtual void TearDown() + { + delete unit; + } +}; + +TEST_F(TestAT_CellularBase, Create) +{ + EXPECT_TRUE(unit); +} + +TEST_F(TestAT_CellularBase, test_AT_CellularBase_get_at_handler) +{ + unit->test_AT_CellularBase_get_at_handler(); +} + +TEST_F(TestAT_CellularBase, test_AT_CellularBase_get_device_error) +{ + unit->test_AT_CellularBase_get_device_error(); +} diff --git a/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/test_at_cellularbase.cpp b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/test_at_cellularbase.cpp new file mode 100644 index 0000000..11d28a2 --- /dev/null +++ b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/test_at_cellularbase.cpp @@ -0,0 +1,59 @@ +/* + * 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 "test_at_cellularbase.h" +#include "EventQueue.h" +#include "AT_CellularBase.h" +#include "ATHandler_stub.h" +#include "FileHandle_stub.h" +#include + +using namespace mbed; +using namespace events; + +Test_AT_CellularBase::Test_AT_CellularBase() +{ + +} + +Test_AT_CellularBase::~Test_AT_CellularBase() +{ +} + +void Test_AT_CellularBase::test_AT_CellularBase_get_at_handler() +{ + EventQueue eq; + FileHandle_stub fh; + ATHandler ah(&fh, eq, 100, ","); + AT_CellularBase at(ah); + + EXPECT_EQ(&ah, &at.get_at_handler()); +} + +void Test_AT_CellularBase::test_AT_CellularBase_get_device_error() +{ + EventQueue eq; + FileHandle_stub fh; + ATHandler ah(&fh, eq, 0, ","); + AT_CellularBase at(ah); + + ATHandler_stub::device_err_value.errCode = 8; + + EXPECT_EQ(8, at.get_device_error().errCode); + + ATHandler_stub::device_err_value.errCode = 0; +} diff --git a/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/test_at_cellularbase.h b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/test_at_cellularbase.h new file mode 100644 index 0000000..3091dad --- /dev/null +++ b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/test_at_cellularbase.h @@ -0,0 +1,31 @@ +/* + * 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. + */ +#ifndef TEST_AT_CELLULARBASE_H +#define TEST_AT_CELLULARBASE_H + +class Test_AT_CellularBase { +public: + Test_AT_CellularBase(); + + virtual ~Test_AT_CellularBase(); + + void test_AT_CellularBase_get_at_handler(); + + void test_AT_CellularBase_get_device_error(); +}; + +#endif // TEST_AT_CELLULARBASE_H diff --git a/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/unittest.cmake b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/unittest.cmake new file mode 100644 index 0000000..196bf7e --- /dev/null +++ b/UNITTESTS/features/cellular/framework/AT/AT_CellularBase/unittest.cmake @@ -0,0 +1,32 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "cellular_framework_AT_AT_CellularBase") + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + features/cellular/framework/AT/AT_CellularBase + ../features/cellular/framework/AT + ../features/cellular/framework/common + ../features/frameworks/mbed-trace + ../features/frameworks/nanostack-libservice/mbed-client-libservice + ../features/netsocket +) + +# Source files +set(unittest-sources + ../features/cellular/framework/AT/AT_CellularBase.cpp +) + +# Test files +set(unittest-test-sources + stubs/mbed_assert_stub.c + stubs/ATHandler_stub.cpp + stubs/EventQueue_stub.cpp + stubs/FileHandle_stub.cpp + features/cellular/framework/AT/AT_CellularBase/test_at_cellularbase.cpp + features/cellular/framework/AT/AT_CellularBase/at_cellularbasetest.cpp +) diff --git a/UNITTESTS/features/cellular/framework/common/util/test_util.cpp b/UNITTESTS/features/cellular/framework/common/util/test_util.cpp new file mode 100644 index 0000000..49aebf9 --- /dev/null +++ b/UNITTESTS/features/cellular/framework/common/util/test_util.cpp @@ -0,0 +1,179 @@ +/* + * 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 "test_util.h" +#include +#include "CellularUtil.h" +#include + +using namespace mbed_cellular_util; + +Test_util::Test_util() +{ + +} + +Test_util::~Test_util() +{ +} + +void Test_util::test_util_uint_to_binary_string() +{ + char str[33]; + uint_to_binary_str(15, str, 33, 32); + str[32] = '\0'; + // 15 is "1111" in binary but we ask all 32 bits so it should return "00000000000000000000000000001111" + EXPECT_STREQ("00000000000000000000000000001111", str); + + // test NULL pointer + uint_to_binary_str(15, NULL, 0, 32); + + // test give too small buffer + char too_small[5]; + uint_to_binary_str(15, too_small, 5, 6); +} + +void Test_util::test_util_char_str_to_hex() +{ + // basic conversion test, happy days + char hex_buf[50]; + uint16_t number_of_hex_chars = char_str_to_hex_str("1234", 4, hex_buf); + hex_buf[number_of_hex_chars] = '\0'; + EXPECT_STREQ("31323334", hex_buf); + EXPECT_EQ(8, number_of_hex_chars); + + number_of_hex_chars = char_str_to_hex_str("wuhuu", 5, hex_buf); + hex_buf[number_of_hex_chars] = '\0'; + EXPECT_STREQ("7775687575", hex_buf); + EXPECT_EQ(10, number_of_hex_chars); + + // First don't omit the leading zero and then omit and check that leading zero is missing + number_of_hex_chars = char_str_to_hex_str("\nwuhuu", 6, hex_buf); + hex_buf[number_of_hex_chars] = '\0'; + EXPECT_STREQ("0A7775687575", hex_buf); + EXPECT_EQ(12, number_of_hex_chars); + + number_of_hex_chars = char_str_to_hex_str("\nwuhuu", 6, hex_buf, true); + hex_buf[number_of_hex_chars] = '\0'; + EXPECT_STREQ("A7775687575", hex_buf); + EXPECT_EQ(11, number_of_hex_chars); + + // test giving a null pointer + number_of_hex_chars = char_str_to_hex_str(NULL, 4, hex_buf); + EXPECT_EQ(0, number_of_hex_chars); + number_of_hex_chars = char_str_to_hex_str("1234", 4, NULL); + EXPECT_EQ(0, number_of_hex_chars); +} + +void Test_util::test_util_convert_ipv6() +{ + // leading zeros omitted + char ipv6[64]; + strncpy(ipv6, "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1", 64); + convert_ipv6(ipv6); + EXPECT_STREQ("101:101:101:101:101:101:101:101", ipv6); + EXPECT_EQ(31, strlen(ipv6)); + + // some omitted and some not so much + strncpy(ipv6, "255.1.120.2.244.12.55.45.201.110.11.2.233.154.85.96", 64); + convert_ipv6(ipv6); + EXPECT_STREQ("FF01:7802:F40C:372D:C96E:B02:E99A:5560", ipv6); + EXPECT_EQ(38, strlen(ipv6)); + + // test giving a null pointer + convert_ipv6(NULL); +} + +void Test_util::test_util_prefer_ipv6() +{ + char tt[20] = "62.241.198.246"; + char temp[64] = "2001:14B8:1000:000:000:000:000:002"; + + // not enough space to swap, arrays should stay the same + prefer_ipv6(tt, sizeof(tt), temp, sizeof(temp)); + EXPECT_STREQ("62.241.198.246", tt); + EXPECT_STREQ("2001:14B8:1000:000:000:000:000:002", temp); + + // should swap as first one was ip4 and later was ipv6 and enough space + char tt2[64] = "62.241.198.246"; + prefer_ipv6(tt2, sizeof(tt2), temp, sizeof(temp)); + EXPECT_STREQ("62.241.198.246", temp); + EXPECT_STREQ("2001:14B8:1000:000:000:000:000:002", tt2); +} + +void Test_util::test_util_separate_ip_addresses() +{ + char *s = (char *)calloc(128, 1); + + char ip[64] = {0}; + char subnet[64] = {0}; + + strncpy(s, "32.1.20.187.1.112.139.245.251.136.232.110.123.51.230.138.0.1.2.3.4.5.6.7.8.9.10.11.12.13.14.15", 94); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("2001:14BB:170:8BF5:FB88:E86E:7B33:E68A", ip); + EXPECT_STREQ("001:203:405:607:809:A0B:C0D:E0F", subnet); + + strncpy(s, "32:1:20:187:1:112:139:245:251:136:232:110:123:51:230:138 0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15", 94); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("32:1:20:187:1:112:139:245:251:136:232:110:123:51:230:138", ip); + EXPECT_STREQ("0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15", subnet); + + ip[0] = '\0'; + subnet[0] = '\0'; + strncpy(s, "1.2.3.4\0", 8); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("1.2.3.4", ip); + EXPECT_STREQ("", subnet); + + ip[0] = '\0'; + subnet[0] = '\0'; + strncpy(s, "1.2.3.4.5.6.7.8\0", 16); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("1.2.3.4", ip); + EXPECT_STREQ("5.6.7.8", subnet); + + ip[0] = '\0'; + subnet[0] = '\0'; + strncpy(s, "1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16\0", 39); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("102:304:506:708:90A:B0C:D0E:F10", ip); + EXPECT_STREQ("", subnet); + + ip[0] = '\0'; + subnet[0] = '\0'; + strncpy(s, "32:1:20:187:1:112:139:245:251:136:232:110:123:51:230:138\0", 57); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("32:1:20:187:1:112:139:245:251:136:232:110:123:51:230:138", ip); + EXPECT_STREQ("", subnet); + + ip[0] = '\0'; + subnet[0] = '\0'; + strncpy(s, "1.2.3.4 32:1:20:187:1:112:139:245:251:136:232:110:123:51:230:138\0", 65); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("1.2.3.4", ip); + EXPECT_STREQ("32:1:20:187:1:112:139:245:251:136:232:110:123:51:230:138", subnet); + + ip[0] = '\0'; + subnet[0] = '\0'; + strncpy(s, "1.2.3.4 5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20\0", 51); + separate_ip_addresses(s, ip, sizeof(ip), subnet, sizeof(subnet)); + EXPECT_STREQ("1.2.3.4", ip); + EXPECT_STREQ("506:708:90A:B0C:D0E:F10:1112:1314", subnet); + EXPECT_STREQ("1.2.3.4 5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20", s); + + free(s); +} diff --git a/UNITTESTS/features/cellular/framework/common/util/test_util.h b/UNITTESTS/features/cellular/framework/common/util/test_util.h new file mode 100644 index 0000000..bb968ef --- /dev/null +++ b/UNITTESTS/features/cellular/framework/common/util/test_util.h @@ -0,0 +1,37 @@ +/* + * 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. + */ +#ifndef TEST_UTIL_H +#define TEST_UTIL_H + +class Test_util { +public: + Test_util(); + + virtual ~Test_util(); + + void test_util_uint_to_binary_string(); + + void test_util_char_str_to_hex(); + + void test_util_convert_ipv6(); + + void test_util_prefer_ipv6(); + + void test_util_separate_ip_addresses(); +}; + +#endif // TEST_UTIL_H diff --git a/UNITTESTS/features/cellular/framework/common/util/unittest.cmake b/UNITTESTS/features/cellular/framework/common/util/unittest.cmake new file mode 100644 index 0000000..0b6370d --- /dev/null +++ b/UNITTESTS/features/cellular/framework/common/util/unittest.cmake @@ -0,0 +1,26 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "cellular_framework_common_util") + +# Add test specific include paths +set(unittest-includes ${unittest-includes} + features/cellular/framework/common/util + ../features/cellular/framework/common + ../features/frameworks/mbed-client-randlib/mbed-client-randlib +) + +# Source files +set(unittest-sources + ../features/cellular/framework/common/CellularUtil.cpp +) + +# Test files +set(unittest-test-sources + stubs/randLIB_stub.c + features/cellular/framework/common/util/test_util.cpp + features/cellular/framework/common/util/utiltest.cpp +) diff --git a/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp b/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp new file mode 100644 index 0000000..deaa0c5 --- /dev/null +++ b/UNITTESTS/features/cellular/framework/common/util/utiltest.cpp @@ -0,0 +1,63 @@ +/* + * 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 "test_util.h" + +class TestUtil : public testing::Test { +protected: + Test_util *unit; + + virtual void SetUp() + { + unit = new Test_util(); + } + + virtual void TearDown() + { + delete unit; + } +}; + +TEST_F(TestUtil, Create) +{ + EXPECT_TRUE(unit); +} + +TEST_F(TestUtil, test_util_uint_to_binary_string) +{ + unit->test_util_uint_to_binary_string(); +} + +TEST_F(TestUtil, char_str_to_hex) +{ + unit->test_util_char_str_to_hex(); +} + +TEST_F(TestUtil, convert_ipv6) +{ + unit->test_util_convert_ipv6(); +} + +TEST_F(TestUtil, prefer_ipv6) +{ + unit->test_util_prefer_ipv6(); +} + +TEST_F(TestUtil, separate_ip_addresses) +{ + unit->test_util_separate_ip_addresses(); +} diff --git a/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp b/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp new file mode 100644 index 0000000..fae48b7 --- /dev/null +++ b/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp @@ -0,0 +1,159 @@ +/* + * 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/InternetSocket.h" +#include "NetworkStack_stub.h" + +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; + } + virtual nsapi_size_or_error_t send(const void *data, nsapi_size_t size) + { + return return_value; + } + virtual nsapi_size_or_error_t recv(void *data, nsapi_size_t size) + { + return return_value; + } + virtual nsapi_size_or_error_t sendto(const SocketAddress &address, + const void *data, nsapi_size_t size) + { + return return_value; + } + virtual nsapi_size_or_error_t recvfrom(SocketAddress *address, + void *data, nsapi_size_t size) + { + return return_value; + } + virtual Socket *accept(nsapi_error_t *error = NULL) + { + return NULL; + } + virtual nsapi_error_t listen(int backlog = 1) + { + return return_value; + } +protected: + virtual nsapi_protocol_t get_proto() + { + return NSAPI_TCP; + } +}; + +static bool callback_is_called; +static void my_callback() +{ + callback_is_called = true; +} + +class TestInternetSocket : public testing::Test { +protected: + stubInternetSocket *socket; + NetworkStackstub stack; + + virtual void SetUp() + { + socket = new stubInternetSocket; + } + + virtual void TearDown() + { + delete socket; + } +}; + +TEST_F(TestInternetSocket, constructor) +{ + EXPECT_TRUE(socket); +} + + +TEST_F(TestInternetSocket, open_null_stack) +{ + EXPECT_EQ(socket->open(NULL), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestInternetSocket, open_error) +{ + stack.return_value = NSAPI_ERROR_PARAMETER; + EXPECT_EQ(socket->open((NetworkStack *)&stack), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestInternetSocket, open) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->open((NetworkStack *)&stack), NSAPI_ERROR_OK); +} + +TEST_F(TestInternetSocket, open_twice) +{ + stack.return_value = NSAPI_ERROR_OK; + EXPECT_EQ(socket->open((NetworkStack *)&stack), NSAPI_ERROR_OK); + EXPECT_EQ(socket->open((NetworkStack *)&stack), NSAPI_ERROR_PARAMETER); +} + +TEST_F(TestInternetSocket, close) +{ + stack.return_value = NSAPI_ERROR_OK; + socket->open((NetworkStack *)&stack); + 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); + + 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) +{ + socket->set_blocking(false); + socket->set_blocking(true); +} + +TEST_F(TestInternetSocket, setsockopt_no_stack) +{ + socket->close(); + EXPECT_EQ(socket->setsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET); +} + +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->attach(mbed::callback(my_callback)); + socket->event(); + EXPECT_EQ(callback_is_called, true); +} diff --git a/UNITTESTS/features/netsocket/InternetSocket/unittest.cmake b/UNITTESTS/features/netsocket/InternetSocket/unittest.cmake new file mode 100644 index 0000000..0a8eb89 --- /dev/null +++ b/UNITTESTS/features/netsocket/InternetSocket/unittest.cmake @@ -0,0 +1,24 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "features_netsocket_InternetSocket") + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp +) + +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/InternetSocket/test_InternetSocket.cpp +) diff --git a/UNITTESTS/features/netsocket/NetworkInterface/test_NetworkInterface.cpp b/UNITTESTS/features/netsocket/NetworkInterface/test_NetworkInterface.cpp new file mode 100644 index 0000000..9ea4937 --- /dev/null +++ b/UNITTESTS/features/netsocket/NetworkInterface/test_NetworkInterface.cpp @@ -0,0 +1,60 @@ +/* + * 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/NetworkInterface.h" + +class stubNetworkInterface : public NetworkInterface { + virtual nsapi_error_t connect() + { + return NSAPI_ERROR_OK; + }; + virtual nsapi_error_t disconnect() + { + return NSAPI_ERROR_OK; + }; + virtual NetworkStack *get_stack() + { + return NULL; + }; +}; + +class TestNetworkInterface : public testing::Test { +protected: + NetworkInterface *iface; + + virtual void SetUp() + { + iface = new stubNetworkInterface(); + } + + virtual void TearDown() + { + delete iface; + } +}; + +TEST_F(TestNetworkInterface, constructor) +{ + EXPECT_TRUE(iface); +} + +TEST_F(TestNetworkInterface, get_mac_address) +{ + char *n = 0; + EXPECT_EQ(iface->get_mac_address(), n); +} diff --git a/UNITTESTS/features/netsocket/NetworkInterface/unittest.cmake b/UNITTESTS/features/netsocket/NetworkInterface/unittest.cmake new file mode 100644 index 0000000..60bc2b0 --- /dev/null +++ b/UNITTESTS/features/netsocket/NetworkInterface/unittest.cmake @@ -0,0 +1,17 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "features_netsocket_NetworkInterface") + +# Source files +set(unittest-sources + ../features/netsocket/NetworkInterface.cpp +) + +# Test files +set(unittest-test-sources + features/netsocket/NetworkInterface/test_NetworkInterface.cpp +) diff --git a/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp b/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp new file mode 100644 index 0000000..113baa2 --- /dev/null +++ b/UNITTESTS/features/netsocket/TCPSocket/test_TCPSocket.cpp @@ -0,0 +1,39 @@ +/* + * 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" + +class TestTCPSocket : public testing::Test { +protected: + TCPSocket *socket; + + virtual void SetUp() + { + socket = new TCPSocket(); + } + + virtual void TearDown() + { + delete socket; + } +}; + +TEST_F(TestTCPSocket, constructor) +{ + EXPECT_TRUE(socket); +} diff --git a/UNITTESTS/features/netsocket/TCPSocket/unittest.cmake b/UNITTESTS/features/netsocket/TCPSocket/unittest.cmake new file mode 100644 index 0000000..aa1d97a --- /dev/null +++ b/UNITTESTS/features/netsocket/TCPSocket/unittest.cmake @@ -0,0 +1,20 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "features_netsocket_TCPSocket") + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/TCPSocket.cpp +) + +set(unittest-test-sources + stubs/Mutex_stub.cpp + stubs/mbed_assert_stub.c + stubs/EventFlags_stub.cpp + features/netsocket/TCPSocket/test_TCPSocket.cpp +) diff --git a/UNITTESTS/features/netsocket/UDPSocket/test_UDPSocket.cpp b/UNITTESTS/features/netsocket/UDPSocket/test_UDPSocket.cpp new file mode 100644 index 0000000..7c590e7 --- /dev/null +++ b/UNITTESTS/features/netsocket/UDPSocket/test_UDPSocket.cpp @@ -0,0 +1,81 @@ +/* + * 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/nsapi_dns.h" +#include "NetworkStack_stub.h" + +/** + * This test needs to access a private function + * which is why it is declared as friend + * following the documentation of google test. + * [*](https://github.com/google/googletest/blob/master/googletest/docs/advanced.md) + */ +class stubUDPSocket : public UDPSocket { + friend class TestUDPSocket; + FRIEND_TEST(TestUDPSocket, get_proto); +}; + +class TestUDPSocket : public testing::Test { +protected: + stubUDPSocket *socket; + NetworkStackstub stack; + + virtual void SetUp() + { + socket = new stubUDPSocket; + stack.return_value = NSAPI_ERROR_OK; + socket->open((NetworkStack *)&stack); + } + + virtual void TearDown() + { + delete socket; + } +}; + +TEST_F(TestUDPSocket, get_proto) +{ + EXPECT_EQ(socket->get_proto(), NSAPI_UDP); +} + +TEST_F(TestUDPSocket, sendto_addr_port) +{ + 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) +{ + SocketAddress addr("127.0.0.1", 1024); + stack.return_value = NSAPI_ERROR_OK; + + 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; + 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); +} diff --git a/UNITTESTS/features/netsocket/UDPSocket/unittest.cmake b/UNITTESTS/features/netsocket/UDPSocket/unittest.cmake new file mode 100644 index 0000000..0444c44 --- /dev/null +++ b/UNITTESTS/features/netsocket/UDPSocket/unittest.cmake @@ -0,0 +1,25 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "features_netsocket_UDPSocket") + +set(unittest-sources + ../features/netsocket/SocketAddress.cpp + ../features/netsocket/NetworkStack.cpp + ../features/netsocket/InternetSocket.cpp + ../features/netsocket/UDPSocket.cpp +) + +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/EventFlags_stub.cpp + stubs/nsapi_dns_stub.cpp + features/netsocket/UDPSocket/test_UDPSocket.cpp +) diff --git a/UNITTESTS/googletest-CMakeLists.txt.in b/UNITTESTS/googletest-CMakeLists.txt.in new file mode 100644 index 0000000..9041496 --- /dev/null +++ b/UNITTESTS/googletest-CMakeLists.txt.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.11) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 8bc11c040a1dcbe50c340b21d78175d152dd3837 + SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) \ No newline at end of file diff --git a/UNITTESTS/mbed_unittest.py b/UNITTESTS/mbed_unittest.py new file mode 100755 index 0000000..e8e6ead --- /dev/null +++ b/UNITTESTS/mbed_unittest.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2018, Arm Limited +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. + + +UNIT TEST BUILD & RUN +""" + +from __future__ import print_function +import os +import logging + +from unit_test.options import get_options_parser, \ + pretty_print_test_options +from unit_test.settings import DEFAULT_CMAKE_GENERATORS +from unit_test.test import UnitTestTool +from unit_test.new import UnitTestGeneratorTool + +def _mbed_unittest_test(options, cwd, pwd): + if options is None: + return + + if options.coverage: + options.debug_build = True + + if options.cmake_generator is None: + options.cmake_generator = DEFAULT_CMAKE_GENERATORS.get( + options.make_program, + "Unix Makefiles") + + # Do not clean directory if only run. + if options.clean and options.run_only and not options.compile_only: + options.clean = False + + # Build and run by default + if (not options.compile_only and + not options.run_only and + not options.clean): + options.compile_only = True + options.run_only = True + + # Set build path + if not os.path.isabs(options.build): + options.build = os.path.normpath( + os.path.join(cwd, options.build)) + + pretty_print_test_options(options) + + # Create test tool + tool = UnitTestTool(make_program=options.make_program) + + # Prepare build directory + tool.prepare_build_directory(path_to_src=pwd, + build_path=options.build, + clean=options.clean) + + if options.compile_only: + # Create makefiles + src_path = os.path.relpath(pwd, options.build) + tool.create_makefiles(path_to_src=src_path, + generator=options.cmake_generator, + coverage_output_type=options.coverage, + debug=options.debug_build) + + # Build tests + tool.build_tests() + + if options.run_only: + # If code coverage generation: + if options.coverage: + # Run tests and generate reports + tool.generate_coverage_report(coverage_output_type=options.coverage, + excludes=[pwd, options.build], + build_path=options.build) + else: + tool.run_tests(filter_regex=options.test_regex) # Only run tests + +def _mbed_unittest_new(options, pwd): + if options is None: + return + + generator = UnitTestGeneratorTool() + + mbed_os_root = os.path.normpath( + os.path.join(pwd, "..") + ) + + for filepath in options.new_files: + generator.create( + mbed_os_root=mbed_os_root, + filepath=filepath) + +def mbed_unittest(options=None): + """ + Create, build and run unit tests + """ + + if options is None: + return + + cwd = os.getcwd() + + # Change current working directory to script location + unittest_dir = os.path.dirname(os.path.realpath(__file__)) + os.chdir(unittest_dir) + + if options.new_files: + _mbed_unittest_new(options, unittest_dir) + else: + _mbed_unittest_test(options, cwd, unittest_dir) + +def mbed_unittest_main(): + """ + Create, build and run unit tests - main + """ + + # Get parser and parse command line arguments + parser = get_options_parser() + options = parser.parse_args() + + # Setup logger + if options.log_level: + logging.basicConfig(level=getattr(logging, options.log_level), + format="%(message)s") + else: + logging.basicConfig(level=logging.INFO, + format="%(message)s") + + mbed_unittest(options) + +if __name__ == "__main__": + mbed_unittest_main() diff --git a/UNITTESTS/platform/CircularBuffer/test_CircularBuffer.cpp b/UNITTESTS/platform/CircularBuffer/test_CircularBuffer.cpp new file mode 100644 index 0000000..5286701 --- /dev/null +++ b/UNITTESTS/platform/CircularBuffer/test_CircularBuffer.cpp @@ -0,0 +1,39 @@ +/* + * 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 "platform/CircularBuffer.h" + +class TestCircularBuffer : public testing::Test { +protected: + mbed::CircularBuffer *buf; + + virtual void SetUp() + { + buf = new mbed::CircularBuffer; + } + + virtual void TearDown() + { + delete buf; + } +}; + +TEST_F(TestCircularBuffer, constructor) +{ + EXPECT_TRUE(buf); +} diff --git a/UNITTESTS/platform/CircularBuffer/unittest.cmake b/UNITTESTS/platform/CircularBuffer/unittest.cmake new file mode 100644 index 0000000..d6842be --- /dev/null +++ b/UNITTESTS/platform/CircularBuffer/unittest.cmake @@ -0,0 +1,14 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "platform_CircularBuffer") + +set(unittest-sources +) + +set(unittest-test-sources + platform/CircularBuffer/test_CircularBuffer.cpp +) diff --git a/UNITTESTS/stubs/ATHandler_stub.cpp b/UNITTESTS/stubs/ATHandler_stub.cpp new file mode 100644 index 0000000..cee8e30 --- /dev/null +++ b/UNITTESTS/stubs/ATHandler_stub.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2017, 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 +#include "nsapi_types.h" +#include "ATHandler.h" +#include "EventQueue.h" +#include "ATHandler_stub.h" + +using namespace mbed; +using namespace events; + +#include "CellularLog.h" + +const int DEFAULT_AT_TIMEOUT = 1000; // at default timeout in milliseconds + +nsapi_error_t ATHandler_stub::nsapi_error_value = 0; +uint8_t ATHandler_stub::nsapi_error_ok_counter = 0; +int ATHandler_stub::int_value = -1; +ssize_t ATHandler_stub::ssize_value = 0; +char *ATHandler_stub::read_string_value = NULL; +size_t ATHandler_stub::size_value = 0; +size_t ATHandler_stub::return_given_size = false; +bool ATHandler_stub::bool_value = false; +uint8_t ATHandler_stub::uint8_value = 0; +FileHandle_stub *ATHandler_stub::fh_value = NULL; +device_err_t ATHandler_stub::device_err_value; +Callback ATHandler_stub::callback = NULL; +uint8_t ATHandler_stub::resp_info_true_counter = false; + +ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) : _nextATHandler(0), + _fileHandle(fh), + _queue(queue) +{ +} + +ATHandler::~ATHandler() +{ +} + +void ATHandler::inc_ref_count() +{ +} + +void ATHandler::dec_ref_count() +{ +} + +int ATHandler::get_ref_count() +{ + return ATHandler_stub::int_value; +} + +FileHandle *ATHandler::get_file_handle() +{ + return ATHandler_stub::fh_value; +} + +void ATHandler::set_file_handle(FileHandle *fh) +{ +} + +nsapi_error_t ATHandler::set_urc_handler(const char *urc, mbed::Callback cb) +{ + ATHandler_stub::callback = cb; + return NSAPI_ERROR_OK; +} + +void ATHandler::remove_urc_handler(const char *prefix, mbed::Callback callback) +{ +} + +nsapi_error_t ATHandler::get_last_error() const +{ + if (ATHandler_stub::nsapi_error_ok_counter) { + ATHandler_stub::nsapi_error_ok_counter--; + return NSAPI_ERROR_OK; + } + return ATHandler_stub::nsapi_error_value; +} + +void ATHandler::lock() +{ +} + +void ATHandler::unlock() +{ +} + +nsapi_error_t ATHandler::unlock_return_error() +{ + return ATHandler_stub::nsapi_error_value; +} + +void ATHandler::set_at_timeout(uint32_t timeout_milliseconds, bool default_timeout) +{ +} + +void ATHandler::restore_at_timeout() +{ +} + +void ATHandler::process_oob() +{ +} + +void ATHandler::clear_error() +{ +} + +void ATHandler::skip_param(uint32_t count) +{ +} + +void ATHandler::skip_param(ssize_t len, uint32_t count) +{ +} + +ssize_t ATHandler::read_bytes(uint8_t *buf, size_t len) +{ + return ATHandler_stub::ssize_value; +} + +ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag) +{ + if (ATHandler_stub::read_string_value && ATHandler_stub::ssize_value >= 0) { + memcpy(buf, ATHandler_stub::read_string_value, ATHandler_stub::ssize_value); + } + return ATHandler_stub::ssize_value; +} + +int ATHandler::read_int() +{ + return ATHandler_stub::int_value; +} + +void ATHandler::set_delimiter(char delimiter) +{ +} + +void ATHandler::set_default_delimiter() +{ +} + +void ATHandler::set_stop_tag(const char *stop_tag_seq) +{ +} + +int ATHandler::get_3gpp_error() +{ + return ATHandler_stub::int_value; +} + +void ATHandler::resp_start(const char *prefix, bool stop) +{ +} + +bool ATHandler::info_resp() +{ + if (ATHandler_stub::resp_info_true_counter) { + ATHandler_stub::resp_info_true_counter--; + return true; + } + return ATHandler_stub::bool_value; +} + +bool ATHandler::info_elem(char start_tag) +{ + return ATHandler_stub::bool_value; +} + +bool ATHandler::consume_to_stop_tag() +{ + return ATHandler_stub::bool_value; +} + +void ATHandler::resp_stop() +{ +} + +void ATHandler::cmd_start(const char *cmd) +{ +} + +void ATHandler::write_int(int param) +{ +} + +void ATHandler::write_string(const char *param, bool useQuotations) +{ +} + +size_t ATHandler::write_bytes(const uint8_t *param, size_t len) +{ + if (ATHandler_stub::return_given_size) { + return len; + } + return ATHandler_stub::size_value; +} + +void ATHandler::cmd_stop() +{ +} + +device_err_t ATHandler::get_last_device_error() const +{ + return ATHandler_stub::device_err_value; +} + +void ATHandler::flush() +{ +} diff --git a/UNITTESTS/stubs/ATHandler_stub.h b/UNITTESTS/stubs/ATHandler_stub.h new file mode 100644 index 0000000..6ea9566 --- /dev/null +++ b/UNITTESTS/stubs/ATHandler_stub.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, 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 "stdint.h" +#include "stdbool.h" +#include +#include "nsapi_types.h" +#include "ATHandler.h" +#include "FileHandle_stub.h" +#include "Callback.h" + +namespace ATHandler_stub +{ + +extern nsapi_error_t nsapi_error_value; +extern uint8_t nsapi_error_ok_counter; +extern int int_value; +extern ssize_t ssize_value; +extern char *read_string_value; +extern size_t size_value; +extern size_t return_given_size; +extern bool bool_value; +extern uint8_t resp_info_true_counter; +extern uint8_t uint8_value; +extern mbed::FileHandle_stub *fh_value; +extern mbed::device_err_t device_err_value; +extern mbed::Callback callback; + +} // namespace ATHandler_stub diff --git a/UNITTESTS/stubs/EventFlags_stub.cpp b/UNITTESTS/stubs/EventFlags_stub.cpp new file mode 100644 index 0000000..95762b8 --- /dev/null +++ b/UNITTESTS/stubs/EventFlags_stub.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, 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 "rtos/EventFlags.h" + +rtos::EventFlags::EventFlags() {} +rtos::EventFlags::~EventFlags() {} +uint32_t rtos::EventFlags::set(uint32_t flags) +{ + return 0; +} +uint32_t rtos::EventFlags::clear(uint32_t flags) +{ + return 0; +} +uint32_t rtos::EventFlags::get() const +{ + return 0; +} +uint32_t rtos::EventFlags::wait_all(uint32_t flags, uint32_t timeout, bool clear) +{ + return 0; +} +uint32_t rtos::EventFlags::wait_any(uint32_t flags, uint32_t timeout, bool clear) +{ + return 0; +} diff --git a/UNITTESTS/stubs/EventQueue_stub.cpp b/UNITTESTS/stubs/EventQueue_stub.cpp new file mode 100644 index 0000000..e343664 --- /dev/null +++ b/UNITTESTS/stubs/EventQueue_stub.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017, 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 "EventQueue.h" +#include "Callback.h" + +using namespace mbed; + +namespace events { + +EventQueue::EventQueue(unsigned event_size, unsigned char *event_pointer) +{ +} + +EventQueue::~EventQueue() +{ +} + +void EventQueue::dispatch(int ms) +{ +} + +void EventQueue::break_dispatch() +{ +} + +unsigned EventQueue::tick() +{ + return 0; +} + +void EventQueue::cancel(int id) +{ +} + +void EventQueue::background(Callback update) +{ +} + +void EventQueue::chain(EventQueue *target) +{ +} + +} // namespace events diff --git a/UNITTESTS/stubs/FileHandle_stub.cpp b/UNITTESTS/stubs/FileHandle_stub.cpp new file mode 100644 index 0000000..03b7625 --- /dev/null +++ b/UNITTESTS/stubs/FileHandle_stub.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) , 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 "FileHandle_stub.h" + +namespace mbed { + +off_t FileHandle::size() +{ + return 0; +} + +std::FILE *fdopen(FileHandle *fh, const char *mode) +{ + return NULL; +} + +} // namespace mbed diff --git a/UNITTESTS/stubs/FileHandle_stub.h b/UNITTESTS/stubs/FileHandle_stub.h new file mode 100644 index 0000000..ef68572 --- /dev/null +++ b/UNITTESTS/stubs/FileHandle_stub.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) , 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. + */ +#ifndef __FILE_HANDLE_STUB_H__ +#define __FILE_HANDLE_STUB_H__ + +#include "FileHandle.h" + +namespace mbed +{ + +static uint8_t filehandle_stub_short_value_counter = 0; +static char *filehandle_stub_table = NULL; +static uint8_t filehandle_stub_table_pos = 0; + +class FileHandle_stub : public FileHandle +{ + public: + ssize_t size_value; + + FileHandle_stub() { size_value = 0; } + + virtual ssize_t read(void *buffer, size_t size) + { + if (filehandle_stub_table) + { + ssize_t ret = strlen(filehandle_stub_table) - filehandle_stub_table_pos; + if (size < ret) + { + ret = size; + } + memcpy(buffer, filehandle_stub_table, ret); + filehandle_stub_table_pos += ret; + return ret; + } + return 0; + } + + virtual ssize_t write(const void *buffer, size_t size) + { + if (size_value > 0) + { + size_value--; + return size; + } + else if (size_value < 0) + { + return -1; + } + return 0; + } + + virtual off_t seek(off_t offset, int whence = SEEK_SET) { return 0; } + + virtual int close() {} + + virtual short poll(short events) const + { + if (filehandle_stub_short_value_counter) + { + filehandle_stub_short_value_counter--; + return short_value; + } + return 0; + } + + virtual void sigio(Callback func) { func(); } + + short short_value; +}; + +} // namespace mbed + +#endif diff --git a/UNITTESTS/stubs/Mutex_stub.cpp b/UNITTESTS/stubs/Mutex_stub.cpp new file mode 100644 index 0000000..c287d3b --- /dev/null +++ b/UNITTESTS/stubs/Mutex_stub.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017, 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 "rtos/Mutex.h" + +rtos::Mutex::Mutex() +{ + return; +} + +rtos::Mutex::~Mutex() +{ + return; +} + +osStatus rtos::Mutex::lock(unsigned int) +{ + return osOK; +} + +osStatus rtos::Mutex::unlock() +{ + return osOK; +} diff --git a/UNITTESTS/stubs/NetworkStack_stub.h b/UNITTESTS/stubs/NetworkStack_stub.h new file mode 100644 index 0000000..2d18f94 --- /dev/null +++ b/UNITTESTS/stubs/NetworkStack_stub.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef NETWORKSTACKSTUB_H +#define NETWORKSTACKSTUB_H + +#include "netsocket/NetworkStack.h" + + +class NetworkStackstub : public NetworkStack { +public: + nsapi_error_t return_value = 0; + virtual const char *get_ip_address() + { + return "127.0.0.1"; + } + virtual nsapi_error_t gethostbyname(const char *host, + SocketAddress *address, nsapi_version_t version) + { + return return_value; + } + virtual nsapi_value_or_error_t gethostbyname_async(const char *host, hostbyname_cb_t callback, + nsapi_version_t version) + { + return return_value; + } + virtual nsapi_error_t gethostbyname_async_cancel(int id) + { + return return_value; + } + +protected: + virtual nsapi_error_t socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) + { + return return_value; + }; + virtual nsapi_error_t socket_close(nsapi_socket_t handle) + { + return return_value; + }; + virtual nsapi_error_t socket_bind(nsapi_socket_t handle, const SocketAddress &address) + { + return return_value; + }; + virtual nsapi_error_t socket_listen(nsapi_socket_t handle, int backlog) + { + return return_value; + }; + virtual nsapi_error_t socket_connect(nsapi_socket_t handle, const SocketAddress &address) + { + return return_value; + }; + virtual nsapi_error_t socket_accept(nsapi_socket_t server, + nsapi_socket_t *handle, SocketAddress *address = 0) + { + return return_value; + }; + virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle, + const void *data, nsapi_size_t size) + { + return return_value; + }; + virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle, + void *data, nsapi_size_t size) + { + return return_value; + }; + virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t handle, const SocketAddress &address, + const void *data, nsapi_size_t size) + { + return return_value; + }; + virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address, + void *buffer, nsapi_size_t size) + { + return return_value; + }; + virtual void socket_attach(nsapi_socket_t handle, void (*callback)(void *), void *data) {}; + +private: + virtual nsapi_error_t call_in(int delay, mbed::Callback func) + { + return return_value; + } +}; + +#endif // NETWORKSTACKSTUB_H diff --git a/UNITTESTS/stubs/equeue_stub.c b/UNITTESTS/stubs/equeue_stub.c new file mode 100644 index 0000000..bd9852b --- /dev/null +++ b/UNITTESTS/stubs/equeue_stub.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, 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 "equeue/equeue.h" + +void *equeue_alloc(equeue_t *q, size_t size) +{ +} + +int equeue_post(equeue_t *q, void (*cb)(void *), void *p) +{ + return 0; +} + +void equeue_event_delay(void *p, int ms) +{ +} + +void equeue_event_period(void *p, int ms) +{ +} + +void equeue_event_dtor(void *p, void (*dtor)(void *)) +{ +} diff --git a/UNITTESTS/stubs/mbed_assert_stub.c b/UNITTESTS/stubs/mbed_assert_stub.c new file mode 100644 index 0000000..9029a61 --- /dev/null +++ b/UNITTESTS/stubs/mbed_assert_stub.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, 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 "platform/mbed_assert.h" +#include + +void mbed_assert_internal(const char *expr, const char *file, int line) +{ + fprintf(stderr, "mbed assertation failed: %s, file: %s, line %d \n", expr, file, line); +} diff --git a/UNITTESTS/stubs/mbed_shared_queues_stub.cpp b/UNITTESTS/stubs/mbed_shared_queues_stub.cpp new file mode 100644 index 0000000..e0c0c2b --- /dev/null +++ b/UNITTESTS/stubs/mbed_shared_queues_stub.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, 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 "events/mbed_shared_queues.h" + +using namespace events; + +namespace mbed { + +EventQueue *mbed_event_queue() +{ + return 0; +} +} // namespace mbed diff --git a/UNITTESTS/stubs/nsapi_dns_stub.cpp b/UNITTESTS/stubs/nsapi_dns_stub.cpp new file mode 100644 index 0000000..dcfe7ef --- /dev/null +++ b/UNITTESTS/stubs/nsapi_dns_stub.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, 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 "netsocket/nsapi_dns.h" + + +nsapi_error_t nsapi_stub_return_value = NSAPI_ERROR_DNS_FAILURE; + +nsapi_error_t nsapi_dns_query(NetworkStack *stack, const char *host, + SocketAddress *addr, nsapi_version_t version) +{ + return nsapi_stub_return_value; +} + +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) +{ + return nsapi_stub_return_value; +} + +nsapi_error_t nsapi_dns_query_async_cancel(nsapi_error_t id) +{ + return nsapi_stub_return_value; +} + +extern "C" nsapi_error_t nsapi_dns_add_server(nsapi_addr_t addr) +{ + return NSAPI_ERROR_OK; +} diff --git a/UNITTESTS/stubs/nvic_wrapper_stub.c b/UNITTESTS/stubs/nvic_wrapper_stub.c new file mode 100644 index 0000000..636f05b --- /dev/null +++ b/UNITTESTS/stubs/nvic_wrapper_stub.c @@ -0,0 +1,3 @@ +#include "nvic_wrapper.h" + +void NVIC_SystemReset(void) {} diff --git a/UNITTESTS/stubs/randLIB_stub.c b/UNITTESTS/stubs/randLIB_stub.c new file mode 100644 index 0000000..97154cf --- /dev/null +++ b/UNITTESTS/stubs/randLIB_stub.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014-2017, 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 +#include +#include +#include +#include "randLIB.h" +#include "platform/arm_hal_random.h" + +#if ((RAND_MAX+1) & RAND_MAX) != 0 +#error "RAND_MAX isn't 2^n-1 :(" +#endif + +int counter = 1; + +void randLIB_seed_random(void) +{ +} + +uint8_t randLIB_get_8bit(void) +{ + return 0; +} + +uint16_t randLIB_get_16bit(void) +{ + return 0; +} + +uint32_t randLIB_get_32bit(void) +{ + return 0; +} + +void *randLIB_get_n_bytes_random(void *data_ptr, uint8_t count) +{ + if (data_ptr && count > 0) { + *((int *)data_ptr) = counter++ % 255; + } + return data_ptr; +} + +uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max) +{ + return 0; +} + +uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor) +{ + return 0; +} diff --git a/UNITTESTS/target_h/PeripheralNames.h b/UNITTESTS/target_h/PeripheralNames.h new file mode 100644 index 0000000..3ca0e7b --- /dev/null +++ b/UNITTESTS/target_h/PeripheralNames.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#endif diff --git a/UNITTESTS/target_h/PinNames.h b/UNITTESTS/target_h/PinNames.h new file mode 100644 index 0000000..01de8ce --- /dev/null +++ b/UNITTESTS/target_h/PinNames.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +typedef enum { + NC = (int)0xFFFFFFFF +} PinName; + +typedef enum { +} PinMode; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/UNITTESTS/target_h/device.h b/UNITTESTS/target_h/device.h new file mode 100644 index 0000000..80d55af --- /dev/null +++ b/UNITTESTS/target_h/device.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_DEVICE_H +#define MBED_DEVICE_H + +#include "objects.h" + +#endif diff --git a/UNITTESTS/target_h/events/equeue/equeue_platform.h b/UNITTESTS/target_h/events/equeue/equeue_platform.h new file mode 100644 index 0000000..7d9f968 --- /dev/null +++ b/UNITTESTS/target_h/events/equeue/equeue_platform.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef EQUEUE_PLATFORM_H +#define EQUEUE_PLATFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef unsigned equeue_mutex_t; + +typedef struct equeue_sema { +} equeue_sema_t; + +#ifdef __cplusplus +} +#endif + +#endif //EQUEUE_PLATFORM_H diff --git a/UNITTESTS/target_h/events/mbed_events.h b/UNITTESTS/target_h/events/mbed_events.h new file mode 100644 index 0000000..5916e02 --- /dev/null +++ b/UNITTESTS/target_h/events/mbed_events.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_EVENTS_H +#define MBED_EVENTS_H + +#include "EventQueue.h" + +#include "events/mbed_shared_queues.h" + +#endif diff --git a/UNITTESTS/target_h/gpio_object.h b/UNITTESTS/target_h/gpio_object.h new file mode 100644 index 0000000..a344bb3 --- /dev/null +++ b/UNITTESTS/target_h/gpio_object.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_GPIO_OBJECT_H +#define MBED_GPIO_OBJECT_H + +#include "mbed_assert.h" +#include "PeripheralNames.h" +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { +} gpio_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/UNITTESTS/target_h/ip6string.h b/UNITTESTS/target_h/ip6string.h new file mode 100644 index 0000000..d1d4ac2 --- /dev/null +++ b/UNITTESTS/target_h/ip6string.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef IP6STRING_H +#define IP6STRING_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +uint_fast8_t ip6tos(const void *ip6addr, char *p) +{ + return 0; +} + +void stoip6(const char *ip6addr, size_t len, void *dest) {} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/UNITTESTS/target_h/mbed.h b/UNITTESTS/target_h/mbed.h new file mode 100644 index 0000000..1f88324 --- /dev/null +++ b/UNITTESTS/target_h/mbed.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_H +#define MBED_H + +#include +#include + +#include "events/mbed_events.h" + +namespace mbed { +#include "platform/Callback.h" +}; + +using namespace mbed; +using namespace std; + +#endif // MBED_H diff --git a/UNITTESTS/target_h/mbed_rtos1_types.h b/UNITTESTS/target_h/mbed_rtos1_types.h new file mode 100644 index 0000000..e200f18 --- /dev/null +++ b/UNITTESTS/target_h/mbed_rtos1_types.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_RTOS1_TYPES_H +#define MBED_RTOS1_TYPES_H + +#include "mbed_rtos_storage.h" + +#endif // MBED_RTOS1_TYPES_H diff --git a/UNITTESTS/target_h/mbed_rtos_storage.h b/UNITTESTS/target_h/mbed_rtos_storage.h new file mode 100644 index 0000000..48923f2 --- /dev/null +++ b/UNITTESTS/target_h/mbed_rtos_storage.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_RTOS_STORAGE_H +#define MBED_RTOS_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cmsis_os2.h" + +typedef osMutexId_t mbed_rtos_storage_mutex_t; +typedef osSemaphoreId_t mbed_rtos_storage_semaphore_t; +typedef osThreadId_t mbed_rtos_storage_thread_t; +typedef osThreadId_t osThreadId; +typedef osMemoryPoolId_t mbed_rtos_storage_mem_pool_t; +typedef osMessageQueueId_t mbed_rtos_storage_msg_queue_t; +typedef osEventFlagsId_t mbed_rtos_storage_event_flags_t; +typedef void *mbed_rtos_storage_message_t; +typedef osTimerId_t mbed_rtos_storage_timer_t; +typedef osStatus_t osStatus; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/UNITTESTS/target_h/nvic_wrapper.h b/UNITTESTS/target_h/nvic_wrapper.h new file mode 100644 index 0000000..056ba48 --- /dev/null +++ b/UNITTESTS/target_h/nvic_wrapper.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef NVIC_WRAPPER_H +#define NVIC_WRAPPER_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +void NVIC_SystemReset(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif //NVIC_WRAPPER_H diff --git a/UNITTESTS/target_h/objects.h b/UNITTESTS/target_h/objects.h new file mode 100644 index 0000000..0e64f41 --- /dev/null +++ b/UNITTESTS/target_h/objects.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_OBJECTS_H +#define MBED_OBJECTS_H + +#include "PeripheralNames.h" +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gpio_object.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/UNITTESTS/target_h/platform/mbed_retarget.h b/UNITTESTS/target_h/platform/mbed_retarget.h new file mode 100644 index 0000000..0c513f5 --- /dev/null +++ b/UNITTESTS/target_h/platform/mbed_retarget.h @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef RETARGET_H +#define RETARGET_H + +#include + +#undef EPERM +#define EPERM 1 /* Operation not permitted */ +#undef ENOENT +#define ENOENT 2 /* No such file or directory */ +#undef ESRCH +#define ESRCH 3 /* No such process */ +#undef EINTR +#define EINTR 4 /* Interrupted system call */ +#undef EIO +#define EIO 5 /* I/O error */ +#undef ENXIO +#define ENXIO 6 /* No such device or address */ +#undef E2BIG +#define E2BIG 7 /* Argument list too long */ +#undef ENOEXEC +#define ENOEXEC 8 /* Exec format error */ +#undef EBADF +#define EBADF 9 /* Bad file number */ +#undef ECHILD +#define ECHILD 10 /* No child processes */ +#undef EAGAIN +#define EAGAIN 11 /* Try again */ +#undef ENOMEM +#define ENOMEM 12 /* Out of memory */ +#undef EACCES +#define EACCES 13 /* Permission denied */ +#undef EFAULT +#define EFAULT 14 /* Bad address */ +#undef ENOTBLK +#define ENOTBLK 15 /* Block device required */ +#undef EBUSY +#define EBUSY 16 /* Device or resource busy */ +#undef EEXIST +#define EEXIST 17 /* File exists */ +#undef EXDEV +#define EXDEV 18 /* Cross-device link */ +#undef ENODEV +#define ENODEV 19 /* No such device */ +#undef ENOTDIR +#define ENOTDIR 20 /* Not a directory */ +#undef EISDIR +#define EISDIR 21 /* Is a directory */ +#undef EINVAL +#define EINVAL 22 /* Invalid argument */ +#undef ENFILE +#define ENFILE 23 /* File table overflow */ +#undef EMFILE +#define EMFILE 24 /* Too many open files */ +#undef ENOTTY +#define ENOTTY 25 /* Not a typewriter */ +#undef ETXTBSY +#define ETXTBSY 26 /* Text file busy */ +#undef EFBIG +#define EFBIG 27 /* File too large */ +#undef ENOSPC +#define ENOSPC 28 /* No space left on device */ +#undef ESPIPE +#define ESPIPE 29 /* Illegal seek */ +#undef EROFS +#define EROFS 30 /* Read-only file system */ +#undef EMLINK +#define EMLINK 31 /* Too many links */ +#undef EPIPE +#define EPIPE 32 /* Broken pipe */ +#undef EDOM +#define EDOM 33 /* Math argument out of domain of func */ +#undef ERANGE +#define ERANGE 34 /* Math result not representable */ +#undef EDEADLK +#define EDEADLK 35 /* Resource deadlock would occur */ +#undef ENAMETOOLONG +#define ENAMETOOLONG 36 /* File name too long */ +#undef ENOLCK +#define ENOLCK 37 /* No record locks available */ +#undef ENOSYS +#define ENOSYS 38 /* Function not implemented */ +#undef ENOTEMPTY +#define ENOTEMPTY 39 /* Directory not empty */ +#undef ELOOP +#define ELOOP 40 /* Too many symbolic links encountered */ +#undef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#undef ENOMSG +#define ENOMSG 42 /* No message of desired type */ +#undef EIDRM +#define EIDRM 43 /* Identifier removed */ +#undef ECHRNG +#define ECHRNG 44 /* Channel number out of range */ +#undef EL2NSYNC +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#undef EL3HLT +#define EL3HLT 46 /* Level 3 halted */ +#undef EL3RST +#define EL3RST 47 /* Level 3 reset */ +#undef ELNRNG +#define ELNRNG 48 /* Link number out of range */ +#undef EUNATCH +#define EUNATCH 49 /* Protocol driver not attached */ +#undef ENOCSI +#define ENOCSI 50 /* No CSI structure available */ +#undef EL2HLT +#define EL2HLT 51 /* Level 2 halted */ +#undef EBADE +#define EBADE 52 /* Invalid exchange */ +#undef EBADR +#define EBADR 53 /* Invalid request descriptor */ +#undef EXFULL +#define EXFULL 54 /* Exchange full */ +#undef ENOANO +#define ENOANO 55 /* No anode */ +#undef EBADRQC +#define EBADRQC 56 /* Invalid request code */ +#undef EBADSLT +#define EBADSLT 57 /* Invalid slot */ +#undef EDEADLOCK +#define EDEADLOCK EDEADLK /* Resource deadlock would occur */ +#undef EBFONT +#define EBFONT 59 /* Bad font file format */ +#undef ENOSTR +#define ENOSTR 60 /* Device not a stream */ +#undef ENODATA +#define ENODATA 61 /* No data available */ +#undef ETIME +#define ETIME 62 /* Timer expired */ +#undef ENOSR +#define ENOSR 63 /* Out of streams resources */ +#undef ENONET +#define ENONET 64 /* Machine is not on the network */ +#undef ENOPKG +#define ENOPKG 65 /* Package not installed */ +#undef EREMOTE +#define EREMOTE 66 /* Object is remote */ +#undef ENOLINK +#define ENOLINK 67 /* Link has been severed */ +#undef EADV +#define EADV 68 /* Advertise error */ +#undef ESRMNT +#define ESRMNT 69 /* Srmount error */ +#undef ECOMM +#define ECOMM 70 /* Communication error on send */ +#undef EPROTO +#define EPROTO 71 /* Protocol error */ +#undef EMULTIHOP +#define EMULTIHOP 72 /* Multihop attempted */ +#undef EDOTDOT +#define EDOTDOT 73 /* RFS specific error */ +#undef EBADMSG +#define EBADMSG 74 /* Not a data message */ +#undef EOVERFLOW +#define EOVERFLOW 75 /* Value too large for defined data type */ +#undef ENOTUNIQ +#define ENOTUNIQ 76 /* Name not unique on network */ +#undef EBADFD +#define EBADFD 77 /* File descriptor in bad state */ +#undef EREMCHG +#define EREMCHG 78 /* Remote address changed */ +#undef ELIBACC +#define ELIBACC 79 /* Can not access a needed shared library */ +#undef ELIBBAD +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#undef ELIBSCN +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#undef ELIBMAX +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#undef ELIBEXEC +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#undef EILSEQ +#define EILSEQ 84 /* Illegal byte sequence */ +#undef ERESTART +#define ERESTART 85 /* Interrupted system call should be restarted */ +#undef ESTRPIPE +#define ESTRPIPE 86 /* Streams pipe error */ +#undef EUSERS +#define EUSERS 87 /* Too many users */ +#undef ENOTSOCK +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#undef EDESTADDRREQ +#define EDESTADDRREQ 89 /* Destination address required */ +#undef EMSGSIZE +#define EMSGSIZE 90 /* Message too long */ +#undef EPROTOTYPE +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#undef ENOPROTOOPT +#define ENOPROTOOPT 92 /* Protocol not available */ +#undef EPROTONOSUPPORT +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#undef ESOCKTNOSUPPORT +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#undef EOPNOTSUPP +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#undef EPFNOSUPPORT +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#undef EAFNOSUPPORT +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#undef EADDRINUSE +#define EADDRINUSE 98 /* Address already in use */ +#undef EADDRNOTAVAIL +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#undef ENETDOWN +#define ENETDOWN 100 /* Network is down */ +#undef ENETUNREACH +#define ENETUNREACH 101 /* Network is unreachable */ +#undef ENETRESET +#define ENETRESET 102 /* Network dropped connection because of reset */ +#undef ECONNABORTED +#define ECONNABORTED 103 /* Software caused connection abort */ +#undef ECONNRESET +#define ECONNRESET 104 /* Connection reset by peer */ +#undef ENOBUFS +#define ENOBUFS 105 /* No buffer space available */ +#undef EISCONN +#define EISCONN 106 /* Transport endpoint is already connected */ +#undef ENOTCONN +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#undef ESHUTDOWN +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#undef ETOOMANYREFS +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#undef ETIMEDOUT +#define ETIMEDOUT 110 /* Connection timed out */ +#undef ECONNREFUSED +#define ECONNREFUSED 111 /* Connection refused */ +#undef EHOSTDOWN +#define EHOSTDOWN 112 /* Host is down */ +#undef EHOSTUNREACH +#define EHOSTUNREACH 113 /* No route to host */ +#undef EALREADY +#define EALREADY 114 /* Operation already in progress */ +#undef EINPROGRESS +#define EINPROGRESS 115 /* Operation now in progress */ +#undef ESTALE +#define ESTALE 116 /* Stale NFS file handle */ +#undef EUCLEAN +#define EUCLEAN 117 /* Structure needs cleaning */ +#undef ENOTNAM +#define ENOTNAM 118 /* Not a XENIX named type file */ +#undef ENAVAIL +#define ENAVAIL 119 /* No XENIX semaphores available */ +#undef EISNAM +#define EISNAM 120 /* Is a named type file */ +#undef EREMOTEIO +#define EREMOTEIO 121 /* Remote I/O error */ +#undef EDQUOT +#define EDQUOT 122 /* Quota exceeded */ +#undef ENOMEDIUM +#define ENOMEDIUM 123 /* No medium found */ +#undef EMEDIUMTYPE +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#undef ECANCELED +#define ECANCELED 125 /* Operation Canceled */ +#undef ENOKEY +#define ENOKEY 126 /* Required key not available */ +#undef EKEYEXPIRED +#define EKEYEXPIRED 127 /* Key has expired */ +#undef EKEYREVOKED +#define EKEYREVOKED 128 /* Key has been revoked */ +#undef EKEYREJECTED +#define EKEYREJECTED 129 /* Key was rejected by service */ +#undef EOWNERDEAD +#define EOWNERDEAD 130 /* Owner died */ +#undef ENOTRECOVERABLE +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif //RETARGET_H diff --git a/UNITTESTS/target_h/platform/platform.h b/UNITTESTS/target_h/platform/platform.h new file mode 100644 index 0000000..7dc963c --- /dev/null +++ b/UNITTESTS/target_h/platform/platform.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, 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. + */ + +#ifndef MBED_PLATFORM_H +#define MBED_PLATFORM_H + +#include +#include +#include +#include + +#include "platform/mbed_retarget.h" +#include "nvic_wrapper.h" + +#endif diff --git a/UNITTESTS/template/test_template.cpp b/UNITTESTS/template/test_template.cpp new file mode 100644 index 0000000..a4aa661 --- /dev/null +++ b/UNITTESTS/template/test_template.cpp @@ -0,0 +1,17 @@ +#include "gtest/gtest.h" +#include "dirname/template.h" + +class Testtemplate : public testing::Test { + virtual void SetUp() + { + } + + virtual void TearDown() + { + } +}; + +TEST_F(Testtemplate, constructor) +{ + EXPECT_TRUE(true); +} diff --git a/UNITTESTS/template/unittest.cmake.template b/UNITTESTS/template/unittest.cmake.template new file mode 100644 index 0000000..bd46366 --- /dev/null +++ b/UNITTESTS/template/unittest.cmake.template @@ -0,0 +1,19 @@ + +#################### +# UNIT TESTS +#################### + +# Unit test suite name +set(TEST_SUITE_NAME "suitename") + +set(unittest-includes ${unittest-includes} + headerfile +) + +set(unittest-sources + cppfile +) + +set(unittest-test-sources + dirname/template/test_template.cpp +) \ No newline at end of file diff --git a/UNITTESTS/unit_test/__init__.py b/UNITTESTS/unit_test/__init__.py new file mode 100644 index 0000000..65fcee4 --- /dev/null +++ b/UNITTESTS/unit_test/__init__.py @@ -0,0 +1,16 @@ +""" +Copyright (c) 2018, Arm Limited +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. +""" diff --git a/UNITTESTS/unit_test/get_tools.py b/UNITTESTS/unit_test/get_tools.py new file mode 100644 index 0000000..3588705 --- /dev/null +++ b/UNITTESTS/unit_test/get_tools.py @@ -0,0 +1,82 @@ +""" +Copyright (c) 2018, Arm Limited +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. + + +GET UNIT TEST TOOLS +""" + +import platform + +from .utils import is_tool +from .settings import MAKE_PROGRAMS, \ + CXX_COMPILERS, \ + C_COMPILERS, \ + GCOV_PROGRAMS + +def _get_program(programs, default=None): + if programs is None: + programs = [] + + for program in programs: + if is_tool(program): + return program + + return default + +def get_make_tool(): + """ + Get make program + """ + + default_make = "mingw32-make" if (platform.system() == "Windows") \ + else "make" + + return _get_program(MAKE_PROGRAMS, default=default_make) + +def get_cmake_tool(): + """ + Get cmake program + """ + + return _get_program(["cmake"]) + +def get_cxx_tool(): + """ + Get C++ compiler + """ + + return _get_program(CXX_COMPILERS, "g++") + +def get_c_tool(): + """ + Get C compiler + """ + + return _get_program(C_COMPILERS, "gcc") + +def get_gcov_program(): + """ + Get gcov program + """ + + return _get_program(GCOV_PROGRAMS, "gcov") + +def get_gcovr_program(): + """ + Get covr program + """ + + return _get_program(["gcovr"]) diff --git a/UNITTESTS/unit_test/new.py b/UNITTESTS/unit_test/new.py new file mode 100644 index 0000000..f9fb748 --- /dev/null +++ b/UNITTESTS/unit_test/new.py @@ -0,0 +1,145 @@ +""" +Copyright (c) 2018, Arm Limited +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. + + +UNIT TEST GENERATE NEW UNIT TESTS +""" + +from __future__ import print_function +import os +import re +import logging + +class UnitTestGeneratorTool(object): + """ + Generator tool to create new unit tests from template + """ + + def _replace_content(self, template_content, dirname, classname, suite_name, extension): + if extension == "h": + content = re.sub(r"cppfile", + "", + template_content) + elif extension == "cpp": + content = re.sub(r"cppfile", + "../dirname/template.cpp", + template_content) + + content = re.sub(r"headerfile", "../dirname/template.h", content) + content = re.sub(r"dirname", dirname, content) + content = re.sub(r"template", classname, content) + content = re.sub(r"suitename", suite_name, content) + + return content + + def create(self, mbed_os_root=None, filepath=None): + """ + Generate a unit test for a file to be tested from templates + + Keyword arguments: + mbed_os_root - Mbed OS root directory + filepath - Path to the file to be tested + """ + + if filepath is None: + logging.error("No filepath given. Cannot create a new unit test.") + return + + if mbed_os_root is None: + mbed_os_root = \ + os.path.normpath(os.path.join(os.path.dirname(__file__), + "../..")) + if os.path.isabs(filepath): + filepath = os.path.join( + os.path.relpath(os.path.dirname(filepath), mbed_os_root), + os.path.basename(filepath)) + + if not re.match(r"((\w+\/)+)(\w+)\.(c|cpp|h|hpp)$", filepath): + logging.error( + "No proper path to source file given.") + return + + if not os.path.isfile(os.path.join(mbed_os_root, filepath)): + logging.warning("Cannot find source file: %s from Mbed OS.", + filepath) + + dir_name = re.sub(r"(\\|\/)(\w+)\.(cpp|h)$", "", filepath) + + match = re.search(r"(\\|\/)(\w+)\.(cpp|h)$", filepath) + + if match: + class_name = match.group(2) + file_extension = match.group(3) + + # Create directory tree if not exist. + test_dir = os.path.join(mbed_os_root, "UNITTESTS", dir_name, class_name) + + if not os.path.exists(test_dir): + os.makedirs(test_dir) + else: + logging.error("Unit tests exist already for this file.") + return + + try: + suite_name = ("%s/%s" % (dir_name, class_name)).replace("/", "_") + + # Test source file template + template_source_file = \ + os.path.join(mbed_os_root, + "UNITTESTS/template/test_template.cpp") + + with open(template_source_file, "r") as input_file: + template_content = input_file.read() + + output_source_file = os.path.join(test_dir, + "test_%s.cpp" % class_name) + + with open(output_source_file, "w") as output_file: + content = self._replace_content(template_content, + dir_name, + class_name, + suite_name, + file_extension) + + output_file.writelines(content) + + # Definition file template + template_source_file = \ + os.path.join(mbed_os_root, + "UNITTESTS/template/unittest.cmake.template") + + with open(template_source_file, "r") as input_file: + template_content = input_file.read() + + output_source_file = os.path.join(test_dir, "unittest.cmake") + + with open(output_source_file, "w") as output_file: + content = self._replace_content(template_content, + dir_name, + class_name, + suite_name, + file_extension) + + output_file.writelines(content) + + logging.info(""" +Unit test %s created. + +Generated files into %s directory. +""", suite_name, test_dir) + + except IOError: + logging.error("Cannot create files for a unit test.") diff --git a/UNITTESTS/unit_test/options.py b/UNITTESTS/unit_test/options.py new file mode 100644 index 0000000..f192006 --- /dev/null +++ b/UNITTESTS/unit_test/options.py @@ -0,0 +1,142 @@ +""" +Copyright (c) 2018, Arm Limited +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. + + +UNIT TEST OPTIONS +""" + +import argparse +import logging + +from .settings import CMAKE_GENERATORS, MAKE_PROGRAMS, COVERAGE_TYPES +from .get_tools import get_make_tool + +def get_options_parser(): + """ + Create a unit test options parser. + + Returns a parser object + """ + + parser = argparse.ArgumentParser() + + log_group = parser.add_mutually_exclusive_group() + + log_group.add_argument("-v", + "--verbose", + help="Verbose output", + action="store_const", + const=logging.getLevelName(logging.DEBUG), + dest="log_level") + + log_group.add_argument("--quiet", + help="Quiet output", + action="store_const", + const=logging.getLevelName(logging.ERROR), + dest="log_level") + + parser.add_argument("--compile", + action="store_true", + help="Only compile unit tests", + dest="compile_only") + + parser.add_argument("--run", + action="store_true", + help="Only run unit tests", + dest="run_only") + + parser.add_argument("-c", + "--clean", + action="store_true", + help="Clean the build directory", + dest="clean") + + parser.add_argument("-d", + "--debug", + action="store_true", + help="Enable debug build", + dest="debug_build") + + parser.add_argument("--coverage", + choices=COVERAGE_TYPES, + help="Generate code coverage report", + dest="coverage") + + parser.add_argument("-m", + "--make-program", + default=get_make_tool(), + choices=MAKE_PROGRAMS, + help="Which make program to use", + dest="make_program") + + parser.add_argument("-g", + "--generator", + choices=CMAKE_GENERATORS, + help="Which CMake generator to use", + dest="cmake_generator") + + parser.add_argument("-r", + "--regex", + help="Run tests matching a regular expression", + dest="test_regex") + + parser.add_argument("--build", + default="build", + help="Build directory. Default: UNITTESTS/build/", + dest="build") + + parser.add_argument("--new", + action="append", + help="Source file from which to generate test files. E.g. rtos/Semaphore.cpp", + metavar="FILEPATH", + dest="new_files") + + return parser + +def pretty_print_test_options(options=None): + """ + Pretty print test options + + Keyword arguments: + options - options + """ + + if options is None: + return + + # Mode + logging.info(""" +##################### +Mbed OS unit testing: +##################### +""") + + logging.info("Steps:\n") + + logging.info(" [%s] \tPrepare build directory", "AUTO") + logging.info(" \t\t - Clean: %s", options.clean) + logging.info(" \t\t - Directory: %s\n", options.build) + status = "SET" if options.compile_only else "UNSET" + logging.info(" [%s] \tBuild unit tests", status) + logging.info(" \t\t - Debug: %s", options.debug_build) + logging.info(" \t\t - CMake generator: %s", options.cmake_generator) + logging.info(" \t\t - Make program: %s\n", options.make_program) + status = "SET" if options.run_only else "UNSET" + logging.info(" [%s] \tRun unit tests", status) + logging.info(" \t\t - Filter: %s\n", options.test_regex) + if options.coverage: + logging.info(" [%s] \tGenerate coverage reports", "SET") + logging.info(" \t\t - Output: %s", options.coverage) diff --git a/UNITTESTS/unit_test/settings.py b/UNITTESTS/unit_test/settings.py new file mode 100644 index 0000000..717cab8 --- /dev/null +++ b/UNITTESTS/unit_test/settings.py @@ -0,0 +1,40 @@ +""" +Copyright (c) 2018, Arm Limited +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. + + +UNIT TEST SETTINGS +""" + +CMAKE_GENERATORS = ["Unix Makefiles", "MinGW Makefiles", "Ninja"] + +MAKE_PROGRAMS = ["gmake", "make", "mingw32-make", "ninja"] + +DEFAULT_CMAKE_GENERATORS = { + "gmake": "Unix Makefiles", + "make": "Unix Makefiles", + "mingw32-make": "MinGW Makefiles", + "ninja": "Ninja" +} + +COVERAGE_TYPES = ["html", + "xml", + "both"] + +CXX_COMPILERS = ["g++-6", "g++-8", "g++-7", "g++-5", "g++-4.9", "g++"] + +C_COMPILERS = ["gcc-6", "gcc-8", "gcc-7", "gcc-5", "gcc-4.9", "gcc"] + +GCOV_PROGRAMS = ["gcov-6", "gcov-8", "gcov-7", "gcov-5", "gcov-4.9", "gcov"] diff --git a/UNITTESTS/unit_test/test.py b/UNITTESTS/unit_test/test.py new file mode 100644 index 0000000..80bbd10 --- /dev/null +++ b/UNITTESTS/unit_test/test.py @@ -0,0 +1,270 @@ +""" +Copyright (c) 2018, Arm Limited +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. + + +UNIT TEST BUILD & RUN +""" + +import os +import logging +import sys +from shutil import copy + +from .utils import execute_program +from .get_tools import get_make_tool, \ + get_cmake_tool, \ + get_cxx_tool, \ + get_c_tool, \ + get_gcov_program, \ + get_gcovr_program +from .settings import DEFAULT_CMAKE_GENERATORS + +class UnitTestTool(object): + """ + Unit test tool to: + - prepare build directory + - create makefiles + - build unit tests + - run unit tests + - generate code coverage reports + """ + + def __init__(self, + make_program=None): + """ + Constructor + + Keyword arguments: + make_program - Make tool to use + """ + + self.make_program = make_program + + if self.make_program is None: + self.make_program = get_make_tool() + + def create_makefiles(self, + path_to_src=None, + generator=None, + coverage_output_type=None, + debug=False): + """ + Create Makefiles and prepare targets with CMake. + + Keyword arguments: + path_to_src - Path to source directory + generator - Type of Makefiles to generate + coverage_output_type - Generate HTML, XML or both reports + debug - Target debug or release build + """ + + if generator is None: + generator = DEFAULT_CMAKE_GENERATORS.get(self.make_program, + "Unix Makefiles") + + cmake = get_cmake_tool() + + if cmake is None: + logging.error( + "No CMake found in Path. Install all the required tools.") + sys.exit(1) + + args = [cmake, + "-G", + generator, + "-DCMAKE_MAKE_PROGRAM=%s" % self.make_program, + "-DCMAKE_CXX_COMPILER=%s" % get_cxx_tool(), + "-DCMAKE_C_COMPILER=%s" % get_c_tool()] + + if debug: + args.append("-DCMAKE_BUILD_TYPE=Debug") + + if coverage_output_type: + args.append("-DCOVERAGE:STRING=%s" % coverage_output_type) + + if path_to_src is not None: + args.append(path_to_src) + + execute_program(args, + "CMake failed to run successfully. See error message.") + + def build_tests(self): + """ + Build unit tests and libraries to be tested. + """ + + args = [self.make_program] + + if logging.getLogger().getEffectiveLevel() == logging.DEBUG: + args.append("VERBOSE=1") + + execute_program(args, + "Building unit tests failed.", + "Unit tests built successfully.") + + def _get_coverage_script(self, coverage_type, excludes): + args = [get_gcovr_program(), + "--gcov-executable", + get_gcov_program(), + "-r", + "../..", + "."] + + if coverage_type == "html": + args.extend(["--html", + "--html-detail", + "-o", + "./coverage/index.html"]) + elif coverage_type == "xml": + args.extend(["-x", + "-o", + "./coverage.xml"]) + + for path in excludes: + args.extend(["-e", path]) + + if logging.getLogger().getEffectiveLevel() == logging.DEBUG: + args.append("-v") + + return args + + def generate_coverage_report(self, + coverage_output_type=None, + excludes=None, + build_path=None): + """ + Run tests to generate coverage data, and generate coverage reports. + """ + + self.run_tests() + + if get_gcovr_program() is None: + logging.error("No gcovr tool found in path. \ + Cannot generate coverage report.") + return + + if build_path is None: + build_path = os.getcwd() + + if coverage_output_type is None: + logging.warning("No coverage output type give. \ + Cannot generate coverage reports.") + return + + if excludes is None: + excludes = [] + + if coverage_output_type == "html" or coverage_output_type == "both": + # Create build directory if not exist. + coverage_path = os.path.join(build_path, "coverage") + if not os.path.exists(coverage_path): + os.mkdir(coverage_path) + + args = self._get_coverage_script("html", excludes) + + execute_program(args, + "HTML code coverage report generation failed.", + "HTML code coverage report created.") + + if coverage_output_type == "xml" or coverage_output_type == "both": + args = self._get_coverage_script("xml", excludes) + + execute_program(args, + "XML code coverage report generation failed.", + "XML code coverage report created.") + + def run_tests(self, filter_regex=None): + """ + Run unit tests. + + Keyword arguments: + filter_regex - Regular expression to select which tests to run + """ + + args = [self.make_program, "test"] + + if filter_regex: + args.append("ARGS=-R %s -V -D ExperimentalTest" % filter_regex) + else: + args.append("ARGS=-V -D ExperimentalTest") + + if logging.getLogger().getEffectiveLevel() == logging.DEBUG: + args.append("VERBOSE=1") + + execute_program(args, "Unit test run failed.") + + def prepare_build_directory(self, + path_to_src=None, + build_path=None, + clean=False): + """ + Create build directory if not exist and + change current working directory to it + + Keyword arguments: + path_to_src - Path to source directory + build_path - Path to build directory + clean - Clean build directory + """ + + if build_path is None: + build_path = os.getcwd() + + # Clean CMake data if exists. + if clean: + self._clean_build(build_path) + + # Create build directory if not exist. + if not os.path.exists(build_path): + os.makedirs(build_path) + filename = ".mbedignore" + inputfile = os.path.join(path_to_src, filename) + outputfile = os.path.join(build_path, filename) + copy(inputfile, outputfile) + + # Change current working directory to build directory. + os.chdir(build_path) + + def _clean_build(self, build_path=None): + """ + Try clean build directory + + Keyword arguments: + build_path - Path to build directory + """ + + logging.info("Cleaning build directory...") + + if os.path.exists(os.path.join(build_path, "CMakeCache.txt")): + args = [self.make_program, + "-C", + build_path, + "--no-print-directory", + "clean"] + + # Remove coverage files + for root, _, files in os.walk(build_path): + for current_file in files: + if current_file.endswith((".gcno", ".gcda")): + os.remove(os.path.join(root, current_file)) + + execute_program(args, + "Clean step failed.", + "Clean done.") + + else: + logging.warning("%s does not exist or \ + does not contain previous build data.", build_path) diff --git a/UNITTESTS/unit_test/utils.py b/UNITTESTS/unit_test/utils.py new file mode 100644 index 0000000..fe41dc8 --- /dev/null +++ b/UNITTESTS/unit_test/utils.py @@ -0,0 +1,66 @@ +""" +Copyright (c) 2018, Arm Limited +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. + + +UNIT TEST UTILITIES +""" + +import platform +import subprocess +import logging +import sys + +def is_tool(name): + """ + Test if tool is found in PATH + + @param name: executable name + @return: true if tool found, false otherwise + """ + cmd = "where" if platform.system() == "Windows" else "which" + try: + subprocess.check_output([cmd, name], stderr=subprocess.STDOUT) + return True + except subprocess.CalledProcessError: + return False + +def execute_program(args, error_msg="An error occurred!", success_msg=None): + """ + Execute program in a subprocess with given arguments + + @param args: program and its arguments in a list + @param success_msg: message to show in case of success + @param error_msg: message to show in case of failure + """ + + try: + process = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + + while process.poll() is None: + logging.info(process.stdout.readline().decode("utf8")) + + retcode = process.wait() + + if retcode: + raise subprocess.CalledProcessError(retcode, args) + elif success_msg: + logging.info(success_msg) + + except subprocess.CalledProcessError as error: + logging.error(error_msg) + sys.exit(error.returncode) diff --git a/doxyfile_options b/doxyfile_options index e13a842..179db0f 100644 --- a/doxyfile_options +++ b/doxyfile_options @@ -854,7 +854,8 @@ */mbed-client-randlib/* \ */nanostack/sal-stack-nanostack-eventloop/* \ */ble/generic/* \ - */ble/pal/* + */ble/pal/* \ + */UNITTESTS/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the