From 33904595f701043afbc8f94036899dc331dd3386 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Wed, 21 Jun 2023 22:26:54 -0500 Subject: [PATCH] Feature: Add f_network_to_ip_string() and f_network_from_ip_string() functions. Provide support for inet_ntop() and inet_pton(). String are handling in FLL via f_string_static_t and f_string_dynamic_t. The functions f_network_to_ip_string() and f_network_from_ip_string() are written to convert to these string types. This implements a custom f_network_family_ip_t type to pass the digit IP address. The idea here is to help reduce how much the FLL API is locked into the "libc" or POSIX API. The structures are allocated using "{ 0 }" to take advantage of the supposed relatively new feature that treats this as an initialize all to NULL. --- build/level_0/settings | 2 +- build/monolithic/settings | 2 +- level_0/f_network/c/network.c | 57 ++++++++++++- level_0/f_network/c/network.h | 64 ++++++++++++++- level_0/f_network/c/network/common.h | 93 ++++++++++++++++++++++ level_0/f_network/data/build/dependencies | 2 + level_0/f_network/data/build/settings | 4 +- level_0/f_network/data/build/settings-mocks | 4 +- level_0/f_network/data/build/settings-tests | 4 +- level_0/f_network/tests/unit/c/mock-network.c | 34 ++++++++ level_0/f_network/tests/unit/c/mock-network.h | 3 + .../tests/unit/c/test-network-from_host_long.h | 2 +- .../tests/unit/c/test-network-from_ip_string.c | 81 +++++++++++++++++++ .../tests/unit/c/test-network-from_ip_string.h | 41 ++++++++++ .../tests/unit/c/test-network-to_ip_string.c | 89 +++++++++++++++++++++ .../tests/unit/c/test-network-to_ip_string.h | 41 ++++++++++ level_0/f_network/tests/unit/c/test-network.c | 7 ++ level_0/f_network/tests/unit/c/test-network.h | 3 + 18 files changed, 517 insertions(+), 16 deletions(-) create mode 100644 level_0/f_network/c/network/common.h create mode 100644 level_0/f_network/tests/unit/c/test-network-from_ip_string.c create mode 100644 level_0/f_network/tests/unit/c/test-network-from_ip_string.h create mode 100644 level_0/f_network/tests/unit/c/test-network-to_ip_string.c create mode 100644 level_0/f_network/tests/unit/c/test-network-to_ip_string.h diff --git a/build/level_0/settings b/build/level_0/settings index 8a29bfa..c0525d0 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -106,7 +106,7 @@ build_sources_headers fss.h fss/comment.h fss/common.h fss/delimit.h fss/named.h build_sources_headers iki.h iki/common.h iki/data.h build_sources_headers limit.h limit/set.h limit/value.h build_sources_headers memory.h memory/structure.h memory/common.h -build_sources_headers network.h +build_sources_headers network.h network/common.h build_sources_headers parse.h parse/utf.h build_sources_headers path.h path/common.h build_sources_headers pipe.h diff --git a/build/monolithic/settings b/build/monolithic/settings index 8a15e3d..a0e42b8 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -128,7 +128,7 @@ build_sources_headers level_0/fss.h level_0/fss/comment.h level_0/fss/common.h l build_sources_headers level_0/iki.h level_0/iki/common.h level_0/iki/data.h build_sources_headers level_0/limit.h level_0/limit/set.h level_0/limit/value.h build_sources_headers level_0/memory.h level_0/memory/structure.h level_0/memory/common.h -build_sources_headers level_0/network.h +build_sources_headers level_0/network.h network/common.h build_sources_headers level_0/parse.h level_0/parse/utf.h build_sources_headers level_0/path.h level_0/path/common.h build_sources_headers level_0/pipe.h diff --git a/level_0/f_network/c/network.c b/level_0/f_network/c/network.c index 5d0389e..d269955 100644 --- a/level_0/f_network/c/network.c +++ b/level_0/f_network/c/network.c @@ -5,7 +5,7 @@ extern "C" { #endif #ifndef _di_f_network_from_host_long_ - f_status_t f_network_from_host_long(const uint32_t from, uint32_t *to) { + f_status_t f_network_from_host_long(const uint32_t from, uint32_t * const to) { #ifndef _di_level_0_parameter_checking_ if (!to) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -17,7 +17,7 @@ extern "C" { #endif // _di_f_network_from_host_long_ #ifndef _di_f_network_from_host_short_ - f_status_t f_network_from_host_short(const uint16_t from, uint16_t *to) { + f_status_t f_network_from_host_short(const uint16_t from, uint16_t * const to) { #ifndef _di_level_0_parameter_checking_ if (!to) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -28,8 +28,26 @@ extern "C" { } #endif // _di_f_network_from_host_short_ +#ifndef _di_f_network_from_ip_string_ + f_status_t f_network_from_ip_string(const f_string_static_t from, f_network_family_ip_t * const to) { + #ifndef _di_level_0_parameter_checking_ + if (!to) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!from.used || to->type == f_network_family_none_e) return F_data_not; + + if (inet_pton(to->type == f_network_family_ip_4_e ? AF_INET : AF_INET6, from.string, (void *) & to->address) == -1) { + if (errno == EAFNOSUPPORT) return F_status_set_error(F_support_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_network_from_ip_string_ + #ifndef _di_f_network_to_host_long_ - f_status_t f_network_to_host_long(const uint32_t from, uint32_t *to) { + f_status_t f_network_to_host_long(const uint32_t from, uint32_t * const to) { #ifndef _di_level_0_parameter_checking_ if (!to) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -41,7 +59,7 @@ extern "C" { #endif // _di_f_network_to_host_long_ #ifndef _di_f_network_to_host_short_ - f_status_t f_network_to_host_short(const uint16_t from, uint16_t *to) { + f_status_t f_network_to_host_short(const uint16_t from, uint16_t * const to) { #ifndef _di_level_0_parameter_checking_ if (!to) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -52,6 +70,37 @@ extern "C" { } #endif // _di_f_network_to_host_short_ +#ifndef _di_f_network_to_ip_string_ + f_status_t f_network_to_ip_string(const f_network_family_ip_t from, f_string_dynamic_t * const to) { + #ifndef _di_level_0_parameter_checking_ + if (!to) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!(from.type == f_network_family_ip_4_e || from.type == f_network_family_ip_6_e)) return F_data_not; + + { + const f_status_t status = f_string_dynamic_increase_by((from.type == f_network_family_ip_4_e ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN) + 1, to); + if (F_status_is_error(status)) return status; + } + + if (!inet_ntop(from.type == f_network_family_ip_4_e ? AF_INET : AF_INET6, (void *) & from.address, to->string + to->used, from.type == f_network_family_ip_4_e ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN)) { + if (errno == EAFNOSUPPORT) return F_status_set_error(F_support_not); + if (errno == ENOSPC) return F_status_set_error(F_space_not); + + return F_status_set_error(F_failure); + } + + while (to->used < to->size && to->string[to->used]) { + ++to->used; + } // while + + // The string should be NULL terminated, but in case it is not, ensure one always exists. + to->string[to->used] = 0; + + return F_none; + } +#endif // _di_f_network_to_ip_string_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_network/c/network.h b/level_0/f_network/c/network.h index d782371..407f1c9 100644 --- a/level_0/f_network/c/network.h +++ b/level_0/f_network/c/network.h @@ -16,8 +16,10 @@ // FLL-0 includes. #include #include +#include // FLL-0 network includes. +#include #ifdef __cplusplus extern "C" { @@ -39,7 +41,7 @@ extern "C" { * @see htonl() */ #ifndef _di_f_network_from_host_long_ - extern f_status_t f_network_from_host_long(const uint32_t from, uint32_t *to); + extern f_status_t f_network_from_host_long(const uint32_t from, uint32_t * const to); #endif // _di_f_network_from_host_long_ /** @@ -58,10 +60,35 @@ extern "C" { * @see htons() */ #ifndef _di_f_network_from_host_short_ - extern f_status_t f_network_from_host_short(const uint16_t from, uint16_t *to); + extern f_status_t f_network_from_host_short(const uint16_t from, uint16_t * const to); #endif // _di_f_network_from_host_short_ /** + * Convert from a human-friendly string into a network IP address digit. + * + * This is for the ip address and is not for the domain name. + * + * @param from + * The human-friendly ip address string. + * @param to + * The converted IP version 4 or version 6 family integer. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to convert (to.type is f_network_family_none_e or from.used is 0). + * + * F_parameter (with error bit) if a parameter is invalid. + * F_space_not (with error bit) if not enough space is available in to.string. + * F_support_not (with error bit) if an invalid address family type is passed to inet_pton(). + * F_failure (with error bit) on any other error. + * + * @see inet_pton() + */ +#ifndef _di_f_network_from_ip_string_ + extern f_status_t f_network_from_ip_string(const f_string_static_t from, f_network_family_ip_t * const to); +#endif // _di_f_network_from_ip_string_ + +/** * Convert from network byte order to host byte order for an unsigned long integer. * * @param from @@ -77,7 +104,7 @@ extern "C" { * @see ntohl() */ #ifndef _di_f_network_to_host_long_ - extern f_status_t f_network_to_host_long(const uint32_t from, uint32_t *to); + extern f_status_t f_network_to_host_long(const uint32_t from, uint32_t * const to); #endif // _di_f_network_to_host_long_ /** @@ -96,9 +123,38 @@ extern "C" { * @see ntohs() */ #ifndef _di_f_network_to_host_short_ - extern f_status_t f_network_to_host_short(const uint16_t from, uint16_t *to); + extern f_status_t f_network_to_host_short(const uint16_t from, uint16_t * const to); #endif // _di_f_network_to_host_short_ +/** + * Convert from a network IP address digit into a human-friendly string. + * + * This is for the ip address and is not for the domain name. + * + * @param from + * The IP version 4 or version 6 family integer. + * @param to + * The converted human-friendly ip address string. + * + * @return + * F_none on success. + * F_data_not on success but there is nothing to convert (from.type is f_network_family_none_e). + * + * F_parameter (with error bit) if a parameter is invalid. + * F_space_not (with error bit) if not enough space is available in to.string. + * F_support_not (with error bit) if an invalid address family type is passed to inet_ntop(). + * F_failure (with error bit) on any other error. + * + * Errors (with error bit) from: f_string_dynamic_increase_by() + * + * @see inet_ntop() + * + * @see f_string_dynamic_increase_by() + */ +#ifndef _di_f_network_to_ip_string_ + extern f_status_t f_network_to_ip_string(const f_network_family_ip_t from, f_string_dynamic_t * const to); +#endif // _di_f_network_to_ip_string_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_network/c/network/common.h b/level_0/f_network/c/network/common.h new file mode 100644 index 0000000..b78f3a2 --- /dev/null +++ b/level_0/f_network/c/network/common.h @@ -0,0 +1,93 @@ +/** + * FLL - Level 0 + * + * Project: Network + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Defines network common data. + * + * This is auto-included by network.h and should not need to be explicitly included. + */ +#ifndef _F_network_common_h +#define _F_network_common_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Designate an ip address family. + * + * f_network_family_*_e: + * - none: Represents address family is not set. + * - ip_4: Represents IP address family version 4, similar to AF_INET. + * - ip_6: Represents IP address family version 6, similar to AF_INET6. + */ +#ifndef _di_f_network_family_e_ + enum { + f_network_family_none_e = 0, + f_network_family_ip_4_e, + f_network_family_ip_6_e, + }; // enum +#endif // _di_f_network_family_e_ + +/** + * A union for representing either an IP version 4 or IP version 6 structure. + * + * v4: The IP version 4. + * v6: The IP version 6. + * + * macro_f_network_family_ip_4_or_6_t_*: + * - initialize_1: Specifically initialize the IP address version 4. + * - initialize_2: Specifically initialize the IP address version 6. + * - clear: Clear the union values. + */ +#ifndef _di_f_network_family_ip_4_or_6_t_ + typedef union { + struct in_addr v4; + struct in6_addr v6; + } f_network_family_ip_4_or_6_t; + + #define f_network_family_ip_4_or_6_t_initialize { 0 } + + #define macro_f_network_family_ip_4_or_6_t_initialize_1(v4) { .v4 = v4 } + #define macro_f_network_family_ip_4_or_6_t_initialize_2(v6) { .v6 = v6 } + + #define f_network_family_ip_4_or_6_t_clear(family_ip_4_or_6) \ + family_ip_4_or_6.v4 = 0; \ + family_ip_4_or_6.v6 = 0; +#endif // _di_f_network_family_ip_4_or_6_t_ + +/** + * A structure for managing an IP address version 4 or 6. + * + * type: The type, usually either one of f_network_family_ip_4_e or f_network_family_ip_6_e. + * address: The address data. + * + * macro_f_network_family_ip_4_or_6_t_*: + * - initialize_1: Specifically initialize the IP address version 4. + * - initialize_2: Specifically initialize the IP address version 6. + * - clear: Clear the union values. + */ +#ifndef _di_f_network_family_ip_t_ + typedef struct { + uint8_t type; + f_network_family_ip_4_or_6_t address; + } f_network_family_ip_t; + + #define f_network_family_ip_t_initialize { 0 } + + #define macro_f_network_family_ip_t_initialize_1(v4) { f_network_family_ip_4_e, macro_f_network_family_ip_4_or_6_t_initialize_1(v4) } + #define macro_f_network_family_ip_t_initialize_2(v6) { f_network_family_ip_6_e, macro_f_network_family_ip_4_or_6_t_initialize_2(v6) } + + #define f_network_family_ip_t_clear(family_ip) \ + family_ip.type = f_network_family_none_e; \ + f_network_family_ip_t_clear(family_ip.address) +#endif // _di_f_network_family_ip_t_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_network_common_h diff --git a/level_0/f_network/data/build/dependencies b/level_0/f_network/data/build/dependencies index d9c4b77..d798245 100644 --- a/level_0/f_network/data/build/dependencies +++ b/level_0/f_network/data/build/dependencies @@ -2,3 +2,5 @@ f_type f_status +f_memory +f_string diff --git a/level_0/f_network/data/build/settings b/level_0/f_network/data/build/settings index eb683e4..cb8d96b 100644 --- a/level_0/f_network/data/build/settings +++ b/level_0/f_network/data/build/settings @@ -30,11 +30,11 @@ build_indexer_arguments rcs build_language c build_libraries -lc -build_libraries-individual +build_libraries-individual -lf_memory -lf_string build_sources_library network.c -build_sources_headers network.h +build_sources_headers network.h network/common.h build_script yes build_shared yes diff --git a/level_0/f_network/data/build/settings-mocks b/level_0/f_network/data/build/settings-mocks index 6a70870..e3d51f3 100644 --- a/level_0/f_network/data/build/settings-mocks +++ b/level_0/f_network/data/build/settings-mocks @@ -22,7 +22,7 @@ build_libraries-individual build_sources_library network.c ../../tests/unit/c/mock-network.c -build_sources_headers network.h +build_sources_headers network.h network/common.h build_script yes build_shared yes @@ -50,5 +50,7 @@ flags_library -fPIC # Inject mocks. flags -Wl,--wrap=htonl flags -Wl,--wrap=htons +flags -Wl,--wrap=inet_ntop +flags -Wl,--wrap=inet_pton flags -Wl,--wrap=ntohl flags -Wl,--wrap=ntohs diff --git a/level_0/f_network/data/build/settings-tests b/level_0/f_network/data/build/settings-tests index ce8bc65..12156bd 100644 --- a/level_0/f_network/data/build/settings-tests +++ b/level_0/f_network/data/build/settings-tests @@ -23,9 +23,9 @@ build_indexer_arguments rcs build_language c build_libraries -lc -lcmocka -build_libraries-individual -lf_network +build_libraries-individual -lf_memory -lf_string -lf_network -build_sources_program test-network-from_host_long.c test-network-from_host_short.c test-network-to_host_long.c test-network-to_host_short.c +build_sources_program test-network-from_host_long.c test-network-from_host_short.c test-network-from_ip_string.c test-network-to_host_long.c test-network-to_host_short.c test-network-to_ip_string.c build_sources_program test-network.c build_script no diff --git a/level_0/f_network/tests/unit/c/mock-network.c b/level_0/f_network/tests/unit/c/mock-network.c index e3c3986..b8f1d0d 100644 --- a/level_0/f_network/tests/unit/c/mock-network.c +++ b/level_0/f_network/tests/unit/c/mock-network.c @@ -14,6 +14,27 @@ uint16_t __wrap_htons(uint16_t hostshort) { return mock_type(uint16_t); } +const char *__wrap_inet_ntop(int af, const void *src, char *dst, socklen_t size) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return 0; + } + + char *string = mock_type(char *); + size_t total = mock_type(size_t); + + if (dst) { + memcpy(dst, string, total); + dst[total] = 0; + } + + return dst; +} + uint32_t __wrap_ntohl(uint32_t netlong) { return mock_type(uint32_t); @@ -24,6 +45,19 @@ uint16_t __wrap_ntohs(uint16_t netshort) { return mock_type(uint16_t); } +int __wrap_inet_pton(int af, const char *src, void *dst) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return 0; +} + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_network/tests/unit/c/mock-network.h b/level_0/f_network/tests/unit/c/mock-network.h index c450df3..5733e36 100644 --- a/level_0/f_network/tests/unit/c/mock-network.h +++ b/level_0/f_network/tests/unit/c/mock-network.h @@ -15,6 +15,7 @@ #include #include #include +#include // cmocka includes. #include @@ -30,8 +31,10 @@ const static int mock_errno_generic = 32767; extern uint32_t __wrap_htonl(uint32_t hostlong); extern uint16_t __wrap_htons(uint16_t hostshort); +const char *__wrap_inet_ntop(int af, const void *src, char *dst, socklen_t size); extern uint32_t __wrap_ntohl(uint32_t netlong); extern uint16_t __wrap_ntohs(uint16_t netshort); +extern int __wrap_inet_pton(int af, const char *src, void *dst); #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_network/tests/unit/c/test-network-from_host_long.h b/level_0/f_network/tests/unit/c/test-network-from_host_long.h index 5c0fbf8..8110ab0 100644 --- a/level_0/f_network/tests/unit/c/test-network-from_host_long.h +++ b/level_0/f_network/tests/unit/c/test-network-from_host_long.h @@ -1,7 +1,7 @@ /** * FLL - Level 0 * - * Project: Limit + * Project: Network * API Version: 0.7 * Licenses: lgpl-2.1-or-later * diff --git a/level_0/f_network/tests/unit/c/test-network-from_ip_string.c b/level_0/f_network/tests/unit/c/test-network-from_ip_string.c new file mode 100644 index 0000000..a0bd722 --- /dev/null +++ b/level_0/f_network/tests/unit/c/test-network-from_ip_string.c @@ -0,0 +1,81 @@ +#include "test-network.h" +#include "test-network-from_ip_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_network_from_ip_string__fails(void **state) { + + int errnos[] = { + EAFNOSUPPORT, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_support_not, + F_failure, + }; + + for (uint8_t i = 0; i < 2; ++i) { + + f_network_family_ip_t family = f_network_family_ip_t_initialize; + + will_return(__wrap_inet_pton, true); + will_return(__wrap_inet_pton, errnos[i]); + + const f_status_t status = f_network_from_ip_string(f_string_empty_s, &family); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_network_from_ip_string__parameter_checking(void **state) { + + { + const f_status_t status = f_network_from_ip_string(f_string_empty_s, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_network_from_ip_string__returns_data_not(void **state) { + + f_network_family_ip_t family = f_network_family_ip_t_initialize; + + const f_string_static_t ip = macro_f_string_static_t_initialize_1("127.0.0.1", 0, 9); + + { + const f_status_t status = f_network_from_ip_string(ip, &family); + + assert_int_equal(status, F_data_not); + } + + family.type = f_network_family_ip_4_e; + + { + const f_status_t status = f_network_from_ip_string(f_string_empty_s, &family); + + assert_int_equal(status, F_data_not); + } +} + +void test__f_network_from_ip_string__works(void **state) { + + f_network_family_ip_t family = f_network_family_ip_t_initialize; + family.type = f_network_family_ip_4_e; + + const f_string_static_t ip = macro_f_string_static_t_initialize_1("127.0.0.1", 0, 9); + + { + will_return(__wrap_inet_pton, false); + + const f_status_t status = f_network_from_ip_string(ip, &family); + + assert_int_equal(status, F_none); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_network/tests/unit/c/test-network-from_ip_string.h b/level_0/f_network/tests/unit/c/test-network-from_ip_string.h new file mode 100644 index 0000000..cbcbf3f --- /dev/null +++ b/level_0/f_network/tests/unit/c/test-network-from_ip_string.h @@ -0,0 +1,41 @@ +/** + * FLL - Level 0 + * + * Project: Network + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the network project. + */ +#ifndef _TEST__F_network_from_ip_string_h +#define _TEST__F_network_from_ip_string_h + +/** + * Test that function fails. + * + * @see f_network_from_ip_string() + */ +extern void test__f_network_from_ip_string__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_network_from_ip_string() + */ +extern void test__f_network_from_ip_string__parameter_checking(void **state); + +/** + * Test that function works but the string is empty or the address.type is 0. + * + * @see f_network_from_ip_string() + */ +extern void test__f_network_from_ip_string__returns_data_not(void **state); + +/** + * Test that function works. + * + * @see f_network_from_ip_string() + */ +extern void test__f_network_from_ip_string__works(void **state); + +#endif // _TEST__F_network_from_ip_string_h diff --git a/level_0/f_network/tests/unit/c/test-network-to_ip_string.c b/level_0/f_network/tests/unit/c/test-network-to_ip_string.c new file mode 100644 index 0000000..218c7f2 --- /dev/null +++ b/level_0/f_network/tests/unit/c/test-network-to_ip_string.c @@ -0,0 +1,89 @@ +#include "test-network.h" +#include "test-network-to_ip_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_network_to_ip_string__fails(void **state) { + + f_network_family_ip_t family = f_network_family_ip_t_initialize; + f_string_dynamic_t ip = f_string_dynamic_t_initialize; + + int errnos[] = { + EAFNOSUPPORT, + ENOSPC, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_support_not, + F_space_not, + F_failure, + }; + + for (uint8_t i = 0; i < 3; ++i) { + + will_return(__wrap_inet_pton, true); + will_return(__wrap_inet_pton, errnos[i]); + + const f_status_t status = f_network_to_ip_string(family, &ip); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + + free(ip.string); +} + +void test__f_network_to_ip_string__parameter_checking(void **state) { + + f_network_family_ip_t family = f_network_family_ip_t_initialize; + + { + const f_status_t status = f_network_to_ip_string(family, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_network_to_ip_string__returns_data_not(void **state) { + + f_network_family_ip_t family = f_network_family_ip_t_initialize; + f_string_dynamic_t ip = f_string_dynamic_t_initialize; + + { + const f_status_t status = f_network_to_ip_string(family, &ip); + + assert_int_equal(status, F_data_not); + } + + free(ip.string); +} + +void test__f_network_to_ip_string__works(void **state) { + + f_network_family_ip_t family = f_network_family_ip_t_initialize; + family.type = f_network_family_ip_4_e; + + f_string_dynamic_t ip = f_string_dynamic_t_initialize; + + const f_string_static_t expect = macro_f_string_static_t_initialize_1("127.0.0.1", 0, 9); + + { + will_return(__wrap_inet_ntop, false); + will_return(__wrap_inet_ntop, expect.string); + will_return(__wrap_inet_ntop, expect.used); + + const f_status_t status = f_network_to_ip_string(family, &ip); + + assert_int_equal(status, F_none); + assert_int_equal(ip.used, expect.used); + assert_string_equal(ip.string, expect.string); + } + + free(ip.string); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_network/tests/unit/c/test-network-to_ip_string.h b/level_0/f_network/tests/unit/c/test-network-to_ip_string.h new file mode 100644 index 0000000..3c42946 --- /dev/null +++ b/level_0/f_network/tests/unit/c/test-network-to_ip_string.h @@ -0,0 +1,41 @@ +/** + * FLL - Level 0 + * + * Project: Network + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the network project. + */ +#ifndef _TEST__F_network_to_ip_string_h +#define _TEST__F_network_to_ip_string_h + +/** + * Test that function fails. + * + * @see f_network_to_ip_string() + */ +extern void test__f_network_to_ip_string__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_network_to_ip_string() + */ +extern void test__f_network_to_ip_string__parameter_checking(void **state); + +/** + * Test that function works but the address.type is 0. + * + * @see f_network_to_ip_string() + */ +extern void test__f_network_to_ip_string__returns_data_not(void **state); + +/** + * Test that function works. + * + * @see f_network_to_ip_string() + */ +extern void test__f_network_to_ip_string__works(void **state); + +#endif // _TEST__F_network_to_ip_string_h diff --git a/level_0/f_network/tests/unit/c/test-network.c b/level_0/f_network/tests/unit/c/test-network.c index f24759f..69b7fbe 100644 --- a/level_0/f_network/tests/unit/c/test-network.c +++ b/level_0/f_network/tests/unit/c/test-network.c @@ -19,16 +19,23 @@ int setdown(void **state) { int main(void) { const struct CMUnitTest tests[] = { + cmocka_unit_test(test__f_network_from_ip_string__returns_data_not), + cmocka_unit_test(test__f_network_to_ip_string__returns_data_not), + cmocka_unit_test(test__f_network_from_host_long__works), cmocka_unit_test(test__f_network_from_host_short__works), + cmocka_unit_test(test__f_network_from_ip_string__works), cmocka_unit_test(test__f_network_to_host_long__works), cmocka_unit_test(test__f_network_to_host_short__works), + cmocka_unit_test(test__f_network_to_ip_string__works), #ifndef _di_level_0_parameter_checking_ cmocka_unit_test(test__f_network_from_host_long__parameter_checking), cmocka_unit_test(test__f_network_from_host_short__parameter_checking), + cmocka_unit_test(test__f_network_from_ip_string__parameter_checking), cmocka_unit_test(test__f_network_to_host_long__parameter_checking), cmocka_unit_test(test__f_network_to_host_short__parameter_checking), + cmocka_unit_test(test__f_network_to_ip_string__parameter_checking), #endif // _di_level_0_parameter_checking_ }; diff --git a/level_0/f_network/tests/unit/c/test-network.h b/level_0/f_network/tests/unit/c/test-network.h index 74dcd06..36f3706 100644 --- a/level_0/f_network/tests/unit/c/test-network.h +++ b/level_0/f_network/tests/unit/c/test-network.h @@ -21,6 +21,7 @@ #include // FLL-0 includes. +#include #include // Mock includes. @@ -29,8 +30,10 @@ // Test includes. #include "test-network-from_host_long.h" #include "test-network-from_host_short.h" +#include "test-network-from_ip_string.h" #include "test-network-to_host_long.h" #include "test-network-to_host_short.h" +#include "test-network-to_ip_string.h" #ifdef __cplusplus extern "C" { -- 1.8.3.1