зеркало из https://github.com/Azure/c-pal.git
implemented sync on linux, worked on feedback from 1st review
This commit is contained in:
Родитель
0ac0c6187c
Коммит
abfdfc52a6
|
@ -19,31 +19,23 @@
|
|||
#include "timer.h"
|
||||
|
||||
#include "umock_c/umock_c.h"
|
||||
#include "umock_c/umock_c_prod.h"
|
||||
|
||||
TEST_DEFINE_ENUM_TYPE(THREADAPI_RESULT, THREADAPI_RESULT_VALUES)
|
||||
|
||||
static TEST_MUTEX_HANDLE g_testByTest;
|
||||
|
||||
MU_DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES)
|
||||
|
||||
static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code)
|
||||
{
|
||||
ASSERT_FAIL("umock_c reported error :%" PRI_MU_ENUM "", MU_ENUM_VALUE(UMOCK_C_ERROR_CODE, error_code));
|
||||
}
|
||||
|
||||
static int increment_on_odd_values(void* address)
|
||||
{
|
||||
volatile_atomic int32_t* ptr = (volatile_atomic int32_t*)address;
|
||||
while (interlocked_add(ptr, 0) < 98)
|
||||
{
|
||||
int value = interlocked_add(ptr, 0);
|
||||
int32_t value = interlocked_add(ptr, 0);
|
||||
while (value % 2 != 1)
|
||||
{
|
||||
wait_on_address(ptr, &value, UINT32_MAX);
|
||||
ASSERT_IS_TRUE(wait_on_address(ptr, &value, UINT32_MAX));
|
||||
value = interlocked_add(ptr, 0);
|
||||
}
|
||||
interlocked_increment(ptr);
|
||||
(void)interlocked_increment(ptr);
|
||||
wake_by_address_all(ptr);
|
||||
}
|
||||
ThreadAPI_Exit(0);
|
||||
|
@ -58,10 +50,10 @@ static int increment_on_even_values(void* address)
|
|||
int value = interlocked_add(ptr, 0);
|
||||
while(value % 2 != 0)
|
||||
{
|
||||
wait_on_address(ptr, &value, UINT32_MAX);
|
||||
ASSERT_IS_TRUE(wait_on_address(ptr, &value, UINT32_MAX));
|
||||
value = interlocked_add(ptr, 0);
|
||||
}
|
||||
interlocked_increment(ptr);
|
||||
(void)interlocked_increment(ptr);
|
||||
wake_by_address_all(ptr);
|
||||
}
|
||||
ThreadAPI_Exit(0);
|
||||
|
@ -73,10 +65,10 @@ static int increment_on_wake_up(void* address)
|
|||
{
|
||||
volatile_atomic int32_t* ptr = (volatile_atomic int32_t*)address;
|
||||
int32_t value = interlocked_add(ptr, 0);
|
||||
interlocked_increment(&create_count);
|
||||
(void)interlocked_increment(&create_count);
|
||||
wake_by_address_single(&create_count);
|
||||
wait_on_address(ptr, &value, UINT32_MAX);
|
||||
interlocked_increment(ptr);
|
||||
ASSERT_IS_TRUE(wait_on_address(ptr, &value, UINT32_MAX));
|
||||
(void)interlocked_increment(ptr);
|
||||
ThreadAPI_Exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -110,38 +102,34 @@ TEST_FUNCTION_CLEANUP(d)
|
|||
TEST_MUTEX_RELEASE(g_testByTest);
|
||||
}
|
||||
|
||||
/*Codes_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Codes_SRS_SYNC_43_007: [ If *address is equal to *compare_address, wait_on_address shall cause the thread to sleep. ]*/
|
||||
/*Codes_SRS_SYNC_43_008: [wait_on_address shall wait indefinitely until it is woken up by a call to wake_by_address_[single/all] if timeout_ms is equal to UINT32_MAX]*/
|
||||
/*Codes_SRS_SYNC_43_003: [ wait_on_address shall wait until another thread in the same process signals at address using wake_by_address_[single/all] and return true. ]*/
|
||||
/*Tests_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Tests_SRS_SYNC_43_007: [ If *address is equal to *compare_address, wait_on_address shall cause the thread to sleep. ]*/
|
||||
/*Tests_SRS_SYNC_43_008: [wait_on_address shall wait indefinitely until it is woken up by a call to wake_by_address_[single/all] if timeout_ms is equal to UINT32_MAX]*/
|
||||
/*Tests_SRS_SYNC_43_003: [ wait_on_address shall wait until another thread in the same process signals at address using wake_by_address_[single/all] and return true. ]*/
|
||||
TEST_FUNCTION(two_threads_increment_alternately)
|
||||
{
|
||||
///arrange
|
||||
volatile_atomic int32_t var;
|
||||
interlocked_exchange(&var, 0);
|
||||
|
||||
THREAD_HANDLE thread1;
|
||||
THREAD_HANDLE thread2;
|
||||
|
||||
///act
|
||||
ASSERT_ARE_EQUAL(THREADAPI_RESULT, THREADAPI_OK, ThreadAPI_Create(&thread1, increment_on_even_values, (void*)&var));
|
||||
ASSERT_ARE_EQUAL(THREADAPI_RESULT, THREADAPI_OK, ThreadAPI_Create(&thread2, increment_on_odd_values, (void*)&var));
|
||||
|
||||
|
||||
|
||||
///assert
|
||||
int return1;
|
||||
ThreadAPI_Join(thread1, &return1);
|
||||
int return2;
|
||||
ThreadAPI_Join(thread2, &return2);
|
||||
ASSERT_ARE_EQUAL(int32_t, 99, interlocked_add(&var, 0), "Return value is incorrect");
|
||||
ASSERT_ARE_EQUAL(THREADAPI_RESULT, THREADAPI_OK, ThreadAPI_Join(thread1, NULL), "ThreadAPI_Join did not work");
|
||||
ASSERT_ARE_EQUAL(THREADAPI_RESULT, THREADAPI_OK, ThreadAPI_Join(thread2, NULL), "ThreadAPI_Join did not work");
|
||||
ASSERT_ARE_EQUAL(int32_t, 99, interlocked_add(&var, 0), "Threads did not increment value expected number of times.");
|
||||
}
|
||||
|
||||
/*Codes_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Codes_SRS_SYNC_43_007: [ If *address is equal to *compare_address, wait_on_address shall cause the thread to sleep. ]*/
|
||||
/*Codes_SRS_SYNC_43_008: [wait_on_address shall wait indefinitely until it is woken up by a call to wake_by_address_[single/all] if timeout_ms is equal to UINT32_MAX]*/
|
||||
/*Codes_SRS_SYNC_43_003: [ wait_on_address shall wait until another thread in the same process signals at address using wake_by_address_[single/all] and return true. ]*/
|
||||
/*Codes_SRS_SYNC_43_004: [ wake_by_address_all shall cause all the thread(s) waiting on a call to wait_on_address with argument address to continue execution. ]*/
|
||||
/*Codes_SRS_SYNC_43_005: [ wake_by_address_single shall cause one thread waiting on a call to wait_on_address with argument address to continue execution. ]*/
|
||||
/*Tests_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Tests_SRS_SYNC_43_007: [ If *address is equal to *compare_address, wait_on_address shall cause the thread to sleep. ]*/
|
||||
/*Tests_SRS_SYNC_43_008: [wait_on_address shall wait indefinitely until it is woken up by a call to wake_by_address_[single/all] if timeout_ms is equal to UINT32_MAX]*/
|
||||
/*Tests_SRS_SYNC_43_003: [ wait_on_address shall wait until another thread in the same process signals at address using wake_by_address_[single/all] and return true. ]*/
|
||||
/*Tests_SRS_SYNC_43_004: [ wake_by_address_all shall cause all the thread(s) waiting on a call to wait_on_address with argument address to continue execution. ]*/
|
||||
/*Tests_SRS_SYNC_43_005: [ wake_by_address_single shall cause one thread waiting on a call to wait_on_address with argument address to continue execution. ]*/
|
||||
TEST_FUNCTION(wake_up_all_threads)
|
||||
{
|
||||
///arrange
|
||||
|
@ -151,20 +139,21 @@ TEST_FUNCTION(wake_up_all_threads)
|
|||
THREAD_HANDLE threads[100];
|
||||
|
||||
///act
|
||||
for(int i = 0; i < 100; ++i){
|
||||
for(int i = 0; i < 100; ++i)
|
||||
{
|
||||
ASSERT_ARE_EQUAL(THREADAPI_RESULT, THREADAPI_OK, ThreadAPI_Create(&threads[i], increment_on_wake_up, (void*)&var));
|
||||
}
|
||||
|
||||
int current_create_count = interlocked_add(&create_count, 0);
|
||||
while (current_create_count < 100)
|
||||
{
|
||||
wait_on_address(&create_count, ¤t_create_count, UINT32_MAX);
|
||||
ASSERT_IS_TRUE(wait_on_address(&create_count, ¤t_create_count, UINT32_MAX));
|
||||
current_create_count = interlocked_add(&create_count, 0);
|
||||
}
|
||||
wake_by_address_all(&var);
|
||||
for(int i = 0; i < 100; ++i){
|
||||
int return_val;
|
||||
ThreadAPI_Join(threads[i], &return_val);
|
||||
for(int i = 0; i < 100; ++i)
|
||||
{
|
||||
ASSERT_ARE_EQUAL(THREADAPI_RESULT, THREADAPI_OK, ThreadAPI_Join(threads[i], NULL), "ThreadAPI_Join did not work");
|
||||
}
|
||||
|
||||
///assert
|
||||
|
@ -172,8 +161,8 @@ TEST_FUNCTION(wake_up_all_threads)
|
|||
}
|
||||
|
||||
|
||||
/*Codes_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Codes_SRS_SYNC_43_002: [ wait_on_address shall immediately return true if *address is not equal to *compare_address.]*/
|
||||
/*Tests_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Tests_SRS_SYNC_43_002: [ wait_on_address shall immediately return true if *address is not equal to *compare_address.]*/
|
||||
TEST_FUNCTION(wait_on_address_returns_immediately)
|
||||
{
|
||||
///arrange
|
||||
|
@ -189,9 +178,9 @@ TEST_FUNCTION(wait_on_address_returns_immediately)
|
|||
}
|
||||
|
||||
|
||||
/*Codes_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Codes_SRS_SYNC_43_002: [ wait_on_address shall immediately return true if *address is not equal to *compare_address.]*/
|
||||
/*Codes_SRS_SYNC_43_009: [ If timeout_ms milliseconds elapse, wait_on_address shall return false. ]*/
|
||||
/*Tests_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Tests_SRS_SYNC_43_002: [ wait_on_address shall immediately return true if *address is not equal to *compare_address.]*/
|
||||
/*Tests_SRS_SYNC_43_009: [ If timeout_ms milliseconds elapse, wait_on_address shall return false. ]*/
|
||||
TEST_FUNCTION(wait_on_address_returns_after_timeout_elapses)
|
||||
{
|
||||
///arrange
|
||||
|
@ -199,13 +188,15 @@ TEST_FUNCTION(wait_on_address_returns_after_timeout_elapses)
|
|||
interlocked_exchange(&var, 0);
|
||||
int value = 0;
|
||||
int timeout = 1000;
|
||||
double tolerance_factor = 1.5;
|
||||
|
||||
/// act
|
||||
double start_time = timer_global_get_elapsed_ms();
|
||||
bool return_val = wait_on_address(&var, &value, timeout);
|
||||
double time_elapsed = timer_global_get_elapsed_ms() - start_time;
|
||||
|
||||
///assert
|
||||
ASSERT_IS_TRUE(time_elapsed < timeout * 1.5, "Too much time elapsed");
|
||||
ASSERT_IS_TRUE(time_elapsed < timeout* tolerance_factor, "Too much time elapsed. Maximum Expected: %lf, Actual: %lf", timeout*tolerance_factor, time_elapsed);
|
||||
ASSERT_IS_FALSE(return_val, "wait_on_address should have returned false");
|
||||
}
|
||||
END_TEST_SUITE(sync_int)
|
||||
|
|
|
@ -22,7 +22,7 @@ MOCKABLE_FUNCTION(, bool, wait_on_address, volatile_atomic int32_t*, address, in
|
|||
**SRS_SYNC_LINUX_43_001: [** `wait_on_address` shall initialize a `timespec` struct with `.tv_nsec` equal to `timeout_ms* 10^6`. **]**
|
||||
|
||||
|
||||
**SRS_SYNC_LINUX_43_002: [** `wait_on_address` shall call `syscall` from `sys/syscall.h` with arguments `SYS_futex`, `address`, `FUTEX_WAIT_PRIVATE`, `*compare_address`, `timeout_struct`, `NULL`, `NULL`. **]**
|
||||
**SRS_SYNC_LINUX_43_002: [** `wait_on_address` shall call `syscall` from `sys/syscall.h` with arguments `SYS_futex`, `address`, `FUTEX_WAIT_PRIVATE`, `*compare_address`, `*timeout_struct`, `NULL`, `0`. **]**
|
||||
|
||||
**SRS_SYNC_LINUX_43_003: [** `wait_on_address` shall return `true` if `syscall` returns `0`.**]**
|
||||
|
||||
|
@ -35,7 +35,7 @@ MOCKABLE_FUNCTION(, bool, wait_on_address, volatile_atomic int32_t*, address, in
|
|||
MOCKABLE_FUNCTION(, void, wake_by_address_all, volatile_atomic int32_t*, address)
|
||||
```
|
||||
|
||||
**SRS_SYNC_LINUX_43_005: [** `wake_by_address_all` shall call `syscall` from `sys/syscall.h` with arguments `SYS_futex`, `address`, `FUTEX_WAKE_PRIVATE`, `INT_MAX`, `NULL`, `NULL`, `NULL`. **]**
|
||||
**SRS_SYNC_LINUX_43_005: [** `wake_by_address_all` shall call `syscall` from `sys/syscall.h` with arguments `SYS_futex`, `address`, `FUTEX_WAKE_PRIVATE`, `INT_MAX`, `NULL`, `NULL`, `0`. **]**
|
||||
|
||||
## wake_by_address_single
|
||||
|
||||
|
@ -43,4 +43,4 @@ MOCKABLE_FUNCTION(, void, wake_by_address_all, volatile_atomic int32_t*, address
|
|||
MOCKABLE_FUNCTION(, void, wake_by_address_single, volatile_atomic int32_t*, address)
|
||||
```
|
||||
|
||||
**SRS_SYNC_LINUX_43_006: [** `wake_by_address_single` shall call `syscall` from `sys/syscall.h` with arguments `SYS_futex`, `address`, `FUTEX_WAKE_PRIVATE`, `1`, `NULL`, `NULL`, `NULL`. **]**
|
||||
**SRS_SYNC_LINUX_43_006: [** `wake_by_address_single` shall call `syscall` from `sys/syscall.h` with arguments `SYS_futex`, `address`, `FUTEX_WAKE_PRIVATE`, `1`, `NULL`, `NULL`, `0`. **]**
|
||||
|
|
|
@ -3,22 +3,37 @@
|
|||
|
||||
#include "sys/syscall.h"
|
||||
#include "linux/futex.h"
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "sync.h"
|
||||
|
||||
IMPLEMENT_MOCKABLE_FUNCTION(, bool, wait_on_address, volatile_atomic int32_t*, address, int32_t*, compare_address, uint32_t, timeout_ms)
|
||||
{
|
||||
(void) address;
|
||||
(void) compare_address;
|
||||
(void) timeout_ms;
|
||||
return false;
|
||||
/*Codes_SRS_SYNC_43_001: [ wait_on_address shall atomically compare *address and *compare_address.]*/
|
||||
/*Codes_SRS_SYNC_43_002: [ wait_on_address shall immediately return true if *address is not equal to *compare_address.]*/
|
||||
/*Codes_SRS_SYNC_43_007: [ If *address is equal to *compare_address, wait_on_address shall cause the thread to sleep. ]*/
|
||||
/*Codes_SRS_SYNC_43_009: [ If timeout_ms milliseconds elapse, wait_on_address shall return false. ]*/
|
||||
/*Codes_SRS_SYNC_43_008: [wait_on_address shall wait indefinitely until it is woken up by a call to wake_by_address_[single/all] if timeout_ms is equal to UINT32_MAX]*/
|
||||
/*Codes_SRS_SYNC_43_003: [ wait_on_address shall wait until another thread in the same process signals at address using wake_by_address_[single/all] and return true. ]*/
|
||||
/*Codes_SRS_SYNC_LINUX_43_001: [ wait_on_address shall initialize a timespec struct with .tv_nsec equal to timeout_ms* 10^6. ]*/
|
||||
struct timespec timeout = {timeout_ms / 1000, (timeout_ms % 1000) * 1e6 };
|
||||
|
||||
/*Codes_SRS_SYNC_LINUX_43_002: [ wait_on_address shall call syscall from sys/syscall.h with arguments SYS_futex, address, FUTEX_WAIT_PRIVATE, *compare_address, *timeout_struct, NULL, 0. ]*/
|
||||
/*Codes_SRS_SYNC_LINUX_43_003: [ wait_on_address shall return true if syscall returns 0.]*/
|
||||
/*Codes_SRS_SYNC_LINUX_43_004: [ wait_on_address shall return false if syscall does not return 0.]*/
|
||||
return syscall(SYS_futex, address, FUTEX_WAIT_PRIVATE, *compare_address, &timeout, NULL, 0) == 0;
|
||||
|
||||
}
|
||||
IMPLEMENT_MOCKABLE_FUNCTION(, void, wake_by_address_all, volatile_atomic int32_t*, address)
|
||||
{
|
||||
(void) address;
|
||||
/*Codes_SRS_SYNC_43_004: [ wake_by_address_all shall cause all the thread(s) waiting on a call to wait_on_address with argument address to continue execution. ]*/
|
||||
/*Codes_SRS_SYNC_LINUX_43_005: [ wake_by_address_all shall call syscall from sys/syscall.h with arguments SYS_futex, address, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0. ]*/
|
||||
syscall(SYS_futex, address, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
|
||||
}
|
||||
IMPLEMENT_MOCKABLE_FUNCTION(, void, wake_by_address_single, volatile_atomic int32_t*, address)
|
||||
{
|
||||
(void) address;
|
||||
/*Codes_SRS_SYNC_43_005: [ wake_by_address_single shall cause one thread waiting on a call to wait_on_address with argument address to continue execution. ]*/
|
||||
/*Codes_SRS_SYNC_LINUX_43_006: [ wake_by_address_single shall call syscall from sys/syscall.h with arguments SYS_futex, address, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0. ]*/
|
||||
syscall(SYS_futex, address, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include "mock_sync.h"
|
||||
|
||||
#undef syscall
|
||||
#define syscall mock_syscall
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#include <sys/sycall.h>
|
||||
#include <linux/futex.h>
|
||||
#ifndef MOCK_SYNC_H
|
||||
#define MOCK_SYNC_H
|
||||
#include <time.h>
|
||||
#include "umock_c/umock_c_prod.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -16,3 +15,4 @@ MOCKABLE_FUNCTION(, int, mock_syscall, long, call_code, int*, uaddr, int, futex_
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -4,20 +4,24 @@
|
|||
#ifdef __cplusplus
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <cstdatomic>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/futex.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "azure_macro_utils/macro_utils.h"
|
||||
#include "testrunnerswitcher.h"
|
||||
|
||||
#include "umock_c/umock_c.h"
|
||||
#include "umock_c/umocktypes_windows.h"
|
||||
|
||||
#include "sync.h"
|
||||
|
||||
|
@ -30,30 +34,26 @@ static void on_umock_c_error(UMOCK_C_ERROR_CODE error_code)
|
|||
ASSERT_FAIL("umock_c reported error :%" PRI_MU_ENUM "", MU_ENUM_VALUE(UMOCK_C_ERROR_CODE, error_code));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define ENABLE_MOCKS
|
||||
#include "mock_sync.h"
|
||||
#undef ENABLE_MOCKS
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool check_timeout;
|
||||
static uint32_t expected_timeout_ms;
|
||||
static int expected_return_val;
|
||||
static bool hook_mock_syscall(long call_code, int* uaddr, int futex_op, int val, const struct timespec* timeout, int* uaddr2, int val3)
|
||||
static int hook_mock_syscall(long call_code, int* uaddr, int futex_op, int val, const struct timespec* timeout, int* uaddr2, int val3)
|
||||
{
|
||||
/*Tests_SRS_SYNC_LINUX_43_001: [ wait_on_address shall initialize a timespec struct with .tv_nsec equal to timeout_ms* 10^6. ]*/
|
||||
ASSERT_ARE_EQUAL(long, expected_timeout_ms*10e6, timeout->tv_nsec);
|
||||
if(check_timeout)
|
||||
{
|
||||
ASSERT_ARE_EQUAL(long, expected_timeout_ms*1e6, timeout->tv_nsec);
|
||||
}
|
||||
return expected_return_val;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_TEST_SUITE(sync_win32_unittests)
|
||||
BEGIN_TEST_SUITE(sync_linux_unittests)
|
||||
|
||||
TEST_SUITE_INITIALIZE(suite_init)
|
||||
{
|
||||
|
@ -91,15 +91,16 @@ TEST_FUNCTION_CLEANUP(cleans)
|
|||
TEST_FUNCTION(wait_on_address_calls_syscall_successfully)
|
||||
{
|
||||
///arrange
|
||||
volatile int32_t var;
|
||||
volatile_atomic int32_t var;
|
||||
int32_t val = INT32_MAX;
|
||||
InterlockedExchange((volatile LONG*)&var, val);
|
||||
expected_timeout_ms = 1000;
|
||||
atomic_exchange(&var, val);
|
||||
check_timeout = true;
|
||||
expected_timeout_ms = 100;
|
||||
expected_return_val = 0;
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int32_t*)&var, FUTEX_WAIT_PRIVATE, val, IGNORED_ARG, NULL, NULL));
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int32_t*)&var, FUTEX_WAIT_PRIVATE, val, IGNORED_ARG, NULL, 0));
|
||||
|
||||
///act
|
||||
bool return_val = wait_on_address(&var, val, timeout);
|
||||
bool return_val = wait_on_address(&var, &val, expected_timeout_ms);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Actual calls differ from expected calls");
|
||||
|
@ -111,15 +112,16 @@ TEST_FUNCTION(wait_on_address_calls_syscall_successfully)
|
|||
TEST_FUNCTION(wait_on_address_calls_sycall_unsuccessfully)
|
||||
{
|
||||
///arrange
|
||||
volatile int32_t var;
|
||||
volatile_atomic int32_t var;
|
||||
int32_t val = INT32_MAX;
|
||||
InterlockedExchange((volatile LONG*)&var, val);
|
||||
expected_timeout_ms = 1000;
|
||||
atomic_exchange(&var, val);
|
||||
check_timeout = true;
|
||||
expected_timeout_ms = 100;
|
||||
expected_return_val = -1;
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int*)&var, FUTEX_WAIT_PRIVATE, val, IGNORED_ARG, NULL, NULL));
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int*)&var, FUTEX_WAIT_PRIVATE, val, IGNORED_ARG, NULL, 0));
|
||||
|
||||
///act
|
||||
bool return_val = wait_on_address(&var, val, timeout);
|
||||
bool return_val = wait_on_address(&var, &val, expected_timeout_ms);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Actual calls differ from expected calls");
|
||||
|
@ -130,10 +132,12 @@ TEST_FUNCTION(wait_on_address_calls_sycall_unsuccessfully)
|
|||
TEST_FUNCTION(wake_by_address_all_calls_sycall)
|
||||
{
|
||||
///arrange
|
||||
volatile int32_t var;
|
||||
check_timeout = false;
|
||||
volatile_atomic int32_t var;
|
||||
int32_t val = INT32_MAX;
|
||||
InterlockedExchange((volatile LONG*)&var, val);
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int*)&var, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, NULL));
|
||||
atomic_exchange(&var, val);
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int*)&var, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0));
|
||||
|
||||
///act
|
||||
wake_by_address_all(&var);
|
||||
|
||||
|
@ -145,14 +149,16 @@ TEST_FUNCTION(wake_by_address_all_calls_sycall)
|
|||
TEST_FUNCTION(wake_by_address_single_calls_sycall)
|
||||
{
|
||||
///arrange
|
||||
volatile int32_t var;
|
||||
check_timeout = false;
|
||||
volatile_atomic int32_t var;
|
||||
int32_t val = INT32_MAX;
|
||||
InterlockedExchange((volatile LONG*)&var, val);
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int*)&var, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, NULL));
|
||||
atomic_exchange(&var, val);
|
||||
STRICT_EXPECTED_CALL(mock_syscall(SYS_futex, (int*)&var, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0));
|
||||
|
||||
///act
|
||||
wake_by_address_all(&var);
|
||||
wake_by_address_single(&var);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Actual calls differ from expected calls");
|
||||
}
|
||||
END_TEST_SUITE(sync_win32_unittests)
|
||||
END_TEST_SUITE(sync_linux_unittests)
|
||||
|
|
|
@ -8,7 +8,7 @@ IMPLEMENT_MOCKABLE_FUNCTION(, bool, wait_on_address, volatile_atomic int32_t*, a
|
|||
{
|
||||
/*Codes_SRS_SYNC_WIN32_43_001: [ wait_on_address shall call WaitOnAddress from windows.h with address as Address, compare_address as CompareAddress, 4 as AddressSize and timeout_ms as dwMilliseconds. ]*/
|
||||
/*Codes_SRS_SYNC_WIN32_43_002: [ wait_on_address shall return the return value of WaitOnAddress ]*/
|
||||
return WaitOnAddress((volatile VOID*) address, (PVOID)compare_address, (SIZE_T)4, (DWORD)timeout_ms);
|
||||
return WaitOnAddress(address, compare_address, sizeof(*compare_address), timeout_ms);
|
||||
}
|
||||
IMPLEMENT_MOCKABLE_FUNCTION(, void, wake_by_address_all, volatile_atomic int32_t*, address)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@ TEST_SUITE_INITIALIZE(suite_init)
|
|||
ASSERT_IS_NOT_NULL(g_testByTest);
|
||||
ASSERT_ARE_EQUAL(int, 0, umock_c_init(on_umock_c_error));
|
||||
ASSERT_ARE_EQUAL(int, 0, umocktypes_windows_register_types());
|
||||
REGISTER_UMOCK_ALIAS_TYPE(SIZE_T, size_t);
|
||||
}
|
||||
|
||||
TEST_SUITE_CLEANUP(TestClassCleanup)
|
||||
|
@ -89,7 +90,7 @@ TEST_FUNCTION(wait_on_address_calls_WaitOnAddress_successfully)
|
|||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Actual calls differ from expected calls");
|
||||
ASSERT_IS_TRUE(return_val, "Return value is incorrect.");
|
||||
ASSERT_IS_TRUE(return_val, "Return value is incorrect");
|
||||
}
|
||||
|
||||
/*Tests_SRS_SYNC_WIN32_43_001: [ wait_on_address shall call WaitOnAddress from windows.h with address as Address, compare_address as CompareAddress, 4 as AddressSize and timeout_ms as dwMilliseconds. ]*/
|
||||
|
@ -109,10 +110,10 @@ TEST_FUNCTION(wait_on_address_calls_WaitOnAddress_unsuccessfully)
|
|||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls(), "Actual calls differ from expected calls");
|
||||
ASSERT_IS_FALSE(return_val, "Return value is incorrect.");
|
||||
ASSERT_IS_FALSE(return_val, "wait_on_address was supposed to fail but did not.");
|
||||
}
|
||||
|
||||
/*Tests_SRS_SYNC_WIN32_43_004: [ wake_by_address_single shall call WakeByAddressSingle from windows.h with address as Address. ]*/
|
||||
/*Tests_SRS_SYNC_WIN32_43_003: [ wake_by_address_all shall call WakeByAddressAll from windows.h with address as Address. ]*/
|
||||
TEST_FUNCTION(wake_by_address_all_calls_WakeByAddressAll)
|
||||
{
|
||||
///arrange
|
||||
|
|
Загрузка…
Ссылка в новой задаче