/*
 * 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);
}
