diff --git a/src/os/inc/osapi-clock.h b/src/os/inc/osapi-clock.h index 50cc82c6d..9c8f489b1 100644 --- a/src/os/inc/osapi-clock.h +++ b/src/os/inc/osapi-clock.h @@ -47,6 +47,29 @@ typedef struct int64 ticks; /**< Ticks elapsed since reference point */ } OS_time_t; +/** + * @brief The maximum value for OS_time_t + * + * This is the largest positive (future) time that is representable + * in an OS_time_t value. + */ +#define OS_TIME_MAX ((OS_time_t) {INT64_MAX}) + +/** + * @brief The zero value for OS_time_t + * + * This is a reasonable initializer/placeholder value for an OS_time_t + */ +#define OS_TIME_ZERO ((OS_time_t) {0}) + +/** + * @brief The minimum value for OS_time_t + * + * This is the largest negative (past) time that is representable + * in an OS_time_t value. + */ +#define OS_TIME_MIN ((OS_time_t) {INT64_MIN}) + /** * @brief Multipliers/divisors to convert ticks into standardized units * @@ -102,6 +125,45 @@ int32 OS_GetLocalTime(OS_time_t *time_struct); */ int32 OS_SetLocalTime(const OS_time_t *time_struct); +/*-------------------------------------------------------------------------------------*/ +/** + * @brief Gets an absolute time value relative to the current time + * + * This function adds the given interval, expressed in milliseconds, to the + * current clock and returns the result. + * + * @note This is intended to ease transitioning from a relative timeout value to + * and absolute timeout value. The result can be passed to any function + * that accepts an absolute timeout, to mimic the behavior of a relative timeout. + * + * @param[in] relative_msec A relative time interval, in milliseconds + * + * @returns Absolute time value after adding interval + */ +OS_time_t OS_TimeFromRelativeMilliseconds(int32 relative_msec); + +/*-------------------------------------------------------------------------------------*/ +/** + * @brief Gets a relative time value from an absolute time + * + * This function computes the number of milliseconds until the given + * absolute time value is reached in the system clock. + * + * @note This is intended to ease transitioning from a relative timeout value to + * and absolute timeout value. The result can be passed to any function + * that accepts a relative timeout, to mimic the behavior of an absolute timeout. + * + * The return value of this function is intended to be compatible with the relative + * timeout parameter of various OSAL APIs e.g. OS_TimedRead() / OS_TimedWrite() + * + * @param[in] time An absolute time value + * + * @returns Milliseconds until time value will be reached + * @retval OS_CHECK (0) if time is the current time or is in the past + * @retval OS_PEND (-1) if time is far in the future (not expressable as an int32) + */ +int32 OS_TimeToRelativeMilliseconds(OS_time_t time); + /*-------------------------------------------------------------------------------------*/ /* * Accessor / Unit Conversion routines for OS_time_t @@ -485,6 +547,60 @@ static inline OS_time_t OS_TimeSubtract(OS_time_t time1, OS_time_t time2) return ostm; } +/*-------------------------------------------------------------------------------------*/ +/** + * @brief Checks if two time values are equal + * + * @param[in] time1 The first time value + * @param[in] time2 The second time value + * + * @retval true if the two values are equal + * @retval false if the two values are not equal + */ +static inline bool OS_TimeEqual(OS_time_t time1, OS_time_t time2) +{ + return (time1.ticks == time2.ticks); +} + +/*-------------------------------------------------------------------------------------*/ +/** + * @brief Checks the sign of the time value + * + * @param[in] time The time to check + * + * @retval -1 if the time value is negative / below 0 + * @retval 0 if the time value is 0 + * @retval 1 if the time value is positive / above 0 + */ +static inline int8_t OS_TimeGetSign(OS_time_t time) +{ + if (time.ticks > 0) + { + return 1; + } + if (time.ticks < 0) + { + return -1; + } + return 0; +} + +/*-------------------------------------------------------------------------------------*/ +/** + * @brief Compares two time values + * + * @param[in] time1 The first time + * @param[in] time2 The second time + * + * @retval -1 if the time1 < time2 + * @retval 0 if the times are equal + * @retval 1 if the time1 > time2 + */ +static inline int8_t OS_TimeCompare(OS_time_t time1, OS_time_t time2) +{ + return OS_TimeGetSign(OS_TimeSubtract(time1, time2)); +} + /**@}*/ #endif /* OSAPI_CLOCK_H */ diff --git a/src/os/inc/osapi-file.h b/src/os/inc/osapi-file.h index e039f2bfc..280482dcf 100644 --- a/src/os/inc/osapi-file.h +++ b/src/os/inc/osapi-file.h @@ -237,7 +237,49 @@ int32 OS_write(osal_id_t filedes, const void *buffer, size_t nbytes); * @param[in] filedes The handle ID to operate on * @param[out] buffer Storage location for file data @nonnull * @param[in] nbytes Maximum number of bytes to read @nonzero - * @param[in] timeout Maximum time to wait, in milliseconds (OS_PEND = forever) + * @param[in] abstime Absolute time at which this function should return, if no data is readable + * + * @returns Byte count on success or appropriate error code, see @ref OSReturnCodes + * @retval #OS_ERROR_TIMEOUT if no data became available during timeout period + * @retval #OS_ERR_INVALID_ID if the file descriptor passed in is invalid + * @retval #OS_ERR_INVALID_SIZE if the passed-in size is not valid + * @retval #OS_INVALID_POINTER if the passed-in buffer is not valid + * @retval 0 if at end of file/stream data + */ +int32 OS_AbsTimedRead(osal_id_t filedes, void *buffer, size_t nbytes, OS_time_t abstime); + +/*-------------------------------------------------------------------------------------*/ +/** + * @brief File/Stream input read with a timeout + * + * This implements a time-limited read and is primarily intended for use with + * sockets but may also work with any other stream-like resource that the underlying + * OS supports, such as pipes or special devices. + * + * If data is immediately available on the file/socket, this will return that data + * along with the actual number of bytes that were immediately available. It will + * not block. + * + * If the file position is at the end of file or end of stream data (e.g. if the remote + * end has closed the connection), then this function will immediately return 0 without + * blocking for the timeout period. + * + * If no data is immediately available, but the underlying resource/stream is still + * connected to a peer, this will wait up to the given timeout for additional + * data to appear. If no data appears within the timeout period, then this returns + * the #OS_ERROR_TIMEOUT status code. This allows the caller to differentiate + * an open (but idle) socket connection from a connection which has been closed + * by the remote peer. + * + * In all cases this will return successfully as soon as at least 1 byte of actual + * data is available. It will not attempt to read the entire input buffer. + * + * If an EOF condition occurs prior to timeout, this function returns zero. + * + * @param[in] filedes The handle ID to operate on + * @param[out] buffer Storage location for file data @nonnull + * @param[in] nbytes Maximum number of bytes to read @nonzero + * @param[in] timeout Maximum time to wait, in milliseconds, relative to current time (OS_PEND = forever) * * @returns Byte count on success or appropriate error code, see @ref OSReturnCodes * @retval #OS_ERROR_TIMEOUT if no data became available during timeout period @@ -272,7 +314,42 @@ int32 OS_TimedRead(osal_id_t filedes, void *buffer, size_t nbytes, int32 timeout * @param[in] filedes The handle ID to operate on * @param[in] buffer Source location for file data @nonnull * @param[in] nbytes Maximum number of bytes to read @nonzero - * @param[in] timeout Maximum time to wait, in milliseconds (OS_PEND = forever) + * @param[in] abstime Absolute time at which this function should return, if no data is readable + * + * @return A non-negative byte count or appropriate error code, see @ref OSReturnCodes + * @retval #OS_ERROR_TIMEOUT if no data became available during timeout period + * @retval #OS_ERR_INVALID_ID if the file descriptor passed in is invalid + * @retval #OS_ERR_INVALID_SIZE if the passed-in size is not valid + * @retval #OS_INVALID_POINTER if the passed-in buffer is not valid + * @retval 0 if file/stream cannot accept any more data + */ +int32 OS_AbsTimedWrite(osal_id_t filedes, const void *buffer, size_t nbytes, OS_time_t abstime); + +/*-------------------------------------------------------------------------------------*/ +/** + * @brief File/Stream output write with a timeout + * + * This implements a time-limited write and is primarily intended for use with + * sockets but may also work with any other stream-like resource that the underlying + * OS supports. + * + * If output buffer space is immediately available on the file/socket, this will + * place data into the buffer and return the actual number of bytes that were + * queued for output. It will not block. + * + * If no output buffer space is immediately available, this will wait up to the + * given timeout for space to become available. If no space becomes available within + * the timeout period, then this returns an error code (not zero). + * + * In all cases this will return successfully as soon as at least 1 byte of actual + * data is output. It will _not_ attempt to write the entire output buffer. + * + * If an EOF condition occurs prior to timeout, this function returns zero. + * + * @param[in] filedes The handle ID to operate on + * @param[in] buffer Source location for file data @nonnull + * @param[in] nbytes Maximum number of bytes to read @nonzero + * @param[in] timeout Maximum time to wait, in milliseconds, relative to current time (OS_PEND = forever) * * @return A non-negative byte count or appropriate error code, see @ref OSReturnCodes * @retval #OS_ERROR_TIMEOUT if no data became available during timeout period diff --git a/src/os/inc/osapi-sockets.h b/src/os/inc/osapi-sockets.h index 93d046527..f461dedc4 100644 --- a/src/os/inc/osapi-sockets.h +++ b/src/os/inc/osapi-sockets.h @@ -28,6 +28,7 @@ /* NOTE - osconfig.h may optionally specify the value for OS_SOCADDR_MAX_LEN */ #include "osconfig.h" #include "common_types.h" +#include "osapi-clock.h" /* * The absolute maximum size of a network address @@ -408,11 +409,43 @@ int32 OS_SocketAccept(osal_id_t sock_id, osal_id_t *connsock_id, OS_SockAddr_t * * If a message is already available on the socket, this should immediately return * that data without blocking. Otherwise, it may block up to the given timeout. * + * This API is identical to OS_SocketRecvFrom() except for the timeout parameter. In + * this call, timeout is expressed as an absolute value of the OS clock, in the same + * time domain as obtained via OS_GetLocalTime(). This allows for a more precise + * timeout than what is possible via the normal OS_SocketRecvFrom(). + * * @param[in] sock_id The socket ID, previously bound using OS_SocketBind() * @param[out] buffer Pointer to message data receive buffer @nonnull * @param[in] buflen The maximum length of the message data to receive @nonzero * @param[out] RemoteAddr Buffer to store the remote network address (may be NULL) - * @param[in] timeout The maximum amount of time to wait, or OS_PEND to wait forever + * @param[in] abs_timeout The absolute time at which the call should return if nothing received + * + * @return Count of actual bytes received or error status, see @ref OSReturnCodes + * @retval #OS_INVALID_POINTER if argument is NULL + * @retval #OS_ERR_INVALID_SIZE if passed-in buflen is not valid + * @retval #OS_ERR_INVALID_ID if the sock_id parameter is not valid + * @retval #OS_ERR_INCORRECT_OBJ_TYPE if the handle is not a socket + */ +int32 OS_AbsSocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, + OS_time_t abs_timeout); + +/*-------------------------------------------------------------------------------------*/ +/** + * @brief Reads data from a message-oriented (datagram) socket + * + * If a message is already available on the socket, this should immediately return + * that data without blocking. Otherwise, it may block up to the given timeout. + * + * The timeout is expressed in milliseconds, relative to the time that the API was + * invoked. Use OS_AbsSocketRecvFrom() for higher timing precision. + * + * @param[in] sock_id The socket ID, previously bound using OS_SocketBind() + * @param[out] buffer Pointer to message data receive buffer @nonnull + * @param[in] buflen The maximum length of the message data to receive @nonzero + * @param[out] RemoteAddr Buffer to store the remote network address (may be NULL) + * @param[in] timeout The maximum amount of time to wait or OS_PEND to wait forever + * + * @sa OS_AbsSocketRecvFrom() * * @return Count of actual bytes received or error status, see @ref OSReturnCodes * @retval #OS_INVALID_POINTER if argument is NULL diff --git a/src/os/portable/os-impl-bsd-select.c b/src/os/portable/os-impl-bsd-select.c index baa516797..162909b04 100644 --- a/src/os/portable/os-impl-bsd-select.c +++ b/src/os/portable/os-impl-bsd-select.c @@ -41,6 +41,7 @@ #include #include "os-impl-select.h" +#include "os-shared-clock.h" #include "os-shared-select.h" #include "os-shared-idmap.h" @@ -163,68 +164,52 @@ static void OS_FdSet_ConvertOut_Impl(fd_set *OS_set, OS_FdSet *OSAL_set) * Actual implementation of select() call * Used by SelectSingle and SelectMultiple implementations (below) *-----------------------------------------------------------------*/ -static int32 OS_DoSelect(int maxfd, fd_set *rd_set, fd_set *wr_set, int32 msecs) +static int32 OS_DoSelect(int maxfd, fd_set *rd_set, fd_set *wr_set, OS_time_t abs_timeout) { int os_status; int32 return_code; struct timeval tv; struct timeval *tvptr; - struct timespec ts_now; - struct timespec ts_end; + OS_time_t curr_time; - if (msecs > 0) + /* Implementations may pass OS_TIME_MAX to mean wait forever */ + if (OS_TimeEqual(abs_timeout, OS_TIME_MAX)) { - clock_gettime(CLOCK_MONOTONIC, &ts_now); - ts_end.tv_sec = ts_now.tv_sec + (msecs / 1000); - ts_end.tv_nsec = ts_now.tv_nsec + (1000000 * (msecs % 1000)); - if (ts_end.tv_nsec >= 1000000000) - { - ++ts_end.tv_sec; - ts_end.tv_nsec -= 1000000000; - } + tvptr = NULL; } else { - /* Zero for consistency and to avoid possible confusion if not cleared */ - memset(&ts_end, 0, sizeof(ts_end)); + /* Not waiting forever, some form of timeout will be calculated */ + tvptr = &tv; } + curr_time = abs_timeout; + do { - if (msecs < 0) - { - tvptr = NULL; - } - else if (msecs == 0) - { - tvptr = &tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - } - else + if (tvptr != NULL) { - tvptr = &tv; - - clock_gettime(CLOCK_MONOTONIC, &ts_now); - - /* note that the tv_sec and tv_usec/tv_nsec values are all signed longs, so OK to subtract */ - tv.tv_sec = ts_end.tv_sec - ts_now.tv_sec; - tv.tv_usec = (ts_end.tv_nsec - ts_now.tv_nsec) / 1000; - - if (tv.tv_sec < 0 || (tv.tv_sec == 0 && tv.tv_usec < 0)) + if (OS_TimeGetSign(abs_timeout) > 0) { - os_status = 0; - break; + OS_GetLocalTime_Impl(&curr_time); + curr_time = OS_TimeSubtract(abs_timeout, curr_time); } - - if (tv.tv_usec < 0) + if (OS_TimeGetSign(curr_time) <= 0) { - tv.tv_usec += 1000000; - --tv.tv_sec; + /* timeout has already passed - this will still poll, but not block */ + tv.tv_sec = 0; + tv.tv_usec = 0; + } + else + { + /* timeout is in the future */ + tv.tv_sec = OS_TimeGetTotalSeconds(curr_time); + tv.tv_usec = OS_TimeGetMicrosecondsPart(curr_time); } } os_status = select(maxfd + 1, rd_set, wr_set, NULL, tvptr); + } while (os_status < 0 && (errno == EINTR || errno == EAGAIN)); if (os_status < 0) @@ -253,7 +238,7 @@ static int32 OS_DoSelect(int maxfd, fd_set *rd_set, fd_set *wr_set, int32 msecs) * See prototype for argument/return detail * *-----------------------------------------------------------------*/ -int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, int32 msecs) +int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, OS_time_t abs_timeout) { int32 return_code; fd_set wr_set; @@ -290,7 +275,7 @@ int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, FD_SET(impl->fd, &wr_set); } - return_code = OS_DoSelect(impl->fd, &rd_set, &wr_set, msecs); + return_code = OS_DoSelect(impl->fd, &rd_set, &wr_set, abs_timeout); if (return_code == OS_SUCCESS) { @@ -323,7 +308,7 @@ int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, * See prototype for argument/return detail * *-----------------------------------------------------------------*/ -int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, int32 msecs) +int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, OS_time_t abs_timeout) { fd_set wr_set; fd_set rd_set; @@ -352,7 +337,7 @@ int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, int32 msecs) if (maxfd >= 0) { - return_code = OS_DoSelect(maxfd, &rd_set, &wr_set, msecs); + return_code = OS_DoSelect(maxfd, &rd_set, &wr_set, abs_timeout); } else { diff --git a/src/os/portable/os-impl-bsd-sockets.c b/src/os/portable/os-impl-bsd-sockets.c index de03b270a..3102d0aac 100644 --- a/src/os/portable/os-impl-bsd-sockets.c +++ b/src/os/portable/os-impl-bsd-sockets.c @@ -52,6 +52,7 @@ #include #include "os-impl-sockets.h" +#include "os-shared-clock.h" #include "os-shared-file.h" #include "os-shared-select.h" #include "os-shared-sockets.h" @@ -284,7 +285,7 @@ int32 OS_SocketListen_Impl(const OS_object_token_t *token) * See prototype for argument/return detail * *-----------------------------------------------------------------*/ -int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, int32 timeout) +int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, OS_time_t abs_timeout) { int32 return_code; int os_status; @@ -345,7 +346,7 @@ int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t operation = OS_STREAM_STATE_WRITABLE; if (impl->selectable) { - return_code = OS_SelectSingle_Impl(token, &operation, timeout); + return_code = OS_SelectSingle_Impl(token, &operation, abs_timeout); } if (return_code == OS_SUCCESS) { @@ -422,7 +423,7 @@ int32 OS_SocketShutdown_Impl(const OS_object_token_t *token, OS_SocketShutdownMo * *-----------------------------------------------------------------*/ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_token_t *conn_token, - OS_SockAddr_t *Addr, int32 timeout) + OS_SockAddr_t *Addr, OS_time_t abs_timeout) { int32 return_code; uint32 operation; @@ -436,7 +437,7 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_ operation = OS_STREAM_STATE_READABLE; if (sock_impl->selectable) { - return_code = OS_SelectSingle_Impl(sock_token, &operation, timeout); + return_code = OS_SelectSingle_Impl(sock_token, &operation, abs_timeout); } else { @@ -476,7 +477,7 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_ * *-----------------------------------------------------------------*/ int32 OS_SocketRecvFrom_Impl(const OS_object_token_t *token, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, - int32 timeout) + OS_time_t abs_timeout) { int32 return_code; int os_result; @@ -507,11 +508,12 @@ int32 OS_SocketRecvFrom_Impl(const OS_object_token_t *token, void *buffer, size_ if (impl->selectable) { waitflags = MSG_DONTWAIT; - return_code = OS_SelectSingle_Impl(token, &operation, timeout); + return_code = OS_SelectSingle_Impl(token, &operation, abs_timeout); } else { - if (timeout == 0) + /* This is a backup option - check if the abs timeout would be a poll/check op */ + if (OS_TimeToRelativeMilliseconds(abs_timeout) == OS_CHECK) { waitflags = MSG_DONTWAIT; } diff --git a/src/os/portable/os-impl-no-sockets.c b/src/os/portable/os-impl-no-sockets.c index 0d14700d2..3c7f15f23 100644 --- a/src/os/portable/os-impl-no-sockets.c +++ b/src/os/portable/os-impl-no-sockets.c @@ -74,7 +74,7 @@ int32 OS_SocketListen_Impl(const OS_object_token_t *token) * * See prototype for argument/return detail *-----------------------------------------------------------------*/ -int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, int32 timeout) +int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, OS_time_t abs_timeout) { return OS_ERR_NOT_IMPLEMENTED; } @@ -95,7 +95,7 @@ int32 OS_SocketShutdown_Impl(const OS_object_token_t *token, OS_SocketShutdownMo * See prototype for argument/return detail *-----------------------------------------------------------------*/ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_token_t *conn_token, - OS_SockAddr_t *Addr, int32 timeout) + OS_SockAddr_t *Addr, OS_time_t abs_timeout) { return OS_ERR_NOT_IMPLEMENTED; } @@ -106,7 +106,7 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_ * See prototype for argument/return detail *-----------------------------------------------------------------*/ int32 OS_SocketRecvFrom_Impl(const OS_object_token_t *token, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, - int32 timeout) + OS_time_t abs_timeout) { return OS_ERR_NOT_IMPLEMENTED; } diff --git a/src/os/portable/os-impl-posix-io.c b/src/os/portable/os-impl-posix-io.c index 5d9dc3b1e..9a0da4d8b 100644 --- a/src/os/portable/os-impl-posix-io.c +++ b/src/os/portable/os-impl-posix-io.c @@ -162,7 +162,7 @@ int32 OS_GenericSeek_Impl(const OS_object_token_t *token, int32 offset, uint32 w * See prototype for argument/return detail * *-----------------------------------------------------------------*/ -int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t nbytes, int32 timeout) +int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t nbytes, OS_time_t abs_timeout) { int32 return_code; ssize_t os_result; @@ -187,7 +187,7 @@ int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t n */ if (impl->selectable) { - return_code = OS_SelectSingle_Impl(token, &operation, timeout); + return_code = OS_SelectSingle_Impl(token, &operation, abs_timeout); } if (return_code == OS_SUCCESS && (operation & OS_STREAM_STATE_READABLE) != 0) @@ -215,7 +215,7 @@ int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t n * See prototype for argument/return detail * *-----------------------------------------------------------------*/ -int32 OS_GenericWrite_Impl(const OS_object_token_t *token, const void *buffer, size_t nbytes, int32 timeout) +int32 OS_GenericWrite_Impl(const OS_object_token_t *token, const void *buffer, size_t nbytes, OS_time_t abs_timeout) { int32 return_code; ssize_t os_result; @@ -240,7 +240,7 @@ int32 OS_GenericWrite_Impl(const OS_object_token_t *token, const void *buffer, s */ if (impl->selectable) { - return_code = OS_SelectSingle_Impl(token, &operation, timeout); + return_code = OS_SelectSingle_Impl(token, &operation, abs_timeout); } if (return_code == OS_SUCCESS && (operation & OS_STREAM_STATE_WRITABLE) != 0) diff --git a/src/os/shared/inc/os-shared-file.h b/src/os/shared/inc/os-shared-file.h index 8c21f3bb4..a96797a74 100644 --- a/src/os/shared/inc/os-shared-file.h +++ b/src/os/shared/inc/os-shared-file.h @@ -85,7 +85,7 @@ int32 OS_GenericSeek_Impl(const OS_object_token_t *token, int32 offset, uint32 w Returns: Number of bytes read (non-negative) on success, or relevant error code (negative) ------------------------------------------------------------------*/ -int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t nbytes, int32 timeout); +int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t nbytes, OS_time_t abs_timeout); /*---------------------------------------------------------------- @@ -94,7 +94,7 @@ int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t n Returns: Number of bytes written (non-negative) on success, or relevant error code (negative) ------------------------------------------------------------------*/ -int32 OS_GenericWrite_Impl(const OS_object_token_t *token, const void *buffer, size_t nbytes, int32 timeout); +int32 OS_GenericWrite_Impl(const OS_object_token_t *token, const void *buffer, size_t nbytes, OS_time_t abs_timeout); /*---------------------------------------------------------------- diff --git a/src/os/shared/inc/os-shared-select.h b/src/os/shared/inc/os-shared-select.h index a2123762e..6d610e9b1 100644 --- a/src/os/shared/inc/os-shared-select.h +++ b/src/os/shared/inc/os-shared-select.h @@ -26,6 +26,7 @@ #ifndef OS_SHARED_SELECT_H #define OS_SHARED_SELECT_H +#include "osapi-clock.h" #include "osapi-select.h" #include "os-shared-globaldefs.h" @@ -48,7 +49,7 @@ Returns: OS_SUCCESS on success, or relevant error code OS_ERR_OPERATION_NOT_SUPPORTED if the specified file handle does not support select ------------------------------------------------------------------*/ -int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, int32 msecs); +int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, OS_time_t abs_timeout); /*---------------------------------------------------------------- @@ -71,6 +72,6 @@ int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, Returns: OS_SUCCESS on success, or relevant error code OS_ERR_OPERATION_NOT_SUPPORTED if the specified file handle(s) do not support select ------------------------------------------------------------------*/ -int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, int32 msecs); +int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, OS_time_t abs_timeout); #endif /* OS_SHARED_SELECT_H */ diff --git a/src/os/shared/inc/os-shared-sockets.h b/src/os/shared/inc/os-shared-sockets.h index 547d011f6..c1989bd92 100644 --- a/src/os/shared/inc/os-shared-sockets.h +++ b/src/os/shared/inc/os-shared-sockets.h @@ -75,7 +75,7 @@ int32 OS_SocketListen_Impl(const OS_object_token_t *token); Returns: OS_SUCCESS on success, or relevant error code ------------------------------------------------------------------*/ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_token_t *conn_token, - OS_SockAddr_t *Addr, int32 timeout); + OS_SockAddr_t *Addr, OS_time_t abs_timeout); /*---------------------------------------------------------------- @@ -84,7 +84,7 @@ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_ Returns: OS_SUCCESS on success, or relevant error code ------------------------------------------------------------------*/ -int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, int32 timeout); +int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, OS_time_t abs_timeout); /*---------------------------------------------------------------- @@ -105,7 +105,7 @@ int32 OS_SocketShutdown_Impl(const OS_object_token_t *token, OS_SocketShutdownMo Returns: OS_SUCCESS on success, or relevant error code ------------------------------------------------------------------*/ int32 OS_SocketRecvFrom_Impl(const OS_object_token_t *token, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, - int32 timeout); + OS_time_t abs_timeout); /*---------------------------------------------------------------- diff --git a/src/os/shared/src/osapi-clock.c b/src/os/shared/src/osapi-clock.c index bd42eb0c7..2cd0b0448 100644 --- a/src/os/shared/src/osapi-clock.c +++ b/src/os/shared/src/osapi-clock.c @@ -65,3 +65,83 @@ int32 OS_SetLocalTime(const OS_time_t *time_struct) return OS_SetLocalTime_Impl(time_struct); } + +/*---------------------------------------------------------------- + * + * Purpose: Implemented per public OSAL API + * See description in API and header file for detail + * + * Helper function to convert a relative timeout to absolute time + * + *-----------------------------------------------------------------*/ +OS_time_t OS_TimeFromRelativeMilliseconds(int32 relative_msec) +{ + OS_time_t abs_time; + + if (relative_msec == OS_CHECK) + { + abs_time = OS_TIME_ZERO; + } + else if (relative_msec > 0) + { + OS_GetLocalTime_Impl(&abs_time); + abs_time = OS_TimeAdd(abs_time, OS_TimeFromTotalMilliseconds(relative_msec)); + } + else + { + abs_time = OS_TIME_MAX; + } + + return abs_time; +} + +/*---------------------------------------------------------------- + * + * Purpose: Implemented per public OSAL API + * See description in API and header file for detail + * + * Helper function to convert an absolute time to relative timeout + * + *-----------------------------------------------------------------*/ +int32 OS_TimeToRelativeMilliseconds(OS_time_t time) +{ + int64 relative_msec; + OS_time_t curr_time; + + /* + * This is an optimization that assumes all negative time values are + * in the past - no need to read the clock to figure that out. + * + * Also OS_TIME_MAX is equivalent to pend forever, and does not + * need to read the clock either. + */ + if (OS_TimeGetSign(time) <= 0 || OS_TimeEqual(time, OS_TIME_MAX)) + { + curr_time = time; + } + else + { + OS_GetLocalTime_Impl(&curr_time); + curr_time = OS_TimeSubtract(time, curr_time); + } + + if (OS_TimeGetSign(curr_time) <= 0) + { + /* map this to a polling op (OS_CHECK) */ + relative_msec = OS_CHECK; + } + else + { + /* note this result is 64 bits, as this can exceed int32 potentially */ + relative_msec = OS_TimeGetTotalMilliseconds(curr_time); + + /* Just in case: cap the value at INT32_MAX */ + if (relative_msec > INT32_MAX) + { + /* map this to an indefinite block (OS_PEND) */ + relative_msec = OS_PEND; + } + } + + return relative_msec; +} diff --git a/src/os/shared/src/osapi-file.c b/src/os/shared/src/osapi-file.c index da5eb7a05..994ff217c 100644 --- a/src/os/shared/src/osapi-file.c +++ b/src/os/shared/src/osapi-file.c @@ -182,7 +182,7 @@ int32 OS_close(osal_id_t filedes) * See description in API and header file for detail * *-----------------------------------------------------------------*/ -int32 OS_TimedRead(osal_id_t filedes, void *buffer, size_t nbytes, int32 timeout) +int32 OS_AbsTimedRead(osal_id_t filedes, void *buffer, size_t nbytes, OS_time_t abstime) { OS_object_token_t token; int32 return_code; @@ -194,7 +194,7 @@ int32 OS_TimedRead(osal_id_t filedes, void *buffer, size_t nbytes, int32 timeout return_code = OS_ObjectIdGetById(OS_LOCK_MODE_REFCOUNT, LOCAL_OBJID_TYPE, filedes, &token); if (return_code == OS_SUCCESS) { - return_code = OS_GenericRead_Impl(&token, buffer, nbytes, timeout); + return_code = OS_GenericRead_Impl(&token, buffer, nbytes, abstime); OS_ObjectIdRelease(&token); } @@ -208,7 +208,18 @@ int32 OS_TimedRead(osal_id_t filedes, void *buffer, size_t nbytes, int32 timeout * See description in API and header file for detail * *-----------------------------------------------------------------*/ -int32 OS_TimedWrite(osal_id_t filedes, const void *buffer, size_t nbytes, int32 timeout) +int32 OS_TimedRead(osal_id_t filedes, void *buffer, size_t nbytes, int32 timeout) +{ + return OS_AbsTimedRead(filedes, buffer, nbytes, OS_TimeFromRelativeMilliseconds(timeout)); +} + +/*---------------------------------------------------------------- + * + * Purpose: Implemented per public OSAL API + * See description in API and header file for detail + * + *-----------------------------------------------------------------*/ +int32 OS_AbsTimedWrite(osal_id_t filedes, const void *buffer, size_t nbytes, OS_time_t abstime) { OS_object_token_t token; int32 return_code; @@ -220,13 +231,24 @@ int32 OS_TimedWrite(osal_id_t filedes, const void *buffer, size_t nbytes, int32 return_code = OS_ObjectIdGetById(OS_LOCK_MODE_REFCOUNT, LOCAL_OBJID_TYPE, filedes, &token); if (return_code == OS_SUCCESS) { - return_code = OS_GenericWrite_Impl(&token, buffer, nbytes, timeout); + return_code = OS_GenericWrite_Impl(&token, buffer, nbytes, abstime); OS_ObjectIdRelease(&token); } return return_code; } +/*---------------------------------------------------------------- + * + * Purpose: Implemented per public OSAL API + * See description in API and header file for detail + * + *-----------------------------------------------------------------*/ +int32 OS_TimedWrite(osal_id_t filedes, const void *buffer, size_t nbytes, int32 timeout) +{ + return OS_AbsTimedWrite(filedes, buffer, nbytes, OS_TimeFromRelativeMilliseconds(timeout)); +} + /*---------------------------------------------------------------- * * Purpose: Implemented per public OSAL API diff --git a/src/os/shared/src/osapi-select.c b/src/os/shared/src/osapi-select.c index 21778cfb1..9d3ff5ca9 100644 --- a/src/os/shared/src/osapi-select.c +++ b/src/os/shared/src/osapi-select.c @@ -65,7 +65,7 @@ int32 OS_SelectSingle(osal_id_t objid, uint32 *StateFlags, int32 msecs) return_code = OS_ObjectIdGetById(OS_LOCK_MODE_REFCOUNT, OS_OBJECT_TYPE_OS_STREAM, objid, &token); if (return_code == OS_SUCCESS) { - return_code = OS_SelectSingle_Impl(&token, StateFlags, msecs); + return_code = OS_SelectSingle_Impl(&token, StateFlags, OS_TimeFromRelativeMilliseconds(msecs)); OS_ObjectIdRelease(&token); } @@ -94,7 +94,7 @@ int32 OS_SelectMultiple(OS_FdSet *ReadSet, OS_FdSet *WriteSet, int32 msecs) * That means a file/socket can be closed while actively inside a * OS_SelectMultiple() call in another thread. */ - return_code = OS_SelectMultiple_Impl(ReadSet, WriteSet, msecs); + return_code = OS_SelectMultiple_Impl(ReadSet, WriteSet, OS_TimeFromRelativeMilliseconds(msecs)); return return_code; } diff --git a/src/os/shared/src/osapi-sockets.c b/src/os/shared/src/osapi-sockets.c index 6e47ffe1d..7b9e62381 100644 --- a/src/os/shared/src/osapi-sockets.c +++ b/src/os/shared/src/osapi-sockets.c @@ -342,7 +342,8 @@ int32 OS_SocketAccept(osal_id_t sock_id, osal_id_t *connsock_id, OS_SockAddr_t * OS_SocketAddrInit_Impl(Addr, sock->socket_domain); - return_code = OS_SocketAccept_Impl(&sock_token, &conn_token, Addr, timeout); + return_code = + OS_SocketAccept_Impl(&sock_token, &conn_token, Addr, OS_TimeFromRelativeMilliseconds(timeout)); if (return_code == OS_SUCCESS) { @@ -393,7 +394,7 @@ int32 OS_SocketConnect(osal_id_t sock_id, const OS_SockAddr_t *Addr, int32 Timeo } else { - return_code = OS_SocketConnect_Impl(&token, Addr, Timeout); + return_code = OS_SocketConnect_Impl(&token, Addr, OS_TimeFromRelativeMilliseconds(Timeout)); if (return_code == OS_SUCCESS) { @@ -467,7 +468,8 @@ int32 OS_SocketShutdown(osal_id_t sock_id, OS_SocketShutdownMode_t Mode) * See description in API and header file for detail * *-----------------------------------------------------------------*/ -int32 OS_SocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, int32 timeout) +int32 OS_AbsSocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, + OS_time_t abs_timeout) { OS_stream_internal_record_t *stream; OS_object_token_t token; @@ -497,7 +499,7 @@ int32 OS_SocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockA } else { - return_code = OS_SocketRecvFrom_Impl(&token, buffer, buflen, RemoteAddr, timeout); + return_code = OS_SocketRecvFrom_Impl(&token, buffer, buflen, RemoteAddr, abs_timeout); } OS_ObjectIdRelease(&token); @@ -506,6 +508,17 @@ int32 OS_SocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockA return return_code; } +/*---------------------------------------------------------------- + * + * Purpose: Implemented per public OSAL API + * See description in API and header file for detail + * + *-----------------------------------------------------------------*/ +int32 OS_SocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, int32 timeout) +{ + return OS_AbsSocketRecvFrom(sock_id, buffer, buflen, RemoteAddr, OS_TimeFromRelativeMilliseconds(timeout)); +} + /*---------------------------------------------------------------- * * Purpose: Implemented per public OSAL API diff --git a/src/tests/network-api-test/network-api-test.c b/src/tests/network-api-test/network-api-test.c index f2426c3e2..920484c89 100644 --- a/src/tests/network-api-test/network-api-test.c +++ b/src/tests/network-api-test/network-api-test.c @@ -378,6 +378,8 @@ void Server_Fn(void) ServerFn_AcceptStatus = OS_SocketAccept(s_socket_id, &connsock_id, &addr, OS_PEND); if (ServerFn_AcceptStatus != OS_SUCCESS) { + snprintf(ServerFn_ErrorString, sizeof(ServerFn_ErrorString), + "OS_SocketAccept() iter=%u, return code=%d", (unsigned int)iter, (int)Status); break; } diff --git a/src/unit-test-coverage/portable/src/coveragetest-bsd-select.c b/src/unit-test-coverage/portable/src/coveragetest-bsd-select.c index 8a6fcb24e..06579d772 100644 --- a/src/unit-test-coverage/portable/src/coveragetest-bsd-select.c +++ b/src/unit-test-coverage/portable/src/coveragetest-bsd-select.c @@ -23,6 +23,7 @@ */ #include "os-portable-coveragetest.h" #include "ut-adaptor-portable-posix-io.h" +#include "os-shared-clock.h" #include "os-shared-select.h" #include "os-shared-idmap.h" @@ -34,89 +35,81 @@ void Test_OS_SelectSingle_Impl(void) /* Test Case For: * int32 OS_SelectSingle_Impl(uint32 stream_id, uint32 *SelectFlags, int32 msecs) */ - uint32 SelectFlags; - OS_object_token_t token; - struct OCS_timespec nowtime; - struct OCS_timespec latertime; - struct OCS_timespec latertime2; + uint32 SelectFlags; + OS_object_token_t token; + OS_time_t nowtime; + OS_time_t latertime; + OS_time_t timeout; memset(&token, 0, sizeof(token)); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, false); SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 0), OS_ERR_OPERATION_NOT_SUPPORTED); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, OS_TIME_MIN), OS_ERR_OPERATION_NOT_SUPPORTED); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, true); - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, OS_TIME_MIN), OS_SUCCESS); /* Cover FD_ISSET true branches and pend */ UT_SetDeferredRetcode(UT_KEY(OCS_FD_ISSET), 1, true); UT_SetDeferredRetcode(UT_KEY(OCS_FD_ISSET), 1, true); SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, -1), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, OS_TIME_MAX), OS_SUCCESS); /* No flags and non-read/write flag branches */ SelectFlags = 0; - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, OS_TIME_MIN), OS_SUCCESS); SelectFlags = OS_STREAM_STATE_BOUND; - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, OS_TIME_MIN), OS_SUCCESS); /* try a case where select() needs to be repeated to achieve the desired wait time */ - UT_ResetState(UT_KEY(OCS_clock_gettime)); UT_ResetState(UT_KEY(OCS_select)); UT_SetDefaultReturnValue(UT_KEY(OCS_select), -1); OCS_errno = OCS_EINTR; UT_SetDeferredRetcode(UT_KEY(OCS_select), 2, 0); - SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; - nowtime.tv_sec = 1; - nowtime.tv_nsec = 0; - latertime.tv_sec = 1; - latertime.tv_nsec = 800000000; - latertime2.tv_sec = 2; - latertime2.tv_nsec = 200000000; - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &nowtime, sizeof(nowtime), false); - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &latertime, sizeof(latertime), false); - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &latertime2, sizeof(latertime2), false); - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 1200), OS_ERROR_TIMEOUT); - UtAssert_STUB_COUNT(OCS_clock_gettime, 3); + SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; + nowtime = OS_TimeFromTotalMilliseconds(1000); + latertime = OS_TimeFromTotalMilliseconds(1800); + timeout = OS_TimeFromTotalMilliseconds(1200); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &nowtime, sizeof(nowtime), false); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &latertime, sizeof(latertime), false); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, timeout), OS_ERROR_TIMEOUT); + UtAssert_STUB_COUNT(OS_GetLocalTime_Impl, 2); UtAssert_STUB_COUNT(OCS_select, 2); /* Repeated select with alternate branches */ - OCS_errno = OCS_EAGAIN; - SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; - latertime2.tv_nsec = 300000000; - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &nowtime, sizeof(nowtime), false); - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &latertime, sizeof(latertime), false); - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &latertime2, sizeof(latertime2), false); - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 1200), OS_ERROR_TIMEOUT); - UtAssert_STUB_COUNT(OCS_clock_gettime, 6); - UtAssert_STUB_COUNT(OCS_select, 3); + OCS_errno = OCS_EAGAIN; + SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; + UT_SetDeferredRetcode(UT_KEY(OCS_select), 2, 0); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &nowtime, sizeof(nowtime), false); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &latertime, sizeof(latertime), false); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, timeout), OS_ERROR_TIMEOUT); + UtAssert_STUB_COUNT(OS_GetLocalTime_Impl, 4); + UtAssert_STUB_COUNT(OCS_select, 4); UT_SetDefaultReturnValue(UT_KEY(OCS_select), 0); - SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; - nowtime.tv_sec = 1; - nowtime.tv_nsec = 500000000; - latertime.tv_sec = 10; - latertime.tv_nsec = 0; - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &nowtime, sizeof(nowtime), false); - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &latertime, sizeof(latertime), false); - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 999), OS_ERROR_TIMEOUT); + SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; + nowtime = OS_TimeFromTotalMilliseconds(1500); + latertime = OS_TimeFromTotalMilliseconds(10000); + timeout = OS_TimeFromTotalMilliseconds(999); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &nowtime, sizeof(nowtime), false); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &latertime, sizeof(latertime), false); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, timeout), OS_ERROR_TIMEOUT); UT_SetDefaultReturnValue(UT_KEY(OCS_select), -1); - OCS_errno = OCS_ETIMEDOUT; - SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; - nowtime.tv_sec = 1; - nowtime.tv_nsec = 0; - latertime.tv_sec = 2; - latertime.tv_nsec = 600000000; - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &nowtime, sizeof(nowtime), false); - UT_SetDataBuffer(UT_KEY(OCS_clock_gettime), &latertime, sizeof(latertime), false); - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 2100), OS_ERROR); + OCS_errno = OCS_ETIMEDOUT; + SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; + nowtime = OS_TimeFromTotalMilliseconds(1000); + latertime = OS_TimeFromTotalMilliseconds(2600); + timeout = OS_TimeFromTotalMilliseconds(2100); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &nowtime, sizeof(nowtime), false); + UT_SetDataBuffer(UT_KEY(OS_GetLocalTime_Impl), &latertime, sizeof(latertime), false); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, timeout), OS_ERROR); /* Test cases where the FD exceeds FD_SETSIZE */ SelectFlags = OS_STREAM_STATE_READABLE | OS_STREAM_STATE_WRITABLE; UT_PortablePosixIOTest_Set_FD(UT_INDEX_0, OCS_FD_SETSIZE); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, true); - OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, 0), OS_ERR_OPERATION_NOT_SUPPORTED); + OSAPI_TEST_FUNCTION_RC(OS_SelectSingle_Impl, (&token, &SelectFlags, OS_TIME_MIN), OS_ERR_OPERATION_NOT_SUPPORTED); } void Test_OS_SelectMultiple_Impl(void) @@ -134,9 +127,9 @@ void Test_OS_SelectMultiple_Impl(void) memset(&ReadSet, 0, sizeof(ReadSet)); memset(&WriteSet, 0, sizeof(WriteSet)); WriteSet.object_ids[0] = 1; - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (NULL, &WriteSet, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (NULL, &WriteSet, OS_TIME_MIN), OS_SUCCESS); ReadSet.object_ids[0] = 1; - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, NULL, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, NULL, OS_TIME_MIN), OS_SUCCESS); /* Branches for processing the set */ UT_SetDeferredRetcode(UT_KEY(OCS_FD_ISSET), 1, true); @@ -144,37 +137,37 @@ void Test_OS_SelectMultiple_Impl(void) UT_PortablePosixIOTest_Set_FD(OSAL_INDEX_C(2), -1); UT_PortablePosixIOTest_Set_FD(OSAL_INDEX_C(3), 0); UT_PortablePosixIOTest_Set_Selectable(OSAL_INDEX_C(3), true); - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, OS_TIME_MIN), OS_SUCCESS); memset(&ReadSet, 0, sizeof(ReadSet)); memset(&WriteSet, 0, sizeof(WriteSet)); ReadSet.object_ids[0] = 1; UT_SetDeferredRetcode(UT_KEY(OCS_select), 1, 0); - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, 1), OS_ERROR_TIMEOUT); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, OS_TIME_MAX), OS_ERROR_TIMEOUT); /* Test where the FD set is empty */ memset(&ReadSet, 0, sizeof(ReadSet)); memset(&WriteSet, 0, sizeof(WriteSet)); - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (NULL, NULL, 0), OS_ERR_INVALID_ID); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (NULL, NULL, OS_TIME_MIN), OS_ERR_INVALID_ID); /* Test cases where the FD exceeds FD_SETSIZE in the read set */ UT_PortablePosixIOTest_Set_FD(UT_INDEX_0, OCS_FD_SETSIZE); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, true); memset(&ReadSet, 0xff, sizeof(ReadSet)); memset(&WriteSet, 0, sizeof(WriteSet)); - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, 0), OS_ERR_OPERATION_NOT_SUPPORTED); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, OS_TIME_MIN), OS_ERR_OPERATION_NOT_SUPPORTED); /* Test cases where the FD exceeds FD_SETSIZE in the write set */ memset(&ReadSet, 0, sizeof(ReadSet)); memset(&WriteSet, 0xff, sizeof(WriteSet)); - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, 0), OS_ERR_OPERATION_NOT_SUPPORTED); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, OS_TIME_MIN), OS_ERR_OPERATION_NOT_SUPPORTED); /* Test cases where additional bits are set in the OS_FdSet */ UT_PortablePosixIOTest_Set_FD(UT_INDEX_0, 0); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, true); memset(&ReadSet, 0xff, sizeof(ReadSet)); memset(&WriteSet, 0xff, sizeof(WriteSet)); - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, 0), OS_ERR_OPERATION_NOT_SUPPORTED); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, OS_TIME_MIN), OS_ERR_OPERATION_NOT_SUPPORTED); /* * Cover OS_FdSet_ConvertOut_Impl for id < OS_MAX_NUM_OPEN_FILES, requires no errors from in conversion @@ -184,7 +177,7 @@ void Test_OS_SelectMultiple_Impl(void) { UT_PortablePosixIOTest_Set_FD(OSAL_INDEX_C(i), -1); } - OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SelectMultiple_Impl, (&ReadSet, &WriteSet, OS_TIME_MIN), OS_SUCCESS); } /* ------------------- End of test cases --------------------------------------*/ diff --git a/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c b/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c index 90c8459bd..eaa227855 100644 --- a/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c +++ b/src/unit-test-coverage/portable/src/coveragetest-bsd-sockets.c @@ -188,16 +188,16 @@ void Test_OS_SocketConnect_Impl(void) /* Default family case */ sa->sa_family = -1; addr.ActualLength = sizeof(struct OCS_sockaddr_in); - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_ERR_BAD_ADDRESS); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_ERR_BAD_ADDRESS); /* Successful connect */ sa->sa_family = OCS_AF_INET; - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_SUCCESS); /* Fail connect, errno ! EINPROGRESS */ OCS_errno = ~OCS_EINPROGRESS; UT_SetDefaultReturnValue(UT_KEY(OCS_connect), -1); - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_ERROR); /* Fail OS_SelectSingle_Impl, errno == EINPROGRESS */ OCS_errno = OCS_EINPROGRESS; @@ -205,30 +205,30 @@ void Test_OS_SocketConnect_Impl(void) addr.ActualLength = sizeof(struct OCS_sockaddr_in6); OS_impl_filehandle_table[0].selectable = true; UT_SetDeferredRetcode(UT_KEY(OS_SelectSingle_Impl), 1, UT_ERR_UNIQUE); - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), UT_ERR_UNIQUE); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), UT_ERR_UNIQUE); /* Timeout error by clearing select flags with hook */ selectflags = 0; UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), UT_Hook_OS_SelectSingle_Impl, &selectflags); - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_ERROR_TIMEOUT); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_ERROR_TIMEOUT); UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), NULL, NULL); /* Fail getsockopt status */ UT_SetDeferredRetcode(UT_KEY(OCS_getsockopt), 1, -1); - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_ERROR); /* Nonzero getsockopt sockopt */ sockopt = 1; UT_SetHookFunction(UT_KEY(OCS_getsockopt), UT_Hook_OCS_getsockopt, &sockopt); - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_ERROR); UT_SetHookFunction(UT_KEY(OCS_getsockopt), NULL, NULL); /* Success case with selectable */ - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_SUCCESS); /* Success case with not selectable */ OS_impl_filehandle_table[0].selectable = false; - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (&token, &addr, OS_TIME_MIN), OS_SUCCESS); } void Test_OS_SocketShutdown_Impl(void) @@ -262,21 +262,21 @@ void Test_OS_SocketAccept_Impl(void) /* Fail OS_SelectSingle_Impl with sock_token selectable */ OS_impl_filehandle_table[0].selectable = true; UT_SetDeferredRetcode(UT_KEY(OS_SelectSingle_Impl), 1, UT_ERR_UNIQUE); - OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), UT_ERR_UNIQUE); + OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, OS_TIME_MIN), UT_ERR_UNIQUE); /* Timeout by clearing select flags with hook */ selectflags = 0; UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), UT_Hook_OS_SelectSingle_Impl, &selectflags); - OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_ERROR_TIMEOUT); + OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, OS_TIME_MIN), OS_ERROR_TIMEOUT); UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), NULL, NULL); /* Clear selectable and fail accept */ OS_impl_filehandle_table[0].selectable = false; UT_SetDeferredRetcode(UT_KEY(OCS_accept), 1, -1); - OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, OS_TIME_MIN), OS_ERROR); /* Success case */ - OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (&sock_token, &conn_token, &addr, OS_TIME_MIN), OS_SUCCESS); } void Test_OS_SocketRecvFrom_Impl(void) @@ -292,35 +292,38 @@ void Test_OS_SocketRecvFrom_Impl(void) /* NULL RemoteAddr, selectable, fail OS_SelectSingle_Impl */ OS_impl_filehandle_table[0].selectable = true; UT_SetDeferredRetcode(UT_KEY(OS_SelectSingle_Impl), 1, UT_ERR_UNIQUE); - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), NULL, 0), UT_ERR_UNIQUE); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), NULL, OS_TIME_MIN), UT_ERR_UNIQUE); /* Timeout by clearing select flags with hook */ selectflags = 0; UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), UT_Hook_OS_SelectSingle_Impl, &selectflags); - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, 0), OS_ERROR_TIMEOUT); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, OS_TIME_MIN), + OS_ERROR_TIMEOUT); UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), NULL, NULL); /* Not selectable, 0 timeout, EAGAIN error from recvfrom error */ OS_impl_filehandle_table[0].selectable = false; OCS_errno = OCS_EAGAIN; UT_SetDeferredRetcode(UT_KEY(OCS_recvfrom), 1, -1); - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, 0), OS_QUEUE_EMPTY); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, OS_TIME_MIN), + OS_QUEUE_EMPTY); /* With timeout, other error from recvfrom error */ OCS_errno = 0; UT_SetDeferredRetcode(UT_KEY(OCS_recvfrom), 1, -1); - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, 1), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, OS_TIME_MAX), OS_ERROR); /* With timeout, EWOULDBLOCK error from recvfrom error */ OCS_errno = OCS_EWOULDBLOCK; UT_SetDeferredRetcode(UT_KEY(OCS_recvfrom), 1, -1); - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, 1), OS_QUEUE_EMPTY); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, OS_TIME_MAX), + OS_QUEUE_EMPTY); /* Success with NULL RemoteAddr */ - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), NULL, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), NULL, OS_TIME_MIN), OS_SUCCESS); /* Success with non-NULL RemoteAddr */ - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (&token, buffer, sizeof(buffer), &addr, OS_TIME_MIN), OS_SUCCESS); } void Test_OS_SocketSendTo_Impl(void) diff --git a/src/unit-test-coverage/portable/src/coveragetest-no-sockets.c b/src/unit-test-coverage/portable/src/coveragetest-no-sockets.c index 71a274180..6013b9637 100644 --- a/src/unit-test-coverage/portable/src/coveragetest-no-sockets.c +++ b/src/unit-test-coverage/portable/src/coveragetest-no-sockets.c @@ -29,10 +29,10 @@ void Test_No_Sockets(void) OSAPI_TEST_FUNCTION_RC(OS_SocketOpen_Impl, (NULL), OS_ERR_NOT_IMPLEMENTED); OSAPI_TEST_FUNCTION_RC(OS_SocketBindAddress_Impl, (NULL, NULL), OS_ERR_NOT_IMPLEMENTED); OSAPI_TEST_FUNCTION_RC(OS_SocketListen_Impl, (NULL), OS_ERR_NOT_IMPLEMENTED); - OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (NULL, NULL, 0), OS_ERR_NOT_IMPLEMENTED); - OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (NULL, NULL, NULL, 0), OS_ERR_NOT_IMPLEMENTED); + OSAPI_TEST_FUNCTION_RC(OS_SocketConnect_Impl, (NULL, NULL, OS_TIME_MIN), OS_ERR_NOT_IMPLEMENTED); + OSAPI_TEST_FUNCTION_RC(OS_SocketAccept_Impl, (NULL, NULL, NULL, OS_TIME_MIN), OS_ERR_NOT_IMPLEMENTED); OSAPI_TEST_FUNCTION_RC(OS_SocketShutdown_Impl, (NULL, 0), OS_ERR_NOT_IMPLEMENTED); - OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (NULL, NULL, 0, NULL, 0), OS_ERR_NOT_IMPLEMENTED); + OSAPI_TEST_FUNCTION_RC(OS_SocketRecvFrom_Impl, (NULL, NULL, 0, NULL, OS_TIME_MIN), OS_ERR_NOT_IMPLEMENTED); OSAPI_TEST_FUNCTION_RC(OS_SocketSendTo_Impl, (NULL, NULL, 0, NULL), OS_ERR_NOT_IMPLEMENTED); OSAPI_TEST_FUNCTION_RC(OS_SocketGetInfo_Impl, (NULL, NULL), OS_SUCCESS); OSAPI_TEST_FUNCTION_RC(OS_SocketAddrInit_Impl, (NULL, 0), OS_ERR_NOT_IMPLEMENTED); diff --git a/src/unit-test-coverage/portable/src/coveragetest-posix-io.c b/src/unit-test-coverage/portable/src/coveragetest-posix-io.c index e6a5a7708..737689978 100644 --- a/src/unit-test-coverage/portable/src/coveragetest-posix-io.c +++ b/src/unit-test-coverage/portable/src/coveragetest-posix-io.c @@ -115,30 +115,30 @@ void Test_OS_GenericRead_Impl(void) UT_SetDataBuffer(UT_KEY(OCS_read), SrcData, sizeof(SrcData), false); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, false); - OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), 0), sizeof(DestData)); + OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), OS_TIME_MIN), sizeof(DestData)); UtAssert_MemCmp(SrcData, DestData, sizeof(SrcData), "read() data Valid"); /* test invocation of select() in nonblocking mode */ UT_ResetState(UT_KEY(OCS_read)); UT_SetDataBuffer(UT_KEY(OCS_read), SrcData, sizeof(SrcData), false); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, true); - OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), 0), sizeof(DestData)); + OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), OS_TIME_MIN), sizeof(DestData)); UtAssert_True(UT_GetStubCount(UT_KEY(OS_SelectSingle_Impl)) == 1, "OS_SelectSingle() called"); /* Read 0 bytes */ - OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, 0, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, 0, OS_TIME_MIN), OS_SUCCESS); /* read() failure */ UT_SetDefaultReturnValue(UT_KEY(OCS_read), -1); - OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), 0), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), OS_TIME_MIN), OS_ERROR); /* Fail select */ UT_SetDeferredRetcode(UT_KEY(OS_SelectSingle_Impl), 1, OS_ERROR_TIMEOUT); - OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), 0), OS_ERROR_TIMEOUT); + OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), OS_TIME_MIN), OS_ERROR_TIMEOUT); /* Not readable */ UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), UT_Hook_OS_SelectSingle_Impl, NULL); - OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_GenericRead_Impl, (&token, DestData, sizeof(DestData), OS_TIME_MIN), OS_SUCCESS); UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), NULL, NULL); } @@ -156,30 +156,30 @@ void Test_OS_GenericWrite_Impl(void) UT_SetDataBuffer(UT_KEY(OCS_write), DestData, sizeof(DestData), false); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, false); - OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), 0), sizeof(SrcData)); + OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), OS_TIME_MIN), sizeof(SrcData)); UtAssert_MemCmp(SrcData, DestData, sizeof(SrcData), "write() data valid"); /* test invocation of select() in nonblocking mode */ UT_ResetState(UT_KEY(OCS_write)); UT_SetDataBuffer(UT_KEY(OCS_write), DestData, sizeof(DestData), false); UT_PortablePosixIOTest_Set_Selectable(UT_INDEX_0, true); - OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), 0), sizeof(SrcData)); + OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), OS_TIME_MIN), sizeof(SrcData)); UtAssert_True(UT_GetStubCount(UT_KEY(OS_SelectSingle_Impl)) == 1, "OS_SelectSingle() called"); /* Fail select */ UT_SetDeferredRetcode(UT_KEY(OS_SelectSingle_Impl), 1, OS_ERROR_TIMEOUT); - OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), 0), OS_ERROR_TIMEOUT); + OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), OS_TIME_MIN), OS_ERROR_TIMEOUT); /* Write 0 bytes */ - OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, 0, 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, 0, OS_TIME_MIN), OS_SUCCESS); /* write() failure */ UT_SetDefaultReturnValue(UT_KEY(OCS_write), -1); - OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, DestData, sizeof(DestData), 0), OS_ERROR); + OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, DestData, sizeof(DestData), OS_TIME_MIN), OS_ERROR); /* Not writeable */ UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), UT_Hook_OS_SelectSingle_Impl, NULL); - OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), 0), OS_SUCCESS); + OSAPI_TEST_FUNCTION_RC(OS_GenericWrite_Impl, (&token, SrcData, sizeof(SrcData), OS_TIME_MIN), OS_SUCCESS); UT_SetHookFunction(UT_KEY(OS_SelectSingle_Impl), NULL, NULL); } diff --git a/src/unit-test-coverage/ut-stubs/CMakeLists.txt b/src/unit-test-coverage/ut-stubs/CMakeLists.txt index b970cf8a2..d96eef819 100644 --- a/src/unit-test-coverage/ut-stubs/CMakeLists.txt +++ b/src/unit-test-coverage/ut-stubs/CMakeLists.txt @@ -21,7 +21,7 @@ add_library(ut_osapi_stub_headers INTERFACE) target_include_directories(ut_osapi_stub_headers INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/inc ) -target_link_libraries(ut_osapi_stub_headers INTERFACE +target_link_libraries(ut_osapi_stub_headers INTERFACE ut_assert ) @@ -163,6 +163,7 @@ add_custom_target(generate_osal_coverage_stubs # and are not public API calls. This is only compiled if used. add_library(ut_osapi_impl_stubs STATIC EXCLUDE_FROM_ALL src/os-shared-binsem-impl-stubs.c + src/os-shared-clock-impl-handlers.c src/os-shared-clock-impl-stubs.c src/os-shared-common-impl-stubs.c src/os-shared-condvar-impl-stubs.c @@ -275,4 +276,3 @@ add_library(ut_bsp_impl_stubs STATIC EXCLUDE_FROM_ALL target_link_libraries(ut_bsp_impl_stubs PUBLIC ut_osapi_stub_headers ) - diff --git a/src/unit-test-coverage/ut-stubs/src/os-shared-clock-impl-handlers.c b/src/unit-test-coverage/ut-stubs/src/os-shared-clock-impl-handlers.c new file mode 100644 index 000000000..6eda3b25f --- /dev/null +++ b/src/unit-test-coverage/ut-stubs/src/os-shared-clock-impl-handlers.c @@ -0,0 +1,52 @@ +/************************************************************************ + * NASA Docket No. GSC-18,719-1, and identified as “core Flight System: Bootes” + * + * Copyright (c) 2020 United States Government as represented by the + * Administrator of the National Aeronautics and Space Administration. + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ************************************************************************/ + +/** + * \file + * \author joseph.p.hickey@nasa.gov + * + * Stub implementations for the functions defined in the OSAL API + * + * The stub implementation can be used for unit testing applications built + * on top of OSAL. The stubs do not do any real function, but allow + * the return code to be crafted such that error paths in the application + * can be executed. + */ + +#include "osapi-clock.h" /* OSAL public API for this subsystem */ +#include "os-shared-clock.h" +#include "utstubs.h" + +/* + * ----------------------------------------------------------------- + * Default handler implementation for 'OS_GetLocalTime_Impl' stub + * ----------------------------------------------------------------- + */ +void UT_DefaultHandler_OS_GetLocalTime_Impl(void *UserObj, UT_EntryKey_t FuncKey, const UT_StubContext_t *Context) +{ + OS_time_t *time_struct = UT_Hook_GetArgValueByName(Context, "time_struct", OS_time_t *); + int32 status; + + UT_Stub_GetInt32StatusCode(Context, &status); + + if (status == OS_SUCCESS && + UT_Stub_CopyToLocal(UT_KEY(OS_GetLocalTime_Impl), time_struct, sizeof(*time_struct)) < sizeof(*time_struct)) + { + memset(time_struct, 0, sizeof(*time_struct)); + } +} diff --git a/src/unit-test-coverage/ut-stubs/src/os-shared-clock-impl-stubs.c b/src/unit-test-coverage/ut-stubs/src/os-shared-clock-impl-stubs.c index 4e7c64470..e8f2160a2 100644 --- a/src/unit-test-coverage/ut-stubs/src/os-shared-clock-impl-stubs.c +++ b/src/unit-test-coverage/ut-stubs/src/os-shared-clock-impl-stubs.c @@ -25,6 +25,8 @@ #include "os-shared-clock.h" #include "utgenstub.h" +void UT_DefaultHandler_OS_GetLocalTime_Impl(void *, UT_EntryKey_t, const UT_StubContext_t *); + /* * ---------------------------------------------------- * Generated stub function for OS_GetLocalTime_Impl() @@ -36,7 +38,7 @@ int32 OS_GetLocalTime_Impl(OS_time_t *time_struct) UT_GenStub_AddParam(OS_GetLocalTime_Impl, OS_time_t *, time_struct); - UT_GenStub_Execute(OS_GetLocalTime_Impl, Basic, NULL); + UT_GenStub_Execute(OS_GetLocalTime_Impl, Basic, UT_DefaultHandler_OS_GetLocalTime_Impl); return UT_GenStub_GetReturnValue(OS_GetLocalTime_Impl, int32); } diff --git a/src/unit-test-coverage/ut-stubs/src/os-shared-file-impl-stubs.c b/src/unit-test-coverage/ut-stubs/src/os-shared-file-impl-stubs.c index 75c5bebf6..87c418997 100644 --- a/src/unit-test-coverage/ut-stubs/src/os-shared-file-impl-stubs.c +++ b/src/unit-test-coverage/ut-stubs/src/os-shared-file-impl-stubs.c @@ -135,14 +135,14 @@ int32 OS_GenericClose_Impl(const OS_object_token_t *token) * Generated stub function for OS_GenericRead_Impl() * ---------------------------------------------------- */ -int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t nbytes, int32 timeout) +int32 OS_GenericRead_Impl(const OS_object_token_t *token, void *buffer, size_t nbytes, OS_time_t abs_timeout) { UT_GenStub_SetupReturnBuffer(OS_GenericRead_Impl, int32); UT_GenStub_AddParam(OS_GenericRead_Impl, const OS_object_token_t *, token); UT_GenStub_AddParam(OS_GenericRead_Impl, void *, buffer); UT_GenStub_AddParam(OS_GenericRead_Impl, size_t, nbytes); - UT_GenStub_AddParam(OS_GenericRead_Impl, int32, timeout); + UT_GenStub_AddParam(OS_GenericRead_Impl, OS_time_t, abs_timeout); UT_GenStub_Execute(OS_GenericRead_Impl, Basic, UT_DefaultHandler_OS_GenericRead_Impl); @@ -172,14 +172,14 @@ int32 OS_GenericSeek_Impl(const OS_object_token_t *token, int32 offset, uint32 w * Generated stub function for OS_GenericWrite_Impl() * ---------------------------------------------------- */ -int32 OS_GenericWrite_Impl(const OS_object_token_t *token, const void *buffer, size_t nbytes, int32 timeout) +int32 OS_GenericWrite_Impl(const OS_object_token_t *token, const void *buffer, size_t nbytes, OS_time_t abs_timeout) { UT_GenStub_SetupReturnBuffer(OS_GenericWrite_Impl, int32); UT_GenStub_AddParam(OS_GenericWrite_Impl, const OS_object_token_t *, token); UT_GenStub_AddParam(OS_GenericWrite_Impl, const void *, buffer); UT_GenStub_AddParam(OS_GenericWrite_Impl, size_t, nbytes); - UT_GenStub_AddParam(OS_GenericWrite_Impl, int32, timeout); + UT_GenStub_AddParam(OS_GenericWrite_Impl, OS_time_t, abs_timeout); UT_GenStub_Execute(OS_GenericWrite_Impl, Basic, UT_DefaultHandler_OS_GenericWrite_Impl); diff --git a/src/unit-test-coverage/ut-stubs/src/os-shared-select-impl-stubs.c b/src/unit-test-coverage/ut-stubs/src/os-shared-select-impl-stubs.c index e166537d2..9ba9a554d 100644 --- a/src/unit-test-coverage/ut-stubs/src/os-shared-select-impl-stubs.c +++ b/src/unit-test-coverage/ut-stubs/src/os-shared-select-impl-stubs.c @@ -30,13 +30,13 @@ * Generated stub function for OS_SelectMultiple_Impl() * ---------------------------------------------------- */ -int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, int32 msecs) +int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, OS_time_t abs_timeout) { UT_GenStub_SetupReturnBuffer(OS_SelectMultiple_Impl, int32); UT_GenStub_AddParam(OS_SelectMultiple_Impl, OS_FdSet *, ReadSet); UT_GenStub_AddParam(OS_SelectMultiple_Impl, OS_FdSet *, WriteSet); - UT_GenStub_AddParam(OS_SelectMultiple_Impl, int32, msecs); + UT_GenStub_AddParam(OS_SelectMultiple_Impl, OS_time_t, abs_timeout); UT_GenStub_Execute(OS_SelectMultiple_Impl, Basic, NULL); @@ -48,13 +48,13 @@ int32 OS_SelectMultiple_Impl(OS_FdSet *ReadSet, OS_FdSet *WriteSet, int32 msecs) * Generated stub function for OS_SelectSingle_Impl() * ---------------------------------------------------- */ -int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, int32 msecs) +int32 OS_SelectSingle_Impl(const OS_object_token_t *token, uint32 *SelectFlags, OS_time_t abs_timeout) { UT_GenStub_SetupReturnBuffer(OS_SelectSingle_Impl, int32); UT_GenStub_AddParam(OS_SelectSingle_Impl, const OS_object_token_t *, token); UT_GenStub_AddParam(OS_SelectSingle_Impl, uint32 *, SelectFlags); - UT_GenStub_AddParam(OS_SelectSingle_Impl, int32, msecs); + UT_GenStub_AddParam(OS_SelectSingle_Impl, OS_time_t, abs_timeout); UT_GenStub_Execute(OS_SelectSingle_Impl, Basic, NULL); diff --git a/src/unit-test-coverage/ut-stubs/src/os-shared-sockets-impl-stubs.c b/src/unit-test-coverage/ut-stubs/src/os-shared-sockets-impl-stubs.c index 5ec3ea0f9..5e258b095 100644 --- a/src/unit-test-coverage/ut-stubs/src/os-shared-sockets-impl-stubs.c +++ b/src/unit-test-coverage/ut-stubs/src/os-shared-sockets-impl-stubs.c @@ -45,14 +45,14 @@ void OS_SetSocketDefaultFlags_Impl(const OS_object_token_t *token) * ---------------------------------------------------- */ int32 OS_SocketAccept_Impl(const OS_object_token_t *sock_token, const OS_object_token_t *conn_token, - OS_SockAddr_t *Addr, int32 timeout) + OS_SockAddr_t *Addr, OS_time_t abs_timeout) { UT_GenStub_SetupReturnBuffer(OS_SocketAccept_Impl, int32); UT_GenStub_AddParam(OS_SocketAccept_Impl, const OS_object_token_t *, sock_token); UT_GenStub_AddParam(OS_SocketAccept_Impl, const OS_object_token_t *, conn_token); UT_GenStub_AddParam(OS_SocketAccept_Impl, OS_SockAddr_t *, Addr); - UT_GenStub_AddParam(OS_SocketAccept_Impl, int32, timeout); + UT_GenStub_AddParam(OS_SocketAccept_Impl, OS_time_t, abs_timeout); UT_GenStub_Execute(OS_SocketAccept_Impl, Basic, NULL); @@ -167,13 +167,13 @@ int32 OS_SocketBindAddress_Impl(const OS_object_token_t *token, const OS_SockAdd * Generated stub function for OS_SocketConnect_Impl() * ---------------------------------------------------- */ -int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, int32 timeout) +int32 OS_SocketConnect_Impl(const OS_object_token_t *token, const OS_SockAddr_t *Addr, OS_time_t abs_timeout) { UT_GenStub_SetupReturnBuffer(OS_SocketConnect_Impl, int32); UT_GenStub_AddParam(OS_SocketConnect_Impl, const OS_object_token_t *, token); UT_GenStub_AddParam(OS_SocketConnect_Impl, const OS_SockAddr_t *, Addr); - UT_GenStub_AddParam(OS_SocketConnect_Impl, int32, timeout); + UT_GenStub_AddParam(OS_SocketConnect_Impl, OS_time_t, abs_timeout); UT_GenStub_Execute(OS_SocketConnect_Impl, Basic, NULL); @@ -235,7 +235,7 @@ int32 OS_SocketOpen_Impl(const OS_object_token_t *token) * ---------------------------------------------------- */ int32 OS_SocketRecvFrom_Impl(const OS_object_token_t *token, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, - int32 timeout) + OS_time_t abs_timeout) { UT_GenStub_SetupReturnBuffer(OS_SocketRecvFrom_Impl, int32); @@ -243,7 +243,7 @@ int32 OS_SocketRecvFrom_Impl(const OS_object_token_t *token, void *buffer, size_ UT_GenStub_AddParam(OS_SocketRecvFrom_Impl, void *, buffer); UT_GenStub_AddParam(OS_SocketRecvFrom_Impl, size_t, buflen); UT_GenStub_AddParam(OS_SocketRecvFrom_Impl, OS_SockAddr_t *, RemoteAddr); - UT_GenStub_AddParam(OS_SocketRecvFrom_Impl, int32, timeout); + UT_GenStub_AddParam(OS_SocketRecvFrom_Impl, OS_time_t, abs_timeout); UT_GenStub_Execute(OS_SocketRecvFrom_Impl, Basic, NULL); diff --git a/src/ut-stubs/osapi-clock-stubs.c b/src/ut-stubs/osapi-clock-stubs.c index 4d3b11bc8..27914ea91 100644 --- a/src/ut-stubs/osapi-clock-stubs.c +++ b/src/ut-stubs/osapi-clock-stubs.c @@ -59,3 +59,35 @@ int32 OS_SetLocalTime(const OS_time_t *time_struct) return UT_GenStub_GetReturnValue(OS_SetLocalTime, int32); } + +/* + * ---------------------------------------------------- + * Generated stub function for OS_TimeFromRelativeMilliseconds() + * ---------------------------------------------------- + */ +OS_time_t OS_TimeFromRelativeMilliseconds(int32 relative_msec) +{ + UT_GenStub_SetupReturnBuffer(OS_TimeFromRelativeMilliseconds, OS_time_t); + + UT_GenStub_AddParam(OS_TimeFromRelativeMilliseconds, int32, relative_msec); + + UT_GenStub_Execute(OS_TimeFromRelativeMilliseconds, Basic, NULL); + + return UT_GenStub_GetReturnValue(OS_TimeFromRelativeMilliseconds, OS_time_t); +} + +/* + * ---------------------------------------------------- + * Generated stub function for OS_TimeToRelativeMilliseconds() + * ---------------------------------------------------- + */ +int32 OS_TimeToRelativeMilliseconds(OS_time_t time) +{ + UT_GenStub_SetupReturnBuffer(OS_TimeToRelativeMilliseconds, int32); + + UT_GenStub_AddParam(OS_TimeToRelativeMilliseconds, OS_time_t, time); + + UT_GenStub_Execute(OS_TimeToRelativeMilliseconds, Basic, NULL); + + return UT_GenStub_GetReturnValue(OS_TimeToRelativeMilliseconds, int32); +} diff --git a/src/ut-stubs/osapi-file-stubs.c b/src/ut-stubs/osapi-file-stubs.c index de52a1570..3a211cc51 100644 --- a/src/ut-stubs/osapi-file-stubs.c +++ b/src/ut-stubs/osapi-file-stubs.c @@ -35,6 +35,44 @@ void UT_DefaultHandler_OS_read(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_OS_stat(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_OS_write(void *, UT_EntryKey_t, const UT_StubContext_t *); +/* + * ---------------------------------------------------- + * Generated stub function for OS_AbsTimedRead() + * ---------------------------------------------------- + */ +int32 OS_AbsTimedRead(osal_id_t filedes, void *buffer, size_t nbytes, OS_time_t abstime) +{ + UT_GenStub_SetupReturnBuffer(OS_AbsTimedRead, int32); + + UT_GenStub_AddParam(OS_AbsTimedRead, osal_id_t, filedes); + UT_GenStub_AddParam(OS_AbsTimedRead, void *, buffer); + UT_GenStub_AddParam(OS_AbsTimedRead, size_t, nbytes); + UT_GenStub_AddParam(OS_AbsTimedRead, OS_time_t, abstime); + + UT_GenStub_Execute(OS_AbsTimedRead, Basic, NULL); + + return UT_GenStub_GetReturnValue(OS_AbsTimedRead, int32); +} + +/* + * ---------------------------------------------------- + * Generated stub function for OS_AbsTimedWrite() + * ---------------------------------------------------- + */ +int32 OS_AbsTimedWrite(osal_id_t filedes, const void *buffer, size_t nbytes, OS_time_t abstime) +{ + UT_GenStub_SetupReturnBuffer(OS_AbsTimedWrite, int32); + + UT_GenStub_AddParam(OS_AbsTimedWrite, osal_id_t, filedes); + UT_GenStub_AddParam(OS_AbsTimedWrite, const void *, buffer); + UT_GenStub_AddParam(OS_AbsTimedWrite, size_t, nbytes); + UT_GenStub_AddParam(OS_AbsTimedWrite, OS_time_t, abstime); + + UT_GenStub_Execute(OS_AbsTimedWrite, Basic, NULL); + + return UT_GenStub_GetReturnValue(OS_AbsTimedWrite, int32); +} + /* * ---------------------------------------------------- * Generated stub function for OS_CloseAllFiles() diff --git a/src/ut-stubs/osapi-sockets-stubs.c b/src/ut-stubs/osapi-sockets-stubs.c index d8676076a..3c8940056 100644 --- a/src/ut-stubs/osapi-sockets-stubs.c +++ b/src/ut-stubs/osapi-sockets-stubs.c @@ -280,6 +280,27 @@ int32 OS_SocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockA return UT_GenStub_GetReturnValue(OS_SocketRecvFrom, int32); } +/* + * ---------------------------------------------------- + * Generated stub function for OS_AbsSocketRecvFrom() + * ---------------------------------------------------- + */ +int32 OS_AbsSocketRecvFrom(osal_id_t sock_id, void *buffer, size_t buflen, OS_SockAddr_t *RemoteAddr, + OS_time_t abs_timeout) +{ + UT_GenStub_SetupReturnBuffer(OS_AbsSocketRecvFrom, int32); + + UT_GenStub_AddParam(OS_AbsSocketRecvFrom, osal_id_t, sock_id); + UT_GenStub_AddParam(OS_AbsSocketRecvFrom, void *, buffer); + UT_GenStub_AddParam(OS_AbsSocketRecvFrom, size_t, buflen); + UT_GenStub_AddParam(OS_AbsSocketRecvFrom, OS_SockAddr_t *, RemoteAddr); + UT_GenStub_AddParam(OS_AbsSocketRecvFrom, OS_time_t, abs_timeout); + + UT_GenStub_Execute(OS_AbsSocketRecvFrom, Basic, NULL); + + return UT_GenStub_GetReturnValue(OS_AbsSocketRecvFrom, int32); +} + /* * ---------------------------------------------------- * Generated stub function for OS_SocketSendTo()