From: Kevin Day Date: Sat, 24 Jun 2023 03:08:45 +0000 (-0500) Subject: Feature: Add additional network and socket related functions. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=22a1cb6f8bb440ddf7fb597757daf2d83a834d3d;p=fll Feature: Add additional network and socket related functions. Add the following: - f_file_poll() for poll(). - f_socket_read_stream() for recv(). - f_socket_write_stream() for send(). Add f_poll_t, f_polls_t, and f_pollss_t typedefs. This adds the appropriate array management functions. To be consistent with type_file.h a new type_array_file.h is created to manage these. Update the existing f_signal_read() to use the new typdef f_poll_t. This includes unit tests as appropriate. --- diff --git a/build/monolithic/settings b/build/monolithic/settings index a0e42b8..de210d7 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 network/common.h +build_sources_headers level_0/network.h level_0/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_file/c/file.c b/level_0/f_file/c/file.c index f845275..dd5d4d2 100644 --- a/level_0/f_file/c/file.c +++ b/level_0/f_file/c/file.c @@ -1578,6 +1578,26 @@ extern "C" { } #endif // _di_f_file_owner_read_ +#ifndef _di_f_file_poll_ + f_status_t f_file_poll(const f_polls_t polls, const int timeout) { + + if (!polls.used) return F_data_not; + + const int result = poll(polls.array, (nfds_t) polls.used, timeout); + + if (result == -1) { + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return result ? F_none : F_time_out; + } +#endif // _di_f_file_poll_ + #ifndef _di_f_file_read_ f_status_t f_file_read(const f_file_t file, f_string_dynamic_t * const buffer) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_file/c/file.h b/level_0/f_file/c/file.h index b770f84..261fc5e 100644 --- a/level_0/f_file/c/file.h +++ b/level_0/f_file/c/file.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1536,6 +1537,47 @@ extern "C" { #endif // _di_f_file_owner_read_ /** + * Perform poll on the one of more file descriptors. + * + * This is a general wrapper around poll. + * For more specialized use cases look at f_signal_read(). + * + * This does not check the revent codes in the polls array. + * + * @todo There also needs to be a ppoll function like this, f_file_poll_lock() perhaps. + * + * @param polls + * An array of polls representing all file descriptors to poll at once. + * + * Warning: The max array length for used is limited to nfds_t which might be different from f_number_unsigned_t. + * The nfds_t is often either uint32_t or an uint64_t. + * The f_number_unsigned_t is often an uint64_t. + * + * When a file descriptor (polls.array[].fd) is set to -1, then the file descriptor is ignored and the return events (polls.array[].revents) is set to 0. + * @param timeout + * The number of milliseconds that the poll will block, waiting for a file descriptor. + * Once time out is reach, then this will unblock and return. + * + * A value of 0 results in immediate return. + * + * @return + * F_none on success. + * F_data_not if polls.used is 0. + * F_time_out if time out is reached befoe a signal is received. + * + * F_buffer (with error bit) if the buffer is invalid. + * F_interrupt (with error bit) if interrupt was received. + * F_memory_not (with error bit) if out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) for any other error. + * + * @see poll() + */ +#ifndef _di_f_file_poll_ + extern f_status_t f_file_poll(const f_polls_t polls, const int timeout); +#endif // _di_f_file_poll_ + +/** * Read until EOF is reached. * * To determine how much was read into the buffer, record buffer->used before execution and compare to buffer->used after execution. diff --git a/level_0/f_file/data/build/settings-mocks b/level_0/f_file/data/build/settings-mocks index 849f9fb..aeae42c 100644 --- a/level_0/f_file/data/build/settings-mocks +++ b/level_0/f_file/data/build/settings-mocks @@ -97,6 +97,7 @@ flags -Wl,--wrap=mkfifo flags -Wl,--wrap=mkfifoat flags -Wl,--wrap=mknod flags -Wl,--wrap=mknodat +flags -Wl,--wrap=poll flags -Wl,--wrap=open flags -Wl,--wrap=openat flags -Wl,--wrap=read diff --git a/level_0/f_file/data/build/settings-tests b/level_0/f_file/data/build/settings-tests index b49d8a7..b604c83 100644 --- a/level_0/f_file/data/build/settings-tests +++ b/level_0/f_file/data/build/settings-tests @@ -25,7 +25,7 @@ build_language c build_libraries -lc -lcmocka build_libraries-individual -lf_memory -lf_string -lf_file -build_sources_program test-file-access.c test-file-access_at.c test-file-clone.c test-file-close.c test-file-copy.c test-file-create.c test-file-create_at.c test-file-create_device.c test-file-create_device_at.c test-file-create_fifo.c test-file-create_fifo_at.c test-file-create_node.c test-file-create_node_at.c test-file-descriptor.c test-file-exists.c test-file-exists_at.c test-file-flush.c test-file-group_read.c test-file-is.c test-file-is_at.c test-file-is_stat.c test-file-link.c test-file-link_at.c test-file-link_hard.c test-file-link_hard_at.c test-file-link_read.c test-file-link_read_at.c test-file-manipulate.c test-file-mode_determine.c test-file-mode_from_string.c test-file-mode_read.c test-file-mode_read_at.c test-file-mode_set.c test-file-mode_set_at.c test-file-mode_to_mode.c test-file-name_base.c test-file-name_directory.c test-file-open.c test-file-open_at.c test-file-owner_read.c test-file-read.c test-file-read_block.c test-file-read_until.c test-file-remove.c test-file-remove_at.c test-file-rename.c test-file-rename_at.c test-file-role_change.c test-file-role_change_at.c test-file-seek.c test-file-size.c test-file-size_at.c test-file-size_by_id.c test-file-stat.c test-file-stat_at.c test-file-stat_by_id.c test-file-stream_close.c test-file-stream_open_descriptor.c test-file-stream_open.c test-file-stream_read.c test-file-stream_read_block.c test-file-stream_read_until.c test-file-stream_reopen.c test-file-stream_write.c test-file-stream_write_block.c test-file-stream_write_until.c test-file-stream_write_range.c test-file-touch.c test-file-touch_at.c test-file-type.c test-file-type_at.c test-file-umask_get.c test-file-umask_set.c test-file-write.c test-file-write_block.c test-file-write_until.c test-file-write_range.c +build_sources_program test-file-access.c test-file-access_at.c test-file-clone.c test-file-close.c test-file-copy.c test-file-create.c test-file-create_at.c test-file-create_device.c test-file-create_device_at.c test-file-create_fifo.c test-file-create_fifo_at.c test-file-create_node.c test-file-create_node_at.c test-file-descriptor.c test-file-exists.c test-file-exists_at.c test-file-flush.c test-file-group_read.c test-file-is.c test-file-is_at.c test-file-is_stat.c test-file-link.c test-file-link_at.c test-file-link_hard.c test-file-link_hard_at.c test-file-link_read.c test-file-link_read_at.c test-file-manipulate.c test-file-mode_determine.c test-file-mode_from_string.c test-file-mode_read.c test-file-mode_read_at.c test-file-mode_set.c test-file-mode_set_at.c test-file-mode_to_mode.c test-file-name_base.c test-file-name_directory.c test-file-open.c test-file-open_at.c test-file-owner_read.c test-file-read.c test-file-read_block.c test-file-read_until.c test-file-remove.c test-file-remove_at.c test-file-rename.c test-file-rename_at.c test-file-role_change.c test-file-role_change_at.c test-file-poll.c test-file-seek.c test-file-size.c test-file-size_at.c test-file-size_by_id.c test-file-stat.c test-file-stat_at.c test-file-stat_by_id.c test-file-stream_close.c test-file-stream_open_descriptor.c test-file-stream_open.c test-file-stream_read.c test-file-stream_read_block.c test-file-stream_read_until.c test-file-stream_reopen.c test-file-stream_write.c test-file-stream_write_block.c test-file-stream_write_until.c test-file-stream_write_range.c test-file-touch.c test-file-touch_at.c test-file-type.c test-file-type_at.c test-file-umask_get.c test-file-umask_set.c test-file-write.c test-file-write_block.c test-file-write_until.c test-file-write_range.c build_sources_program test-file.c build_script no diff --git a/level_0/f_file/tests/unit/c/mock-file.c b/level_0/f_file/tests/unit/c/mock-file.c index 1aa8aba..8069930 100644 --- a/level_0/f_file/tests/unit/c/mock-file.c +++ b/level_0/f_file/tests/unit/c/mock-file.c @@ -494,6 +494,21 @@ int __wrap_openat(int dirfd, const char *pathname, int flags, mode_t mode) { return mock_type(int); } +int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + fds->revents = mock_type(short); + + return mock_type(int); +} + ssize_t __wrap_read(int fd, void *buf, size_t count) { const bool failure = mock_type(bool); diff --git a/level_0/f_file/tests/unit/c/mock-file.h b/level_0/f_file/tests/unit/c/mock-file.h index 7b876f9..76c8fb9 100644 --- a/level_0/f_file/tests/unit/c/mock-file.h +++ b/level_0/f_file/tests/unit/c/mock-file.h @@ -66,6 +66,7 @@ extern int __wrap_mknod(const char *pathname, mode_t mode, dev_t dev); extern int __wrap_mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev); extern int __wrap_open(const char *pathname, int flags, mode_t mode); extern int __wrap_openat(int dirfd, const char *pathname, int flags, mode_t mode); +extern int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout); extern ssize_t __wrap_read(int fd, void *buf, size_t count); extern ssize_t __wrap_readlink(const char *pathname, char *buf, size_t bufsiz); extern ssize_t __wrap_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); diff --git a/level_0/f_file/tests/unit/c/test-file-poll.c b/level_0/f_file/tests/unit/c/test-file-poll.c new file mode 100644 index 0000000..60c72d9 --- /dev/null +++ b/level_0/f_file/tests/unit/c/test-file-poll.c @@ -0,0 +1,78 @@ +#include "test-file.h" +#include "test-file-poll.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_file_poll__fails(void **state) { + + { + int errnos[] = { + EFAULT, + EINTR, + EINVAL, + ENOMEM, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_buffer, + F_interrupt, + F_parameter, + F_memory_not, + F_failure, + }; + + f_polls_t polls = f_polls_t_initialize; + polls.used = 1; + + for (int i = 0; i < 5; ++i) { + + will_return(__wrap_poll, true); + will_return(__wrap_poll, errnos[i]); + + const f_status_t status = f_file_poll(polls, 0); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_file_poll__returns_data_not(void **state) { + + f_polls_t polls = f_polls_t_initialize; + + { + const f_status_t status = f_file_poll(polls, 0); + + assert_int_equal(status, F_data_not); + } +} + +void test__f_file_poll__works(void **state) { + + { + const int fd = 0; + const int total = 1; + const short revents = 5; + + f_poll_t poll = macro_f_poll_t_initialize_1(fd, 1, 2); + f_polls_t polls = macro_f_polls_t_initialize_1(&poll, 0, 1); + + will_return(__wrap_poll, false); + will_return(__wrap_poll, revents); + will_return(__wrap_poll, total); + + const f_status_t status = f_file_poll(polls, 0); + + assert_int_equal(status, F_none); + assert_int_equal(poll.fd, fd); + assert_int_equal(poll.events, total); + assert_int_equal(poll.revents, revents); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_file/tests/unit/c/test-file-poll.h b/level_0/f_file/tests/unit/c/test-file-poll.h new file mode 100644 index 0000000..ac53fec --- /dev/null +++ b/level_0/f_file/tests/unit/c/test-file-poll.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: File + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the file project. + */ +#ifndef _TEST__F_file_poll_h +#define _TEST__F_file_poll_h + +/** + * Test that function fails. + * + * @see f_file_poll() + */ +extern void test__f_file_poll__fails(void **state); + +/** + * Test that function works but the path is empty. + * + * @see f_file_poll() + */ +extern void test__f_file_poll__returns_data_not(void **state); + +/** + * Test that function works. + * + * @see f_file_poll() + */ +extern void test__f_file_poll__works(void **state); + +#endif // _TEST__F_file_poll_h diff --git a/level_0/f_file/tests/unit/c/test-file.c b/level_0/f_file/tests/unit/c/test-file.c index e74a43d..55058f2 100644 --- a/level_0/f_file/tests/unit/c/test-file.c +++ b/level_0/f_file/tests/unit/c/test-file.c @@ -210,6 +210,10 @@ int main(void) { cmocka_unit_test(test__f_file_owner_read__returns_data_not), cmocka_unit_test(test__f_file_owner_read__works), + cmocka_unit_test(test__f_file_poll__fails), + cmocka_unit_test(test__f_file_poll__returns_data_not), + cmocka_unit_test(test__f_file_poll__works), + cmocka_unit_test(test__f_file_read__fails), cmocka_unit_test(test__f_file_read__returns_file_descriptor_not), cmocka_unit_test(test__f_file_read__works), @@ -414,6 +418,7 @@ int main(void) { cmocka_unit_test(test__f_file_open__parameter_checking), cmocka_unit_test(test__f_file_open_at__parameter_checking), cmocka_unit_test(test__f_file_owner_read__parameter_checking), + // f_file_poll() doesn't use parameter checking. cmocka_unit_test(test__f_file_read__parameter_checking), cmocka_unit_test(test__f_file_read_block__parameter_checking), cmocka_unit_test(test__f_file_read_until__parameter_checking), diff --git a/level_0/f_file/tests/unit/c/test-file.h b/level_0/f_file/tests/unit/c/test-file.h index 142c0d5..0636fc5 100644 --- a/level_0/f_file/tests/unit/c/test-file.h +++ b/level_0/f_file/tests/unit/c/test-file.h @@ -66,6 +66,7 @@ #include "test-file-open.h" #include "test-file-open_at.h" #include "test-file-owner_read.h" +#include "test-file-poll.h" #include "test-file-read.h" #include "test-file-read_block.h" #include "test-file-read_until.h" diff --git a/level_0/f_signal/c/signal.c b/level_0/f_signal/c/signal.c index bc91470..f05c93d 100644 --- a/level_0/f_signal/c/signal.c +++ b/level_0/f_signal/c/signal.c @@ -119,11 +119,7 @@ extern "C" { if (!information) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - struct pollfd data_poll; - memset(&data_poll, 0, sizeof(struct pollfd)); - - data_poll.fd = signal.id; - data_poll.events = POLLIN; + f_poll_t data_poll = macro_f_poll_t_initialize_2(signal.id, POLLIN); const int result = poll(&data_poll, 1, timeout); @@ -137,17 +133,9 @@ extern "C" { } if (result) { - if (data_poll.revents & POLLNVAL) { - return F_status_set_error(F_parameter); - } - - if (data_poll.revents & POLLHUP) { - return F_status_set_error(F_file_closed); - } - - if (data_poll.revents & POLLERR) { - return F_status_set_error(F_stream); - } + if (data_poll.revents & POLLNVAL) return F_status_set_error(F_parameter); + if (data_poll.revents & POLLHUP) return F_status_set_error(F_file_closed); + if (data_poll.revents & POLLERR) return F_status_set_error(F_stream); if (data_poll.revents & POLLIN) { const ssize_t total = read(signal.id, information, sizeof(struct signalfd_siginfo)); diff --git a/level_0/f_signal/c/signal.h b/level_0/f_signal/c/signal.h index f78a97b..0c92ffd 100644 --- a/level_0/f_signal/c/signal.h +++ b/level_0/f_signal/c/signal.h @@ -19,6 +19,7 @@ // FLL-0 includes. #include +#include #include // FLL-0 signal includes. @@ -177,6 +178,10 @@ extern "C" { /** * Read a current process signal, if one exists. * + * For a more generalized call to poll() look at f_file_poll(). + * + * @todo This may be better suited for calling ppoll() instead of poll(). + * * @param signal * The signal settings. * @param timeout diff --git a/level_0/f_signal/tests/unit/c/mock-signal.h b/level_0/f_signal/tests/unit/c/mock-signal.h index 656f411..df56322 100644 --- a/level_0/f_signal/tests/unit/c/mock-signal.h +++ b/level_0/f_signal/tests/unit/c/mock-signal.h @@ -1,7 +1,7 @@ /** * FLL - Level 0 * - * Project: Account + * Project: Signal * API Version: 0.7 * Licenses: lgpl-2.1-or-later * diff --git a/level_0/f_signal/tests/unit/c/test-signal.h b/level_0/f_signal/tests/unit/c/test-signal.h index 96a77d3..2137074 100644 --- a/level_0/f_signal/tests/unit/c/test-signal.h +++ b/level_0/f_signal/tests/unit/c/test-signal.h @@ -1,7 +1,7 @@ /** * FLL - Level 0 * - * Project: Account + * Project: Signal * API Version: 0.7 * Licenses: lgpl-2.1-or-later * diff --git a/level_0/f_socket/c/socket.c b/level_0/f_socket/c/socket.c index 1e95ee9..72935d6 100644 --- a/level_0/f_socket/c/socket.c +++ b/level_0/f_socket/c/socket.c @@ -444,6 +444,45 @@ extern "C" { } #endif // _di_f_socket_read_message_ +#ifndef _di_f_socket_read_stream_ + f_status_t f_socket_read_stream(f_socket_t * const socket, const int flags, void * const buffer, size_t * const length) { + #ifndef _di_level_0_parameter_checking_ + if (!socket) return F_status_set_error(F_parameter); + if (!buffer) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const ssize_t result = recv(socket->id, buffer, socket->size_read, flags); + + if (result < 0) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EALREADY) return F_status_set_error(F_complete_not); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == ECONNREFUSED) return F_status_set_error(F_connect_refuse); + if (errno == ECONNRESET) return F_status_set_error(F_connect_reset); + if (errno == EDESTADDRREQ) return F_status_set_error(F_address_not); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ENOMEM) return F_status_set_error(F_memory_not); + if (errno == ENOTCONN) return F_status_set_error(F_connect_not); + if (errno == ENOTSOCK) return F_status_set_error(F_socket_not); + if (errno == EOPNOTSUPP) return F_status_set_error(F_option_not); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EPIPE) return F_status_set_error(F_pipe); + if (errno == ETIMEDOUT) return F_status_set_error(F_time_out); + + return F_status_set_error(F_failure); + } + + if (length) { + *length = (size_t) result; + } + + return F_none; + } +#endif // _di_f_socket_read_stream_ + #ifndef _di_f_socket_write_ f_status_t f_socket_write(f_socket_t * const socket, const int flags, void * const buffer, size_t * const length) { #ifndef _di_level_0_parameter_checking_ @@ -528,6 +567,48 @@ extern "C" { } #endif // _di_f_socket_write_message_ +#ifndef _di_f_socket_write_stream_ + f_status_t f_socket_write_stream(f_socket_t * const socket, const int flags, void * const buffer, size_t * const length) { + #ifndef _di_level_0_parameter_checking_ + if (!socket) return F_status_set_error(F_parameter); + if (!buffer) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const ssize_t result = send(socket->id, buffer, socket->size_write, flags); + + if (result < 0) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EAGAIN || errno == EWOULDBLOCK) return F_status_set_error(F_block); + if (errno == EALREADY) return F_status_set_error(F_complete_not); + if (errno == EBADF) return F_status_set_error(F_file_descriptor); + if (errno == ECONNREFUSED) return F_status_set_error(F_connect_refuse); + if (errno == ECONNRESET) return F_status_set_error(F_connect_reset); + if (errno == EDESTADDRREQ) return F_status_set_error(F_address_not); + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EISCONN) return F_status_set_error(F_connect); + if (errno == EMSGSIZE) return F_status_set_error(F_size); + if (errno == ENOBUFS) return F_status_set_error(F_buffer_not); + if (errno == ENOMEM) return F_status_set_error(F_memory_not); + if (errno == ENOTCONN) return F_status_set_error(F_connect_not); + if (errno == ENOTSOCK) return F_status_set_error(F_socket_not); + if (errno == EOPNOTSUPP) return F_status_set_error(F_option_not); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == EPIPE) return F_status_set_error(F_pipe); + if (errno == ETIMEDOUT) return F_status_set_error(F_time_out); + + return F_status_set_error(F_failure); + } + + if (length) { + *length = (size_t) result; + } + + return F_none; + } +#endif // _di_f_socket_write_stream_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_socket/c/socket.h b/level_0/f_socket/c/socket.h index 3ee54b0..103f5c6 100644 --- a/level_0/f_socket/c/socket.h +++ b/level_0/f_socket/c/socket.h @@ -462,6 +462,8 @@ extern "C" { /** * Read from a socket. * + * This is the recommneded way to read UDP streams. + * * @param socket * The socket structure. * The socket.id must represent a valid socket file descriptor. @@ -548,8 +550,57 @@ extern "C" { #endif // _di_f_socket_read_message_ /** + * Read from a socket stream. + * + * This is the recommneded way to read TCP streams. + * + * @param socket + * The socket structure. + * The socket.id must represent a valid socket file descriptor. + * The socket.size_read is used to represent the buffer size in buffer and must not be larger than the actual size of the buffer. + * @param flags + * Read flags. + * @param buffer + * The buffer to populate. + * @param length + * (optional) The length of the buffer. + * This gets replaced with the value of a positive ssize_t representing the length read. + * Data may be lost if the amount of data read is larger than given buffer length. + * Set to NULL to not use. + * + * @return + * F_none on success. + * + * F_access_denied (with error bit) on access denied. + * F_complete_not (with error bit) if an existing connection is not yet complete. + * F_connect_not (with error bit) if the socket is not connected. + * F_connect_refuse (with error bit) if connection is refused. + * F_connect_reset (with error bit) if connection is reset. + * F_block (with error bit) if socket is blocked. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_descriptor (with error bit) if id is an invalid descriptor. + * F_interrupt (with error bit) if interrupt is received. + * F_memory_not (with error bit) if out of memory. + * F_option_not (with error bit) if a flag is not supported. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received. + * F_prohibited (with error bit) if the insufficient privileges to perform read. + * F_socket_not (with error bit) if the id is not a socket descriptor. + * F_time_out (with error bit) if a timeout occurred. + * + * F_failure (with error bit) for any other error. + * + * @see recv() + */ +#ifndef _di_f_socket_read_stream_ + extern f_status_t f_socket_read_stream(f_socket_t * const socket, const int flags, void * const buffer, size_t * const length); +#endif // _di_f_socket_read_stream_ + +/** * Send to a socket. * + * This is the recommneded way to write UDP streams. + * * @param socket * The socket structure. * The socket.id must represent a valid socket file descriptor. @@ -643,6 +694,57 @@ extern "C" { extern f_status_t f_socket_write_message(f_socket_t * const socket, const int flags, struct msghdr * const header, size_t * const length); #endif // _di_f_socket_write_message_ +/** + * Send to a socket. + * + * This is the recommneded way to write TCP streams. + * + * @param socket + * The socket structure. + * The socket.id must represent a valid socket file descriptor. + * The socket.size_write is used to represent the buffer size in buffer and must not be larger than the actual size of the buffer. + * @param flags + * Read flags. + * @param buffer + * The buffer to populate. + * @param length + * (optional) The length of the buffer. + * This gets replaced with the value of a positive ssize_t representing the length send. + * Data may be lost if the amount of data send is larger than given buffer length. + * Set to NULL to not use. + * + * @return + * F_none on success. + * + * F_access_denied (with error bit) on access denied. + * F_address_not (with error bit) if no address is provided and the connection is not "connection-mode". + * F_buffer_not (with error bit) if unable to send message because output buffer is full. + * F_complete_not (with error bit) if an existing connection is not yet complete. + * F_connect (with error bit) if an address is provided and the connection is "connection-mode". + * F_connect_not (with error bit) if the socket is not connected. + * F_connect_refuse (with error bit) if connection is refused. + * F_connect_reset (with error bit) if connection is reset. + * F_block (with error bit) if socket is blocked. + * F_buffer (with error bit) if the buffer is invalid. + * F_file_descriptor (with error bit) if id is an invalid descriptor. + * F_interrupt (with error bit) if interrupt is received. + * F_memory_not (with error bit) if out of memory. + * F_option_not (with error bit) if a flag is not supported. + * F_parameter (with error bit) if a parameter is invalid. + * F_pipe (with error bit) if the local end of a connection oriented socket is closed or SIGPIPE is received. + * F_prohibited (with error bit) if the insufficient privileges to perform send. + * F_size (with error bit) if size of message makes atomically sending message impossible on a socket type that requires this to be atomic. + * F_socket_not (with error bit) if the id is not a socket descriptor. + * F_time_out (with error bit) if a timeout occurred. + * + * F_failure (with error bit) for any other error. + * + * @see send() + */ +#ifndef _di_f_socket_write_stream_ + extern f_status_t f_socket_write_stream(f_socket_t * const socket, const int flags, void * const buffer, size_t * const length); +#endif // _di_f_socket_write_stream_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_socket/data/build/settings-mocks b/level_0/f_socket/data/build/settings-mocks index 77979cf..6d0eda7 100644 --- a/level_0/f_socket/data/build/settings-mocks +++ b/level_0/f_socket/data/build/settings-mocks @@ -69,8 +69,10 @@ flags -Wl,--wrap=getsockopt flags -Wl,--wrap=listen flags -Wl,--wrap=gethostname flags -Wl,--wrap=getpeername +flags -Wl,--wrap=recv flags -Wl,--wrap=recvfrom flags -Wl,--wrap=recvmsg +flags -Wl,--wrap=send flags -Wl,--wrap=sendmsg flags -Wl,--wrap=sendto flags -Wl,--wrap=setsockopt diff --git a/level_0/f_socket/data/build/settings-tests b/level_0/f_socket/data/build/settings-tests index 19b0f34..8c11dc5 100644 --- a/level_0/f_socket/data/build/settings-tests +++ b/level_0/f_socket/data/build/settings-tests @@ -25,7 +25,7 @@ build_language c build_libraries -lc -lcmocka build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_socket -build_sources_program test-socket-accept.c test-socket-bind.c test-socket-bind_local.c test-socket-connect.c test-socket-create.c test-socket-create_pair.c test-socket-disconnect.c test-socket-listen.c test-socket-name_host.c test-socket-name_peer.c test-socket-option_get.c test-socket-option_set.c test-socket-read.c test-socket-read_message.c test-socket-write.c test-socket-write_message.c +build_sources_program test-socket-accept.c test-socket-bind.c test-socket-bind_local.c test-socket-connect.c test-socket-create.c test-socket-create_pair.c test-socket-disconnect.c test-socket-listen.c test-socket-name_host.c test-socket-name_peer.c test-socket-option_get.c test-socket-option_set.c test-socket-read.c test-socket-read_message.c test-socket-read_stream.c test-socket-write.c test-socket-write_message.c test-socket-write_stream.c build_sources_program test-socket.c build_script no diff --git a/level_0/f_socket/tests/unit/c/mock-socket.c b/level_0/f_socket/tests/unit/c/mock-socket.c index ea3dbf3..efe49b8 100644 --- a/level_0/f_socket/tests/unit/c/mock-socket.c +++ b/level_0/f_socket/tests/unit/c/mock-socket.c @@ -108,6 +108,19 @@ int __wrap_listen(int sockfd, int backlog) { return 0; } +ssize_t __wrap_recv(int sockfd, void *buf, size_t len, int flags) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return mock_type(int); +} + ssize_t __wrap_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { const bool failure = mock_type(bool); @@ -134,6 +147,19 @@ ssize_t __wrap_recvmsg(int sockfd, struct msghdr *msg, int flags) { return mock_type(int); } +ssize_t __wrap_send(int sockfd, const void *buf, size_t len, int flags) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return mock_type(int); +} + ssize_t __wrap_sendmsg(int sockfd, const struct msghdr *msg, int flags) { const bool failure = mock_type(bool); diff --git a/level_0/f_socket/tests/unit/c/mock-socket.h b/level_0/f_socket/tests/unit/c/mock-socket.h index 32d2972..8cbabb7 100644 --- a/level_0/f_socket/tests/unit/c/mock-socket.h +++ b/level_0/f_socket/tests/unit/c/mock-socket.h @@ -36,8 +36,10 @@ int __wrap_gethostname(char *name, size_t len); int __wrap_getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen); int __wrap_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); int __wrap_listen(int sockfd, int backlog); +ssize_t __wrap_recv(int sockfd, void *buf, size_t len, int flags); ssize_t __wrap_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); ssize_t __wrap_recvmsg(int sockfd, struct msghdr *msg, int flags); +ssize_t __wrap_send(int sockfd, const void *buf, size_t len, int flags); ssize_t __wrap_sendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t __wrap_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); int __wrap_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); diff --git a/level_0/f_socket/tests/unit/c/test-socket-read_stream.c b/level_0/f_socket/tests/unit/c/test-socket-read_stream.c new file mode 100644 index 0000000..726ca31 --- /dev/null +++ b/level_0/f_socket/tests/unit/c/test-socket-read_stream.c @@ -0,0 +1,113 @@ +#include "test-socket.h" +#include "test-socket-read_stream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_socket_read_stream__fails(void **state) { + + f_socket_t socket = f_socket_t_initialize; + char *buffer = "test"; + size_t length = 0; + + int errnos[] = { + EACCES, + EAGAIN, + EALREADY, + EBADF, + ECONNREFUSED, + ECONNRESET, + EDESTADDRREQ, + EFAULT, + EINTR, + EINVAL, + ENOMEM, + ENOTCONN, + ENOTSOCK, + EOPNOTSUPP, + EPERM, + EPIPE, + ETIMEDOUT, + EWOULDBLOCK, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_access_denied, + F_block, + F_complete_not, + F_file_descriptor, + F_connect_refuse, + F_connect_reset, + F_address_not, + F_buffer, + F_interrupt, + F_parameter, + F_memory_not, + F_connect_not, + F_socket_not, + F_option_not, + F_prohibited, + F_pipe, + F_time_out, + F_block, + F_failure, + }; + + for (uint8_t i = 0; i < 19; ++i) { + + will_return(__wrap_recv, true); + will_return(__wrap_recv, errnos[i]); + + const f_status_t status = f_socket_read_stream(&socket, 0, (void *) buffer, &length); + + assert_int_equal(status, F_status_set_error(statuss[i])); + assert_int_equal(length, 0); + } // for +} + +void test__f_socket_read_stream__parameter_checking(void **state) { + + f_socket_t socket = f_socket_t_initialize; + char *buffer = "test"; + + { + const f_status_t status = f_socket_read_stream(0, 0, 0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_socket_read_stream(&socket, 0, 0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_socket_read_stream(0, 0, buffer, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_socket_read_stream__works(void **state) { + + f_socket_t socket = f_socket_t_initialize; + char *buffer = "test"; + size_t length = 0; + + { + will_return(__wrap_recv, false); + will_return(__wrap_recv, 1); + + const f_status_t status = f_socket_read_stream(&socket, 0, (void *) buffer, &length); + + assert_int_equal(status, F_none); + assert_int_equal(length, 1); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_socket/tests/unit/c/test-socket-read_stream.h b/level_0/f_socket/tests/unit/c/test-socket-read_stream.h new file mode 100644 index 0000000..67c3c75 --- /dev/null +++ b/level_0/f_socket/tests/unit/c/test-socket-read_stream.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Socket + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the socket project. + */ +#ifndef _TEST__F_socket_read_stream_h +#define _TEST__F_socket_read_stream_h + +/** + * Test that function fails. + * + * @see f_socket_read_stream() + */ +extern void test__f_socket_read_stream__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_socket_read_stream() + */ +extern void test__f_socket_read_stream__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_socket_read_stream() + */ +extern void test__f_socket_read_stream__works(void **state); + +#endif // _TEST__F_socket_read_stream_h diff --git a/level_0/f_socket/tests/unit/c/test-socket-write_stream.c b/level_0/f_socket/tests/unit/c/test-socket-write_stream.c new file mode 100644 index 0000000..3f71d34 --- /dev/null +++ b/level_0/f_socket/tests/unit/c/test-socket-write_stream.c @@ -0,0 +1,119 @@ +#include "test-socket.h" +#include "test-socket-write_stream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_socket_write_stream__fails(void **state) { + + f_socket_t socket = f_socket_t_initialize; + char *buffer = "test"; + size_t length = 0; + + int errnos[] = { + EACCES, + EAGAIN, + EALREADY, + EBADF, + ECONNREFUSED, + ECONNRESET, + EDESTADDRREQ, + EFAULT, + EINTR, + EINVAL, + EISCONN, + EMSGSIZE, + ENOBUFS, + ENOMEM, + ENOTCONN, + ENOTSOCK, + EOPNOTSUPP, + EPERM, + EPIPE, + ETIMEDOUT, + EWOULDBLOCK, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_access_denied, + F_block, + F_complete_not, + F_file_descriptor, + F_connect_refuse, + F_connect_reset, + F_address_not, + F_buffer, + F_interrupt, + F_parameter, + F_connect, + F_size, + F_buffer_not, + F_memory_not, + F_connect_not, + F_socket_not, + F_option_not, + F_prohibited, + F_pipe, + F_time_out, + F_block, + F_failure, + }; + + for (uint8_t i = 0; i < 22; ++i) { + + will_return(__wrap_send, true); + will_return(__wrap_send, errnos[i]); + + const f_status_t status = f_socket_write_stream(&socket, 0, buffer, &length); + + assert_int_equal(status, F_status_set_error(statuss[i])); + assert_int_equal(length, 0); + } // for +} + +void test__f_socket_write_stream__parameter_checking(void **state) { + + f_socket_t socket = f_socket_t_initialize; + char *buffer = "test"; + + { + const f_status_t status = f_socket_write_stream(0, 0, 0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_socket_write_stream(&socket, 0, 0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_socket_write_stream(0, 0, buffer, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_socket_write_stream__works(void **state) { + + f_socket_t socket = f_socket_t_initialize; + char *buffer = "test"; + size_t length = 0; + + { + will_return(__wrap_send, false); + will_return(__wrap_send, 1); + + const f_status_t status = f_socket_write_stream(&socket, 0, buffer, &length); + + assert_int_equal(status, F_none); + assert_int_equal(length, 1); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_socket/tests/unit/c/test-socket-write_stream.h b/level_0/f_socket/tests/unit/c/test-socket-write_stream.h new file mode 100644 index 0000000..5bc28e5 --- /dev/null +++ b/level_0/f_socket/tests/unit/c/test-socket-write_stream.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Socket + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the socket project. + */ +#ifndef _TEST__F_socket_write_stream_h +#define _TEST__F_socket_write_stream_h + +/** + * Test that function fails. + * + * @see f_socket_write_stream() + */ +extern void test__f_socket_write_stream__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_socket_write_stream() + */ +extern void test__f_socket_write_stream__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_socket_write_stream() + */ +extern void test__f_socket_write_stream__works(void **state); + +#endif // _TEST__F_socket_write_stream_h diff --git a/level_0/f_socket/tests/unit/c/test-socket.c b/level_0/f_socket/tests/unit/c/test-socket.c index 8fb134e..0b998aa 100644 --- a/level_0/f_socket/tests/unit/c/test-socket.c +++ b/level_0/f_socket/tests/unit/c/test-socket.c @@ -67,12 +67,18 @@ int main(void) { cmocka_unit_test(test__f_socket_read_message__fails), cmocka_unit_test(test__f_socket_read_message__works), + cmocka_unit_test(test__f_socket_read_stream__fails), + cmocka_unit_test(test__f_socket_read_stream__works), + cmocka_unit_test(test__f_socket_write__fails), cmocka_unit_test(test__f_socket_write__works), cmocka_unit_test(test__f_socket_write_message__fails), cmocka_unit_test(test__f_socket_write_message__works), + cmocka_unit_test(test__f_socket_write_stream__fails), + cmocka_unit_test(test__f_socket_write_stream__works), + #ifndef _di_level_0_parameter_checking_ cmocka_unit_test(test__f_socket_accept__parameter_checking), cmocka_unit_test(test__f_socket_bind__parameter_checking), @@ -87,8 +93,10 @@ int main(void) { cmocka_unit_test(test__f_socket_option_set__parameter_checking), cmocka_unit_test(test__f_socket_read__parameter_checking), cmocka_unit_test(test__f_socket_read_message__parameter_checking), + cmocka_unit_test(test__f_socket_read_stream__parameter_checking), cmocka_unit_test(test__f_socket_write__parameter_checking), cmocka_unit_test(test__f_socket_write_message__parameter_checking), + cmocka_unit_test(test__f_socket_write_stream__parameter_checking), #endif // _di_level_0_parameter_checking_ }; diff --git a/level_0/f_socket/tests/unit/c/test-socket.h b/level_0/f_socket/tests/unit/c/test-socket.h index d8e56b5..084a75e 100644 --- a/level_0/f_socket/tests/unit/c/test-socket.h +++ b/level_0/f_socket/tests/unit/c/test-socket.h @@ -40,8 +40,10 @@ #include "test-socket-option_set.h" #include "test-socket-read.h" #include "test-socket-read_message.h" +#include "test-socket-read_stream.h" #include "test-socket-write.h" #include "test-socket-write_message.h" +#include "test-socket-write_stream.h" #ifdef __cplusplus extern "C" { diff --git a/level_0/f_type/c/type_file.h b/level_0/f_type/c/type_file.h index c7814c0..2420401 100644 --- a/level_0/f_type/c/type_file.h +++ b/level_0/f_type/c/type_file.h @@ -18,6 +18,7 @@ // Libc includes. #include #include +#include #ifdef __cplusplus extern "C" { @@ -185,6 +186,70 @@ extern "C" { file.size_write = F_file_default_size_write_d; #endif // _di_f_file_t_ +/** + * A typdef for representing struct pollfd. + */ +#ifndef _di_f_poll_t_ + typedef struct pollfd f_poll_t; + + #define f_poll_t_initialize { 0 } + + #define macro_f_poll_t_initialize_1(fd, events, revents) { fd, events, revents } + #define macro_f_poll_t_initialize_2(fd, events) { fd, events, 0 } + #define macro_f_poll_t_initialize_3(fd) { fd, 0, 0 } + #define macro_f_poll_t_initialize_4(events) { 0, events, 0 } +#endif // _di_f_poll_t_ + +/** + * An array of pollfd structures. + * + * The macros are defined in type_array.h or type_array-common.h. + * + * If used for functions like poll() (a common use) then the max array length for used is limited to nfds_t which might be different from f_number_unsigned_t. + * The nfds_t is often either uint32_t or an uint64_t. + * The f_number_unsigned_t is often an uint64_t. + * + * array: An array of f_poll_t. + * size: Total amount of allocated space. + * used: Total number of allocated spaces used. + */ +#ifndef _di_f_polls_t_ + typedef struct { + f_poll_t *array; + + f_number_unsigned_t size; + f_number_unsigned_t used; + } f_polls_t; + + #define f_polls_t_initialize { 0, 0, 0 } + + #define macro_f_polls_t_initialize_1(array, size, used) { array, size, used } + #define macro_f_polls_t_initialize_2(array, length) { array, length, length } +#endif // _di_f_polls_t_ + +/** + * An array of f_polls_t. + * + * The macros are defined in type_array.h or type_array-common.h. + * + * array: The array of f_polls_t. + * size: Total amount of allocated space. + * used: Total number of allocated spaces used. + */ +#ifndef _di_f_pollss_t_ + typedef struct { + f_polls_t *array; + + f_number_unsigned_t size; + f_number_unsigned_t used; + } f_pollss_t; + + #define f_pollss_t_initialize { 0, 0, 0 } + + #define macro_f_pollss_t_initialize_1(array, size, used) { array, size, used } + #define macro_f_pollss_t_initialize_2(array, length) { array, length, length } +#endif // _di_f_pollss_t_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_type_array/c/type_array/poll.c b/level_0/f_type_array/c/type_array/poll.c new file mode 100644 index 0000000..5a5a69a --- /dev/null +++ b/level_0/f_type_array/c/type_array/poll.c @@ -0,0 +1,259 @@ +#include "../type_array.h" +#include "../type_array_file.h" +#include "poll.h" +#include "private-poll.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_f_polls_adjust_ + f_status_t f_polls_adjust(const f_number_unsigned_t length, f_polls_t *polls) { + #ifndef _di_level_0_parameter_checking_ + if (!polls) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_polls_adjust(length, polls); + } +#endif // _di_f_polls_adjust_ + +#ifndef _di_f_polls_append_ + f_status_t f_polls_append(const f_poll_t source, f_polls_t *destination) { + #ifndef _di_level_0_parameter_checking_ + if (!destination) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_polls_append(source, destination); + } +#endif // _di_f_polls_append_ + +#ifndef _di_f_polls_append_all_ + f_status_t f_polls_append_all(const f_polls_t source, f_polls_t *destination) { + #ifndef _di_level_0_parameter_checking_ + if (!destination) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!source.used) return F_data_not; + + return private_f_polls_append_all(source, destination); + } +#endif // _di_f_polls_append_all_ + +#ifndef _di_f_polls_decimate_by_ + f_status_t f_polls_decimate_by(const f_number_unsigned_t amount, f_polls_t *polls) { + #ifndef _di_level_0_parameter_checking_ + if (!polls) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!amount) return F_data_not; + if (polls->size - amount > 0) return private_f_polls_adjust(polls->size - amount, polls); + + return private_f_polls_adjust(0, polls); + } +#endif // _di_f_polls_decimate_by_ + +#ifndef _di_f_polls_decrease_by_ + f_status_t f_polls_decrease_by(const f_number_unsigned_t amount, f_polls_t *polls) { + #ifndef _di_level_0_parameter_checking_ + if (!polls) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!amount) return F_data_not; + if (polls->size - amount > 0) return private_f_polls_resize(polls->size - amount, polls); + + return private_f_polls_resize(0, polls); + } +#endif // _di_f_polls_decrease_by_ + +#ifndef _di_f_polls_increase_ + f_status_t f_polls_increase(const f_number_unsigned_t step, f_polls_t *polls) { + #ifndef _di_level_0_parameter_checking_ + if (!polls) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (step && polls->used + 1 > polls->size) { + f_number_unsigned_t size = polls->used + step; + + if (size > F_number_t_size_unsigned_d) { + if (polls->used + 1 > F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large); + + size = F_number_t_size_unsigned_d; + } + + return private_f_polls_resize(size, polls); + } + + return F_data_not; + } +#endif // _di_f_polls_increase_ + +#ifndef _di_f_polls_increase_by_ + f_status_t f_polls_increase_by(const f_number_unsigned_t amount, f_polls_t *polls) { + #ifndef _di_level_0_parameter_checking_ + if (!polls) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!amount) return F_data_not; + + if (polls->used + amount > polls->size) { + if (polls->used + amount > F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large); + + return private_f_polls_resize(polls->used + amount, polls); + } + + return F_data_not; + } +#endif // _di_f_polls_increase_by_ + +#ifndef _di_f_polls_resize_ + f_status_t f_polls_resize(const f_number_unsigned_t length, f_polls_t *polls) { + #ifndef _di_level_0_parameter_checking_ + if (!polls) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_polls_resize(length, polls); + } +#endif // _di_f_polls_resize_ + +#ifndef _di_f_pollss_adjust_ + f_status_t f_pollss_adjust(const f_number_unsigned_t length, f_pollss_t *pollss) { + #ifndef _di_level_0_parameter_checking_ + if (!pollss) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_pollss_adjust(length, pollss); + } +#endif // _di_f_pollss_adjust_ + +#ifndef _di_f_pollss_append_ + f_status_t f_pollss_append(const f_polls_t source, f_pollss_t *destination) { + #ifndef _di_level_0_parameter_checking_ + if (!destination) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!source.used) return F_data_not; + + f_status_t status = F_none; + + if (destination->used + 1 > destination->size) { + status = private_f_pollss_resize(destination->used + F_memory_default_allocation_small_d, destination); + if (F_status_is_error(status)) return status; + } + + status = private_f_polls_append_all(source, &destination->array[destination->used]); + if (F_status_is_error(status)) return status; + + ++destination->used; + + return F_none; + } +#endif // _di_f_pollss_append_ + +#ifndef _di_f_pollss_append_all_ + f_status_t f_pollss_append_all(const f_pollss_t source, f_pollss_t *destination) { + #ifndef _di_level_0_parameter_checking_ + if (!destination) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!source.used) return F_data_not; + + f_status_t status = F_none; + + if (destination->used + source.used > destination->size) { + status = private_f_pollss_resize(destination->used + source.used, destination); + if (F_status_is_error(status)) return status; + } + + for (f_number_unsigned_t i = 0; i < source.used; ++i, ++destination->used) { + + destination->array[destination->used].used = 0; + + if (source.array[i].used) { + status = private_f_polls_append_all(source.array[i], &destination->array[destination->used]); + if (F_status_is_error(status)) return status; + } + } // for + + return F_none; + } +#endif // _di_f_pollss_append_all_ + +#ifndef _di_f_pollss_decimate_by_ + f_status_t f_pollss_decimate_by(const f_number_unsigned_t amount, f_pollss_t *pollss) { + #ifndef _di_level_0_parameter_checking_ + if (!pollss) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!amount) return F_data_not; + if (pollss->size - amount > 0) return private_f_pollss_adjust(pollss->size - amount, pollss); + + return private_f_pollss_adjust(0, pollss); + } +#endif // _di_f_pollss_decimate_by_ + +#ifndef _di_f_pollss_decrease_by_ + f_status_t f_pollss_decrease_by(const f_number_unsigned_t amount, f_pollss_t *pollss) { + #ifndef _di_level_0_parameter_checking_ + if (!pollss) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!amount) return F_data_not; + if (pollss->size - amount > 0) return private_f_pollss_resize(pollss->size - amount, pollss); + + return private_f_pollss_resize(0, pollss); + } +#endif // _di_f_pollss_decrease_by_ + +#ifndef _di_f_pollss_increase_ + f_status_t f_pollss_increase(const f_number_unsigned_t step, f_pollss_t *pollss) { + #ifndef _di_level_0_parameter_checking_ + if (!pollss) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (step && pollss->used + 1 > pollss->size) { + f_number_unsigned_t size = pollss->used + step; + + if (size > F_number_t_size_unsigned_d) { + if (pollss->used + 1 > F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large); + + size = F_number_t_size_unsigned_d; + } + + return private_f_pollss_resize(size, pollss); + } + + return F_data_not; + } +#endif // _di_f_pollss_increase_ + +#ifndef _di_f_pollss_increase_by_ + f_status_t f_pollss_increase_by(const f_number_unsigned_t amount, f_pollss_t *pollss) { + #ifndef _di_level_0_parameter_checking_ + if (!pollss) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (!amount) return F_data_not; + + if (pollss->used + amount > pollss->size) { + if (pollss->used + amount > F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large); + + return private_f_pollss_resize(pollss->used + amount, pollss); + } + + return F_data_not; + } +#endif // _di_f_pollss_increase_by_ + +#ifndef _di_f_pollss_resize_ + f_status_t f_pollss_resize(const f_number_unsigned_t length, f_pollss_t *pollss) { + #ifndef _di_level_0_parameter_checking_ + if (!pollss) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_pollss_resize(length, pollss); + } +#endif // _di_f_pollss_resize_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/c/type_array/poll.h b/level_0/f_type_array/c/type_array/poll.h new file mode 100644 index 0000000..ee33efd --- /dev/null +++ b/level_0/f_type_array/c/type_array/poll.h @@ -0,0 +1,379 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Defines data to be used for/by type (array) related functionality. + * + * This is auto-included by type_array.h and should not need to be explicitly included. + */ +#ifndef _F_type_array_poll_h +#define _F_type_array_poll_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Resize the string polls array. + * + * @param length + * The new size to use. + * @param polls + * The string polls array to resize. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_adjust(). + */ +#ifndef _di_f_polls_adjust_ + extern f_status_t f_polls_adjust(const f_number_unsigned_t length, f_polls_t *polls); +#endif // _di_f_polls_adjust_ + +/** + * Append the single source poll onto the destination. + * + * @param source + * The source poll to append. + * @param destination + * The destination polls the source is appended onto. + * + * @return + * F_none on success. + * F_data_not on success, but there is nothing to append (size == 0). + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_polls_append_ + extern f_status_t f_polls_append(const f_poll_t source, f_polls_t *destination); +#endif // _di_f_polls_append_ + +/** + * Append the source polls onto the destination. + * + * @param source + * The source polls to append. + * @param destination + * The destination polls the source is appended onto. + * + * @return + * F_none on success. + * F_data_not on success, but there is nothing to append (size == 0). + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_polls_append_all_ + extern f_status_t f_polls_append_all(const f_polls_t source, f_polls_t *destination); +#endif // _di_f_polls_append_all_ + +/** + * Resize the string polls array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to les than 0. + * + * @param amount + * A positive number representing how much to decimate the size by. + * @param polls + * The string polls array to resize. + * + * @return + * F_none on success. + * F_data_not if amount is 0. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_adjust(). + */ +#ifndef _di_f_polls_decimate_by_ + extern f_status_t f_polls_decimate_by(const f_number_unsigned_t amount, f_polls_t *polls); +#endif // _di_f_polls_decimate_by_ + +/** + * Resize the string polls array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to les than 0. + * + * @param amount + * A positive number representing how much to decrease the size by. + * @param polls + * The string polls array to resize. + * + * @return + * F_none on success. + * F_data_not if amount is 0. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_polls_decrease_by_ + extern f_status_t f_polls_decrease_by(const f_number_unsigned_t amount, f_polls_t *polls); +#endif // _di_f_polls_decrease_by_ + +/** + * Increase the size of the string polls array, but only if necesary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param step + * The allocation step to use. + * Must be greater than 0. + * @param polls + * The string polls array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_polls_increase_ + extern f_status_t f_polls_increase(const f_number_unsigned_t step, f_polls_t *polls); +#endif // _di_f_polls_increase_ + +/** + * Resize the string polls array to a larger size. + * + * This will resize making the array larger based on the given length. + * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param amount + * A positive number representing how much to increase the size by. + * @param polls + * The string polls array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + amount <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_polls_increase_by_ + extern f_status_t f_polls_increase_by(const f_number_unsigned_t amount, f_polls_t *polls); +#endif // _di_f_polls_increase_by_ + +/** + * Resize the string polls array. + * + * @param length + * The new size to use. + * @param polls + * The string polls array to adjust. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_polls_resize_ + extern f_status_t f_polls_resize(const f_number_unsigned_t length, f_polls_t *polls); +#endif // _di_f_polls_resize_ + +/** + * Resize the string pollss array. + * + * @param length + * The new size to use. + * @param pollss + * The string pollss array to resize. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_adjust(). + * Errors (with error bit) from: f_memory_destroy(). + */ +#ifndef _di_f_pollss_adjust_ + extern f_status_t f_pollss_adjust(const f_number_unsigned_t length, f_pollss_t *pollss); +#endif // _di_f_pollss_adjust_ + +/** + * Append the single source polls onto the destination. + * + * @param source + * The source polls to append. + * @param destination + * The destination ranges the source is appended onto. + * + * @return + * F_none on success. + * F_data_not on success, but there is nothing to append (size == 0). + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_pollss_append_ + extern f_status_t f_pollss_append(const f_polls_t source, f_pollss_t *destination); +#endif // _di_f_pollss_append_ + +/** + * Append the source pollss onto the destination. + * + * @param source + * The source pollss to append. + * @param destination + * The destination ranges the source is appended onto. + * + * @return + * F_none on success. + * F_data_not on success, but there is nothing to append (size == 0). + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_pollss_append_all_ + extern f_status_t f_pollss_append_all(const f_pollss_t source, f_pollss_t *destination); +#endif // _di_f_pollss_append_all_ + +/** + * Resize the string pollss array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decimate the size by. + * @param pollss + * The string pollss array to resize. + * + * @return + * F_none on success. + * F_data_not if amount is 0. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_adjust(). + * Errors (with error bit) from: f_memory_destroy(). + */ +#ifndef _di_f_pollss_decimate_by_ + extern f_status_t f_pollss_decimate_by(const f_number_unsigned_t amount, f_pollss_t *pollss); +#endif // _di_f_pollss_decimate_by_ + +/** + * Resize the string pollss array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decrease the size by. + * @param pollss + * The string pollss array to resize. + * + * @return + * F_none on success. + * F_data_not if amount is 0. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_delete(). + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_pollss_decrease_by_ + extern f_status_t f_pollss_decrease_by(const f_number_unsigned_t amount, f_pollss_t *pollss); +#endif // _di_f_pollss_decrease_by_ + +/** + * Increase the size of the string pollss array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param step + * The allocation step to use. + * Must be greater than 0. + * @param pollss + * The string pollss array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_pollss_increase_ + extern f_status_t f_pollss_increase(const f_number_unsigned_t step, f_pollss_t *pollss); +#endif // _di_f_pollss_increase_ + +/** + * Resize the string pollss array to a larger size. + * + * This will resize making the array larger based on the given length. + * If the given length is too large for the buffer, then attempt to set max buffer size (F_number_t_size_unsigned_d). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param amount + * A positive number representing how much to increase the size by. + * @param pollss + * The string pollss array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + amount <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_pollss_increase_by_ + extern f_status_t f_pollss_increase_by(const f_number_unsigned_t amount, f_pollss_t *pollss); +#endif // _di_f_pollss_increase_by_ + +/** + * Resize the string pollss array. + * + * @param length + * The new size to use. + * @param pollss + * The string pollss array to adjust. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_delete(). + * Errors (with error bit) from: f_memory_resize(). + */ +#ifndef _di_f_pollss_resize_ + extern f_status_t f_pollss_resize(const f_number_unsigned_t length, f_pollss_t *pollss); +#endif // _di_f_pollss_resize_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_type_array_poll_h diff --git a/level_0/f_type_array/c/type_array/private-poll.c b/level_0/f_type_array/c/type_array/private-poll.c new file mode 100644 index 0000000..2d27207 --- /dev/null +++ b/level_0/f_type_array/c/type_array/private-poll.c @@ -0,0 +1,127 @@ +#include "../type_array.h" +#include "../type_array_file.h" +#include "private-poll.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_di_f_polls_adjust_) || !defined(_di_f_polls_decimate_by_) + f_status_t private_f_polls_adjust(const f_number_unsigned_t length, f_polls_t *polls) { + + const f_status_t status = f_memory_adjust(polls->size, length, sizeof(f_poll_t), (void **) & polls->array); + if (F_status_is_error(status)) return status; + + polls->size = length; + + if (polls->used > polls->size) { + polls->used = length; + } + + return F_none; + } +#endif // !defined(_di_f_polls_adjust_) || !defined(_di_f_polls_decimate_by_) + +#if !defined(_di_f_polls_append_) || !defined(_di_f_pollss_append_) + extern f_status_t private_f_polls_append(const f_poll_t source, f_polls_t *destination) { + + if (destination->used + 1 > destination->size) { + const f_status_t status = private_f_polls_resize(destination->used + F_memory_default_allocation_small_d, destination); + if (F_status_is_error(status)) return status; + } + + destination->array[destination->used++] = source; + + return F_none; + } +#endif // !defined(_di_f_polls_append_) || !defined(_di_f_pollss_append_) + +#if !defined(_di_f_polls_append_) || !defined(_di_f_polls_append_all_) || !defined(_di_f_pollss_append_all_) + extern f_status_t private_f_polls_append_all(const f_polls_t source, f_polls_t *destination) { + + if (destination->used + source.used > destination->size) { + const f_status_t status = private_f_polls_resize(destination->used + source.used, destination); + if (F_status_is_error(status)) return status; + } + + for (f_number_unsigned_t i = 0; i < source.used; ++i) { + destination->array[destination->used++] = source.array[i]; + } // for + + return F_none; + } +#endif // !defined(_di_f_polls_append_) || !defined(_di_f_polls_append_all_) || !defined(_di_f_pollss_append_all_) + +#if !defined(_di_f_polls_resize_) || !defined(_di_f_polls_append_) || !defined(_di_f_polls_decrease_by_) || !defined(_di_f_pollss_append_) + f_status_t private_f_polls_resize(const f_number_unsigned_t length, f_polls_t *polls) { + + const f_status_t status = f_memory_resize(polls->size, length, sizeof(f_poll_t), (void **) & polls->array); + if (F_status_is_error(status)) return status; + + polls->size = length; + + if (polls->used > polls->size) { + polls->used = length; + } + + return F_none; + } +#endif // !defined(_di_f_polls_resize_) || !defined(_di_f_polls_append_) || !defined(_di_f_polls_decrease_by_) || !defined(_di_f_pollss_append_) + +#if !defined(_di_f_pollss_adjust_) || !defined(_di_f_pollss_decimate_by_) + f_status_t private_f_pollss_adjust(const f_number_unsigned_t length, f_pollss_t *pollss) { + + f_status_t status = F_none; + + for (f_number_unsigned_t i = length; i < pollss->size; ++i) { + + status = f_memory_destroy(pollss->array[i].size, sizeof(f_polls_t), (void **) & pollss->array[i].array); + if (F_status_is_error(status)) return status; + + pollss->array[i].size = 0; + pollss->array[i].used = 0; + } // for + + status = f_memory_adjust(pollss->size, length, sizeof(f_polls_t), (void **) & pollss->array); + if (F_status_is_error(status)) return status; + + pollss->size = length; + + if (pollss->used > pollss->size) { + pollss->used = length; + } + + return F_none; + } +#endif // !defined(_di_f_pollss_adjust_) || !defined(_di_f_pollss_decimate_by_) + +#if !defined(_di_f_pollss_decrease_by_) || !defined(_di_f_pollss_increase_) || !defined(_di_f_pollss_increase_by_) || !defined(_di_f_pollss_resize_) + f_status_t private_f_pollss_resize(const f_number_unsigned_t length, f_pollss_t *pollss) { + + f_status_t status = F_none; + + for (f_number_unsigned_t i = length; i < pollss->size; ++i) { + + status = f_memory_delete(pollss->array[i].size, sizeof(f_polls_t), (void **) & pollss->array[i].array); + if (F_status_is_error(status)) return status; + + pollss->array[i].size = 0; + pollss->array[i].used = 0; + } // for + + status = f_memory_resize(pollss->size, length, sizeof(f_polls_t), (void **) & pollss->array); + if (F_status_is_error(status)) return status; + + pollss->size = length; + + if (pollss->used > pollss->size) { + pollss->used = length; + } + + return F_none; + } +#endif // !defined(_di_f_pollss_decrease_by_) || !defined(_di_f_pollss_increase_) || !defined(_di_f_pollss_increase_by_) || !defined(_di_f_pollss_resize_) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/c/type_array/private-poll.h b/level_0/f_type_array/c/type_array/private-poll.h new file mode 100644 index 0000000..4bdab09 --- /dev/null +++ b/level_0/f_type_array/c/type_array/private-poll.h @@ -0,0 +1,175 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * These are provided for internal reduction in redundant code. + * These should not be exposed/used outside of this project. + */ +#ifndef _PRIVATE_F_type_array_poll_h +#define _PRIVATE_F_type_array_poll_h + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Private implementation for resizing the polls array. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The length to adjust to. + * @param polls + * The polls array to adjust. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_polls_adjust() + * @see f_polls_decimate_by() + */ +#if !defined(_di_f_polls_adjust_) || !defined(_di_f_polls_decimate_by_) + extern f_status_t private_f_polls_adjust(const f_number_unsigned_t length, f_polls_t *polls) F_attribute_visibility_internal_d; +#endif // !defined(_di_f_polls_adjust_) || !defined(_di_f_polls_decimate_by_) + +/** + * Private implementation for appending the poll array. + * + * Intended to be shared to each of the different implementation variations. + * + * @param source + * The source poll to append. + * @param destination + * The destination lengths the source is appended onto. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_polls_append() + * @see f_pollss_append() + */ +#if !defined(_di_f_polls_append_) || !defined(_di_f_pollss_append_) + extern f_status_t private_f_polls_append(const f_poll_t source, f_polls_t *destination) F_attribute_visibility_internal_d; +#endif // !defined(_di_f_polls_append_) || !defined(_di_f_pollss_append_) + +/** + * Private implementation for appending the poll array. + * + * Intended to be shared to each of the different implementation variations. + * + * @param source + * The source polls to append. + * @param destination + * The destination lengths the source is appended onto. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_polls_append_all() + * @see f_pollss_append() + * @see f_pollss_append_all() + */ +#if !defined(_di_f_polls_append_) || !defined(_di_f_polls_append_all_) || !defined(_di_f_pollss_append_all_) + extern f_status_t private_f_polls_append_all(const f_polls_t source, f_polls_t *destination) F_attribute_visibility_internal_d; +#endif // !defined(_di_f_polls_append_) || !defined(_di_f_polls_append_all_) || !defined(_di_f_pollss_append_all_) + +/** + * Private implementation for resizing the polls array. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The length to adjust to. + * @param polls + * The polls array to adjust. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_polls_resize() + * @see f_polls_append() + * @see f_polls_decrease_by() + * @see f_pollss_append() + */ +#if !defined(_di_f_polls_resize_) || !defined(_di_f_polls_append_) || !defined(_di_f_polls_decrease_by_) || !defined(_di_f_pollss_append_) + extern f_status_t private_f_polls_resize(const f_number_unsigned_t length, f_polls_t *polls) F_attribute_visibility_internal_d; +#endif // !defined(_di_f_polls_resize_) || !defined(_di_f_polls_append_) || !defined(_di_f_polls_decrease_by_) || !defined(_di_f_pollss_append_) + +/** + * Private implementation for resizing the pollss array. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The length to adjust to. + * @param pollss + * The pollss array to adjust. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * F_array_too_large (with error bit) if new length is larger than max array length. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_adjust(). + * Errors (with error bit) from: f_memory_destroy(). + * + * @see f_pollss_adjust() + * @see f_pollss_decimate_by() + */ +#if !defined(_di_f_pollss_adjust_) || !defined(_di_f_pollss_decimate_by_) + extern f_status_t private_f_pollss_adjust(const f_number_unsigned_t length, f_pollss_t *pollss) F_attribute_visibility_internal_d; +#endif // !defined(_di_f_pollss_adjust_) || !defined(_di_f_pollss_decimate_by_) + +/** + * Private implementation for resizing the pollss array. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The length to resize to. + * @param pollss + * The pollss array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * F_array_too_large (with error bit) if new length is larger than max array length. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * + * Errors (with error bit) from: f_memory_delete(). + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_pollss_decrease_by() + * @see f_pollss_increase() + * @see f_pollss_increase_by() + * @see f_pollss_resize() + */ +#if !defined(_di_f_pollss_decrease_by_) || !defined(_di_f_pollss_increase_) || !defined(_di_f_pollss_increase_by_) || !defined(_di_f_pollss_resize_) + extern f_status_t private_f_pollss_resize(const f_number_unsigned_t length, f_pollss_t *pollss) F_attribute_visibility_internal_d; +#endif // !defined(_di_f_pollss_decrease_by_) || !defined(_di_f_pollss_increase_) || !defined(_di_f_pollss_increase_by_) || !defined(_di_f_pollss_resize_) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_F_type_array_poll_h diff --git a/level_0/f_type_array/c/type_array_file.h b/level_0/f_type_array/c/type_array_file.h new file mode 100644 index 0000000..dddc0fb --- /dev/null +++ b/level_0/f_type_array/c/type_array_file.h @@ -0,0 +1,32 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides an extension to the Type project (f_type) that depends on f_memory (linking to the f_memory library). + * + * As an exceptional case, this is an extension to f_type to avoid circular dependency issues with f_memory. + * The functions and macros in this project therefore are prefixed with 'f_type_' instead of 'f_type_array_'. + */ +#ifndef _F_type_array_file_h +#define _F_type_array_file_h + +// FLL-0 includes. +#include +#include +#include + +// FLL-0 type_array includes. +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_type_array_file_h diff --git a/level_0/f_type_array/data/build/settings b/level_0/f_type_array/data/build/settings index e69100e..76dbae7 100644 --- a/level_0/f_type_array/data/build/settings +++ b/level_0/f_type_array/data/build/settings @@ -32,10 +32,10 @@ build_language c build_libraries -lc build_libraries-individual -lf_memory -build_sources_library type_array/cell.c type_array/fll_id.c type_array/int8.c type_array/int16.c type_array/int32.c type_array/int64.c type_array/int128.c type_array/number_unsigned.c type_array/state.c type_array/status.c type_array/uint8.c type_array/uint16.c type_array/uint32.c type_array/uint64.c type_array/uint128.c -build_sources_library type_array/private-cell.c type_array/private-fll_id.c type_array/private-int8.c type_array/private-int16.c type_array/private-int32.c type_array/private-int64.c type_array/private-int128.c type_array/private-number_unsigned.c type_array/private-state.c type_array/private-status.c type_array/private-uint8.c type_array/private-uint16.c type_array/private-uint32.c type_array/private-uint64.c type_array/private-uint128.c +build_sources_library type_array/cell.c type_array/fll_id.c type_array/int8.c type_array/int16.c type_array/int32.c type_array/int64.c type_array/int128.c type_array/number_unsigned.c type_array/poll.c type_array/state.c type_array/status.c type_array/uint8.c type_array/uint16.c type_array/uint32.c type_array/uint64.c type_array/uint128.c +build_sources_library type_array/private-cell.c type_array/private-fll_id.c type_array/private-int8.c type_array/private-int16.c type_array/private-int32.c type_array/private-int64.c type_array/private-int128.c type_array/private-number_unsigned.c type_array/private-poll.c type_array/private-state.c type_array/private-status.c type_array/private-uint8.c type_array/private-uint16.c type_array/private-uint32.c type_array/private-uint64.c type_array/private-uint128.c -build_sources_headers type_array.h type_array/common.h type_array/cell.h type_array/fll_id.h type_array/int8.h type_array/int16.h type_array/int32.h type_array/int64.h type_array/int128.h type_array/number_unsigned.h type_array/state.h type_array/status.h type_array/uint8.h type_array/uint16.h type_array/uint32.h type_array/uint64.h type_array/uint128.h +build_sources_headers type_array.h type_array_file.h type_array/common.h type_array/cell.h type_array/fll_id.h type_array/int8.h type_array/int16.h type_array/int32.h type_array/int64.h type_array/int128.h type_array/number_unsigned.h type_array/poll.h type_array/state.h type_array/status.h type_array/uint8.h type_array/uint16.h type_array/uint32.h type_array/uint64.h type_array/uint128.h build_script yes build_shared yes diff --git a/level_0/f_type_array/data/build/settings-mocks b/level_0/f_type_array/data/build/settings-mocks new file mode 100644 index 0000000..1f0f920 --- /dev/null +++ b/level_0/f_type_array/data/build/settings-mocks @@ -0,0 +1,66 @@ +# fss-0001 +# +# Build the project with appropriate mocks linked in via the dynamic linker's "--wrap" functionality. +# +# The -Wl,--wrap does not work across shared files. +# Therefore, this file is a work-around to inject the mocks into the library for testing purposes. +# This should exactly match the "settings" file, except for the additional "-Wl,--wrap" parts and the additional mock source file. +# +# The flags -o0 must be passed to prevent the compiler from optimizing away any functions being mocked (which results in the mock not happening and a real function being called). +# Alternatively, figure out which optimization that is disabled by -o0 and have that specific optimization disabled. +# + +build_name f_type_array + +version_major 0 +version_minor 7 +version_micro 0 +version_file micro +version_target minor + +modes individual clang test coverage +modes_default individual test + +build_compiler gcc +build_compiler-clang clang +build_indexer ar +build_indexer_arguments rcs +build_language c + +build_libraries -lc +build_libraries-individual -lf_memory + +build_sources_library type_array/cell.c type_array/fll_id.c type_array/int8.c type_array/int16.c type_array/int32.c type_array/int64.c type_array/int128.c type_array/number_unsigned.c type_array/poll.c type_array/state.c type_array/status.c type_array/uint8.c type_array/uint16.c type_array/uint32.c type_array/uint64.c type_array/uint128.c +build_sources_library type_array/private-cell.c type_array/private-fll_id.c type_array/private-int8.c type_array/private-int16.c type_array/private-int32.c type_array/private-int64.c type_array/private-int128.c type_array/private-number_unsigned.c type_array/private-poll.c type_array/private-state.c type_array/private-status.c type_array/private-uint8.c type_array/private-uint16.c type_array/private-uint32.c type_array/private-uint64.c type_array/private-uint128.c +build_sources_library ../../tests/unit/c/mock-type_array.c + +build_sources_headers type_array.h type_array_file.h type_array/common.h type_array/cell.h type_array/fll_id.h type_array/int8.h type_array/int16.h type_array/int32.h type_array/int64.h type_array/int128.h type_array/number_unsigned.h type_array/poll.h type_array/state.h type_array/status.h type_array/uint8.h type_array/uint16.h type_array/uint32.h type_array/uint64.h type_array/uint128.h + +build_script yes +build_shared yes +build_static no + +path_headers fll/level_0 +path_library_script script +path_library_shared shared +path_library_static static + +has_path_standard yes +preserve_path_headers yes + +search_exclusive yes +search_shared yes +search_static yes + +environment PATH LD_LIBRARY_PATH +environment LANG LC_ALL LC_COLLATE LC_CTYPE LC_FASTMSG LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LOCPATH NLSPATH + +flags -O0 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses +flags-clang -Wno-logical-op-parentheses +flags-test -fstack-protector -Wall -Wno-missing-braces +flags-coverage --coverage -fprofile-abs-path -fprofile-dir=build/coverage/ + +flags_library -fPIC + +# Inject mocks. +flags -Wl,--wrap=poll diff --git a/level_0/f_type_array/data/build/settings-tests b/level_0/f_type_array/data/build/settings-tests index d8e3654..32bf164 100644 --- a/level_0/f_type_array/data/build/settings-tests +++ b/level_0/f_type_array/data/build/settings-tests @@ -39,6 +39,8 @@ build_sources_program test-type_array-int128s_adjust.c test-type_array-int128s_a build_sources_program test-type_array-int128ss_adjust.c test-type_array-int128ss_append.c test-type_array-int128ss_append_all.c test-type_array-int128ss_decimate_by.c test-type_array-int128ss_decrease_by.c test-type_array-int128ss_increase.c test-type_array-int128ss_increase_by.c test-type_array-int128ss_resize.c build_sources_program test-type_array-number_unsigneds_adjust.c test-type_array-number_unsigneds_append.c test-type_array-number_unsigneds_append_all.c test-type_array-number_unsigneds_decimate_by.c test-type_array-number_unsigneds_decrease_by.c test-type_array-number_unsigneds_increase.c test-type_array-number_unsigneds_increase_by.c test-type_array-number_unsigneds_resize.c build_sources_program test-type_array-number_unsignedss_adjust.c test-type_array-number_unsignedss_append.c test-type_array-number_unsignedss_append_all.c test-type_array-number_unsignedss_decimate_by.c test-type_array-number_unsignedss_decrease_by.c test-type_array-number_unsignedss_increase.c test-type_array-number_unsignedss_increase_by.c test-type_array-number_unsignedss_resize.c +build_sources_program test-type_array-polls_adjust.c test-type_array-polls_append.c test-type_array-polls_append_all.c test-type_array-polls_decimate_by.c test-type_array-polls_decrease_by.c test-type_array-polls_increase.c test-type_array-polls_increase_by.c test-type_array-polls_resize.c +build_sources_program test-type_array-pollss_adjust.c test-type_array-pollss_append.c test-type_array-pollss_append_all.c test-type_array-pollss_decimate_by.c test-type_array-pollss_decrease_by.c test-type_array-pollss_increase.c test-type_array-pollss_increase_by.c test-type_array-pollss_resize.c build_sources_program test-type_array-states_adjust.c test-type_array-states_append.c test-type_array-states_append_all.c test-type_array-states_decimate_by.c test-type_array-states_decrease_by.c test-type_array-states_increase.c test-type_array-states_increase_by.c test-type_array-states_resize.c build_sources_program test-type_array-statess_adjust.c test-type_array-statess_append.c test-type_array-statess_append_all.c test-type_array-statess_decimate_by.c test-type_array-statess_decrease_by.c test-type_array-statess_increase.c test-type_array-statess_increase_by.c test-type_array-statess_resize.c build_sources_program test-type_array-statuss_adjust.c test-type_array-statuss_append.c test-type_array-statuss_append_all.c test-type_array-statuss_decimate_by.c test-type_array-statuss_decrease_by.c test-type_array-statuss_increase.c test-type_array-statuss_increase_by.c test-type_array-statuss_resize.c diff --git a/level_0/f_type_array/tests/unit/c/mock-type_array.c b/level_0/f_type_array/tests/unit/c/mock-type_array.c new file mode 100644 index 0000000..cef5a0d --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/mock-type_array.c @@ -0,0 +1,24 @@ +#include "mock-type_array.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int __wrap_poll(f_poll_t *fds, nfds_t nfds, int timeout) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + fds->revents = mock_type(short); + + return mock_type(int); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/mock-type_array.h b/level_0/f_type_array/tests/unit/c/mock-type_array.h new file mode 100644 index 0000000..534130c --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/mock-type_array.h @@ -0,0 +1,38 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the type_array project. + */ +#ifndef _MOCK__type_array_h +#define _MOCK__type_array_h + +// Libc includes. +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-0 includes. +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +const static int mock_errno_generic = 32767; + +extern int __wrap_poll(f_poll_t *fds, nfds_t nfds, int timeout); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _MOCK__type_array_h diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_adjust.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_adjust.c new file mode 100644 index 0000000..3b8669f --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_adjust.c @@ -0,0 +1,42 @@ +#include "test-type_array.h" +#include "test-type_array-polls_adjust.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_adjust__parameter_checking(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_adjust(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_polls_adjust__works(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_adjust(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_adjust.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_adjust.h new file mode 100644 index 0000000..540f21c --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_adjust.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_adjust +#define _TEST__F_type_array__polls_adjust + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_adjust() + */ +extern void test__f_type_array_polls_adjust__parameter_checking(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_adjust() + */ +extern void test__f_type_array_polls_adjust__works(void **poll); + +#endif // _TEST__F_type_array__polls_adjust diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_append.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append.c new file mode 100644 index 0000000..f455a42 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append.c @@ -0,0 +1,39 @@ +#include "test-type_array.h" +#include "test-type_array-polls_append.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_append__parameter_checking(void **poll) { + + const f_poll_t data = f_poll_t_initialize; + + { + const f_status_t status = f_polls_append(data, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_type_array_polls_append__works(void **poll) { + + const f_poll_t source = macro_f_poll_t_initialize_1(0, 1, 2); + f_polls_t destination = f_polls_t_initialize; + + { + const f_status_t status = f_polls_append(source, &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, 1); + assert_int_equal(destination.array[0].fd, source.fd); + assert_int_equal(destination.array[0].events, source.events); + assert_int_equal(destination.array[0].revents, source.revents); + } + + free((void *) destination.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_append.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append.h new file mode 100644 index 0000000..3b5b519 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_append +#define _TEST__F_type_array__polls_append + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_append() + */ +extern void test__f_type_array_polls_append__parameter_checking(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_append() + */ +extern void test__f_type_array_polls_append__works(void **poll); + +#endif // _TEST__F_type_array__polls_append diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_append_all.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append_all.c new file mode 100644 index 0000000..25f096c --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append_all.c @@ -0,0 +1,86 @@ +#include "test-type_array.h" +#include "test-type_array-polls_append_all.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_append_all__parameter_checking(void **poll) { + + const f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_append_all(data, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_type_array_polls_append_all__returns_data_not(void **poll) { + + const int length = 5; + f_polls_t source = f_polls_t_initialize; + f_polls_t destination = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &source); + + assert_int_equal(status, F_none); + assert_int_equal(source.used, 0); + assert_int_equal(source.size, length); + } + + { + const f_status_t status = f_polls_append_all(source, &destination); + + assert_int_equal(status, F_data_not); + assert_int_equal(destination.used, 0); + assert_int_equal(destination.size, 0); + assert_null(destination.array); + } + + free((void *) source.array); +} + +void test__f_type_array_polls_append_all__works(void **poll) { + + const int length = 5; + f_polls_t source = f_polls_t_initialize; + f_polls_t destination = f_polls_t_initialize; + + const f_poll_t poll_0 = { 0, 1, 2 }; + const f_poll_t poll_1 = { 0, 2, 3 }; + + { + const f_status_t status = f_polls_resize(length, &source); + + assert_int_equal(status, F_none); + assert_int_equal(source.used, 0); + assert_int_equal(source.size, length); + } + + memcpy(&source.array[source.used++], (void *) &poll_0, sizeof(f_poll_t)); + memcpy(&source.array[source.used++], (void *) &poll_1, sizeof(f_poll_t)); + + { + const f_status_t status = f_polls_append_all(source, &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, source.used); + assert_int_equal(destination.size, source.used); + + for (f_number_unsigned_t i = 0; i < source.used; ++i) { + + assert_int_equal(destination.array[i].fd, source.array[i].fd); + assert_int_equal(destination.array[i].events, source.array[i].events); + assert_int_equal(destination.array[i].revents, source.array[i].revents); + } // for + } + + free((void *) source.array); + free((void *) destination.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_append_all.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append_all.h new file mode 100644 index 0000000..15bf28f --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_append_all.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_append_all +#define _TEST__F_type_array__polls_append_all + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_append_all() + */ +extern void test__f_type_array_polls_append_all__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_polls_append_all() + */ +extern void test__f_type_array_polls_append_all__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_append_all() + */ +extern void test__f_type_array_polls_append_all__works(void **poll); + +#endif // _TEST__F_type_array__polls_append_all diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_decimate_by.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decimate_by.c new file mode 100644 index 0000000..7efb151 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decimate_by.c @@ -0,0 +1,74 @@ +#include "test-type_array.h" +#include "test-type_array-polls_decimate_by.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_decimate_by__parameter_checking(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_decimate_by(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_polls_decimate_by__returns_data_not(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_polls_decimate_by(0, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_polls_decimate_by__works(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_polls_decimate_by(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_decimate_by.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decimate_by.h new file mode 100644 index 0000000..359403f --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decimate_by.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_decimate_by +#define _TEST__F_type_array__polls_decimate_by + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_decimate_by() + */ +extern void test__f_type_array_polls_decimate_by__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_polls_decimate_by() + */ +extern void test__f_type_array_polls_decimate_by__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_decimate_by() + */ +extern void test__f_type_array_polls_decimate_by__works(void **poll); + +#endif // _TEST__F_type_array__polls_decimate_by diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_decrease_by.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decrease_by.c new file mode 100644 index 0000000..1c7fb64 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decrease_by.c @@ -0,0 +1,74 @@ +#include "test-type_array.h" +#include "test-type_array-polls_decrease_by.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_decrease_by__parameter_checking(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_decrease_by(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_polls_decrease_by__returns_data_not(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_polls_decrease_by(0, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_polls_decrease_by__works(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_polls_decrease_by(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_decrease_by.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decrease_by.h new file mode 100644 index 0000000..3024366 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_decrease_by.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_decrease_by +#define _TEST__F_type_array__polls_decrease_by + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_decrease_by() + */ +extern void test__f_type_array_polls_decrease_by__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_polls_decrease_by() + */ +extern void test__f_type_array_polls_decrease_by__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_decrease_by() + */ +extern void test__f_type_array_polls_decrease_by__works(void **poll); + +#endif // _TEST__F_type_array__polls_decrease_by diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase.c new file mode 100644 index 0000000..f5a8826 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase.c @@ -0,0 +1,76 @@ +#include "test-type_array.h" +#include "test-type_array-polls_increase.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_increase__parameter_checking(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_increase(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + free((void *) data.array); +} + +void test__f_type_array_polls_increase__returns_data_not(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_polls_increase(length, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_polls_increase__works(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + data.used = length; + + const f_status_t status = f_polls_increase(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, length); + assert_in_range(data.size, length + 1, length + 1 + F_memory_default_allocation_small_d); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase.h new file mode 100644 index 0000000..4856646 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_increase +#define _TEST__F_type_array__polls_increase + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_increase() + */ +extern void test__f_type_array_polls_increase__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_polls_increase() + */ +extern void test__f_type_array_polls_increase__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_increase() + */ +extern void test__f_type_array_polls_increase__works(void **poll); + +#endif // _TEST__F_type_array__polls_increase diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase_by.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase_by.c new file mode 100644 index 0000000..535b4f3 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase_by.c @@ -0,0 +1,76 @@ +#include "test-type_array.h" +#include "test-type_array-polls_increase_by.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_increase_by__parameter_checking(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_increase_by(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_polls_increase_by__returns_data_not(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_polls_increase_by(0, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_polls_increase_by__works(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + data.used = length; + + const f_status_t status = f_polls_increase_by(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, length); + assert_int_equal(data.size, length * 2); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase_by.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase_by.h new file mode 100644 index 0000000..f6356c4 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_increase_by.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_increase_by +#define _TEST__F_type_array__polls_increase_by + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_increase_by() + */ +extern void test__f_type_array_polls_increase_by__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_polls_increase_by() + */ +extern void test__f_type_array_polls_increase_by__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_increase_by() + */ +extern void test__f_type_array_polls_increase_by__works(void **poll); + +#endif // _TEST__F_type_array__polls_increase_by diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_resize.c b/level_0/f_type_array/tests/unit/c/test-type_array-polls_resize.c new file mode 100644 index 0000000..87f01e2 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_resize.c @@ -0,0 +1,42 @@ +#include "test-type_array.h" +#include "test-type_array-polls_resize.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_polls_resize__parameter_checking(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_polls_resize__works(void **poll) { + + const int length = 5; + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-polls_resize.h b/level_0/f_type_array/tests/unit/c/test-type_array-polls_resize.h new file mode 100644 index 0000000..52e3e94 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-polls_resize.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__polls_resize +#define _TEST__F_type_array__polls_resize + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_polls_resize() + */ +extern void test__f_type_array_polls_resize__parameter_checking(void **poll); + +/** + * Test that the function works. + * + * @see f_polls_resize() + */ +extern void test__f_type_array_polls_resize__works(void **poll); + +#endif // _TEST__F_type_array__polls_resize diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_adjust.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_adjust.c new file mode 100644 index 0000000..007cf1a --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_adjust.c @@ -0,0 +1,42 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_adjust.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_adjust__parameter_checking(void **poll) { + + const int length = 5; + f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_adjust(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_pollss_adjust__works(void **poll) { + + const int length = 5; + f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_adjust(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_adjust.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_adjust.h new file mode 100644 index 0000000..51481a3 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_adjust.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_adjust +#define _TEST__F_type_array__pollss_adjust + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_adjust() + */ +extern void test__f_type_array_pollss_adjust__parameter_checking(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_adjust() + */ +extern void test__f_type_array_pollss_adjust__works(void **poll); + +#endif // _TEST__F_type_array__pollss_adjust diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append.c new file mode 100644 index 0000000..8f22b02 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append.c @@ -0,0 +1,91 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_append.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_append__parameter_checking(void **poll) { + + f_polls_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_append(data, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_type_array_pollss_append__returns_data_not(void **poll) { + + const int length = 5; + f_polls_t source = f_polls_t_initialize; + f_pollss_t destination = f_pollss_t_initialize; + + { + const f_status_t status = f_polls_resize(length, &source); + + assert_int_equal(status, F_none); + assert_int_equal(source.used, 0); + assert_int_equal(source.size, length); + } + + { + const f_status_t status = f_pollss_append(source, &destination); + + assert_int_equal(status, F_data_not); + assert_int_equal(destination.used, 0); + assert_int_equal(destination.size, 0); + assert_null(destination.array); + } + + free((void *) source.array); +} + +void test__f_type_array_pollss_append__works(void **poll) { + + const int length = 5; + f_polls_t source = f_polls_t_initialize; + f_pollss_t destination = f_pollss_t_initialize; + + const f_poll_t poll_data = macro_f_poll_t_initialize_1(0, 1, 2); + + { + const f_status_t status = f_polls_resize(length, &source); + + assert_int_equal(status, F_none); + assert_int_equal(source.used, 0); + assert_int_equal(source.size, length); + } + + while (source.used < length) { + memcpy(&source.array[source.used++], (void *) &poll_data, sizeof(f_poll_t)); + } // while + + { + const f_status_t status = f_pollss_append(source, &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, 1); + assert_int_equal(destination.array[0].used, source.used); + assert_int_equal(destination.array[0].size, source.used); + + for (f_number_unsigned_t i = 0; i < destination.array[0].used; ++i) { + + assert_int_equal(destination.array[0].array[i].fd, source.array[0].fd); + assert_int_equal(destination.array[0].array[i].events, source.array[0].events); + assert_int_equal(destination.array[0].array[i].revents, source.array[0].revents); + } // for + } + + for (f_number_unsigned_t i = 0; i < destination.used; ++i) { + free((void *) destination.array[i].array); + } // for + + free((void *) source.array); + free((void *) destination.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append.h new file mode 100644 index 0000000..c61f63e --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_append +#define _TEST__F_type_array__pollss_append + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_append() + */ +extern void test__f_type_array_pollss_append__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_pollss_append() + */ +extern void test__f_type_array_pollss_append__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_append() + */ +extern void test__f_type_array_pollss_append__works(void **poll); + +#endif // _TEST__F_type_array__pollss_append diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append_all.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append_all.c new file mode 100644 index 0000000..a8be357 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append_all.c @@ -0,0 +1,110 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_append_all.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_append_all__parameter_checking(void **poll) { + + const f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_append_all(data, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_type_array_pollss_append_all__returns_data_not(void **poll) { + + const int length = 5; + f_pollss_t source = f_pollss_t_initialize; + f_pollss_t destination = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &source); + + assert_int_equal(status, F_none); + assert_int_equal(source.used, 0); + assert_int_equal(source.size, length); + } + + { + const f_status_t status = f_pollss_append_all(source, &destination); + + assert_int_equal(status, F_data_not); + assert_int_equal(destination.used, 0); + assert_int_equal(destination.size, 0); + assert_null(destination.array); + } + + free((void *) source.array); +} + +void test__f_type_array_pollss_append_all__works(void **poll) { + + const int length = 5; + const int length_inner = 2; + f_pollss_t source = f_pollss_t_initialize; + f_pollss_t destination = f_pollss_t_initialize; + + const f_poll_t poll_0 = { 0, 1, 2 }; + const f_poll_t poll_1 = { 0, 3, 4 }; + + { + const f_status_t status = f_pollss_resize(length, &source); + + assert_int_equal(status, F_none); + assert_int_equal(source.used, 0); + assert_int_equal(source.size, length); + } + + { + for (; source.used < length; ++source.used) { + + const f_status_t status = f_polls_resize(length_inner, &source.array[source.used]); + + assert_int_equal(status, F_none); + + memcpy(&source.array[source.used].array[source.array[source.used].used++], (void *) &poll_0, sizeof(f_poll_t)); + memcpy(&source.array[source.used].array[source.array[source.used].used++], (void *) &poll_1, sizeof(f_poll_t)); + } // for + } + + { + const f_status_t status = f_pollss_append_all(source, &destination); + + assert_int_equal(status, F_none); + assert_int_equal(destination.used, source.used); + assert_int_equal(destination.size, source.used); + + for (f_number_unsigned_t i = 0; i < destination.used; ++i) { + + assert_int_equal(destination.array[i].used, length_inner); + assert_int_equal(destination.array[i].size, length_inner); + + for (f_number_unsigned_t j = 0; j < length_inner; ++j) { + + assert_int_equal(destination.array[i].array[j].fd, source.array[i].array[j].fd); + assert_int_equal(destination.array[i].array[j].events, source.array[i].array[j].events); + assert_int_equal(destination.array[i].array[j].revents, source.array[i].array[j].revents); + } // for + } // for + } + + for (f_number_unsigned_t i = 0; i < source.used; ++i) { + free((void *) source.array[i].array); + } // for + + for (f_number_unsigned_t i = 0; i < destination.used; ++i) { + free((void *) destination.array[i].array); + } // for + + free((void *) source.array); + free((void *) destination.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append_all.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append_all.h new file mode 100644 index 0000000..b07cfb0 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_append_all.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_append_all +#define _TEST__F_type_array__pollss_append_all + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_append_all() + */ +extern void test__f_type_array_pollss_append_all__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_pollss_append_all() + */ +extern void test__f_type_array_pollss_append_all__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_append_all() + */ +extern void test__f_type_array_pollss_append_all__works(void **poll); + +#endif // _TEST__F_type_array__pollss_append_all diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decimate_by.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decimate_by.c new file mode 100644 index 0000000..f76b136 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decimate_by.c @@ -0,0 +1,74 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_decimate_by.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_decimate_by__parameter_checking(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_decimate_by(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_pollss_decimate_by__returns_data_not(void **poll) { + + const int length = 5; + f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_pollss_decimate_by(0, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_pollss_decimate_by__works(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_pollss_decimate_by(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decimate_by.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decimate_by.h new file mode 100644 index 0000000..d67aed4 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decimate_by.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_decimate_by +#define _TEST__F_type_array__pollss_decimate_by + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_decimate_by() + */ +extern void test__f_type_array_pollss_decimate_by__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_type_array_pollss_decimate_by() + */ +extern void test__f_type_array_pollss_decimate_by__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_decimate_by() + */ +extern void test__f_type_array_pollss_decimate_by__works(void **poll); + +#endif // _TEST__F_type_array__pollss_decimate_by diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decrease_by.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decrease_by.c new file mode 100644 index 0000000..68bc836 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decrease_by.c @@ -0,0 +1,74 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_decrease_by.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_decrease_by__parameter_checking(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_decrease_by(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_pollss_decrease_by__returns_data_not(void **poll) { + + const int length = 5; + f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_pollss_decrease_by(0, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_pollss_decrease_by__works(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_pollss_decrease_by(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decrease_by.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decrease_by.h new file mode 100644 index 0000000..48919c0 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_decrease_by.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_decrease_by +#define _TEST__F_type_array__pollss_decrease_by + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_decrease_by() + */ +extern void test__f_type_array_pollss_decrease_by__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_pollss_decrease_by() + */ +extern void test__f_type_array_pollss_decrease_by__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_decrease_by() + */ +extern void test__f_type_array_pollss_decrease_by__works(void **poll); + +#endif // _TEST__F_type_array__pollss_decrease_by diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase.c new file mode 100644 index 0000000..518f191 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase.c @@ -0,0 +1,76 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_increase.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_increase__parameter_checking(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_increase(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + free((void *) data.array); +} + +void test__f_type_array_pollss_increase__returns_data_not(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_pollss_increase(length, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_pollss_increase__works(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + data.used = length; + + const f_status_t status = f_pollss_increase(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, length); + assert_in_range(data.size, length + 1, length + 1 + F_memory_default_allocation_small_d); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase.h new file mode 100644 index 0000000..78956f2 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_increase +#define _TEST__F_type_array__pollss_increase + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_increase() + */ +extern void test__f_type_array_pollss_increase__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_pollss_increase() + */ +extern void test__f_type_array_pollss_increase__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_increase() + */ +extern void test__f_type_array_pollss_increase__works(void **poll); + +#endif // _TEST__F_type_array__pollss_increase diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase_by.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase_by.c new file mode 100644 index 0000000..0cd5a63 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase_by.c @@ -0,0 +1,84 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_increase_by.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_increase_by__parameter_checking(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_increase_by(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_pollss_increase_by__returns_data_not(void **poll) { + + const int length = 5; + f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_pollss_increase_by(0, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + const f_status_t status = f_pollss_increase_by(length, &data); + + assert_int_equal(status, F_data_not); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +void test__f_type_array_pollss_increase_by__works(void **poll) { + + const int length = 5; + f_pollss_t data = f_polls_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + { + data.used = length; + + const f_status_t status = f_pollss_increase_by(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, length); + assert_int_equal(data.size, length * 2); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase_by.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase_by.h new file mode 100644 index 0000000..af7fb3f --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_increase_by.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_increase_by +#define _TEST__F_type_array__pollss_increase_by + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_increase_by() + */ +extern void test__f_type_array_pollss_increase_by__parameter_checking(void **poll); + +/** + * Test that the function returns F_data_not. + * + * @see f_pollss_increase_by() + */ +extern void test__f_type_array_pollss_increase_by__returns_data_not(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_increase_by() + */ +extern void test__f_type_array_pollss_increase_by__works(void **poll); + +#endif // _TEST__F_type_array__pollss_increase_by diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_resize.c b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_resize.c new file mode 100644 index 0000000..d553ed6 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_resize.c @@ -0,0 +1,42 @@ +#include "test-type_array.h" +#include "test-type_array-pollss_resize.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_type_array_pollss_resize__parameter_checking(void **poll) { + + const int length = 5; + f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, 0); + } + + assert_null(data.array); +} + +void test__f_type_array_pollss_resize__works(void **poll) { + + const int length = 5; + f_pollss_t data = f_pollss_t_initialize; + + { + const f_status_t status = f_pollss_resize(length, &data); + + assert_int_equal(status, F_none); + assert_int_equal(data.used, 0); + assert_int_equal(data.size, length); + } + + free((void *) data.array); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_type_array/tests/unit/c/test-type_array-pollss_resize.h b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_resize.h new file mode 100644 index 0000000..35ff454 --- /dev/null +++ b/level_0/f_type_array/tests/unit/c/test-type_array-pollss_resize.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Type + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the array types in the type project. + */ +#ifndef _TEST__F_type_array__pollss_resize +#define _TEST__F_type_array__pollss_resize + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_pollss_resize() + */ +extern void test__f_type_array_pollss_resize__parameter_checking(void **poll); + +/** + * Test that the function works. + * + * @see f_pollss_resize() + */ +extern void test__f_type_array_pollss_resize__works(void **poll); + +#endif // _TEST__F_type_array__pollss_resize diff --git a/level_0/f_type_array/tests/unit/c/test-type_array.c b/level_0/f_type_array/tests/unit/c/test-type_array.c index e8fbd28..85f92ea 100644 --- a/level_0/f_type_array/tests/unit/c/test-type_array.c +++ b/level_0/f_type_array/tests/unit/c/test-type_array.c @@ -265,6 +265,36 @@ int main(void) { cmocka_unit_test(test__f_type_array_int128ss_increase_by__works), cmocka_unit_test(test__f_type_array_int128ss_resize__works), + cmocka_unit_test(test__f_type_array_polls_append_all__returns_data_not), + cmocka_unit_test(test__f_type_array_polls_decimate_by__returns_data_not), + cmocka_unit_test(test__f_type_array_polls_decrease_by__returns_data_not), + cmocka_unit_test(test__f_type_array_polls_increase__returns_data_not), + cmocka_unit_test(test__f_type_array_polls_increase_by__returns_data_not), + + cmocka_unit_test(test__f_type_array_polls_adjust__works), + cmocka_unit_test(test__f_type_array_polls_append__works), + cmocka_unit_test(test__f_type_array_polls_append_all__works), + cmocka_unit_test(test__f_type_array_polls_decimate_by__works), + cmocka_unit_test(test__f_type_array_polls_decrease_by__works), + cmocka_unit_test(test__f_type_array_polls_increase__works), + cmocka_unit_test(test__f_type_array_polls_increase_by__works), + cmocka_unit_test(test__f_type_array_polls_resize__works), + + cmocka_unit_test(test__f_type_array_pollss_append_all__returns_data_not), + cmocka_unit_test(test__f_type_array_pollss_decimate_by__returns_data_not), + cmocka_unit_test(test__f_type_array_pollss_decrease_by__returns_data_not), + cmocka_unit_test(test__f_type_array_pollss_increase__returns_data_not), + cmocka_unit_test(test__f_type_array_pollss_increase_by__returns_data_not), + + cmocka_unit_test(test__f_type_array_pollss_adjust__works), + cmocka_unit_test(test__f_type_array_pollss_append__works), + cmocka_unit_test(test__f_type_array_pollss_append_all__works), + cmocka_unit_test(test__f_type_array_pollss_decimate_by__works), + cmocka_unit_test(test__f_type_array_pollss_decrease_by__works), + cmocka_unit_test(test__f_type_array_pollss_increase__works), + cmocka_unit_test(test__f_type_array_pollss_increase_by__works), + cmocka_unit_test(test__f_type_array_pollss_resize__works), + cmocka_unit_test(test__f_type_array_states_append_all__returns_data_not), cmocka_unit_test(test__f_type_array_states_decimate_by__returns_data_not), cmocka_unit_test(test__f_type_array_states_decrease_by__returns_data_not), @@ -627,6 +657,24 @@ int main(void) { cmocka_unit_test(test__f_type_array_int128ss_increase_by__parameter_checking), cmocka_unit_test(test__f_type_array_int128ss_resize__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_adjust__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_append__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_append_all__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_decimate_by__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_decrease_by__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_increase__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_increase_by__parameter_checking), + cmocka_unit_test(test__f_type_array_polls_resize__parameter_checking), + + cmocka_unit_test(test__f_type_array_pollss_adjust__parameter_checking), + cmocka_unit_test(test__f_type_array_pollss_append__parameter_checking), + cmocka_unit_test(test__f_type_array_pollss_append_all__parameter_checking), + cmocka_unit_test(test__f_type_array_pollss_decimate_by__parameter_checking), + cmocka_unit_test(test__f_type_array_pollss_decrease_by__parameter_checking), + cmocka_unit_test(test__f_type_array_pollss_increase__parameter_checking), + cmocka_unit_test(test__f_type_array_pollss_increase_by__parameter_checking), + cmocka_unit_test(test__f_type_array_pollss_resize__parameter_checking), + cmocka_unit_test(test__f_type_array_states_adjust__parameter_checking), cmocka_unit_test(test__f_type_array_states_append__parameter_checking), cmocka_unit_test(test__f_type_array_states_append_all__parameter_checking), diff --git a/level_0/f_type_array/tests/unit/c/test-type_array.h b/level_0/f_type_array/tests/unit/c/test-type_array.h index 701e47d..e7f228a 100644 --- a/level_0/f_type_array/tests/unit/c/test-type_array.h +++ b/level_0/f_type_array/tests/unit/c/test-type_array.h @@ -21,8 +21,10 @@ // fll-0 includes. #include +#include #include #include +#include // Test includes. #include "test-type_array-cells_adjust.h" @@ -153,6 +155,22 @@ #include "test-type_array-number_unsignedss_increase.h" #include "test-type_array-number_unsignedss_increase_by.h" #include "test-type_array-number_unsignedss_resize.h" +#include "test-type_array-polls_adjust.h" +#include "test-type_array-polls_append.h" +#include "test-type_array-polls_append_all.h" +#include "test-type_array-polls_decimate_by.h" +#include "test-type_array-polls_decrease_by.h" +#include "test-type_array-polls_increase.h" +#include "test-type_array-polls_increase_by.h" +#include "test-type_array-polls_resize.h" +#include "test-type_array-pollss_adjust.h" +#include "test-type_array-pollss_append.h" +#include "test-type_array-pollss_append_all.h" +#include "test-type_array-pollss_decimate_by.h" +#include "test-type_array-pollss_decrease_by.h" +#include "test-type_array-pollss_increase.h" +#include "test-type_array-pollss_increase_by.h" +#include "test-type_array-pollss_resize.h" #include "test-type_array-states_adjust.h" #include "test-type_array-states_append.h" #include "test-type_array-states_append_all.h"