Skip to content

Commit 6343da9

Browse files
authored
Add code example to doxygen and validate in CI (#30)
Add POSIX example application of using backoffAlgorithm library in doxygen documentation. Also, add a CI check mechanism to validate compilation of code example.
1 parent b70641b commit 6343da9

File tree

6 files changed

+157
-34
lines changed

6 files changed

+157
-34
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
cmake -S test -B build/ \
1818
-G "Unix Makefiles" \
1919
-DCMAKE_BUILD_TYPE=Debug \
20-
-DBUILD_CLONE_SUBMODULES=ON \
20+
-DBUILD_UNIT_TESTS=ON \
2121
-DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror'
2222
make -C build/ all
2323
- name: Test
@@ -35,6 +35,15 @@ jobs:
3535
uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main
3636
with:
3737
path: ./build/coverage.info
38+
build-code-example:
39+
runs-on: ubuntu-latest
40+
steps:
41+
- name: Clone This Repo
42+
uses: actions/checkout@v2
43+
- name: Build code example
44+
run: |
45+
cmake -S test -B Build -DBUILD_CODE_EXAMPLE=ON
46+
make -C Build code_example_posix -j8
3847
complexity:
3948
runs-on: ubuntu-latest
4049
steps:
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include "backoff_algorithm.h"
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <netdb.h>
5+
#include <unistd.h>
6+
#include <time.h>
7+
8+
/* The maximum number of retries for the example code. */
9+
#define RETRY_MAX_ATTEMPTS ( 5U )
10+
11+
/* The maximum back-off delay (in milliseconds) for between retries in the example. */
12+
#define RETRY_MAX_BACKOFF_DELAY_MS ( 5000U )
13+
14+
/* The base back-off delay (in milliseconds) for retry configuration in the example. */
15+
#define RETRY_BACKOFF_BASE_MS ( 500U )
16+
17+
int main()
18+
{
19+
/* @[code_example_backoffalgorithm_initializeparams] */
20+
/* Variables used in this example. */
21+
BackoffAlgorithmStatus_t retryStatus = BackoffAlgorithmSuccess;
22+
BackoffAlgorithmContext_t retryParams;
23+
char serverAddress[] = "amazon.com";
24+
uint16_t nextRetryBackoff = 0;
25+
26+
/* Initialize reconnect attempts and interval. */
27+
BackoffAlgorithm_InitializeParams( &retryParams,
28+
RETRY_BACKOFF_BASE_MS,
29+
RETRY_MAX_BACKOFF_DELAY_MS,
30+
RETRY_MAX_ATTEMPTS );
31+
/* @[code_example_backoffalgorithm_initializeparams] */
32+
33+
int32_t dnsStatus = -1;
34+
struct addrinfo hints;
35+
struct addrinfo ** pListHead = NULL;
36+
struct timespec tp;
37+
38+
/* Add hints to retrieve only TCP sockets in getaddrinfo. */
39+
( void ) memset( &hints, 0, sizeof( hints ) );
40+
41+
/* Address family of either IPv4 or IPv6. */
42+
hints.ai_family = AF_UNSPEC;
43+
/* TCP Socket. */
44+
hints.ai_socktype = ( int32_t ) SOCK_STREAM;
45+
hints.ai_protocol = IPPROTO_TCP;
46+
47+
/* @[code_example_backoffalgorithm_getnextbackoff] */
48+
49+
/* Seed the pseudo random number generator used in this example (with call to
50+
* rand() function provided by ISO C standard library) for use in backoff period
51+
* calculation when retrying failed DNS resolution. */
52+
53+
/* Get current time to seed pseudo random number generator. */
54+
( void ) clock_gettime( CLOCK_REALTIME, &tp );
55+
/* Seed pseudo random number generator with seconds. */
56+
srand( tp.tv_sec );
57+
58+
do
59+
{
60+
/* Perform a DNS lookup on the given host name. */
61+
dnsStatus = getaddrinfo( serverAddress, NULL, &hints, pListHead );
62+
63+
/* Retry if DNS resolution query failed. */
64+
if( dnsStatus != 0 )
65+
{
66+
/* Generate a random number and get back-off value (in milliseconds) for the next retry.
67+
* Note: It is recommended to use a random number generator that is seeded with
68+
* device-specific entropy source so that backoff calculation across devices is different
69+
* and possibility of network collision between devices attempting retries can be avoided.
70+
*
71+
* For the simplicity of this code example, the pseudo random number generator, rand()
72+
* function is used. */
73+
retryStatus = BackoffAlgorithm_GetNextBackoff( &retryParams, rand(), &nextRetryBackoff );
74+
75+
/* Wait for the calculated backoff period before the next retry attempt of querying DNS.
76+
* As usleep() takes nanoseconds as the parameter, we multiply the backoff period by 1000. */
77+
( void ) usleep( nextRetryBackoff * 1000U );
78+
}
79+
} while( ( dnsStatus != 0 ) && ( retryStatus != BackoffAlgorithmRetriesExhausted ) );
80+
81+
/* @[code_example_backoffalgorithm_getnextbackoff] */
82+
83+
return dnsStatus;
84+
}

docs/doxygen/config.doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ EXCLUDE_SYMLINKS = NO
797797
# that contain example code fragments that are included (see the \include
798798
# command).
799799

800-
EXAMPLE_PATH = source/include docs/doxygen/include
800+
EXAMPLE_PATH = source/include docs/doxygen/include docs/doxygen/code_examples
801801

802802
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
803803
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and

docs/doxygen/pages.dox

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,34 @@ every path of execution and achieve 100% branch coverage.
6161
</p>
6262
*/
6363

64+
/**
65+
@page backoff_algorithm_example Code Example for backoffAlgorithm API
66+
@brief Example POSIX application that retries DNS resolution operation with exponential backoff-and-jitter using the backoffAlgorithm library.
67+
68+
@include backoff_algorithm_posix.c
69+
*/
70+
6471
/**
6572
@page backoff_algorithm_functions Functions
6673
@brief Primary functions of the backoffAlgorithm library:<br><br>
6774
@subpage define_backoffalgorithm_initializeparams <br>
6875
@subpage define_backoffalgorithm_getnextbackoff <br>
6976

77+
<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.
78+
7079
@page define_backoffalgorithm_initializeparams BackoffAlgorithm_InitializeParams
7180
@snippet backoff_algorithm.h define_backoffalgorithm_initializeparams
7281
@copydoc BackoffAlgorithm_InitializeParams
7382

83+
From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_InitializeParams API.
84+
@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_initializeparams
85+
7486
@page define_backoffalgorithm_getnextbackoff BackoffAlgorithm_GetNextBackoff
75-
@snippet backoff_algorithm.h define_backoffalgorithm_getnextbackoff
7687
@copydoc BackoffAlgorithm_GetNextBackoff
88+
89+
From the @ref backoff_algorithm_example, following is the part relevant to the @ref BackoffAlgorithm_GetNextBackoff API.
90+
@snippet backoff_algorithm_posix.c code_example_backoffalgorithm_getnextbackoff
91+
7792
*/
7893

7994
<!-- We do not use doxygen ALIASes here because there have been issues in the past versions with "^^" newlines within the alias definition. -->

lexicon.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ os
4141
param
4242
pcontext
4343
pnextbackoff
44+
posix
4445
pretrycontext
4546
pretryparams
4647
prng
48+
rand
4749
randomvalue
4850
readme
4951
rm
@@ -57,4 +59,5 @@ td
5759
toolchain
5860
tr
5961
trng
60-
utils
62+
usleep
63+
utils

test/CMakeLists.txt

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ set( UNIT_TEST_DIR ${MODULE_ROOT_DIR}/test/unit-test CACHE INTERNAL "backoffAlgo
2222
set( UNITY_DIR ${UNIT_TEST_DIR}/Unity CACHE INTERNAL "Unity library source directory." )
2323

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

2929
# Set output directories.
@@ -47,41 +47,53 @@ target_include_directories( coverity_analysis
4747

4848
# ==================================== Unit Test Configuration ====================================
4949

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

53-
# Check if the Unity source directory exists, and if not present, clone the submodule
54-
# if BUILD_CLONE_SUBMODULES configuration is enabled.
55-
if( NOT EXISTS ${UNITY_DIR}/src )
56-
# Attempt to clone Unity.
57-
if( ${BUILD_CLONE_SUBMODULES} )
52+
# Target for code example binary.
53+
add_executable( code_example_posix
54+
${MODULE_ROOT_DIR}/docs/doxygen/code_examples/backoff_algorithm_posix.c )
55+
56+
target_link_libraries( code_example_posix coverity_analysis )
57+
58+
endif()
59+
60+
# ==================================== Unit Test Configuration ====================================
61+
62+
if(${BUILD_UNIT_TESTS})
63+
64+
# Include Unity build configuration.
65+
include( unit-test/unity_build.cmake )
66+
67+
# Check if the Unity source directory exists, and if not present, clone the submodule
68+
# if BUILD_CLONE_SUBMODULES configuration is enabled.
69+
if( NOT EXISTS ${UNITY_DIR}/src )
70+
# Attempt to clone Unity.
5871
clone_unity()
59-
else()
60-
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." )
6172
endif()
62-
endif()
6373

64-
# Add unit test and coverage configuration.
74+
# Add unit test and coverage configuration.
6575

66-
# Use CTest utility for managing test runs. This has to be added BEFORE
67-
# defining test targets with add_test()
68-
enable_testing()
76+
# Use CTest utility for managing test runs. This has to be added BEFORE
77+
# defining test targets with add_test()
78+
enable_testing()
6979

70-
# Add build targets for Unity and Unit, required for unit testing.
71-
add_unity_targets()
80+
# Add build targets for Unity and Unit, required for unit testing.
81+
add_unity_targets()
7282

73-
# Add function to enable Unity based tests and coverage.
74-
include( ${MODULE_ROOT_DIR}/tools/unity/create_test.cmake )
83+
# Add function to enable Unity based tests and coverage.
84+
include( ${MODULE_ROOT_DIR}/tools/unity/create_test.cmake )
7585

76-
# Include build configuration for unit tests.
77-
add_subdirectory( unit-test )
86+
# Include build configuration for unit tests.
87+
add_subdirectory( unit-test )
7888

79-
# ==================================== Coverage Analysis configuration ============================
89+
# ==================================== Coverage Analysis configuration ============================
8090

81-
# Add a target for running coverage on tests.
82-
add_custom_target( coverage
83-
COMMAND ${CMAKE_COMMAND} -DUNITY_DIR=${UNITY_DIR}
84-
-P ${MODULE_ROOT_DIR}/tools/unity/coverage.cmake
85-
DEPENDS unity backoff_algorithm_utest
86-
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
87-
)
91+
# Add a target for running coverage on tests.
92+
add_custom_target( coverage
93+
COMMAND ${CMAKE_COMMAND} -DUNITY_DIR=${UNITY_DIR}
94+
-P ${MODULE_ROOT_DIR}/tools/unity/coverage.cmake
95+
DEPENDS unity backoff_algorithm_utest
96+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
97+
)
98+
99+
endif()

0 commit comments

Comments
 (0)