Initial contribution

This commit is contained in:
Michiel Beemster 2018-04-10 17:03:59 +02:00
parent 7b5cc4fa59
commit 11d9ce37aa
580 changed files with 155133 additions and 162 deletions

View file

@ -0,0 +1,16 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
include(CUnit)
add_cunit_executable(abstraction .)
target_link_libraries(abstraction OSAPI)

467
src/os/tests/atomics.c Normal file
View file

@ -0,0 +1,467 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "os/os.h"
#include "CUnit/Runner.h"
uint32_t _osuint32 = 0;
uint64_t _osuint64 = 0;
// os_address is uintptr_t
uintptr_t _osaddress = 0;
ptrdiff_t _ptrdiff = 0;
void * _osvoidp = (uintptr_t *)0;
CUnit_Test(os_atomics, load_store)
{
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(5);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(5);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(5);
volatile os_atomic_voidp_t voidp = OS_ATOMIC_VOIDP_INIT((uintptr_t)5);
/* Test uint32 LD-ST */
printf ("Starting os_atomics_load_store_001\n");
CU_ASSERT (os_atomic_ld32 (&uint32) == 5); /* Returns contents of uint32 */
os_atomic_st32 (&uint32, _osuint32); /* Writes os_uint32 into uint32 */
CU_ASSERT (os_atomic_ld32 (&uint32) == _osuint32);
/* Test uint64 LD-ST */
printf ("Starting os_atomics_load_store_002\n");
#if OS_ATOMIC64_SUPPORT
CU_ASSERT (os_atomic_ld64 (&uint64) == 5);
os_atomic_st64 (&uint64, _osuint64);
CU_ASSERT (os_atomic_ld64 (&uint64) == _osuint64);
#endif
/* Test uintptr LD-ST */
printf ("Starting os_atomics_load_store_003\n");
CU_ASSERT (os_atomic_ldptr (&uintptr) == 5);
os_atomic_stptr (&uintptr, _osaddress);
CU_ASSERT (os_atomic_ldptr (&uintptr) == _osaddress);
/* Test uintvoidp LD-ST */
printf ("Starting os_atomics_load_store_004\n");
CU_ASSERT (os_atomic_ldvoidp (&voidp) == (uintptr_t*)5);
os_atomic_stvoidp (&voidp, _osvoidp);
CU_ASSERT (os_atomic_ldvoidp (&voidp) == (uintptr_t*)_osvoidp);
printf ("Ending atomics_load_store\n");
}
CUnit_Test(os_atomics, compare_and_swap)
{
/* Compare and Swap
* if (ptr == expected) { ptr = newval; }
*/
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(0);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(0);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(0);
volatile os_atomic_voidp_t uintvoidp = OS_ATOMIC_VOIDP_INIT((uintptr_t)0);
_osuint32 = 1;
_osuint64 = 1;
_osaddress = 1;
_osvoidp = (uintptr_t *)1;
uint32_t expected = 0, newval = 5;
uintptr_t addr_expected = 0, addr_newval = 5;
void *void_expected = (uintptr_t*)0;
void *void_newval = (uintptr_t*)5;
int ret = 0;
/* Test os_atomic_cas32 */
printf ("Starting os_atomics_compare_and_swap_001\n");
ret = os_atomic_cas32 (&uint32, expected, newval);
CU_ASSERT (os_atomic_ld32 (&uint32) == newval && ret == 1);
os_atomic_st32 (&uint32, _osuint32);
ret = os_atomic_cas32 (&uint32, expected, newval);
CU_ASSERT (os_atomic_ld32 (&uint32) != newval && ret == 0);
/* Test os_atomic_cas64 */
printf ("Starting os_atomics_compare_and_swap_002\n");
#if OS_ATOMIC64_SUPPORT
ret = os_atomic_cas64 (&uint64, expected, newval);
CU_ASSERT (os_atomic_ld64 (&uint64) == newval && ret == 1);
os_atomic_st64 (&uint64, _osuint64);
ret = os_atomic_cas64 (&uint64, expected, newval);
CU_ASSERT (os_atomic_ld64 (&uint64) != newval && ret == 0);
#endif
/* Test os_atomic_casptr */
printf ("Starting os_atomics_compare_and_swap_003\n");
ret = os_atomic_casptr (&uintptr, addr_expected, addr_newval);
CU_ASSERT (os_atomic_ldptr (&uintptr) == addr_newval && ret == 1);
os_atomic_stptr (&uintptr, _osaddress);
ret = os_atomic_casptr (&uintptr, addr_expected, addr_newval);
CU_ASSERT (os_atomic_ldptr (&uintptr) != addr_newval && ret == 0);
/* Test os_atomic_casvoidp */
printf ("Starting os_atomics_compare_and_swap_003\n");
ret = os_atomic_casvoidp (&uintvoidp, void_expected, void_newval);
CU_ASSERT (os_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)void_newval && ret == 1);
os_atomic_stvoidp (&uintvoidp, _osvoidp);
ret = os_atomic_casvoidp (&uintvoidp, void_expected, void_newval);
CU_ASSERT (os_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)1 && ret == 0);
printf ("Ending atomics_compare_and_swap\n");
}
CUnit_Test(os_atomics, increment)
{
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(0);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(0);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(0);
_osuint32 = 0;
_osuint64 = 0;
_osaddress = 0;
_osvoidp = (uintptr_t *)0;
/* Test os_inc32 */
printf ("Starting os_atomics_increment_001\n");
os_atomic_inc32 (&uint32);
CU_ASSERT (os_atomic_ld32 (&uint32) == 1);
/* Test os_inc64 */
printf ("Starting os_atomics_increment_002\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_inc64 (&uint64);
CU_ASSERT (os_atomic_ld64 (&uint64) == 1);
#endif
/* Test os_incptr */
printf ("Starting os_atomics_increment_003\n");
os_atomic_incptr (&uintptr);
CU_ASSERT (os_atomic_ldptr (&uintptr) == 1);
/* Test os_atomic_inc32_nv */
printf ("Starting os_atomics_increment_004\n");
os_atomic_st32 (&uint32, _osuint32);
CU_ASSERT (os_atomic_inc32_nv (&uint32) == 1);
/* Test os_atomic_inc64_nv */
printf ("Starting os_atomics_increment_005\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_st64 (&uint64, _osuint64);
CU_ASSERT (os_atomic_inc64_nv (&uint64) == 1);
#endif
/* Test os_atomic_incptr_nv */
printf ("Starting os_atomics_increment_006\n");
os_atomic_stptr (&uintptr, _osaddress);
CU_ASSERT (os_atomic_incptr_nv(&uintptr) == 1);
printf ("Ending atomics_increment\n");
}
CUnit_Test(os_atomics, decrement)
{
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(1);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(1);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(1);
_osuint32 = 1;
_osuint64 = 1;
_osaddress = 1;
_osvoidp = (uintptr_t *)1;
/* Test os_atomic_dec32 */
printf ("Starting os_atomics_decrement_001\n");
os_atomic_dec32 (&uint32);
CU_ASSERT (os_atomic_ld32 (&uint32) == 0);
/* Test os_atomic_dec64 */
printf ("Starting os_atomics_decrement_002\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_dec64 (&uint64);
CU_ASSERT (os_atomic_ld64 (&uint64) == 0);
#endif
/* Test os_atomic_decptr */
printf ("Starting os_atomics_decrement_003\n");
os_atomic_decptr (&uintptr);
CU_ASSERT (os_atomic_ldptr (&uintptr) == 0);
/* Test os_atomic_dec32_nv */
printf ("Starting os_atomics_decrement_004\n");
os_atomic_st32 (&uint32, _osuint32);
CU_ASSERT (os_atomic_dec32_nv (&uint32) == 0);
/* Test os_atomic_dec64_nv */
printf ("Starting os_atomics_decrement_005\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_st64 (&uint64, _osuint64);
CU_ASSERT (os_atomic_dec64_nv (&uint64) == 0);
#endif
/* Test os_atomic_decptr_nv */
printf ("Starting os_atomics_decrement_006\n");
os_atomic_stptr (&uintptr, _osaddress);
CU_ASSERT (os_atomic_decptr_nv(&uintptr) == 0);
printf ("Ending atomics_decrement\n");
}
CUnit_Test(os_atomics, add)
{
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(1);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(1);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(1);
volatile os_atomic_voidp_t uintvoidp = OS_ATOMIC_VOIDP_INIT((uintptr_t)1);
_osuint32 = 2;
_osuint64 = 2;
_osaddress = 2;
_ptrdiff = 2;
/* Test os_atomic_add32 */
printf ("Starting os_atomics_add_001\n");
os_atomic_add32 (&uint32, _osuint32);
CU_ASSERT (os_atomic_ld32 (&uint32) == 3);
/* Test os_atomic_add64 */
printf ("Starting os_atomics_add_002\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_add64 (&uint64, _osuint64);
CU_ASSERT (os_atomic_ld64 (&uint64) == 3);
#endif
/* Test os_atomic_addptr */
printf ("Starting os_atomics_add_003\n");
os_atomic_addptr (&uintptr, _osaddress);
CU_ASSERT (os_atomic_ldptr (&uintptr) == 3);
/* Test os_atomic_addvoidp */
printf ("Starting os_atomics_add_004\n");
os_atomic_addvoidp (&uintvoidp, _ptrdiff);
CU_ASSERT (os_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)3);
/* Test os_atomic_add32_nv */
printf ("Starting os_atomics_add_005\n");
os_atomic_st32 (&uint32, 1);
CU_ASSERT (os_atomic_add32_nv (&uint32, _osuint32) == 3);
/* Test os_atomic_add64_nv */
printf ("Starting os_atomics_add_006\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_st64 (&uint64, 1);
CU_ASSERT (os_atomic_add64_nv (&uint64, _osuint64) == 3);
#endif
/* Test os_atomic_addptr_nv */
printf ("Starting os_atomics_add_007\n");
os_atomic_stptr (&uintptr, 1);
CU_ASSERT (os_atomic_addptr_nv (&uintptr, _osaddress) == 3);
/* Test os_atomic_addvoidp_nv */
printf ("Starting os_atomics_add_008\n");
os_atomic_stvoidp (&uintvoidp, (uintptr_t*)1);
CU_ASSERT (os_atomic_addvoidp_nv (&uintvoidp, _ptrdiff) == (uintptr_t*)3);
printf ("Ending atomics_add\n");
}
CUnit_Test(os_atomics, subtract)
{
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(5);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(5);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(5);
volatile os_atomic_voidp_t uintvoidp = OS_ATOMIC_VOIDP_INIT((uintptr_t)5);
_osuint32 = 2;
_osuint64 = 2;
_osaddress = 2;
_ptrdiff = 2;
/* Test os_atomic_sub32 */
printf ("Starting os_atomics_subtract_001\n");
os_atomic_sub32 (&uint32, _osuint32);
CU_ASSERT (os_atomic_ld32 (&uint32) == 3);
/* Test os_atomic_sub64 */
printf ("Starting os_atomics_subtract_002\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_sub64 (&uint64, _osuint64);
CU_ASSERT (os_atomic_ld64 (&uint64) == 3);
#endif
/* Test os_atomic_subptr */
printf ("Starting os_atomics_subtract_003\n");
os_atomic_subptr (&uintptr, _osaddress);
CU_ASSERT (os_atomic_ldptr (&uintptr) == 3);
/* Test os_atomic_subvoidp */
printf ("Starting os_atomics_subtract_004\n");
os_atomic_subvoidp (&uintvoidp, _ptrdiff);
CU_ASSERT (os_atomic_ldvoidp (&uintvoidp) == (uintptr_t*)3);
/* Test os_atomic_sub32_nv */
printf ("Starting os_atomics_subtract_005\n");
os_atomic_st32 (&uint32, 5);
CU_ASSERT (os_atomic_sub32_nv (&uint32, _osuint32) == 3);
/* Test os_atomic_sub64_nv */
printf ("Starting os_atomics_subtract_006\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_st64 (&uint64, 5);
CU_ASSERT (os_atomic_sub64_nv (&uint64, _osuint64) == 3);
#endif
/* Test os_atomic_subptr_nv */
printf ("Starting os_atomics_subtract_007\n");
os_atomic_stptr (&uintptr, 5);
CU_ASSERT (os_atomic_subptr_nv (&uintptr, _osaddress) == 3);
/* Test os_atomic_subvoidp_nv */
printf ("Starting os_atomics_subtract_008\n");
os_atomic_stvoidp (&uintvoidp, (uintptr_t*)5);
CU_ASSERT (os_atomic_subvoidp_nv (&uintvoidp, _ptrdiff) == (void *)3);
printf ("Ending atomics_subtract\n");
}
CUnit_Test(os_atomics, and)
{
/* AND Operation:
150 010010110
500 111110100
148 010010100 */
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(150);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(150);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(150);
_osuint32 = 500;
_osuint64 = 500;
_osaddress = 500;
/* Test os_atomic_and32 */
printf ("Starting os_atomics_and_001\n");
os_atomic_and32 (&uint32, _osuint32);
CU_ASSERT (os_atomic_ld32 (&uint32) == 148);
/* Test os_atomic_and64 */
printf ("Starting os_atomics_and_002\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_and64 (&uint64, _osuint64);
CU_ASSERT (os_atomic_ld64 (&uint64) == 148);
#endif
/* Test os_atomic_andptr */
printf ("Starting os_atomics_and_003\n");
os_atomic_andptr (&uintptr, _osaddress);
CU_ASSERT (os_atomic_ldptr (&uintptr) == 148);
/* Test os_atomic_and32_ov */
printf ("Starting os_atomics_and_004\n");
CU_ASSERT (os_atomic_and32_ov (&uint32, _osuint32) == 148);
/* Test os_atomic_and64_ov */
printf ("Starting os_atomics_and_005\n");
#if OS_ATOMIC64_SUPPORT
CU_ASSERT (os_atomic_and64_ov (&uint64, _osuint64) == 148);
#endif
/* Test os_atomic_andptr_ov */
printf ("Starting os_atomics_and_006\n");
CU_ASSERT (os_atomic_andptr_ov (&uintptr, _osaddress) == 148);
/* Test os_atomic_and32_nv */
printf ("Starting os_atomics_and_007\n");
CU_ASSERT (os_atomic_and32_nv (&uint32, _osuint32) == 148);
/* Test os_atomic_and64_nv */
printf ("Starting os_atomics_and_008\n");
#if OS_ATOMIC64_SUPPORT
CU_ASSERT (os_atomic_and64_nv (&uint64, _osuint64) == 148);
#endif
/* Test os_atomic_andptr_nv */
printf ("Starting os_atomics_and_009\n");
CU_ASSERT (os_atomic_andptr_nv (&uintptr, _osaddress) == 148);
printf ("Ending atomics_and\n");
}
CUnit_Test(os_atomics, or)
{
/* OR Operation:
150 010010110
500 111110100
502 111110110 */
volatile os_atomic_uint32_t uint32 = OS_ATOMIC_UINT32_INIT(150);
#if OS_ATOMIC64_SUPPORT
volatile os_atomic_uint64_t uint64 = OS_ATOMIC_UINT64_INIT(150);
#endif
volatile os_atomic_uintptr_t uintptr = OS_ATOMIC_UINTPTR_INIT(150);
_osuint32 = 500;
_osuint64 = 500;
_osaddress = 500;
/* Test os_atomic_or32 */
printf ("Starting os_atomics_or_001\n");
os_atomic_or32 (&uint32, _osuint32);
CU_ASSERT (os_atomic_ld32 (&uint32) == 502);
/* Test os_atomic_or64 */
printf ("Starting os_atomics_or_002\n");
#if OS_ATOMIC64_SUPPORT
os_atomic_or64 (&uint64, _osuint64);
CU_ASSERT (os_atomic_ld64 (&uint64) == 502);
#endif
/* Test os_atomic_orptr */
printf ("Starting os_atomics_or_003\n");
os_atomic_orptr (&uintptr, _osaddress);
CU_ASSERT (os_atomic_ldptr (&uintptr) == 502);
/* Test os_atomic_or32_ov */
printf ("Starting os_atomics_or_004\n");
CU_ASSERT (os_atomic_or32_ov (&uint32, _osuint32) == 502);
/* Test os_atomic_or64_ov */
printf ("Starting os_atomics_or_005\n");
#if OS_ATOMIC64_SUPPORT
CU_ASSERT (os_atomic_or64_ov (&uint64, _osuint64) == 502);
#endif
/* Test os_atomic_orptr_ov */
printf ("Starting os_atomics_or_006\n");
CU_ASSERT (os_atomic_orptr_ov (&uintptr, _osaddress) == 502);
/* Test os_atomic_or32_nv */
printf ("Starting os_atomics_or_007\n");
CU_ASSERT (os_atomic_or32_nv (&uint32, _osuint32) == 502);
/* Test os_atomic_or64_nv */
printf ("Starting os_atomics_or_008\n");
#if OS_ATOMIC64_SUPPORT
CU_ASSERT (os_atomic_or64_nv (&uint64, _osuint64) == 502);
#endif
/* Test os_atomic_orptr_nv */
printf ("Starting os_atomics_or_009\n");
CU_ASSERT (os_atomic_orptr_nv (&uintptr, _osaddress) == 502);
printf ("Ending atomics_or\n");
}

47
src/os/tests/error_no.c Normal file
View file

@ -0,0 +1,47 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
CUnit_Suite_Initialize(os_errno)
{
int result = 0;
os_osInit();
printf("Run os_errno_Initialize\n");
return result;
}
CUnit_Suite_Cleanup(os_errno)
{
int result = 0;
os_osExit();
printf("Run os_errno_Cleanup\n");
return result;
}
CUnit_Test(os_errno, get_and_set)
{
printf ("Starting os_errno_get_and_set_001\n");
os_setErrno (0);
CU_ASSERT (os_getErrno () == 0);
printf ("Starting os_errno_get_and_set_002\n");
os_setErrno (0);
/* Call strtol with an invalid format on purpose. */
(void)strtol ("1000000000000000000000000000000000000000000000000", NULL, 10);
CU_ASSERT (os_getErrno () != 0);
printf ("Ending tc_os_errno\n");
}

197
src/os/tests/heap.c Normal file
View file

@ -0,0 +1,197 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
CUnit_Suite_Initialize(os_heap)
{
int result = 0;
os_osInit();
printf("Run os_heap_Initialize\n");
return result;
}
CUnit_Suite_Cleanup(os_heap)
{
int result = 0;
os_osExit();
printf("Run os_heap_Cleanup\n");
return result;
}
static const size_t allocsizes[] = {0, 1, 2, 3, 4, 5, 10, 20, 257, 1024};
static const size_t nof_allocsizes = sizeof allocsizes / sizeof *allocsizes;
CUnit_Test(os_heap, os_malloc)
{
for(int i = 0; i < nof_allocsizes; i++) {
for(int j = 0; j < nof_allocsizes; j++) {
size_t s = allocsizes[i] * allocsizes[j]; /* Allocates up to 1MB */
void *ptr = os_malloc(s);
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL); /* os_malloc is supposed to abort on failure */
memset(ptr, 0, s); /* This potentially segfaults if the actual allocated block is too small */
os_free(ptr);
}
}
CU_PASS("os_malloc");
}
CUnit_Test(os_heap, os_malloc_0)
{
for(int i = 0; i < nof_allocsizes; i++) {
for(int j = 0; j < nof_allocsizes; j++) {
size_t s = allocsizes[i] * allocsizes[j]; /* Allocates up to 1MB */
char *ptr = os_malloc_0(s);
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL); /* os_malloc_0 is supposed to abort on failure */
if(s) {
CU_ASSERT (ptr[0] == 0 && !memcmp(ptr, ptr + 1, s - 1)); /* malloc_0 should memset properly */
}
os_free(ptr);
}
}
CU_PASS("os_malloc_0");
}
CUnit_Test(os_heap, os_calloc)
{
for(int i = 0; i < nof_allocsizes; i++) {
for(int j = 0; j < nof_allocsizes; j++) {
char *ptr = os_calloc(allocsizes[i], allocsizes[j]);
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL); /* os_calloc is supposed to abort on failure */
if(allocsizes[i] * allocsizes[j]) {
CU_ASSERT (ptr[0] == 0 && !memcmp(ptr, ptr + 1, (allocsizes[i] * allocsizes[j]) - 1)); /* os_calloc should memset properly */
}
os_free(ptr);
}
}
CU_PASS("os_calloc");
}
CUnit_Test(os_heap, os_realloc)
{
char *ptr = NULL;
size_t unchanged, s, prevs = 0;
for(int i = 0; i < nof_allocsizes; i++) {
for(int j = 0; j < nof_allocsizes; j++) {
s = allocsizes[i] * allocsizes[j]; /* Allocates up to 1MB */
printf("os_realloc(%p) %zu -> %zu\n", ptr, prevs, s);
ptr = os_realloc(ptr, s);
CU_ASSERT_PTR_NOT_EQUAL(ptr, NULL); /* os_realloc is supposed to abort on failure */
unchanged = (prevs < s) ? prevs : s;
if(unchanged) {
CU_ASSERT (ptr[0] == 1 && !memcmp(ptr, ptr + 1, unchanged - 1)); /* os_realloc shouldn't change memory */
}
memset(ptr, 1, s); /* This potentially segfaults if the actual allocated block is too small */
prevs = s;
}
}
os_free(ptr);
CU_PASS("os_realloc");
}
static const size_t allocsizes_s[] = {0, 1, 2, 3, 4, 5, 10, 20, 257, 1024, 8192};
static const size_t nof_allocsizes_s = sizeof allocsizes_s / sizeof *allocsizes_s;
CUnit_Test(os_heap, os_malloc_s)
{
for(int i = 0; i < nof_allocsizes_s; i++) {
for(int j = 0; j < nof_allocsizes_s; j++) {
size_t s = allocsizes_s[i] * allocsizes_s[j]; /* Allocates up to 8MB */
void *ptr = os_malloc_s(s); /* If s == 0, os_malloc_s should still return a pointer */
if(ptr) {
memset(ptr, 0, s); /* This potentially segfaults if the actual allocated block is too small */
} else if (s <= 16) {
/* Failure to allocate can't be considered a test fault really,
* except that a malloc(<=16) would fail is unlikely. */
CU_FAIL("os_malloc_0_s(<=16) returned NULL");
}
os_free(ptr);
}
}
CU_PASS("os_malloc_s");
}
CUnit_Test(os_heap, os_malloc_0_s)
{
for(int i = 0; i < nof_allocsizes_s; i++) {
for(int j = 0; j < nof_allocsizes_s; j++) {
size_t s = allocsizes_s[i] * allocsizes_s[j]; /* Allocates up to 8MB */
char *ptr = os_malloc_0_s(s); /* If s == 0, os_malloc_0_s should still return a pointer */
if(ptr) {
if(s) {
CU_ASSERT (ptr[0] == 0 && !memcmp(ptr, ptr + 1, s - 1)); /* malloc_0_s should memset properly */
}
} else if (s <= 16) {
/* Failure to allocate can't be considered a test fault really,
* except that a malloc(<=16) would fail is unlikely. */
CU_FAIL("os_malloc_0_s(<=16) returned NULL");
}
os_free(ptr);
}
}
CU_PASS("os_malloc_0_s");
}
CUnit_Test(os_heap, os_calloc_s)
{
for(int i = 0; i < nof_allocsizes_s; i++) {
for(int j = 0; j < nof_allocsizes_s; j++) {
size_t s = allocsizes_s[i] * allocsizes_s[j];
char *ptr = os_calloc_s(allocsizes_s[i], allocsizes_s[j]); /* If either one is 0, os_calloc_s should still return a pointer */
if(ptr) {
if(s) {
CU_ASSERT (ptr[0] == 0 && !memcmp(ptr, ptr + 1, s - 1)); /* malloc_0_s should memset properly */
}
} else if (s <= 16) {
/* Failure to allocate can't be considered a test fault really,
* except that a calloc(<=16) would fail is unlikely. */
CU_FAIL("os_calloc_s(<=16) returned NULL");
}
os_free(ptr);
}
}
CU_PASS("os_calloc_s");
}
CUnit_Test(os_heap, os_realloc_s)
{
char *newptr, *ptr = NULL;
size_t unchanged, s, prevs = 0;
for(int i = 0; i < nof_allocsizes_s; i++) {
for(int j = 0; j < nof_allocsizes_s; j++) {
s = allocsizes_s[i] * allocsizes_s[j]; /* Allocates up to 8MB */
newptr = os_realloc_s(ptr, s);
printf("%p = os_realloc_s(%p) %zu -> %zu\n", newptr, ptr, prevs, s);
if (s <= 16) {
/* Failure to allocate can't be considered a test fault really,
* except that a os_realloc_s(0 < s <=16) would fail is unlikely. */
CU_ASSERT_PTR_NOT_EQUAL(newptr, NULL);
}
if(newptr){
unchanged = (prevs < s) ? prevs : s;
if(unchanged) {
CU_ASSERT (newptr[0] == 1 && !memcmp(newptr, newptr + 1, unchanged - 1)); /* os_realloc_s shouldn't change memory */
}
memset(newptr, 1, s); /* This potentially segfaults if the actual allocated block is too small */
}
prevs = s;
ptr = newptr;
}
}
os_free(ptr);
CU_PASS("os_realloc_s");
}

239
src/os/tests/iter.c Executable file
View file

@ -0,0 +1,239 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
#include "assert.h"
static int32_t one = 1;
static int32_t two = 2;
static int32_t three = 3;
static int32_t four = 4;
static int32_t five = 5;
CUnit_Test(os_iter, create)
{
os_iter *iter;
iter = os_iterNew();
CU_ASSERT_PTR_NOT_NULL_FATAL(iter);
CU_ASSERT_EQUAL(os_iterLength(iter), 0);
CU_ASSERT_PTR_NULL(os_iterObject(iter, 0));
CU_ASSERT_PTR_NULL(os_iterTake(iter, 0));
os_iterFree(iter, NULL);
}
CUnit_Test(os_iter, prepend)
{
os_iter *iter;
int32_t idx;
iter = os_iterNew();
CU_ASSERT_PTR_NOT_NULL_FATAL(iter);
idx = os_iterInsert(iter, &one, 0);
CU_ASSERT_EQUAL(idx, 0);
idx = os_iterInsert(iter, &two, 0);
CU_ASSERT_EQUAL(idx, 0);
idx = os_iterInsert(iter, &three, 0);
CU_ASSERT_EQUAL(idx, 0);
CU_ASSERT_EQUAL(os_iterLength(iter), 3);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 0), 3);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 1), 2);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 2), 1);
os_iterFree(iter, NULL);
}
CUnit_Test(os_iter, append)
{
os_iter *iter;
int32_t idx;
iter = os_iterNew();
CU_ASSERT_PTR_NOT_NULL_FATAL(iter);
idx = os_iterInsert(iter, &one, OS_ITER_LENGTH);
CU_ASSERT_EQUAL(idx, 0);
idx = os_iterInsert(iter, &two, OS_ITER_LENGTH);
CU_ASSERT_EQUAL(idx, 1);
idx = os_iterInsert(iter, &three, OS_ITER_LENGTH);
CU_ASSERT_EQUAL(idx, 2);
CU_ASSERT_EQUAL(os_iterLength(iter), 3);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 0), 1);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 1), 2);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 2), 3);
os_iterFree(iter, NULL);
}
CUnit_Test(os_iter, insert)
{
os_iter *iter;
int32_t idx;
iter = os_iterNew();
CU_ASSERT_PTR_NOT_NULL_FATAL(iter);
idx = os_iterInsert(iter, &one, 0);
CU_ASSERT_EQUAL(idx, 0);
idx = os_iterInsert(iter, &three, OS_ITER_LENGTH);
CU_ASSERT_EQUAL(idx, 1);
idx = os_iterInsert(iter, &two, idx);
CU_ASSERT_EQUAL(idx, 1);
idx = os_iterInsert(iter, &four, -2);
CU_ASSERT_EQUAL(idx, 1);
idx = os_iterInsert(iter, &five, -2);
CU_ASSERT_EQUAL(idx, 2);
CU_ASSERT_EQUAL(os_iterLength(iter), 5);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 0), 1);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 1), 4);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 2), 5);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 3), 2);
CU_ASSERT_EQUAL(*(int32_t *)os_iterObject(iter, 4), 3);
os_iterFree(iter, NULL);
}
static void
iter_free_callback(
void *ptr)
{
(*(int32_t *)ptr)++;
}
CUnit_Test(os_iter, free)
{
os_iter *iter;
int32_t cnt = 0;
iter = os_iterNew();
CU_ASSERT_PTR_NOT_NULL_FATAL(iter);
(void)os_iterInsert(iter, &cnt, OS_ITER_LENGTH);
(void)os_iterInsert(iter, &cnt, OS_ITER_LENGTH);
(void)os_iterInsert(iter, &cnt, OS_ITER_LENGTH);
os_iterFree(iter, &iter_free_callback);
CU_ASSERT_EQUAL(cnt, 3);
}
static void
iter_walk_callback(
void *ptr, void *arg)
{
(*(int32_t *)ptr)++;
(*(int32_t *)arg)++;
}
CUnit_Test(os_iter, walk)
{
os_iter *iter;
int32_t cnt = 0;
iter = os_iterNew();
CU_ASSERT_PTR_NOT_NULL_FATAL(iter);
(void)os_iterInsert(iter, &cnt, OS_ITER_LENGTH);
(void)os_iterInsert(iter, &cnt, OS_ITER_LENGTH);
(void)os_iterInsert(iter, &cnt, OS_ITER_LENGTH);
os_iterWalk(iter, &iter_walk_callback, &cnt);
CU_ASSERT_EQUAL(cnt, 6);
os_iterFree(iter, &iter_free_callback);
CU_ASSERT_EQUAL(cnt, 9);
}
static os_iter *
iter_new(
void)
{
os_iter *iter;
int32_t idx;
iter = os_iterNew();
CU_ASSERT_PTR_NOT_NULL_FATAL(iter);
idx = os_iterInsert(iter, &one, OS_ITER_LENGTH);
CU_ASSERT_EQUAL_FATAL(idx, 0);
idx = os_iterInsert(iter, &two, OS_ITER_LENGTH);
CU_ASSERT_EQUAL_FATAL(idx, 1);
idx = os_iterInsert(iter, &three, OS_ITER_LENGTH);
CU_ASSERT_EQUAL_FATAL(idx, 2);
idx = os_iterInsert(iter, &four, OS_ITER_LENGTH);
CU_ASSERT_EQUAL_FATAL(idx, 3);
idx = os_iterInsert(iter, &five, OS_ITER_LENGTH);
CU_ASSERT_EQUAL_FATAL(idx, 4);
CU_ASSERT_EQUAL_FATAL(os_iterLength(iter), 5);
return iter;
}
CUnit_Test(os_iter, object_indices)
{
os_iter *iter;
int32_t *num;
iter = iter_new();
/* index out of range on purpose */
OS_WARNING_MSVC_OFF(28020);
num = os_iterObject(iter, OS_ITER_LENGTH);
OS_WARNING_MSVC_ON(28020);
CU_ASSERT_PTR_NULL(num);
num = os_iterObject(iter, os_iterLength(iter));
CU_ASSERT_PTR_NULL(num);
num = os_iterObject(iter, -6);
CU_ASSERT_PTR_NULL(num);
num = os_iterObject(iter, 0);
CU_ASSERT_PTR_EQUAL(num, &one);
num = os_iterObject(iter, -5);
CU_ASSERT_PTR_EQUAL(num, &one);
num = os_iterObject(iter, os_iterLength(iter) - 1);
CU_ASSERT_PTR_EQUAL(num, &five);
num = os_iterObject(iter, -1);
CU_ASSERT_PTR_EQUAL(num, &five);
num = os_iterObject(iter, 2);
CU_ASSERT_PTR_EQUAL(num, &three);
num = os_iterObject(iter, -3);
CU_ASSERT_PTR_EQUAL(num, &three);
os_iterFree(iter, NULL);
}
CUnit_Test(os_iter, take_indices)
{
os_iter *iter;
int32_t *num, cnt = 0;
iter = iter_new();
/* index out of range on purpose */
OS_WARNING_MSVC_OFF(28020);
num = os_iterTake(iter, OS_ITER_LENGTH);
OS_WARNING_MSVC_ON(28020);
CU_ASSERT_PTR_NULL(num);
num = os_iterTake(iter, os_iterLength(iter));
CU_ASSERT_PTR_NULL(num);
num = os_iterTake(iter, -6);
CU_ASSERT_PTR_NULL(num);
num = os_iterTake(iter, -5);
CU_ASSERT_PTR_EQUAL(num, &one);
CU_ASSERT_EQUAL(os_iterLength(iter), 4);
num = os_iterTake(iter, -3);
CU_ASSERT_PTR_EQUAL(num, &three);
CU_ASSERT_EQUAL(os_iterLength(iter), 3);
num = os_iterTake(iter, -1);
CU_ASSERT_PTR_EQUAL(num, &five);
CU_ASSERT_EQUAL(os_iterLength(iter), 2);
num = os_iterTake(iter, 1);
CU_ASSERT_PTR_EQUAL(num, &four);
CU_ASSERT_EQUAL(os_iterLength(iter), 1);
num = os_iterTake(iter, 1);
CU_ASSERT_PTR_NULL(num);
num = os_iterTake(iter, -2);
CU_ASSERT_PTR_NULL(num);
num = os_iterTake(iter, -1);
CU_ASSERT_PTR_EQUAL(num, &two);
CU_ASSERT_EQUAL(os_iterLength(iter), 0);
os_iterWalk(iter, &iter_walk_callback, &cnt);
CU_ASSERT_EQUAL(cnt, 0);
os_iterFree(iter, NULL);
}

369
src/os/tests/mutex.c Normal file
View file

@ -0,0 +1,369 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
#ifdef __VXWORKS__
# ifdef _WRS_KERNEL
# define FORCE_SCHEDULING() taskDelay(1)
# else
# define FORCE_SCHEDULING() sched_yield()
# endif
#else
# define FORCE_SCHEDULING()
#endif
#define BUSYLOOP (100000)
#define MAX_LOOPS (20)
typedef struct {
os_mutex global_mutex;
os_threadId global_data;
int nolock_corrupt_count;
int nolock_loop_count;
int lock_corrupt_count;
int lock_loop_count;
int trylock_corrupt_count;
int trylock_loop_count;
int trylock_busy_count;
int stop;
} shared_data;
os_threadAttr mutex_os_threadAttr;
os_threadId mutex_os_threadId[4];
os_time delay1 = { 5, 0 };
os_time pdelay = { 1, 0 };
os_procId mutex_os_procId;
os_procId mutex_os_procId1;
os_procId mutex_os_procId2;
char buffer[512];
int supported_resultBusy;
int loop;
static shared_data *sd;
char filePath[255];
uint32_t concurrent_lock_thread (_In_opt_ void *arg)
{
int j;
int loopc = 0;
int printed = 0;
while (!sd->stop)
{
if (arg) os_mutexLock (&sd->global_mutex);
sd->global_data = os_threadIdSelf();
FORCE_SCHEDULING();
for (j = 0; j < BUSYLOOP; j++);
if (os_threadIdToInteger(sd->global_data) !=
os_threadIdToInteger(os_threadIdSelf()))
{
if (arg)
{
sd->lock_corrupt_count++;
}
else
{
sd->nolock_corrupt_count++;
}
if (!printed) {
printed++;
}
}
if (arg)
{
sd->lock_loop_count++;
os_mutexUnlock (&sd->global_mutex);
}
else
{
sd->nolock_loop_count++;
}
FORCE_SCHEDULING();
for (j = 0; j < BUSYLOOP; j++);
loopc++;
}
return 0;
}
uint32_t concurrent_trylock_thread (_In_opt_ void *arg)
{
int j;
int loopc = 0;
int printed = 0;
os_result result;
while (!sd->stop)
{
if (arg)
{
while ((result = os_mutexTryLock (&sd->global_mutex))
!= os_resultSuccess)
{
if (result == os_resultBusy)
{
sd->trylock_busy_count++;
}
FORCE_SCHEDULING();
}
}
sd->global_data = os_threadIdSelf();
FORCE_SCHEDULING();
for (j = 0; j < BUSYLOOP; j++);
if (os_threadIdToInteger(sd->global_data) !=
os_threadIdToInteger(os_threadIdSelf()))
{
if (arg)
{
sd->trylock_corrupt_count++;
}
else
{
sd->nolock_corrupt_count++;
}
if (!printed) {
printed++;
}
}
if (arg)
{
sd->trylock_loop_count++;
os_mutexUnlock (&sd->global_mutex);
}
else
{
sd->nolock_loop_count++;
}
FORCE_SCHEDULING();
for (j = 0; j < BUSYLOOP; j++);
loopc++;
}
return 0;
}
CUnit_Suite_Initialize(os_mutex)
{
printf ( "Run os_mutex_Initialize\n" );
os_osInit();
return 0;
}
CUnit_Suite_Cleanup(os_mutex)
{
printf("Run os_mutex_Cleanup\n");
os_osExit();
return 0;
}
/* This test only checks a single-threaded use-case; just API availability.*/
CUnit_Test(os_mutex, basic)
{
os_mutex m;
os_result r;
printf("Starting os_mutex_basic\n");
os_mutexInit(&m);
os_mutexLock(&m);
os_mutexUnlock(&m);
r = os_mutexLock_s(&m);
CU_ASSERT_EQUAL(r, os_resultSuccess); /* Failure can't be forced */
os_mutexUnlock(&m);
os_mutexDestroy(&m);
printf("Ending os_mutex_basic\n");
}
#define RUNTIME_SEC (4)
#define NUM_THREADS (8)
#define OS_STRESS_STOP (0)
#define OS_STRESS_GO (1)
#define THREAD_NAME_LEN (8)
struct os_mutex_stress {
os_threadId tid;
os_mutex m;
os_atomic_uint32_t * flag;
char name[THREAD_NAME_LEN];
};
static uint32_t
os_mutex_init_thr(
void *args)
{
struct os_mutex_stress *state = (struct os_mutex_stress *)args;
os_result r;
uint32_t iterations = 0;
do {
os_mutexInit(&state->m);
r = os_mutexLock_s(&state->m); /* Use the mutex to check that all is OK. */
CU_ASSERT_EQUAL(r, os_resultSuccess); /* Failure can't be forced. */
os_mutexUnlock(&state->m);
os_mutexDestroy(&state->m);
iterations++;
} while ( os_atomic_ld32(state->flag) != OS_STRESS_STOP && r == os_resultSuccess);
printf("%s <%"PRIxMAX">: Performed %u iterations. Stopping now.\n", state->name, os_threadIdToInteger(os_threadIdSelf()), iterations);
return r != os_resultSuccess; /* Return true on faulure */
}
CUnit_Test(os_mutex, init_stress)
{
struct os_mutex_stress threads[NUM_THREADS];
os_threadAttr tattr;
unsigned i;
os_atomic_uint32_t flag = OS_ATOMIC_UINT32_INIT(OS_STRESS_GO);
os_time runtime = { .tv_sec = RUNTIME_SEC, .tv_nsec = 0 };
printf("Starting os_mutex_init_stress\n");
os_threadAttrInit(&tattr);
for ( i = 0; i < NUM_THREADS; i++ ) {
(void) snprintf(&threads[i].name[0], THREAD_NAME_LEN, "thr%u", i);
threads[i].flag = &flag;
os_threadCreate(&threads[i].tid, threads[i].name, &tattr, &os_mutex_init_thr, &threads[i]);
printf("main <%"PRIxMAX">: Started thread '%s' with thread-id %" PRIxMAX "\n", os_threadIdToInteger(os_threadIdSelf()), threads[i].name, os_threadIdToInteger(threads[i].tid));
}
printf("main <%"PRIxMAX">: Test will run for ~%ds with %d threads\n", os_threadIdToInteger(os_threadIdSelf()), RUNTIME_SEC, NUM_THREADS);
os_nanoSleep(runtime);
os_atomic_st32(&flag, OS_STRESS_STOP);
for ( ; i != 0; i-- ) {
uint32_t thread_failed;
os_threadWaitExit(threads[i - 1].tid, &thread_failed);
printf("main <%"PRIxMAX">: Thread %s <%" PRIxMAX "> stopped with result %s.\n", os_threadIdToInteger(os_threadIdSelf()), threads[i - 1].name, os_threadIdToInteger(threads[i - 1].tid), thread_failed ? "FAILED" : "PASS");
CU_ASSERT_FALSE(thread_failed);
}
printf("Ending os_mutex_init_stress\n");
}
CUnit_Test(os_mutex, lock, false)
{
/* Test critical section access with locking and PRIVATE scope */
printf ("Starting tc_os_mutex_lock_001\n");
os_threadAttrInit (&mutex_os_threadAttr);
FORCE_SCHEDULING();
delay1.tv_sec = 3;
printf ("Testing for %d.%9.9d seconds without lock\n", delay1.tv_sec, delay1.tv_nsec);
sd->stop = 0;
sd->nolock_corrupt_count = 0;
sd->nolock_loop_count = 0;
sd->lock_corrupt_count = 0;
sd->lock_loop_count = 0;
sd->trylock_corrupt_count = 0;
sd->trylock_loop_count = 0;
sd->trylock_busy_count = 0;
os_threadCreate (&mutex_os_threadId[0], "thr0", &mutex_os_threadAttr, &concurrent_lock_thread, NULL);
os_threadCreate (&mutex_os_threadId[1], "thr1", &mutex_os_threadAttr, &concurrent_lock_thread, NULL);
os_threadCreate (&mutex_os_threadId[2], "thr2", &mutex_os_threadAttr, &concurrent_trylock_thread, NULL);
os_threadCreate (&mutex_os_threadId[3], "thr3", &mutex_os_threadAttr, &concurrent_trylock_thread, NULL);
os_nanoSleep (delay1);
sd->stop = 1;
os_threadWaitExit (mutex_os_threadId[0], NULL);
os_threadWaitExit (mutex_os_threadId[1], NULL);
os_threadWaitExit (mutex_os_threadId[2], NULL);
os_threadWaitExit (mutex_os_threadId[3], NULL);
printf ("All threads stopped\n");
delay1.tv_sec = 3;
printf ("Testing for %d.%9.9d seconds with lock\n", delay1.tv_sec, delay1.tv_nsec);
sd->stop = 0;
sd->nolock_corrupt_count = 0;
sd->nolock_loop_count = 0;
sd->lock_corrupt_count = 0;
sd->lock_loop_count = 0;
sd->trylock_corrupt_count = 0;
sd->trylock_loop_count = 0;
sd->trylock_busy_count = 0;
os_threadCreate (&mutex_os_threadId[0], "thr0", &mutex_os_threadAttr, &concurrent_lock_thread, (void *)1);
os_threadCreate (&mutex_os_threadId[1], "thr1", &mutex_os_threadAttr, &concurrent_lock_thread, (void *)1);
os_threadCreate (&mutex_os_threadId[2], "thr2", &mutex_os_threadAttr, &concurrent_trylock_thread, (void *)1);
os_threadCreate (&mutex_os_threadId[3], "thr3", &mutex_os_threadAttr, &concurrent_trylock_thread, (void *)1);
os_nanoSleep (delay1);
sd->stop = 1;
os_threadWaitExit (mutex_os_threadId[0], NULL);
os_threadWaitExit (mutex_os_threadId[1], NULL);
os_threadWaitExit (mutex_os_threadId[2], NULL);
os_threadWaitExit (mutex_os_threadId[3], NULL);
printf ("All threads stopped\n");
CU_ASSERT (sd->lock_corrupt_count == 0 || sd->lock_loop_count > 0);
/* Lock mutex with PRIVATE scope and Success result */
printf ("Starting tc_os_mutex_lock_002\n");
os_mutexLock (&sd->global_mutex); //Cannot be checked
os_mutexUnlock (&sd->global_mutex);
/* Lock mutex with PRIVATE scope and Fail result */
printf ("Starting tc_os_mutex_lock_003\n");
printf ("N.A - Failure cannot be forced\n");
/* mutexLock_s with PRIVATE scope and Success result */
printf ("Starting tc_os_mutex_lock_004\n");
CU_ASSERT (os_mutexLock_s (&sd->global_mutex) == os_resultSuccess);
os_mutexUnlock (&sd->global_mutex);
printf ("Ending os_mutex_lock\n");
}
CUnit_Test(os_mutex, trylock, false)
{
os_result result;
/* Test critical section access with trylocking and PRIVATE scope */
printf ("Starting os_mutex_trylock_001\n");
CU_ASSERT (sd->trylock_corrupt_count == 0 || sd->trylock_loop_count > 0);
/* TryLock mutex with PRIVATE scope and Success result */
printf ("Starting os_mutex_trylock_002\n");
result = os_mutexTryLock (&sd->global_mutex);
CU_ASSERT (result == os_resultSuccess);
/* TryLock mutex with PRIVATE scope and Busy result */
printf ("Starting os_mutex_trylock_003\n");
#if defined(__VXWORKS__) && !defined(_WRS_KERNEL)
printf ("N.A - Mutexes are recursive on VxWorks RTP so this test is disabled\n");
#endif
result = os_mutexTryLock (&sd->global_mutex);
CU_ASSERT (result == os_resultBusy);
printf ("Ending os_mutex_trylock\n");
}
CUnit_Test(os_mutex, destroy, false)
{
/* Deinitialize mutex with PRIVATE scope and Success result */
printf ("Starting os_mutex_destroy_001\n");
os_mutexDestroy(&sd->global_mutex); // Cannot be checked directly - Success is assumed
/* Deinitialize mutex with PRIVATE scope and Fail result */
printf ("Starting os_mutex_destroy_002\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending os_mutex_destroy\n");
}

167
src/os/tests/once.c Normal file
View file

@ -0,0 +1,167 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
/* Suite os_once*/
CUnit_Suite_Initialize(os_once)
{
printf("Run os_once_Initialize\n");
os_osInit();
return 0;
}
CUnit_Suite_Cleanup(os_once)
{
printf("Run os_once_Cleanup\n");
os_osExit();
return 0;
}
static uint32_t counter;
static void once_func(void)
{
counter++;
printf("Counter increased to %u\n", counter);
}
/* This test only checks a single-threaded use-case; mostly API availability and mere basics.*/
CUnit_Test(os_once, basic)
{
static os_once_t init = OS_ONCE_T_STATIC_INIT;
printf("Starting os_once_basic\n");
os_once(&init, &once_func);
CU_ASSERT(counter == 1);
os_once(&init, &once_func);
CU_ASSERT(counter == 1);
printf("Ending os_once_basic\n");
}
/* Update atomically, so that a failing os_once can be detected and isn't potentially lost due to a race. */
static os_atomic_uint32_t counter1 = OS_ATOMIC_UINT32_INIT(0);
static void once1_func(void)
{
os_time delay = { .tv_sec = 0,.tv_nsec = 250000000 }; /* 250ms */
os_nanoSleep(delay);
printf("%"PRIxMAX": Counter 1 increased to %u\n", os_threadIdToInteger(os_threadIdSelf()), os_atomic_inc32_nv(&counter1));
}
/* Update atomically, so that a failing os_once can be detected and isn't potentially lost due to a race. */
static os_atomic_uint32_t counter2 = OS_ATOMIC_UINT32_INIT(0);
static void once2_func(void)
{
os_time delay = { .tv_sec = 0, .tv_nsec = 500000000 }; /* 500ms */
os_nanoSleep(delay);
printf("%"PRIxMAX": Counter 2 increased to %u\n", os_threadIdToInteger(os_threadIdSelf()), os_atomic_inc32_nv(&counter2));
}
#define OS_ONCE_NUM_THREADS (20)
#define OS_ONCE_STATE_STARTUP (0)
#define OS_ONCE_STATE_GO (1)
struct os_once_parallel {
os_mutex m;
os_cond c;
os_atomic_uint32_t flag;
os_atomic_uint32_t started;
os_once_t init1;
os_once_t init2;
};
static uint32_t
os_once_parallel_thr(
void *args)
{
const os_time sched_delay = { .tv_sec = 0,.tv_nsec = 25000000 }; /* 25ms */
const os_time poll_delay = { .tv_sec = 0,.tv_nsec = 5000000 }; /* 5ms */
struct os_once_parallel *state = (struct os_once_parallel *)args;
bool done = false;
bool started = false;
while (!done) {
switch (os_atomic_ld32(&state->flag)) {
case OS_ONCE_STATE_STARTUP:
if (!started && (os_atomic_inc32_nv(&state->started) == OS_ONCE_NUM_THREADS)) {
printf("%"PRIxMAX": Started. Signalling GO.\n", os_threadIdToInteger(os_threadIdSelf()));
os_atomic_st32(&state->flag, OS_ONCE_STATE_GO);
os_mutexLock(&state->m);
os_condBroadcast(&state->c);
os_mutexUnlock(&state->m);
os_nanoSleep(sched_delay);
}
else {
if(!started ) printf("%"PRIxMAX": Started. Awaiting GO.\n", os_threadIdToInteger(os_threadIdSelf()));
os_mutexLock(&state->m);
(void) os_condTimedWait(&state->c, &state->m, &poll_delay);
os_mutexUnlock(&state->m);
}
started = true;
break;
case OS_ONCE_STATE_GO:
os_once(&state->init1, &once1_func);
os_once(&state->init2, &once2_func);
/* Fallthrough intentional */
default:
done = true;
break;
}
}
return 0;
}
CUnit_Test(os_once, parallel)
{
os_threadId threads[OS_ONCE_NUM_THREADS];
struct os_once_parallel state = {
.init1 = OS_ONCE_T_STATIC_INIT,
.init2 = OS_ONCE_T_STATIC_INIT,
.started = OS_ATOMIC_UINT32_INIT(0),
.flag = OS_ATOMIC_UINT32_INIT(OS_ONCE_STATE_STARTUP)
};
os_threadAttr tattr;
unsigned i;
printf("Starting os_once_parallel\n");
os_mutexInit(&state.m);
os_condInit(&state.c, &state.m);
os_threadAttrInit(&tattr);
for (i = 0; i < OS_ONCE_NUM_THREADS; i++) {
char thrname[16];
(void) snprintf(thrname, sizeof thrname, "thr%u", i);
os_threadCreate(&threads[i], thrname, &tattr, &os_once_parallel_thr, &state);
printf("%"PRIxMAX": Started thread '%s' with thread-id %" PRIxMAX "\n", os_threadIdToInteger(os_threadIdSelf()), thrname, os_threadIdToInteger(threads[i]));
}
for (; i != 0; i--) {
os_threadWaitExit(threads[i - 1], NULL);
printf("%"PRIxMAX": Thread with thread-id %" PRIxMAX " stopped.\n", os_threadIdToInteger(os_threadIdSelf()), os_threadIdToInteger(threads[i - 1]));
}
CU_ASSERT(os_atomic_ld32(&counter1) == 1);
CU_ASSERT(os_atomic_ld32(&counter2) == 1);
os_condDestroy(&state.c);
os_mutexDestroy(&state.m);
printf("Ending os_once_parallel\n");
}

404
src/os/tests/report.c Normal file
View file

@ -0,0 +1,404 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
#include "os/os_project.h"
#include <stdio.h>
CUnit_Suite_Initialize(os_report)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE=vdds_test_error");
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE=vdds_test_info");
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND=TRUE");
return 0;
}
void remove_logs()
{
const char * error_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE");
const char * info_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE");
os_remove(error_file_name);
os_remove(info_file_name);
}
void check_existence(os_result error_log_existence, os_result info_log_existence)
{
const char * error_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE");
const char * info_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE");
CU_ASSERT(os_access(error_file_name, OS_ROK) == error_log_existence);
CU_ASSERT(os_access(info_file_name, OS_ROK) == info_log_existence);
}
CUnit_Suite_Cleanup(os_report)
{
remove_logs();
return 0;
}
CUnit_Test(os_report, re_init)
{
os_reportInit(true);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
os_reportInit(true);
check_existence(os_resultSuccess, os_resultSuccess);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, stack_critical)
{
os_reportInit(true);
OS_REPORT_STACK();
OS_CRITICAL(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultFail, os_resultFail);
OS_REPORT_FLUSH(false);
// Since a critical is logged, the error log should be created
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, stack_non_critical)
{
os_reportInit(true);
OS_REPORT_STACK();
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultFail, os_resultFail);
OS_REPORT_FLUSH(false);
// Since a non critical is logged, the error log should not be created
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, error_file_creation_critical)
{
os_reportInit(true);
OS_CRITICAL(OS_FUNCTION, 0, "os_report-critical-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, error_file_creation_fatal)
{
os_reportInit(true);
OS_FATAL(OS_FUNCTION, 0, "os_report-fatal-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, info_file_creation_warning)
{
os_reportInit(true);
OS_WARNING(OS_FUNCTION, 0, "os_report-warning-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, info_file_creation_info)
{
os_reportInit(true);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, verbosity_low)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_ERROR;
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, verbosity_high)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_DEBUG;
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, verbosity_equal)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_WARNING;
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, stack_verbosity_low)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_ERROR;
OS_REPORT_STACK();
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_REPORT_FLUSH(true);
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, stack_verbosity_high)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_DEBUG;
OS_REPORT_STACK();
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_REPORT_FLUSH(true);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, stack_verbosity_equal)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_WARNING;
OS_REPORT_STACK();
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_REPORT_FLUSH(true);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, no_log_append)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND=FALSE");
os_reportInit(true);
// Both logs should be deleted
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, log_dir)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGPATH=.");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
remove_logs();
}
CUnit_Test(os_report, verbosity_env_value_info)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=0");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}
CUnit_Test(os_report, verbosity_env_value_error)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=3");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}
CUnit_Test(os_report, verbosity_env_value_error_as_string)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=ERROR");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_DEBUG(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}
CUnit_Test(os_report, verbosity_wrong_env_value)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=WRONG");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_DEBUG(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}

577
src/os/tests/rwlock.c Normal file
View file

@ -0,0 +1,577 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
#ifdef __VXWORKS__
# ifdef _WRS_KERNEL
# define FORCE_SCHEDULING() taskDelay(1)
# else
# define FORCE_SCHEDULING() sched_yield()
# endif
#else
# define FORCE_SCHEDULING()
#endif
#define ENABLE_TRACING 0
#define BUSYLOOP (100000)
#define MAX_LOOPS (20)
#define RWLOCK_THREADS 12
os_time rwlock_delay = { 0, 500 };
typedef struct Par {
int lock;
int index;
int read_access;
int concurrent_read_access;
} Par;
typedef struct {
os_rwlock global_rwlock;
os_threadId global_data;
os_threadId read_thread[RWLOCK_THREADS];
int read_corrupt_count;
int write_corrupt_count;
int concurrent_read_access;
int concurrent_write_access;
int tryread_corrupt_count;
int trywrite_corrupt_count;
int concurrent_tryread_access;
int concurrent_trywrite_access;
int tryread_busy_count;
int trywrite_busy_count;
int stop;
} shared_data;
os_threadAttr rwlock_os_threadAttr;
os_threadId rwlock_os_threadId[RWLOCK_THREADS];
static int i;
char buffer[512];
os_procId rwlock_os_procId;
int supported_resultBusy;
int loop;
static shared_data sd;
uint32_t concurrent_write_thread (_In_ void *arg)
{
struct Par *par = (struct Par *)arg;
os_threadId myid = os_threadIdSelf();
int printed = 0;
while (!sd.stop) {
if (par->lock) {
os_rwlockWrite (&sd.global_rwlock);
}
sd.global_data = myid;
FORCE_SCHEDULING();
os_nanoSleep( rwlock_delay );
if (os_threadIdToInteger(sd.global_data) != os_threadIdToInteger(myid)) {
sd.write_corrupt_count++;
if (!printed) {
/* printf ("Critical section corrupted during write [%d]\n", par->index); */
printed++;
}
}
sd.concurrent_write_access++;
if (par->lock) {
os_rwlockUnlock (&sd.global_rwlock);
}
FORCE_SCHEDULING();
os_nanoSleep( rwlock_delay );
}
return 0;
}
uint32_t concurrent_read_thread (_In_ void *arg)
{
int j;
os_threadId prevId;
struct Par *par = (struct Par *)arg;
int printed = 0;
while (!sd.stop) {
if (par->lock) {
os_rwlockRead (&sd.global_rwlock);
}
sd.read_thread[par->index] = os_threadIdSelf();
par->read_access++;
prevId = sd.global_data;
FORCE_SCHEDULING();
for (j = 0; j < BUSYLOOP/2; j++) {
if (os_threadIdToInteger(sd.global_data) !=
os_threadIdToInteger(prevId)) {
sd.read_corrupt_count++;
if (!printed) {
/* printf ("Critical section corrupted during read [%d]\n", par->index); */
printed++;
}
prevId = sd.global_data;
}
FORCE_SCHEDULING();
}
if (os_threadIdToInteger(sd.read_thread[0]) ||
os_threadIdToInteger(sd.read_thread[1]) ||
os_threadIdToInteger(sd.read_thread[2]) ||
os_threadIdToInteger(sd.read_thread[3]) ||
os_threadIdToInteger(sd.read_thread[4]) ||
os_threadIdToInteger(sd.read_thread[5]) ||
os_threadIdToInteger(sd.read_thread[6]) ||
os_threadIdToInteger(sd.read_thread[7]) ||
os_threadIdToInteger(sd.read_thread[8]) ||
os_threadIdToInteger(sd.read_thread[9]) ||
os_threadIdToInteger(sd.read_thread[10]) ||
os_threadIdToInteger(sd.read_thread[11])) {
par->concurrent_read_access++;
}
sd.concurrent_read_access++;
if (par->lock) {
os_rwlockUnlock (&sd.global_rwlock);
}
FORCE_SCHEDULING();
os_nanoSleep( rwlock_delay );
}
return 0;
}
uint32_t concurrent_trywrite_thread (_In_ void *arg)
{
struct Par *par = (struct Par *)arg;
os_result result;
os_threadId myid = os_threadIdSelf();
int printed = 0;
while (!sd.stop) {
if (par->lock) {
while ((result = os_rwlockTryWrite (&sd.global_rwlock)) != os_resultSuccess) {
if (result == os_resultBusy) {
sd.trywrite_busy_count++;
}
FORCE_SCHEDULING();
}
}
sd.global_data = os_threadIdSelf();
FORCE_SCHEDULING();
os_nanoSleep( rwlock_delay );
if (os_threadIdToInteger(sd.global_data) != os_threadIdToInteger(myid)) {
sd.trywrite_corrupt_count++;
if (!printed) {
/* printf ("Critical section corrupted during trywrite [%d]\n", par->index); */
printed++;
}
}
sd.concurrent_trywrite_access++;
if (par->lock) {
os_rwlockUnlock (&sd.global_rwlock);
}
FORCE_SCHEDULING();
os_nanoSleep( rwlock_delay );
}
return 0;
}
uint32_t concurrent_tryread_thread (_In_ void *arg)
{
int j;
os_threadId prevId;
struct Par *par = (struct Par *)arg;
os_result result;
int printed = 0;
while (!sd.stop) {
if (par->lock) {
while ((result = os_rwlockTryRead (&sd.global_rwlock)) != os_resultSuccess) {
if (result == os_resultBusy) {
sd.tryread_busy_count++;
}
FORCE_SCHEDULING();
}
}
sd.read_thread[par->index] = os_threadIdSelf();
par->read_access++;
prevId = sd.global_data;
FORCE_SCHEDULING();
for (j = 0; j < BUSYLOOP/2; j++) {
if (os_threadIdToInteger(sd.global_data) !=
os_threadIdToInteger(prevId)) {
sd.tryread_corrupt_count++;
if (!printed) {
/* printf ("Critical section corrupted during read [%d]\n", par->index); */
printed++;
}
prevId = sd.global_data;
}
FORCE_SCHEDULING();
}
if (os_threadIdToInteger(sd.read_thread[0]) ||
os_threadIdToInteger(sd.read_thread[1]) ||
os_threadIdToInteger(sd.read_thread[2]) ||
os_threadIdToInteger(sd.read_thread[3]) ||
os_threadIdToInteger(sd.read_thread[4]) ||
os_threadIdToInteger(sd.read_thread[5]) ||
os_threadIdToInteger(sd.read_thread[6]) ||
os_threadIdToInteger(sd.read_thread[7]) ||
os_threadIdToInteger(sd.read_thread[8]) ||
os_threadIdToInteger(sd.read_thread[9]) ||
os_threadIdToInteger(sd.read_thread[10]) ||
os_threadIdToInteger(sd.read_thread[11])) {
par->concurrent_read_access++;
}
sd.concurrent_tryread_access++;
if (par->lock) {
os_rwlockUnlock (&sd.global_rwlock);
}
FORCE_SCHEDULING();
os_nanoSleep( rwlock_delay );
}
return 0;
}
CUnit_Suite_Initialize(os_rwlock)
{
int result = 0;
os_osInit();
printf("Run os_rwlock_Initialize\n");
#ifdef OS_LINUX_RWLOCK_H149C
supported_resultBusy = 1;
#else
supported_resultBusy = 0;
#endif
return result;
}
CUnit_Suite_Cleanup(os_rwlock)
{
int result = 0;
printf("Run os_rwlock_Cleanup\n");
os_osExit();
return result;
}
CUnit_Test(os_rwlock, init)
{
/* Initilalize reader/writer lock with PRIVATE scope and Success result */
printf ("Starting os_rwlock_init_001\n");
os_rwlockInit (&sd.global_rwlock);
/* Initilalize reader/writer lock with Fail result */
printf ("Starting os_rwlock_init_001\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending os_rwlock_init\n");
}
CUnit_Test(os_rwlock, read, false)
{
os_time rdelay = { 3, 0 };
struct Par par[RWLOCK_THREADS];
/* Test critical section access without locking to show problem */
printf ("Starting os_rwlock_read_001\n");
rdelay.tv_sec = 3;
printf ("Testing for %d.%9.9d seconds without lock\n", rdelay.tv_sec, rdelay.tv_nsec);
sd.read_corrupt_count = 0;
sd.write_corrupt_count = 0;
sd.concurrent_read_access = 0;
sd.concurrent_write_access = 0;
sd.tryread_corrupt_count = 0;
sd.trywrite_corrupt_count = 0;
sd.concurrent_tryread_access = 0;
sd.concurrent_trywrite_access = 0;
sd.tryread_busy_count = 0;
sd.trywrite_busy_count = 0;
sd.stop = 0;
for (i = 0; i < RWLOCK_THREADS; i++) {
par[i].concurrent_read_access = 0;
par[i].read_access = 0;
par[i].lock = 0;
par[i].index = i;
}
os_threadAttrInit (&rwlock_os_threadAttr);
os_threadCreate (&rwlock_os_threadId[0], "thr0", &rwlock_os_threadAttr, &concurrent_write_thread, (void *)&par[0]);
os_threadCreate (&rwlock_os_threadId[1], "thr1", &rwlock_os_threadAttr, &concurrent_write_thread, (void *)&par[1]);
os_threadCreate (&rwlock_os_threadId[2], "thr2", &rwlock_os_threadAttr, &concurrent_read_thread, (void *)&par[2]);
os_threadCreate (&rwlock_os_threadId[3], "thr3", &rwlock_os_threadAttr, &concurrent_read_thread, (void *)&par[3]);
os_threadCreate (&rwlock_os_threadId[4], "thr4", &rwlock_os_threadAttr, &concurrent_trywrite_thread, (void *)&par[4]);
os_threadCreate (&rwlock_os_threadId[5], "thr5", &rwlock_os_threadAttr, &concurrent_trywrite_thread, (void *)&par[5]);
os_threadCreate (&rwlock_os_threadId[6], "thr6", &rwlock_os_threadAttr, &concurrent_tryread_thread, (void *)&par[6]);
os_threadCreate (&rwlock_os_threadId[7], "thr7", &rwlock_os_threadAttr, &concurrent_tryread_thread, (void *)&par[7]);
os_nanoSleep (rdelay);
sd.stop = 1;
os_threadWaitExit (rwlock_os_threadId[0], NULL);
os_threadWaitExit (rwlock_os_threadId[1], NULL);
os_threadWaitExit (rwlock_os_threadId[2], NULL);
os_threadWaitExit (rwlock_os_threadId[3], NULL);
os_threadWaitExit (rwlock_os_threadId[4], NULL);
os_threadWaitExit (rwlock_os_threadId[5], NULL);
os_threadWaitExit (rwlock_os_threadId[6], NULL);
os_threadWaitExit (rwlock_os_threadId[7], NULL);
printf ("All threads stopped\n");
for (i = 2; i < 4; i++) {
printf ("total read access %d, concurrent read access %d for thread %d\n",
par[i].read_access, par[i].concurrent_read_access, i);
}
for (i = 6; i < 8; i++) {
printf ("total try read access %d, concurrent try read access %d for thread %d\n",
par[i].read_access, par[i].concurrent_read_access, i);
}
printf ("read_corrupt_count = %d\n", sd.read_corrupt_count);
printf ("write_corrupt_count = %d\n", sd.write_corrupt_count);
printf ("tryread_corrupt_count = %d\n", sd.tryread_corrupt_count);
printf ("trywrite_corrupt_count = %d\n", sd.trywrite_corrupt_count);
printf ("concurrent_read_access = %d\n", sd.concurrent_read_access);
printf ("concurrent_write_access = %d\n", sd.concurrent_write_access);
printf ("concurrent_tryread_access = %d\n", sd.concurrent_tryread_access);
printf ("concurrent_trywrite_access = %d\n", sd.concurrent_trywrite_access);
sprintf (buffer, "Corrupt counter = %d, Loop counter is %d",
sd.read_corrupt_count + sd.write_corrupt_count + sd.tryread_corrupt_count + sd.trywrite_corrupt_count,
sd.concurrent_read_access + sd.concurrent_write_access + sd.concurrent_tryread_access + sd.concurrent_trywrite_access);
CU_ASSERT((sd.read_corrupt_count > 0 ||
sd.write_corrupt_count > 0 ||
sd.tryread_corrupt_count > 0 ||
sd.trywrite_corrupt_count > 0) &&
sd.concurrent_read_access > 0 &&
sd.concurrent_write_access > 0 &&
sd.concurrent_tryread_access > 0 &&
sd.concurrent_trywrite_access > 0);
/* Test critical section READ access with locking and PRIVATE scope */
printf ("Starting os_rwlock_read_002\n");
rdelay.tv_sec = 3;
printf ("Testing for %d.%9.9d seconds with lock\n", rdelay.tv_sec, rdelay.tv_nsec);
sd.read_corrupt_count = 0;
sd.write_corrupt_count = 0;
sd.concurrent_read_access = 0;
sd.concurrent_write_access = 0;
sd.tryread_corrupt_count = 0;
sd.trywrite_corrupt_count = 0;
sd.concurrent_tryread_access = 0;
sd.concurrent_trywrite_access = 0;
sd.tryread_busy_count = 0;
sd.trywrite_busy_count = 0;
sd.stop = 0;
for (i = 0; i < RWLOCK_THREADS; i++) {
par[i].concurrent_read_access = 0;
par[i].read_access = 0;
par[i].lock = 1;
par[i].index = i;
}
os_threadAttrInit (&rwlock_os_threadAttr);
os_threadCreate (&rwlock_os_threadId[0], "thr0", &rwlock_os_threadAttr, &concurrent_write_thread, (void *)&par[0]);
os_threadCreate (&rwlock_os_threadId[1], "thr1", &rwlock_os_threadAttr, &concurrent_write_thread, (void *)&par[1]);
os_threadCreate (&rwlock_os_threadId[2], "thr2", &rwlock_os_threadAttr, &concurrent_read_thread, (void *)&par[2]);
os_threadCreate (&rwlock_os_threadId[3], "thr3", &rwlock_os_threadAttr, &concurrent_read_thread, (void *)&par[3]);
os_threadCreate (&rwlock_os_threadId[4], "thr4", &rwlock_os_threadAttr, &concurrent_trywrite_thread, (void *)&par[4]);
os_threadCreate (&rwlock_os_threadId[5], "thr5", &rwlock_os_threadAttr, &concurrent_trywrite_thread, (void *)&par[5]);
os_threadCreate (&rwlock_os_threadId[6], "thr6", &rwlock_os_threadAttr, &concurrent_tryread_thread, (void *)&par[6]);
os_threadCreate (&rwlock_os_threadId[7], "thr7", &rwlock_os_threadAttr, &concurrent_tryread_thread, (void *)&par[7]);
os_nanoSleep (rdelay);
sd.stop = 1;
os_threadWaitExit (rwlock_os_threadId[0], NULL);
os_threadWaitExit (rwlock_os_threadId[1], NULL);
os_threadWaitExit (rwlock_os_threadId[2], NULL);
os_threadWaitExit (rwlock_os_threadId[3], NULL);
os_threadWaitExit (rwlock_os_threadId[4], NULL);
os_threadWaitExit (rwlock_os_threadId[5], NULL);
os_threadWaitExit (rwlock_os_threadId[6], NULL);
os_threadWaitExit (rwlock_os_threadId[7], NULL);
printf ("All threads stopped\n");
for (i = 2; i < 4; i++) {
printf ("total read access %d, concurrent read access %d for thread %d\n",
par[i].read_access, par[i].concurrent_read_access, i);
}
for (i = 6; i < 8; i++) {
printf ("total try read access %d, concurrent try read access %d for thread %d\n",
par[i].read_access, par[i].concurrent_read_access, i);
}
sprintf (buffer, "Corrupt read counter = %d, Read loop counter is %d", sd.read_corrupt_count, sd.concurrent_read_access);
CU_ASSERT (sd.read_corrupt_count == 0 && sd.concurrent_read_access > 0);
/* Test read on rwlock with PRIVATE scope and Success result & not locked */
printf ("Starting os_rwlock_read_003\n");
os_rwlockRead (&sd.global_rwlock); // Cannot be checked
os_rwlockUnlock (&sd.global_rwlock);
/* Test read on rwlock with PRIVATE scope and Success result & locked by read */
printf ("Starting os_rwlock_read_004\n");
printf ("N.A - Not implemented\n");
/* Test read on rwlock with PRIVATE scope and Fail result */
printf ("Starting os_rwlock_read_005\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending os_rwlock_read\n");
}
CUnit_Test(os_rwlock, write, false)
{
/* Test critical section WRITE access with locking and PRIVATE scope */
printf ("Starting os_rwlock_write_001\n");
sprintf (buffer, "Corrupt write counter = %d, Write loop counter is %d", sd.write_corrupt_count, sd.concurrent_write_access);
CU_ASSERT (sd.write_corrupt_count == 0 && sd.concurrent_write_access > 0);
/* Test write on rwlock with PRIVATE scope and Success result */
printf ("Starting os_rwlock_write_002\n");
os_rwlockWrite (&sd.global_rwlock); //Cannot be checked
os_rwlockUnlock (&sd.global_rwlock);
/* Test write on rwlock with PRIVATE scope and Fail result */
printf ("Starting os_rwlock_write_003\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending tc_rwlockWrite\n");
}
CUnit_Test(rwlock, tryread, false)
{
os_result result;
/* Test critical section READ access with trylocking and PRIVATE scope */
printf ("Starting os_rwlock_tryread_001\n");
sprintf (buffer, "Corrupt tryread counter = %d, Tryread loop counter is %d, Busy counter = %d", sd.tryread_corrupt_count, sd.concurrent_tryread_access, sd.tryread_busy_count);
CU_ASSERT (sd.tryread_corrupt_count == 0 && sd.concurrent_tryread_access > 0);
/* Test try read on rwlock with PRIVATE scope and Success result & not locked */
printf ("Starting os_rwlock_tryread_002\n");
result = os_rwlockTryRead (&sd.global_rwlock);
CU_ASSERT (result == os_resultSuccess);
os_rwlockUnlock (&sd.global_rwlock);
/* Test try read on rwlock with PRIVATE scope and Success result & locked by read */
printf ("Starting os_rwlock_tryread_003\n");
printf ("N.A - Not implemented\n");
/* Test try read on rwlock with PRIVATE scope and Busy result & locked by write */
printf ("Starting os_rwlock_tryread_004\n");
printf ("N.A - Not implemented\n");
/* Test try read on rwlock with PRIVATE scope and Fail result */
printf ("Starting os_rwlock_tryread_005\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending os_rwlock_tryread\n");
}
CUnit_Test(os_rwlock, trywrite, false)
{
os_result result;
/* Test critical section WRITE access with trylocking and PRIVATE scope */
printf ("Starting os_rwlock_trywrite_001\n");
sprintf (buffer, "Corrupt trywrite counter = %d, Trywrite loop counter is %d, Busy counter = %d", sd.trywrite_corrupt_count, sd.concurrent_trywrite_access, sd.trywrite_busy_count);
CU_ASSERT (sd.trywrite_corrupt_count == 0 && sd.concurrent_trywrite_access > 0);
/* Test try write on rwlock with PRIVATE scope and Success result */
printf ("Starting os_rwlock_trywrite_002\n");
result = os_rwlockTryWrite (&sd.global_rwlock);
CU_ASSERT (result == os_resultSuccess);
os_rwlockUnlock (&sd.global_rwlock);
/* Test try write on rwlock with PRIVATE scope and Busy result & locked by read */
printf ("Starting os_rwlock_trywrite_003\n");
printf ("N.A - Not implemented\n");
/* Test try write on rwlock with PRIVATE scope and Busy result & locked by write */
printf ("Starting os_rwlock_trywrite_004\n");
printf ("N.A - Not implemented\n");
/* Test try write on rwlock with PRIVATE scope and Fail result */
printf ("Starting os_rwlock_trywrite_005\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending os_rwlock_trywrite\n");
}
CUnit_Test(os_rwlock, unlock, false)
{
os_result result;
/* Unlock rwlock with PRIVATE scope and Success result and claimed with read */
printf ("Starting os_rwlock_unlock_001\n");
os_rwlockRead (&sd.global_rwlock);
os_rwlockUnlock (&sd.global_rwlock); //Cannot be checked
/* Unlock rwlock with PRIVATE scope and Success result and claimed with try read */
printf ("Starting os_rwlock_unlock_002\n");
result = os_rwlockTryRead (&sd.global_rwlock);
CU_ASSERT (result == os_resultSuccess);
os_rwlockUnlock (&sd.global_rwlock);
/* Unlock rwlock with PRIVATE scope and Success result and claimed with write */
printf ("Starting os_rwlock_unlock_003\n");
os_rwlockWrite (&sd.global_rwlock);
os_rwlockUnlock (&sd.global_rwlock); //Cannot be checked
/* Unlock rwlock with PRIVATE scope and Success result and claimed with try write */
printf ("Starting os_rwlock_unlock_004\n");
result = os_rwlockTryWrite (&sd.global_rwlock);
CU_ASSERT (result == os_resultSuccess);
os_rwlockUnlock (&sd.global_rwlock);
/* Unlock rwlock with PRIVATE scope and Fail result */
printf ("Starting os_rwlock_unlock_005\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending tc_rwlockUnlock\n");
}
CUnit_Test(os_rwlock, destroy, false)
{
/* Deinitialize rwlock with PRIVATE scope and Success result */
printf ("Starting os_rwlock_destroy_001\n");
os_rwlockDestroy (&sd.global_rwlock); //Cannot be checked
/* Deinitialize rwlock with PRIVATE scope and Fail result */
printf ("Starting os_rwlock_destroy_002\n");
printf ("N.A - Failure cannot be forced\n");
printf ("Ending tc_rwlockDestroy\n");
}
CUnit_Test(os_rwlock, destroy_shared)
{
os_rwlock mylock;
os_rwlockInit(&mylock);
os_rwlockRead(&mylock);
os_rwlockUnlock(&mylock);
/* This test used to assert on a debug-build on Windows. Failure can't be forced, but if
* someone adds the naively sensible assert again, this test won't run on a debug-build. */
os_rwlockDestroy(&mylock);
CU_PASS("os_rwlockDestroy succeeds after releasing a shared lock");
}

869
src/os/tests/stdlib.c Executable file
View file

@ -0,0 +1,869 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
#ifndef WINCE
#include <fcntl.h>
#endif
#if (defined WIN32 || defined WIN64)
#include <direct.h>
#include <Windows.h>
#endif
static const os_time wait_time_out = { 1, 0 };
static FILE *file;
#define ENABLE_TRACING 0
#define FLOCKFILE_THREAD1_INPUT1 "thread1_flockfile_proc: *** input 1 ***"
#define FLOCKFILE_THREAD1_INPUT3 "thread1_flockfile_proc: *** input 3 ***"
#define FLOCKFILE_THREAD2_INPUT2 "thread2_flockfile_proc: *** input 2 ***"
#define defSignal(signal) \
static os_cond signal;\
static bool signal##_set = false;
#define initSignal(signal, mutex) \
os_condInit(&signal, &mutex);\
signal##_set = false;
#define sendSignal(signal, mutex) \
os_mutexLock(&mutex);\
/* signaling */ \
signal##_set = true; \
os_condSignal(&signal);\
os_mutexUnlock(&mutex);
#define waitForSignal(signal, mutex) \
os_mutexLock(&mutex);\
while(!signal##_set) { \
/* waiting for signal */ \
os_condWait(&signal, &mutex);\
/* received */ \
} /* else already signal received */ \
os_mutexUnlock(&mutex);
#define timedWaitSignal(signal, mutex, time) \
{ \
os_time duration = time; \
os_time startTime, currentTime; \
os_result rc; \
os_mutexLock(&mutex); \
startTime = os_timeGetElapsed(); \
while(!signal##_set) { \
/* waiting for signal */ \
rc = os_condTimedWait(&signal, &mutex, &duration); \
/* signal received or timeout */ \
if(rc == os_resultTimeout) { \
break; \
} else { \
currentTime = os_timeGetElapsed(); \
if(os_timeCompare(os_timeSub(currentTime, startTime), wait_time_out) >= 0) { \
break; \
} \
duration = os_timeSub(wait_time_out, os_timeSub(currentTime, startTime)); \
} \
} /* else already signal received */ \
os_mutexUnlock(&mutex);\
}
static os_mutex mutex;
static bool do_locking;
/* signals set by threads */
defSignal(thread1_started);
defSignal(thread2_started);
defSignal(action1_done);
defSignal(action2_done);
/* signals set by the test orchestrator (doFlockfileTest) */
defSignal(do_action1);
defSignal(do_action2);
defSignal(do_action3);
static uint32_t thread1_flockfile_proc(void* args) {
int result = 0;
/* thread1: start */
sendSignal(thread1_started, mutex);
waitForSignal(do_action1, mutex);
if(do_locking) os_flockfile(file);
/* Thread1: writing input 1 to the file */
result = fputs(FLOCKFILE_THREAD1_INPUT1, file);
CU_ASSERT(result >= 0);
sendSignal(action1_done, mutex);
waitForSignal(do_action3, mutex);
/* Thread1: writing input 3 to the file */
result = fputs(FLOCKFILE_THREAD1_INPUT3, file);
CU_ASSERT(result >= 0);
if(do_locking) os_funlockfile(file);
/* thread1: end */
return 0;
}
static uint32_t thread2_flockfile_proc(void* args) {
int result = 0;
/* thread2: start */
sendSignal(thread2_started, mutex);
waitForSignal(do_action2, mutex);
/* Thread2: writing input 2 to the file */
result = fputs(FLOCKFILE_THREAD2_INPUT2, file);
CU_ASSERT(result >= 0);
sendSignal(action2_done, mutex);
/* thread2: end */
return 0;
}
bool doFlockfileTest(bool lock) {
bool testPassed = true;
bool strcmpResult = true;
os_result result;
os_threadAttr threadAttr;
os_threadId thread1;
os_threadId thread2;
int FLOCKFILE_INPUT_MAX = sizeof(FLOCKFILE_THREAD1_INPUT1);
do_locking = lock;
char *buffer = os_malloc(sizeof(char) * FLOCKFILE_INPUT_MAX);
file = tmpfile();
os_mutexInit(&mutex);
/* initialize all signal conditions */
os_mutexLock(&mutex);
initSignal(thread1_started, mutex);
initSignal(thread2_started, mutex);
initSignal(action1_done, mutex);
initSignal(action2_done, mutex);
initSignal(do_action1, mutex);
initSignal(do_action2, mutex);
initSignal(do_action3, mutex);
os_mutexUnlock(&mutex);
/* create threads... */
os_threadAttrInit(&threadAttr);
result = os_threadCreate(
&thread1,
"thread 1",
&threadAttr,
thread1_flockfile_proc,
NULL);
CU_ASSERT(result == os_resultSuccess);
result = os_threadCreate(
&thread2,
"thread 2",
&threadAttr,
thread2_flockfile_proc,
NULL);
CU_ASSERT(result == os_resultSuccess);
/* wait for threads to start */
waitForSignal(thread1_started, mutex);
waitForSignal(thread2_started, mutex);
/* get thread one to do its first thing */
sendSignal(do_action1, mutex);
/* wait for thread 1 to acknowledge */
timedWaitSignal(action1_done, mutex, wait_time_out);
/* kick thead 2 */
sendSignal(do_action2, mutex);
/* wait for thread 2 to acknowledge */
timedWaitSignal(action2_done, mutex, wait_time_out);
/* kick thread 1, again */
sendSignal(do_action3, mutex);
/* wait for threads to shutdown */
result = os_threadWaitExit(thread1,NULL);
CU_ASSERT(result == os_resultSuccess);
result = os_threadWaitExit(thread2,NULL);
CU_ASSERT(result == os_resultSuccess);
/* if lock then Expected action order: 1 3 2
* else Expected action order: 1 2 3 */
rewind(file);
if(lock) {
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > 0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT1) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > 0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT3) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > 0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD2_INPUT2) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
} else {
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > 0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT1) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > 0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD2_INPUT2) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > 0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT3) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
}
/* cleanup */
os_free(buffer);
fclose(file);
os_mutexLock(&mutex);
os_condDestroy(&do_action1);
os_condDestroy(&do_action2);
os_condDestroy(&do_action3);
os_condDestroy(&thread1_started);
os_condDestroy(&thread2_started);
os_condDestroy(&action1_done);
os_condDestroy(&action2_done);
os_mutexUnlock(&mutex);
os_mutexDestroy(&mutex);
/* doFlockfileTest */
return testPassed;
}
static int
vsnprintfTest(
const char *format,
...)
{
va_list varargs;
int result = 0;
char description[10];
va_start(varargs, format);
memset(description, 0, sizeof(description));
result = os_vsnprintf(description, sizeof(description)-1, format, varargs);
va_end(varargs);
return result;
}
CUnit_Suite_Initialize(os_stdlib)
{
int result = 0;
os_osInit();
return result;
}
CUnit_Suite_Cleanup(os_stdlib)
{
/* Remove files used to test permissions */
remove ("exec_only");
remove ("read_exec");
remove ("read_only");
remove ("read_write_exec");
remove ("write_only");
remove ("existing_file");
os_osExit();
return 0;
}
CUnit_Test(os_stdlib, strcasecmp)
{
int res;
char *s1, *s2;
s1 = "a";
s2 = "a";
printf ("Starting os_stdlib_strcasecmp_001\n");
res = os_strcasecmp (s1,s2);
CU_ASSERT (res == 0);
printf ("Starting os_stdlib_strcasecmp_002\n");
s1 = "aa";
s2 = "a";
res = os_strcasecmp (s1,s2);
CU_ASSERT (res > 0);
printf ("Starting os_stdlib_strcasecmp_003\n");
s1 = "a";
s2 = "aa";
res = os_strcasecmp (s1,s2);
CU_ASSERT (res < 0);
printf ("Starting os_stdlib_strcasecmp_004\n");
s1 = "a";
s2 = "A";
res = os_strcasecmp (s1,s2);
CU_ASSERT (res == 0);
printf ("Starting os_stdlib_strcasecmp_005\n");
s1 = "A";
s2 = "a";
res = os_strcasecmp (s1,s2);
CU_ASSERT (res == 0);
printf ("Starting os_stdlib_strcasecmp_006\n");
s1 = "a";
s2 = "b";
res = os_strcasecmp (s1,s2);
CU_ASSERT (res < 0);
printf ("Starting os_stdlib_strcasecmp_007\n");
s1 = "b";
s2 = "a";
res = os_strcasecmp (s1,s2);
CU_ASSERT (res > 0);
printf ("Ending os_stdlib_strcasecmp\n");
}
CUnit_Test(os_stdlib, strncasecmp)
{
int res;
char *s1, *s2;
s1 = "a";
s2 = "a";
printf ("Starting os_stdlib_strncasecmp_001\n");
res = os_strncasecmp (s1,s2,2);
CU_ASSERT (res == 0);
s1 = "aa";
s2 = "a";
printf ("Starting os_stdlib_strncasecmp_002\n");
res = os_strncasecmp (s1,s2,2);
CU_ASSERT (res > 0);
s1 = "a";
s2 = "aa";
printf ("Starting os_stdlib_strncasecmp_003\n");
res = os_strncasecmp (s1,s2,2);
CU_ASSERT (res < 0);
s1 = "a";
s2 = "A";
printf ("Starting os_stdlib_strncasecmp_004\n");
res = os_strncasecmp (s1,s2,2);
CU_ASSERT (res == 0);
s1 = "A";
s2 = "a";
printf ("Starting os_stdlib_strncasecmp_005\n");
res = os_strncasecmp (s1,s2,2);
CU_ASSERT (res == 0);
s1 = "a";
s2 = "b";
printf ("Starting os_stdlib_strncasecmp_006\n");
res = os_strncasecmp (s1,s2,2);
CU_ASSERT (res < 0);
s1 = "b";
s2 = "a";
printf ("Starting os_stdlib_strncasecmp_007\n");
res = os_strncasecmp (s1,s2,2);
CU_ASSERT (res > 0);
s1 = "abcdefghijkl";
s2 = "AbCdEaGhIjKl";
printf ("Starting os_stdlib_strncasecmp_008\n");
res = os_strncasecmp (s1,s2,5);
CU_ASSERT (res == 0);
s1 = "abcdefghijkl";
s2 = "AbCdEaGhIjKl";
printf ("Starting os_stdlib_strncasecmp_009\n");
res = os_strncasecmp (s1,s2,6);
CU_ASSERT (res > 0);
printf ("Ending os_stdlib_strncasecmp\n");
}
CUnit_Test(os_stdlib, gethostname)
{
int res;
os_result os_res;
char os_cpu[200];
char cpu[200];
printf ("Starting os_stdlib_gethostname_001\n");
os_cpu[0] = '\0';
os_res = os_gethostname (os_cpu, sizeof(os_cpu));
CU_ASSERT (os_res == os_resultSuccess);
cpu[0] = '\0';
res = gethostname (cpu, sizeof(cpu));
CU_ASSERT (res == 0);
printf ("Starting os_stdlib_gethostname_002\n");
os_res = os_gethostname (os_cpu, strlen(os_cpu)-1);
CU_ASSERT (os_res == os_resultFail);
printf ("Ending os_stdlib_gethostname\n");
}
CUnit_Test(os_stdlib, putenv)
{
os_result os_res;
printf ("Starting os_stdlib_putenv_001\n");
os_res = os_putenv ("ABCDE=FGHIJ");
CU_ASSERT (os_res == os_resultSuccess);
CU_ASSERT (strcmp (os_getenv("ABCDE"), "FGHIJ") == 0);
printf ("Ending os_stdlib_putenv\n");
}
CUnit_Test(os_stdlib, getenv)
{
const char *env;
os_result res;
printf ("Starting os_stdlib_getenv_001\n");
res = os_putenv("ABCDE=FGHIJ");
CU_ASSERT(res == os_resultSuccess);
env = os_getenv("ABCDE");
CU_ASSERT(env != NULL);
if (env != NULL) {
CU_ASSERT(strcmp(env, "FGHIJ") == 0);
}
printf ("Starting os_stdlib_getenv_002\n");
CU_ASSERT (os_getenv("XXABCDEXX") == NULL );
printf ("Ending os_stdlib_getenv\n");
}
CUnit_Test(os_stdlib, fileSep)
{
#if defined WIN32
const char *wanted= "\\";
#else
const char *wanted= "/";
#endif
printf ("Starting os_stdlib_fileSep_001\n");
CU_ASSERT (strcmp(os_fileSep(), wanted) == 0);
printf ("Ending os_stdlib_fileSep\n");
}
CUnit_Test(os_stdlib, access)
{
os_result os_res;
os_result wanted;
int fh;
/* Check correct functioning of os_access, non existing file read access */
printf ("Starting os_stdlib_access_001\n");
#if defined VXWORKS_RTP || defined _WRS_KERNEL
printf ("N.A - Not tested for vxworks.\n");
#else
os_res = os_access("non_existing_file", OS_ROK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, non existing file write access */
printf ("Starting os_stdlib_access_002\n");
os_res = os_access("non_existing_file", OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, non existing file execute access */
printf ("Starting os_stdlib_access_003\n");
os_res = os_access("non_existing_file", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, non existing file existence */
printf ("Starting os_stdlib_access_004\n");
os_res = os_access("non_existing_file", OS_FOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, existing file with no
permissions read access */
printf ("Starting os_stdlib_access_005\n");
#ifdef WIN32
fh= _creat("existing_file", 0000); /* Note always has read & execute */
if (fh != -1)
_close(fh);
wanted = os_resultSuccess;
#else
fh= creat("existing_file", 0000);
if (fh != -1)
close(fh);
wanted = os_resultFail;
#endif /* WIN32 */
os_res = os_access("existing_file", OS_ROK);
CU_ASSERT (os_res == wanted);
/* Check correct functioning of os_access, existing file with no
permissions write access */
printf ("Starting os_stdlib_access_006\n");
os_res = os_access("existing_file", OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, existing file with no
permissions execute access */
printf ("Starting os_stdlib_access_007\n");
os_res = os_access("existing_file", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, existing file with no permissions existence */
printf ("Starting os_stdlib_access_008\n");
os_res = os_access("existing_file", OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read permissions read access */
printf ("Starting os_stdlib_access_009\n");
#ifdef WIN32
fh= _creat("read_only", _S_IREAD); /* Note always has read & execute */
if (fh != -1)
_close(fh);
#else
fh= creat("read_only", S_IRUSR);
if (fh != -1)
close(fh);
#endif /* WIN32 */
os_res = os_access("read_only", OS_ROK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read permissions write access */
printf ("Starting os_stdlib_access_010\n");
os_res = os_access("read_only", OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read permissions execute access */
printf ("Starting os_stdlib_access_011\n");
os_res = os_access("read_only", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read permissions existence */
printf ("Starting os_stdlib_access_012\n");
os_res = os_access("read_only", OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with write permissions read access */
printf ("Starting os_stdlib_access_013\n");
#ifdef WIN32
fh= _creat("write_only", _S_IWRITE); /* Note windows automatically has read access can't have write only */
if (fh != -1)
_close(fh);
wanted = os_resultSuccess;
#else
fh= creat("write_only", S_IWUSR);
if (fh != -1)
close(fh);
wanted = os_resultFail;
#endif /* WIN32 */
os_res = os_access("write_only", OS_ROK);
CU_ASSERT (os_res == wanted);
/* Check correct functioning of os_access,
existing file with write permissions write access */
printf ("Starting os_stdlib_access_014\n");
os_res = os_access("write_only", OS_WOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with write permissions execute access */
printf ("Starting os_stdlib_access_015\n");
os_res = os_access("write_only", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with write permissions existence */
printf ("Starting os_stdlib_access_016\n");
os_res = os_access("write_only", OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with exec permissions read access */
printf ("Starting os_stdlib_access_017\n");
#ifdef WIN32
fh= _creat("exec_only" OS_OS_EXESUFFIX, _S_IREAD); /* Windows always has read and can't do execute (that's based upon filename ext only) */
if (fh != -1)
_close(fh);
wanted = os_resultSuccess;
#else
fh= creat("exec_only" OS_OS_EXESUFFIX, S_IXUSR);
if (fh != -1)
close(fh);
wanted = os_resultFail;
#endif /* WIN32 */
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_ROK);
CU_ASSERT (os_res == wanted);
/* Check correct functioning of os_access,
existing file with exec permissions write access */
printf ("Starting os_stdlib_access_018\n");
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with exec permissions execute access */
printf ("Starting os_stdlib_access_019\n");
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_XOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with exec permissions existence */
printf ("Starting os_stdlib_access_020\n");
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions read access */
printf ("Starting os_stdlib_access_021\n");
#ifdef WIN32
fh= _creat("read_write_exec" OS_OS_EXESUFFIX, _S_IREAD | _S_IWRITE); /* Windows always has read and can't do execute (that's based upon filename ext only) */
if (fh != -1)
_close(fh);
#else
fh= creat("read_write_exec" OS_OS_EXESUFFIX, S_IRUSR | S_IWUSR | S_IXUSR);
if (fh != -1)
close(fh);
#endif /* WIN32 */
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_ROK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions write access */
printf ("Starting os_stdlib_access_022\n");
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_WOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions execute access */
printf ("Starting os_stdlib_access_023\n");
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_XOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions existence */
printf ("Starting os_stdlib_access_024\n");
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/exec permissions read+write access */
printf ("Starting os_stdlib_access_025\n");
#ifdef WIN32
fh= _creat("read_exec" OS_OS_EXESUFFIX, _S_IREAD); /* Windows always has read and can't do execute (that's based upon filename ext only) */
if (fh != -1)
_close(fh);
#else
fh= creat("read_exec" OS_OS_EXESUFFIX, S_IRUSR | S_IXUSR);
if (fh != -1)
close(fh);
#endif /* WIN32 */
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read/exec permissions write+exec access */
printf ("Starting os_stdlib_access_026\n");
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_WOK|OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read/exec permissions read+exec access */
printf ("Starting os_stdlib_access_027\n");
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_XOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/exec permissions read+exec+existence */
printf ("Starting os_stdlib_access_028\n");
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_XOK|OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
#endif /* VXWORKS */
printf ("Ending stdlib_os_access\n");
}
CUnit_Test(os_stdlib, vsnprintf)
{
printf ("Starting os_stdlib_vsnprintf_001\n");
CU_ASSERT (vsnprintfTest("%s","test") == 4);
CU_ASSERT (vsnprintfTest("%d",12) == 2);
CU_ASSERT (vsnprintfTest("hello %s","world") == 11);
printf ("Ending os_stdlib_vsnprintf\n");
}
CUnit_Test(os_stdlib, strtok_r)
{
char * res;
char *strtok_r_ts1;
char *saveptr;
printf ("Starting os_stdlib_strtok_r_001\n");
strtok_r_ts1= os_strdup("123,234");
res = os_strtok_r( strtok_r_ts1, ",", &saveptr );
CU_ASSERT (strcmp(res, "123") == 0);
printf ("Starting os_stdlib_strtok_r_002\n");
res = os_strtok_r( NULL, ",", &saveptr );
CU_ASSERT (strcmp(res, "234") == 0);
printf ("Starting os_stdlib_strtok_r_003\n");
res = os_strtok_r( NULL, ",", &saveptr );
CU_ASSERT (res == NULL);
os_free(strtok_r_ts1);
printf ("Starting os_stdlib_strtok_r_004\n");
strtok_r_ts1= os_strdup(",;,123abc,,456,:,");
res = os_strtok_r( strtok_r_ts1, ",;", &saveptr );
CU_ASSERT (strcmp(res, "123abc") == 0);
printf ("Starting os_stdlib_strtok_r_005\n");
res = os_strtok_r( NULL, ",", &saveptr );
CU_ASSERT (strcmp(res, "456") == 0);
printf ("Starting os_stdlib_strtok_r_006\n");
res = os_strtok_r( NULL, ",:", &saveptr );
CU_ASSERT (res == NULL);
free(strtok_r_ts1);
printf ("Starting os_stdlib_strtok_r_007\n");
strtok_r_ts1= os_strdup(",,,123,,456,789,,,");
res = os_strtok_r( strtok_r_ts1, ",", &saveptr );
CU_ASSERT (strcmp(res, "123") == 0);
printf ("Starting os_stdlib_strtok_r_008\n");
res = os_strtok_r( NULL, ",", &saveptr );
CU_ASSERT (strcmp(res, "456") == 0);
printf ("Starting os_stdlib_strtok_r_009\n");
res = os_strtok_r( NULL, ",", &saveptr );
CU_ASSERT (strcmp(res, "789") == 0);
printf ("Starting os_stdlib_strtok_r_010\n");
res = os_strtok_r( NULL, ",:", &saveptr );
CU_ASSERT (res == NULL);
free(strtok_r_ts1);
printf ("Ending os_stdlib_strtok_r\n");
}
CUnit_Test(os_stdlib, index)
{
char * res;
char *index_ts1;
printf ("Starting os_stdlib_index_001\n");
index_ts1 = "abc";
res = os_index( index_ts1, 'a' );
CU_ASSERT (res == index_ts1);
printf ("Starting os_stdlib_index_002\n");
res = os_index( index_ts1, 'c' );
CU_ASSERT (res == &index_ts1[2]);
printf ("Starting os_stdlib_index_003\n");
index_ts1 = "abcdefghij";
res = os_index( index_ts1, 'f' );
CU_ASSERT (res == &index_ts1[5]);
printf ("Starting os_stdlib_index_004\n");
res = os_index( index_ts1, 'k' );
CU_ASSERT (res == NULL);
printf ("Ending os_stdlib_index\n");
}
CUnit_Test(os_stdlib, flockfile)
{
bool result = false;
os_osInit();
/* Check writing in a FILE from multiple threads without using os_flockfile. */
printf ("Starting os_stdlib_flockfile_001\n");
result = doFlockfileTest(false);
CU_ASSERT (result);
/* Check writing in a FILE from multiple threads using os_flockfile in the first thread. */
printf ("Starting os_stdlib_flockfile_002\n");
result = doFlockfileTest(true);
CU_ASSERT (result);
printf ("Ending os_stdlib_flockfile\n");
os_osExit();
}
CUnit_Test(os_stdlib, getopt)
{
int c = 0;
int argc = 3;
char *argv001[] = {"", "-a", "-b"};
char *argv002[] = {"", "-c", "foo"};
char *argv003[] = {"", "-d"};
/* Check correct functioning of os_getopt */
printf ("Starting os_stdlib_getopt_001\n");
c = os_getopt(argc, argv001, "abc:");
CU_ASSERT (c == 'a');
c = os_getopt(argc, argv001, "abc:");
CU_ASSERT (c == 'b');
c = os_getopt(argc, argv001, "abc:");
CU_ASSERT (c == -1);
/* Check correct functioning of os_set_optind and os_get_optind */
printf ("Starting os_stdlib_getopt_002\n");
os_set_optind(1);
CU_ASSERT (os_get_optind() == 1);
/* Check correct functioning of os_get_optarg */
printf ("Starting os_stdlib_getopt_003\n");
c = os_getopt (argc, argv002, "c:");
CU_ASSERT (c == 'c');
CU_ASSERT (strcmp(os_get_optarg(), "foo") == 0);
c = os_getopt(argc, argv002, "c:");
CU_ASSERT (c == -1);
/* Check correct functioning of os_set_opterr, os_get_opterr and os_get_optopt */
printf ("Starting os_stdlib_getopt_004\n");
argc = 2;
os_set_optind(1);
os_set_opterr(0);
CU_ASSERT(os_get_opterr() == 0)
c = os_getopt (argc, argv003, "c:");
CU_ASSERT (c == '?');
CU_ASSERT (os_get_optopt() == 'd');
printf ("Ending os_stdlib_getopt\n");
}

321
src/os/tests/strtoll.c Normal file
View file

@ -0,0 +1,321 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
long long ll;
unsigned long long ull;
const char *str;
char *ptr;
char buf[100];
char str_llmin[100];
char str_llmax[100];
char str_ullmax[100];
char str_llrange[100];
char str_ullrange[100];
char str_xllmin[99], str_xllmax[99];
/* Really test with the maximum values supported on a platform, not some
made up number. */
long long llmin = OS_MIN_INTEGER(long long);
long long llmax = OS_MAX_INTEGER(long long);
unsigned long long ullmax = OS_MAX_INTEGER(unsigned long long);
CUnit_Suite_Initialize(os_str_convert)
{
int result = 0;
os_osInit();
printf("Run os_str_convert_Initialize\n");
(void)snprintf (str_llmin, sizeof(str_llmin), "%lld", llmin);
(void)snprintf (str_llmax, sizeof(str_llmax), "%lld", llmax);
(void)snprintf (str_llrange, sizeof(str_llrange), "%lld1", llmax);
(void)snprintf (str_ullmax, sizeof(str_ullmax), "%llu", ullmax);
(void)snprintf (str_ullrange, sizeof(str_ullrange), "%llu1", ullmax);
(void)snprintf (str_xllmin, sizeof(str_xllmin), "-%llx", llmin);
(void)snprintf (str_xllmax, sizeof(str_xllmax), "+%llx", llmax);
return result;
}
CUnit_Suite_Cleanup(os_str_convert)
{
int result = 0;
printf("Run os_str_convert_Cleanup\n");
os_osExit();
return result;
}
CUnit_Test(os_str_convert, strtoll)
{
printf ("Starting os_strtoll_001a\n");
str = "gibberish";
ll = os_strtoll(str, &ptr, 0);
CU_ASSERT (ll == 0 && ptr == str);
printf ("Starting os_strtoll_001b\n");
str = "+gibberish";
ll = os_strtoll(str, &ptr, 0);
CU_ASSERT (ll == 0 && ptr == str);
printf ("Starting os_strtoll_001c\n");
str = "-gibberish";
ll = os_strtoll(str, &ptr, 0);
CU_ASSERT (ll == 0 && ptr == str);
printf ("Starting os_strtoll_001d\n");
str = "gibberish";
ptr = NULL;
errno=0;
ll = os_strtoll(str, &ptr, 36);
CU_ASSERT (ll == 46572948005345 && errno == 0 && ptr && *ptr == '\0');
printf ("Starting os_strtoll_001e\n");
str = "1050505055";
ptr = NULL;
errno = 0;
ll = os_strtoll(str, &ptr, 37);
CU_ASSERT (ll == 0LL && errno == EINVAL && ptr == str);
printf ("Starting os_strtoll_001f\n");
str = " \t \n 1050505055";
ll = os_strtoll(str, NULL, 10);
CU_ASSERT (ll == 1050505055LL);
printf ("Starting os_strtoll_001g\n");
str = " \t \n -1050505055";
ptr = NULL;
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT (ll == -1050505055LL);
printf ("Starting os_strtoll_001h\n");
str = " \t \n - \t \n 1050505055";
ptr = NULL;
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT (ll == 0LL && ptr == str);
printf ("Starting os_strtoll_002a\n");
str = "10x";
ptr = NULL;
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT (ll == 10LL && ptr && *ptr == 'x');
printf ("Starting os_strtoll_002b\n");
str = "+10x";
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT (ll == 10LL && ptr && *ptr == 'x');
printf ("Starting os_strtoll_002c\n");
str = "-10x";
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT (ll == -10LL && ptr && *ptr == 'x');
printf ("Starting os_strtoll_002d\n");
str = (const char *)str_llmax;
ll = os_strtoll(str, NULL, 10);
CU_ASSERT (ll == llmax);
printf ("Starting os_strtoll_002e\n");
str = (const char *)str_llmin;
ll = os_strtoll(str, NULL, 10);
CU_ASSERT (ll == llmin);
printf ("Starting os_strtoll_002f\n");
str = (const char *)str_llrange;
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT (ll == llmax && *ptr == '1');
printf ("Starting os_strtoll_003a\n");
str = "0x100";
ll = os_strtoll(str, NULL, 16);
CU_ASSERT (ll == 0x100LL);
printf ("Starting os_strtoll_003b\n");
str = "0X100";
ll = os_strtoll(str, NULL, 16);
CU_ASSERT (ll == 0x100LL);
printf ("Starting os_strtoll_003c\n");
str = "0x1DEFCAB";
ll = os_strtoll(str, NULL, 16);
CU_ASSERT (ll == 0x1DEFCABLL);
printf ("Starting os_strtoll_003d\n");
str = "0x1defcab";
ll = os_strtoll(str, NULL, 16);
CU_ASSERT (ll == 0x1DEFCABLL);
printf ("Starting os_strtoll_003e\n");
str = (char *)str_xllmin;
ll = os_strtoll(str, NULL, 16);
CU_ASSERT (ll == llmin);
printf ("Starting os_strtoll_003f\n");
str = (char *)str_xllmax;
ll = os_strtoll(str, NULL, 16);
CU_ASSERT (ll == llmax);
printf ("Starting os_strtoll_003g\n");
str = "0x100";
ll = os_strtoll(str, NULL, 0);
CU_ASSERT (ll == 0x100LL);
printf ("Starting os_strtoll_003h\n");
str = "100";
ll = os_strtoll(str, NULL, 16);
CU_ASSERT (ll == 0x100LL);
printf ("Starting os_strtoll_003i\n");
/* calling os_strtoll with \"%s\" and base 10, expected result 0 */
str = "0x100";
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT (ll == 0 && ptr && *ptr == 'x');
printf ("Starting os_strtoll_003j\n");
/* calling os_strtoll with \"%s\" and base 0, expected result 256 */
str = "0x100g";
ll = os_strtoll(str, &ptr, 0);
CU_ASSERT (ll == 256 && ptr && *ptr == 'g');
printf ("Starting os_strtoll_004a\n");
str = "0100";
ll = os_strtoll(str, NULL, 0);
CU_ASSERT(ll == 64LL);
printf ("Starting os_strtoll_004b\n");
str = "0100";
ll = os_strtoll(str, NULL, 8);
CU_ASSERT(ll == 64LL);
printf ("Starting os_strtoll_004c\n");
str = "100";
ll = os_strtoll(str, NULL, 8);
CU_ASSERT(ll == 64LL);
printf ("Starting os_strtoll_004d\n");
/* calling os_strtoll with \"%s\" and base 10, expected result 100 */
str = "0100";
ll = os_strtoll(str, &ptr, 10);
CU_ASSERT(ll == 100);
printf ("Starting os_strtoll_004e\n");
/* calling os_strtoll with \"%s\" and base 0, expected result 64 */
str = "01008";
ll = os_strtoll(str, &ptr, 8);
CU_ASSERT(ll == 64LL && ptr && *ptr == '8');
printf ("Starting os_strtoll_004f\n");
str = "00001010";
ll = os_strtoll(str, NULL, 2);
CU_ASSERT(ll == 10LL);
printf ("Ending os_strtoll\n");
}
CUnit_Test(os_str_convert, strtoull)
{
printf ("Starting os_strtoull_001a\n");
str = "0xffffffffffffffff";
ull = os_strtoull(str, NULL, 0);
CU_ASSERT(ull == ullmax);
printf ("Starting os_strtoull_001b\n");
str = "-1";
ull = os_strtoull(str, NULL, 0);
CU_ASSERT(ull == ullmax);
printf ("Starting os_strtoull_001c\n");
str = "-2";
ull = os_strtoull(str, NULL, 0);
CU_ASSERT(ull == (ullmax - 1));
printf ("Ending os_strtoull\n");
}
CUnit_Test(os_str_convert, atoll)
{
printf ("Starting os_atoll_001\n");
str = "10";
ll = os_atoll(str);
CU_ASSERT(ll == 10);
printf ("Ending os_atoll\n");
}
CUnit_Test(os_str_convert, atoull)
{
printf ("Starting os_atoull_001\n");
str = "10";
ull = os_atoull(str);
CU_ASSERT(ull == 10);
printf ("Ending tc_os_atoull\n");
}
CUnit_Test(os_str_convert, lltostr)
{
printf ("Starting os_lltostr_001\n");
ll = llmax;
ptr = os_lltostr(ll, buf, 0, NULL);
CU_ASSERT(ptr == NULL);
printf ("Starting os_lltostr_002\n");
/* calling os_lltostr with %lld with buffer size of 5, expected result \"5432\" */
ll = 54321;
ptr = os_lltostr(ll, buf, 5, NULL);
CU_ASSERT(strcmp(ptr, "5432") == 0);
printf ("Starting os_lltostr_003a\n");
ll = llmax;
ptr = os_lltostr(ll, buf, sizeof(buf), NULL);
CU_ASSERT(strcmp(ptr, str_llmax) == 0);
printf ("Starting os_lltostr_003b\n");
ll = llmin;
ptr = os_lltostr(ll, buf, sizeof(buf), NULL);
CU_ASSERT(strcmp(ptr, str_llmin) == 0);
printf ("Starting os_lltostr_004\n");
ll = 1;
ptr = os_lltostr(ll, buf, sizeof(buf), NULL);
CU_ASSERT(strcmp(ptr, "1") == 0);
printf ("Starting os_lltostr_005\n");
ll = 0;
ptr = os_lltostr(ll, buf, sizeof(buf), NULL);
CU_ASSERT(strcmp(ptr, "0") == 0);
printf ("Starting os_lltostr_006\n");
ll = -1;
ptr = os_lltostr(ll, buf, sizeof(buf), NULL);
CU_ASSERT(strcmp(ptr, "-1") == 0);
printf ("Ending os_lltostr\n");
}
CUnit_Test(os_str_convert, ulltostr)
{
printf ("Starting os_ulltostr_001\n");
ull = ullmax;
ptr = os_ulltostr(ull, buf, sizeof(buf), NULL);
CU_ASSERT(strcmp(ptr, str_ullmax) == 0);
printf ("Starting os_ulltostr_002\n");
ull = 0ULL;
ptr = os_ulltostr(ull, buf, sizeof(buf), NULL);
CU_ASSERT(strcmp(ptr, "0") == 0);
printf ("Ending os_ulltostr\n");
}

842
src/os/tests/thread.c Normal file
View file

@ -0,0 +1,842 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Runner.h"
#include "os/os.h"
#include "assert.h"
#define ENABLE_TRACING 0
char arg_result[30];
int threadCalled;
int startCallbackCount;
int stopCallbackCount;
void *returnval;
static void
sleepMsec(int32_t msec)
{
os_time delay;
assert(msec > 0);
assert(msec < 1000);
delay.tv_sec = 0;
delay.tv_nsec = msec*1000*1000;
os_nanoSleep(delay);
}
uint32_t new_thread (_In_ void *args)
{
(void)snprintf (arg_result, sizeof (arg_result), "%s", (char *)args);
sleepMsec (500);
return 0;
}
static uintmax_t thread_id_from_thread;
uint32_t threadId_thread (_In_opt_ void *args)
{
if (args != NULL) {
sleepMsec (500);
}
thread_id_from_thread = os_threadIdToInteger (os_threadIdSelf ());
return (uint32_t)thread_id_from_thread; /* Truncates potentially; just used for checking passing a result-value. */
}
uint32_t get_threadExit_thread (void *args)
{
os_threadId * threadId = args;
uint32_t id;
os_result ret = os_threadWaitExit (*threadId, &id);
return id;
}
uint32_t threadIdentity_thread (_In_ void *args)
{
char *identity = args;
os_threadFigureIdentity (identity, 512);
return 0;
}
static uint32_t threadMain(_In_opt_ void *args)
{
OS_UNUSED_ARG(args);
threadCalled = 1;
sleepMsec(500);
return 0;
}
uint32_t threadMemory_thread (_In_opt_ void *args)
{
OS_UNUSED_ARG(args);
/* Check os_threadMemMalloc with success result for child thread */
printf("Starting os_threadMemMalloc_003\n");
returnval = os_threadMemMalloc (3, 100);
CU_ASSERT (returnval != NULL);
/* Check os_threadMemMalloc with fail result for child thread for index already in use */
printf("Starting os_threadMemMalloc_004\n");
returnval = os_threadMemMalloc (3, 100);
CU_ASSERT (returnval == NULL);
/* Check os_threadMemGet for child thread and non allocated index */
printf("Starting os_threadMemGet_003\n");
returnval = os_threadMemGet (OS_THREAD_WARNING);
CU_ASSERT (returnval == NULL);
/* Check os_threadMemGet for child thread and allocated index */
printf("Starting os_threadMemGet_004\n");
returnval = os_threadMemGet (3);
CU_ASSERT (returnval != NULL);
/* Check os_threadMemFree for child thread and non allocated index */
printf("Starting os_threadMemFree_003\n");
os_threadMemFree (OS_THREAD_WARNING);
returnval = os_threadMemGet (OS_THREAD_WARNING);
CU_ASSERT (returnval == NULL);
/* Check os_threadMemFree for child thread and allocated index */
printf("Starting os_threadMemFree_004\n");
os_threadMemFree (3);
returnval = os_threadMemGet (3);
CU_ASSERT (returnval == NULL);
return 0;
}
CUnit_Suite_Initialize(os_thread)
{
int result = 0;
os_osInit();
printf("Run os_thread_Initialize\n");
return result;
}
CUnit_Suite_Cleanup(os_thread)
{
int result = 0;
printf("Run os_thread_Cleanup\n");
os_osExit();
return result;
}
CUnit_Test(os_thread, create)
{
int result;
os_threadId thread_os_threadId;
os_threadAttr thread_os_threadAttr;
#ifndef WIN32
int result_int;
#endif
/* Check os_threadCreate with Success result\n\t\t
(check thread creation and check argument passing) */
printf ("Starting os_thread_create_001\n");
os_threadAttrInit (&thread_os_threadAttr);
result = os_threadCreate (&thread_os_threadId, "ThreadCreate1", &thread_os_threadAttr, &new_thread, "os_threadCreate");
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
taskDelay(1 * sysClkRateGet());
#endif
result = os_threadWaitExit (thread_os_threadId, NULL);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
result = strcmp (arg_result, "os_threadCreate");
CU_ASSERT (result == 0);
if (result == 0)
printf("Thread created and argument correctly passed.\n");
else
printf("Thread created but argument incorrectly passed.\n");
} else {
printf("os_threadCreate success, failed os_threadWaitExit.\n");
}
}
/* Check os_threadCreate with Failed result */
printf ("Starting os_thread_create_002\n");
printf ("N.A - Failure cannot be forced\n");
/* Check os_threadCreate with scheduling class SCHED_DEFAULT */
printf ("Starting s_thread_create_003\n");
os_threadAttrInit (&thread_os_threadAttr);
thread_os_threadAttr.schedClass = OS_SCHED_DEFAULT;
result = os_threadCreate (&thread_os_threadId, "ThreadCreate3", &thread_os_threadAttr, &new_thread, "os_threadCreate");
CU_ASSERT (result == os_resultSuccess);
#if !(defined _WRS_KERNEL || defined WIN32)
if (result == os_resultSuccess) {
int policy;
struct sched_param sched_param;
result_int = pthread_getschedparam (thread_os_threadId.v, &policy, &sched_param);
CU_ASSERT (result_int == 0);
if (result_int != 0) {
printf ("pthread_getschedparam failed");
} else {
CU_ASSERT (policy == SCHED_OTHER);
}
result = os_threadWaitExit (thread_os_threadId, NULL);
CU_ASSERT (result == os_resultSuccess);
} else {
printf ("os_threadCreate failed.\n");
}
#endif
/* SCHED_TIMESHARE not supported by vxworks kernel */
#ifndef _WRS_KERNEL
/* Check os_threadCreate with scheduling class SCHED_TIMESHARE */
printf ("Starting os_thread_create_004\n");
os_threadAttrInit (&thread_os_threadAttr);
thread_os_threadAttr.schedClass = OS_SCHED_TIMESHARE;
result = os_threadCreate (&thread_os_threadId, "ThreadCreate4", &thread_os_threadAttr, &new_thread, "os_threadCreate");
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifndef WIN32
int policy;
struct sched_param sched_param;
result_int = pthread_getschedparam (thread_os_threadId.v, &policy, &sched_param);
CU_ASSERT (result_int == 0);
if (result_int != 0) {
printf ("pthread_getschedparam failed");
} else {
CU_ASSERT (policy == SCHED_OTHER);
}
#endif /* WIN32 */
result = os_threadWaitExit (thread_os_threadId, NULL);
} else {
printf ("os_threadCreate failed.\n");
}
#endif
/* Check os_threadCreate with scheduling class SCHED_REALTIME */
printf ("Starting tc_os_thread_create_005\n");
#if ! defined WIN32 && ! defined _WRS_KERNEL
#ifndef VXWORKS_RTP
if (getuid() != 0 && geteuid() != 0) {
printf ("N.A - Need root privileges to do the test\n");
}
else
#endif /* VXWORKS_RTP */
{
os_threadAttrInit (&thread_os_threadAttr);
thread_os_threadAttr.schedClass = OS_SCHED_REALTIME;
thread_os_threadAttr.schedPriority = sched_get_priority_min (SCHED_FIFO);
result = os_threadCreate (&thread_os_threadId, "ThreadCreate5", &thread_os_threadAttr, &new_thread, "os_threadCreate");
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
int policy;
struct sched_param sched_param;
result_int = pthread_getschedparam (thread_os_threadId.v, &policy, &sched_param);
CU_ASSERT (result_int == 0);
if (result_int == 0) {
CU_ASSERT (policy == SCHED_FIFO);
} else {
printf ("pthread_getschedparam failed\n");
}
result = os_threadWaitExit (thread_os_threadId, NULL);
} else {
printf ("os_threadCreate failed\n");
}
}
#else /* WIN32 */
printf ("N.A - Not tested on Windows or vxworks kernel\n");
#endif
/* Check os_threadCreate with scheduling class SCHED_TIMESHARE and min priority */
printf ("Starting os_thread_create_006\n");
#ifndef WIN32
os_threadAttrInit (&thread_os_threadAttr);
thread_os_threadAttr.schedClass = OS_SCHED_TIMESHARE;
#ifdef _WRS_KERNEL
thread_os_threadAttr.schedPriority = 250;
#else
thread_os_threadAttr.schedPriority = sched_get_priority_min (SCHED_OTHER);
#endif
result = os_threadCreate (&thread_os_threadId, "ThreadCreate6", &thread_os_threadAttr, &new_thread, "os_threadCreate");
#ifdef _WRS_KERNEL
if (result == os_resultSuccess)
printf ("os_threadCreate failed - Expected failure from VXWORKS\n");
else
printf ("OS_SCHED_TIMESHARE not supported\n");
#else
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
int policy;
struct sched_param sched_param;
result_int = pthread_getschedparam (thread_os_threadId.v, &policy, &sched_param);
CU_ASSERT (result_int == 0);
if (result_int == 0) {
CU_ASSERT (sched_param.sched_priority == sched_get_priority_min (SCHED_OTHER));
} else {
printf ("pthread_getschedparam failed\n");
}
result = os_threadWaitExit (thread_os_threadId, NULL);
} else {
printf ("os_threadCreate failed.\n");
}
#endif /* _WRS_KERNEL */
#else
printf ("N.A - Not tested on Windows.\n");
#endif /* WIN32 */
/* Check os_threadCreate with scheduling class SCHED_TIMESHARE and max priority */
printf ("Starting os_thread_create_007\n");
#ifndef WIN32
os_threadAttrInit (&thread_os_threadAttr);
thread_os_threadAttr.schedClass = OS_SCHED_TIMESHARE;
#ifdef _WRS_KERNEL
thread_os_threadAttr.schedPriority = 60;
#else
thread_os_threadAttr.schedPriority = sched_get_priority_max (SCHED_OTHER);
#endif
result = os_threadCreate (&thread_os_threadId, "ThreadCreate7", &thread_os_threadAttr, &new_thread, "os_threadCreate");
#ifdef _WRS_KERNEL
if (result == os_resultSuccess) {
printf ("os_threadCreate failed - Expected failure from VXWORKS\n");
} else {
printf ("OS_SCHED_TIMESHARE not supported\n");
}
#else
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
int policy;
struct sched_param sched_param;
result_int = pthread_getschedparam (thread_os_threadId.v, &policy, &sched_param);
CU_ASSERT (result_int == 0);
if (result_int == 0) {
CU_ASSERT (sched_param.sched_priority == sched_get_priority_max (SCHED_OTHER));
} else {
printf ("pthread_getschedparam failed\n");
}
result = os_threadWaitExit (thread_os_threadId, NULL);
} else {
printf ("os_threadCreate failed.\n");
}
#endif /* _WRS_KERNEL */
#else
printf ("N.A - Not tested on Windows.\n");
#endif /* WIN32 */
/* Check os_threadCreate with scheduling class SCHED_REALTIME and min priority */
printf ("Starting os_thread_create_008\n");
#ifndef WIN32
#ifndef VXWORKS_RTP
if (getuid() != 0 && geteuid() != 0)
{
printf ("N.A - Need root privileges to do the test\n");
}
else
#endif /* VXWORKS_RTP */
{
os_threadAttrInit (&thread_os_threadAttr);
thread_os_threadAttr.schedClass = OS_SCHED_REALTIME;
#ifdef _WRS_KERNEL
thread_os_threadAttr.schedPriority = 250;
#else
thread_os_threadAttr.schedPriority = sched_get_priority_min (SCHED_FIFO);
#endif
result = os_threadCreate (&thread_os_threadId, "ThreadCreate8", &thread_os_threadAttr, &new_thread, "os_threadCreate");
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
TASK_ID id;
int pri;
STATUS status;
sleepSeconds (2);
pri = 0;
id = taskNameToId("ThreadCreate8");
status = taskPriorityGet(id,&pri);
CU_ASSERT (status == OK);
CU_ASSERT (pri == 250);
#else
int policy;
struct sched_param sched_param;
result_int = pthread_getschedparam (thread_os_threadId.v, &policy, &sched_param);
CU_ASSERT (result_int == 0);
if (result_int == 0) {
CU_ASSERT (sched_param.sched_priority == sched_get_priority_min (SCHED_FIFO));
} else {
printf ("pthread_getschedparam failed.\n");
}
#endif /* _WRS_KERNEL */
result = os_threadWaitExit (thread_os_threadId, NULL);
} else {
printf ("os_threadCreate failed.\n");
}
}
#else /* WIN32 */
printf ("N.A - Not tested on Windows\n");
#endif
/* Check os_threadCreate with scheduling class SCHED_REALTIME and max priority */
printf ("Starting os_thread_create_009\n");
#ifndef WIN32
#ifndef VXWORKS_RTP
if (getuid() != 0 && geteuid() != 0)
{
printf ("N.A - Need root privileges to do the test\n");
}
else
#endif /* VXWORKS_RTP */
{
os_threadAttrInit (&thread_os_threadAttr);
thread_os_threadAttr.schedClass = OS_SCHED_REALTIME;
#ifdef _WRS_KERNEL
thread_os_threadAttr.schedPriority = 250;
#else
thread_os_threadAttr.schedPriority = sched_get_priority_max (SCHED_FIFO);
#endif
result = os_threadCreate (&thread_os_threadId, "ThreadCreate9", &thread_os_threadAttr, &new_thread, "os_threadCreate");
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
int status;
sleepSeconds (2);
status = 0;
taskPriorityGet(taskNameToId("ThreadCreate9"),&status);
CU_ASSERT (status == 250);
#else
int policy;
struct sched_param sched_param;
result_int = pthread_getschedparam (thread_os_threadId.v, &policy, &sched_param);
CU_ASSERT (result_int == 0);
if (result_int == 0) {
CU_ASSERT (sched_param.sched_priority == sched_get_priority_max (SCHED_FIFO));
} else {
printf ("pthread_getschedparam failed.\n");
}
#endif
result = os_threadWaitExit (thread_os_threadId, NULL);
} else {
printf ("os_threadCreate failed.\n");
}
}
#else /* WIN32 */
printf ("N.A - Not tested on Windows\n");
#endif
/* Check os_threadCreate by checking scheduling scope PTHREAD_SCOPE_SYSTEM */
printf ("Starting os_thread_create_010\n");
printf ("N.A - No way to queuery scope from running thread");
/* Check os_threadCreate and stacksize sttribute */
printf ("Starting os_thread_create_011\n");
printf ("N.A - No way to queuery scope from running thread");
printf ("Ending os_thread_create\n");
}
CUnit_Test(os_thread, idself)
{
os_threadId thread_os_threadId;
os_threadAttr thread_os_threadAttr;
int result;
uint32_t result_from_thread;
/* Check if own thread ID is correctly provided */
printf ("Starting tc_os_threadIdSelf_001\n");
os_threadAttrInit (&thread_os_threadAttr);
result = os_threadCreate (&thread_os_threadId, "OwnThreadId", &thread_os_threadAttr, &threadId_thread, NULL);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
result = os_threadWaitExit (thread_os_threadId, &result_from_thread);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
uintmax_t tmp_thread_os_threadId = os_threadIdToInteger(thread_os_threadId);
CU_ASSERT (thread_id_from_thread == tmp_thread_os_threadId);
CU_ASSERT (result_from_thread == (uint32_t)tmp_thread_os_threadId);
} else {
printf ("os_threadWaitExit failed.\n");
}
} else {
printf ("os_threadCreate failed.\n");
}
printf ("Ending tc_threadIdSelf\n");
}
CUnit_Test(os_thread, join)
{
os_threadId thread_os_threadId;
os_threadAttr thread_os_threadAttr;
int result;
uint32_t result_from_thread;
/* Wait for thread to terminate and get the return value with Success result,
while thread is still running */
printf("Starting os_thread_join_001\n");
os_threadAttrInit (&thread_os_threadAttr);
result = os_threadCreate (&thread_os_threadId, "threadWaitExit", &thread_os_threadAttr, &threadId_thread, (void *)1);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
result = os_threadWaitExit (thread_os_threadId, &result_from_thread);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
CU_ASSERT (thread_id_from_thread == os_threadIdToInteger(thread_os_threadId));
CU_ASSERT (result_from_thread == (uint32_t)thread_id_from_thread);
} else {
printf ("os_threadWaitExit failed.\n");
}
} else {
printf ("os_threadCreate failed.\n");
}
/* Wait for thread to terminate and get the return value with Success result,
while thread is already terminated */
printf ("Starting os_thread_join_002\n");
os_threadAttrInit (&thread_os_threadAttr);
result = os_threadCreate (&thread_os_threadId, "threadWaitExit", &thread_os_threadAttr, &threadId_thread, NULL);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
result = os_threadWaitExit (thread_os_threadId, &result_from_thread);
CU_ASSERT(result == os_resultSuccess);
if (result == os_resultSuccess) {
CU_ASSERT (thread_id_from_thread == os_threadIdToInteger(thread_os_threadId));
CU_ASSERT (result_from_thread == (uint32_t)thread_id_from_thread);
} else {
printf ("os_threadWaitExit failed.\n");
}
} else {
printf ("os_threadCreate failed.\n");
}
/* Get thread return value with Fail result because result is already read */
printf ("Starting tc_os_thread_join_003\n");
os_threadAttrInit (&thread_os_threadAttr);
result = os_threadCreate (&thread_os_threadId, "threadWaitExit", &thread_os_threadAttr, &threadId_thread, NULL);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
result = os_threadWaitExit (thread_os_threadId, NULL);
CU_ASSERT (result == os_resultSuccess);
} else {
printf ("os_threadCreate failed.\n");
}
/* Wait for thread to terminate and get the return value by multiple threads,
one thread gets Success other Fail */
printf ("Starting tc_os_thread_join_004\n");
#ifndef WIN32
os_threadAttrInit (&thread_os_threadAttr);
{
os_threadId threadWait1;
os_result result1;
result = os_threadCreate (&thread_os_threadId, "threadToWaitFor", &thread_os_threadAttr, &threadId_thread, (void*) 1);
CU_ASSERT (result == os_resultSuccess);
result1 = os_threadCreate (&threadWait1, "waitingThread1", &thread_os_threadAttr, &get_threadExit_thread, &thread_os_threadId);
CU_ASSERT (result1 == os_resultSuccess);
if (result == os_resultSuccess && result1 == os_resultSuccess)
{
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
result1 = os_threadWaitExit (threadWait1, NULL);
if (result1 != os_resultSuccess) {
printf ("os_threadWaitExit 1 failed\n");
CU_ASSERT (result1 == os_resultSuccess);
}
} else {
printf ("os_threadCreate failed.\n");
}
}
#else /* WIN32 */
printf ("N.A - Not tested on Windows.\n");
#endif
/* Wait for thread to terminate and pass NULL for the
return value address - not interrested */
printf ("Starting tc_os_threadWaitExit_005\n");
os_threadAttrInit (&thread_os_threadAttr);
result = os_threadCreate (&thread_os_threadId, "threadWaitExit", &thread_os_threadAttr, &threadId_thread, NULL);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
result = os_threadWaitExit (thread_os_threadId, NULL);
CU_ASSERT (result == os_resultSuccess);
if (result != os_resultSuccess)
printf ("os_threadWaitExit failed.\n");
} else {
printf ("os_threadCreate failed.\n");
}
printf ("Ending tc_threadWaitExit\n");
}
CUnit_Test(os_thread, figure_identity)
{
#if !defined(_WIN32)
os_threadId thread_os_threadId;
os_threadAttr thread_os_threadAttr;
char threadId[512];
char thread_name[512];
int result;
#endif /* WIN32 */
/* Figure out the identity of the thread, where it's name is known */
printf ("Starting os_thread_figure_identity_001\n");
#ifdef WIN32
/* Untested because the identifier does not contain the name on Windows */
#else
os_threadAttrInit (&thread_os_threadAttr);
result = os_threadCreate (&thread_os_threadId, "threadFigureIdentity", &thread_os_threadAttr, &threadIdentity_thread, threadId);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
result = os_threadWaitExit (thread_os_threadId, NULL);
CU_ASSERT (result == os_resultSuccess);
if (result == os_resultSuccess) {
uintmax_t threadNumeric = 0;
#ifdef _WRS_KERNEL
int dum;
(void)sscanf (threadId, "%s (%d %d)", thread_name, &threadNumeric, &dum);
#else
(void)sscanf (threadId, "%s 0x%"SCNxMAX, thread_name, &threadNumeric);
#endif
CU_ASSERT (strcmp (thread_name, "threadFigureIdentity") == 0 && threadNumeric == os_threadIdToInteger(thread_os_threadId));
} else {
printf ("os_threadWaitExit failed.\n");
}
} else {
printf ("os_threadCreate failed.\n");
}
#endif /* WIN32 */
/* Figure out the identity of the thread, where it's name is unknown */
printf ("Starting os_thread_figure_identity_002\n");
#if (defined _WRS_KERNEL || defined WIN32)
{
char threadId[512];
int threadNumeric;
os_threadFigureIdentity (threadId, sizeof(threadId));
#if defined WIN32
(void)sscanf (threadId, "%"PRIx32, &threadNumeric);
#else /* VXWORKS */
(void)sscanf (index(threadId,'(') + 1, "%"PRIx32, &threadNumeric);
#endif
CU_ASSERT (threadNumeric == os_threadIdToInteger(os_threadIdSelf()));
}
#else
{
char threadId[512];
uintptr_t threadNumeric;
os_threadFigureIdentity (threadId, sizeof(threadId));
#ifdef WIN32
(void)sscanf (threadId, "%"PRIxPTR, &threadNumeric);
#else
(void)sscanf (threadId, "%"PRIxPTR, &threadNumeric);
#endif
#ifndef INTEGRITY
CU_ASSERT (threadNumeric == (uintptr_t)os_threadIdToInteger(os_threadIdSelf()));
#endif
}
#endif
/* Figure out the identity of the thread, check the return parameter */
printf ("Starting os_thread_figure_identity_003\n");
#ifdef _WRS_KERNEL
{
char threadId[512];
char threadIdString[512];
int threadNumeric;
int threadIdLen;
snprintf (threadIdString, sizeof(threadIdString), "%s (%d %d)", taskName(taskIdSelf()),os_threadIdSelf(),taskIdSelf());
threadIdLen = os_threadFigureIdentity (threadId, sizeof(threadId));
CU_ASSERT (threadIdLen == strlen(threadIdString));
}
#else
{
char threadId[512];
char threadIdString[512];
unsigned int threadIdLen;
(void)snprintf (threadIdString, sizeof(threadIdString), "0x%"PRIxMAX, os_threadIdToInteger(os_threadIdSelf()));
threadIdLen = os_threadFigureIdentity (threadId, sizeof(threadId));
CU_ASSERT (threadIdLen == strlen(threadIdString));
}
#endif
printf ("Ending os_thread_figure_identity\n");
}
CUnit_Test(os_thread, attr_init)
{
os_threadAttr thread_os_threadAttr;
/* Check default attributes: schedClass */
printf ("Starting os_thread_attr_init_001\n");
os_threadAttrInit (&thread_os_threadAttr);
CU_ASSERT (thread_os_threadAttr.schedClass == OS_SCHED_DEFAULT);
/* Check default attributes: schedPriority */
printf ("Starting os_thread_attr_init_002\n");
#if !(defined _WRS_KERNEL || defined WIN32 || defined __APPLE__)
os_threadAttrInit (&thread_os_threadAttr);
CU_ASSERT (thread_os_threadAttr.schedPriority == ((sched_get_priority_min (SCHED_OTHER) + sched_get_priority_max (SCHED_OTHER)) / 2 ));
#else
/* OSX priorities are different (min=15 and max=47) */
printf ("N.A - Not tested for VxWorks, Windows and OSX\n");
#endif
/* Check default attributes: stacksize */
printf ("Starting os_thread_attr_init_003\n");
os_threadAttrInit (&thread_os_threadAttr);
CU_ASSERT (thread_os_threadAttr.stackSize == 0);
printf ("Ending os_thread_attr_init\n");
}
CUnit_Test(os_thread, memmalloc)
{
/* Check os_threadMemMalloc with success result for main thread */
printf ("Starting os_thread_memmalloc_001\n");
returnval = os_threadMemMalloc (3, 100);
CU_ASSERT (returnval != NULL);
/* Check os_threadMemMalloc with fail result for main thread
for index already in use */
printf ("Starting os_thread_memmalloc_002\n");
returnval = os_threadMemMalloc (3, 100);
CU_ASSERT (returnval == NULL);
/* Check os_threadMemMalloc with fail result for main thread
for index < 0 */
printf ("Starting os_thread_memmalloc_003\n");
returnval = os_threadMemMalloc (-1, 100);
CU_ASSERT (returnval == NULL);
/* Check os_threadMemMalloc with fail result for main thread
for index >= OS_THREAD_MEM_ARRAY_SIZE */
printf ("Starting os_thread_memmalloc_004\n");
returnval = os_threadMemMalloc (OS_THREAD_MEM_ARRAY_SIZE, 100);
CU_ASSERT (returnval == NULL);
printf ("Ending tc_thread_memmalloc\n");
}
CUnit_Test(os_thread, memget)
{
/* Check os_threadMemGet for main thread and non allocated index */
printf ("Starting os_thread_memget_001\n");
returnval = os_threadMemGet (OS_THREAD_WARNING);
CU_ASSERT (returnval == NULL);
/* Check os_threadMemGet for main thread and allocated index */
printf ("Starting os_thread_memget_002\n");
/* FIXME: This test is no good. Apart from the fact that a valid thread
memory index should be used (os_threadMemoryIndex), this also
does not work if the test is executed in a self-contained
manner using the CUnit runner. For now just work around it by
first doing a os_threadMemMalloc. */
(void)os_threadMemMalloc(3, 100);
returnval = os_threadMemGet (3);
CU_ASSERT (returnval != NULL);
printf ("Ending tc_thread_memget\n");
}
CUnit_Test(os_thread, memfree)
{
/* Check os_threadMemFree for main thread and non allocated index */
printf ("Starting os_thread_memfree_001\n");
os_threadMemFree (OS_THREAD_WARNING);
returnval = os_threadMemGet (OS_THREAD_WARNING);
CU_ASSERT (returnval == NULL);
/* Check os_threadMemFree for main thread and allocated index */
printf ("Starting os_thread_memfree_002\n");
/* FIXME: See comments on memget test. */
(void)os_threadMemMalloc(3, 100);
returnval = os_threadMemGet(3);
CU_ASSERT(returnval != NULL);
os_threadMemFree (3);
returnval = os_threadMemGet (3);
CU_ASSERT (returnval == NULL);
printf ("Ending os_thread_memfree\n");
}
CUnit_Test(os_thread, module)
{
os_threadId tid;
os_threadAttr tattr;
os_result res;
os_threadAttrInit (&tattr);
/* Run the following tests for child thread */
res = os_threadCreate (&tid, "ThreadMemory", &tattr, &threadMemory_thread, NULL);
CU_ASSERT_EQUAL(res, os_resultSuccess);
if (res == os_resultSuccess) {
#ifdef _WRS_KERNEL
sleepSeconds(1);
#endif
res = os_threadWaitExit (tid, NULL);
CU_ASSERT_EQUAL(res, os_resultSuccess);
}
}

View file

@ -0,0 +1,283 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include "os/os.h"
#include "CUnit/Runner.h"
CUnit_Suite_Initialize(os_thread_cleanup)
{
os_osInit();
return 0;
}
CUnit_Suite_Cleanup(os_thread_cleanup)
{
os_osExit();
return 0;
}
#define THREAD_RESET_1 (1<<0)
#define THREAD_RESET_2 (1<<1)
#define THREAD_RUN_OFFSET (4)
#define THREAD_RUN_1 (1<<(THREAD_RUN_OFFSET))
#define THREAD_RUN_2 (1<<(THREAD_RUN_OFFSET + 1))
struct thread_argument {
int flags;
int pop;
int one;
int two;
int executed;
int cancelled;
int block;
os_mutex *mutex;
os_threadId thread;
};
static struct thread_argument *
make_thread_argument(
int flags, int pop, int one, int two)
{
struct thread_argument *targ = os_malloc(sizeof(*targ));
memset(targ, 0, sizeof(*targ));
targ->flags = flags;
targ->pop = pop;
targ->one = one;
targ->two = two;
return targ;
}
static void
reset_one(
void *arg)
{
struct thread_argument *targ = (struct thread_argument *)arg;
targ->one = 0;
targ->executed++;
}
static void
reset_two(
void *arg)
{
struct thread_argument *targ = (struct thread_argument *)arg;
targ->two = 0;
targ->executed++;
}
static uint32_t
thread_main(
void *arg)
{
int pushed = 0;
int popped = 0;
int execute = 0;
struct thread_argument *targ = (struct thread_argument *)arg;
if (targ->flags & THREAD_RESET_1) {
os_threadCleanupPush(&reset_one, arg);
pushed++;
}
if (targ->flags & THREAD_RESET_2) {
os_threadCleanupPush(&reset_two, arg);
pushed++;
}
assert(targ->pop <= pushed);
if (targ->block) {
os_mutexLock(targ->mutex);
}
while (popped < targ->pop) {
execute = 1 << (THREAD_RUN_OFFSET + (targ->pop - (popped + 1)));
os_threadCleanupPop(targ->flags & execute);
targ->cancelled++;
popped++;
}
if (targ->block) {
os_mutexUnlock(targ->mutex);
}
return 0;
}
static void
setup(
struct thread_argument *targ)
{
os_result res;
os_threadId tid;
os_threadAttr tattr;
uint32_t tres = 0;
os_threadAttrInit(&tattr);
res = os_threadCreate(&tid, "", &tattr, &thread_main, (void *)targ);
CU_ASSERT_EQUAL_FATAL(res, os_resultSuccess);
targ->thread = tid;
if (!targ->block) {
res = os_threadWaitExit(tid, &tres);
CU_ASSERT_EQUAL_FATAL(res, os_resultSuccess);
}
}
/* verify the cleanup routine is called */
CUnit_Test(os_thread_cleanup, push_one)
{
int flags = THREAD_RESET_1;
struct thread_argument *targ = make_thread_argument(flags, 0, 1, 2);
setup(targ);
CU_ASSERT_EQUAL(targ->one, 0);
CU_ASSERT_EQUAL(targ->two, 2);
CU_ASSERT_EQUAL(targ->executed, 1);
CU_ASSERT_EQUAL(targ->cancelled, 0);
free(targ);
}
/* verify all cleanup routines are called if multiple are registered */
CUnit_Test(os_thread_cleanup, push_two)
{
int flags = THREAD_RESET_1 | THREAD_RESET_2;
struct thread_argument *targ = make_thread_argument(flags, 0, 1, 2);
setup(targ);
CU_ASSERT_EQUAL(targ->one, 0);
CU_ASSERT_EQUAL(targ->two, 0);
CU_ASSERT_EQUAL(targ->executed, 2);
CU_ASSERT_EQUAL(targ->cancelled, 0);
free(targ);
}
/* verify the first cleanup routine is still called if second got popped */
CUnit_Test(os_thread_cleanup, push_two_pop_one_no_exec)
{
int flags = THREAD_RESET_1 | THREAD_RESET_2;
struct thread_argument *targ = make_thread_argument(flags, 1, 1, 2);
setup(targ);
CU_ASSERT_EQUAL(targ->one, 0);
CU_ASSERT_EQUAL(targ->two, 2);
CU_ASSERT_EQUAL(targ->executed, 1);
CU_ASSERT_EQUAL(targ->cancelled, 1);
free(targ);
}
CUnit_Test(os_thread_cleanup, push_two_pop_one_exec)
{
int flags = THREAD_RESET_1 | THREAD_RESET_2 | THREAD_RUN_1;
struct thread_argument *targ = make_thread_argument(flags, 1, 1, 2);
setup(targ);
CU_ASSERT_EQUAL(targ->one, 0);
CU_ASSERT_EQUAL(targ->two, 0);
CU_ASSERT_EQUAL(targ->executed, 2);
CU_ASSERT_EQUAL(targ->cancelled, 1);
free(targ);
}
/* verify no cleanup routines are called if all got popped */
CUnit_Test(os_thread_cleanup, push_two_pop_two_no_exec)
{
int flags = THREAD_RESET_1 | THREAD_RESET_2;
struct thread_argument *targ = make_thread_argument(flags, 2, 1, 2);
setup(targ);
CU_ASSERT_EQUAL(targ->one, 1);
CU_ASSERT_EQUAL(targ->two, 2);
CU_ASSERT_EQUAL(targ->executed, 0);
CU_ASSERT_EQUAL(targ->cancelled, 2);
free(targ);
}
CUnit_Test(os_thread_cleanup, push_two_pop_two_exec_one)
{
int flags = THREAD_RESET_1 | THREAD_RESET_2 | THREAD_RUN_1;
struct thread_argument *targ = make_thread_argument(flags, 2, 1, 2);
setup(targ);
CU_ASSERT_EQUAL(targ->one, 0);
CU_ASSERT_EQUAL(targ->two, 2);
CU_ASSERT_EQUAL(targ->executed, 1);
CU_ASSERT_EQUAL(targ->cancelled, 2);
free(targ);
}
CUnit_Test(os_thread_cleanup, push_two_pop_two_exec_both)
{
int flags = THREAD_RESET_1 | THREAD_RESET_2 | THREAD_RUN_1 | THREAD_RUN_2;
struct thread_argument *targ = make_thread_argument(flags, 2, 1, 2);
setup(targ);
CU_ASSERT_EQUAL(targ->one, 0);
CU_ASSERT_EQUAL(targ->two, 0);
CU_ASSERT_EQUAL(targ->executed, 2);
CU_ASSERT_EQUAL(targ->cancelled, 2);
free(targ);
}
CUnit_Test(os_thread_cleanup, no_interference)
{
int flags = THREAD_RESET_1 | THREAD_RESET_2;
struct thread_argument *targ1 = make_thread_argument(flags, 0, 1, 2);
struct thread_argument *targ2 = make_thread_argument(flags, 2, 1, 2);
os_mutex mutex1, mutex2;
os_mutexInit(&mutex1);
os_mutexInit(&mutex2);
os_mutexLock(&mutex1);
os_mutexLock(&mutex2);
targ1->mutex = &mutex1;
targ1->block = 1;
targ2->mutex = &mutex2;
targ2->block = 1;
setup(targ1);
setup(targ2);
/* ensure thread 2 pops it's cleanup routines while thread 1 blocks */
os_mutexUnlock(&mutex2);
os_threadWaitExit(targ2->thread, NULL);
CU_ASSERT_EQUAL(targ2->one, 1);
CU_ASSERT_EQUAL(targ2->two, 2);
CU_ASSERT_EQUAL(targ2->executed, 0);
CU_ASSERT_EQUAL(targ2->cancelled, 2);
/* instruct thread 1 to continue */
os_mutexUnlock(&mutex1);
os_threadWaitExit(targ1->thread, NULL);
CU_ASSERT_EQUAL(targ1->one, 0);
CU_ASSERT_EQUAL(targ1->two, 0);
CU_ASSERT_EQUAL(targ1->executed, 2);
CU_ASSERT_EQUAL(targ1->cancelled, 0);
os_mutexDestroy(&mutex1);
os_mutexDestroy(&mutex2);
free(targ1);
free(targ2);
}