From 7deaf1ab9e0921297420969e03e4b09dbab30deb Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Thu, 25 Aug 2022 21:19:32 +0100 Subject: [PATCH 01/10] Add changes to allow integration tests to run Make all stubs stubs - remove all Cpputest header includes - we dont want them for integration tests --- src/apps/LoRaMac/common/callbacks.c | 3 + src/apps/LoRaMac/common/message_sender.c | 5 + .../periodic-uplink-lpp/B-L072Z-LRWAN1/main.c | 17 +- src/peripherals/config.h | 2 +- tests/CMakeLists.txt | 21 +- tests/bsp_mock.cpp | 1 - tests/eeprom-board-mock.cpp | 1 - tests/gps_mock_utils.cpp | 3 - tests/mocks/main.h | 29 -- tests/mocks/rtc_mock.c | 39 +++ tests/mocks/rtc_mock.h | 12 + tests/rtc-board-mock.c | 328 +----------------- tests/timer-mock.cpp | 150 -------- tests/ublox-mock.cpp | 8 +- 14 files changed, 107 insertions(+), 512 deletions(-) delete mode 100644 tests/mocks/main.h create mode 100644 tests/mocks/rtc_mock.c create mode 100644 tests/mocks/rtc_mock.h delete mode 100644 tests/timer-mock.cpp 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 5e7e67b4b..1a4edf6df 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 @@ -39,6 +39,10 @@ #include "eeprom_settings_manager.h" #include "nvmm.h" +#ifdef UNITTESTING_LORA +#include "rtc_mock.h" +#endif + /*! * User application data */ @@ -121,7 +125,6 @@ static volatile uint8_t IsTxFramePending = 0; */ extern Uart_t Uart1; - uint32_t tx_count_on_this_credential = 0; /*! @@ -144,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 @@ -156,8 +156,12 @@ 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 @@ -195,6 +199,10 @@ static void transmit_n_times_on_this_credential( void ) while( tx_count_on_this_credential < N_TRANMISSIONS_PER_CREDENTIAL ) { +#ifdef UNITTESTING_LORA + /* simulate 1 millisecond per loop */ + bump_rtc_tick( ); +#endif // Process characters sent over the command line interface CliProcess( &Uart1 ); @@ -236,7 +244,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 90c12e206..e9a5a1eed 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -87,16 +87,16 @@ set(MOCKS cli-mock.c board-mock.c sx1276-mock.c - timer-mock.cpp bsp_mock.cpp eeprom-board-mock.cpp # loramac-mock.cpp 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 ) @@ -118,7 +118,9 @@ set(FILES_UNDER_TEST ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/LmHandlerMsgDisplay.c ${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/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c @@ -175,15 +177,14 @@ set(SOURCE_FILES ${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) +set(INTEGRATION_TEST_SOURCE_FILES + ${MOCKS} + ${FILES_UNDER_TEST} +) +add_executable(picotracker_lora_integration_tests ${INTEGRATION_TEST_SOURCE_FILES}) # only build 32-bit binaries -target_compile_options(picotracker_lora_tests PRIVATE -m32) -target_link_options(picotracker_lora_tests PRIVATE -m32) +target_compile_options(picotracker_lora_integration_tests PRIVATE -m32) +target_link_options(picotracker_lora_integration_tests PRIVATE -m32) -# Add tests -add_test(picotracker_lora_tests picotracker_lora_tests -p) # Pass option to run CppUTests all on different threads 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/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/mocks/rtc_mock.c b/tests/mocks/rtc_mock.c new file mode 100644 index 000000000..799c3abfb --- /dev/null +++ b/tests/mocks/rtc_mock.c @@ -0,0 +1,39 @@ +/** + * @file rtc_mock.cpp + * @author Medad Newman (medad@medadnewman.co.uk) + * @brief + * @version 0.1 + * @date 2022-08-08 + * + * @copyright Copyright (c) 2022 + * + */ + +#include "rtc_mock.h" +#include "stdint.h" +#include "stdbool.h" +#include "stm32l0xx.h" +#include "rtc-board.h" + + +extern uint32_t countdown; +extern bool alarm_stopped; +extern TimerTime_t current_time; + + +void bump_rtc_tick() +{ + current_time += 1; /* simulate 1 millisecond per loop */ + if (countdown > 0 && !alarm_stopped) + { + countdown--; + } + + // printf("current time: %d ms, countdown: %d ms, alarm_stopped: %d\n", current_time, countdown, alarm_stopped); + + if (countdown == 0) + { + RTC_HandleTypeDef dummy; + HAL_RTC_AlarmAEventCallback(&dummy); + } +} diff --git a/tests/mocks/rtc_mock.h b/tests/mocks/rtc_mock.h new file mode 100644 index 000000000..0e301cf2f --- /dev/null +++ b/tests/mocks/rtc_mock.h @@ -0,0 +1,12 @@ +/** + * @file rtc_mock.hpp + * @author Medad Newman (medad@medadnewman.co.uk) + * @brief + * @version 0.1 + * @date 2022-08-08 + * + * @copyright Copyright (c) 2022 + * + */ + +void bump_rtc_tick(); diff --git a/tests/rtc-board-mock.c b/tests/rtc-board-mock.c index d8dcfd565..dabee9793 100644 --- a/tests/rtc-board-mock.c +++ b/tests/rtc-board-mock.c @@ -38,56 +38,14 @@ // MCU Wake Up Time #define MIN_ALARM_DELAY 3 // in ticks -// sub-second number of bits -#define N_PREDIV_S 10 - -// Synchronous prediv -#define PREDIV_S ((1 << N_PREDIV_S) - 1) - -// Asynchronous prediv -#define PREDIV_A (1 << (15 - N_PREDIV_S)) - 1 - -// Sub-second mask definition -#define ALARM_SUBSECOND_MASK (N_PREDIV_S << RTC_ALRMASSR_MASKSS_Pos) - -// RTC Time base in us -#define USEC_NUMBER 1000000 -#define MSEC_NUMBER (USEC_NUMBER / 1000) - -#define COMMON_FACTOR 3 -#define CONV_NUMER (MSEC_NUMBER >> COMMON_FACTOR) -#define CONV_DENOM (1 << (N_PREDIV_S - COMMON_FACTOR)) - -/*! - * \brief Days, Hours, Minutes and seconds - */ -#define DAYS_IN_LEAP_YEAR ((uint32_t)366U) -#define DAYS_IN_YEAR ((uint32_t)365U) -#define SECONDS_IN_1DAY ((uint32_t)86400U) -#define SECONDS_IN_1HOUR ((uint32_t)3600U) -#define SECONDS_IN_1MINUTE ((uint32_t)60U) -#define MINUTES_IN_1HOUR ((uint32_t)60U) -#define HOURS_IN_1DAY ((uint32_t)24U) +TimerTime_t current_time = 0; /*! - * \brief Correction factors - */ -#define DAYS_IN_MONTH_CORRECTION_NORM ((uint32_t)0x99AAA0) -#define DAYS_IN_MONTH_CORRECTION_LEAP ((uint32_t)0x445550) - -/*! - * \brief Calculates ceiling( X / N ) - */ -#define DIVC(X, N) (((X) + (N)-1) / (N)) - -/*! - * RTC timer context + * RTC timer context */ typedef struct { - uint32_t Time; // Reference time - RTC_TimeTypeDef CalendarTime; // Reference time in calendar format - RTC_DateTypeDef CalendarDate; // Reference date in calendar format + uint32_t Time; // Reference time } RtcTimerContext_t; /*! @@ -95,43 +53,8 @@ typedef struct */ static bool RtcInitialized = false; -/*! - * \brief Indicates if the RTC Wake Up Time is calibrated or not - */ -static bool McuWakeUpTimeInitialized = false; - -/*! - * \brief Compensates MCU wakeup time - */ -static int16_t McuWakeUpTimeCal = 0; - -/*! - * Number of days in each month on a normal year - */ -static const uint8_t DaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -/*! - * Number of days in each month on a leap year - */ -static const uint8_t DaysInMonthLeapYear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -/*! - * \brief RTC Handle - */ -static RTC_HandleTypeDef RtcHandle = - { - .Instance = NULL, - .Init = - { - .HourFormat = 0, - .AsynchPrediv = 0, - .SynchPrediv = 0, - .OutPut = 0, - .OutPutRemap = 0, - .OutPutPolarity = 0, - .OutPutType = 0}, - .Lock = HAL_UNLOCKED, - .State = HAL_RTC_STATE_RESET}; +uint32_t countdown = 0; +bool alarm_stopped = true; /*! * \brief RTC Alarm @@ -145,17 +68,13 @@ static RTC_AlarmTypeDef RtcAlarm; */ static RtcTimerContext_t RtcTimerContext; -/*! - * \brief Get the current time from calendar in ticks - * - * \param [IN] date Pointer to RTC_DateStruct - * \param [IN] time Pointer to RTC_TimeStruct - * \retval calendarValue Time in ticks - */ -static uint64_t RtcGetCalendarValue(RTC_DateTypeDef *date, RTC_TimeTypeDef *time); - void RtcInit(void) { + if (RtcInitialized == false) + { + RtcSetTimerContext(); + RtcInitialized = true; + } } /*! @@ -166,7 +85,7 @@ void RtcInit(void) */ uint32_t RtcSetTimerContext(void) { - RtcTimerContext.Time = (uint32_t)RtcGetCalendarValue(&RtcTimerContext.CalendarDate, &RtcTimerContext.CalendarTime); + RtcTimerContext.Time = current_time; return (uint32_t)RtcTimerContext.Time; } @@ -199,7 +118,7 @@ uint32_t RtcGetMinimumTimeout(void) */ uint32_t RtcMs2Tick(uint32_t milliseconds) { - return (uint32_t)((((uint64_t)milliseconds) * CONV_DENOM) / CONV_NUMER); + return milliseconds; } /*! @@ -210,29 +129,7 @@ uint32_t RtcMs2Tick(uint32_t milliseconds) */ uint32_t RtcTick2Ms(uint32_t tick) { - uint32_t seconds = tick >> N_PREDIV_S; - - tick = tick & PREDIV_S; - return ((seconds * 1000) + ((tick * 1000) >> N_PREDIV_S)); -} - -/*! - * \brief a delay of delay ms by polling RTC - * - * \param[IN] delay in ms - */ -void RtcDelayMs(uint32_t delay) -{ - uint64_t delayTicks = 0; - uint64_t refTicks = RtcGetTimerValue(); - - delayTicks = RtcMs2Tick(delay); - - // Wait delay ms - while (((RtcGetTimerValue() - refTicks)) < delayTicks) - { - __NOP(); - } + return tick; } /*! @@ -250,175 +147,26 @@ void RtcSetAlarm(uint32_t timeout) void RtcStopAlarm(void) { + alarm_stopped = true; } void RtcStartAlarm(uint32_t timeout) { - uint16_t rtcAlarmSubSeconds = 0; - uint16_t rtcAlarmSeconds = 0; - uint16_t rtcAlarmMinutes = 0; - uint16_t rtcAlarmHours = 0; - uint16_t rtcAlarmDays = 0; - RTC_TimeTypeDef time = RtcTimerContext.CalendarTime; - RTC_DateTypeDef date = RtcTimerContext.CalendarDate; RtcStopAlarm(); + countdown = timeout; - /*reverse counter */ - rtcAlarmSubSeconds = PREDIV_S - time.SubSeconds; - rtcAlarmSubSeconds += (timeout & PREDIV_S); - // convert timeout to seconds - timeout >>= N_PREDIV_S; - - // Convert microsecs to RTC format and add to 'Now' - rtcAlarmDays = date.Date; - while (timeout >= TM_SECONDS_IN_1DAY) - { - timeout -= TM_SECONDS_IN_1DAY; - rtcAlarmDays++; - } - - // Calc hours - rtcAlarmHours = time.Hours; - while (timeout >= TM_SECONDS_IN_1HOUR) - { - timeout -= TM_SECONDS_IN_1HOUR; - rtcAlarmHours++; - } - - // Calc minutes - rtcAlarmMinutes = time.Minutes; - while (timeout >= TM_SECONDS_IN_1MINUTE) - { - timeout -= TM_SECONDS_IN_1MINUTE; - rtcAlarmMinutes++; - } - - // Calc seconds - rtcAlarmSeconds = time.Seconds + timeout; - - //***** Correct for modulo******** - while (rtcAlarmSubSeconds >= (PREDIV_S + 1)) - { - rtcAlarmSubSeconds -= (PREDIV_S + 1); - rtcAlarmSeconds++; - } - - while (rtcAlarmSeconds >= TM_SECONDS_IN_1MINUTE) - { - rtcAlarmSeconds -= TM_SECONDS_IN_1MINUTE; - rtcAlarmMinutes++; - } - - while (rtcAlarmMinutes >= TM_MINUTES_IN_1HOUR) - { - rtcAlarmMinutes -= TM_MINUTES_IN_1HOUR; - rtcAlarmHours++; - } - - while (rtcAlarmHours >= TM_HOURS_IN_1DAY) - { - rtcAlarmHours -= TM_HOURS_IN_1DAY; - rtcAlarmDays++; - } - - if (date.Year % 4 == 0) - { - if (rtcAlarmDays > DaysInMonthLeapYear[date.Month - 1]) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[date.Month - 1]; - } - } - else - { - if (rtcAlarmDays > DaysInMonth[date.Month - 1]) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonth[date.Month - 1]; - } - } - - /* Set RTC_AlarmStructure with calculated values*/ - RtcAlarm.AlarmTime.SubSeconds = PREDIV_S - rtcAlarmSubSeconds; - RtcAlarm.AlarmSubSecondMask = ALARM_SUBSECOND_MASK; - RtcAlarm.AlarmTime.Seconds = rtcAlarmSeconds; - RtcAlarm.AlarmTime.Minutes = rtcAlarmMinutes; - RtcAlarm.AlarmTime.Hours = rtcAlarmHours; - RtcAlarm.AlarmDateWeekDay = (uint8_t)rtcAlarmDays; - RtcAlarm.AlarmTime.TimeFormat = time.TimeFormat; - RtcAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; - RtcAlarm.AlarmMask = RTC_ALARMMASK_NONE; - RtcAlarm.Alarm = RTC_ALARM_A; - RtcAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; - RtcAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET; - - // Set RTC_Alarm + alarm_stopped = false; } uint32_t RtcGetTimerValue(void) { - RTC_TimeTypeDef time; - RTC_DateTypeDef date; - - uint32_t calendarValue = (uint32_t)RtcGetCalendarValue(&date, &time); - - return (calendarValue); + return current_time; } uint32_t RtcGetTimerElapsedTime(void) { - RTC_TimeTypeDef time; - RTC_DateTypeDef date; - - uint32_t calendarValue = (uint32_t)RtcGetCalendarValue(&date, &time); - - return ((uint32_t)(calendarValue - RtcTimerContext.Time)); -} - -void RtcSetMcuWakeUpTime(void) -{ - RTC_TimeTypeDef time; - RTC_DateTypeDef date; - - uint32_t now, hit; - int16_t mcuWakeUpTime; -} - -int16_t RtcGetMcuWakeUpTime(void) -{ - return McuWakeUpTimeCal; -} - -static uint64_t RtcGetCalendarValue(RTC_DateTypeDef *date, RTC_TimeTypeDef *time) -{ - uint64_t calendarValue = 0; - - return (calendarValue); -} - -extern TimerTime_t current_time; - -uint32_t RtcGetCalendarTime(uint16_t *milliseconds) -{ - RTC_TimeTypeDef time; - RTC_DateTypeDef date; - uint32_t ticks; - - uint64_t calendarValue = RtcGetCalendarValue(&date, &time); - - uint32_t seconds = (uint32_t)(calendarValue >> N_PREDIV_S); - - ticks = (uint32_t)calendarValue & PREDIV_S; - - *milliseconds = current_time; - - return seconds; -} - -/*! - * \brief RTC IRQ Handler of the RTC Alarm - */ -void RTC_IRQHandler(void) -{ + return ((uint32_t)(current_time - RtcTimerContext.Time)); } /*! @@ -430,15 +178,6 @@ void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) { TimerIrqHandler(); } - -void RtcBkupWrite(uint32_t data0, uint32_t data1) -{ -} - -void RtcBkupRead(uint32_t *data0, uint32_t *data1) -{ -} - void RtcProcess(void) { // Not used on this platform. @@ -446,35 +185,6 @@ void RtcProcess(void) TimerTime_t RtcTempCompensation(TimerTime_t period, float temperature) { - float k = RTC_TEMP_COEFFICIENT; - float kDev = RTC_TEMP_DEV_COEFFICIENT; - float t = RTC_TEMP_TURNOVER; - float tDev = RTC_TEMP_DEV_TURNOVER; - float interim = 0.0f; - float ppm = 0.0f; - - if (k < 0.0f) - { - ppm = (k - kDev); - } - else - { - ppm = (k + kDev); - } - interim = (temperature - (t - tDev)); - ppm *= interim * interim; - - // Calculate the drift in time - interim = ((float)period * ppm) / 1000000.0f; - // Calculate the resulting time period - interim += period; - interim = floor(interim); - - if (interim < 0.0f) - { - interim = (float)period; - } - // Calculate the resulting period - return (TimerTime_t)interim; + return (TimerTime_t)1; } diff --git a/tests/timer-mock.cpp b/tests/timer-mock.cpp deleted file mode 100644 index 2ac1a4cda..000000000 --- a/tests/timer-mock.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/*! - * \file timer.c - * - * \brief Timer objects and scheduling management implementation - * - * \copyright Revised BSD License, see section \ref LICENSE. - * - * \code - * ______ _ - * / _____) _ | | - * ( (____ _____ ____ _| |_ _____ ____| |__ - * \____ \| ___ | (_ _) ___ |/ ___) _ \ - * _____) ) ____| | | || |_| ____( (___| | | | - * (______/|_____)_|_|_| \__)_____)\____)_| |_| - * (C)2013-2017 Semtech - * - * \endcode - * - * \author Miguel Luis ( Semtech ) - * - * \author Gregory Cristian ( Semtech ) - * - * \author Modified for mocking by Medad Newman - * - * This file implements a mock of the timer.c file, using a c++ list to hold all pointers - * to timers. It calls the call back of each timer when it expires. - */ - -#include "CppUTestExt/MockSupport.h" -#include - -/*! - * Safely execute call back - */ -#define ExecuteCallBack(_callback_, context) \ - do \ - { \ - if (_callback_ == NULL) \ - { \ - while (1) \ - ; \ - } \ - else \ - { \ - _callback_(context); \ - } \ - } while (0); - -extern "C" -{ -#include "timer.h" -} -/*! - * Timers list head pointer - */ -TimerTime_t current_time = 0; - -TimerEvent_t *list_of_timer_event_pointers[100000]; /* There won't be more than 100 timers in the project */ -int number_of_timers = 0; - -void TimerInit(TimerEvent_t *obj, void (*callback)(void *context)) -{ - obj->Timestamp = 0; - obj->ReloadValue = 0; - obj->IsStarted = false; - obj->IsNext2Expire = false; - obj->Callback = callback; - obj->Context = NULL; - obj->Next = NULL; - - list_of_timer_event_pointers[number_of_timers] = obj; - number_of_timers++; -} - -void TimerStart(TimerEvent_t *obj) -{ - obj->Timestamp = obj->ReloadValue; - obj->IsStarted = true; - obj->IsNext2Expire = false; -} - -void TimerIrqHandler(void) -{ - /** - * @brief Check through countdown timers, and decrement them if they are active. - * If hits zero, set them inactive(IsStarted = false), and set IsNext2Expire - * - * @param list_of_timer_event_pointers - */ - for (int i = 0; i < number_of_timers; ++i) - { - TimerEvent_t *timer_event = list_of_timer_event_pointers[i]; - // printf("Timestamp[ms]: %d\n", timer_event->Timestamp); - - if (timer_event->IsStarted) - { - timer_event->Timestamp--; - - if (timer_event->Timestamp == 0) - { - timer_event->IsNext2Expire = true; - timer_event->IsStarted = false; - } - } - } - - // printf("\n"); - - /** - * Now here, execute the call back of first expiring timer - * Leave the execution of the next expiring timer to the next time - * TimerIrqHandler() is called, to allow stuff to update on the main - * main loop. - * - */ - for (int i = 0; i < number_of_timers; ++i) - { - TimerEvent_t *timer_event = list_of_timer_event_pointers[i]; - if (timer_event->IsNext2Expire == true) - { - ExecuteCallBack(timer_event->Callback, timer_event->Context); - timer_event->IsNext2Expire = false; - return; - } - } -} - -void TimerStop(TimerEvent_t *obj) -{ - obj->IsStarted = false; -} - -void TimerSetValue(TimerEvent_t *obj, uint32_t value) -{ - - TimerStop(obj); - - obj->Timestamp = value; - obj->ReloadValue = value; -} - -TimerTime_t TimerGetCurrentTime(void) -{ - return current_time; -} - -TimerTime_t TimerGetElapsedTime(TimerTime_t past) -{ - return current_time - past; -} diff --git a/tests/ublox-mock.cpp b/tests/ublox-mock.cpp index 88fa44e67..0ebb0bdf3 100644 --- a/tests/ublox-mock.cpp +++ b/tests/ublox-mock.cpp @@ -1,10 +1,13 @@ -#include "CppUTestExt/MockSupport.h" extern "C" { #include "ublox.h" } +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 +32,7 @@ uint16_t get_load_solar_voltage() gps_info_t get_latest_gps_info() { - auto returnValue = mock().actualCall(__func__).returnPointerValue(); - return *(gps_info_t *)(returnValue); + return dummy_gps_info; } gps_status_t get_latest_gps_status(void) From ee5db8acb2900e51205b551c820ae922bec3edc5 Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Thu, 25 Aug 2022 21:30:00 +0100 Subject: [PATCH 02/10] add ublox simulator --- tests/CMakeLists.txt | 1 + tests/ublox-mock.cpp | 7 ++----- tests/ublox_simulator.cpp | 23 +++++++++++++++++++++++ tests/ublox_simulator.hpp | 3 +++ 4 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 tests/ublox_simulator.cpp create mode 100644 tests/ublox_simulator.hpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e9a5a1eed..0165ac82b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -97,6 +97,7 @@ set(MOCKS gpio_mock.c rtc-board-mock.c mocks/rtc_mock.c + ublox_simulator.cpp ) diff --git a/tests/ublox-mock.cpp b/tests/ublox-mock.cpp index 0ebb0bdf3..2d041a787 100644 --- a/tests/ublox-mock.cpp +++ b/tests/ublox-mock.cpp @@ -4,10 +4,7 @@ extern "C" #include "ublox.h" } -gps_info_t dummy_gps_info = { - .GPS_UBX_latitude_Float = 1.290270, - .GPS_UBX_longitude_Float = 103.851959 -}; +#include "ublox_simulator.hpp" gps_status_t get_location_fix(uint32_t timeout) @@ -32,7 +29,7 @@ uint16_t get_load_solar_voltage() gps_info_t get_latest_gps_info() { - return dummy_gps_info; + return get_simulated_gps_position(); } gps_status_t get_latest_gps_status(void) diff --git a/tests/ublox_simulator.cpp b/tests/ublox_simulator.cpp new file mode 100644 index 000000000..1b3ff5f05 --- /dev/null +++ b/tests/ublox_simulator.cpp @@ -0,0 +1,23 @@ + +#include "ublox_simulator.hpp" +#include + +gps_info_t dummy_gps_info = { + .GPS_UBX_latitude_Float = 1.290270, + .GPS_UBX_longitude_Float = 103.851959, + .unix_time = 1660247778, + .latest_gps_status = GPS_SUCCESS, + +}; + +float gps_long_counter = 0; + +gps_info_t get_simulated_gps_position() +{ + gps_long_counter += 0.1; + dummy_gps_info.GPS_UBX_longitude_Float = fmod(gps_long_counter * 1.8, 360) - 180; + dummy_gps_info.GPS_UBX_latitude_Float = fmod(gps_long_counter, 180) - 90; + dummy_gps_info.unix_time += 360; + + return dummy_gps_info; +} diff --git a/tests/ublox_simulator.hpp b/tests/ublox_simulator.hpp new file mode 100644 index 000000000..b3c27e795 --- /dev/null +++ b/tests/ublox_simulator.hpp @@ -0,0 +1,3 @@ +#include "ublox.h" + +gps_info_t get_simulated_gps_position(); From 7dfeaafbf1704efbdf048f6344fc03aa233e370a Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Thu, 25 Aug 2022 21:32:53 +0100 Subject: [PATCH 03/10] Enable coverage for executable --- .../periodic-uplink-lpp/B-L072Z-LRWAN1/main.c | 17 +++++++++++++++++ tests/CMakeLists.txt | 1 + 2 files changed, 18 insertions(+) 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 1a4edf6df..73e6f965c 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 @@ -38,6 +38,7 @@ #include "message_sender.h" #include "eeprom_settings_manager.h" #include "nvmm.h" +#include "signal.h" #ifdef UNITTESTING_LORA #include "rtc_mock.h" @@ -127,11 +128,27 @@ extern Uart_t Uart1; uint32_t tx_count_on_this_credential = 0; +void handler(int signum) +{ + /* notify the operator that the service has receive SIGTERM + and clean up (close file descriptors, etc). Will allow .gcda runtime + coverage files to be properly created. + Taken from https://stackoverflow.com/a/71168545 + */ + + exit(0); +} + + /*! * Main application entry point. */ int main( void ) { + signal(SIGTERM, handler); + signal(SIGHUP, handler); + signal(SIGINT, handler); + #if( USE_WATCHDOG ) IWDG_Init( ); #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0165ac82b..d7e751f4a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -188,4 +188,5 @@ add_executable(picotracker_lora_integration_tests ${INTEGRATION_TEST_SOURCE_FILE # only build 32-bit binaries target_compile_options(picotracker_lora_integration_tests PRIVATE -m32) target_link_options(picotracker_lora_integration_tests PRIVATE -m32) +target_compile_options(picotracker_lora_integration_tests PRIVATE -g -fprofile-arcs -ftest-coverage) From 12a654af6d51b73dbf69ae4ee01961499e022363 Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Thu, 25 Aug 2022 21:33:11 +0100 Subject: [PATCH 04/10] remove redundant code --- tests/CMakeLists.txt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d7e751f4a..de0a78ac0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,21 +1,6 @@ cmake_minimum_required(VERSION 3.7) -# 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") - -FetchContent_MakeAvailable(cpputest) add_definitions( -DREGION_EU868 @@ -35,9 +20,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/) @@ -153,7 +135,6 @@ set(FILES_UNDER_TEST ${PROJECT_SOURCE_DIR}/src/peripherals/soft-se/aes.c ${PROJECT_SOURCE_DIR}/src/peripherals/soft-se/soft-se-hal.c - ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/CayenneLpp.c ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/LmHandlerMsgDisplay.c ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/NvmDataMgmt.c ${PROJECT_SOURCE_DIR}/src/apps/LoRaMac/common/LmHandler/LmHandler.c From 6cbdb549a7abd2fffbcd32f2d3031f346828cd42 Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Mon, 29 Aug 2022 16:35:47 +0100 Subject: [PATCH 05/10] Update CMakeLists.txt --- CMakeLists.txt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f02280a5a..6e621524c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,15 +26,6 @@ if(UNIT_TESTING) # Use reference https://stackoverflow.com/a/52257586 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - include(CodeCoverage) - APPEND_COVERAGE_COMPILER_FLAGS() - SETUP_TARGET_FOR_COVERAGE_LCOV( - NAME coverage_my - EXECUTABLE ctest -j ${n_cores} # Executable in PROJECT_BINARY_DIR - DEPENDENCIES - picotracker_lora_tests - EXCLUDE "build/_deps*" "/usr/include/c++/*" # Patterns to exclude (can be relative - ) add_subdirectory(tests) else() message(STATUS ">>> Compiling for target") From d6e751c7381c4975278f068e164b833865844e24 Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Mon, 29 Aug 2022 16:36:01 +0100 Subject: [PATCH 06/10] mvp --- tests/CMakeLists.txt | 19 +++++++++++-------- tests/parser_brute_force.cpp | 12 ++++++++++++ 2 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 tests/parser_brute_force.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index de0a78ac0..8c13b721a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.7) - +set(CMAKE_C_COMPILER "clang") +set(CMAKE_CXX_COMPILER "clang++") +set(CMAKE_CXX_STANDARD 14) add_definitions( @@ -47,7 +49,6 @@ include_directories(${PROJECT_SOURCE_DIR}/src/radio/sx1276/) # Unittests set(UNIT_TESTS - main.cpp geofence_ut.cpp playback_ut.cpp lorawan_credentials_ut.cpp @@ -103,7 +104,6 @@ set(FILES_UNDER_TEST ${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/periodic-uplink-lpp/B-L072Z-LRWAN1/main.c @@ -164,10 +164,13 @@ set(INTEGRATION_TEST_SOURCE_FILES ${MOCKS} ${FILES_UNDER_TEST} ) -add_executable(picotracker_lora_integration_tests ${INTEGRATION_TEST_SOURCE_FILES}) -# only build 32-bit binaries -target_compile_options(picotracker_lora_integration_tests PRIVATE -m32) -target_link_options(picotracker_lora_integration_tests PRIVATE -m32) -target_compile_options(picotracker_lora_integration_tests PRIVATE -g -fprofile-arcs -ftest-coverage) + +set(CMAKE_CXX_FLAGS -fsanitize=fuzzer,address,undefined) + + +add_executable(parser_brute_force + parser_brute_force.cpp + ${INTEGRATION_TEST_SOURCE_FILES} +) diff --git a/tests/parser_brute_force.cpp b/tests/parser_brute_force.cpp new file mode 100644 index 000000000..d0cf231dc --- /dev/null +++ b/tests/parser_brute_force.cpp @@ -0,0 +1,12 @@ +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ + for (size_t i = 0; i < Size; ++i) + { + mavlink_message_t message; + mavlink_status_t status; + mavlink_parse_char(MAVLINK_COMM_0, Data[i], &message, &status); + } + return 0; +} From 69f674db43ed9ff4e30e2c0c8c972507bf6877ea Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Mon, 29 Aug 2022 16:41:30 +0100 Subject: [PATCH 07/10] Update parser_brute_force.cpp --- tests/parser_brute_force.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/parser_brute_force.cpp b/tests/parser_brute_force.cpp index d0cf231dc..3626d3714 100644 --- a/tests/parser_brute_force.cpp +++ b/tests/parser_brute_force.cpp @@ -1,12 +1,13 @@ #include +#include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - for (size_t i = 0; i < Size; ++i) - { - mavlink_message_t message; - mavlink_status_t status; - mavlink_parse_char(MAVLINK_COMM_0, Data[i], &message, &status); - } + LoRaMacMessageData_t message = { + .Buffer = Data, + .BufSize = Size, + }; + LoRaMacParserData(&message); + return 0; } From dc84ba8046bd4bf7fc8aca1c6fa2e797ea8f9a2d Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Mon, 29 Aug 2022 16:43:39 +0100 Subject: [PATCH 08/10] Update parser_brute_force.cpp --- tests/parser_brute_force.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/parser_brute_force.cpp b/tests/parser_brute_force.cpp index 3626d3714..aaf7548d3 100644 --- a/tests/parser_brute_force.cpp +++ b/tests/parser_brute_force.cpp @@ -4,8 +4,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { LoRaMacMessageData_t message = { - .Buffer = Data, - .BufSize = Size, + .Buffer = (uint8_t*)Data, + .BufSize = (uint8_t)Size, }; LoRaMacParserData(&message); From 022f019931dfb046242c32c1cb14715774b26548 Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Mon, 29 Aug 2022 16:45:29 +0100 Subject: [PATCH 09/10] buillds --- src/apps/LoRaMac/common/callbacks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/LoRaMac/common/callbacks.c b/src/apps/LoRaMac/common/callbacks.c index 5ad26e5f5..9ddc851bf 100644 --- a/src/apps/LoRaMac/common/callbacks.c +++ b/src/apps/LoRaMac/common/callbacks.c @@ -47,7 +47,7 @@ void OnNvmDataChange(LmHandlerNvmContextStates_t state, uint16_t size) */ if (state == LORAMAC_HANDLER_NVM_STORE) { - tx_count_on_this_credential++; + // tx_count_on_this_credential++; #if GPS_ENABLED setup_GPS(); From a70856bfcf76b9fab46e183a979b5f635e200561 Mon Sep 17 00:00:00 2001 From: Medad Rufus Newman Date: Mon, 29 Aug 2022 17:51:38 +0100 Subject: [PATCH 10/10] workaround to use canonical string.h --- src/mac/LoRaMacParser.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mac/LoRaMacParser.c b/src/mac/LoRaMacParser.c index 9c76eb36f..292703842 100644 --- a/src/mac/LoRaMacParser.c +++ b/src/mac/LoRaMacParser.c @@ -20,6 +20,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ), */ #include "LoRaMacParser.h" #include "utilities.h" +#include "string.h" LoRaMacParserStatus_t LoRaMacParserJoinAccept( LoRaMacMessageJoinAccept_t* macMsg ) { @@ -88,7 +89,7 @@ LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t* macMsg ) if( macMsg->FHDR.FCtrl.Bits.FOptsLen <= 15 ) { - memcpy1( macMsg->FHDR.FOpts, &macMsg->Buffer[bufItr], macMsg->FHDR.FCtrl.Bits.FOptsLen ); + memcpy( macMsg->FHDR.FOpts, &macMsg->Buffer[bufItr], macMsg->FHDR.FCtrl.Bits.FOptsLen ); bufItr = bufItr + macMsg->FHDR.FCtrl.Bits.FOptsLen; } else @@ -105,7 +106,7 @@ LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t* macMsg ) macMsg->FPort = macMsg->Buffer[bufItr++]; macMsg->FRMPayloadSize = ( macMsg->BufSize - bufItr - LORAMAC_MIC_FIELD_SIZE ); - memcpy1( macMsg->FRMPayload, &macMsg->Buffer[bufItr], macMsg->FRMPayloadSize ); + memcpy( macMsg->FRMPayload, &macMsg->Buffer[bufItr], macMsg->FRMPayloadSize ); bufItr = bufItr + macMsg->FRMPayloadSize; }