ReactOS 0.4.15-dev-7918-g2a2556c
fiber.c
Go to the documentation of this file.
1/*
2 * Unit tests for fiber functions
3 *
4 * Copyright (c) 2010 André Hentschel
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "wine/test.h"
22
24static LPVOID (WINAPI *pConvertThreadToFiber)(LPVOID);
25static BOOL (WINAPI *pConvertFiberToThread)(void);
26static void (WINAPI *pSwitchToFiber)(LPVOID);
27static void (WINAPI *pDeleteFiber)(LPVOID);
28static LPVOID (WINAPI *pConvertThreadToFiberEx)(LPVOID,DWORD);
30static BOOL (WINAPI *pIsThreadAFiber)(void);
31static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
32static BOOL (WINAPI *pFlsFree)(DWORD);
33static PVOID (WINAPI *pFlsGetValue)(DWORD);
34static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
35
36static void *fibers[3];
37static BYTE testparam = 185;
39static void* fls_value_to_set;
40
41static int fiberCount = 0;
42static int cbCount = 0;
43
44static VOID init_funcs(void)
45{
46 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
47
48#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
57 X(FlsAlloc);
58 X(FlsFree);
61#undef X
62}
63
65{
66 ok(lpFlsData == fls_value_to_set,
67 "FlsData expected not to be changed, value is %p, expected %p\n",
68 lpFlsData, fls_value_to_set);
69 cbCount++;
70}
71
72static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
73{
74 BYTE *tparam = (BYTE *)lpFiberParameter;
75 fiberCount++;
76 ok(*tparam == 185, "Parameterdata expected not to be changed\n");
78 {
79 void* ret;
80 BOOL bret;
81
82 ret = pFlsGetValue(fls_index_to_set);
83 ok(ret == NULL, "FlsGetValue returned %p, expected NULL\n", ret);
84
85 /* Set the FLS value */
86 bret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
87 ok(bret, "FlsSetValue failed with error %u\n", GetLastError());
88
89 /* Verify that FlsGetValue retrieves the value set by FlsSetValue */
90 SetLastError( 0xdeadbeef );
91 ret = pFlsGetValue(fls_index_to_set);
92 ok(ret == fls_value_to_set, "FlsGetValue returned %p, expected %p\n", ret, fls_value_to_set);
93 ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue error %u\n", GetLastError());
94 }
95 pSwitchToFiber(fibers[0]);
96}
97
99{
100 if (pConvertThreadToFiber)
101 {
102 fibers[0] = pConvertThreadToFiber(&testparam);
103 ok(fibers[0] != NULL, "ConvertThreadToFiber failed with error %u\n", GetLastError());
104 }
105 else
106 {
107 win_skip( "ConvertThreadToFiber not present\n" );
108 }
109}
110
112{
113 if (pConvertThreadToFiberEx)
114 {
115 fibers[0] = pConvertThreadToFiberEx(&testparam, 0);
116 ok(fibers[0] != NULL, "ConvertThreadToFiberEx failed with error %u\n", GetLastError());
117 }
118 else
119 {
120 win_skip( "ConvertThreadToFiberEx not present\n" );
121 }
122}
123
125{
126 if (pConvertFiberToThread)
127 {
128 BOOL ret = pConvertFiberToThread();
129 ok(ret, "ConvertFiberToThread failed with error %u\n", GetLastError());
130 }
131 else
132 {
133 win_skip( "ConvertFiberToThread not present\n" );
134 }
135}
136
137static void test_FiberHandling(void)
138{
139 fiberCount = 0;
140 fibers[0] = pCreateFiber(0,FiberMainProc,&testparam);
141 ok(fibers[0] != NULL, "CreateFiber failed with error %u\n", GetLastError());
142 pDeleteFiber(fibers[0]);
143
146 if (pConvertThreadToFiberEx)
148 else
150
151 fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
152 ok(fibers[1] != NULL, "CreateFiber failed with error %u\n", GetLastError());
153
154 pSwitchToFiber(fibers[1]);
155 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
156 pDeleteFiber(fibers[1]);
157
158 if (pCreateFiberEx)
159 {
160 fibers[1] = pCreateFiberEx(0,0,0,FiberMainProc,&testparam);
161 ok(fibers[1] != NULL, "CreateFiberEx failed with error %u\n", GetLastError());
162
163 pSwitchToFiber(fibers[1]);
164 ok(fiberCount == 2, "Wrong fiber count: %d\n", fiberCount);
165 pDeleteFiber(fibers[1]);
166 }
167 else win_skip( "CreateFiberEx not present\n" );
168
169 if (pIsThreadAFiber) ok(pIsThreadAFiber(), "IsThreadAFiber reported FALSE\n");
171 if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n");
172}
173
174static void test_FiberLocalStorage(void)
175{
176 DWORD fls, fls_2;
177 BOOL ret;
178 void* val;
179
180 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
181 {
182 win_skip( "Fiber Local Storage not supported\n" );
183 return;
184 }
185
186 /* Test an unallocated index
187 * FlsFree should fail
188 * FlsGetValue and FlsSetValue should succeed
189 */
190 SetLastError( 0xdeadbeef );
191 ret = pFlsFree( 127 );
192 ok( !ret, "freeing fls index 127 (unallocated) succeeded\n" );
194 "freeing fls index 127 (unallocated) wrong error %u\n", GetLastError() );
195
196 val = pFlsGetValue( 127 );
197 ok( val == NULL,
198 "getting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
199
200 ret = pFlsSetValue( 127, (void*) 0x217 );
201 ok( ret, "setting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
202
203 SetLastError( 0xdeadbeef );
204 val = pFlsGetValue( 127 );
205 ok( val == (void*) 0x217, "fls index 127 (unallocated) wrong value %p\n", val );
207 "getting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
208
209 /* FlsFree, FlsGetValue, and FlsSetValue out of bounds should return
210 * ERROR_INVALID_PARAMETER
211 */
212 SetLastError( 0xdeadbeef );
213 ret = pFlsFree( 128 );
214 ok( !ret, "freeing fls index 128 (out of bounds) succeeded\n" );
216 "freeing fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
217
218 SetLastError( 0xdeadbeef );
219 ret = pFlsSetValue( 128, (void*) 0x217 );
220 ok( !ret, "setting fls index 128 (out of bounds) succeeded\n" );
222 "setting fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
223
224 SetLastError( 0xdeadbeef );
225 val = pFlsGetValue( 128 );
227 "getting fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
228
229 /* Test index 0 */
230 SetLastError( 0xdeadbeef );
231 val = pFlsGetValue( 0 );
232 ok( !val, "fls index 0 set to %p\n", val );
233 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() );
234 SetLastError( 0xdeadbeef );
235 ret = pFlsSetValue( 0, (void *)0xdeadbeef );
236 ok( !ret, "setting fls index 0 succeeded\n" );
237 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() );
238 SetLastError( 0xdeadbeef );
239 val = pFlsGetValue( 0 );
240 ok( !val, "fls index 0 wrong value %p\n", val );
241 ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() );
242
243 /* Test creating an FLS index */
244 fls = pFlsAlloc( NULL );
245 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed\n" );
246 ok( fls != 0, "fls index 0 allocated\n" );
247 val = pFlsGetValue( fls );
248 ok( !val, "fls index %u wrong value %p\n", fls, val );
249 ret = pFlsSetValue( fls, (void *)0xdeadbeef );
250 ok( ret, "setting fls index %u failed\n", fls );
251 SetLastError( 0xdeadbeef );
252 val = pFlsGetValue( fls );
253 ok( val == (void *)0xdeadbeef, "fls index %u wrong value %p\n", fls, val );
255 "getting fls index %u failed with error %u\n", fls, GetLastError() );
256 pFlsFree( fls );
257
258 /* Undefined behavior: verify the value is NULL after it the slot is freed */
259 SetLastError( 0xdeadbeef );
260 val = pFlsGetValue( fls );
261 ok( val == NULL, "fls index %u wrong value %p\n", fls, val );
263 "getting fls index %u failed with error %u\n", fls, GetLastError() );
264
265 /* Undefined behavior: verify the value is settable after the slot is freed */
266 ret = pFlsSetValue( fls, (void *)0xdeadbabe );
267 ok( ret, "setting fls index %u failed\n", fls );
268 val = pFlsGetValue( fls );
269 ok( val == (void *)0xdeadbabe, "fls index %u wrong value %p\n", fls, val );
270
271 /* Try to create the same FLS index again, and verify that is initialized to NULL */
272 fls_2 = pFlsAlloc( NULL );
273 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %u\n", GetLastError() );
274 /* If this fails it is not an API error, but the test will be inconclusive */
275 ok( fls_2 == fls, "different FLS index allocated, was %u, now %u\n", fls, fls_2 );
276
277 SetLastError( 0xdeadbeef );
278 val = pFlsGetValue( fls_2 );
279 ok( val == NULL, "fls index %u wrong value %p\n", fls, val );
281 "getting fls index %u failed with error %u\n", fls_2, GetLastError() );
282 pFlsFree( fls_2 );
283}
284
286{
287 DWORD fls;
288 BOOL ret;
289 void* val, *val2;
290
291 if (!pFlsAlloc || !pFlsSetValue || !pFlsGetValue || !pFlsFree)
292 {
293 win_skip( "Fiber Local Storage not supported\n" );
294 return;
295 }
296
297 /* Test that the callback is executed */
298 cbCount = 0;
299 fls = pFlsAlloc( cbfunc );
300 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %u\n", GetLastError() );
301
302 val = (void*) 0x1587;
304 ret = pFlsSetValue( fls, val );
305 ok(ret, "FlsSetValue failed with error %u\n", GetLastError() );
306
307 val2 = pFlsGetValue( fls );
308 ok(val == val2, "FlsGetValue returned %p, expected %p\n", val2, val);
309
310 ret = pFlsFree( fls );
311 ok(ret, "FlsFree failed with error %u\n", GetLastError() );
312 todo_wine ok( cbCount == 1, "Wrong callback count: %d\n", cbCount );
313
314 /* Test that callback is not executed if value is NULL */
315 cbCount = 0;
316 fls = pFlsAlloc( cbfunc );
317 ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %u\n", GetLastError() );
318
319 ret = pFlsSetValue( fls, NULL );
320 ok( ret, "FlsSetValue failed with error %u\n", GetLastError() );
321
322 pFlsFree( fls );
323 ok( ret, "FlsFree failed with error %u\n", GetLastError() );
324 ok( cbCount == 0, "Wrong callback count: %d\n", cbCount );
325}
326
328{
329 void* val1 = (void*) 0x314;
330 void* val2 = (void*) 0x152;
331 BOOL ret;
332
333 if (!pFlsAlloc || !pFlsFree || !pFlsSetValue || !pFlsGetValue)
334 {
335 win_skip( "Fiber Local Storage not supported\n" );
336 return;
337 }
338
339 fls_index_to_set = pFlsAlloc(cbfunc);
340 ok(fls_index_to_set != FLS_OUT_OF_INDEXES, "FlsAlloc failed with error %u\n", GetLastError());
341
343
344 fiberCount = 0;
345 cbCount = 0;
346 fibers[1] = pCreateFiber(0,FiberMainProc,&testparam);
347 fibers[2] = pCreateFiber(0,FiberMainProc,&testparam);
348 ok(fibers[1] != NULL, "CreateFiber failed with error %u\n", GetLastError());
349 ok(fibers[2] != NULL, "CreateFiber failed with error %u\n", GetLastError());
350 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
351 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
352
353 fiberCount = 0;
354 cbCount = 0;
355 fls_value_to_set = val1;
356 pSwitchToFiber(fibers[1]);
357 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
358 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
359
360 fiberCount = 0;
361 cbCount = 0;
362 fls_value_to_set = val2;
363 pSwitchToFiber(fibers[2]);
364 ok(fiberCount == 1, "Wrong fiber count: %d\n", fiberCount);
365 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
366
367 fls_value_to_set = val2;
368 ret = pFlsSetValue(fls_index_to_set, fls_value_to_set);
369 ok(ret, "FlsSetValue failed\n");
370 ok(val2 == pFlsGetValue(fls_index_to_set), "FlsGetValue failed\n");
371
372 fiberCount = 0;
373 cbCount = 0;
374 fls_value_to_set = val1;
375 pDeleteFiber(fibers[1]);
376 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
377 todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
378
379 fiberCount = 0;
380 cbCount = 0;
381 fls_value_to_set = val2;
382 pFlsFree(fls_index_to_set);
383 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
384 todo_wine ok(cbCount == 2, "Wrong callback count: %d\n", cbCount);
385
386 fiberCount = 0;
387 cbCount = 0;
388 fls_value_to_set = val1;
389 pDeleteFiber(fibers[2]);
390 ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount);
391 ok(cbCount == 0, "Wrong callback count: %d\n", cbCount);
392
394}
395
397{
398 init_funcs();
399
400 if (!pCreateFiber)
401 {
402 win_skip( "Fibers not supported by win95\n" );
403 return;
404 }
405
410}
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
static int fls(int x)
Definition: bitops.h:157
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
LPVOID WINAPI ConvertThreadToFiberEx(_In_opt_ LPVOID lpParameter, _In_ DWORD dwFlags)
Definition: fiber.c:99
BOOL WINAPI ConvertFiberToThread(VOID)
Definition: fiber.c:64
LPVOID WINAPI CreateFiberEx(_In_ SIZE_T dwStackCommitSize, _In_ SIZE_T dwStackReserveSize, _In_ DWORD dwFlags, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
Definition: fiber.c:191
VOID WINAPI DeleteFiber(_In_ LPVOID lpFiber)
Definition: fiber.c:290
BOOL WINAPI IsThreadAFiber(VOID)
Definition: fiber.c:330
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
LPVOID WINAPI ConvertThreadToFiber(_In_opt_ LPVOID lpParameter)
Definition: fiber.c:162
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
LPVOID WINAPI CreateFiber(_In_ SIZE_T dwStackSize, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
Definition: fiber.c:174
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLfloat * val
Definition: glext.h:7180
HANDLE hKernel32
Definition: locale.c:13
static void * fibers[3]
Definition: fiber.c:36
static LPFIBER_START_ROUTINE
Definition: fiber.c:23
static BYTE testparam
Definition: fiber.c:37
static int cbCount
Definition: fiber.c:42
#define X(f)
static DWORD fls_index_to_set
Definition: fiber.c:38
static void test_ConvertThreadToFiberEx(void)
Definition: fiber.c:111
static void test_ConvertFiberToThread(void)
Definition: fiber.c:124
static void * fls_value_to_set
Definition: fiber.c:39
static DWORD
Definition: fiber.c:28
static int fiberCount
Definition: fiber.c:41
static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:327
static PVOID
Definition: fiber.c:34
static void test_ConvertThreadToFiber(void)
Definition: fiber.c:98
static VOID init_funcs(void)
Definition: fiber.c:44
static LPVOID
Definition: fiber.c:23
static SIZE_T
Definition: fiber.c:29
static void test_FiberHandling(void)
Definition: fiber.c:137
static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:285
static void test_FiberLocalStorage(void)
Definition: fiber.c:174
static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData)
Definition: fiber.c:64
static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
Definition: fiber.c:72
#define todo_wine
Definition: custom.c:79
#define BOOL
Definition: nt_native.h:43
#define win_skip
Definition: test.h:160
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:576
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
Definition: winbase.h:1444
void WINAPI SwitchToFiber(_In_ PVOID)
#define WINAPI
Definition: msvc.h:6
unsigned char BYTE
Definition: xxhash.c:193