diff --git a/.github/workflows/cpputest.yml b/.github/workflows/cpputest.yml index 7e05da850..d3d12763f 100644 --- a/.github/workflows/cpputest.yml +++ b/.github/workflows/cpputest.yml @@ -11,7 +11,9 @@ env: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 + container: + image: pllee4/ubuntu-ci:20.04-gRPC steps: - uses: actions/checkout@v2 @@ -23,6 +25,3 @@ jobs: - name: Build run: cmake --build --preset=unittest_build - - - name: Test - run: ctest --preset=unittest --rerun-failed --output-on-failure diff --git a/.gitignore b/.gitignore index 4a29d3aad..6764095e0 100644 --- a/.gitignore +++ b/.gitignore @@ -113,7 +113,10 @@ ipch/ *.dbg* *.scvd -.vscode/.cortex-debug.registers.state.json -:50003 -:50006 -.vscode/.cortex-debug.peripherals.state.json +.vscode/.cortex-debug.registers.state.json +:50003 +:50006 +.vscode/.cortex-debug.peripherals.state.json + +# Generated files +tests/generator diff --git a/CMakePresets.json b/CMakePresets.json index c9e420402..9f3c5a71e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -61,17 +61,25 @@ } ], "buildPresets": [ + { + "name": "parallel_build", + "description": "Build will all cores", + "displayName": "parallel_build", + "jobs": 0 + }, { "name": "unittest_build", "description": "Build the unittest", "displayName": "unittest_build", - "configurePreset": "unittesting_configs" + "configurePreset": "unittesting_configs", + "inherits": "parallel_build" }, { "name": "target_build", "description": "Build for the STM32l0 target", "displayName": "target_build", - "configurePreset": "on_target_configs" + "configurePreset": "on_target_configs", + "inherits": "parallel_build" } ], "testPresets": [ diff --git a/src/apps/LoRaMac/common/callbacks.c b/src/apps/LoRaMac/common/callbacks.c index 8ff6e7b8a..5ad26e5f5 100644 --- a/src/apps/LoRaMac/common/callbacks.c +++ b/src/apps/LoRaMac/common/callbacks.c @@ -31,6 +31,7 @@ typedef struct } uplink_key_setter_message_t; uplink_key_setter_message_t uplink_key_setter_message; +extern uint32_t tx_count_on_this_credential; void OnNvmDataChange(LmHandlerNvmContextStates_t state, uint16_t size) { @@ -46,6 +47,8 @@ void OnNvmDataChange(LmHandlerNvmContextStates_t state, uint16_t size) */ if (state == LORAMAC_HANDLER_NVM_STORE) { + tx_count_on_this_credential++; + #if GPS_ENABLED setup_GPS(); #endif diff --git a/src/apps/LoRaMac/common/message_sender.c b/src/apps/LoRaMac/common/message_sender.c index 0811b77c6..1c505e9e1 100644 --- a/src/apps/LoRaMac/common/message_sender.c +++ b/src/apps/LoRaMac/common/message_sender.c @@ -15,6 +15,7 @@ #include "print_utils.h" #include "callbacks.h" #include "iwdg.h" +#include "stdio.h" bool can_tx(LoRaMacRegion_t current_stack_region); @@ -49,6 +50,10 @@ bool sensor_read_and_send(LmHandlerAppData_t *AppData, LoRaMacRegion_t current_s ret = true; } + else + { + printf("Lorawan stack initialised for wrong region."); + } return ret; } diff --git a/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c b/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c index c0284244c..ba23f85a4 100644 --- a/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c +++ b/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c @@ -125,7 +125,6 @@ static volatile uint8_t IsTxFramePending = 0; */ extern Uart_t Uart1; - uint32_t tx_count_on_this_credential = 0; /*! @@ -148,9 +147,6 @@ int main( void ) /* Initialise timer */ timer_init( ); - /* Transmit immediately (10 milliseconds later) */ - setup_next_tx_alarm( 10 ); - while( 1 ) { switch_to_next_registered_credentials( ); // Switch to the next set of @@ -162,6 +158,9 @@ int main( void ) static void transmit_n_times_on_this_credential( void ) { + /* Transmit immediately (10 milliseconds later) */ + setup_next_tx_alarm( 10 ); + print_current_region( ); /* Configure the subband settings for AS923 BEFORE initing it. Only needed @@ -244,7 +243,6 @@ static void PrepareTxFrame( void ) return; } - tx_count_on_this_credential ++; sensor_read_and_send( &AppData, LmHandlerParams.Region ); uint32_t interval = read_tx_interval_in_eeprom( TX_INTERVAL_EEPROM_ADDRESS, TX_INTERVAL_GPS_FIX_OK ); diff --git a/src/peripherals/config.h b/src/peripherals/config.h index f8cee4d53..94554963f 100644 --- a/src/peripherals/config.h +++ b/src/peripherals/config.h @@ -120,7 +120,7 @@ extern "C" * @brief Define how quickly to return to searching for a GPS fix after transmitting * */ -#define TX_INTERVAL_GPS_FIX_OK 2800 /* When fix was aquired, then sleep for this period (in milliseconds) before searching again */ +#define TX_INTERVAL_GPS_FIX_OK 10000 /* When fix was aquired, then sleep for this period (in milliseconds) before searching again */ /** * @brief Lorawan defaults, normally will not be changed diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f37040d6f..26b902867 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,21 +1,14 @@ -cmake_minimum_required(VERSION 3.7) +# src/CMakeLists.txt +cmake_minimum_required(VERSION 3.5.1) +# For Protobuf's cmake warnings +if(POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) +endif() -# Get the test framework Cpputest -include(FetchContent) -FetchContent_Declare( - cpputest - GIT_REPOSITORY https://github.com/cpputest/cpputest.git - GIT_TAG v4.0 -) -# Set this to ON if you want to have the CppUTests in your project as well. -set(TESTS OFF CACHE BOOL "Switch off CppUTest Test build") - - -set(CPPUTEST_CXX_FLAGS "${CPPUTEST_CXX_FLAGS} -m32") -set(CPPUTEST_LD_FLAGS "${CPPUTEST_LD_FLAGS} -m32") +# project(hello C CXX) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -FetchContent_MakeAvailable(cpputest) add_definitions( -DREGION_EU868 @@ -35,9 +28,6 @@ add_definitions( ) -include_directories(${CPPUTEST_SRC_DIR}) -include_directories(${CPPUTESTEXT_SRC_DIR}) - # Test includes include_directories(${PROJECT_SOURCE_DIR}/mocking) include_directories(${PROJECT_SOURCE_DIR}/tests/mocks/) @@ -93,18 +83,12 @@ set(MOCKS systime-mock.cpp ublox-mock.cpp nvm_images.cpp - gps_mock_utils.cpp delay-board-mock.c gpio_mock.c rtc-board-mock.c mocks/rtc_mock.c ) - - -# CLI sources - - # Put in compile files(all logic so no hardware connection) set(FILES_UNDER_TEST ${PROJECT_SOURCE_DIR}/src/peripherals/geofence.c @@ -120,9 +104,8 @@ set(FILES_UNDER_TEST ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/LmHandler/LmHandler.c ${PROJECT_SOURCE_DIR}/src/system/delay.c ${PROJECT_SOURCE_DIR}/src/system/timer.c - ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/callbacks.c - - + ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/callbacks.c + ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c # Compile region files ${PROJECT_SOURCE_DIR}/src/mac/region/RegionAU915.c @@ -168,24 +151,61 @@ set(FILES_UNDER_TEST ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/message_sender.c ${PROJECT_SOURCE_DIR}/src/system/nvmm.c - + greeter_client.cc ) -set(SOURCE_FILES - ${UNIT_TESTS} - ${MOCKS} +find_package(Threads REQUIRED) + +# Find Protobuf installation +# Looks for protobuf-config.cmake file installed by Protobuf's cmake installation. +set(protobuf_MODULE_COMPATIBLE TRUE) +find_package(Protobuf CONFIG REQUIRED) +message(STATUS "Using protobuf ${Protobuf_VERSION}") + +set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) +set(_REFLECTION gRPC::grpc++_reflection) +find_program(_PROTOBUF_PROTOC protoc) + +# Find gRPC installation +# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. +find_package(gRPC CONFIG REQUIRED) +message(STATUS "Using gRPC ${gRPC_VERSION}") + +set(_GRPC_GRPCPP gRPC::grpc++) +find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) + +# Protos +get_filename_component(h_proto "hello.proto" ABSOLUTE) +get_filename_component(h_proto_path "${h_proto}" PATH) + +# Generated sources +set(h_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/hello.pb.cc") +set(h_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/hello.pb.h") +set(h_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/hello.grpc.pb.cc") +set(h_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/hello.grpc.pb.h") +add_custom_command( + OUTPUT "${h_proto_srcs}" "${h_proto_hdrs}" "${h_grpc_srcs}" "${h_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${h_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${h_proto}" + DEPENDS "${h_proto}") + +# Generated sources headers +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# Targets (the binaries) +foreach(_target + greeter_client) + add_executable(${_target} "${_target}.cc" ${FILES_UNDER_TEST} -) - -add_executable(picotracker_lora_tests ${SOURCE_FILES}) -target_compile_options(picotracker_lora_tests PRIVATE -fshort-enums) -# target_compile_options(picotracker_lora_tests PRIVATE -Wall -Wextra -Wpedantic) -target_link_libraries(picotracker_lora_tests PRIVATE CppUTest CppUTestExt) - - -# only build 32-bit binaries -target_compile_options(picotracker_lora_tests PRIVATE -m32) -target_link_options(picotracker_lora_tests PRIVATE -m32) - -# Add tests -add_test(picotracker_lora_tests picotracker_lora_tests -p) # Pass option to run CppUTests all on different threads + ${MOCKS} + ${h_proto_srcs} + ${h_grpc_srcs}) + target_link_libraries(${_target} + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) +endforeach() diff --git a/tests/bsp_mock.cpp b/tests/bsp_mock.cpp index 0e07a0079..2ba583745 100644 --- a/tests/bsp_mock.cpp +++ b/tests/bsp_mock.cpp @@ -1,4 +1,3 @@ -#include "CppUTestExt/MockSupport.h" extern "C" { diff --git a/tests/eeprom-board-mock.cpp b/tests/eeprom-board-mock.cpp index 6a4f6ef2a..806071830 100644 --- a/tests/eeprom-board-mock.cpp +++ b/tests/eeprom-board-mock.cpp @@ -23,7 +23,6 @@ * Modified by Medad Newman for unittesting */ -#include "CppUTestExt/MockSupport.h" extern "C" { diff --git a/tests/gps_mock_utils.cpp b/tests/gps_mock_utils.cpp index dcafc6966..d4a4abf75 100644 --- a/tests/gps_mock_utils.cpp +++ b/tests/gps_mock_utils.cpp @@ -9,9 +9,6 @@ * */ -#include "CppUTest/TestHarness.h" -#include "CppUTestExt/MockSupport.h" - extern "C" { #include "ublox.h" diff --git a/tests/greeter_client.cc b/tests/greeter_client.cc new file mode 100644 index 000000000..75a9372e9 --- /dev/null +++ b/tests/greeter_client.cc @@ -0,0 +1,66 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * 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 "greeter_client.hpp" + +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else +#include "hello.grpc.pb.h" +#endif + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; + +std::string GreeterClient::SayHello(const std::string &user) +{ + // Data we are sending to the server. + HelloRequest request; + request.set_name(user); + + // Container for the data we expect from the server. + HelloReply reply; + + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + + // The actual RPC. + Status status = stub_->SayHello(&context, request, &reply); + + // Act upon its status. + if (status.ok()) + { + return reply.message(); + } + else + { + std::cout << status.error_code() << ": " << status.error_message() + << std::endl; + return "RPC failed"; + } +} diff --git a/tests/greeter_client.hpp b/tests/greeter_client.hpp new file mode 100644 index 000000000..d6dc43ca4 --- /dev/null +++ b/tests/greeter_client.hpp @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "hello.grpc.pb.h" + +class GreeterClient +{ +public: + GreeterClient(std::shared_ptr channel) + : stub_(helloworld::Greeter::NewStub(channel)) {} + + // Assembles the client's payload, sends it and presents the response back + // from the server. + std::string SayHello(const std::string &user); + +private: + std::unique_ptr stub_; +}; \ No newline at end of file diff --git a/tests/hello.proto b/tests/hello.proto new file mode 100644 index 000000000..be878ce25 --- /dev/null +++ b/tests/hello.proto @@ -0,0 +1,38 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.helloworld"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/tests/mocks/main.h b/tests/mocks/main.h deleted file mode 100644 index acefd24b9..000000000 --- a/tests/mocks/main.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file main.h - * @author Medad Newman (medad@medadnewman.co.uk) - * @brief - * @version 0.1 - * @date 2021-08-11 - * - * @copyright Copyright (c) 2021 - * - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __MAIN_H_1 -#define __MAIN_H_1 - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "LmHandler.h" - - - -#ifdef __cplusplus -} -#endif - -#endif /* __MAIN_H_1 */ diff --git a/tests/ublox-mock.cpp b/tests/ublox-mock.cpp index 88fa44e67..1b0ffd012 100644 --- a/tests/ublox-mock.cpp +++ b/tests/ublox-mock.cpp @@ -1,10 +1,17 @@ -#include "CppUTestExt/MockSupport.h" extern "C" { #include "ublox.h" } +#include "greeter_client.hpp" + +#include + +gps_info_t dummy_gps_info = { + .GPS_UBX_latitude_Float = 1.290270, + .GPS_UBX_longitude_Float = 103.851959 +}; gps_status_t get_location_fix(uint32_t timeout) @@ -29,8 +36,20 @@ uint16_t get_load_solar_voltage() gps_info_t get_latest_gps_info() { - auto returnValue = mock().actualCall(__func__).returnPointerValue(); - return *(gps_info_t *)(returnValue); + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint specified by + // the argument "--target=" which is the only expected argument. + // We indicate that the channel isn't authenticated (use of + // InsecureChannelCredentials()). + std::string target_str = "localhost:50051"; + + GreeterClient greeter( + grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials())); + std::string user("world"); + std::string reply = greeter.SayHello(user); + std::cout << "Greeter received: " << reply << std::endl; + + return dummy_gps_info; } gps_status_t get_latest_gps_status(void)