ReactOS  0.4.14-dev-293-g2b39b42
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 
24 static LPVOID (WINAPI *pConvertThreadToFiber)(LPVOID);
25 static BOOL (WINAPI *pConvertFiberToThread)(void);
26 static void (WINAPI *pSwitchToFiber)(LPVOID);
27 static void (WINAPI *pDeleteFiber)(LPVOID);
28 static LPVOID (WINAPI *pConvertThreadToFiberEx)(LPVOID,DWORD);
30 static BOOL (WINAPI *pIsThreadAFiber)(void);
31 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
32 static BOOL (WINAPI *pFlsFree)(DWORD);
33 static PVOID (WINAPI *pFlsGetValue)(DWORD);
34 static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
35 
36 static void *fibers[3];
37 static BYTE testparam = 185;
39 static void* fls_value_to_set;
40 
41 static int fiberCount = 0;
42 static int cbCount = 0;
43 
44 static VOID init_funcs(void)
45 {
46  HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
47 
48 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
49  X(CreateFiber);
53  X(DeleteFiber);
57  X(FlsAlloc);
58  X(FlsFree);
59  X(FlsGetValue);
60  X(FlsSetValue);
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 
72 static 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 
98 static void test_ConvertThreadToFiber(void)
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 
124 static void test_ConvertFiberToThread(void)
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 
137 static 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 
174 static 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 ERROR_INVALID_PARAMETER
Definition: compat.h:91
LPVOID WINAPI ConvertThreadToFiberEx(_In_opt_ LPVOID lpParameter, _In_ DWORD dwFlags)
Definition: fiber.c:99
static void(WINAPI *pSwitchToFiber)(LPVOID)
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:557
#define ERROR_SUCCESS
Definition: deptool.c:10
static int fiberCount
Definition: fiber.c:41
static int cbCount
Definition: fiber.c:42
static BOOL(WINAPI *pConvertFiberToThread)(void)
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
Definition: winbase.h:1404
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static VOID WINAPI FiberMainProc(LPVOID lpFiberParameter)
Definition: fiber.c:72
static void test_ConvertThreadToFiber(void)
Definition: fiber.c:98
BOOL WINAPI ConvertFiberToThread(VOID)
Definition: fiber.c:64
static DWORD
Definition: fiber.c:28
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:285
BOOL WINAPI IsThreadAFiber(VOID)
Definition: fiber.c:330
static int fls(int x)
Definition: bitops.h:157
unsigned int BOOL
Definition: ntddk_ex.h:94
static LPFIBER_START_ROUTINE
Definition: fiber.c:23
static void test_ConvertThreadToFiberEx(void)
Definition: fiber.c:111
LPVOID WINAPI ConvertThreadToFiber(_In_opt_ LPVOID lpParameter)
Definition: fiber.c:162
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
static void * fibers[3]
Definition: fiber.c:36
smooth NULL
Definition: ftsmooth.c:416
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
static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc)
Definition: fiber.c:327
static SIZE_T
Definition: fiber.c:29
GLuint GLfloat * val
Definition: glext.h:7180
VOID WINAPI DeleteFiber(_In_ LPVOID lpFiber)
Definition: fiber.c:290
#define X(f)
#define WINAPI
Definition: msvc.h:8
static void test_ConvertFiberToThread(void)
Definition: fiber.c:124
unsigned long DWORD
Definition: ntddk_ex.h:95
void WINAPI SwitchToFiber(_In_ PVOID)
#define SetLastError(x)
Definition: compat.h:409
static PVOID
Definition: fiber.c:34
int ret
static LPVOID
Definition: fiber.c:23
#define todo_wine
Definition: test.h:154
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
unsigned char BYTE
Definition: mem.h:68
static VOID init_funcs(void)
Definition: fiber.c:44
static void test_FiberLocalStorage(void)
Definition: fiber.c:174
static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData)
Definition: fiber.c:64
#define ok(value,...)
Definition: atltest.h:57
static void test_FiberHandling(void)
Definition: fiber.c:137
static BYTE testparam
Definition: fiber.c:37
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
static DWORD fls_index_to_set
Definition: fiber.c:38
START_TEST(fiber)
Definition: fiber.c:396
#define win_skip
Definition: test.h:141
static void * fls_value_to_set
Definition: fiber.c:39
LPVOID WINAPI CreateFiber(_In_ SIZE_T dwStackSize, _In_ LPFIBER_START_ROUTINE lpStartAddress, _In_opt_ LPVOID lpParameter)
Definition: fiber.c:174