Skip to content

Commit

Permalink
Add code example to doxygen and validate in CI (#30)
Browse files Browse the repository at this point in the history
Add POSIX example application of using backoffAlgorithm library in doxygen documentation. Also, add a CI check mechanism to validate compilation of code example.
  • Loading branch information
aggarw13 authored Jul 23, 2021
1 parent b70641b commit 6343da9
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 34 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
cmake -S test -B build/ \
-G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_CLONE_SUBMODULES=ON \
-DBUILD_UNIT_TESTS=ON \
-DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror'
make -C build/ all
- name: Test
Expand All @@ -35,6 +35,15 @@ jobs:
uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main
with:
path: ./build/coverage.info
build-code-example:
runs-on: ubuntu-latest
steps:
- name: Clone This Repo
uses: actions/checkout@v2
- name: Build code example
run: |
cmake -S test -B Build -DBUILD_CODE_EXAMPLE=ON
make -C Build code_example_posix -j8
complexity:
runs-on: ubuntu-latest
steps:
Expand Down
84 changes: 84 additions & 0 deletions docs/doxygen/code_examples/backoff_algorithm_posix.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "backoff_algorithm.h"
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <time.h>

/* The maximum number of retries for the example code. */
#define RETRY_MAX_ATTEMPTS ( 5U )

/* The maximum back-off delay (in milliseconds) for between retries in the example. */
#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U )

/* The base back-off delay (in milliseconds) for retry configuration in the example. */
#define RETRY_BACKOFF_BASE_MS ( 500U )

int main()
{
/* @[code_example_backoffalgorithm_initializeparams] */
/* Variables used in this example. */
BackoffAlgorithmStatus_t retryStatus = BackoffAlgorithmSuccess;
BackoffAlgorithmContext_t retryParams;
char serverAddress[] = "amazon.com";
uint16_t nextRetryBackoff = 0;

/* Initialize reconnect attempts and interval. */
BackoffAlgorithm_InitializeParams( &retryParams,
RETRY_BACKOFF_BASE_MS,
RETRY_MAX_BACKOFF_DELAY_MS,
RETRY_MAX_ATTEMPTS );
/* @[code_example_backoffalgorithm_initializeparams] */

int32_t dnsStatus = -1;
struct addrinfo hints;
struct addrinfo ** pListHead = NULL;
struct timespec tp;

/* Add hints to retrieve only TCP sockets in getaddrinfo. */
( void ) memset( &hints, 0, sizeof( hints ) );

/* Address family of either IPv4 or IPv6. */
hints.ai_family = AF_UNSPEC;
/* TCP Socket. */
hints.ai_socktype = ( int32_t ) SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

/* @[code_example_backoffalgorithm_getnextbackoff] */

/* Seed the pseudo random number generator used in this example (with call to
* rand() function provided by ISO C standard library) for use in backoff period
* calculation when retrying failed DNS resolution. */

/* Get current time to seed pseudo random number generator. */
( void ) clock_gettime( CLOCK_REALTIME, &tp );
/* Seed pseudo random number generator with seconds. */
srand( tp.tv_sec );

do
{
/* Perform a DNS lookup on the given host name. */
dnsStatus = getaddrinfo( serverAddress, NULL, &hints, pListHead );

/* Retry if DNS resolution query failed. */
if( dnsStatus != 0 )
{
/* Generate a random number and get back-off value (in milliseconds) for the next retry.
* Note: It is recommended to use a random number generator that is seeded with
* device-specific entropy source so that backoff calculation across devices is different
* and possibility of network collision between devices attempting retries can be avoided.
*
* For the simplicity of this code example, the pseudo random number generator, rand()
* function is used. */
retryStatus = BackoffAlgorithm_GetNextBackoff( &retryParams, rand(), &nextRetryBackoff );

/* Wait for the calculated backoff period before the next retry attempt of querying DNS.
* As usleep() takes nanoseconds as the parameter, we multiply the backoff period by 1000. */
( void ) usleep( nextRetryBackoff * 1000U );
}
} while( ( dnsStatus != 0 ) && ( retryStatus != BackoffAlgorithmRetriesExhausted ) );

/* @[code_example_backoffalgorithm_getnextbackoff] */

return dnsStatus;
}
2 changes: 1 addition & 1 deletion docs/doxygen/config.doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ EXCLUDE_SYMLINKS = NO
# that contain example code fragments that are included (see the \include
# command).

EXAMPLE_PATH = source/include docs/doxygen/include
EXAMPLE_PATH = source/include docs/doxygen/include docs/doxygen/code_examples

# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
Expand Down
17 changes: 16 additions & 1 deletion docs/doxygen/pages.dox
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,34 @@ every path of execution and achieve 100% branch coverage.
</p>
*/

/**
@page backoff_algorithm_example Code Example for backoffAlgorithm API
@brief Example POSIX application that retries DNS resolution operation with exponential backoff-and-jitter using the backoffAlgorithm library.

@include backoff_algorithm_posix.c
*/

/**
@page backoff_algorithm_functions Functions
@brief Primary functions of the backoffAlgorithm library:<br><br>
@subpage define_backoffalgorithm_initializeparams <br>
@subpage define_backoffalgorithm_getnextbackoff <br>

<b>For a code example </b> of using backoffAlgorithm library for retrying operations with exponential back-off and jitter, refer to @ref backoff_algorithm_example.

@page define_backoffalgorithm_initializeparams BackoffAlgorithm_InitializeParams
@snippet backoff_algorithm.h define_backoffalgorithm_initializeparams
@copydoc BackoffAlgorithm_InitializeParams

From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_InitializeParams API.
@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_initializeparams

@page define_backoffalgorithm_getnextbackoff BackoffAlgorithm_GetNextBackoff
@snippet backoff_algorithm.h define_backoffalgorithm_getnextbackoff
@copydoc BackoffAlgorithm_GetNextBackoff

From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_GetNextBackoff API.
@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_getnextbackoff

*/

<!-- We do not use doxygen ALIASes here because there have been issues in the past versions with "^^" newlines within the alias definition. -->
Expand Down
5 changes: 4 additions & 1 deletion lexicon.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ os
param
pcontext
pnextbackoff
posix
pretrycontext
pretryparams
prng
rand
randomvalue
readme
rm
Expand All @@ -57,4 +59,5 @@ td
toolchain
tr
trng
utils
usleep
utils
72 changes: 42 additions & 30 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ set( UNIT_TEST_DIR ${MODULE_ROOT_DIR}/test/unit-test CACHE INTERNAL "backoffAlgo
set( UNITY_DIR ${UNIT_TEST_DIR}/Unity CACHE INTERNAL "Unity library source directory." )

# Configure options to always show in CMake GUI.
option( BUILD_CLONE_SUBMODULES
"Set this to ON to automatically clone any required Git submodules. When OFF, submodules must be manually cloned."
option( BUILD_UNIT_TESTS
"Set this to ON to build unit tests. This will clone the required Unity test framework submodule if it is not cloned already."
OFF )

# Set output directories.
Expand All @@ -47,41 +47,53 @@ target_include_directories( coverity_analysis

# ==================================== Unit Test Configuration ====================================

# Include Unity build configuration.
include( unit-test/unity_build.cmake )
if(${BUILD_CODE_EXAMPLE})

# Check if the Unity source directory exists, and if not present, clone the submodule
# if BUILD_CLONE_SUBMODULES configuration is enabled.
if( NOT EXISTS ${UNITY_DIR}/src )
# Attempt to clone Unity.
if( ${BUILD_CLONE_SUBMODULES} )
# Target for code example binary.
add_executable( code_example_posix
${MODULE_ROOT_DIR}/docs/doxygen/code_examples/backoff_algorithm_posix.c )

target_link_libraries( code_example_posix coverity_analysis )

endif()

# ==================================== Unit Test Configuration ====================================

if(${BUILD_UNIT_TESTS})

# Include Unity build configuration.
include( unit-test/unity_build.cmake )

# Check if the Unity source directory exists, and if not present, clone the submodule
# if BUILD_CLONE_SUBMODULES configuration is enabled.
if( NOT EXISTS ${UNITY_DIR}/src )
# Attempt to clone Unity.
clone_unity()
else()
message( FATAL_ERROR "The required submodule Unity does not exist. Either clone it manually, or set BUILD_CLONE_SUBMODULES to 1 to automatically clone it during build." )
endif()
endif()

# Add unit test and coverage configuration.
# Add unit test and coverage configuration.

# Use CTest utility for managing test runs. This has to be added BEFORE
# defining test targets with add_test()
enable_testing()
# Use CTest utility for managing test runs. This has to be added BEFORE
# defining test targets with add_test()
enable_testing()

# Add build targets for Unity and Unit, required for unit testing.
add_unity_targets()
# Add build targets for Unity and Unit, required for unit testing.
add_unity_targets()

# Add function to enable Unity based tests and coverage.
include( ${MODULE_ROOT_DIR}/tools/unity/create_test.cmake )
# Add function to enable Unity based tests and coverage.
include( ${MODULE_ROOT_DIR}/tools/unity/create_test.cmake )

# Include build configuration for unit tests.
add_subdirectory( unit-test )
# Include build configuration for unit tests.
add_subdirectory( unit-test )

# ==================================== Coverage Analysis configuration ============================
# ==================================== Coverage Analysis configuration ============================

# Add a target for running coverage on tests.
add_custom_target( coverage
COMMAND ${CMAKE_COMMAND} -DUNITY_DIR=${UNITY_DIR}
-P ${MODULE_ROOT_DIR}/tools/unity/coverage.cmake
DEPENDS unity backoff_algorithm_utest
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
# Add a target for running coverage on tests.
add_custom_target( coverage
COMMAND ${CMAKE_COMMAND} -DUNITY_DIR=${UNITY_DIR}
-P ${MODULE_ROOT_DIR}/tools/unity/coverage.cmake
DEPENDS unity backoff_algorithm_utest
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)

endif()

0 comments on commit 6343da9

Please sign in to comment.