}
#endif // _di_f_time_of_day_set_
+#ifndef _di_f_time_sleep_spec_
+ f_status_t f_time_sleep_spec(const f_time_spec_t time, f_time_spec_t * const remaining) {
+
+ if (nanosleep(&time, remaining) == -1) {
+ if (errno == EFAULT) return F_status_set_error(F_buffer);
+ if (errno == EINTR) return F_interrupt;
+ if (errno == EINVAL) return F_status_set_error(F_parameter);
+
+ return F_status_set_error(F_failure);
+ }
+
+ return F_okay;
+ }
+#endif // _di_f_time_sleep_spec_
+
#ifndef _di_f_time_spec_millisecond_
extern f_status_t f_time_spec_millisecond(const f_number_unsigned_t second, const f_number_unsigned_t millisecond, f_time_spec_t * const time) {
#ifndef _di_level_0_parameter_checking_
#endif // _di_f_time_of_day_set_
/**
+ * Sleep a given amount of time specified by the f_time_spec_t.
+ *
+ * @param time
+ * The time to sleep (in seconds and nanoseconds).
+ * @param remaining
+ * (optional) Contains the remaining time if stopped on interrupt.
+ * Set to NULL to not use.
+ *
+ * @return
+ * F_okay on success.
+ * F_interrupt if interrupted by a signal.
+ *
+ * F_buffer (with error bit) if failed to copy data from user space.
+ * F_parameter (with error bit) if a parameter is invalid (such as tv_nsec is not in range 0 to 999999999 or tv_sec is negative).
+ *
+ * F_failure (with error bit) on any other error.
+ *
+ * @see nanosleep()
+ */
+#ifndef _di_f_time_sleep_spec_
+ extern f_status_t f_time_sleep_spec(const f_time_spec_t time, f_time_spec_t * const remaining);
+#endif // _di_f_time_sleep_spec_
+
+/**
* Create a timespec representing the given seconds and milliseconds.
*
* The "f_time_spec_t" may have different lengths and so this function provides overflow and underflow protection.
flags -Wl,--wrap=gettimeofday
flags -Wl,--wrap=gmtime_r
flags -Wl,--wrap=localtime_r
+flags -Wl,--wrap=nanosleep
flags -Wl,--wrap=settimeofday
flags -Wl,--wrap=time
build_sources_program test-time-calendar_string.c test-time-calendar_string_part.c test-time-epoch_get.c
build_sources_program test-time-of_day_get.c test-time-of_day_set.c
build_sources_program test-time-local_get.c test-time-utc_get.c
-build_sources_program test-time-spec_millisecond.c test-time-spec_nanosecond.c
+build_sources_program test-time-sleep_spec.c test-time-spec_millisecond.c test-time-spec_nanosecond.c
build_sources_program test-time.c
build_script no
return res;
}
+int __wrap_nanosleep(const struct timespec *req, struct timespec *rem) {
+
+ const bool failure = mock_type(bool);
+
+ if (failure) {
+ errno = mock_type(int);
+
+ return -1;
+ }
+
+ if (rem) {
+ *rem = *mock_type(struct timespec *);
+ }
+
+ return 0;
+}
+
int __wrap_settimeofday(const struct timeval *tv, const struct timezone *tz) {
const bool failure = mock_type(bool);
#include <setjmp.h>
#include <stdint.h>
#include <string.h>
+#include <time.h>
// cmocka includes.
#include <cmocka.h>
extern int __wrap_gettimeofday(struct timeval *tv, struct timezone *tz);
extern struct tm *__wrap_gmtime_r(const time_t *timep, struct tm *result);
extern struct tm *__wrap_localtime_r(const time_t *timep, struct tm *result);
+extern int __wrap_nanosleep(const struct timespec *req, struct timespec *rem);
extern int __wrap_settimeofday(const struct timeval *tv, const struct timezone *tz);
extern time_t __wrap_time(time_t *tloc);
--- /dev/null
+#include "test-time.h"
+#include "test-time-sleep_spec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_time_sleep_spec__fails(void **state) {
+
+ const f_time_spec_t spec = f_time_spec_t_initialize;
+
+ {
+ int errnos[] = {
+ EFAULT,
+ EINTR,
+ EINVAL,
+ mock_errno_generic,
+ };
+
+ f_status_t statuss[] = {
+ F_status_set_error(F_buffer),
+ F_interrupt,
+ F_status_set_error(F_parameter),
+ F_status_set_error(F_failure),
+ };
+
+ for (int i = 0; i < 4; ++i) {
+
+ will_return(__wrap_nanosleep, true);
+ will_return(__wrap_nanosleep, errnos[i]);
+
+ const f_status_t status = f_time_sleep_spec(spec, 0);
+
+ assert_int_equal(status, statuss[i]);
+ } // for
+ }
+}
+
+void test__f_time_sleep_spec__works(void **state) {
+
+ const f_time_spec_t spec = { .tv_sec = 1, .tv_nsec = 1 };
+ const f_time_spec_t expect = { .tv_sec = 3, .tv_nsec = 4 };
+
+ {
+ will_return(__wrap_nanosleep, false);
+
+ const f_status_t status = f_time_sleep_spec(spec, 0);
+
+ assert_int_equal(status, F_okay);
+ }
+
+ {
+ f_time_spec_t remaining = f_time_spec_t_initialize;
+
+ will_return(__wrap_nanosleep, false);
+ will_return(__wrap_nanosleep, &expect);
+
+ const f_status_t status = f_time_sleep_spec(spec, &remaining);
+
+ assert_int_equal(status, F_okay);
+ assert_int_equal(remaining.tv_sec, expect.tv_sec);
+ assert_int_equal(remaining.tv_nsec, expect.tv_nsec);
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null
+/**
+ * FLL - Level 0
+ *
+ * Project: Time
+ * API Version: 0.7
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the time project.
+ */
+#ifndef _TEST__F_time_sleep_spec_h
+#define _TEST__F_time_sleep_spec_h
+
+/**
+ * Test that function fails.
+ *
+ * @see f_time_sleep_spec()
+ */
+extern void test__f_time_sleep_spec__fails(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_time_sleep_spec()
+ */
+extern void test__f_time_sleep_spec__works(void **state);
+
+#endif // _TEST__F_time_sleep_spec_h
cmocka_unit_test(test__f_time_local_get__fails),
cmocka_unit_test(test__f_time_of_day_get__fails),
cmocka_unit_test(test__f_time_of_day_set__fails),
+ cmocka_unit_test(test__f_time_sleep_spec__fails),
cmocka_unit_test(test__f_time_utc_get__fails),
cmocka_unit_test(test__f_time_calendar_string__works),
cmocka_unit_test(test__f_time_local_get__works),
cmocka_unit_test(test__f_time_of_day_get__works),
cmocka_unit_test(test__f_time_of_day_set__works),
+ cmocka_unit_test(test__f_time_sleep_spec__works),
cmocka_unit_test(test__f_time_utc_get__works),
cmocka_unit_test(test__f_time_spec_millisecond__number_overflow),
cmocka_unit_test(test__f_time_local_get__parameter_checking),
cmocka_unit_test(test__f_time_of_day_get__parameter_checking),
// f_time_of_day_set() doesn't use parameter checking.
- cmocka_unit_test(test__f_time_utc_get__parameter_checking),
+ // f_time_sleep_spec() doesn't use parameter checking.
cmocka_unit_test(test__f_time_spec_millisecond__parameter_checking),
cmocka_unit_test(test__f_time_spec_nanosecond__parameter_checking),
+ cmocka_unit_test(test__f_time_utc_get__parameter_checking),
#endif // _di_level_0_parameter_checking_
};
#include "test-time-of_day_get.h"
#include "test-time-of_day_set.h"
#include "test-time-utc_get.h"
+#include "test-time-sleep_spec.h"
#include "test-time-spec_millisecond.h"
#include "test-time-spec_nanosecond.h"