diff options
author | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
---|---|---|
committer | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
commit | ef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch) | |
tree | dee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/pal/tests/palsuite/threading/WaitForSingleObject | |
download | coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2 coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip |
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/pal/tests/palsuite/threading/WaitForSingleObject')
19 files changed, 1666 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt new file mode 100644 index 0000000000..94bd51caa6 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +add_subdirectory(test1) +add_subdirectory(WFSOExMutexTest) +add_subdirectory(WFSOExSemaphoreTest) +add_subdirectory(WFSOExThreadTest) +add_subdirectory(WFSOMutexTest) +add_subdirectory(WFSOProcessTest) +add_subdirectory(WFSOSemaphoreTest) +add_subdirectory(WFSOThreadTest) + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt new file mode 100644 index 0000000000..611e1f7a9c --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + WFSOExMutexTest.c +) + +add_executable(paltest_waitforsingleobject_wfsoexmutextest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoexmutextest CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsoexmutextest + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c new file mode 100644 index 0000000000..35ecb1ee5f --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.c @@ -0,0 +1,217 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*===================================================================== +** +** Source: WFSOExMutex.c +** +** Purpose: Tests a child thread in the middle of a +** WaitForSingleObjectEx call will be interrupted by QueueUserAPC +** if the alert flag was set. +** +** +**===================================================================*/ + +#include <palsuite.h> + +/*Based on SleepEx/test2 */ + +const int ChildThreadWaitTime = 4000; +const int InterruptTime = 2000; +const int AcceptableDelta = 100; + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI WaiterProc(LPVOID lpParameter); + +DWORD ThreadWaitDelta; +HANDLE hMutex; + + + +int __cdecl main( int argc, char **argv ) +{ + int ret=0; + + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + /* + The state of a mutex object is signaled when it is not owned by any thread. + The creating thread can use the bInitialOwner flag to request immediate ownership + of the mutex. Otherwise, a thread must use one of the wait functions to request + ownership. When the mutex's state is signaled, one waiting thread is granted + ownership, the mutex's state changes to nonsignaled, and the wait function returns. + Only one thread can own a mutex at any given time. The owning thread uses the + ReleaseMutex function to release its ownership. + */ + + /* Create a mutex that is not in the signalled state */ + hMutex = CreateMutex( NULL, //No security attributes + TRUE, //Iniitally owned + "SomeMutex"); //Name of mutex + + if (hMutex == NULL) + { + Fail("Failed to create mutex! GetLastError returned %d.\n", + GetLastError()); + } + /* + * Check that Queueing an APC in the middle of a wait does interrupt + * it, if it's in an alertable state. + */ + + RunTest(TRUE); + if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and get interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + InterruptTime, ThreadWaitDelta, AcceptableDelta); + } + + + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt + * it, if it is not in an alertable state. + */ + RunTest(FALSE); + if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and not be interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta); + } + + + + //Release Mutex + ret = ReleaseMutex(hMutex); + if (0==ret) + { + Fail("Unable to Release Mutex!\n" + "GetLastError returned %d\n", GetLastError()); + } + + //Close Mutex Handle + ret = CloseHandle(hMutex); + if (!ret) + { + Fail("Unable to close handle to Mutex!\n" + "GetLastError returned %d\n", GetLastError()); + } + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + + HANDLE hThread = 0; + DWORD dwThreadId = 0; + + int ret=0; + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaiterProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + + + Sleep(InterruptTime); + + ret = QueueUserAPC(APCFunc, hThread, 0); + + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", + GetLastError()); + } + + ret = WaitForSingleObject(hThread, INFINITE); + + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + GetLastError()); + } + + + if (0==CloseHandle(hThread)) + { + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt the wait*/ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ +} + +/* Entry Point for child thread. */ +DWORD PALAPI WaiterProc(LPVOID lpParameter) +{ + DWORD OldTickCount; + DWORD NewTickCount; + BOOL Alertable; + DWORD ret; + + Alertable = (BOOL) lpParameter; + + OldTickCount = GetTickCount(); + + ret = WaitForSingleObjectEx( hMutex, + ChildThreadWaitTime, + Alertable); + + NewTickCount = GetTickCount(); + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != WAIT_TIMEOUT) + { + Fail("WaitForSingleObjectEx did not timeout.\n" + "Expected return of WAIT_TIMEOUT, got %d.\n", ret); + } + + /* + * Check for DWORD wraparound + */ + if (OldTickCount>NewTickCount) + { + OldTickCount -= NewTickCount+1; + NewTickCount = 0xFFFFFFFF; + } + ThreadWaitDelta = NewTickCount - OldTickCount; + + return 0; +} + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt new file mode 100644 index 0000000000..fc49935fda --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + WFSOExSemaphoreTest.c +) + +add_executable(paltest_waitforsingleobject_wfsoexsemaphoretest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoexsemaphoretest CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsoexsemaphoretest + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c new file mode 100644 index 0000000000..ad8697c52c --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExSemaphoreTest/WFSOExSemaphoreTest.c @@ -0,0 +1,188 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*===================================================================== +** +** Source: WFSOExSemaphore.c +** +** Purpose: Tests a child thread in the middle of a +** WaitForSingleObjectEx call will be interrupted by QueueUserAPC +** if the alert flag was set. +** +** +**===================================================================*/ + +#include <palsuite.h> + +/*Based on SleepEx/test2 */ + +const int ChildThreadWaitTime = 4000; +const int InterruptTime = 2000; +const int AcceptableDelta = 100; + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI WaiterProc(LPVOID lpParameter); + +DWORD ThreadWaitDelta; + +int __cdecl main( int argc, char **argv ) +{ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + /* + * Check that Queueing an APC in the middle of a wait does interrupt + * it, if it's in an alertable state. + */ + + RunTest(TRUE); + if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and get interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + InterruptTime, ThreadWaitDelta, AcceptableDelta); + } + + + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt + * it, if it is not in an alertable state. + */ + RunTest(FALSE); + if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and not be interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta); + } + + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaiterProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Sleep(InterruptTime); + + ret = QueueUserAPC(APCFunc, hThread, 0); + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", + GetLastError()); + } + + ret = WaitForSingleObject(hThread, INFINITE); + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + GetLastError()); + } + + if (0==CloseHandle(hThread)) + { + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt the wait*/ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ +} + +/* Entry Point for child thread. */ +DWORD PALAPI WaiterProc(LPVOID lpParameter) +{ + HANDLE hSemaphore; + DWORD OldTickCount; + DWORD NewTickCount; + BOOL Alertable; + DWORD ret; + + /* Create a semaphore that is not in the signalled state */ + hSemaphore = CreateSemaphoreW(NULL, 0, 1, NULL); + + if (hSemaphore == NULL) + { + Fail("Failed to create semaphore! GetLastError returned %d.\n", + GetLastError()); + } + + Alertable = (BOOL) lpParameter; + + OldTickCount = GetTickCount(); + + ret = WaitForSingleObjectEx( hSemaphore, + ChildThreadWaitTime, + Alertable); + + NewTickCount = GetTickCount(); + + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != WAIT_TIMEOUT) + { + Fail("WaitForSingleObjectEx did not timeout.\n" + "Expected return of WAIT_TIMEOUT, got %d.\n", ret); + } + + + /* + * Check for DWORD wraparound + */ + if (OldTickCount>NewTickCount) + { + OldTickCount -= NewTickCount+1; + NewTickCount = 0xFFFFFFFF; + } + + ThreadWaitDelta = NewTickCount - OldTickCount; + + ret = CloseHandle(hSemaphore); + if (!ret) + { + Fail("Unable to close handle to semaphore!\n" + "GetLastError returned %d\n", GetLastError()); + } + + return 0; +} + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt new file mode 100644 index 0000000000..788dc36fbf --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + WFSOExThreadTest.c +) + +add_executable(paltest_waitforsingleobject_wfsoexthreadtest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoexthreadtest CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsoexthreadtest + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c new file mode 100644 index 0000000000..b7b035819a --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.c @@ -0,0 +1,208 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*===================================================================== +** +** Source: WFSOExThreadTest.c +** +** Purpose: Tests a child thread in the middle of a +** WaitForSingleObjectEx call will be interrupted by QueueUserAPC +** if the alert flag was set. +** +** +**===================================================================*/ + +#include <palsuite.h> + +/*Based on SleepEx/test2 */ + +const int ChildThreadWaitTime = 4000; +const int InterruptTime = 2000; +const int AcceptableDelta = 100; + +void RunTest(BOOL AlertThread); +VOID PALAPI APCFunc(ULONG_PTR dwParam); +DWORD PALAPI WaiterProc(LPVOID lpParameter); +void WorkerThread(void); + +DWORD ThreadWaitDelta; + +int __cdecl main( int argc, char **argv ) +{ + if (0 != (PAL_Initialize(argc, argv))) + { + return FAIL; + } + + /* + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that + can make the first wait slighty longer, potentially going above the + acceptable delta for this test. Let's add a dummy wait to preinitialize + internal structures + */ + Sleep(100); + + /* + * Check that Queueing an APC in the middle of a wait does interrupt + * it, if it's in an alertable state. + */ + + RunTest(TRUE); + if (abs(ThreadWaitDelta - InterruptTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and get interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + InterruptTime, ThreadWaitDelta, AcceptableDelta); + } + + + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt + * it, if it is not in an alertable state. + */ + RunTest(FALSE); + if (abs(ThreadWaitDelta - ChildThreadWaitTime) > AcceptableDelta) + { + Fail("Expected thread to wait for %d ms (and not be interrupted).\n" + "Thread waited for %d ms! (Acceptable delta: %d)\n", + ChildThreadWaitTime, ThreadWaitDelta, AcceptableDelta); + } + + + PAL_Terminate(); + return PASS; +} + +void RunTest(BOOL AlertThread) +{ + HANDLE hThread = 0; + DWORD dwThreadId = 0; + int ret; + + //Create thread + hThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WaiterProc, + (LPVOID) AlertThread, + 0, + &dwThreadId); + + if (hThread == NULL) + { + Fail("ERROR: Was not able to create the thread to test!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Sleep(InterruptTime); + + ret = QueueUserAPC(APCFunc, hThread, 0); + if (ret == 0) + { + Fail("QueueUserAPC failed! GetLastError returned %d\n", + GetLastError()); + } + + + ret = WaitForSingleObject(hThread, INFINITE); + if (ret == WAIT_FAILED) + { + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + GetLastError()); + } + + if (0==CloseHandle(hThread)) + { + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +} + +/* Function doesn't do anything, just needed to interrupt the wait*/ +VOID PALAPI APCFunc(ULONG_PTR dwParam) +{ +} + +/* Entry Point for child thread. */ +DWORD PALAPI WaiterProc(LPVOID lpParameter) +{ + HANDLE hWaitThread; + DWORD OldTickCount; + DWORD NewTickCount; + BOOL Alertable; + DWORD ret; + DWORD dwThreadId = 0; + +/* +When a thread terminates, the thread object attains a signaled state, +satisfying any threads that were waiting on the object. +*/ + +/* Create a thread that does not return immediately to maintain a non signaled test*/ + hWaitThread = CreateThread( NULL, + 0, + (LPTHREAD_START_ROUTINE)WorkerThread, + NULL, + 0, + &dwThreadId); + + if (hWaitThread == NULL) + { + Fail("ERROR: Was not able to create worker thread to wait on!\n" + "GetLastError returned %d\n", GetLastError()); + } + + Alertable = (BOOL) lpParameter; + + OldTickCount = GetTickCount(); + + ret = WaitForSingleObjectEx( hWaitThread, + ChildThreadWaitTime, + Alertable); + + NewTickCount = GetTickCount(); + + + if (Alertable && ret != WAIT_IO_COMPLETION) + { + Fail("Expected the interrupted wait to return WAIT_IO_COMPLETION.\n" + "Got %d\n", ret); + } + else if (!Alertable && ret != WAIT_TIMEOUT) + { + Fail("WaitForSingleObjectEx did not timeout.\n" + "Expected return of WAIT_TIMEOUT, got %d.\n", ret); + } + + /* + * Check for DWORD wraparound + */ + if (OldTickCount>NewTickCount) + { + OldTickCount -= NewTickCount+1; + NewTickCount = 0xFFFFFFFF; + } + + ThreadWaitDelta = NewTickCount - OldTickCount; + + ret = CloseHandle(hWaitThread); + if (!ret) + { + Fail("Unable to close handle to Thread!\n" + "GetLastError returned %d\n", GetLastError()); + } + + return 0; +} + + +void WorkerThread(void) +{ + + //Make the worker thread sleep to test WFSOEx Functionality + + Sleep(2*ChildThreadWaitTime); +} + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt new file mode 100644 index 0000000000..302556240a --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + WFSOMutexTest.c +) + +add_executable(paltest_waitforsingleobject_wfsomutextest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsomutextest CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsomutextest + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c new file mode 100644 index 0000000000..f28d1a5a00 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOMutexTest/WFSOMutexTest.c @@ -0,0 +1,186 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*============================================================ +** +** Source: WFSOMutexTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create Mutex Object +** Create Two Threads, Each Threads does WFSO for the Mutex Object +** Increments Counter +** Releases Mutex +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include <palsuite.h> + + +#define NUMBER_OF_WORKER_THREADS 2 + +//Declaring Variables +HANDLE hMutex = NULL; +unsigned int globalcounter =0; +int testReturnCode = PASS; + +//Declaring Function Prototypes +DWORD WFSOMutexTest(LPVOID params); +void incrementCounter(void); + + + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + int i =0; + + // 2 dimensional array to hold thread handles for each worker thread + HANDLE hThread[NUMBER_OF_WORKER_THREADS]; + DWORD dwThreadId=0; + int returnCode = 0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Create Mutex + hMutex = CreateMutex( + NULL, // no security attributes + FALSE, // initially not owned + "MutexToProtectGlobalCounter"); // name of mutex + + //Check for Mutex Creation + + if (hMutex == NULL) + { + Fail("Create Mutex Failed, GetLastError: %d\n", GetLastError()); + } + + + //Spawn 2 worker threads + for (i=0;i<NUMBER_OF_WORKER_THREADS;i++) + { + //Create Thread + + hThread[i] = CreateThread( + NULL, + 0, + WFSOMutexTest, + NULL, + 0, + &dwThreadId); + + if ( NULL == hThread[i] ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + } + + /* Test running */ + returnCode = WaitForMultipleObjects( NUMBER_OF_WORKER_THREADS, hThread, TRUE, 5000); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) returned %d, and GetLastError value is %d\n", returnCode, GetLastError()); + testReturnCode = FAIL; + } + +//Close thread handles +for (i=0;i<NUMBER_OF_WORKER_THREADS;i++) + { + + if (0==CloseHandle(hThread[i])) + { + Trace("Could not Close thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + } + +//Close Mutex Handle +if (0==CloseHandle(hMutex)) + { + Trace("Could not close mutex handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + +PAL_TerminateEx(testReturnCode); +return ( testReturnCode ); + +} + + +void incrementCounter(void) +{ + if (INT_MAX == globalcounter) + { + globalcounter = 0; + } + + globalcounter++; + Trace("Global Counter Value: %d \n", globalcounter); +} + + +DWORD WFSOMutexTest(LPVOID params) +{ + + DWORD dwWaitResult; + + // Request ownership of mutex. + + dwWaitResult = WaitForSingleObject( + hMutex, // handle to mutex + 5000L); // five-second time-out interval + + switch (dwWaitResult) + { + // The thread got mutex ownership. + case WAIT_OBJECT_0: + { + + incrementCounter(); + + //Release ownership of the mutex object. + if (! ReleaseMutex(hMutex)) + { + Fail ( "ReleaseMutex() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + break; + } + + // Cannot get mutex ownership due to time-out. + case WAIT_TIMEOUT: + { + Fail ( "Cannot get mutex ownership due to time-out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned mutex object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned mutex object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + } + + return 1; +} + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt new file mode 100644 index 0000000000..33b8ef0ed6 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(TESTSOURCES + WFSOProcessTest.c +) + +add_executable(paltest_waitforsingleobject_wfsoprocesstest + ${TESTSOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoprocesstest CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsoprocesstest + pthread + rt + m + CoreClrPal +) + + +set(HELPERSOURCES + ChildProcess.c +) + +add_executable(paltest_waitforsingleobject_wfsoprocesstest_child + ${HELPERSOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsoprocesstest_child CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsoprocesstest_child + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.c new file mode 100644 index 0000000000..b1592d437e --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/ChildProcess.c @@ -0,0 +1,51 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*============================================================ +** +** Source: ChildProcess.c +** +** Purpose: Dummy Process which does some work on which the Main Test case waits +** +** + +** +**=========================================================*/ + + + +#include <palsuite.h> + +int __cdecl main(int argc, char **argv) +{ + +//Declare local variables +int i =0; + + + +//Initialize PAL +if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + +//Do some work +for (i=0; i<100000; i++); + +Trace("Counter Value was incremented to %d \n ",i); + +PAL_Terminate(); +return ( PASS ); + +} + + + + + + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.c new file mode 100644 index 0000000000..71bc4069b7 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOProcessTest/WFSOProcessTest.c @@ -0,0 +1,120 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*============================================================ +** +** Source: WFSOProcessTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create One Process and do some work +** Use WFSO For the Process to finish +** +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include <palsuite.h> + +int __cdecl main(int argc, char **argv) +{ + +//Declare local variables +STARTUPINFO si; +PROCESS_INFORMATION pi; + +DWORD dwWaitResult=0; + +//Initialize PAL +if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + +ZeroMemory( &si, sizeof(si) ); +si.cb = sizeof(si); +ZeroMemory( &pi, sizeof(pi) ); + +// Start the child process. +if( !CreateProcess( NULL, // No module name (use command line). + "childprocess", // Command line. + NULL, // Process handle not inheritable. + NULL, // Thread handle not inheritable. + FALSE, // Set handle inheritance to FALSE. + 0, // No creation flags. + NULL, // Use parent's environment block. + NULL, // Use parent's starting directory. + &si, // Pointer to STARTUPINFO structure. + &pi ) // Pointer to PROCESS_INFORMATION structure. +) + +{ +Fail ( "Create Process Failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); +} + +// Wait until child process exits. + dwWaitResult = WaitForSingleObject( pi.hProcess, INFINITE ); +switch (dwWaitResult) + { + // The Process wait was successful + case WAIT_OBJECT_0: + { + + Trace("Wait for Process was successful\n"); + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned process object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned Process object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + //Error condition + case WAIT_FAILED: + { + Fail ( "Wait for Process Failed. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + +} + + + +// Close process handle +if (0==CloseHandle(pi.hProcess)) + { + Trace("Could not close process handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + + +PAL_Terminate(); +return ( PASS ); + +} + + + + + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt new file mode 100644 index 0000000000..db8c58d083 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + WFSOSemaphoreTest.c +) + +add_executable(paltest_waitforsingleobject_wfsosemaphoretest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsosemaphoretest CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsosemaphoretest + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c new file mode 100644 index 0000000000..ca66d827b6 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOSemaphoreTest/WFSOSemaphoreTest.c @@ -0,0 +1,184 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*============================================================ +** +** Source: WFSOMutexTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create Semaphore Object +** Create Two Threads, Each Threads does WFSO for the Semaphore Object +** Increments Counter +** Releases Semaphore +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include <palsuite.h> + + +#define NUMBER_OF_WORKER_THREADS 2 + + +//Declaring Variables +HANDLE hSemaphore = NULL; +unsigned int globalcounter =0; +int testReturnCode = PASS; + +//Declaring Function Prototypes +DWORD WFSOSemaphoreTest(LPVOID params); +void incrementCounter(void); + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + int i =0; + int cMax = 2; + + int returnCode = 0; + + // 2 dimensional array to hold thread handles for each worker thread + HANDLE hThread[NUMBER_OF_WORKER_THREADS]; + DWORD dwThreadId=0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + //Create Semaphore + hSemaphore = CreateSemaphore( + NULL, // no security attributes + cMax, // initial count + cMax, // maximum count + NULL); // unnamed semaphore + + if (hSemaphore == NULL) + { + // Check for error. + Fail("Create Semaphore Failed, GetLastError: %d\n", GetLastError()); + } + + + + //Spawn 2 worker threads + for (i=0;i<NUMBER_OF_WORKER_THREADS;i++) + { + //Create Thread + + hThread[i] = CreateThread( + NULL, + 0, + WFSOSemaphoreTest, + NULL, + 0, + &dwThreadId); + + if ( NULL == hThread[i] ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + } + + + /* Test running */ + returnCode = WaitForMultipleObjects( NUMBER_OF_WORKER_THREADS, hThread, TRUE, 5000); + if( WAIT_OBJECT_0 != returnCode ) + { + Trace("Wait for Object(s) returned %d, and GetLastError value is %d\n", returnCode, GetLastError()); + testReturnCode = FAIL; + } + +//Close thread handles +for (i=0;i<NUMBER_OF_WORKER_THREADS;i++) + { + + if (0==CloseHandle(hThread[i])) + { + Trace("Could not Close thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + } + +//Close Semaphore Handle +if (0==CloseHandle(hSemaphore)) + { + Trace("Could not close semaphore handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + +PAL_TerminateEx(testReturnCode); +return ( testReturnCode ); + +} + + +void incrementCounter(void) +{ + if (INT_MAX == globalcounter) + { + globalcounter = 0; + } + + globalcounter++; + Trace("Global Counter Value: %d \n", globalcounter); +} + + +DWORD WFSOSemaphoreTest(LPVOID params) +{ + + DWORD dwWaitResult; + + // Request ownership of Semaphore + + dwWaitResult = WaitForSingleObject( + hSemaphore, // handle to semaphore + 0L); // zero-second time-out interval + + + switch (dwWaitResult) + { + // The semaphore object was signaled. + case WAIT_OBJECT_0: + { + + incrementCounter(); + // Increment the count of the semaphore. + + if (!ReleaseSemaphore( + hSemaphore, // handle to semaphore + 1, // increase count by one + NULL) ) // not interested in previous count + { + Fail ( "ReleaseSemaphore() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + break; + } + + // Semaphore was nonsignaled, so a time-out occurred. + case WAIT_TIMEOUT: + { + Fail ( "Semaphore was nonsignaled, so a time-out occurred. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + } + + return 1; +} + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt new file mode 100644 index 0000000000..06d28c1c86 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + WFSOThreadTest.c +) + +add_executable(paltest_waitforsingleobject_wfsothreadtest + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_wfsothreadtest CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_wfsothreadtest + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c new file mode 100644 index 0000000000..a2e5a87645 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/WFSOThreadTest/WFSOThreadTest.c @@ -0,0 +1,180 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*============================================================ +** +** Source: WFSOThreadTest.c +** +** Purpose: Test for WaitForSingleObjectTest. +** Create One Thread and do some work +** Use WFSO For the Thread to finish +** +** Test Passes if the above operations are successful +** +** +** +**=========================================================*/ + + + +#include <palsuite.h> + + +//Declaring Variables +HANDLE hThread = NULL; +HANDLE hEvent = NULL; + +unsigned int globalcounter =0; + +//Declaring Function Prototypes +DWORD incrementCounter(LPVOID params); + +int __cdecl main(int argc, char **argv) +{ + + //Declare local variables + DWORD dwThreadId=0; + DWORD dwWaitResult=0; + + //Initialize PAL + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + + //Create Event + hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); + if(hEvent == NULL) + { + Fail("Create Event Failed\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Create Thread + hThread = CreateThread( + NULL, + 0, + incrementCounter, + NULL, + 0, + &dwThreadId); + + if ( NULL == hThread ) + { + Fail ( "CreateThread() returned NULL. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + + //Wait For Thread to signal start + dwWaitResult = WaitForSingleObject(hEvent,INFINITE); + + switch (dwWaitResult) + { + // The thread wait was successful + case WAIT_OBJECT_0: + { + + Trace ("Wait for Single Object (hEvent) was successful.\n"); + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned event object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned event object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + } + + + //Wait for Thread to finish + dwWaitResult = WaitForSingleObject( + hThread, //handle to thread + 5000L); //Wait Indefinitely + + + switch (dwWaitResult) + { + // The thread wait was successful + case WAIT_OBJECT_0: + { + + Trace("Wait for thread was successful\n"); + + break; + } + + // Time-out. + case WAIT_TIMEOUT: + { + Fail ( "Time -out. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + // Got ownership of the abandoned thread object. + case WAIT_ABANDONED: + { + Fail ( "Got ownership of the abandoned thread object. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + return FALSE; + } + + } + + +//Close Handles +if (0==CloseHandle(hEvent)) + { + Trace("Could not Close event handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } +if (0==CloseHandle(hThread)) + { + Trace("Could not Close thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } + +PAL_Terminate(); +return ( PASS ); + +} + +DWORD incrementCounter(LPVOID params) +{ + + //Signal Event so that main thread can start to wait for thread object + if (0==SetEvent(hEvent)) + { + Fail ( "SetEvent returned Zero. Failing test.\n" + "GetLastError returned %d\n", GetLastError()); + } + + for (globalcounter=0;globalcounter<100000;globalcounter++); + + //Sleep(5000); + + Trace("Global Counter Value: %d \n", globalcounter); + return 0; +} + + + + + + diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt new file mode 100644 index 0000000000..2d343ed420 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test1.c +) + +add_executable(paltest_waitforsingleobject_test1 + ${SOURCES} +) + +add_dependencies(paltest_waitforsingleobject_test1 CoreClrPal) + +target_link_libraries(paltest_waitforsingleobject_test1 + pthread + rt + m + CoreClrPal +) diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c new file mode 100644 index 0000000000..7bea24bbd6 --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/test1.c @@ -0,0 +1,129 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*============================================================ +** +** Source: test1.c +** +** Purpose: Test for WaitForSingleObjectTest. Create two events, one +** with a TRUE and one with FALSE intial state. Ensure that WaitForSingle +** returns correct values for each of these. +** +** +**=========================================================*/ + +#include <palsuite.h> + +BOOL WaitForSingleObjectTest() +{ + + BOOL bRet = FALSE; + DWORD dwRet = 0; + + LPSECURITY_ATTRIBUTES lpEventAttributes = 0; + BOOL bManualReset = TRUE; + BOOL bInitialState = TRUE; + LPCTSTR lpName = "Event #6"; + + HANDLE hEvent; + + /* Create an event, and ensure the HANDLE is valid */ + hEvent = CreateEvent(lpEventAttributes, bManualReset, + bInitialState, lpName); + + if (hEvent != INVALID_HANDLE_VALUE) + { + + /* Call WaitForSingleObject with 0 time on the event. It + should return WAIT_OBJECT_0 + */ + + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_OBJECT_0) + { + Trace("WaitForSingleObjectTest:WaitForSingleObject %s " + "failed (%x)\n",lpName,GetLastError()); + } + else + { + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("WaitForSingleObjectTest:CloseHandle %s " + "failed (%x)\n",lpName,GetLastError()); + } + } + } + else + { + Trace("WaitForSingleObjectTest:CreateEvent %s " + "failed (%x)\n",lpName,GetLastError()); + } + + /* If the first section passed, Create another event, with the + intial state being FALSE this time. + */ + + if (bRet) + { + bRet = FALSE; + + bInitialState = FALSE; + + hEvent = CreateEvent( lpEventAttributes, + bManualReset, bInitialState, lpName); + + if (hEvent != INVALID_HANDLE_VALUE) + { + + /* Test WaitForSingleObject and ensure that it returns + WAIT_TIMEOUT in this case. + */ + + dwRet = WaitForSingleObject(hEvent,0); + + if (dwRet != WAIT_TIMEOUT) + { + Trace("WaitForSingleObjectTest:WaitForSingleObject %s " + "failed (%x)\n",lpName,GetLastError()); + } + else + { + bRet = CloseHandle(hEvent); + + if (!bRet) + { + Trace("WaitForSingleObjectTest:CloseHandle %s failed " + "(%x)\n",lpName,GetLastError()); + } + } + } + else + { + Trace("WaitForSingleObjectTest::CreateEvent %s failed " + "(%x)\n",lpName,GetLastError()); + } + } + return bRet; +} + +int __cdecl main(int argc, char **argv) +{ + if(0 != (PAL_Initialize(argc, argv))) + { + return ( FAIL ); + } + + if(!WaitForSingleObjectTest()) + { + Fail ("Test failed\n"); + } + + PAL_Terminate(); + return ( PASS ); + +} diff --git a/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat new file mode 100644 index 0000000000..210b87517c --- /dev/null +++ b/src/pal/tests/palsuite/threading/WaitForSingleObject/test1/testinfo.dat @@ -0,0 +1,14 @@ +# +# Copyright (c) Microsoft Corporation. All rights reserved. +# + +Version = 1.0 +Section = threading +Function = WaitForSingleObject +Name = Positive Test for WaitForSingleObject +TYPE = DEFAULT +EXE1 = test1 +Description += Test for WaitForSingleObject. Create two events, one += with a TRUE and one with FALSE intial state. Ensure that WaitForSingle += returns correct values for each of these. |