diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ab22e79..31f5976 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -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
@@ -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:
diff --git a/docs/doxygen/code_examples/backoff_algorithm_posix.c b/docs/doxygen/code_examples/backoff_algorithm_posix.c
new file mode 100644
index 0000000..978a63e
--- /dev/null
+++ b/docs/doxygen/code_examples/backoff_algorithm_posix.c
@@ -0,0 +1,84 @@
+#include "backoff_algorithm.h"
+#include
+#include
+#include
+#include
+#include
+
+/* 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;
+}
diff --git a/docs/doxygen/config.doxyfile b/docs/doxygen/config.doxyfile
index 01da3ef..665f932 100644
--- a/docs/doxygen/config.doxyfile
+++ b/docs/doxygen/config.doxyfile
@@ -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
diff --git a/docs/doxygen/pages.dox b/docs/doxygen/pages.dox
index 89d5e3a..1c1b260 100644
--- a/docs/doxygen/pages.dox
+++ b/docs/doxygen/pages.dox
@@ -61,19 +61,34 @@ every path of execution and achieve 100% branch coverage.
*/
+/**
+@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:
@subpage define_backoffalgorithm_initializeparams
@subpage define_backoffalgorithm_getnextbackoff
+For a code example 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
+
*/
diff --git a/lexicon.txt b/lexicon.txt
index 4eadb40..5e17bca 100644
--- a/lexicon.txt
+++ b/lexicon.txt
@@ -41,9 +41,11 @@ os
param
pcontext
pnextbackoff
+posix
pretrycontext
pretryparams
prng
+rand
randomvalue
readme
rm
@@ -57,4 +59,5 @@ td
toolchain
tr
trng
-utils
+usleep
+utils
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 13aad94..becb94e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -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.
@@ -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()