From 0d6fe7db24fa436e14b960c311339b60847a365e Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sun, 31 Aug 2025 15:49:01 -0500 Subject: [PATCH] Update: Finish adding functions to f_schedule. This adds: - `f_schedule_affinity_get()` - `f_schedule_affinity_set()` - `f_schedule_attribute_get()` - `f_schedule_attribute_set()` - `f_schedule_policy_robin_interval_get()` - `f_schedule_priority_get_max()` - `f_schedule_priority_get_min()` - `f_schedule_yield()` Note: the `f_schedule_attribute_get()` and `f_schedule_attribute_set()` have to use `syscall()` directly due to design problems with glibc. The `struct sched_attr` is also an incomplete/broken type in glibc. I have declared my own type based on the kernel structure. It is unclear on how well this will work in practice. I am also uncertain of the best way to mock a variadic function like `syscall()`. The mocks for these are therefore incomplete. --- level_0/f_schedule/c/schedule.c | 164 ++++++++++++++ level_0/f_schedule/c/schedule.h | 239 ++++++++++++++++++++- level_0/f_schedule/c/schedule/common.h | 104 +++++++++ level_0/f_schedule/data/build/settings-mocks | 9 + level_0/f_schedule/data/build/settings-tests | 7 +- level_0/f_schedule/tests/unit/c/mock-schedule.c | 126 +++++++++++ level_0/f_schedule/tests/unit/c/mock-schedule.h | 14 +- .../tests/unit/c/test-schedule-affinity_get.c | 89 ++++++++ .../tests/unit/c/test-schedule-affinity_get.h | 34 +++ .../tests/unit/c/test-schedule-affinity_set.c | 56 +++++ .../tests/unit/c/test-schedule-affinity_set.h | 27 +++ .../tests/unit/c/test-schedule-attribute_get.c | 67 ++++++ .../tests/unit/c/test-schedule-attribute_get.h | 34 +++ .../tests/unit/c/test-schedule-attribute_set.c | 60 ++++++ .../tests/unit/c/test-schedule-attribute_set.h | 27 +++ .../tests/unit/c/test-schedule-policy_get.c | 1 - .../c/test-schedule-policy_robin_interval_get.c | 70 ++++++ .../c/test-schedule-policy_robin_interval_get.h | 34 +++ .../tests/unit/c/test-schedule-priority_get.c | 1 - .../tests/unit/c/test-schedule-priority_get_max.c | 63 ++++++ .../tests/unit/c/test-schedule-priority_get_max.h | 34 +++ .../tests/unit/c/test-schedule-priority_get_min.c | 63 ++++++ .../tests/unit/c/test-schedule-priority_get_min.h | 34 +++ .../tests/unit/c/test-schedule-value_get.c | 1 - .../f_schedule/tests/unit/c/test-schedule-yield.c | 44 ++++ .../f_schedule/tests/unit/c/test-schedule-yield.h | 27 +++ level_0/f_schedule/tests/unit/c/test-schedule.c | 32 +++ level_0/f_schedule/tests/unit/c/test-schedule.h | 8 + 28 files changed, 1452 insertions(+), 17 deletions(-) create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.h create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.h create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.h create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.h create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.h create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.h create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.h create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-yield.c create mode 100644 level_0/f_schedule/tests/unit/c/test-schedule-yield.h diff --git a/level_0/f_schedule/c/schedule.c b/level_0/f_schedule/c/schedule.c index 2c38f63..f2d0e46 100644 --- a/level_0/f_schedule/c/schedule.c +++ b/level_0/f_schedule/c/schedule.c @@ -4,6 +4,96 @@ extern "C" { #endif +#ifndef _di_f_schedule_affinity_get_ + f_status_t f_schedule_affinity_get(const pid_t id, size_t * const size, cpu_set_t * const affinity) { + #ifndef _di_level_0_parameter_checking_ + if (!size) return F_status_set_error(F_parameter); + if (!affinity) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + cpu_set_t set = { 0 }; + + const int result = sched_getaffinity(id, *size, &set); + + if (result == -1) { + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == ESRCH) return F_status_set_error(F_search); + + return F_status_set_error(F_failure); + } + + *size = (size_t) result; + *affinity = set; + + return F_okay; + } +#endif // _di_f_schedule_affinity_get_ + +#ifndef _di_f_schedule_affinity_set_ + f_status_t f_schedule_affinity_set(const pid_t id, const size_t size, const cpu_set_t affinity) { + + if (sched_setaffinity(id, size, &affinity) == -1) { + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == ESRCH) return F_status_set_error(F_search); + + return F_status_set_error(F_failure); + } + + return F_okay; + } +#endif // _di_f_schedule_affinity_set_ + +#ifndef _di_f_schedule_attribute_get_ + f_status_t f_schedule_attribute_get(const pid_t id, const unsigned int flags, const unsigned int size, f_schedule_attribute_t * const attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!size) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + f_schedule_attribute_t result = f_schedule_attribute_t_initialize; + + if (syscall(SYS_sched_getattr, id, &result, size, flags) == -1) { + if (errno == E2BIG) return F_status_set_error(F_too_large); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ESRCH) return F_status_set_error(F_search); + + return F_status_set_error(F_failure); + } + + #undef internal_macro_f_schedule_attribute_get + + *attribute = result; + + return F_okay; + } +#endif // _di_f_schedule_attribute_get_ + +#ifndef _di_f_schedule_attribute_set_ + f_status_t f_schedule_attribute_set(const pid_t id, const unsigned int flags, const f_schedule_attribute_t attribute) { + + // The standard shows the attribute as a non-constant. + // Create a new non-constant to pass the attributes such that this function can still safely specify attribute parameter as a constant. + f_schedule_attribute_t attr = attribute; + + if (syscall(SYS_sched_setattr, id, &attr, flags) == -1) { + if (errno == E2BIG) return F_status_set_error(F_too_large); + if (errno == EBUSY) return F_status_set_error(F_busy); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EOPNOTSUPP) return F_status_set_error(F_support_not); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == ESRCH) return F_status_set_error(F_search); + + return F_status_set_error(F_failure); + } + + return F_okay; + } +#endif // _di_f_schedule_attribute_set_ + #ifndef _di_f_schedule_nice_ f_status_t f_schedule_nice(const int niceness) { @@ -45,6 +135,29 @@ extern "C" { } #endif // _di_f_schedule_policy_get_ +#ifndef _di_f_schedule_policy_robin_interval_get_ + f_status_t f_schedule_policy_robin_interval_get(const pid_t id, f_time_spec_t * const interval) { + #ifndef _di_level_0_parameter_checking_ + if (!interval) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + f_time_spec_t result = f_time_spec_t_initialize; + + if (sched_rr_get_interval(id, &result) == -1) { + if (errno == EFAULT) return F_status_set_error(F_buffer); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EPERM) return F_status_set_error(F_prohibited); + if (errno == ESRCH) return F_status_set_error(F_search); + + return F_status_set_error(F_failure); + } + + *interval = result; + + return F_okay; + } +#endif // _di_f_schedule_policy_robin_interval_get_ + #ifndef _di_f_schedule_policy_set_ f_status_t f_schedule_policy_set(const pid_t id, const int policy, const f_schedule_value_t * const value) { #ifndef _di_level_0_parameter_checking_ @@ -86,6 +199,46 @@ extern "C" { } #endif // _di_f_schedule_priority_get_ +#ifndef _di_f_schedule_priority_get_max_ + f_status_t f_schedule_priority_get_max(const int type, int * const priority) { + #ifndef _di_level_0_parameter_checking_ + if (!priority) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int result = sched_get_priority_max(type); + + if (result == -1) { + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + *priority = result; + + return F_okay; + } +#endif // _di_f_schedule_priority_get_max_ + +#ifndef _di_f_schedule_priority_get_min_ + f_status_t f_schedule_priority_get_min(const int type, int * const priority) { + #ifndef _di_level_0_parameter_checking_ + if (!priority) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int result = sched_get_priority_min(type); + + if (result == -1) { + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + *priority = result; + + return F_okay; + } +#endif // _di_f_schedule_priority_get_min_ + #ifndef _di_f_schedule_priority_set_ f_status_t f_schedule_priority_set(const int type, const id_t id, const int priority) { @@ -142,6 +295,17 @@ extern "C" { } #endif // _di_f_schedule_value_set_ +#ifndef _di_f_schedule_yield_ + f_status_t f_schedule_yield() { + + if (sched_yield() == -1) { + return F_status_set_error(F_failure); + } + + return F_okay; + } +#endif // _di_f_schedule_yield_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_schedule/c/schedule.h b/level_0/f_schedule/c/schedule.h index 9dca3df..53cca54 100644 --- a/level_0/f_schedule/c/schedule.h +++ b/level_0/f_schedule/c/schedule.h @@ -10,9 +10,15 @@ #ifndef _F_schedule_h #define _F_schedule_h +// To enable appropiate sched.h functions and macros. +#ifndef _GNU_SOURCE + #define _GNU_SOURCE +#endif // _GNU_SOURCE + // Libc includes. #include #include +#include #include #include @@ -28,6 +34,132 @@ extern "C" { #endif /** + * Get the processor affinity. + * + * @param id + * The process ID. + * + * If id is 0, then the affinity of the current process thread is returned. + * @param size + * The size of the affinity set in bytes. + * + * This must be set to the expected affinity set size. + * If this value is too low, then F_parameter (with error bit) may be returned. + * + * On success, the size is modified with the retrieved size of the affinity set. + * + * Must not be NULL. + * @param affinity + * The retrieved affinity set. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_buffer (with error bit) if unable to populate the affinity set. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if a ID is valid but the effective ID or real ID does not match the callers and CAP_SYS_NICE is not set. + * F_search (with error bit) if ID could not be found. + * + * F_failure (with error bit) for any other error. + * + * @see sched_getaffinity() + */ +#ifndef _di_f_schedule_affinity_get_ + extern f_status_t f_schedule_affinity_get(const pid_t id, size_t * const size, cpu_set_t * const affinity); +#endif // _di_f_schedule_affinity_get_ + +/** + * Set the processor affinity. + * + * @param id + * The process ID, process group ID, or user ID. + * @param size + * The size of the affinity set in bytes. + * @param affinity + * The affinity set to assign. + * + * @return + * F_okay on success. + * + * F_buffer (with error bit) if unable to populate the affinity set. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if a ID is valid but the effective ID or real ID does not match the callers and CAP_SYS_NICE is not set. + * F_search (with error bit) if ID could not be found. + * + * F_failure (with error bit) for any other error. + * + * @see sched_setaffinity() + */ +#ifndef _di_f_schedule_affinity_set_ + extern f_status_t f_schedule_affinity_set(const pid_t id, const size_t size, const cpu_set_t affinity); +#endif // _di_f_schedule_affinity_set_ + +/** + * Get the processor attribute. + * + * @param id + * The process ID. + * + * If id is 0, then the attribute of the current process thread is returned. + * @param flags + * The flags beyond the standard f_schedule_attribute_*_d. + * This is pretty much always 0. + * @param size + * The size of the attribute structure in bytes.. + * @param attribute + * The retrieved attribute set. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_search (with error bit) if ID could not be found. + * F_too_large (with error bit) if the size and attribute are too small. + * + * F_failure (with error bit) for any other error. + * + * @see sched_getattr() + * @see SYS_sched_getattr() + */ +#ifndef _di_f_schedule_attribute_get_ + extern f_status_t f_schedule_attribute_get(const pid_t id, const unsigned int flags, const unsigned int size, f_schedule_attribute_t * const attribute); +#endif // _di_f_schedule_attribute_get_ + +/** + * Set the processor attribute. + * + * @param id + * The process ID, process group ID, or user ID. + * @param flags + * The flags beyond the standard f_schedule_attribute_*_d. + * This is pretty much always 0. + * @param attribute + * The attribute set to assign. + * + * @return + * F_okay on success. + * + * F_busy (with error bit) if scheduler is too busy to perform operation. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if a ID is valid but the effective ID or real ID does not match the callers and CAP_SYS_NICE is not set. + * F_search (with error bit) if ID could not be found. + * F_support_not (with error bit) if the system does not support this operation for the current scheduler policy. + * F_too_large (with error bit) if the size and attribute are too small. + * + * F_failure (with error bit) for any other error. + * + * @see sched_setattr() + * @see SYS_sched_setattr() + */ +#ifndef _di_f_schedule_attribute_set_ + extern f_status_t f_schedule_attribute_set(const pid_t id, const unsigned int flags, const f_schedule_attribute_t attribute); +#endif // _di_f_schedule_attribute_set_ + +/** * Set the niceness of the current process. * * The niceness affects the priority of the process for processor scheduling purposes. @@ -86,6 +218,34 @@ extern "C" { #endif // _di_f_schedule_policy_get_ /** + * Get the interval of the round-robin process policy. + * + * @param id + * The process ID. + * + * If id is 0, then the interval of the current process thread is returned. + * @param interval + * The retrieved interval. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_buffer (with error bit) if unable to populate interval with the time. + * F_parameter (with error bit) if a parameter is invalid. + * F_search (with error bit) if ID could not be found. + * F_support_not (with error bit) if the system call is not supported. + * + * F_failure (with error bit) for any other error. + * + * @see sched_rr_get_interval() + */ +#ifndef _di_f_schedule_policy_robin_interval_get_ + extern f_status_t f_schedule_policy_robin_interval_get(const pid_t id, f_time_spec_t * const interval); +#endif // _di_f_schedule_policy_robin_interval_get_ + +/** * Set the process policy. * * @param id @@ -144,6 +304,60 @@ extern "C" { #endif // _di_f_schedule_priority_get_ /** + * Get the maximum process priority available. + * + * @param type + * The type being whose schedule priority is being retrieved + * One of f_schedule_priority_*_d. + * @param priority + * The retrieved priority. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_access_denied (with error bit) If caller has insufficient priviledges to get the priority. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if a ID is valid but the effective ID or real ID does not match the callers and CAP_SYS_NICE is not set. + * F_search (with error bit) if ID could not be found. + * + * F_failure (with error bit) for any other error. + * + * @see sched_get_priority_max() + */ +#ifndef _di_f_schedule_priority_get_max_ + extern f_status_t f_schedule_priority_get_max(const int type, int * const priority); +#endif // _di_f_schedule_priority_get_max_ + +/** + * Get the minimum process priority available. + * + * @param type + * The type being whose schedule priority is being retrieved + * One of f_schedule_priority_*_d. + * @param priority + * The retrieved priority. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_access_denied (with error bit) If caller has insufficient priviledges to get the priority. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if a ID is valid but the effective ID or real ID does not match the callers and CAP_SYS_NICE is not set. + * F_search (with error bit) if ID could not be found. + * + * F_failure (with error bit) for any other error. + * + * @see sched_get_priority_min() + */ +#ifndef _di_f_schedule_priority_get_min_ + extern f_status_t f_schedule_priority_get_min(const int type, int * const priority); +#endif // _di_f_schedule_priority_get_min_ + +/** * Set the process priority. * * @param type @@ -222,17 +436,20 @@ extern "C" { extern f_status_t f_schedule_value_set(const pid_t id, const f_schedule_value_t * const value); #endif // _di_f_schedule_value_set_ -/* - * @todo: add all of these: - sched_get_priority_max() - sched_get_priority_min() - sched_rr_get_interval() - sched_yield() - sched_setaffinity() - sched_getaffinity() - sched_setattr() - sched_getattr() -*/ +/** + * Explicitly release contol of the CPU so that other process threads can utilize the CPU. + * + * + * @return + * F_okay on success. + * + * F_failure (with error bit) for any other error. + * + * @see sched_yield() + */ +#ifndef _di_f_schedule_yield_ + extern f_status_t f_schedule_yield(); +#endif // _di_f_schedule_yield_ #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_schedule/c/schedule/common.h b/level_0/f_schedule/c/schedule/common.h index 2f1d6fa..b53d223 100644 --- a/level_0/f_schedule/c/schedule/common.h +++ b/level_0/f_schedule/c/schedule/common.h @@ -17,6 +17,24 @@ extern "C" { #endif /** + * Thread scheduler attribute defines. + * + * f_schedule_attribute_*_d: + * - clamp_max: The schedule util maximum is set. + * - clamp_min: The schedule util minimum is set. + * - fork_reset: Forked child processes do not inherit scheduling policies. + * - overrun: Allow accessing overrun information. + * - reclaim: Enabling reclaiming unused bandwidth. + */ +#ifndef _di_f_schedule_attribute_d_ + #define f_schedule_attribute_clamp_max_d SCHED_FLAG_UTIL_CLAMP_MAX + #define f_schedule_attribute_clamp_min_d SCHED_FLAG_UTIL_CLAMP_MIN + #define f_schedule_attribute_fork_reset_d SCHED_FLAG_RESET_ON_FORK + #define f_schedule_attribute_overrun_d SCHED_FLAG_DL_OVERRUN + #define f_schedule_attribute_reclaim_d SCHED_FLAG_RECLAIM +#endif // _di_f_schedule_attribute_d_ + +/** * Thread scheduler policy defines. * * f_schedule_policy_*_d: @@ -49,6 +67,92 @@ extern "C" { #endif // _di_f_schedule_priority_d_ /** + * A typedef for representing a sched_att structure from . + * + * Note: "struct sched_attr" is an incomplete type on systems like glibc. + * The approach here is to entirely replace it and use syscalls. + * + * The following is the known structure (be sure to check types.h for the actual structure on any particular system): + * - __u32 size + * - __u32 sched_policy + * - __u64 sched_flags + * - __s32 sched_nice + * - __u32 sched_priority + * - __u64 sched_runtime + * - __u64 sched_deadline + * - __u64 sched_period + * - __u32 sched_util_min + * - __u32 sched_util_max + */ +#ifndef _di_f_schedule_attribute_t_ + typedef struct { + uint32_t size; + uint32_t sched_policy; + uint64_t sched_flags; + int32_t sched_nice; + uint32_t sched_priority; + uint64_t sched_runtime; + uint64_t sched_deadline; + uint64_t sched_period; + } f_schedule_attribute_t; + + #define f_schedule_attribute_t_initialize { \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + } + + #define macro_f_schedule_attribute_t_initialize_1(size) { \ + size, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + } + + #define macro_f_schedule_attribute_t_initialize_2(size, policy, flags) { \ + size, \ + policy, \ + flags, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + } + + #define macro_f_schedule_attribute_t_initialize_3(size, policy, flags, nice, priority) { \ + size, \ + policy, \ + flags, \ + nice, \ + priority, \ + 0, \ + 0, \ + 0, \ + } + + #define macro_f_schedule_attribute_t_initialize_4(size, policy, flags, nice, priority, runtime, deadline, period) { \ + size, \ + policy, \ + flags, \ + nice, \ + priority, \ + runtime, \ + deadline, \ + period, \ + } +#endif // _di_f_schedule_attribute_t_ + +/** * A typedef for representing a sched_param structure from . * * Note that the actual path might be something like . diff --git a/level_0/f_schedule/data/build/settings-mocks b/level_0/f_schedule/data/build/settings-mocks index af58b0c..267f766 100644 --- a/level_0/f_schedule/data/build/settings-mocks +++ b/level_0/f_schedule/data/build/settings-mocks @@ -66,8 +66,17 @@ flags_library -fPIC # Inject mocks. flags -Wl,--wrap=getpriority flags -Wl,--wrap=nice +flags -Wl,--wrap=sched_getaffinity +#flags -Wl,--wrap=sched_getattr +flags -Wl,--wrap=sched_get_priority_max +flags -Wl,--wrap=sched_get_priority_min flags -Wl,--wrap=sched_getparam flags -Wl,--wrap=sched_getscheduler +flags -Wl,--wrap=sched_rr_get_interval +flags -Wl,--wrap=sched_setaffinity +#flags -Wl,--wrap=sched_setattr flags -Wl,--wrap=sched_setparam flags -Wl,--wrap=sched_setscheduler +flags -Wl,--wrap=sched_yield flags -Wl,--wrap=setpriority +#flags -Wl,--wrap=syscall diff --git a/level_0/f_schedule/data/build/settings-tests b/level_0/f_schedule/data/build/settings-tests index 670b31b..30c164e 100644 --- a/level_0/f_schedule/data/build/settings-tests +++ b/level_0/f_schedule/data/build/settings-tests @@ -25,10 +25,13 @@ build_language c build_libraries -lc -lcmocka build_libraries-individual -lf_memory -lf_string -lf_schedule +build_sources_program test-schedule-affinity_get.c test-schedule-affinity_set.c +build_sources_program test-schedule-attribute_get.c test-schedule-attribute_set.c build_sources_program test-schedule-nice.c -build_sources_program test-schedule-policy_get.c test-schedule-policy_set.c -build_sources_program test-schedule-priority_get.c test-schedule-priority_set.c +build_sources_program test-schedule-policy_get.c test-schedule-policy_robin_interval_get.c test-schedule-policy_set.c +build_sources_program test-schedule-priority_get.c test-schedule-priority_get_max.c test-schedule-priority_get_min.c test-schedule-priority_set.c build_sources_program test-schedule-value_get.c test-schedule-value_set.c +build_sources_program test-schedule-yield.c build_sources_program test-schedule.c build_script no diff --git a/level_0/f_schedule/tests/unit/c/mock-schedule.c b/level_0/f_schedule/tests/unit/c/mock-schedule.c index 513aabc..9e1726c 100644 --- a/level_0/f_schedule/tests/unit/c/mock-schedule.c +++ b/level_0/f_schedule/tests/unit/c/mock-schedule.c @@ -4,6 +4,8 @@ extern "C" { #endif +int mock_unwrap_syscall = 1; + int __wrap_getpriority(int which, id_t who) { const bool failure = mock_type(bool); @@ -30,6 +32,92 @@ int __wrap_nice(int inc) { return 0; } +int __wrap_sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return 0; +} + +int __wrap_sched_setattr(pid_t pid, f_schedule_attribute_t *attr, unsigned int flags) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return 0; +} + +int __wrap_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + cpu_set_t *mock_mask = mock_ptr_type(cpu_set_t *); + + *mask = *mock_mask; + + return mock_type(int); +} + +int __wrap_sched_getattr(pid_t pid, f_schedule_attribute_t *attr, unsigned int size, unsigned int flags) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + f_schedule_attribute_t *mock_attr = mock_ptr_type(f_schedule_attribute_t *); + + *attr = *mock_attr; + + return 0; +} + +int __wrap_sched_get_priority_max(int policy) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return mock_type(int); +} + +int __wrap_sched_get_priority_min(int policy) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return mock_type(int); +} + int __wrap_sched_getparam(pid_t pid, struct sched_param *param) { const bool failure = mock_type(bool); @@ -60,6 +148,23 @@ int __wrap_sched_getscheduler(pid_t pid) { return mock_type(int); } +int __wrap_sched_rr_get_interval(pid_t pid, struct timespec *tp) { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + f_time_spec_t *mock_time = mock_ptr_type(f_time_spec_t *); + + *tp = *mock_time; + + return 0; +} + int __wrap_sched_setparam(pid_t pid, const struct sched_param *param) { const bool failure = mock_type(bool); @@ -99,6 +204,27 @@ int __wrap_setpriority(int which, id_t who, int prio) { return 0; } +int __wrap_sched_yield() { + + const bool failure = mock_type(bool); + + if (failure) { + errno = mock_type(int); + + return -1; + } + + return 0; +} + +/* How can this be done? +long __wrap_syscall(long number, ...) { + + if (mock_unwrap_syscall) { + return __real_syscall(number, ); + } +} */ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_schedule/tests/unit/c/mock-schedule.h b/level_0/f_schedule/tests/unit/c/mock-schedule.h index 9f1c93d..97ef99a 100644 --- a/level_0/f_schedule/tests/unit/c/mock-schedule.h +++ b/level_0/f_schedule/tests/unit/c/mock-schedule.h @@ -28,14 +28,26 @@ extern "C" { const static int mock_errno_generic = 32767; +extern int mock_unwrap_syscall; + +extern long __real_syscall(long number, ...); + extern int __wrap_getpriority(int which, id_t who); extern int __wrap_nice(int inc); +extern int __wrap_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); +extern int __wrap_sched_getattr(pid_t pid, f_schedule_attribute_t *attr, unsigned int size, unsigned int flags); +extern int __wrap_sched_get_priority_max(int policy); +extern int __wrap_sched_get_priority_min(int policy); extern int __wrap_sched_getparam(pid_t pid, struct sched_param *param); extern int __wrap_sched_getscheduler(pid_t pid); +extern int __wrap_sched_rr_get_interval(pid_t pid, struct timespec *tp); +extern int __wrap_sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); +extern int __wrap_sched_setattr(pid_t pid, f_schedule_attribute_t *attr, unsigned int flags); extern int __wrap_sched_setparam(pid_t pid, const struct sched_param *param); extern int __wrap_sched_setscheduler(pid_t pid, int policy, const struct sched_param *param); extern int __wrap_setpriority(int which, id_t who, int prio); - +extern int __wrap_sched_yield(); +//extern long __wrap_syscall(long number, ...); #ifdef __cplusplus } // extern "C" diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.c b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.c new file mode 100644 index 0000000..1fdb181 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.c @@ -0,0 +1,89 @@ +#include "test-schedule.h" +#include "test-schedule-affinity_get.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_affinity_get__fails(void **state) { + + { + int errnos[] = { + EFAULT, + EINVAL, + EPERM, + ESRCH, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_buffer, + F_parameter, + F_prohibited, + F_search, + F_failure, + }; + + for (int i = 0; i < 5; ++i) { + + size_t size = 0; + cpu_set_t affinity = { 0 }; + + will_return(__wrap_sched_getaffinity, true); + will_return(__wrap_sched_getaffinity, errnos[i]); + + const f_status_t status = f_schedule_affinity_get(0, &size, &affinity); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_affinity_get__parameter_checking(void **state) { + + size_t size = 0; + cpu_set_t affinity = { 0 }; + + { + const f_status_t status = f_schedule_affinity_get(0, 0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_schedule_affinity_get(0, &size, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_schedule_affinity_get(0, 0, &affinity); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_schedule_affinity_get__works(void **state) { + + const size_t expected_size = 2; + cpu_set_t expected_affinity = { 0 }; + + { + size_t size = 1; + cpu_set_t affinity = { 0 }; + + will_return(__wrap_sched_getaffinity, false); + will_return(__wrap_sched_getaffinity, &expected_affinity); + will_return(__wrap_sched_getaffinity, expected_size); + + const f_status_t status = f_schedule_affinity_get(0, &size, &affinity); + + assert_int_equal(status, F_okay); + assert_int_equal(size, expected_size); + assert_int_equal(affinity.__bits[0], expected_affinity.__bits[0]); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.h b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.h new file mode 100644 index 0000000..0ff609a --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_get.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_affinity_get_h +#define _TEST__F_schedule_affinity_get_h + +/** + * Test that function fails. + * + * @see f_schedule_affinity_get() + */ +extern void test__f_schedule_affinity_get__fails(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_schedule_affinity_get() + */ +extern void test__f_schedule_affinity_get__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_schedule_affinity_get() + */ +extern void test__f_schedule_affinity_get__works(void **state); + +#endif // _TEST__F_schedule_affinity_get_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.c b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.c new file mode 100644 index 0000000..77fdf38 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.c @@ -0,0 +1,56 @@ +#include "test-schedule.h" +#include "test-schedule-affinity_set.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_affinity_set__fails(void **state) { + + { + int errnos[] = { + EFAULT, + EINVAL, + EPERM, + ESRCH, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_buffer, + F_parameter, + F_prohibited, + F_search, + F_failure, + }; + + for (int i = 0; i < 5; ++i) { + + cpu_set_t affinity = { 0 }; + + will_return(__wrap_sched_setaffinity, true); + will_return(__wrap_sched_setaffinity, errnos[i]); + + const f_status_t status = f_schedule_affinity_set(0, 0, affinity); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_affinity_set__works(void **state) { + + { + cpu_set_t affinity = { 0 }; + + will_return(__wrap_sched_setaffinity, false); + + const f_status_t status = f_schedule_affinity_set(0, 0, affinity); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.h b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.h new file mode 100644 index 0000000..0087629 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-affinity_set.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_affinity_set_h +#define _TEST__F_schedule_affinity_set_h + +/** + * Test that function fails. + * + * @see f_schedule_affinity_set() + */ +extern void test__f_schedule_affinity_set__fails(void **state); + +/** + * Test that function works. + * + * @see f_schedule_affinity_set() + */ +extern void test__f_schedule_affinity_set__works(void **state); + +#endif // _TEST__F_schedule_affinity_set_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.c b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.c new file mode 100644 index 0000000..fceae79 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.c @@ -0,0 +1,67 @@ +#include "test-schedule.h" +#include "test-schedule-attribute_get.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_attribute_get__fails(void **state) { + + { + int errnos[] = { + E2BIG, + EINVAL, + ESRCH, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_too_large, + F_parameter, + F_search, + F_failure, + }; + + for (int i = 0; i < 4; ++i) { + + f_schedule_attribute_t attribute = f_schedule_attribute_t_initialize; + + will_return(__wrap_sched_getattr, true); + will_return(__wrap_sched_getattr, errnos[i]); + + const f_status_t status = f_schedule_attribute_get(0, 0, 0, &attribute); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_attribute_get__parameter_checking(void **state) { + + { + const f_status_t status = f_schedule_attribute_get(0, 0, 0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_schedule_attribute_get__works(void **state) { + + f_schedule_attribute_t expected_attribute = macro_f_schedule_attribute_t_initialize_1(sizeof(f_schedule_attribute_t)); + + { + f_schedule_attribute_t attribute = f_schedule_attribute_t_initialize; + + //will_return(__wrap_sched_getattr, false); + //will_return(__wrap_sched_getattr, &expected_attribute); + + const f_status_t status = f_schedule_attribute_get(0, 0, expected_attribute.size, &attribute); + + assert_int_equal(status, F_okay); + assert_int_equal(attribute.size, expected_attribute.size); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.h b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.h new file mode 100644 index 0000000..6c4c1b1 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_get.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_attribute_get_h +#define _TEST__F_schedule_attribute_get_h + +/** + * Test that function fails. + * + * @see f_schedule_attribute_get() + */ +extern void test__f_schedule_attribute_get__fails(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_schedule_attribute_get() + */ +extern void test__f_schedule_attribute_get__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_schedule_attribute_get() + */ +extern void test__f_schedule_attribute_get__works(void **state); + +#endif // _TEST__F_schedule_attribute_get_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.c b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.c new file mode 100644 index 0000000..be229bd --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.c @@ -0,0 +1,60 @@ +#include "test-schedule.h" +#include "test-schedule-attribute_set.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_attribute_set__fails(void **state) { + + const f_schedule_attribute_t attribute = f_schedule_attribute_t_initialize; + + { + int errnos[] = { + E2BIG, + EBUSY, + EINVAL, + EOPNOTSUPP, + EPERM, + ESRCH, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_too_large, + F_busy, + F_parameter, + F_support_not, + F_prohibited, + F_search, + F_failure, + }; + + for (int i = 0; i < 7; ++i) { + + will_return(__wrap_sched_setattr, true); + will_return(__wrap_sched_setattr, errnos[i]); + + const f_status_t status = f_schedule_attribute_set(0, 0, attribute); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_attribute_set__works(void **state) { + + const f_schedule_attribute_t attribute = f_schedule_attribute_t_initialize; + + { + //will_return(__wrap_sched_setattr, false); + + const f_status_t status = f_schedule_attribute_set(0, 0, attribute); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.h b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.h new file mode 100644 index 0000000..707d729 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-attribute_set.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_attribute_set_h +#define _TEST__F_schedule_attribute_set_h + +/** + * Test that function fails. + * + * @see f_schedule_attribute_set() + */ +extern void test__f_schedule_attribute_set__fails(void **state); + +/** + * Test that function works. + * + * @see f_schedule_attribute_set() + */ +extern void test__f_schedule_attribute_set__works(void **state); + +#endif // _TEST__F_schedule_attribute_set_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-policy_get.c b/level_0/f_schedule/tests/unit/c/test-schedule-policy_get.c index d745fb2..1ca9b6a 100644 --- a/level_0/f_schedule/tests/unit/c/test-schedule-policy_get.c +++ b/level_0/f_schedule/tests/unit/c/test-schedule-policy_get.c @@ -45,7 +45,6 @@ void test__f_schedule_policy_get__parameter_checking(void **state) { } } - void test__f_schedule_policy_get__works(void **state) { const int expected = 2; diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.c b/level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.c new file mode 100644 index 0000000..959db9d --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.c @@ -0,0 +1,70 @@ +#include "test-schedule.h" +#include "test-schedule-policy_robin_interval_get.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_policy_robin_interval_get__fails(void **state) { + + { + int errnos[] = { + EFAULT, + EINVAL, + EPERM, + ESRCH, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_buffer, + F_parameter, + F_prohibited, + F_search, + F_failure, + }; + + for (int i = 0; i < 5; ++i) { + + f_time_spec_t time = f_time_spec_t_initialize; + + will_return(__wrap_sched_rr_get_interval, true); + will_return(__wrap_sched_rr_get_interval, errnos[i]); + + const f_status_t status = f_schedule_policy_robin_interval_get(0, &time); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_policy_robin_interval_get__parameter_checking(void **state) { + + { + const f_status_t status = f_schedule_policy_robin_interval_get(0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_schedule_policy_robin_interval_get__works(void **state) { + + f_time_spec_t expected = macro_f_time_spec_t_initialize_1(100, 200); + + { + f_time_spec_t time = f_time_spec_t_initialize; + + will_return(__wrap_sched_rr_get_interval, false); + will_return(__wrap_sched_rr_get_interval, &expected); + + const f_status_t status = f_schedule_policy_robin_interval_get(0, &time); + + assert_int_equal(status, F_okay); + assert_int_equal(time.tv_sec, expected.tv_sec); + assert_int_equal(time.tv_nsec, expected.tv_nsec); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.h b/level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.h new file mode 100644 index 0000000..d92f79f --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-policy_robin_interval_get.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_policy_robin_interval_get_h +#define _TEST__F_schedule_policy_robin_interval_get_h + +/** + * Test that function fails. + * + * @see f_schedule_policy_robin_interval_get() + */ +extern void test__f_schedule_policy_robin_interval_get__fails(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_schedule_policy_robin_interval_get() + */ +extern void test__f_schedule_policy_robin_interval_get__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_schedule_policy_robin_interval_get() + */ +extern void test__f_schedule_policy_robin_interval_get__works(void **state); + +#endif // _TEST__F_schedule_policy_robin_interval_get_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-priority_get.c b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get.c index 3ca582f..d5793ba 100644 --- a/level_0/f_schedule/tests/unit/c/test-schedule-priority_get.c +++ b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get.c @@ -47,7 +47,6 @@ void test__f_schedule_priority_get__parameter_checking(void **state) { } } - void test__f_schedule_priority_get__works(void **state) { const int expected = 2; diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.c b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.c new file mode 100644 index 0000000..59085e1 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.c @@ -0,0 +1,63 @@ +#include "test-schedule.h" +#include "test-schedule-priority_get_max.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_priority_get_max__fails(void **state) { + + { + int errnos[] = { + EINVAL, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_parameter, + F_failure, + }; + + for (int i = 0; i < 2; ++i) { + + int priority = 0; + + will_return(__wrap_sched_get_priority_max, true); + will_return(__wrap_sched_get_priority_max, errnos[i]); + + const f_status_t status = f_schedule_priority_get_max(0, &priority); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_priority_get_max__parameter_checking(void **state) { + + { + const f_status_t status = f_schedule_priority_get_max(0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_schedule_priority_get_max__works(void **state) { + + const int expected = 2; + + { + int priority = 0; + + will_return(__wrap_sched_get_priority_max, false); + will_return(__wrap_sched_get_priority_max, expected); + + const f_status_t status = f_schedule_priority_get_max(0, &priority); + + assert_int_equal(status, F_okay); + assert_int_equal(priority, expected); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.h b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.h new file mode 100644 index 0000000..656610e --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_max.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_priority_get_max_h +#define _TEST__F_schedule_priority_get_max_h + +/** + * Test that function fails. + * + * @see f_schedule_priority_get_max() + */ +extern void test__f_schedule_priority_get_max__fails(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_schedule_priority_get_max() + */ +extern void test__f_schedule_priority_get_max__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_schedule_priority_get_max() + */ +extern void test__f_schedule_priority_get_max__works(void **state); + +#endif // _TEST__F_schedule_priority_get_max_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.c b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.c new file mode 100644 index 0000000..150d249 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.c @@ -0,0 +1,63 @@ +#include "test-schedule.h" +#include "test-schedule-priority_get_min.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_priority_get_min__fails(void **state) { + + { + int errnos[] = { + EINVAL, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_parameter, + F_failure, + }; + + for (int i = 0; i < 2; ++i) { + + int priority = 0; + + will_return(__wrap_sched_get_priority_min, true); + will_return(__wrap_sched_get_priority_min, errnos[i]); + + const f_status_t status = f_schedule_priority_get_min(0, &priority); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_priority_get_min__parameter_checking(void **state) { + + { + const f_status_t status = f_schedule_priority_get_min(0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_schedule_priority_get_min__works(void **state) { + + const int expected = 2; + + { + int priority = 0; + + will_return(__wrap_sched_get_priority_min, false); + will_return(__wrap_sched_get_priority_min, expected); + + const f_status_t status = f_schedule_priority_get_min(0, &priority); + + assert_int_equal(status, F_okay); + assert_int_equal(priority, expected); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.h b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.h new file mode 100644 index 0000000..2b902c0 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-priority_get_min.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_priority_get_min_h +#define _TEST__F_schedule_priority_get_min_h + +/** + * Test that function fails. + * + * @see f_schedule_priority_get_min() + */ +extern void test__f_schedule_priority_get_min__fails(void **state); + +/** + * Test that the function correctly fails on invalid parameter. + * + * @see f_schedule_priority_get_min() + */ +extern void test__f_schedule_priority_get_min__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_schedule_priority_get_min() + */ +extern void test__f_schedule_priority_get_min__works(void **state); + +#endif // _TEST__F_schedule_priority_get_min_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-value_get.c b/level_0/f_schedule/tests/unit/c/test-schedule-value_get.c index 6cff16f..0171ff1 100644 --- a/level_0/f_schedule/tests/unit/c/test-schedule-value_get.c +++ b/level_0/f_schedule/tests/unit/c/test-schedule-value_get.c @@ -45,7 +45,6 @@ void test__f_schedule_value_get__parameter_checking(void **state) { } } - void test__f_schedule_value_get__works(void **state) { f_schedule_value_t expected = macro_f_schedule_value_t_initialize_1(2); diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-yield.c b/level_0/f_schedule/tests/unit/c/test-schedule-yield.c new file mode 100644 index 0000000..c90cc55 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-yield.c @@ -0,0 +1,44 @@ +#include "test-schedule.h" +#include "test-schedule-yield.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_schedule_yield__fails(void **state) { + + { + int errnos[] = { + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_failure, + }; + + for (int i = 0; i < 1; ++i) { + + will_return(__wrap_sched_yield, true); + will_return(__wrap_sched_yield, errnos[i]); + + const f_status_t status = f_schedule_yield(); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for + } +} + +void test__f_schedule_yield__works(void **state) { + + { + will_return(__wrap_sched_yield, false); + + const f_status_t status = f_schedule_yield(); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_schedule/tests/unit/c/test-schedule-yield.h b/level_0/f_schedule/tests/unit/c/test-schedule-yield.h new file mode 100644 index 0000000..8815e19 --- /dev/null +++ b/level_0/f_schedule/tests/unit/c/test-schedule-yield.h @@ -0,0 +1,27 @@ +/** + * FLL - Level 0 + * + * Project: Schedule + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the schedule project. + */ +#ifndef _TEST__F_schedule_yield_h +#define _TEST__F_schedule_yield_h + +/** + * Test that function fails. + * + * @see f_schedule_yield() + */ +extern void test__f_schedule_yield__fails(void **state); + +/** + * Test that function works. + * + * @see f_schedule_yield() + */ +extern void test__f_schedule_yield__works(void **state); + +#endif // _TEST__F_schedule_yield_h diff --git a/level_0/f_schedule/tests/unit/c/test-schedule.c b/level_0/f_schedule/tests/unit/c/test-schedule.c index ec80813..4ceb251 100644 --- a/level_0/f_schedule/tests/unit/c/test-schedule.c +++ b/level_0/f_schedule/tests/unit/c/test-schedule.c @@ -19,6 +19,18 @@ int setdown(void **state) { int main(void) { const struct CMUnitTest tests[] = { + cmocka_unit_test(test__f_schedule_affinity_get__fails), + cmocka_unit_test(test__f_schedule_affinity_get__works), + + cmocka_unit_test(test__f_schedule_affinity_set__fails), + cmocka_unit_test(test__f_schedule_affinity_set__works), + + //cmocka_unit_test(test__f_schedule_attribute_get__fails), + cmocka_unit_test(test__f_schedule_attribute_get__works), + + //cmocka_unit_test(test__f_schedule_attribute_set__fails), + cmocka_unit_test(test__f_schedule_attribute_set__works), + cmocka_unit_test(test__f_schedule_nice__fails), cmocka_unit_test(test__f_schedule_nice__works), @@ -28,12 +40,21 @@ int main(void) { cmocka_unit_test(test__f_schedule_policy_get__fails), cmocka_unit_test(test__f_schedule_policy_get__works), + cmocka_unit_test(test__f_schedule_policy_robin_interval_get__fails), + cmocka_unit_test(test__f_schedule_policy_robin_interval_get__works), + cmocka_unit_test(test__f_schedule_policy_set__fails), cmocka_unit_test(test__f_schedule_policy_set__works), cmocka_unit_test(test__f_schedule_priority_get__fails), cmocka_unit_test(test__f_schedule_priority_get__works), + cmocka_unit_test(test__f_schedule_priority_get_max__fails), + cmocka_unit_test(test__f_schedule_priority_get_max__works), + + cmocka_unit_test(test__f_schedule_priority_get_min__fails), + cmocka_unit_test(test__f_schedule_priority_get_min__works), + cmocka_unit_test(test__f_schedule_priority_set__fails), cmocka_unit_test(test__f_schedule_priority_set__works), @@ -43,14 +64,25 @@ int main(void) { cmocka_unit_test(test__f_schedule_value_set__fails), cmocka_unit_test(test__f_schedule_value_set__works), + cmocka_unit_test(test__f_schedule_yield__fails), + cmocka_unit_test(test__f_schedule_yield__works), + #ifndef _di_level_0_parameter_checking_ + cmocka_unit_test(test__f_schedule_affinity_get__parameter_checking), + // f_schedule_affinity_set() doesn't use parameter checking. + cmocka_unit_test(test__f_schedule_attribute_get__parameter_checking), + // f_schedule_attribute_set() doesn't use parameter checking. // f_schedule_nice() doesn't use parameter checking. cmocka_unit_test(test__f_schedule_policy_get__parameter_checking), + cmocka_unit_test(test__f_schedule_policy_robin_interval_get__parameter_checking), cmocka_unit_test(test__f_schedule_policy_set__parameter_checking), cmocka_unit_test(test__f_schedule_priority_get__parameter_checking), + cmocka_unit_test(test__f_schedule_priority_get_max__parameter_checking), + cmocka_unit_test(test__f_schedule_priority_get_min__parameter_checking), // f_schedule_priority_set() doesn't use parameter checking. cmocka_unit_test(test__f_schedule_value_get__parameter_checking), cmocka_unit_test(test__f_schedule_value_set__parameter_checking), + // f_schedule_yield() doesn't use parameter checking. #endif // _di_level_0_parameter_checking_ }; diff --git a/level_0/f_schedule/tests/unit/c/test-schedule.h b/level_0/f_schedule/tests/unit/c/test-schedule.h index 8c5932b..c8c22a6 100644 --- a/level_0/f_schedule/tests/unit/c/test-schedule.h +++ b/level_0/f_schedule/tests/unit/c/test-schedule.h @@ -26,13 +26,21 @@ #include "mock-schedule.h" // Test includes. +#include "test-schedule-affinity_get.h" +#include "test-schedule-affinity_set.h" +#include "test-schedule-attribute_get.h" +#include "test-schedule-attribute_set.h" #include "test-schedule-nice.h" #include "test-schedule-policy_get.h" +#include "test-schedule-policy_robin_interval_get.h" #include "test-schedule-policy_set.h" #include "test-schedule-priority_get.h" +#include "test-schedule-priority_get_max.h" +#include "test-schedule-priority_get_min.h" #include "test-schedule-priority_set.h" #include "test-schedule-value_get.h" #include "test-schedule-value_set.h" +#include "test-schedule-yield.h" #ifdef __cplusplus extern "C" { -- 1.8.3.1