| /* | 
 |  * Unit tests for fiber functions | 
 |  * | 
 |  * Copyright (c) 2010 André Hentschel | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |  * Lesser General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Lesser General Public | 
 |  * License along with this library; if not, write to the Free Software | 
 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
 |  */ | 
 |  | 
 | #include "wine/test.h" | 
 |  | 
 | static LPVOID (WINAPI *pCreateFiber)(SIZE_T,LPFIBER_START_ROUTINE,LPVOID); | 
 | static LPVOID (WINAPI *pConvertThreadToFiber)(LPVOID); | 
 | static BOOL (WINAPI *pConvertFiberToThread)(void); | 
 | static void (WINAPI *pSwitchToFiber)(LPVOID); | 
 | static void (WINAPI *pDeleteFiber)(LPVOID); | 
 | static LPVOID (WINAPI *pConvertThreadToFiberEx)(LPVOID,DWORD); | 
 | static LPVOID (WINAPI *pCreateFiberEx)(SIZE_T,SIZE_T,DWORD,LPFIBER_START_ROUTINE,LPVOID); | 
 | static BOOL (WINAPI *pIsThreadAFiber)(void); | 
 | static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); | 
 | static BOOL (WINAPI *pFlsFree)(DWORD); | 
 | static PVOID (WINAPI *pFlsGetValue)(DWORD); | 
 | static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); | 
 |  | 
 | static LPVOID fibers[2]; | 
 | static BYTE testparam = 185; | 
 | static WORD cbCount; | 
 |  | 
 | static VOID init_funcs(void) | 
 | { | 
 |     HMODULE hKernel32 = GetModuleHandle("kernel32"); | 
 |  | 
 | #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f); | 
 |     X(CreateFiber); | 
 |     X(ConvertThreadToFiber); | 
 |     X(ConvertFiberToThread); | 
 |     X(SwitchToFiber); | 
 |     X(DeleteFiber); | 
 |     X(ConvertThreadToFiberEx); | 
 |     X(CreateFiberEx); | 
 |     X(IsThreadAFiber); | 
 |     X(FlsAlloc); | 
 |     X(FlsFree); | 
 |     X(FlsGetValue); | 
 |     X(FlsSetValue); | 
 | #undef X | 
 | } | 
 |  | 
 | static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData) | 
 | { | 
 |     cbCount++; | 
 |     ok(lpFlsData == (PVOID) 1587, "FlsData expected not to be changed\n"); | 
 | } | 
 |  | 
 | static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter) | 
 | { | 
 |     BYTE *tparam = (BYTE *)lpFiberParameter; | 
 |     cbCount++; | 
 |     ok(*tparam == 185, "Parameterdata expected not to be changed\n"); | 
 |     pSwitchToFiber(fibers[0]); | 
 | } | 
 |  | 
 | static void test_ConvertThreadToFiber(void) | 
 | { | 
 |     if (pConvertThreadToFiber) | 
 |     { | 
 |         fibers[0] = pConvertThreadToFiber(&testparam); | 
 |         ok(fibers[0] != 0, "ConvertThreadToFiber failed with error %d\n", GetLastError()); | 
 |     } | 
 |     else | 
 |     { | 
 |         win_skip( "ConvertThreadToFiber not present\n" ); | 
 |     } | 
 | } | 
 |  | 
 | static void test_ConvertThreadToFiberEx(void) | 
 | { | 
 |     if (pConvertThreadToFiberEx) | 
 |     { | 
 |         fibers[0] = pConvertThreadToFiberEx(&testparam, 0); | 
 |         ok(fibers[0] != 0, "ConvertThreadToFiberEx failed with error %d\n", GetLastError()); | 
 |     } | 
 |     else | 
 |     { | 
 |         win_skip( "ConvertThreadToFiberEx not present\n" ); | 
 |     } | 
 | } | 
 |  | 
 | static void test_ConvertFiberToThread(void) | 
 | { | 
 |     if (pConvertFiberToThread) | 
 |     { | 
 |         ok(pConvertFiberToThread() , "ConvertFiberToThread failed with error %d\n", GetLastError()); | 
 |     } | 
 |     else | 
 |     { | 
 |         win_skip( "ConvertFiberToThread not present\n" ); | 
 |     } | 
 | } | 
 |  | 
 | static void test_FiberHandling(void) | 
 | { | 
 |     cbCount = 0; | 
 |     fibers[0] = pCreateFiber(0,FiberMainProc,&testparam); | 
 |     ok(fibers[0] != 0, "CreateFiber failed with error %d\n", GetLastError()); | 
 |     pDeleteFiber(fibers[0]); | 
 |  | 
 |     test_ConvertThreadToFiber(); | 
 |     test_ConvertFiberToThread(); | 
 |     if (pConvertThreadToFiberEx) | 
 |         test_ConvertThreadToFiberEx(); | 
 |     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); | 
 |     pDeleteFiber(fibers[1]); | 
 |  | 
 |     if (!pCreateFiberEx) | 
 |     { | 
 |         win_skip( "CreateFiberEx not present\n" ); | 
 |         return; | 
 |     } | 
 |  | 
 |     fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam); | 
 |     ok(fibers[1] != 0, "CreateFiberEx failed with error %d\n", GetLastError()); | 
 |  | 
 |     pSwitchToFiber(fibers[1]); | 
 |     ok(cbCount == 2, "Wrong callback count: %d\n", cbCount); | 
 |     pDeleteFiber(fibers[1]); | 
 |  | 
 |     if (!pIsThreadAFiber) | 
 |     { | 
 |         win_skip( "IsThreadAFiber not present\n" ); | 
 |         return; | 
 |     } | 
 |  | 
 |     ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n"); | 
 |     test_ConvertFiberToThread(); | 
 |     ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n"); | 
 | } | 
 |  | 
 | static void test_FiberLocalStorage(PFLS_CALLBACK_FUNCTION cbfunc) | 
 | { | 
 |     DWORD fls; | 
 |     BOOL ret; | 
 |     PVOID val = (PVOID) 1587; | 
 |  | 
 |     if (!pFlsAlloc) | 
 |     { | 
 |         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()); | 
 |  | 
 |     ret = pFlsSetValue(fls, val); | 
 |     ok(ret, "FlsSetValue failed\n"); | 
 |     ok(val == pFlsGetValue(fls), "FlsGetValue failed\n"); | 
 |  | 
 |     ret = pFlsFree(fls); | 
 |     ok(ret, "FlsFree failed\n"); | 
 |     if (cbfunc) | 
 |         todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount); | 
 | } | 
 |  | 
 | START_TEST(fiber) | 
 | { | 
 |     init_funcs(); | 
 |  | 
 |     if (!pCreateFiber) | 
 |     { | 
 |         win_skip( "Fibers not supported by win95\n" ); | 
 |         return; | 
 |     } | 
 |  | 
 |     test_FiberHandling(); | 
 |     test_FiberLocalStorage(NULL); | 
 |     test_FiberLocalStorage(FiberLocalStorageProc); | 
 | } |