Change the inet_pton() and inet_ntop() function calls to use the explicit .v4 and .v6 union members.
Being explicit is much safer.
The inet_pton() function also returns zero without the errno set when the address is invalid.
Handle this case, returning F_address_not (with error bit) when zero is returned by inet_pton().
The unit tests for these functions are incorrect and are not all called (which is why their incorrectness was not previously discovered).
Make sure to use h_errno where appropriate.
Make sure the mock function for inet_pton() allows for returning zero or non-zero.
Make sure the family type is set so that the expected return codes are returned.
Make sure the ip string is set so that the expected return codes are returned.
Handle the newly added F_address_not case.
Add the missing unit test function calls:
- test__f_network_from_ip_address__fails
- test__f_network_from_ip_name__fails
- test__f_network_from_ip_string__fails
- test__f_network_to_ip_string__fails
This could use more review and testing.
Such extra review will be performed while I continue to write TacocaT.
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);
+ {
+ const int result = (to->type == f_network_family_ip_4_e)
+ ? inet_pton(AF_INET, from.string, (void *) & to->address.v4)
+ : inet_pton(AF_INET6, from.string, (void *) & to->address.v6);
- return F_status_set_error(F_failure);
+ if (result == -1) {
+ if (errno == EAFNOSUPPORT) return F_status_set_error(F_support_not);
+
+ return F_status_set_error(F_failure);
+ }
+ else if (result) {
+ return F_okay;
+ }
}
- return F_okay;
+ return F_status_set_error(F_address_not);
}
#endif // _di_f_network_from_ip_string_
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);
+ {
+ const char * const result = (from.type == f_network_family_ip_4_e)
+ ? inet_ntop(AF_INET, (void *) & from.address.v4, to->string + to->used, INET_ADDRSTRLEN)
+ : inet_ntop(AF_INET6, (void *) & from.address.v6, to->string + to->used, INET6_ADDRSTRLEN);
- return F_status_set_error(F_failure);
+ if (!result) {
+ 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]) {
* F_okay 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_address_not (with error bit) if from is not a valid address.
* 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().
const bool failure = mock_type(bool);
if (failure) {
- errno = mock_type(int);
+ h_errno = mock_type(int);
return 0;
}
const bool failure = mock_type(bool);
if (failure) {
- errno = mock_type(int);
+ h_errno = mock_type(int);
return 0;
}
return -1;
}
- return 0;
+ return mock_type(int);
}
#ifdef __cplusplus
F_failure,
};
+ int types[] = {
+ f_network_family_ip_4_e,
+ f_network_family_ip_6_e,
+ };
+
for (uint8_t i = 0; i < 6; ++i) {
- struct hostent host;
+ for (uint8_t j = 0; j < 2; ++j) {
- will_return(__wrap_gethostbyaddr, true);
- will_return(__wrap_gethostbyaddr, errnos[i]);
+ family.type = types[j];
- const f_status_t status = f_network_from_ip_address(family, &host);
+ struct hostent host;
+
+ will_return(__wrap_gethostbyaddr, true);
+ will_return(__wrap_gethostbyaddr, errnos[i]);
+
+ const f_status_t status = f_network_from_ip_address(family, &host);
- assert_int_equal(status, F_status_set_error(statuss[i]));
+ assert_int_equal(status, F_status_set_error(statuss[i]));
+ } // for
} // for
}
void test__f_network_from_ip_name__fails(void **state) {
+ const f_string_static_t ip = macro_f_string_static_t_initialize_1("localhost", 0, 9);
+
int errnos[] = {
HOST_NOT_FOUND,
NO_DATA,
will_return(__wrap_gethostbyname, true);
will_return(__wrap_gethostbyname, errnos[i]);
- const f_status_t status = f_network_from_ip_name(f_string_empty_s, &host);
+ const f_status_t status = f_network_from_ip_name(ip, &host);
assert_int_equal(status, F_status_set_error(statuss[i]));
} // for
void test__f_network_from_ip_string__fails(void **state) {
+ const f_string_static_t ip = macro_f_string_static_t_initialize_1("127.0.0.1", 0, 9);
+
int errnos[] = {
EAFNOSUPPORT,
mock_errno_generic,
f_network_family_ip_t family = f_network_family_ip_t_initialize;
+ family.type = f_network_family_ip_4_e;
+
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);
+ const f_status_t status = f_network_from_ip_string(ip, &family);
assert_int_equal(status, F_status_set_error(statuss[i]));
} // for
+
+ // Should return F_address_not (with error bit) for when non-errno return result of inet_pton() is 0.
+ {
+ f_network_family_ip_t family = f_network_family_ip_t_initialize;
+
+ family.type = f_network_family_ip_4_e;
+
+ will_return(__wrap_inet_pton, false);
+ will_return(__wrap_inet_pton, 0);
+
+ const f_status_t status = f_network_from_ip_string(ip, &family);
+
+ assert_int_equal(status, F_status_set_error(F_address_not));
+ }
}
void test__f_network_from_ip_string__parameter_checking(void **state) {
{
will_return(__wrap_inet_pton, false);
+ will_return(__wrap_inet_pton, 1);
const f_status_t status = f_network_from_ip_string(ip, &family);
{
will_return(__wrap_inet_pton, false);
+ will_return(__wrap_inet_pton, 1);
const f_status_t status = f_network_from_ip_string(ip, &family);
F_failure,
};
+ int types[] = {
+ f_network_family_ip_4_e,
+ f_network_family_ip_6_e,
+ };
+
for (uint8_t i = 0; i < 3; ++i) {
- will_return(__wrap_inet_pton, true);
- will_return(__wrap_inet_pton, errnos[i]);
+ for (uint8_t j = 0; j < 2; ++j) {
- const f_status_t status = f_network_to_ip_string(family, &ip);
+ family.type = types[j];
+
+ will_return(__wrap_inet_ntop, true);
+ will_return(__wrap_inet_ntop, errnos[i]);
+
+ const f_status_t status = f_network_to_ip_string(family, &ip);
- assert_int_equal(status, F_status_set_error(statuss[i]));
+ assert_int_equal(status, F_status_set_error(statuss[i]));
+ } // for
} // for
free(ip.string);
int setdown(void **state) {
errno = 0;
+ h_errno = 0;
return 0;
}
int main(void) {
const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test__f_network_from_ip_address__fails),
+ cmocka_unit_test(test__f_network_from_ip_name__fails),
+ cmocka_unit_test(test__f_network_from_ip_string__fails),
+ cmocka_unit_test(test__f_network_to_ip_string__fails),
+
cmocka_unit_test(test__f_network_from_ip_address__returns_data_not),
cmocka_unit_test(test__f_network_from_ip_name__returns_data_not),
cmocka_unit_test(test__f_network_from_ip_string__returns_data_not),