From 14f512ab8259de45221c277a69e44879d256089e Mon Sep 17 00:00:00 2001 From: Joshua Yan <52796499+yanjos-dev@users.noreply.github.com> Date: Tue, 8 Dec 2020 15:13:00 -0800 Subject: [PATCH] Update the OTA PAL unit tests for 100% code coverage (#1430) * Add OTA from AFR 202007.00 release * Fix OTA CMake file, add jsmn and tinycbor * Delete JSMN files before submodule * Submodule JSMN on master * Update JSMN to v1.1.0 * Delete tinycbor before submodule * Submodule TinyCBOR to master * Update .gitmodule with the version of TinyCBOR * OTA Agent Posix : Use POSIX thread instead of FreeRTOS task * OTA Agent POSIX: Use POSIX semaphore instead of FreeRTOS semaphore * OTA linux pal * Add OTA demo * Update OTA library to use new MQTT library * OTA LTS Dev: Update include files in OTA Agent File * OTA LTS Dev: Update OTA Agent context initialization * OTA LTS Dev: Self-test timer functions to use timer interface * OTA LTS Dev: Request timer functions implementation to use timers passed to the lib * OTA LTS Dev: use assert instead of configassert in OTA Agent * OTA LTS Dev: Update buffer get and free functions by removing protection * OTA LTS Dev: Add OS interface context to OTA Agent Init functions * OTA LTS Dev: Add OTA OS implementation file * OTA LTS Dev: OTA MQTT demo update * OTA LTS Dev: OTA Agent changes for C-SDK * OTA LTS Dev: OTA MQTT component changes for C-SDK * OTA Dev LTS: OTA OS interface for linux * Add mbedtls * Remove mock * tmp fix for OTA * Remove OTA library * Add OTA as an submodule * Update OTA config with minimum request blocks * Remove ota_os_interface.h from platform folder * Remove stdbool.h from ota_os_posix.h * Update OTA naming convention * Update OTA submodule * Update OTA demo cmake file * Fix warnings * Update OTA submodule * Remove tinycbor from 3rdparty dir * Update OTA submodule and demo CMake file * OTA MQTT demo main and startota functions * MQTT and OS interface in startotademo * OTA MQTT interface publish and subscribe implementation * OTA demo MQTT interface cleanup * Fix OTA demo due to folder structure update * Remove hard coded cert from OTA demo * Use OTA error codes for OTA MQTT interface * Add sending start event from the OTA demo * Implement MQTT unscubscribe function for OTA MQTT * Update OTA submodule and remove jsmn, mbedtls * Update OTA submodule * Update .gitmodules URL and ota target commit * Update OTA submodule * Update OTA submodule and remove iot_appversion32.h * Update naming convention in OTA demo and OTA submodule * Add platform state update in OTA pal for linux * Update OTA demo loop for receivng notification * Update OTA submodule * Update OTA submodule * Add sleep in the OTA demo loop for all conditions * Change to use https link for ota submodule * Add payload size to callback log messages * Remove OTA OS Posix implementation from Paltforms * OTA demo directory change * renaming demos * Refactor MQTT initialization and connection functions * OTA over HTTP demo use local mqtt context * Add http interface to OTA_AgentInit * Add http utils functions * Update HTTP utils functions * OTA over HTTP cmake update for HTTP sources * Implement OTA http request function * Implement http deinit function * Add HTTP port to OTA HTTP demo config * Update OTA submodule * Fix OTA platform cmake file * Remove aws_ota_agent_config.h * Add ota_config.h for MQTT & HTTP demos * change OTA logging to csdk logging in demos * Change OTA logging to Csdk on Linux OTA pal * Update OTA demo config files and OTA submodule * Use application buffers in OTA MQTT demo * Uncrustify demo * use application memory in OTA HTTP * remove ota pal file temporarily * Adding OTA Linux Pal file * Update with new PAL interface * Update after PR review * Update OTA submodule * Refactor and cleanup OTA MQTT demo * Format aws_ota_pal.c * Update log strings in aws_ota_pal.c * Fix typos in aws_ota_pal.c (#47) * Fix space formatting in aws_ota_mqtt.c (#48) * Update OTA submodule * Added OTA Pal unit tests (#50) * ota pal unittests addition * Added more ota pal unittest coverage * Fix file context check in ota linux pal * Update OTA submodule * Formatting changes (#52) * formatting update (#53) * Update OTA submodule * Change OTA demo config and remove pal context checks * Update OTA submodule * Update OTA submodule * Update coreHTTP submodule * Fix OTA HTTP demo * Update Thing Name to 128 * Update ota_config.h * Build and CI checks fixed * Fixing the CMakeLists.txt * Coverity MISRA warning fix * Fix spell check errors * Fix uncrustify warning * changes from review * changes from review * File, folder name changes. * formatting and spell check fix * fix spell check * Update OTA submodule, demo, and posix pal * Update HTTP submodule * Clean up and remove duplicates in demo/lexicon.txt * Fix OTA demo after merge with c-sdk main * Temporarily remove ota demos * Revert a cmake change * Fix some compiler warnings in ota pal posix * Update OTA submodule * Update error codes in OTA pal and unit tests * Add realpath to the file name. (#57) * Add realpath to the file name. * Update OTA submodule * Fix unused variable warning * Fix ota pal unit tests * Remove the private key for ota unit tests * Update CMake files for OTA test mocks * Mock fseek and fwrite in OTA PAL tests * Enhance OTA PAL posix unit test coverage Get 100% coverage for: * otaPal_Abort * otaPal_CreateFileForRx * otaPal_WriteBlock * Fix build errors in posix OTA PAL tests * Mock OpenSSL and stdio func. for OTA unit tests * Rewrite otaPal_GetPlatformImageState unit tests * tmp commit for initial attempt * Add helper function to fail a single mock call * Update unit tests for otaPal_SetPlatformImageState * Add mock helper functions to OTA PAL unit tests * Fix some mistakes in the OTA PAL unit tests * Fix OTA PAL unit test variable names * Get OTA PAL unit test coverage over 90% * Remove some of the alias funcs * Remove impossible condition from OTA PAL * Update OTA PAL unit tests for 100% coverage * Remove unnecessary alias mocks from OTA PAL tests * Organize OTA PAL unit tests * Start to remove global usage * Update OTA PAL unit tests for 100% coverage * Remove globals from OTA PAL unit tests * Uncrustify OTA PAL test files * Fix spelling in OTA PAL unit tests * Fix mistake in OTA PAL unit tests cmake * Add mock header include to OTA PAL test * Fix warnings in OTA PAL unit tests * Fix incorrect OTA PAL test asserts * Fix typos in the lexicon files * Remove unnecessary content from ota.yml * Remove unnecessary OTA PAL unit test. * Clarify variable in OTA PAL unit tests * Remove unnecessary configs from ota.yml * Update spelling and formatting for OTA PAL * Address PR feedback for OTA PAL unit tests * Uncrustify OTA PAL unit test code Co-authored-by: Tiangang Song Co-authored-by: Prasad Vyawahare Co-authored-by: Xie Co-authored-by: xuelix Co-authored-by: xuelix <33909469+xuelix@users.noreply.github.com> Co-authored-by: Shubham Divekar --- CMakeLists.txt | 2 +- demos/lexicon.txt | 2 + platform/lexicon.txt | 13 +- platform/posix/ota_pal/CMakeLists.txt | 2 +- platform/posix/ota_pal/source/ota_pal_posix.c | 59 +- platform/posix/ota_pal/utest/CMakeLists.txt | 23 +- .../posix/ota_pal/utest/mocks/openssl_api.h | 137 ++ .../posix/ota_pal/utest/mocks/stdio_api.h | 78 + platform/posix/ota_pal/utest/ota_config.h | 19 + .../posix/ota_pal/utest/ota_pal_posix_utest.c | 1330 +++++++++++------ .../posix/ota_pal/utest/ota_utest_config.h.in | 44 - tools/cmock/ota.yml | 33 + 12 files changed, 1156 insertions(+), 586 deletions(-) create mode 100644 platform/posix/ota_pal/utest/mocks/openssl_api.h create mode 100644 platform/posix/ota_pal/utest/mocks/stdio_api.h delete mode 100644 platform/posix/ota_pal/utest/ota_utest_config.h.in create mode 100644 tools/cmock/ota.yml diff --git a/CMakeLists.txt b/CMakeLists.txt index 5911761e3f..bb9a092e64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,7 @@ if(${BUILD_TESTS}) # Create a list for each unit test target. set(utest_targets openssl_utest sockets_utest - plaintext_utest clock_utest) + plaintext_utest clock_utest ota_pal_posix_utest) # Add a target for running coverage on tests. add_custom_target(coverage diff --git a/demos/lexicon.txt b/demos/lexicon.txt index 3788daeb29..7dfb63d8e9 100644 --- a/demos/lexicon.txt +++ b/demos/lexicon.txt @@ -1,3 +1,4 @@ + accel ack acks @@ -266,6 +267,7 @@ lastcontrolpacketsent latestversion len leurent +lfilecloseresult libc libmosquitto libpkcs diff --git a/platform/lexicon.txt b/platform/lexicon.txt index 19546bfd04..6dd70d633e 100644 --- a/platform/lexicon.txt +++ b/platform/lexicon.txt @@ -9,6 +9,7 @@ aws backoff backoffdelay basedefs +bio bitmasking bool bootable @@ -29,6 +30,7 @@ const couldn coverity crt +crypto csdk cwd didn @@ -40,10 +42,12 @@ endcode endif enum enums +eof epalstate errno errornumber esavedagentstate +evp ewouldblock exe expectedstatus @@ -60,13 +64,16 @@ fopen fread freertos fseek +fseeksuccessreturn functionname functionpage functionspage functiontofail fwrite +fwriteerrorreturn getaddrinfo getcwd +h hostnamelength html http @@ -79,6 +86,7 @@ int iot ip ip +lfilecloseresult linux logpath longjmp @@ -113,9 +121,11 @@ otafile otaimagestateaborted otaimagestateaccepted otaimagestaterejected +otaimagestatetesting otaimagestateinvalid otaimagestatependingcommit otaimagestateunknown +otalastimagestate otapalimagestateinvalid otapalimagestatependingcommit otapalimagestateunknown @@ -175,6 +185,7 @@ sizeof sleeptimems sni snihostname +snprintf sockaddr sockets_invalid_parameter socketstatus @@ -232,4 +243,4 @@ otapalactivatefailed otapalfileabort otapalfileclose pdata -pfilecontext \ No newline at end of file +pfilecontext diff --git a/platform/posix/ota_pal/CMakeLists.txt b/platform/posix/ota_pal/CMakeLists.txt index 3a6d4cf107..f5bec31de2 100644 --- a/platform/posix/ota_pal/CMakeLists.txt +++ b/platform/posix/ota_pal/CMakeLists.txt @@ -14,6 +14,6 @@ target_link_libraries( ota_pal INTERFACE ${OPENSSL_CRYPTO_LIBRARY} ) -if(BUILD_TESTS) +if(${BUILD_TESTS}) add_subdirectory(utest) endif() diff --git a/platform/posix/ota_pal/source/ota_pal_posix.c b/platform/posix/ota_pal/source/ota_pal_posix.c index 620ff09a51..ed659020bc 100644 --- a/platform/posix/ota_pal/source/ota_pal_posix.c +++ b/platform/posix/ota_pal/source/ota_pal_posix.c @@ -155,11 +155,10 @@ static OtaPalMainStatus_t Openssl_DigestVerifyStart( EVP_MD_CTX * pSigContext, OtaPalMainStatus_t mainErr = OtaPalSignatureCheckFailed; assert( pBuf != NULL ); + assert( ( pSigContext != NULL ) && ( pPkey != NULL ) ); /* Verify an ECDSA-SHA256 signature. */ - if( ( pSigContext != NULL ) && - ( pPkey != NULL ) && - ( pFile != NULL ) && + if( ( pFile != NULL ) && ( 1 == EVP_DigestVerifyInit( pSigContext, NULL, EVP_sha256(), NULL, pPkey ) ) ) { LogDebug( ( "Started signature verification." ) ); @@ -196,10 +195,12 @@ static bool Openssl_DigestVerifyUpdate( EVP_MD_CTX * pSigContext, /* coverity[misra_c_2012_rule_21_6_violation] */ bytesRead = fread( pBuf, 1U, OTA_PAL_POSIX_BUF_SIZE, pFile ); + assert( bytesRead < OTA_PAL_POSIX_BUF_SIZE ); + /* feof returns non-zero if end of file is reached, otherwise it returns 0. When * bytesRead is not equal to OTA_PAL_POSIX_BUF_SIZE, we should be reading last * chunk and reach to end of file. */ - if( ( bytesRead < OTA_PAL_POSIX_BUF_SIZE ) && ( 0 == feof( pFile ) ) ) + if( 0 == feof( pFile ) ) { break; } @@ -263,44 +264,36 @@ static OtaPalStatus_t otaPal_CheckFileSignature( OtaFileContext_t * const C ) EVP_PKEY * pPkey = NULL; EVP_MD_CTX * pSigContext = NULL; - if( C != NULL ) - { - /* Extract the signer cert from the file */ - pPkey = Openssl_GetPkeyFromCertificate( C->pCertFilepath ); + assert( C != NULL ); - /* Create a new signature context for verification purpose */ - pSigContext = EVP_MD_CTX_new(); + /* Extract the signer cert from the file. */ + pPkey = Openssl_GetPkeyFromCertificate( C->pCertFilepath ); - if( ( pPkey != NULL ) && ( pSigContext != NULL ) ) + /* Create a new signature context for verification purpose. */ + pSigContext = EVP_MD_CTX_new(); + + if( ( pPkey != NULL ) && ( pSigContext != NULL ) ) + { + /* Verify the signature. */ + mainErr = Openssl_DigestVerify( pSigContext, pPkey, C->pFile, C->pSignature ); + } + else + { + if( pSigContext == NULL ) { - /* Verify an ECDSA-SHA256 signature. */ - mainErr = Openssl_DigestVerify( pSigContext, pPkey, C->pFile, C->pSignature ); + LogError( ( "File signature check failed at NEW sig context." ) ); } else { - if( pSigContext == NULL ) - { - LogError( ( "File signature check failed at NEW sig context." ) ); - } - else - { - LogError( ( "File signature check failed at EXTRACT pkey from signer certificate." ) ); - mainErr = OtaPalBadSignerCert; - } + LogError( ( "File signature check failed at EXTRACT pkey from signer certificate." ) ); + mainErr = OtaPalBadSignerCert; } - - /* Free up objects */ - EVP_MD_CTX_free( pSigContext ); - EVP_PKEY_free( pPkey ); - } - else - { - LogError( ( "Failed to check file signature: Paramater check failed: " - " Invalid OTA file context." ) ); - /* Invalid OTA context or file pointer. */ - mainErr = OtaPalNullFileContext; } + /* Free up objects */ + EVP_MD_CTX_free( pSigContext ); + EVP_PKEY_free( pPkey ); + return OTA_PAL_COMBINE_ERR( mainErr, 0 ); } diff --git a/platform/posix/ota_pal/utest/CMakeLists.txt b/platform/posix/ota_pal/utest/CMakeLists.txt index 7e25bdb7fd..4308f66697 100644 --- a/platform/posix/ota_pal/utest/CMakeLists.txt +++ b/platform/posix/ota_pal/utest/CMakeLists.txt @@ -8,11 +8,13 @@ set( project_name "ota_pal" ) #list the files to mock here list( APPEND mock_list - "" + ${CMAKE_CURRENT_LIST_DIR}/mocks/stdio_api.h + ${CMAKE_CURRENT_LIST_DIR}/mocks/openssl_api.h ) #list the directories your mocks need list( APPEND mock_include_list - "" + ${LOGGING_INCLUDE_DIRS} + ${PLATFORM_DIR}/include ) #list the definitions of your mocks to control what to be included list( APPEND mock_define_list @@ -32,6 +34,7 @@ list( APPEND real_include_directories "${PLATFORM_DIR}/posix/ota_pal/source/include" ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/mocks ) #== =================== Create UnitTest Code here (edit) ===================== @@ -41,12 +44,20 @@ list ( APPEND test_include_directories ${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_LIST_DIR} ${MODULES_DIR}/aws/ota-for-aws-iot-embedded-sdk/source/include + /usr/include/x86_64-linux-gnu/sys + mocks ) #== =========================== (end edit) =================================== -set ( mock_name "" ) +set ( mock_name "ota_pal_mocks" ) set ( real_name "ota_pal_real" ) +create_mock_list(${mock_name} + "${mock_list}" + "${ROOT_DIR}/tools/cmock/ota.yml" + "${mock_include_list}" + "${mock_define_list}" + ) create_real_library ( ${real_name} "${real_source_files}" @@ -56,7 +67,6 @@ create_real_library ( ${real_name} list(APPEND utest_link_list lib${real_name}.a - ${OPENSSL_LIBRARIES} ) list ( APPEND utest_dep_list @@ -71,8 +81,3 @@ create_test ( ${utest_name} "${utest_dep_list}" "${test_include_directories}" ) - -# Unit tests configuration -set(OTA_PAL_UTEST_CERT_FILE "${CMAKE_CURRENT_LIST_DIR}/test_files/ecdsa-sha256-signer.crt.pem") -set(OTA_PAL_UTEST_FIRMWARE_FILE "${CMAKE_BINARY_DIR}/bin/tests/dummy.bin") -configure_file(ota_utest_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/ota_utest_config.h) diff --git a/platform/posix/ota_pal/utest/mocks/openssl_api.h b/platform/posix/ota_pal/utest/mocks/openssl_api.h new file mode 100644 index 0000000000..aca227bccf --- /dev/null +++ b/platform/posix/ota_pal/utest/mocks/openssl_api.h @@ -0,0 +1,137 @@ +/* + * AWS IoT Device SDK for Embedded C V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef OPENSSL_API_H_ +#define OPENSSL_API_H_ + +#include + +/** + * @file openssl_api.h + * @brief This file is used to generate mocks for the OpenSSL API's used in + * the abstraction layer. Mocking openssl/ssl.h itself causes several + * errors from parsing its macros. + */ + +/* These structs must be defined to avoid a build error because the + * they are set as opaque types by the OpenSSL library. */ +struct bio_st +{ + int filler; +}; + +struct bio_method_st +{ + int filler; +}; + +struct x509_st +{ + int filler; +}; + +struct evp_pkey_st +{ + int filler; +}; + +struct evp_md_ctx_st +{ + int filler; +}; + +struct evp_pkey_ctx_st +{ + int filler; +}; + +struct engine_st +{ + int filler; +}; + +struct evp_md_st +{ + int filler; +}; + +/* Function declarations for functions in the OpenSSL bio.h header file. */ +extern const BIO_METHOD * BIO_s_file( void ); + +extern BIO * BIO_new( const BIO_METHOD * type ); + +extern const BIO_METHOD * BIO_s_mem( void ); + +extern int BIO_puts( BIO * bp, + const char * buf ); + +extern void BIO_free_all( BIO * a ); + +extern long BIO_ctrl( BIO * bp, + int cmd, + long larg, + void * parg ); + +/* Function declarations for functions in the OpenSSL pem.h header file. */ +extern X509 * PEM_read_bio_X509( BIO * bp, + X509 ** x, + pem_password_cb * cb, + void * u ); + +/* Function declarations for functions in the OpenSSL x509.h header file. */ +EVP_PKEY * X509_get_pubkey( X509 * x ); + +extern void X509_free( X509 * a ); + +/* Function declarations for functions in the OpenSSL evp.h header file. */ +extern EVP_MD_CTX * EVP_MD_CTX_new( void ); + +extern int EVP_DigestVerifyInit( EVP_MD_CTX * ctx, + EVP_PKEY_CTX ** pctx, + const EVP_MD * type, + ENGINE * e, + EVP_PKEY * pkey ); + +extern int EVP_DigestUpdate( EVP_MD_CTX * ctx, + const void * d, + size_t cnt ); + +extern int EVP_DigestVerifyFinal( EVP_MD_CTX * ctx, + const unsigned char * sig, + size_t siglen ); + +extern void EVP_MD_CTX_free( EVP_MD_CTX * ctx ); + +extern void EVP_PKEY_free( EVP_PKEY * pkey ); + +extern const EVP_MD * EVP_sha256( void ); + +/* Function declarations for functions in the OpenSSL crypto.h header file. */ +extern void CRYPTO_free( void * ptr, + const char * file, + int line ); + +extern void * CRYPTO_malloc( size_t num, + const char * file, + int line ); + +#endif /* ifndef OPENSSL_API_H_ */ diff --git a/platform/posix/ota_pal/utest/mocks/stdio_api.h b/platform/posix/ota_pal/utest/mocks/stdio_api.h new file mode 100644 index 0000000000..0020be9c6f --- /dev/null +++ b/platform/posix/ota_pal/utest/mocks/stdio_api.h @@ -0,0 +1,78 @@ +/* + * AWS IoT Device SDK for Embedded C V202011.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef STDIO_API_H_ +#define STDIO_API_H_ + +#include + +#if defined( __FILE_defined ) + #define _STDIO_FILE_TYPE __FILE +#else + #define _STDIO_FILE_TYPE _IO_FILE +#endif + +/** + * @file stdio_api.h + * @brief This file is used to generate mocks for functions used from . + * Mocking stdio.h itself causes several errors from parsing its macros. + */ + +/* Open a file and create a new stream for it. */ +extern _STDIO_FILE_TYPE * fopen( const char * __filename, + const char * __modes ); + +/* Close STREAM. */ +extern int fclose( _STDIO_FILE_TYPE * __stream ); + +extern int snprintf( char * s, + size_t n, + const char * format, + ... ); + +extern size_t fread( void * ptr, + size_t size, + size_t count, + FILE * stream ); + +extern int feof( FILE * __stream ); + +/* The "fseek" function needs to be mocked to test the OTA PAL. This function + * can't be directly mocked because it's required by the coverage tools. To get + * around this, the "fseek" function is defined as "fseek_alias" in the test + * config file. This replaces the calls to fseek in the OTA PAL with calls to + * this "fseek_alias" function. */ +extern int fseek_alias( _STDIO_FILE_TYPE * __stream, + long int __off, + int __whence ); + +/* The "fwrite" function needs to be mocked to test the OTA PAL. This function + * can't be directly mocked because it's required by the coverage tools. To get + * around this, the "fwrite" function is defined as "fwrite_alias" in the test + * config file. This replaces the calls to fseek in the OTA PAL with calls to + * this "fwrite_alias" function. */ +extern size_t fwrite_alias( const void * __restrict __ptr, + size_t __size, + size_t __n, + _STDIO_FILE_TYPE * __restrict __s ); + +#endif /* ifndef STDIO_API_H_ */ diff --git a/platform/posix/ota_pal/utest/ota_config.h b/platform/posix/ota_pal/utest/ota_config.h index 826cb9e397..edec94e28a 100644 --- a/platform/posix/ota_pal/utest/ota_config.h +++ b/platform/posix/ota_pal/utest/ota_config.h @@ -31,6 +31,9 @@ #ifndef _OTA_CONFIG_H_ #define _OTA_CONFIG_H_ +/* Required for the declarations of fseek_alias and fwrite_alias. */ +#include "stdio_api.h" + /** * @brief The number of words allocated to the stack for the OTA agent. */ @@ -148,4 +151,20 @@ #define configOTA_PRIMARY_DATA_PROTOCOL ( OTA_DATA_OVER_MQTT ) +/* The "fseek" function needs to be mocked to test the OTA PAL. This function + * can't be directly mocked because it's required by the coverage tools. As an + * alternative, this define replaces the fseek calls in the OTA PAL + * implementation with "fseek_alias". This "fseek_alias" function is declared + * with an identical function signature to "fseek" and is mocked in place of + * "fseek". The function declaration for this alias is in "stdio_api.h". */ +#define fseek fseek_alias + +/* The "fwrite" function needs to be mocked to test the OTA PAL. This function + * can't be directly mocked because it's required by the coverage tools. As an + * alternative, this define replaces the fwrite calls in the OTA PAL + * implementation with "fwrite_alias". This "fwrite_alias" function is declared + * with an identical function signature to "fwrite" and is mocked in place of + * "fwrite". The function declaration for this alias is in "stdio_api.h". */ +#define fwrite fwrite_alias + #endif /* _OTA_CONFIG_H_ */ diff --git a/platform/posix/ota_pal/utest/ota_pal_posix_utest.c b/platform/posix/ota_pal/utest/ota_pal_posix_utest.c index a934ca111d..2d99968c94 100644 --- a/platform/posix/ota_pal/utest/ota_pal_posix_utest.c +++ b/platform/posix/ota_pal/utest/ota_pal_posix_utest.c @@ -32,100 +32,320 @@ #include #include -#include #include #include "unity.h" /* For accessing OTA private functions. */ #include "ota_private.h" #include "ota_pal_posix.h" +#include "mock_stdio_api.h" +#include "mock_openssl_api.h" -/* Unit test config. */ -#include "ota_utest_config.h" +/* errno error macro. errno.h can't be included in this file due to mocking. */ +#define ENOENT 0x02 -/* For the otaPal_WriteBlock_WriteManyBlocks test this is the number of blocks of - * dummyData to write to the non-volatile memory. */ -#define testotapalNUM_WRITE_BLOCKS 10 +/* ============================ UNITY FIXTURES ============================ */ -/* For the otaPal_WriteBlock_WriteManyBlocks test this the delay time in ms following - * the block write loop. */ -#define testotapalWRITE_BLOCKS_DELAY_MS 5000 +void setUp( void ) +{ + /* Always reset the OTA file context before each test. */ +} -/** - * @brief Invalid signature for OTA PAL testing. - */ -static const uint8_t ucInvalidSignature[] = +void tearDown( void ) { - 0x30, 0x44, 0x02, 0x20, 0x75, 0xde, 0xa8, 0x1f, 0xca, 0xec, 0xff, 0x16, - 0xbb, 0x38, 0x4b, 0xe3, 0x14, 0xe7, 0xfb, 0x68, 0xf5, 0x3e, 0x86, 0xa2, - 0x71, 0xba, 0x9e, 0x5e, 0x50, 0xbf, 0xb2, 0x7a, 0x9e, 0x00, 0xc6, 0x4d, - 0x02, 0x20, 0x19, 0x72, 0x42, 0x85, 0x2a, 0xac, 0xdf, 0x5a, 0x5e, 0xfa, - 0xad, 0x49, 0x17, 0x5b, 0xce, 0x5b, 0x65, 0x75, 0x08, 0x47, 0x3e, 0x55, - 0xf9, 0x0e, 0xdf, 0x9e, 0x8c, 0xdc, 0x95, 0xdf, 0x63, 0xd2 -}; -static const int ucInvalidSignatureLength = 70; +} -/** - * @brief Valid signature matching the test block in the OTA PAL tests. - */ -static const uint8_t ucValidSignature[] = +/* ========================== HELPER FUNCTIONS ========================== */ +typedef enum +{ + none_fn = 0, + BIO_s_file_fn, + BIO_new_fn, + BIO_s_mem_fn, + BIO_puts_fn, + BIO_free_all_fn, + BIO_read_filename_fn, + PEM_read_bio_X509_fn, + X509_get_pubkey_fn, + X509_free_fn, + EVP_MD_CTX_new_fn, + EVP_DigestVerifyInit_fn, + EVP_DigestVerifyUpdate_fn, + EVP_DigestVerifyFinal_fn, + EVP_MD_CTX_free_fn, + EVP_PKEY_free_fn, + EVP_sha256_fn, + OPENSSL_malloc_fn, + CRYPTO_free_fn, + fopen_fn, + fclose_fn, + snprintf_fn, + feof_fn, + fread_fn, + fseek_alias_fn, + fwrite_alias_fn +} MockFunctionNames_t; + +static void OTA_PAL_FailSingleMock_Except_fread( MockFunctionNames_t funcToFail, + OtaImageState_t * pFreadStateToSet ); +static void OTA_PAL_FailSingleMock_openssl_BIO( MockFunctionNames_t funcToFail ); +static void OTA_PAL_FailSingleMock_openssl_X509( MockFunctionNames_t funcToFail ); +static void OTA_PAL_FailSingleMock_openssl_EVP( MockFunctionNames_t funcToFail ); +static void OTA_PAL_FailSingleMock_openssl_crypto( MockFunctionNames_t funcToFail ); +static void OTA_PAL_FailSingleMock_stdio( MockFunctionNames_t funcToFail, + OtaImageState_t * pFreadStateToSet ); +static void OTA_PAL_FailSingleMock( MockFunctionNames_t funcToFail, + OtaImageState_t * pFreadStateToSet ); + +static void OTA_PAL_FailSingleMock_Except_fread( MockFunctionNames_t funcToFail, + OtaImageState_t * pFreadStateToSet ) { - 0x30, 0x44, 0x02, 0x20, 0x15, 0x6a, 0x68, 0x98, 0xf0, 0x4e, 0x1e, 0x12, - 0x4c, 0xc4, 0xf1, 0x05, 0x22, 0x36, 0xfd, 0xb4, 0xe5, 0x5d, 0x83, 0x08, - 0x2a, 0xf3, 0xa6, 0x7d, 0x32, 0x6b, 0xff, 0x85, 0x27, 0x14, 0x9b, 0xbf, - 0x02, 0x20, 0x26, 0x7d, 0x5f, 0x4d, 0x12, 0xab, 0xec, 0x17, 0xd8, 0x45, - 0xc6, 0x3d, 0x8e, 0xd8, 0x8d, 0x3f, 0x28, 0x26, 0xfd, 0xce, 0x32, 0x34, - 0x17, 0x05, 0x47, 0xb2, 0xf6, 0x84, 0xd5, 0x68, 0x3e, 0x36 -}; -static const int ucValidSignatureLength = 70; + const size_t fread_failure = 0; -/** - * @brief The type of signature method this file defines for the valid signature. - */ -#define otatestSIG_METHOD otatestSIG_SHA256_ECDSA + /* When fread is being called in this case, it is looping until there is + * no more data. Setting fread to fail prevents us from getting stuck in + * the loops. */ + OTA_PAL_FailSingleMock_stdio( funcToFail, pFreadStateToSet ); -/* - * @brief: This dummy data is prepended by a SHA1 hash generated from the rsa-sha1-signer - * certificate and keys in tests/common/ota/test_files. - * - * The RSA SHA256 signature and ECDSA 256 signature are generated from this entire data - * block as is. - */ -static uint8_t dummyData[] = -{ - 0x83, 0x0b, 0xf0, 0x6a, 0x81, 0xd6, 0xca, 0xd7, 0x08, 0x22, 0x0d, 0x6a, - 0x33, 0xfa, 0x31, 0x9f, 0xa9, 0x5f, 0xb5, 0x26, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f -}; + fread_IgnoreAndReturn( fread_failure ); + fread_ReturnThruPtr_ptr( pFreadStateToSet ); -/* Global static OTA file context used in every test. This context is reset to all zeros - * before every test. */ -static OtaFileContext_t otaFile; + OTA_PAL_FailSingleMock_openssl_BIO( funcToFail ); + OTA_PAL_FailSingleMock_openssl_X509( funcToFail ); + OTA_PAL_FailSingleMock_openssl_crypto( funcToFail ); + OTA_PAL_FailSingleMock_openssl_EVP( funcToFail ); +} -/* ============================ UNITY FIXTURES ============================ */ +static void OTA_PAL_FailSingleMock_openssl_BIO( MockFunctionNames_t funcToFail ) +{ + /* + * Define success and failure return values for OpenSSL BIO.h mocks. + */ + static BIO_METHOD dummyBioMethod; + static BIO dummyBIO; + + /* BIO_s_file_fn: Has no documented failure returns. It always returns a + * valid "BIO_METHOD *". */ + BIO_METHOD * BIO_s_file_return; + /* BIO_new_fn: Returns a newly created BIO or NULL if the call fails. */ + BIO * BIO_new_success = &dummyBIO; + BIO * BIO_new_failure = NULL; + BIO * BIO_new_return; + + /* BIO_s_mem_fn: Has no documented failure returns. It always returns + * a valid "BIO_METHOD *". */ + BIO_METHOD * BIO_s_mem_return; + + /* BIO_puts_fn: Returns either the amount of data successfully written + * (if the return value is positive) or that no data was successfully + * written if the result is 0 or -1. */ + int BIO_puts_success = 1; + int BIO_puts_failure = 0; + int BIO_puts_return; + /* BIO_free_all_fn: Does not return anything. */ + + /* BIO_read_filename_fn: Calls BIO_ctrl indirectly. BIO_ctrl + * returns 1 for success or 0 for failure. */ + long BIO_read_filename_fn_success = 1; + long BIO_read_filename_fn_failure = 0; + long BIO_read_filename_fn_return; + + /* + * Set the return value for the mock ( if any ) that matches the input. Set + * the rest of the mock functions to return the success value when called. + */ + BIO_s_file_return = &dummyBioMethod; + BIO_s_file_IgnoreAndReturn( BIO_s_file_return ); + + BIO_new_return = ( funcToFail == BIO_new_fn ) ? BIO_new_failure : BIO_new_success; + BIO_new_IgnoreAndReturn( BIO_new_return ); + + BIO_s_mem_return = &dummyBioMethod; + BIO_s_mem_IgnoreAndReturn( BIO_s_mem_return ); + + BIO_puts_return = ( funcToFail == BIO_puts_fn ) ? BIO_puts_failure : BIO_puts_success; + BIO_puts_IgnoreAndReturn( BIO_puts_return ); + + BIO_free_all_Ignore(); + + BIO_read_filename_fn_return = ( funcToFail == BIO_read_filename_fn ) ? BIO_read_filename_fn_failure : BIO_read_filename_fn_success; + BIO_ctrl_IgnoreAndReturn( BIO_read_filename_fn_return ); +} -void setUp( void ) +static void OTA_PAL_FailSingleMock_openssl_X509( MockFunctionNames_t funcToFail ) { - /* Always reset the OTA file context before each test. */ - memset( &otaFile, 0, sizeof( otaFile ) ); + /* + * Define success and failure return values for OpenSSL X509.h mocks. + */ + static X509 dummyX509; + static EVP_PKEY dummyEVP_PKEY; + /* PEM_read_bio_X509_fn: Returns a valid "X509 *" on success and NULL on error. */ + X509 * PEM_read_bio_X509_success = &dummyX509; + X509 * PEM_read_bio_X509_failure = NULL; + X509 * PEM_read_bio_X509_return; + /* X509_get_pubkey_fn: Returns EVP_PKEY* on success and NULL on error. */ + EVP_PKEY * X509_get_pubkey_success = &dummyEVP_PKEY; + EVP_PKEY * X509_get_pubkey_failure = NULL; + EVP_PKEY * X509_get_pubkey_return; + + /* X509_free_fn: Has no return value. */ + + /* + * Set the return value for the mock ( if any ) that matches the input. Set + * the rest of the mock functions to return the success value when called. + */ + PEM_read_bio_X509_return = ( funcToFail == PEM_read_bio_X509_fn ) ? PEM_read_bio_X509_failure : PEM_read_bio_X509_success; + PEM_read_bio_X509_IgnoreAndReturn( PEM_read_bio_X509_return ); + + X509_get_pubkey_return = ( funcToFail == X509_get_pubkey_fn ) ? X509_get_pubkey_failure : X509_get_pubkey_success; + X509_get_pubkey_IgnoreAndReturn( X509_get_pubkey_return ); + + X509_free_Ignore(); } -void tearDown( void ) +static void OTA_PAL_FailSingleMock_openssl_EVP( MockFunctionNames_t funcToFail ) { - OtaPalMainStatus_t result; + static EVP_MD_CTX dummyEVP_MD_CTX; + static EVP_MD dummyEVP_MD; + /* EVP_MD_CTX_new_fn: Has no documented failure returns. Allocates and returns a valid digest context. */ + EVP_MD_CTX * EVP_MD_CTX_new_success = &dummyEVP_MD_CTX; + EVP_MD_CTX * EVP_MD_CTX_new_failure = NULL; + EVP_MD_CTX * EVP_MD_CTX_new_return; + /* EVP_DigestVerifyInit_fn: Return 1 for success and 0 for failure. */ + int EVP_DigestVerifyInit_success = 1; + int EVP_DigestVerifyInit_failure = 0; + int EVP_DigestVerifyInit_return; + /* EVP_DigestVerifyUpdate_fn: Return 1 for success and 0 for failure. */ + int EVP_DigestVerifyUpdate_success = 1; + int EVP_DigestVerifyUpdate_failure = 0; + int EVP_DigestVerifyUpdate_return; + /* EVP_DigestVerifyFinal_fn: Return 1 for success; any other value indicates a failure. */ + int EVP_DigestVerifyFinal_success = 1; + int EVP_DigestVerifyFinal_failure = -1; + int EVP_DigestVerifyFinal_return; + + /* EVP_MD_CTX_free_fn: No return. */ + /* EVP_PKEY_free_fn: No return. */ + /* EVP_sha256_fn: Always returns a valid pointer. */ + + EVP_MD_CTX_new_return = ( funcToFail == EVP_MD_CTX_new_fn ) ? EVP_MD_CTX_new_failure : EVP_MD_CTX_new_success; + EVP_MD_CTX_new_IgnoreAndReturn( EVP_MD_CTX_new_return ); + + EVP_DigestVerifyInit_return = ( funcToFail == EVP_DigestVerifyInit_fn ) ? EVP_DigestVerifyInit_failure : EVP_DigestVerifyInit_success; + EVP_DigestVerifyInit_IgnoreAndReturn( EVP_DigestVerifyInit_return ); + + EVP_DigestVerifyUpdate_return = ( funcToFail == EVP_DigestVerifyUpdate_fn ) ? EVP_DigestVerifyUpdate_failure : EVP_DigestVerifyUpdate_success; + EVP_DigestUpdate_IgnoreAndReturn( EVP_DigestVerifyUpdate_return ); + + EVP_DigestVerifyFinal_return = ( funcToFail == EVP_DigestVerifyFinal_fn ) ? EVP_DigestVerifyFinal_failure : EVP_DigestVerifyFinal_success; + EVP_DigestVerifyFinal_IgnoreAndReturn( EVP_DigestVerifyFinal_return ); + + EVP_MD_CTX_free_Ignore(); + + EVP_PKEY_free_Ignore(); + + EVP_sha256_IgnoreAndReturn( &dummyEVP_MD ); +} - /* We want to abort the OTA file after every test. This closes the OtaFile. */ - result = otaPal_Abort( &otaFile ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); +static void OTA_PAL_FailSingleMock_openssl_crypto( MockFunctionNames_t funcToFail ) +{ + int mockVariable; + + /* OPENSSL_malloc is a macro define for CRYPTO_malloc. */ + void * OPENSSL_malloc_success = &mockVariable; + void * OPENSSL_malloc_failure = NULL; + void * OPENSSL_malloc_return; + + OPENSSL_malloc_return = ( funcToFail == OPENSSL_malloc_fn ) ? OPENSSL_malloc_failure : OPENSSL_malloc_success; + CRYPTO_malloc_StopIgnore(); + CRYPTO_malloc_IgnoreAndReturn( OPENSSL_malloc_return ); + /* CRYPTO_free_fn: Has no return value. */ + CRYPTO_free_Ignore(); +} - unlink( "PlatformImageState.txt" ); +/** + * @brief Helper function specify a single point of failure. This needs to be + * updated each time a mocked function is added or removed to the OTA PAL unit + * tests. + * + * Remark: This function assumes specific values for the success and failure + * of the functions. */ +static void OTA_PAL_FailSingleMock_stdio( MockFunctionNames_t funcToFail, + OtaImageState_t * pFreadStateToSet ) +{ + static FILE dummyFile; + + /* On success, snprintf returns a positive number that is less than the amount of data requested. */ + const int snprintf_success = 0; + const int snprintf_failure = -1; + int snprintf_return; + /* On success, fopen returns a FILE address that is not null. */ + FILE * const fopen_success = &dummyFile; + FILE * const fopen_failure = NULL; + FILE * fopen_return; + /* otaPal_SetPlatformImageState calls write to write a single byte. On success, fwrite will return 1. */ + /* fwrite returns a 0 when reaching the EOF or error. */ + const size_t fwrite_success = 1U; + const size_t fwrite_failure = 0; + size_t fwrite_return; + /* On success, fclose returns a zero. */ + /* On failure, fclose returns EOF. */ + const int fclose_success = 0; + const int fclose_failure = EOF; + int fclose_return; + + /* In otaPal_GetPlatformImageState, fread is always called with a 1 for the + * size parameter. So, any number other than 1 is an error. */ + const size_t fread_failure = 0; + const size_t fread_success = 1; + size_t fread_return; + + /* feof returns a non-zero value when End-of-File indicator associated with + * the stream is set, else zero is returned. */ + const int feof_success = 1; + const int feof_failure = 0; + int feof_return; + /* fseek returns a zero on success and a non-zero number on failure. */ + const int32_t fseek_success = 0; + const int32_t fseek_failure = -1; + int32_t fseek_return; + + + /* Set the return value for each of the callable functions. */ + fopen_return = ( funcToFail == fopen_fn ) ? fopen_failure : fopen_success; + fopen_IgnoreAndReturn( fopen_return ); + + snprintf_return = ( funcToFail == snprintf_fn ) ? snprintf_failure : snprintf_success; + snprintf_IgnoreAndReturn( snprintf_return ); + + fread_return = ( funcToFail == fread_fn ) ? fread_failure : fread_success; + fread_IgnoreAndReturn( fread_return ); + fread_ReturnThruPtr_ptr( pFreadStateToSet ); + + feof_return = ( funcToFail == feof_fn ) ? feof_failure : feof_success; + feof_IgnoreAndReturn( feof_return ); + + fseek_return = ( funcToFail == fseek_alias_fn ) ? fseek_failure : fseek_success; + fseek_alias_IgnoreAndReturn( fseek_return ); + + fwrite_return = ( funcToFail == fwrite_alias_fn ) ? fwrite_failure : fwrite_success; + fwrite_alias_IgnoreAndReturn( fwrite_return ); + + fclose_return = ( funcToFail == fclose_fn ) ? fclose_failure : fclose_success; + fclose_IgnoreAndReturn( fclose_return ); +} + +static void OTA_PAL_FailSingleMock( MockFunctionNames_t funcToFail, + OtaImageState_t * pFreadStateToSet ) +{ + OTA_PAL_FailSingleMock_stdio( funcToFail, pFreadStateToSet ); + OTA_PAL_FailSingleMock_openssl_BIO( funcToFail ); + OTA_PAL_FailSingleMock_openssl_X509( funcToFail ); + OTA_PAL_FailSingleMock_openssl_crypto( funcToFail ); + OTA_PAL_FailSingleMock_openssl_EVP( funcToFail ); } -/* ========================================================================== */ +/* ====================== OTA PAL ABORT UNIT TESTS ====================== */ /** * @brief Test that otaPal_Abort will return correct result code. @@ -146,9 +366,10 @@ void test_OTAPAL_Abort_NullFileContext( void ) void test_OTAPAL_Abort_NullFileHandle( void ) { OtaPalMainStatus_t result; + OtaFileContext_t testFileContext; - otaFile.pFile = NULL; - result = OTA_PAL_MAIN_ERR( otaPal_Abort( &otaFile ) ); + testFileContext.pFile = NULL; + result = OTA_PAL_MAIN_ERR( otaPal_Abort( &testFileContext ) ); TEST_ASSERT_EQUAL( OtaPalSuccess, result ); } @@ -159,27 +380,38 @@ void test_OTAPAL_Abort_NullFileHandle( void ) void test_OTAPAL_Abort_ValidFileHandle( void ) { OtaPalMainStatus_t result; + FILE placeholder_file; + OtaFileContext_t testFileContext; - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); + testFileContext.pFilePath = ( uint8_t * ) "placeholder_path"; + testFileContext.pFile = &placeholder_file; + + fclose_ExpectAnyArgsAndReturn( 0 ); - result = OTA_PAL_MAIN_ERR( otaPal_Abort( &otaFile ) ); + result = OTA_PAL_MAIN_ERR( otaPal_Abort( &testFileContext ) ); TEST_ASSERT_EQUAL( OtaPalSuccess, result ); } /** * @brief Test that otaPal_Abort will return correct result code. */ -void test_OTAPAL_Abort_NonExistentFile( void ) +void test_OTAPAL_Abort_FileCloseFail( void ) { OtaPalMainStatus_t result; + OtaFileContext_t testFileContext; + FILE dummyFile; - otaFile.pFilePath = ( uint8_t * ) ( "nonexistingfile.bin" ); - result = OTA_PAL_MAIN_ERR( otaPal_Abort( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); + testFileContext.pFilePath = ( uint8_t * ) "placeholder"; + testFileContext.pFile = &dummyFile; + + fclose_ExpectAnyArgsAndReturn( EOF ); + + result = otaPal_Abort( &testFileContext ); + TEST_ASSERT_EQUAL( OtaPalFileAbort, OTA_PAL_MAIN_ERR( result ) ); } +/* =================== OTA PAL CREATE FILE UNIT TESTS =================== */ + /** * @brief Test that otaPal_CreateFileForRx will return correct result code. */ @@ -198,9 +430,10 @@ void test_OTAPAL_CreateFileForRx_NullFileContext( void ) void test_OTAPAL_CreateFileForRx_NullFilePath( void ) { OtaPalMainStatus_t result; + OtaFileContext_t testFile; - otaFile.pFilePath = NULL; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); + testFile.pFilePath = NULL; + result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &testFile ) ); TEST_ASSERT_EQUAL( OtaPalRxFileCreateFailed, result ); } @@ -211,17 +444,17 @@ void test_OTAPAL_CreateFileForRx_NullFilePath( void ) void test_OTAPAL_CreateFileForRx_FailedToCreateFile( void ) { OtaPalMainStatus_t result; + FILE placeholder_file; + OtaFileContext_t testFile; + + testFile.pFilePath = ( uint8_t * ) "placeholder_path"; + testFile.pFile = &placeholder_file; - chmod( OTA_PAL_UTEST_FIRMWARE_FILE, S_IRUSR ); - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; + fopen_ExpectAnyArgsAndReturn( NULL ); /* Create a file that exists with w+b mode */ - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); + result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &testFile ) ); TEST_ASSERT_EQUAL( OtaPalRxFileCreateFailed, result ); - - chmod( OTA_PAL_UTEST_FIRMWARE_FILE, S_IRWXU ); - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); } /** @@ -230,259 +463,416 @@ void test_OTAPAL_CreateFileForRx_FailedToCreateFile( void ) void test_OTAPAL_CreateFileForRx_ValidFileHandle( void ) { OtaPalMainStatus_t result; + FILE placeholder_file; + OtaFileContext_t otaFileContext; + + otaFileContext.pFilePath = ( uint8_t * ) "placeholder_path"; - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); + fopen_ExpectAnyArgsAndReturn( &placeholder_file ); + result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFileContext ) ); TEST_ASSERT_EQUAL( OtaPalSuccess, result ); } - /** - * @brief Test that otaPal_WriteBlock will return correct result code. + * @brief Test that otaPal_CreateFileForRx will handle the two types of + * potential paths. */ -void test_OTAPAL_WriteBlock_NullFileContext( void ) +void test_OTAPAL_CreateFileForRx_PathTypes( void ) { - int16_t bytes_written = 0; - uint8_t data = 0xAA; + OtaPalMainStatus_t result; + FILE placeholder_file; + OtaFileContext_t otaFileContext; + + /* Test for a leading forward slash in the path. */ + otaFileContext.pFilePath = ( uint8_t * ) "/placeholder_path"; + fopen_ExpectAnyArgsAndReturn( &placeholder_file ); + result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFileContext ) ); + TEST_ASSERT_EQUAL( OtaPalSuccess, result ); - bytes_written = otaPal_WriteBlock( NULL, 0, &data, 1 ); - TEST_ASSERT_EQUAL( OtaPalSuccess, bytes_written + 1 ); + /* Test for no leading forward slash in the path. */ + otaFileContext.pFilePath = ( uint8_t * ) "placeholder_path"; + fopen_ExpectAnyArgsAndReturn( &placeholder_file ); + result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFileContext ) ); + TEST_ASSERT_EQUAL( OtaPalSuccess, result ); } +/* =================== OTA PAL CLOSE FILE UNIT TESTS ==================== */ -/** - * @brief Test that otaPal_WriteBlock will return correct result code. - */ -void test_OTAPAL_WriteBlock_WriteSingleByte( void ) +void test_OTAPAL_CloseFile_NullInput( void ) { - OtaPalMainStatus_t result; - int16_t numBytesWritten; - uint8_t data = 0xAA; + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + OTA_PAL_FailSingleMock_Except_fread( fread_fn, &expectedImageState ); + + /* NULL file context. */ + result = otaPal_CloseFile( NULL ); + TEST_ASSERT_EQUAL( OtaPalFileClose, OTA_PAL_MAIN_ERR( result ) ); + + /* NULL signature input. */ + otaFileContext.pSignature = NULL; + otaFileContext.pFile = &dummyFile; + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSignatureCheckFailed, OTA_PAL_MAIN_ERR( result ) ); + + /* NULL file input */ + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = NULL; + /* NULL signature input. */ + OTA_PAL_FailSingleMock_Except_fread( fread_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSignatureCheckFailed, OTA_PAL_MAIN_ERR( result ) ); +} - /* TEST: Write a byte of data. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); +void test_OTAPAL_CloseFile_HappyPath( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + /* When fread is being called in this case, it is looping until there is + * no more data. Setting fread to fail prevents us from getting stuck in + * the loops. */ + OTA_PAL_FailSingleMock( fread_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSuccess, OTA_PAL_MAIN_ERR( result ) ); +} - if( TEST_PROTECT() ) - { - numBytesWritten = otaPal_WriteBlock( &otaFile, 0, &data, 1 ); - TEST_ASSERT_EQUAL_INT( 1, numBytesWritten ); - } +void test_OTAPAL_CloseFile_OpenSSL_failures( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + OTA_PAL_FailSingleMock_Except_fread( BIO_puts_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSuccess, OTA_PAL_MAIN_ERR( result ) ); + + /* Test OpenSSL/X509.h functions failing. */ + otaFileContext.pFile = &dummyFile; + OTA_PAL_FailSingleMock_Except_fread( PEM_read_bio_X509_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalBadSignerCert, OTA_PAL_MAIN_ERR( result ) ); + + otaFileContext.pFile = &dummyFile; + OTA_PAL_FailSingleMock_Except_fread( X509_get_pubkey_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSuccess, OTA_PAL_MAIN_ERR( result ) ); + + /* Test fclose failing. */ + otaFileContext.pFile = &dummyFile; + OTA_PAL_FailSingleMock_Except_fread( fclose_fn, &expectedImageState ); + /* Just want the first fclose to fail. */ + fclose_StopIgnore(); + fclose_ExpectAnyArgsAndReturn( EOF ); + fclose_IgnoreAndReturn( 0 ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalFileClose, OTA_PAL_MAIN_ERR( result ) ); + + /* Test OPENSSL_malloc failing. */ + otaFileContext.pFile = &dummyFile; + OTA_PAL_FailSingleMock_Except_fread( OPENSSL_malloc_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalOutOfMemory, OTA_PAL_MAIN_ERR( result ) ); + + /* Test EVP_MD_CTX_new failing. */ + otaFileContext.pFile = &dummyFile; + OTA_PAL_FailSingleMock_Except_fread( EVP_MD_CTX_new_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSignatureCheckFailed, OTA_PAL_MAIN_ERR( result ) ); } -/** - * @brief Test that otaPal_WriteBlock will return correct result code. - */ -void test_OTAPAL_WriteBlock_WriteManyBlocks( void ) +void test_OTAPAL_CloseFile_BIO_puts( void ) { - OtaPalMainStatus_t result; - int16_t numBytesWritten; + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + /* Test fseek failing. */ + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + /* BIO_ctrl has to fail first to call BIO_puts. */ + BIO_ctrl_IgnoreAndReturn( 0 ); + OTA_PAL_FailSingleMock_Except_fread( BIO_puts_fn, &expectedImageState ); + + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalBadSignerCert, OTA_PAL_MAIN_ERR( result ) ); +} - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ) * testotapalNUM_WRITE_BLOCKS; - /* TEST: Write many bytes of data. */ +void test_OTAPAL_CloseFile_feof_fail( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + /* Test feof failing both times it is called.*/ + OTA_PAL_FailSingleMock_Except_fread( feof_fn, &expectedImageState ); + feof_IgnoreAndReturn( 0 ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSignatureCheckFailed, OTA_PAL_MAIN_ERR( result ) ); +} - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); +void test_OTAPAL_CloseFile_EVP_DigestVerifyFinal_fail( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + /* Test fseek failing. */ + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + OTA_PAL_FailSingleMock_Except_fread( EVP_DigestVerifyFinal_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSignatureCheckFailed, OTA_PAL_MAIN_ERR( result ) ); +} - if( TEST_PROTECT() ) - { - int index = 0; +void test_OTAPAL_CloseFile_EVP_DigestVerifyUpdate_fail( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + /* Test fseek failing. */ + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + OTA_PAL_FailSingleMock_Except_fread( EVP_DigestVerifyUpdate_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSuccess, OTA_PAL_MAIN_ERR( result ) ); +} - for( index = 0; index < testotapalNUM_WRITE_BLOCKS; index++ ) - { - numBytesWritten = otaPal_WriteBlock( &otaFile, index * sizeof( dummyData ), dummyData, sizeof( dummyData ) ); - TEST_ASSERT_EQUAL_INT( sizeof( dummyData ), numBytesWritten ); - } +void test_OTAPAL_CloseFile_fseek_fail( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + /* Test fseek failing. */ + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + OTA_PAL_FailSingleMock_Except_fread( fseek_alias_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSignatureCheckFailed, OTA_PAL_MAIN_ERR( result ) ); +} +#define OTA_PAL_POSIX_BUF_SIZE ( ( size_t ) 4096U ) +void test_OTAPAL_CloseFile_fread_fail( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + /* Test fread pass then fail. */ + OTA_PAL_FailSingleMock( none_fn, &expectedImageState ); + fread_StopIgnore(); + fread_ExpectAnyArgsAndReturn( 1 ); + fread_ExpectAnyArgsAndReturn( 0 ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSuccess, OTA_PAL_MAIN_ERR( result ) ); +} - /* Sufficient delay for flash write to complete. */ - /* vTaskDelay( pdMS_TO_TICKS( testotapalWRITE_BLOCKS_DELAY_MS ) ); */ - } +void test_OTAPAL_CloseFile_BIO_new( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + BIO dummyBIO; + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + /* Test OpenSSL/bio.h functions failing. */ + OTA_PAL_FailSingleMock_Except_fread( none_fn, &expectedImageState ); + BIO_new_StopIgnore(); + BIO_ctrl_StopIgnore(); + BIO_new_ExpectAnyArgsAndReturn( &dummyBIO ); + BIO_ctrl_ExpectAnyArgsAndReturn( 0 ); + BIO_new_ExpectAnyArgsAndReturn( NULL ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalBadSignerCert, OTA_PAL_MAIN_ERR( result ) ); + + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + OTA_PAL_FailSingleMock_Except_fread( BIO_new_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalBadSignerCert, OTA_PAL_MAIN_ERR( result ) ); +} + +void test_OTAPAL_CloseFile_BIO_read_filename_fail( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + OTA_PAL_FailSingleMock_Except_fread( BIO_read_filename_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSuccess, OTA_PAL_MAIN_ERR( result ) ); +} + +void test_OTAPAL_CloseFile_EVP_DigestVerifyInit_fail( void ) +{ + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + Sig256_t dummySig; + OtaImageState_t expectedImageState = OtaImageStateTesting; + FILE dummyFile; + + otaFileContext.pSignature = &dummySig; + otaFileContext.pFile = &dummyFile; + + OTA_PAL_FailSingleMock_Except_fread( EVP_DigestVerifyInit_fn, &expectedImageState ); + result = otaPal_CloseFile( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalSignatureCheckFailed, OTA_PAL_MAIN_ERR( result ) ); } +/* =================== OTA PAL WRITE BLOCK UNIT TESTS =================== */ + /** * @brief Test that otaPal_WriteBlock will return correct result code. */ -void test_OTAPAL_WriteBlock_FseekError( void ) +void test_OTAPAL_WriteBlock_NullFileContext( void ) { + int16_t result = 0; + uint8_t data = 0xAA; + uint32_t blockSize = 1; + + result = otaPal_WriteBlock( NULL, 0, &data, blockSize ); + TEST_ASSERT_EQUAL( -1, result ); } /** * @brief Test that otaPal_WriteBlock will return correct result code. */ -void test_OTAPAL_WriteBlock_FwriteError( void ) +void test_OTAPAL_WriteBlock_WriteSingleByte( void ) { + int16_t numBytesWritten; + uint8_t data = 0xAA; + uint32_t blockSize = 1; + OtaFileContext_t otaFileContext; + + /* TEST: Write a byte of data. */ + otaFileContext.pFilePath = ( uint8_t * ) "placeholder"; + fseek_alias_ExpectAnyArgsAndReturn( 0 ); + fwrite_alias_ExpectAnyArgsAndReturn( blockSize ); + numBytesWritten = otaPal_WriteBlock( &otaFileContext, 0, &data, blockSize ); + TEST_ASSERT_EQUAL_INT( blockSize, numBytesWritten ); } -void test_OTAPAL_CloseFile_ValidSignature( void ) +/** + * @brief Test that otaPal_WriteBlock will return correct result code. + */ +void test_OTAPAL_WriteBlock_WriteMultipleBytes( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; - Sig256_t sig = { 0 }; - - /* We use a dummy file name here because closing the system designated bootable - * image with content that is not runnable may cause issues. */ - otaFile.pFilePath = ( uint8_t * ) ( "test_happy_path_image.bin" ); - otaFile.fileSize = sizeof( dummyData ); - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); + int16_t numBytesWritten; + size_t index = 0; + uint8_t pData[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE }; + uint32_t blockSize = sizeof( pData[ 0 ] ); + OtaFileContext_t otaFileContext; - /* We still want to close the file if the test fails somewhere here. */ - if( TEST_PROTECT() ) + /* TEST: Write multiple bytes of data. */ + for( index = 0; index < ( sizeof( pData ) / sizeof( pData[ 0 ] ) ); index++ ) { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - otaFile.pSignature = &sig; - otaFile.pSignature->size = ucValidSignatureLength; - memcpy( otaFile.pSignature->data, ucValidSignature, ucValidSignatureLength ); - otaFile.pCertFilepath = ( uint8_t * ) OTA_PAL_UTEST_CERT_FILE; - - result = OTA_PAL_MAIN_ERR( otaPal_CloseFile( &otaFile ) ); - TEST_ASSERT_EQUAL_INT( OtaPalSuccess, result ); + fseek_alias_ExpectAnyArgsAndReturn( 0 ); + fwrite_alias_ExpectAnyArgsAndReturn( blockSize ); + numBytesWritten = otaPal_WriteBlock( &otaFileContext, index * blockSize, pData, blockSize ); + TEST_ASSERT_EQUAL_INT( blockSize, numBytesWritten ); } } - /** - * @brief Call otaPal_CloseFile with an invalid signature in the file context. - * The close is called after we have a written a block of dummy data to the file. - * Verify the correct OTA Agent level error code is returned from otaPal_CloseFile. + * @brief Test that otaPal_WriteBlock will return correct result code. */ -void test_OTAPAL_CloseFile_InvalidSignatureBlockWritten( void ) +void test_OTAPAL_WriteBlock_FseekError( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; - Sig256_t sig = { 0 }; - - /* Create a local file using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); - - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); + int16_t numBytesWritten; + uint8_t data = 0xAA; + uint32_t blockSize = 1; + const int16_t fseek_error_num = 1; /* fseek returns a non-zero number on error. */ + OtaFileContext_t validFileContext; - /* We still want to close the file if the test fails somewhere here. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - /* Fill out an incorrect signature. */ - otaFile.pSignature = &sig; - otaFile.pSignature->size = ucInvalidSignatureLength; - memcpy( otaFile.pSignature->data, ucInvalidSignature, ucInvalidSignatureLength ); - otaFile.pCertFilepath = ( uint8_t * ) OTA_PAL_UTEST_CERT_FILE; - - /* Try to close the file. */ - result = OTA_PAL_MAIN_ERR( otaPal_CloseFile( &otaFile ) ); - - if( ( OtaPalBadSignerCert != result ) && - ( OtaPalSignatureCheckFailed != result ) && - ( OtaPalFileClose != result ) ) - { - TEST_ASSERT_TRUE( 0 ); - } - } + /* TEST: Write a byte of data. */ + fseek_alias_ExpectAnyArgsAndReturn( fseek_error_num ); + numBytesWritten = otaPal_WriteBlock( &validFileContext, 0, &data, blockSize ); + TEST_ASSERT_EQUAL_INT( -1, numBytesWritten ); } /** - * @brief Call otaPal_CloseFile with an invalid signature in the file context. - * The close is called when no blocks have been written to the file. - * Verify the correct OTA Agent level error code is returned from otaPal_CloseFile. + * @brief Test that otaPal_WriteBlock will return correct result code. */ -void test_OTAPAL_CloseFile_InvalidSignatureNoBlockWritten( void ) +void test_OTAPAL_WriteBlock_FwriteError( void ) { - OtaPalMainStatus_t result; - Sig256_t sig = { 0 }; - - /* Create a local file using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); - - /* Fill out an incorrect signature. */ - otaFile.pSignature = &sig; - otaFile.pSignature->size = ucInvalidSignatureLength; - memcpy( otaFile.pSignature->data, ucInvalidSignature, ucInvalidSignatureLength ); - otaFile.pCertFilepath = ( uint8_t * ) OTA_PAL_UTEST_CERT_FILE; - - /* We still want to close the file if the test fails somewhere here. */ - if( TEST_PROTECT() ) - { - /* Try to close the file. */ - result = OTA_PAL_MAIN_ERR( otaPal_CloseFile( &otaFile ) ); - - if( ( OtaPalBadSignerCert != result ) && - ( OtaPalSignatureCheckFailed != result ) && - ( OtaPalFileClose != result ) ) - { - TEST_ASSERT_TRUE( 0 ); - } - } + int16_t numBytesWritten; + uint8_t data = 0xAA; + uint32_t blockSize = 1; + OtaFileContext_t validFileContext; + const int32_t fseekSuccessReturn = 0; /* fseek returns a zero on success. */ + const size_t fwriteErrorReturn = 0; /* fwrite returns a number less than the requested number of bytes to write on error. */ + const int16_t writeblockErrorReturn = -1; + + fseek_alias_ExpectAnyArgsAndReturn( fseekSuccessReturn ); + fwrite_alias_ExpectAnyArgsAndReturn( fwriteErrorReturn ); + + /* fwrite returns a number less than the amount requested to write on error. */ + numBytesWritten = otaPal_WriteBlock( &validFileContext, 0, &data, blockSize ); + TEST_ASSERT_EQUAL_INT( writeblockErrorReturn, numBytesWritten ); } +/* =============== OTA PAL ACTIVATE NEW IMAGE UNIT TESTS ================ */ + /** - * @brief Call otaPal_CloseFile with a signature verification certificate path does - * not exist in the system. Verify the correct OTA Agent level error code is returned - * from otaPal_CloseFile. - * - * @note This test is only valid if your device uses a file system in your non-volatile memory. - * Some devices may revert to using aws_codesigner_certificate.h if a file is not found, but - * that option is not being enforced. + * @brief Test that otaPal_WriteBlock will return correct result code. */ -void test_OTAPAL_CloseFile_NonexistingCodeSignerCertificate( void ) +void test_OTAPAL_ActivateNewImage_NullFileContext( void ) { OtaPalMainStatus_t result; - int16_t bytes_written = 0; - Sig256_t sig = { 0 }; - - memset( &otaFile, 0, sizeof( otaFile ) ); - - /* Create a local file using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); + result = OTA_PAL_MAIN_ERR( otaPal_ActivateNewImage( NULL ) ); TEST_ASSERT_EQUAL( OtaPalSuccess, result ); - - /* We still want to close the file if the test fails somewhere here. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - /* Check the signature (not expected to be valid in this case). */ - otaFile.pSignature = &sig; - otaFile.pSignature->size = ucValidSignatureLength; - memcpy( otaFile.pSignature->data, ucValidSignature, ucValidSignatureLength ); - otaFile.pCertFilepath = ( uint8_t * ) ( "nonexistingfile.crt" ); - - result = OTA_PAL_MAIN_ERR( otaPal_CloseFile( &otaFile ) ); - - if( ( OtaPalBadSignerCert != result ) && - ( OtaPalSignatureCheckFailed != result ) && - ( OtaPalFileClose != result ) ) - { - TEST_ASSERT_TRUE( 0 ); - } - } } +/* ================== OTA PAL RESET DEVICE UNIT TESTS =================== */ + /** * @brief Test that otaPal_ResetDevice will return correct result code. */ @@ -495,263 +885,209 @@ void test_OTAPAL_ResetDevice_NullFileContext( void ) TEST_ASSERT_EQUAL( OtaPalSuccess, result ); } +/* ============ OTA PAL SET PLATFORM IMAGE STATE UNIT TESTS ============= */ + /** - * @brief Test that otaPal_WriteBlock will return correct result code. + * @brief Verify that otaPal_SetPlatformImageState correctly handles + * attempts to set invalid image states. */ -void test_OTAPAL_ActivateNewImage_NullFileContext( void ) +void test_OTAPAL_SetPlatformImageState_InvalidStates( void ) { - OtaPalMainStatus_t result; + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + OtaImageState_t stateToSet; - result = OTA_PAL_MAIN_ERR( otaPal_ActivateNewImage( NULL ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); + stateToSet = OtaImageStateUnknown; + result = otaPal_SetPlatformImageState( &otaFileContext, stateToSet ); + TEST_ASSERT_EQUAL( OtaPalBadImageState, OTA_PAL_MAIN_ERR( result ) ); + + stateToSet = OtaLastImageState + 1; + result = otaPal_SetPlatformImageState( &otaFileContext, stateToSet ); + TEST_ASSERT_EQUAL( OtaPalBadImageState, OTA_PAL_MAIN_ERR( result ) ); } /** - * @brief Set the platform state to self-test and verify success. + * @brief Test otaPal_SetPlatformImageState correctly handles setting valid + * image states. */ -void test_OTAPAL_SetPlatformImageState_SelfTestImageState( void ) +void test_OTAPAL_SetPlatformImageState_HappyPath( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + OtaImageState_t validState = OtaImageStateTesting; - OtaImageState_t eImageState = OtaImageStateUnknown; - OtaPalImageState_t palImageState = OtaPalImageStateUnknown; - - /* Create a local file again using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); - - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); - - /* We still want to close the file if the test fails. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - /* Set the image state. */ - eImageState = OtaImageStateTesting; - result = OTA_PAL_MAIN_ERR( otaPal_SetPlatformImageState( &otaFile, eImageState ) ); - TEST_ASSERT_EQUAL_INT( OtaPalSuccess, result ); - - /* Verify that image state was saved correctly. */ - - /* [**]All platforms need a reboot of a successfully close image in order to return - * eOTA_PAL_ImageState_PendingCommit from otaPal_GetPlatformImageState(). So this cannot be tested. - */ - /* For Linux platform, this can be read directly from the image state file */ - palImageState = otaPal_GetPlatformImageState( &otaFile ); - TEST_ASSERT_EQUAL_INT( OtaPalImageStatePendingCommit, palImageState ); - } + OTA_PAL_FailSingleMock_stdio( none_fn, NULL ); + result = otaPal_SetPlatformImageState( &otaFileContext, validState ); + TEST_ASSERT_EQUAL( OtaPalSuccess, OTA_PAL_MAIN_ERR( result ) ); } /** - * @brief Set an invalid platform image state exceeding the range and verify success. + * @brief Test otaPal_SetPlatformImageState correctly handles fopen failing. */ -void test_OTAPAL_SetPlatformImageState_InvalidImageState( void ) +void test_OTAPAL_SetPlatformImageState_fopen_fail( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; - OtaImageState_t eImageState = OtaImageStateUnknown; - OtaPalImageState_t palImageState = OtaPalImageStateUnknown; - - /* Create a local file again using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + OtaImageState_t validState = OtaImageStateTesting; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); - - /* We still want to close the file if the test fails. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - /* Try to set an invalid image state. */ - eImageState = ( OtaImageState_t ) ( OtaLastImageState + 1 ); - result = OTA_PAL_MAIN_ERR( otaPal_SetPlatformImageState( &otaFile, eImageState ) ); - TEST_ASSERT_EQUAL( OtaPalBadImageState, result ); - - /* Read the platform image state to verify */ - /* Nothing wrote to the image state file. Ota Pal Image state remain valid */ - palImageState = otaPal_GetPlatformImageState( &otaFile ); - TEST_ASSERT_EQUAL_INT( OtaPalImageStateValid, palImageState ); - } + OTA_PAL_FailSingleMock_stdio( fopen_fn, NULL ); + result = otaPal_SetPlatformImageState( &otaFileContext, validState ); + TEST_ASSERT_EQUAL( OtaPalBadImageState, OTA_PAL_MAIN_ERR( result ) ); } /** - * @brief Set the image state to unknown and verify a failure. + * @brief Test otaPal_SetPlatformImageState correctly handles fwrite failing. */ -void test_OTAPAL_SetPlatformImageState_UnknownImageState( void ) +void test_OTAPAL_SetPlatformImageState_fwrite_fail( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; - OtaImageState_t eImageState = OtaImageStateUnknown; - OtaPalImageState_t palImageState = OtaPalImageStateUnknown; - - /* Create a local file again using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); - - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + OtaImageState_t validState = OtaImageStateTesting; - /* We still want to close the file if the test fails. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - /* Try to set an invalid image state. */ - eImageState = OtaImageStateUnknown; - result = OTA_PAL_MAIN_ERR( otaPal_SetPlatformImageState( &otaFile, eImageState ) ); - TEST_ASSERT_EQUAL( OtaPalBadImageState, result ); - - /* Read the platform image state to verify */ - /* Nothing wrote to the image state file. Ota Pal Image state remain valid */ - palImageState = otaPal_GetPlatformImageState( &otaFile ); - TEST_ASSERT_EQUAL_INT( OtaPalImageStateValid, palImageState ); - } + OTA_PAL_FailSingleMock_stdio( fwrite_alias_fn, NULL ); + result = otaPal_SetPlatformImageState( &otaFileContext, validState ); + TEST_ASSERT_EQUAL( OtaPalBadImageState, OTA_PAL_MAIN_ERR( result ) ); } - /** - * @brief Set platform image state to rejected and verify success. - * We cannot test a reject failed without mocking the underlying non volatile memory. + * @brief Test otaPal_SetPlatformImageState correctly handles fclose failing. */ -void test_OTAPAL_SetPlatformImageState_RejectImageState( void ) +void test_OTAPAL_SetPlatformImageState_fclose_fail( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; - OtaImageState_t eImageState = OtaImageStateUnknown; - OtaPalImageState_t palImageState = OtaPalImageStateUnknown; - - /* Create a local file again using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); + OtaPalStatus_t result; + OtaFileContext_t otaFileContext; + OtaImageState_t validState = OtaImageStateTesting; - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); - - /* We still want to close the file if the test fails. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - eImageState = OtaImageStateRejected; - result = OTA_PAL_MAIN_ERR( otaPal_SetPlatformImageState( &otaFile, eImageState ) ); - TEST_ASSERT_EQUAL_INT( OtaPalSuccess, result ); - - /* Read the platform image state to verify */ - palImageState = otaPal_GetPlatformImageState( &otaFile ); - TEST_ASSERT_EQUAL_INT( OtaPalImageStateInvalid, palImageState ); - } + OTA_PAL_FailSingleMock_stdio( fclose_fn, NULL ); + result = otaPal_SetPlatformImageState( &otaFileContext, validState ); + TEST_ASSERT_EQUAL( OtaPalBadImageState, OTA_PAL_MAIN_ERR( result ) ); } +/* ============ OTA PAL GET PLATFORM IMAGE STATE UNIT TESTS ============= */ + /** - * @brief Set the platform image state to aborted. - * We cannot test a abort failed without mocking the underlying non-volatile memory. - */ -void test_OTAPAL_SetPlatformImageState_AbortImageState( void ) + * @brief Verify that otaPal_GetPlatformImageState correctly handles a fopen + * failure. This test assumes that all other function calls return + * success. + * */ +void test_OTAPAL_GetPlatformImageState_fopen_fails( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; - OtaImageState_t eImageState = OtaImageStateUnknown; - OtaPalImageState_t palImageState = OtaPalImageStateUnknown; + OtaPalImageState_t ePalImageState; + OtaFileContext_t otaFileContext; - /* Create a local file again using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); + OTA_PAL_FailSingleMock_stdio( fopen_fn, NULL ); + /* The file failed to close, so it is invalid or in an unknown state. */ + ePalImageState = otaPal_GetPlatformImageState( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalImageStateValid, ePalImageState ); +} - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); +/** + * @brief Verify that otaPal_GetPlatformImageState correctly handles a fread + * failure. This test assumes that all other function calls return + * success. + * */ +void test_OTAPAL_GetPlatformImageState_fread_fails( void ) +{ + OtaPalImageState_t ePalImageState; + OtaFileContext_t otaFileContext; - /* We still want to close the file if the test fails. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - eImageState = OtaImageStateAborted; - result = OTA_PAL_MAIN_ERR( otaPal_SetPlatformImageState( &otaFile, eImageState ) ); - TEST_ASSERT_EQUAL_INT( OtaPalSuccess, result ); - - /* Read the platform image state to verify */ - palImageState = otaPal_GetPlatformImageState( &otaFile ); - TEST_ASSERT_EQUAL_INT( OtaPalImageStateInvalid, palImageState ); - } + OTA_PAL_FailSingleMock_stdio( fread_fn, NULL ); + ePalImageState = otaPal_GetPlatformImageState( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalImageStateInvalid, ePalImageState ); } /** - * @brief Verify that the current image received is in the invalid state after a - * failure to close the file because of a bad signature. - */ -void test_OTAPAL_GetPlatformImageState_InvalidImageStateFromFileCloseFailure( void ) + * @brief This test validates that the valid states are correctly returned to + * the caller. + * */ +void test_OTAPAL_GetPlatformImageState_fclose_fails( void ) { - OtaPalMainStatus_t result; - int16_t bytes_written = 0; - Sig256_t sig = { 0 }; OtaPalImageState_t ePalImageState = OtaPalImageStateUnknown; + OtaFileContext_t otaFileContext; + FILE dummyFile; + + /* On success, snprintf returns a positive number that is less than the amount of data requested. */ + const int snprintf_success_val = 0; + /* On success, fopen returns a FILE address that is not null. */ + FILE * const fopen_success_val = &dummyFile; + + /* In otaPal_GetPlatformImageState, fread is always called with a 1 for the + * size parameter. So, any number other than 1 is an error. */ + const size_t fread_success_val = 1; + /* On failure, fclose returns EOF. */ + const int fclose_fail_val = EOF; + + /* Predefine what functions are expected to be called. */ + snprintf_ExpectAnyArgsAndReturn( snprintf_success_val ); + fopen_ExpectAnyArgsAndReturn( fopen_success_val ); + fread_ExpectAnyArgsAndReturn( fread_success_val ); + fclose_ExpectAnyArgsAndReturn( fclose_fail_val ); + + /* Call otaPal_GetPlatformImageState and check the result. */ + ePalImageState = otaPal_GetPlatformImageState( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalImageStateInvalid, ePalImageState ); +} - /* TEST: Invalid image returned from otaPal_GetPlatformImageState(). Using a failure to close. */ - /* Create a local file again using the PAL. */ - otaFile.pFilePath = ( uint8_t * ) OTA_PAL_UTEST_FIRMWARE_FILE; - otaFile.fileSize = sizeof( dummyData ); - - result = OTA_PAL_MAIN_ERR( otaPal_CreateFileForRx( &otaFile ) ); - TEST_ASSERT_EQUAL( OtaPalSuccess, result ); - - /* We still want to close the file if the test fails. */ - if( TEST_PROTECT() ) - { - /* Write data to the file. */ - bytes_written = otaPal_WriteBlock( &otaFile, - 0, - dummyData, - sizeof( dummyData ) ); - TEST_ASSERT_EQUAL( sizeof( dummyData ), bytes_written ); - - /* Check the signature. */ - otaFile.pSignature = &sig; - otaFile.pSignature->size = ucInvalidSignatureLength; - memcpy( otaFile.pSignature->data, ucInvalidSignature, ucInvalidSignatureLength ); - otaFile.pCertFilepath = ( uint8_t * ) OTA_PAL_UTEST_CERT_FILE; - - result = OTA_PAL_MAIN_ERR( otaPal_CloseFile( &otaFile ) ); - - if( ( OtaPalBadSignerCert != result ) && - ( OtaPalSignatureCheckFailed != result ) && - ( OtaPalFileClose != result ) ) - { - TEST_ASSERT_TRUE( 0 ); - } - - /* The file failed to close, so it is invalid or in an unknown state. */ - ePalImageState = otaPal_GetPlatformImageState( &otaFile ); - TEST_ASSERT( ( OtaPalImageStateInvalid == ePalImageState ) || - ( OtaPalImageStateUnknown == ePalImageState ) ); - } +/** + * @brief This test validates that the valid states are correctly returned to + * the caller. + * */ +void test_OTAPAL_GetPlatformImageState_ValidStates( void ) +{ + OtaPalImageState_t ePalImageState = OtaPalImageStateUnknown; + OtaFileContext_t otaFileContext; + FILE dummyFile; + OtaImageState_t freadResultingState; + + /* OtaLastImageState is always the largest number in the enum. This + * variable represents an invalid state because it is outside of the + * expected values. */ + const OtaImageState_t invalidImageState = OtaLastImageState + 1; + + /* On success, snprintf returns a positive number that is less than the amount of data requested. */ + const int snprintf_success_val = 0; + /* On success, fopen returns a FILE address that is not null. */ + FILE * const fopen_success_val = &dummyFile; + + /* In otaPal_GetPlatformImageState, fread is always called with a 1 for the + * size parameter. So, any number other than 1 is an error. */ + const size_t fread_success_val = 1; + /* On success, fclose returns a zero. */ + const int fclose_success_val = 0; + + /* Test the scenario where the platform state is OtaImageStateTesting. */ + freadResultingState = OtaImageStateTesting; + /* Predefine what functions are expected to be called. */ + snprintf_ExpectAnyArgsAndReturn( snprintf_success_val ); + fopen_ExpectAnyArgsAndReturn( fopen_success_val ); + fread_ExpectAnyArgsAndReturn( fread_success_val ); + fread_ReturnThruPtr_ptr( &freadResultingState ); + fclose_ExpectAnyArgsAndReturn( fclose_success_val ); + /* Call otaPal_GetPlatformImageState and check the result. */ + ePalImageState = otaPal_GetPlatformImageState( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalImageStatePendingCommit, ePalImageState ); + + /* Test the scenario where the platform state is OtaImageStateAccepted. */ + freadResultingState = OtaImageStateAccepted; + /* Predefine what functions are expected to be called. */ + snprintf_ExpectAnyArgsAndReturn( snprintf_success_val ); + fopen_ExpectAnyArgsAndReturn( fopen_success_val ); + fread_ExpectAnyArgsAndReturn( fread_success_val ); + fread_ReturnThruPtr_ptr( &freadResultingState ); + fclose_ExpectAnyArgsAndReturn( fclose_success_val ); + /* Call otaPal_GetPlatformImageState and check the result. */ + ePalImageState = otaPal_GetPlatformImageState( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalImageStateValid, ePalImageState ); + + /* Test the scenario where the platform state is an unexpected value. */ + freadResultingState = invalidImageState; + /* Predefine what functions are expected to be called. */ + snprintf_ExpectAnyArgsAndReturn( snprintf_success_val ); + fopen_ExpectAnyArgsAndReturn( fopen_success_val ); + fread_ExpectAnyArgsAndReturn( fread_success_val ); + fread_ReturnThruPtr_ptr( &freadResultingState ); + fclose_ExpectAnyArgsAndReturn( fclose_success_val ); + /* Call otaPal_GetPlatformImageState and check the result. */ + ePalImageState = otaPal_GetPlatformImageState( &otaFileContext ); + TEST_ASSERT_EQUAL( OtaPalImageStateInvalid, ePalImageState ); } diff --git a/platform/posix/ota_pal/utest/ota_utest_config.h.in b/platform/posix/ota_pal/utest/ota_utest_config.h.in deleted file mode 100644 index 33318b8cc7..0000000000 --- a/platform/posix/ota_pal/utest/ota_utest_config.h.in +++ /dev/null @@ -1,44 +0,0 @@ -/* - * AWS IoT Device SDK for Embedded C V202011.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://aws.amazon.com/freertos - * http://www.FreeRTOS.org - */ - -/** - * @file ota_config.h - * @brief OTA user configurable settings. - */ - -#ifndef _OTA_UTEST_CONFIG_H_ -#define _OTA_UTEST_CONFIG_H_ - -/** - * @brief Path to cert for OTA PAL test. Used to verify signature. - */ -#cmakedefine OTA_PAL_UTEST_CERT_FILE "@OTA_PAL_UTEST_CERT_FILE@" - -/** - * @brief Some devices have a hard-coded name for the firmware image to boot. - */ -#cmakedefine OTA_PAL_UTEST_FIRMWARE_FILE "@OTA_PAL_UTEST_FIRMWARE_FILE@" - -#endif diff --git a/tools/cmock/ota.yml b/tools/cmock/ota.yml new file mode 100644 index 0000000000..d9f1d990ea --- /dev/null +++ b/tools/cmock/ota.yml @@ -0,0 +1,33 @@ +:cmock: + :mock_prefix: mock_ + :when_no_prototypes: :warn + :enforce_strict_ordering: true + # fclose is called after program terminates, so this will avoid a segfault. + :fail_on_unexpected_calls: false + :plugins: + - :ignore + - :ignore_arg + - :expect_any_args + - :array + - :callback + - :return_thru_ptr + :callback_include_count: true # include a count arg when calling the callback + :callback_after_arg_check: false # check arguments before calling the callback + :treat_as: + uint8: HEX8 + uint16: HEX16 + uint32: UINT32 + int8: INT8 + bool: UINT8 + :includes: # This will add these includes to each mock. + - + - + :treat_externs: :include # Now the extern-ed functions will be mocked. + :weak: __attribute__((weak)) + :verbosity: 3 + :strippables: + # These keywords are found in many POSIX APIs but is stripped as it cannot be parsed by CMock. + - __restrict + - \s__THROW + - __owur + - __attribute__((__warn_unused_result__))