[PATCH] kernel32/tests/fiber: Add tests for fiber-local storage.
John Sheu
sheu at google.com
Thu Jul 7 17:16:07 CDT 2016
Signed-off-by: John Sheu <sheu at google.com>
---
dlls/kernel32/tests/fiber.c | 291 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 258 insertions(+), 33 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c
index 1e4ca66..4f61f80 100644
--- a/dlls/kernel32/tests/fiber.c
+++ b/dlls/kernel32/tests/fiber.c
@@ -33,9 +33,13 @@ static BOOL (WINAPI *pFlsFree)(DWORD);
static PVOID (WINAPI *pFlsGetValue)(DWORD);
static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
-static LPVOID fibers[2];
+static LPVOID fibers[3];
static BYTE testparam = 185;
-static WORD cbCount;
+static DWORD fls_index_to_set = FLS_OUT_OF_INDEXES;
+static PVOID fls_value_to_set = NULL;
+
+static int fiberCount = 0;
+static int cbCount = 0;
static VOID init_funcs(void)
{
@@ -59,15 +63,44 @@ static VOID init_funcs(void)
static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData)
{
+ ok(lpFlsData == fls_value_to_set,
+ "FlsData expected not to be changed, value is %p, expected %p\n",
+ lpFlsData, fls_value_to_set);
cbCount++;
- ok(lpFlsData == (PVOID) 1587, "FlsData expected not to be changed\n");
}
static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
{
BYTE *tparam = (BYTE *)lpFiberParameter;
- cbCount++;
+ fiberCount++;
ok(*tparam == 185, "Parameterdata expected not to be changed\n");
+ if (fls_index_to_set != FLS_OUT_OF_INDEXES)
+ {
+ if (!pFlsSetValue || !pFlsGetValue)
+ {
+ win_skip( "Fiber Local Storage not supported\n" );
+ }
+ else
+ {
+ PVOID pret;
+ BOOL bret;
+
+ pret = pFlsGetValue(fls_index_to_set);
+ ok(pret == NULL, "FlsGetValue returned %p, expected NULL\n", pret);
+
+ /* Set the FLS value */
+ SetLastError( 0xdeadbeef );
+ bret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
+ ok(bret, "FlsSetValue failed with error %u\n", GetLastError());
+
+ /* Verify that FlsGetValue retrieves the value set by FlsSetValue */
+ SetLastError( 0xdeadbeef );
+ pret = pFlsGetValue(fls_index_to_set);
+ ok(pret == fls_value_to_set,
+ "FlsGetValue returned %p, expected %p\n", pret, fls_value_to_set);
+ ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue error %u\n", GetLastError());
+ }
+ }
pSwitchToFiber(fibers[0]);
}
@@ -110,9 +143,23 @@ static void test_ConvertFiberToThread(void)
}
}
+static void test_IsThreadAFiber(BOOL is_fiber)
+{
+ if (pIsThreadAFiber)
+ {
+ BOOL ret = pIsThreadAFiber();
+ ok(ret == is_fiber, "IsThreadAFiber reported %d, expected %d\n", ret, is_fiber);
+ }
+ else
+ {
+ win_skip( "IsThreadAFiber not present\n" );
+ return;
+ }
+}
+
static void test_FiberHandling(void)
{
- cbCount = 0;
+ fiberCount = 0;
fibers[0] = pCreateFiber(0,FiberMainProc,&testparam);
ok(fibers[0] != 0, "CreateFiber failed with error %d\n", GetLastError());
pDeleteFiber(fibers[0]);
@@ -124,12 +171,11 @@ static void test_FiberHandling(void)
else
test_ConvertThreadToFiber();
-
fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
ok(fibers[1] != 0, "CreateFiber failed with error %d\n", GetLastError());
pSwitchToFiber(fibers[1]);
- ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
+ ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
pDeleteFiber(fibers[1]);
if (!pCreateFiberEx)
@@ -143,46 +189,72 @@ static void test_FiberHandling(void)
ok(fibers[1] != 0, "CreateFiberEx failed with error %d\n", GetLastError());
pSwitchToFiber(fibers[1]);
- ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
+ ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount);
pDeleteFiber(fibers[1]);
- if (!pIsThreadAFiber)
- {
- win_skip( "IsThreadAFiber not present\n" );
- return;
- }
-
- ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n");
+ test_IsThreadAFiber(TRUE);
test_ConvertFiberToThread();
- ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n");
+ test_IsThreadAFiber(FALSE);
}
-static void test_FiberLocalStorage(PFLS_CALLBACK_FUNCTION cbfunc)
+static void test_FiberLocalStorage(void)
{
- DWORD fls;
+ DWORD fls, fls_2;
BOOL ret;
- PVOID val = (PVOID) 1587;
+ PVOID val;
- if (!pFlsAlloc)
+ if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
{
win_skip( "Fiber Local Storage not supported\n" );
return;
}
- cbCount = 0;
- fls = pFlsAlloc(cbfunc);
- ok(fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %d\n", GetLastError());
+ /* Test an unallocated index
+ * FlsFree should fail
+ * FlsGetValue and FlsSetValue should succeed
+ */
+ SetLastError( 0xdeadbeef );
+ ret = pFlsFree( 127 );
+ ok( !ret, "freeing fls index 127 (unallocated) succeeded\n" );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER,
+ "freeing fls index 127 (unallocated) wrong error %u\n", GetLastError() );
- ret = pFlsSetValue(fls, val);
- ok(ret, "FlsSetValue failed\n");
- ok(val == pFlsGetValue(fls), "FlsGetValue failed\n");
+ SetLastError( 0xdeadbeef );
+ val = pFlsGetValue( 127 );
+ ok( val == NULL,
+ "getting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ ret = pFlsSetValue( 127, (PVOID) 0x217 );
+ ok( ret, "setting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ val = pFlsGetValue( 127 );
+ ok( val == (PVOID) 0x217, "fls index 127 (unallocated) wrong value %p\n", val );
+ ok( GetLastError() == ERROR_SUCCESS,
+ "getting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
+
+ /* FlsFree, FlsGetValue, and FlsSetValue out of bounds should return
+ * ERROR_INVALID_PARAMETER
+ */
+ SetLastError( 0xdeadbeef );
+ ret = pFlsFree( 128 );
+ ok( !ret, "freeing fls index 128 (out of bounds) succeeded\n" );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER,
+ "freeing fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
- ret = pFlsFree(fls);
- ok(ret, "FlsFree failed\n");
- if (cbfunc)
- todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
+ SetLastError( 0xdeadbeef );
+ ret = pFlsSetValue( 128, (PVOID) 0x217 );
+ ok( !ret, "setting fls index 128 (out of bounds) succeeded\n" );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER,
+ "setting fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ val = pFlsGetValue( 128 );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER,
+ "setting fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
- /* test index 0 */
+ /* Test index 0 */
SetLastError( 0xdeadbeef );
val = pFlsGetValue( 0 );
ok( !val, "fls index 0 set to %p\n", val );
@@ -196,6 +268,7 @@ static void test_FiberLocalStorage(PFLS_CALLBACK_FUNCTION cbfunc)
ok( !val, "fls index 0 wrong value %p\n", val );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() );
+ /* Test creating an FLS index */
fls = pFlsAlloc( NULL );
ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed\n" );
ok( fls != 0, "fls index 0 allocated\n" );
@@ -205,11 +278,162 @@ static void test_FiberLocalStorage(PFLS_CALLBACK_FUNCTION cbfunc)
ok( ret, "setting fls index %u failed\n", fls );
val = pFlsGetValue( fls );
ok( val == (void *)0xdeadbeef, "fls index %u wrong value %p\n", fls, val );
+ ok( GetLastError() == ERROR_SUCCESS,
+ "getting fls index %u failed with error %u\n", fls, GetLastError() );
pFlsFree( fls );
+
+ /* Undefined behavior: verify the value is NULL after it the slot is freed */
+ val = pFlsGetValue( fls );
+ ok( val == NULL, "fls index %u wrong value %p\n", fls, val );
+ ok( GetLastError() == ERROR_SUCCESS,
+ "getting fls index %u failed with error %u\n", fls, GetLastError() );
+
+ /* Undefined behavior: verify the value is settable after the slot is freed */
ret = pFlsSetValue( fls, (void *)0xdeadbabe );
ok( ret, "setting fls index %u failed\n", fls );
val = pFlsGetValue( fls );
ok( val == (void *)0xdeadbabe, "fls index %u wrong value %p\n", fls, val );
+
+ /* Try to create the same FLS index again, and verify that is initialized to NULL */
+ fls_2 = pFlsAlloc( NULL );
+ ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed\n" );
+ /* If this fails it is not an API error, but the test will be inconclusive */
+ ok( fls_2 == fls, "different FLS index allocated, was %u, now %u\n", fls, fls_2 );
+ val = pFlsGetValue( fls_2 );
+ ok( val == NULL, "fls index %u wrong value %p\n", fls, val );
+ ok( GetLastError() == ERROR_SUCCESS,
+ "getting fls index %u failed with error %u\n", fls_2, GetLastError() );
+ pFlsFree( fls_2 );
+}
+
+static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc) {
+ DWORD fls;
+ BOOL ret;
+ PVOID val, val2;
+
+ if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
+ {
+ win_skip( "Fiber Local Storage not supported\n" );
+ return;
+ }
+
+ /* Test that the callback is executed */
+ SetLastError( 0xdeadbeef );
+ cbCount = 0;
+ fls = pFlsAlloc( cbfunc );
+ ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ val = (PVOID) 0x1587;
+ fls_value_to_set = val;
+ ret = pFlsSetValue( fls, val );
+ ok(ret, "FlsSetValue failed with error %u\n", GetLastError() );
+
+ val2 = pFlsGetValue( fls );
+ ok(val == val2, "FlsGetValue returned %p, expected %p\n", val2, val);
+
+ SetLastError( 0xdeadbeef );
+ ret = pFlsFree( fls );
+ ok(ret, "FlsFree failed with error %u\n", GetLastError() );
+ todo_wine
+ {
+ ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
+ }
+
+ /* Test that callback is not executed if value is NULL */
+ SetLastError( 0xdeadbeef );
+ cbCount = 0;
+ fls = pFlsAlloc( cbfunc );
+ ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ ret = pFlsSetValue( fls, NULL );
+ ok( ret, "FlsSetValue failed with error %u\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ pFlsFree( fls );
+ ok( ret, "FlsFree failed with error %u\n", GetLastError() );
+ ok( cbCount == 0, "Wrong callback count: %d\n", cbCount );
+}
+
+static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc) {
+ PVOID val1 = (PVOID) 0x314;
+ PVOID val2 = (PVOID) 0x152;
+ BOOL ret;
+
+ if (!pConvertThreadToFiber || !pSwitchToFiber || !pDeleteFiber || !pConvertFiberToThread)
+ {
+ win_skip( "Fibers not supported\n" );
+ return;
+ }
+ if (!pFlsAlloc || !pFlsFree || !pFlsSetValue || !pFlsGetValue)
+ {
+ win_skip( "Fiber Local Storage not supported\n" );
+ return;
+ }
+
+
+ fls_index_to_set = pFlsAlloc(cbfunc);
+ ok(fls_index_to_set != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %d\n", GetLastError());
+
+ test_ConvertThreadToFiber();
+
+ fiberCount = 0;
+ cbCount = 0;
+ fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
+ fibers[2] = pCreateFiber(0,FiberMainProc,&testparam);
+ ok(fibers[1] != 0, "CreateFiber failed with error %d\n", GetLastError());
+ ok(fibers[2] != 0, "CreateFiber failed with error %d\n", GetLastError());
+ ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
+ ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
+
+ fiberCount = 0;
+ cbCount = 0;
+ fls_value_to_set = val1;
+ pSwitchToFiber(fibers[1]);
+ ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
+ ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
+
+ fiberCount = 0;
+ cbCount = 0;
+ fls_value_to_set = val2;
+ pSwitchToFiber(fibers[2]);
+ ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
+ ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
+
+ fls_value_to_set = val2;
+ ret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
+ ok(ret, "FlsSetValue failed\n");
+ ok(val2 == pFlsGetValue(fls_index_to_set), "FlsGetValue failed\n");
+
+ fiberCount = 0;
+ cbCount = 0;
+ fls_value_to_set = val1;
+ pDeleteFiber(fibers[1]);
+ ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
+ todo_wine
+ {
+ ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
+ }
+
+ fiberCount = 0;
+ cbCount = 0;
+ fls_value_to_set = val2;
+ pFlsFree(fls_index_to_set);
+ ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
+ todo_wine
+ {
+ ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
+ }
+
+ fiberCount = 0;
+ cbCount = 0;
+ fls_value_to_set = val1;
+ pDeleteFiber(fibers[2]);
+ ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
+ ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
+
+ test_ConvertFiberToThread();
}
START_TEST(fiber)
@@ -223,6 +447,7 @@ START_TEST(fiber)
}
test_FiberHandling();
- test_FiberLocalStorage(NULL);
- test_FiberLocalStorage(FiberLocalStorageProc);
+ test_FiberLocalStorage();
+ test_FiberLocalStorageCallback(FiberLocalStorageProc);
+ test_FiberLocalStorageWithFibers(FiberLocalStorageProc);
}
--
2.8.0.rc3.226.g39d4020
More information about the wine-patches
mailing list