From: Kevin Day Date: Sun, 31 Dec 2023 03:09:24 +0000 (-0600) Subject: Feature: Add f_random project for providing basic calls to getting and using entropy. X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=3bcf21d5719500fee6fa29f2ac6c22817fb272f1;p=fll Feature: Add f_random project for providing basic calls to getting and using entropy. Update the stand alone build config files. Add the appropriate unit tests. --- diff --git a/build/level_0/settings b/build/level_0/settings index c6cd04d..140879c 100644 --- a/build/level_0/settings +++ b/build/level_0/settings @@ -56,6 +56,7 @@ build_sources_library parse.c parse/utf.c build_sources_library path.c private-path.c path/common.c build_sources_library pipe.c build_sources_library print.c private-print.c print/common.c print/to.c print/private-to.c +build_sources_library random.c build_sources_library rip.c rip/utf.c private-rip.c rip/private-utf.c build_sources_library serialize.c private-serialize.c serialize/common.c build_sources_library signal.c @@ -104,6 +105,7 @@ build_sources_headers parse.h parse/utf.h build_sources_headers path.h path/common.h build_sources_headers pipe.h build_sources_headers print.h print/to.h print/common.h +build_sources_headers random.h build_sources_headers rip.h rip/utf.h build_sources_headers serialize.h serialize/common.h build_sources_headers signal.h signal/common.h diff --git a/build/monolithic/settings b/build/monolithic/settings index b5a6303..ded3fc9 100644 --- a/build/monolithic/settings +++ b/build/monolithic/settings @@ -56,6 +56,7 @@ build_sources_library level_0/parse.c level_0/parse/utf.c build_sources_library level_0/path.c level_0/private-path.c level_0/path/common.c build_sources_library level_0/pipe.c build_sources_library level_0/print.c level_0/private-print.c level_0/print/common.c level_0/print/to.c level_0/print/private-to.c +build_sources_library level_0/random.c build_sources_library level_0/rip.c level_0/rip/utf.c level_0/private-rip.c level_0/rip/private-utf.c build_sources_library level_0/serialize.c level_0/private-serialize.c level_0/serialize/common.c build_sources_library level_0/signal.c @@ -125,6 +126,7 @@ 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 build_sources_headers level_0/print.h level_0/print/to.h level_0/print/common.h +build_sources_headers level_0/random.h build_sources_headers level_0/rip.h level_0/rip/utf.h build_sources_headers level_0/serialize.h level_0/serialize/common.h build_sources_headers level_0/signal.h level_0/signal/common.h diff --git a/build/scripts/bootstrap-example.sh b/build/scripts/bootstrap-example.sh index 07e1a57..8fff508 100644 --- a/build/scripts/bootstrap-example.sh +++ b/build/scripts/bootstrap-example.sh @@ -130,7 +130,7 @@ if [[ ${1} == "individual" ]] ; then ${shell_command} build/scripts/package.sh ${verbose} ${color} rebuild -i if [[ ${?} -eq 0 ]] ; then - for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_status_string f_serialize f_signal f_socket f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do + for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_random f_rip f_serialize f_signal f_socket f_status_string f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do echo && echo "Processing ${i}." && cd package/individual/${i}-${version}/ && diff --git a/build/scripts/test.sh b/build/scripts/test.sh index 60117c8..3e6ef91 100644 --- a/build/scripts/test.sh +++ b/build/scripts/test.sh @@ -71,7 +71,7 @@ test_main() { local verbose= local verbose_common= - local projects="f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_serialize f_signal f_socket f_status_string f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program" + local projects="f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_random f_rip f_serialize f_signal f_socket f_status_string f_thread f_time fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program" local projects_no_tests="f_type" local programs="fss_read" diff --git a/build/stand_alone/byte_dump.config.h b/build/stand_alone/byte_dump.config.h index 979334d..b85aabb 100644 --- a/build/stand_alone/byte_dump.config.h +++ b/build/stand_alone/byte_dump.config.h @@ -8,9 +8,9 @@ // // Example: // echo > /tmp/all.txt -// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done -// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done -// for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done +// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_random f_rip f_serialize f_signal f_socket f_status_string f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done +// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done +// for i in fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done // sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt // echo "#define _di_private_inline_f_print_to_error_" >> /tmp/sorted.txt // echo "#define _di_private_inline_private_f_print_to_error_" >> /tmp/sorted.txt diff --git a/build/stand_alone/fake.config.h b/build/stand_alone/fake.config.h index cc212c2..8fe1594 100644 --- a/build/stand_alone/fake.config.h +++ b/build/stand_alone/fake.config.h @@ -8,9 +8,9 @@ // // Example: // echo > /tmp/all.txt -// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done -// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done -// for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done +// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_random f_rip f_serialize f_signal f_socket f_status_string f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done +// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done +// for i in fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done // sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt // echo "#define _di_private_inline_f_print_to_error_" >> /tmp/sorted.txt // echo "#define _di_private_inline_private_f_print_to_error_" >> /tmp/sorted.txt @@ -838,6 +838,17 @@ #define _di_fll_fss_snatch_mash_ #define _di_fll_fss_snatch_mash_apart_ #define _di_fll_fss_snatch_together_ +#define _di_fll_fss_status_codes_ +#define _di_fll_fss_status_error_ +#define _di_fll_fss_status_string_ +#define _di_fll_fss_status_string_from_ +#define _di_fll_fss_status_string_to_ +#define _di_fll_fss_status_success_ +#define _di_fll_fss_status_warning_ +#define _di_fll_iki_content_escape_ +#define _di_fll_iki_content_partial_escape_ +#define _di_fll_iki_content_partial_unescape_ +#define _di_fll_iki_content_unescape_ #define _di_fll_print_ #define _di_fll_print_character_ #define _di_fll_print_character_safely_ @@ -1017,6 +1028,15 @@ #define _di_fl_print_trim_raw_safely_ #define _di_fl_print_trim_safely_ //#define _di_fl_print_warning_s_ +#define _di_fl_status_string_from_ +#define _di_fl_utf_file_read_ +#define _di_fl_utf_file_read_block_ +#define _di_fl_utf_file_read_range_ +#define _di_fl_utf_file_read_until_ +#define _di_fl_utf_file_write_ +#define _di_fl_utf_file_write_block_ +#define _di_fl_utf_file_write_range_ +#define _di_fl_utf_file_write_until_ #define _di_f_memory_adjust_ #define _di_f_memory_array_adjust_ #define _di_f_memory_array_append_ @@ -1288,6 +1308,30 @@ #define _di_f_print_to_safely_terminated_ #define _di_f_print_to_terminated_ //#define _di_f_print_write_max_d_ +#define _di_f_random_get_ +#define _di_f_random_read_ +#define _di_f_random_seed_ +#define _di_f_random_seed_set_ +#define _di_f_range_double_empty_c_ +#define _di_f_range_doubles_append_ +#define _di_f_range_doubles_append_all_ +#define _di_f_range_doubless_append_ +#define _di_f_range_doubless_append_all_ +#define _di_f_range_doubless_delete_callback_ +#define _di_f_range_doubless_destroy_callback_ +#define _di_f_range_doubless_t_ +#define _di_f_range_doubles_t_ +#define _di_f_range_double_t_ +#define _di_f_range_empty_c_ +#define _di_f_ranges_append_ +#define _di_f_ranges_append_all_ +#define _di_f_rangess_append_ +#define _di_f_rangess_append_all_ +//#define _di_f_rangess_delete_callback_ +#define _di_f_rangess_destroy_callback_ +//#define _di_f_rangess_t_ +//#define _di_f_ranges_t_ +//#define _di_f_range_t_ #define _di_f_rip_ //#define _di_f_rip_dynamic_ #define _di_f_rip_dynamic_nulless_ @@ -1298,6 +1342,15 @@ #define _di_f_rip_utf_dynamic_ #define _di_f_rip_utf_dynamic_nulless_ #define _di_f_rip_utf_nulless_ +#define _di_f_serialize_delimited_delimiter_s_ +#define _di_f_serialize_delimited_splitter_s_ +#define _di_f_serialize_from_simple_ +#define _di_f_serialize_from_simple_get_ +#define _di_f_serialize_from_simple_range_ +#define _di_f_serialize_from_simple_select_ +#define _di_f_serialize_splitter_s_ +#define _di_f_serialize_to_simple_ +#define _di_f_serialize_to_simple_splitter_s_ #define _di_f_signal_action_ //#define _di_f_signal_close_ //#define _di_f_signal_how_t_ @@ -1318,15 +1371,13 @@ #define _di_f_signal_wait_until_ #define _di_f_socket_accept_ #define _di_f_socket_address_family_e_ +#define _di_f_socket_address_form_e_ #define _di_f_socket_addressss_delete_callback_ #define _di_f_socket_addressss_destroy_callback_ #define _di_f_socket_addressss_t_ #define _di_f_socket_addresss_t_ #define _di_f_socket_address_t_ #define _di_f_socket_bind_ -#define _di_f_socket_bind_inet4_ -#define _di_f_socket_bind_inet6_ -#define _di_f_socket_bind_local_ #define _di_f_socket_close_e_ #define _di_f_socket_connect_ #define _di_f_socket_create_ @@ -1362,12 +1413,15 @@ #define _di_f_statess_t_ #define _di_f_states_t_ //#define _di_f_state_t_ +#define _di_f_status_directory_s_ //#define _di_f_status_e_ //#define _di_f_status_mask_d_ #define _di_f_statusss_delete_callback_ #define _di_f_statusss_destroy_callback_ #define _di_f_statusss_t_ #define _di_f_statuss_t_ +#define _di_f_status_string_s_ +#define _di_f_status_string_to_ //#define _di_f_status_t_ //#define _di_f_string_append_ #define _di_f_string_append_assure_ @@ -1461,26 +1515,6 @@ #define _di_f_string_quantityss_t_ #define _di_f_string_quantitys_t_ #define _di_f_string_quantity_t_ -#define _di_f_range_double_empty_c_ -#define _di_f_range_doubles_append_ -#define _di_f_range_doubles_append_all_ -#define _di_f_range_doubless_append_ -#define _di_f_range_doubless_append_all_ -#define _di_f_range_doubless_delete_callback_ -#define _di_f_range_doubless_destroy_callback_ -#define _di_f_range_doubless_t_ -#define _di_f_range_doubles_t_ -#define _di_f_range_double_t_ -#define _di_f_range_empty_c_ -#define _di_f_ranges_append_ -#define _di_f_ranges_append_all_ -#define _di_f_rangess_append_ -#define _di_f_rangess_append_all_ -//#define _di_f_rangess_delete_callback_ -#define _di_f_rangess_destroy_callback_ -//#define _di_f_rangess_t_ -//#define _di_f_ranges_t_ -//#define _di_f_range_t_ #define _di_f_string_seek_line_ #define _di_f_string_seek_line_to_ #define _di_f_string_seek_to_ diff --git a/build/stand_alone/firewall.config.h b/build/stand_alone/firewall.config.h index 979334d..b85aabb 100644 --- a/build/stand_alone/firewall.config.h +++ b/build/stand_alone/firewall.config.h @@ -8,9 +8,9 @@ // // Example: // echo > /tmp/all.txt -// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done -// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done -// for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done +// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_random f_rip f_serialize f_signal f_socket f_status_string f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done +// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done +// for i in fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done // sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt // echo "#define _di_private_inline_f_print_to_error_" >> /tmp/sorted.txt // echo "#define _di_private_inline_private_f_print_to_error_" >> /tmp/sorted.txt diff --git a/build/stand_alone/utf8.config.h b/build/stand_alone/utf8.config.h index 979334d..b85aabb 100644 --- a/build/stand_alone/utf8.config.h +++ b/build/stand_alone/utf8.config.h @@ -8,9 +8,9 @@ // // Example: // echo > /tmp/all.txt -// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_rip f_signal f_socket f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done -// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done -// for i in fll_error fll_execute fll_file fll_fss fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done +// for i in f_type f_status f_memory f_type_array f_string f_utf f_abstruse f_account f_capability f_color f_compare f_console f_control_group f_conversion f_directory f_environment f_execute f_file f_fss f_iki f_limit f_network f_parse f_path f_pipe f_print f_random f_rip f_serialize f_signal f_socket f_status_string f_thread f_time ; do grep -horP '\b_di_f_\w*\b' level_0/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_0/$i/c >> /tmp/all.txt ; done +// for i in fl_control_group fl_conversion fl_directory fl_environment fl_execute fl_fss fl_iki fl_path fl_print fl_status_string fl_utf_file ; do grep -horP '\b_di_fl_\w*\b' level_1/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_1/$i/c >> /tmp/all.txt ; done +// for i in fll_control_group fll_error fll_execute fll_file fll_fss fll_fss_status_string fll_iki fll_print fll_program ; do grep -horP '\b_di_fll_\w*\b' level_2/$i/c >> /tmp/all.txt ; grep -horP '\b_di_macro_\w*\b' level_2/$i/c >> /tmp/all.txt ; done // sort /tmp/all.txt | uniq | sed -e 's|^_|#define &|g' > /tmp/sorted.txt // echo "#define _di_private_inline_f_print_to_error_" >> /tmp/sorted.txt // echo "#define _di_private_inline_private_f_print_to_error_" >> /tmp/sorted.txt diff --git a/level_0/f_random/c/random.c b/level_0/f_random/c/random.c new file mode 100644 index 0000000..7fda850 --- /dev/null +++ b/level_0/f_random/c/random.c @@ -0,0 +1,86 @@ +#include "random.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _di_f_random_get_ + f_status_t f_random_get(long * const destination) { + #ifndef _di_level_0_parameter_checking_ + if (!destination) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + *destination = random(); + + return F_okay; + } +#endif // _di_f_random_get_ + +#ifndef _di_f_random_read_ + f_status_t f_random_read(const unsigned int flag, const f_number_unsigned_t length, f_string_t * const destination, ssize_t * const total) { + #ifndef _di_level_0_parameter_checking_ + if (!destination) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const ssize_t result = getrandom((void *) (*destination), length, flag); + + if (result == -1) { + if (errno == EAGAIN) return F_status_set_error(F_again); + 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 == ENOSYS) return F_status_set_error(F_support_not); + + return F_status_set_error(F_failure); + } + + if (total) { + *total = result; + } + + return F_okay; + } +#endif // _di_f_random_read_ + +#ifndef _di_f_random_seed_ + f_status_t f_random_seed(const unsigned int flag) { + + char raw[4] = { 0 }; + + if (getrandom((void *) raw, sizeof(char) * 4, flag) == -1) { + if (errno == EAGAIN) return F_status_set_error(F_again); + 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 == ENOSYS) return F_status_set_error(F_support_not); + + return F_status_set_error(F_failure); + } + + uint32_t entropy_digit = (uint32_t) ((uint8_t) raw[0]); + entropy_digit += ((uint32_t) ((uint8_t) raw[1])) << 8; + entropy_digit += ((uint32_t) ((uint8_t) raw[2])) << 16; + entropy_digit += ((uint32_t) ((uint8_t) raw[3])) << 24; + + srandom(entropy_digit); + + // Clear the memory before de-allocating to reduce chances of the seed being in free memory. + memset(&entropy_digit, 0, sizeof(uint32_t)); + memset(raw, 0, sizeof(char) * 4); + + return F_okay; + } +#endif // _di_f_random_seed_ + +#ifndef _di_f_random_seed_set_ + f_status_t f_random_seed_set(unsigned int seed) { + + srandom(seed); + + return F_okay; + } +#endif // _di_f_random_seed_set_ + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_random/c/random.h b/level_0/f_random/c/random.h new file mode 100644 index 0000000..f58f739 --- /dev/null +++ b/level_0/f_random/c/random.h @@ -0,0 +1,153 @@ +/** + * FLL - Level 0 + * + * Project: Random + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Provides basic string random capabilities. + */ +#ifndef _F_random_h +#define _F_random_h + +// Libc includes. +#include +#include +#include +#include + +// FLL-0 includes. +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Set the destination string by reading from the random or urandom entropy source directly. + * + * The standard behavior of this is to call random(). + * + * The random seed should be set by either calling f_random_seed(), f_random_seed_set(), or directly calling random(). + * Calling f_random_seed() or f_random_seed_set() to set the seed is generally safer from a library implementation perspective for situations where the implementation of f_random_seed() or f_random_seed_set() and therefore f_random() is changed from the standard behavior. + * + * @param destination + * The destination long to write to. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_random_get_ + extern f_status_t f_random_get(long * const destination); +#endif // _di_f_random_get_ + +/** + * Set the destination string by reading from the random or urandom entropy source directly. + * + * The standard behavior of this is to call getrandom(). + * + * The behavior of this function might also be replaced with calls to other libraries that are highly security specialized. + * If this is done, the meaning behind the flags passed should not be changed. + * + * This calls the Linux-specific getrandom() by default. + * If this is not available or pure POSIX is desired, then the implementation must handle accessing the /dev/random and /dev/urandom themselves (or something equivalent). + * + * @param flag + * The flags to be passed to getrandom(). + * + * Flag bits: + * - GRND_RANDOM: Random data is taken from the random source, such as /dev/random and not the urandom source. + * - GRND_NONBLOCK: Does not block when getting the bits. + * @param length + * The size within the destination string to copy. + * The standard max size is 255. + * This length must not exceed the size allocated in destination or buffer overrun or other security problems may occur. + * @param destination + * The destination string to write to. + * The size of this is not dynamically allocated. + * The caller must assure that the size allocated is not smaller than the size specified in the length parameter. + * + * Must not be NULL. + * @param total + * (optional) The total number of bytes actually read. + * This value is not changed on error. + * + * Set to NULL to not use. + * + * @return + * F_okay on success. + * + * F_again (with error bit) when in non-blocking mode but reading entropy source would block (such as when the entropy source is busy). + * F_buffer (with error bit) if the address represented by the buffer is outside accessible address space. + * F_interrupt (with error bit) if stopping due to an interrupt. + * F_parameter (with error bit) if a parameter is invalid. + * F_support_not (with error bit) if the running kernel does not support the getrandom() call. + */ +#ifndef _di_f_random_read_ + extern f_status_t f_random_read(const unsigned int flag, const f_number_unsigned_t length, f_string_t * const destination, ssize_t * const total); +#endif // _di_f_random_read_ + +/** + * Set the random seed from random entropy, generally for the standard POSIX random() use cases. + * + * The standard behavior of this is to call getrandom(). + * + * The behavior of this function might also be replaced with calls to other libraries that are highly security specialized. + * If this is done, the meaning behind the flags passed should not be changed. + * + * This calls the Linux-specific getrandom() by default. + * If this is not available or pure POSIX is desired, then the implementation must handle accessing the /dev/random and /dev/urandom themselves (or something equivalent). + * + * @param flag + * The flags to be passed to getrandom(). + * + * Flag bits: + * - GRND_RANDOM: Random data is taken from the random source, such as /dev/random and not the urandom source. + * - GRND_NONBLOCK: Does not block when getting the bits. + * + * @return + * F_okay on success. + * + * F_again (with error bit) when in non-blocking mode but reading entropy source would block (such as when the entropy source is busy). + * F_buffer (with error bit) if the address represented by the buffer is outside accessible address space. + * F_interrupt (with error bit) if stopping due to an interrupt. + * F_parameter (with error bit) if a parameter is invalid. + * F_support_not (with error bit) if the running kernel does not support the getrandom() call. + * + * @see getrandom() + * @see srandom() + */ +#ifndef _di_f_random_seed_ + extern f_status_t f_random_seed(const unsigned int flag); +#endif // _di_f_random_seed_ + +/** + * Set the random seed manually using the given seed value, generally for the standard POSIX random() use cases. + * + * The standard behavior of this is to call srandom(). + * + * The behavior of this function might also be replaced with calls to other libraries that are highly security specialized. + * + * @param seed + * The seed value to assign. + * + * @return + * F_okay on success. + * + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_random_seed_set_ + extern f_status_t f_random_seed_set(unsigned int seed); +#endif // _di_f_random_seed_set_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _F_random_h diff --git a/level_0/f_random/data/build/defines b/level_0/f_random/data/build/defines new file mode 100644 index 0000000..4f13080 --- /dev/null +++ b/level_0/f_random/data/build/defines @@ -0,0 +1 @@ +# fss-0000 diff --git a/level_0/f_random/data/build/dependencies b/level_0/f_random/data/build/dependencies new file mode 100644 index 0000000..c06dda5 --- /dev/null +++ b/level_0/f_random/data/build/dependencies @@ -0,0 +1,5 @@ +# fss-0000 + +f_type +f_status +f_string diff --git a/level_0/f_random/data/build/dependencies-tests b/level_0/f_random/data/build/dependencies-tests new file mode 100644 index 0000000..dea3179 --- /dev/null +++ b/level_0/f_random/data/build/dependencies-tests @@ -0,0 +1,3 @@ +# fss-0001 + +cmocka 1.* diff --git a/level_0/f_random/data/build/fakefile b/level_0/f_random/data/build/fakefile new file mode 100644 index 0000000..90a7134 --- /dev/null +++ b/level_0/f_random/data/build/fakefile @@ -0,0 +1,12 @@ +# fss-0005 iki-0002 + +settings: + fail exit + modes individual individual_thread level monolithic clang test fanalyzer thread threadless + + 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 + +main: + + build diff --git a/level_0/f_random/data/build/settings b/level_0/f_random/data/build/settings new file mode 100644 index 0000000..b9bb7f8 --- /dev/null +++ b/level_0/f_random/data/build/settings @@ -0,0 +1,71 @@ +# fss-0001 +# +# Modes: +# - individual: Compile using per project (individual) libraries, does not handle thread or threadless cases. +# - individual_thread: This is required when compiling in individual mode with "thread" mode. +# - level: Compile using per level libraries. +# - monolithic: Compile using per monolithic libraries. +# - clang: Use clang rather than the default, which is generally gcc. +# - test: Compile for a test, such as unit testing. +# - fanalyzer: Compile using GCC's -fanalyzer compile time option. +# - thread: Compile with thread support. +# - threadless: Compile without thread support. +# + +build_name f_random + +version_major 0 +version_minor 7 +version_micro 0 +version_file micro +version_target minor + +modes individual individual_thread level monolithic clang test fanalyzer thread threadless +modes_default individual individual_thread thread + +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 -lf_string + +build_sources_library random.c + +build_sources_headers random.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 +path_object_script script +path_object_shared shared +path_object_static static +path_program_script script +path_program_shared shared +path_program_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 -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses +flags-clang -Wno-logical-op-parentheses +flags-test -O0 -fstack-protector -Wall +flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/ + +flags_library -fPIC +flags_object -fPIC +flags_program -fPIE diff --git a/level_0/f_random/data/build/settings-mocks b/level_0/f_random/data/build/settings-mocks new file mode 100644 index 0000000..9548555 --- /dev/null +++ b/level_0/f_random/data/build/settings-mocks @@ -0,0 +1,57 @@ +# fss-0001 + +build_name f_random + +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 random.c +build_sources_library ../../tests/unit/c/mock-random.c + +build_sources_headers random.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 +flags-coverage --coverage -fprofile-abs-path -fprofile-dir=build/coverage/ + +flags_library -fPIC + +# Inject mocks. +flags -Wl,--wrap=getrandom +flags -Wl,--wrap=random +flags -Wl,--wrap=srandom diff --git a/level_0/f_random/data/build/settings-tests b/level_0/f_random/data/build/settings-tests new file mode 100644 index 0000000..db0efd7 --- /dev/null +++ b/level_0/f_random/data/build/settings-tests @@ -0,0 +1,57 @@ +# fss-0001 +# +# Builds a program that is links to the generated library and is executed to perform tests. +# +# Memory leaks in the test program can be checked for by running valgrind with this executable. +# + +build_name test-f_random + +version_major 0 +version_minor 7 +version_micro 0 +version_file major +version_target major + +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 -lcmocka +build_libraries-individual -lf_memory -lf_random + +build_sources_program test-random-get.c test-random-read.c test-random-seed.c test-random-seed_set.c +build_sources_program test-random.c + +build_script no +build_shared yes +build_static no + +path_headers tests/unit/c +path_sources tests/unit/c + +has_path_standard no +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 + +defines -Ibuild/includes +defines_static -Lbuild/libraries/static +defines_shared -Lbuild/libraries/shared + +flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses +flags-clang -Wno-logical-op-parentheses +flags-test -fstack-protector -Wall +flags-coverage -O0 --coverage -fprofile-abs-path -fprofile-dir=build/coverage/ + +flags_program -fPIE diff --git a/level_0/f_random/data/build/testfile b/level_0/f_random/data/build/testfile new file mode 100644 index 0000000..709fd21 --- /dev/null +++ b/level_0/f_random/data/build/testfile @@ -0,0 +1,63 @@ +# fss-0005 iki-0002 + +settings: + load_build yes + fail exit + + 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 + environment CMOCKA_XML_FILE CMOCKA_MESSAGE_OUTPUT CMOCKA_TEST_ABORT + + # Cmocka is not fully thread-safe, set this to "1" to have cmocka call abort() on a test failure. + #CMOCKA_TEST_ABORT 1 + + # One of: STDOUT, SUBUNIT, TAP, or XML. + #define CMOCKA_MESSAGE_OUTPUT STDOUT + + # When in "XML" output mode, output to this file rather than stdout. + #define CMOCKA_XML_FILE ./out.xml + +main: + build settings-mocks individual test + build settings-tests individual test + + operate build_path + operate ld_library_path + + if exist parameter:"build_path"programs/shared/test-f_random + shell parameter:"build_path"programs/shared/test-f_random + + if exist parameter:"build_path"programs/static/test-f_random + shell parameter:"build_path"programs/static/test-f_random + + if not exist parameter:"build_path"programs/shared/test-f_random + and not exist parameter:"build_path"programs/static/test-f_random + operate not_created + +not_created: + print + print 'context:"error"Failed to test due to being unable to find either a shared or static test binary to perform tests. context:"reset"' + + exit failure + +build_path: + parameter build_path build/ + + if parameter build:value + parameter build_path parameter:"build:value" + +ld_library_path: + if define LD_LIBRARY_PATH + and parameter work:value + define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared:parameter:"work:value"libraries/shared:define:"LD_LIBRARY_PATH"' + + else + if define LD_LIBRARY_PATH + define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared:define:"LD_LIBRARY_PATH"' + + else + if parameter work:value + define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared:parameter:"work:value"libraries/shared' + + else + define LD_LIBRARY_PATH 'parameter:"build_path"libraries/shared' diff --git a/level_0/f_random/tests/unit/c/mock-random.c b/level_0/f_random/tests/unit/c/mock-random.c new file mode 100644 index 0000000..ec2dc0c --- /dev/null +++ b/level_0/f_random/tests/unit/c/mock-random.c @@ -0,0 +1,32 @@ +#include "mock-random.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ssize_t __wrap_getrandom(void *buf, size_t buflen, unsigned int flags) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return mock_type(ssize_t); + } + + memcpy(buf, mock_type(void *), buflen); + + return mock_type(ssize_t); +} + +long __wrap_random(void) { + return mock_type(long); +} + +void __wrap_srandom(unsigned seed) { + // Do nothing. +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_random/tests/unit/c/mock-random.h b/level_0/f_random/tests/unit/c/mock-random.h new file mode 100644 index 0000000..205f366 --- /dev/null +++ b/level_0/f_random/tests/unit/c/mock-random.h @@ -0,0 +1,39 @@ +/** + * FLL - Level 0 + * + * Project: Random + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the random project. + */ +#ifndef _MOCK__random_h +#define _MOCK__random_h + +// Libc includes. +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-0 includes. +#include + +#ifdef __cplusplus +extern "C" { +#endif + +const static int mock_errno_generic = 32767; + +extern ssize_t __wrap_getrandom(void *buf, size_t buflen, unsigned int flags); +extern long __wrap_random(void); +extern void __wrap_srandom(unsigned seed); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _MOCK__random_h diff --git a/level_0/f_random/tests/unit/c/test-random-get.c b/level_0/f_random/tests/unit/c/test-random-get.c new file mode 100644 index 0000000..3ad505b --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-get.c @@ -0,0 +1,36 @@ +#include "test-random.h" +#include "test-random-get.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_random_get__works(void **state) { + + const long mocked_data = 1234; + + { + long data = 0; + + will_return(__wrap_random, mocked_data); + + const f_status_t status = f_random_get(&data); + + assert_int_equal(status, F_okay); + + assert_int_equal(data, mocked_data); + } +} + +void test__f_random_get__parameter_checking(void **state) { + + { + const f_status_t status = f_random_get(0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_random/tests/unit/c/test-random-get.h b/level_0/f_random/tests/unit/c/test-random-get.h new file mode 100644 index 0000000..e991e3b --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-get.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Random + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the get function in the random project. + */ +#ifndef _TEST__F_random_get_h +#define _TEST__F_random_get_h + +/** + * Test that the function works. + * + * @see f_random_get() + */ +extern void test__f_random_get__works(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_random_get() + */ +extern void test__f_random_get__parameter_checking(void **state); + +#endif // _TEST__F_random_get_h diff --git a/level_0/f_random/tests/unit/c/test-random-read.c b/level_0/f_random/tests/unit/c/test-random-read.c new file mode 100644 index 0000000..9c33377 --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-read.c @@ -0,0 +1,115 @@ +#include "test-random.h" +#include "test-random-read.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_random_read__fails(void **state) { + + int errnos[] = { + EAGAIN, + EFAULT, + EINTR, + EINVAL, + ENOSYS, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_again, + F_buffer, + F_interrupt, + F_parameter, + F_support_not, + F_failure, + }; + + for (uint8_t i = 0; i < 6; ++i) { + + will_return(__wrap_getrandom, true); + will_return(__wrap_getrandom, errnos[i]); + will_return(__wrap_getrandom, -1); + + f_char_t buffer[4] = { 0, 0, 0, 0 }; + f_string_t buffer_ptr = buffer; + ssize_t total = 0; + + const f_status_t status = f_random_read(0, 4, &buffer_ptr, &total); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + + for (uint8_t i = 0; i < 6; ++i) { + + will_return(__wrap_getrandom, true); + will_return(__wrap_getrandom, errnos[i]); + will_return(__wrap_getrandom, -1); + + f_char_t buffer[4] = { 0, 0, 0, 0 }; + f_string_t buffer_ptr = buffer; + + const f_status_t status = f_random_read(0, 4, &buffer_ptr, 0); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_random_read__works(void **state) { + + const f_number_unsigned_t length = 4; + + { + char mocked_data[4] = "abcd"; + f_char_t buffer[4] = { 0, 0, 0, 0 }; + f_string_t buffer_ptr = buffer; + ssize_t total = 0; + + will_return(__wrap_getrandom, false); + will_return(__wrap_getrandom, (void *) mocked_data); + will_return(__wrap_getrandom, length); + + const f_status_t status = f_random_read(0, length, &buffer_ptr, &total); + + assert_int_equal(status, F_okay); + + assert_int_equal(buffer[0], mocked_data[0]); + assert_int_equal(buffer[1], mocked_data[1]); + assert_int_equal(buffer[2], mocked_data[2]); + assert_int_equal(buffer[3], mocked_data[3]); + + assert_int_equal(total, length); + } + + { + char mocked_data[4] = "abcd"; + f_char_t buffer[4] = { 0, 0, 0, 0 }; + f_string_t buffer_ptr = buffer; + + will_return(__wrap_getrandom, false); + will_return(__wrap_getrandom, (void *) mocked_data); + will_return(__wrap_getrandom, length); + + const f_status_t status = f_random_read(0, length, &buffer_ptr, 0); + + assert_int_equal(status, F_okay); + + assert_int_equal(buffer[0], mocked_data[0]); + assert_int_equal(buffer[1], mocked_data[1]); + assert_int_equal(buffer[2], mocked_data[2]); + assert_int_equal(buffer[3], mocked_data[3]); + } +} + +void test__f_random_read__parameter_checking(void **state) { + + { + const f_status_t status = f_random_read(0, 0, 0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_random/tests/unit/c/test-random-read.h b/level_0/f_random/tests/unit/c/test-random-read.h new file mode 100644 index 0000000..d60244b --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-read.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Random + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the read function in the random project. + */ +#ifndef _TEST__F_random_read_h +#define _TEST__F_random_read_h + +/** + * Test that the function fails. + * + * @see f_random_read() + */ +extern void test__f_random_read__fails(void **state); + +/** + * Test that the function works. + * + * @see f_random_read() + */ +extern void test__f_random_read__works(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_random_read() + */ +extern void test__f_random_read__parameter_checking(void **state); + +#endif // _TEST__F_random_read_h diff --git a/level_0/f_random/tests/unit/c/test-random-seed.c b/level_0/f_random/tests/unit/c/test-random-seed.c new file mode 100644 index 0000000..2edf1a3 --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-seed.c @@ -0,0 +1,59 @@ +#include "test-random.h" +#include "test-random-seed.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_random_seed__fails(void **state) { + + int errnos[] = { + EAGAIN, + EFAULT, + EINTR, + EINVAL, + ENOSYS, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_again, + F_buffer, + F_interrupt, + F_parameter, + F_support_not, + F_failure, + }; + + for (uint8_t i = 0; i < 6; ++i) { + + will_return(__wrap_getrandom, true); + will_return(__wrap_getrandom, errnos[i]); + will_return(__wrap_getrandom, -1); + + const f_status_t status = f_random_seed(0); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_random_seed__works(void **state) { + + const f_number_unsigned_t length = 4; + + { + char mocked_data[4] = "abcd"; + + will_return(__wrap_getrandom, false); + will_return(__wrap_getrandom, (void *) mocked_data); + will_return(__wrap_getrandom, length); + + const f_status_t status = f_random_seed(0); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_random/tests/unit/c/test-random-seed.h b/level_0/f_random/tests/unit/c/test-random-seed.h new file mode 100644 index 0000000..416ef34 --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-seed.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Random + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the seed function in the random project. + */ +#ifndef _TEST__F_random_seed_h +#define _TEST__F_random_seed_h + +/** + * Test that the function fails. + * + * @see f_random_seed() + */ +extern void test__f_random_seed__fails(void **state); + +/** + * Test that the function works. + * + * @see f_random_seed() + */ +extern void test__f_random_seed__works(void **state); + +#endif // _TEST__F_random_seed_h diff --git a/level_0/f_random/tests/unit/c/test-random-seed_set.c b/level_0/f_random/tests/unit/c/test-random-seed_set.c new file mode 100644 index 0000000..928c7bf --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-seed_set.c @@ -0,0 +1,19 @@ +#include "test-random.h" +#include "test-random-seed_set.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_random_seed_set__works(void **state) { + + { + const f_status_t status = f_random_seed_set(1); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_random/tests/unit/c/test-random-seed_set.h b/level_0/f_random/tests/unit/c/test-random-seed_set.h new file mode 100644 index 0000000..62862f9 --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random-seed_set.h @@ -0,0 +1,20 @@ +/** + * FLL - Level 0 + * + * Project: Random + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the seed function in the random project. + */ +#ifndef _TEST__F_random_seed_set_h +#define _TEST__F_random_seed_set_h + +/** + * Test that the function works. + * + * @see f_random_seed_set() + */ +extern void test__f_random_seed_set__works(void **state); + +#endif // _TEST__F_random_seed_h diff --git a/level_0/f_random/tests/unit/c/test-random.c b/level_0/f_random/tests/unit/c/test-random.c new file mode 100644 index 0000000..f5d04b5 --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random.c @@ -0,0 +1,44 @@ +#include "test-random.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int setup(void **state) { + + return 0; +} + +int setdown(void **state) { + + errno = 0; + + return 0; +} + +int main(void) { + + const struct CMUnitTest tests[] = { + cmocka_unit_test(test__f_random_read__fails), + cmocka_unit_test(test__f_random_seed__fails), + + cmocka_unit_test(test__f_random_get__works), + cmocka_unit_test(test__f_random_read__works), + cmocka_unit_test(test__f_random_seed__works), + cmocka_unit_test(test__f_random_seed_set__works), + + #ifndef _di_level_0_parameter_checking_ + cmocka_unit_test(test__f_random_get__parameter_checking), + cmocka_unit_test(test__f_random_read__parameter_checking), + + // f_random_seed() doesn't use parameter checking. + // f_random_seed_set() doesn't use parameter checking. + #endif // _di_level_0_parameter_checking_ + }; + + return cmocka_run_group_tests(tests, setup, setdown); +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_random/tests/unit/c/test-random.h b/level_0/f_random/tests/unit/c/test-random.h new file mode 100644 index 0000000..546118d --- /dev/null +++ b/level_0/f_random/tests/unit/c/test-random.h @@ -0,0 +1,75 @@ +/** + * FLL - Level 0 + * + * Project: Random + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the random project. + */ +#ifndef _TEST__F_random_h +#define _TEST__F_random_h + +// Libc includes. +#include +#include +#include +#include + +// cmocka includes. +#include + +// FLL-0 includes. +#include + +// Mock includes. +#include "mock-random.h" + +// Test includes. +#include "test-random-get.h" +#include "test-random-read.h" +#include "test-random-seed.h" +#include "test-random-seed_set.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Perform any setup operations. + * + * @param state + * The test state. + * + * @return + * The status of this function, where 0 means success. + */ +extern int setup(void **state); + +/** + * Peform any setdown operations. + * + * @param state + * The test state. + * + * @return + * The status of this function, where 0 means success. + */ +extern int setdown(void **state); + +/** + * Run all tests. + * + * @return + * The final result of the tests. + * + * @see cmocka_run_group_tests() + * @see cmocka_unit_test() + */ +extern int main(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _TEST__F_random_h