Provide stubs for Create/DeleteTimerQueueTimer.
[wine] / dlls / kernel / tests / alloc.c
1 /*
2  * Unit test suite for memory allocation functions.
3  *
4  * Copyright 2002 Geoffrey Hausheer
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "wine/test.h"
22 #include "winbase.h"
23 #include "winerror.h"
24
25 /* Currently Wine doesn't have macros for LocalDiscard and GlobalDiscard
26    so I am disableing the checks for them.  These macros are equivalent
27    to reallocing '0' bytes, so we try that instead
28 */
29 #define DISCARD_DEFINED 0
30
31 /* The following functions don't have tests, because either I don't know how
32    to test them, or they are WinNT only, or require multiple threads.
33    Since the last two issues shouldn't really stop the tests from being
34    written, assume for now that it is all due to the first case
35        HeapCompact
36        HeapLock
37        HeapQueryInformation
38        HeapSetInformation
39        HeapUnlock
40        HeapValidate
41        HeapWalk
42 */
43 /* In addition, these features aren't being tested
44        HEAP_NO_SERIALIZE
45        HEAP_GENERATE_EXCEPTIONS
46        STATUS_ACCESS_VIOLATION (error code from HeapAlloc)
47 */
48
49 static void test_Heap(void)
50 {
51     SYSTEM_INFO sysInfo;
52     ULONG memchunk;
53     HANDLE heap;
54     LPVOID mem1,mem1a,mem3;
55     UCHAR *mem2,*mem2a;
56     UINT error,i;
57     DWORD dwSize;
58
59 /* Retreive the page size for this system */
60     sysInfo.dwPageSize=0;
61     GetSystemInfo(&sysInfo);
62     ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size");
63
64 /* Create a Heap with a minimum and maximum size */
65 /* Note that Windows and Wine seem to behave a bit differently with respect
66    to memory allocation.  In Windows, you can't access all the memory
67    specified in the heap (due to overhead), so choosing a reasonable maximum
68    size for the heap was done mostly by trial-and-error on Win2k.  It may need
69    more tweaking for otherWindows variants.
70 */
71     memchunk=10*sysInfo.dwPageSize;
72     heap=HeapCreate((DWORD)NULL,2*memchunk,5*memchunk);
73
74 /* Check that HeapCreate allocated the right amount of ram */
75     todo_wine {
76     /* Today HeapCreate seems to return a memory block larger than specified.
77        MSDN says the maximum heap size should be dwMaximumSize rounded up to the
78        nearest page boundary
79     */
80       mem1=HeapAlloc(heap,(DWORD)NULL,5*memchunk+1);
81       ok(mem1==NULL,"HeapCreate allocated more Ram than it should have");
82       if(mem1) {
83         HeapFree(heap,(DWORD)NULL,mem1);
84       }
85     }
86
87 /* Check that a normal alloc works */
88     mem1=HeapAlloc(heap,(DWORD)NULL,memchunk);
89     ok(mem1!=NULL,"HeapAlloc failed");
90     if(mem1) {
91       ok(HeapSize(heap,(DWORD)NULL,mem1)>=memchunk, "HeapAlloc should return a big enough memory block");
92     }
93
94 /* Check that a 'zeroing' alloc works */
95     mem2=(UCHAR *)HeapAlloc(heap,HEAP_ZERO_MEMORY,memchunk);
96     ok(mem2!=NULL,"HeapAlloc failed");
97     if(mem2) {
98       ok(HeapSize(heap,(DWORD)NULL,mem2)>=memchunk,"HeapAlloc should return a big enough memory block");
99       error=0;
100       for(i=0;i<memchunk;i++) {
101         if(mem2[i]!=0) {
102           error=1;
103         }
104       }
105       ok(!error,"HeapAlloc should have zeroed out it's allocated memory");
106     }
107
108 /* Check that HeapAlloc returns NULL when requested way too much memory */
109     mem3=HeapAlloc(heap,(DWORD)NULL,5*memchunk);
110     ok(mem3==NULL,"HeapAlloc should return NULL");
111     if(mem3) {
112       ok(HeapFree(heap,(DWORD)NULL,mem3),"HeapFree didn't pass successfully");
113     }
114
115 /* Check that HeapRealloc works */
116     mem2a=(UCHAR *)HeapReAlloc(heap,HEAP_ZERO_MEMORY,mem2,memchunk+5*sysInfo.dwPageSize);
117     ok(mem2a!=NULL,"HeapReAlloc failed");
118     if(mem2a) {
119       ok(HeapSize(heap,(DWORD)NULL,mem2a)>=memchunk+5*sysInfo.dwPageSize,"HeapReAlloc failed");
120       error=0;
121       for(i=0;i<5*sysInfo.dwPageSize;i++) {
122         if(mem2a[memchunk+i]!=0) {
123           error=1;
124         }
125       }
126       ok(!error,"HeapReAlloc should have zeroed out it's allocated memory");
127     }
128
129 /* Check that HeapRealloc honours HEAP_REALLOC_IN_PLACE_ONLY */
130     error=0;
131     mem1a=HeapReAlloc(heap,HEAP_REALLOC_IN_PLACE_ONLY,mem1,memchunk+sysInfo.dwPageSize);
132     if(mem1a!=NULL) {
133       if(mem1a!=mem1) {
134         error=1;
135       }
136     }
137     ok(mem1a==NULL || error==0,"HeapReAlloc didn't honour HEAP_REALLOC_IN_PLACE_ONLY");
138
139 /* Check that HeapFree works correctly */
140    if(mem1a) {
141      ok(HeapFree(heap,(DWORD)NULL,mem1a),"HeapFree failed");
142    } else {
143      ok(HeapFree(heap,(DWORD)NULL,mem1),"HeapFree failed");
144    }
145    if(mem2a) {
146      ok(HeapFree(heap,(DWORD)NULL,mem2a),"HeapFree failed");
147    } else {
148      ok(HeapFree(heap,(DWORD)NULL,mem2),"HeapFree failed");
149    }
150
151    /* take just freed pointer */
152    if (mem1a)
153        mem1 = mem1a;
154
155    /* try to free it one more time */
156    HeapFree(heap, 0, mem1);
157
158    dwSize = HeapSize(heap, 0, mem1);
159    ok(dwSize == 0xFFFFFFFF, "The size");
160
161    /* 0-length buffer */
162    mem1 = HeapAlloc(heap, 0, 0);
163    ok(mem1 != NULL, "Reserved memory");
164
165    dwSize = HeapSize(heap, 0, mem1);
166    /* should work with 0-length buffer */
167    ok((dwSize >= 0) && (dwSize < 0xFFFFFFFF),
168       "The size of the 0-length buffer");
169    ok(HeapFree(heap, 0, mem1), "Freed the 0-length buffer");
170
171 /* Check that HeapDestry works */
172    ok(HeapDestroy(heap),"HeapDestroy failed");
173 }
174
175 /* The following functions don't have tests, because either I don't know how
176    to test them, or they are WinNT only, or require multiple threads.
177    Since the last two issues shouldn't really stop the tests from being
178    written, assume for now that it is all due to the first case
179        GlobalFlags
180        GlobalMemoryStatus
181        GlobalMemoryStatusEx
182 */
183 /* In addition, these features aren't being tested
184        GMEM_DISCADABLE
185        GMEM_NOCOMPACT
186 */
187 static void test_Global(void)
188 {
189     ULONG memchunk;
190     HGLOBAL mem1,mem2,mem2a,mem2b;
191     UCHAR *mem2ptr;
192     UINT error,i;
193     memchunk=100000;
194
195     SetLastError(NO_ERROR);
196 /* Check that a normal alloc works */
197     mem1=GlobalAlloc((UINT)NULL,memchunk);
198     ok(mem1!=(HGLOBAL)NULL,"GlobalAlloc failed");
199     if(mem1) {
200       ok(GlobalSize(mem1)>=memchunk, "GlobalAlloc should return a big enough memory block");
201     }
202
203 /* Check that a 'zeroing' alloc works */
204     mem2=GlobalAlloc(GMEM_ZEROINIT,memchunk);
205     ok(mem2!=(HGLOBAL)NULL,"GlobalAlloc failed");
206     if(mem2) {
207       ok(GlobalSize(mem2)>=memchunk,"GlobalAlloc should return a big enough memory block");
208       mem2ptr=(UCHAR *)GlobalLock(mem2);
209       ok(mem2ptr==(UCHAR *)mem2,"GlobalLock should have returned the same memory as was allocated");
210       if(mem2ptr) {
211         error=0;
212         for(i=0;i<memchunk;i++) {
213           if(mem2ptr[i]!=0) {
214             error=1;
215           }
216         }
217         ok(!error,"GlobalAlloc should have zeroed out it's allocated memory");
218       }
219    }
220 /* Check that GlobalReAlloc works */
221 /* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */
222     mem2a=GlobalReAlloc(mem2,0,GMEM_MODIFY | GMEM_MOVEABLE);
223     ok(mem2a!=(HGLOBAL)NULL,"GlobalReAlloc failed to convert FIXED to MOVEABLE");
224     if(mem2a!=(HGLOBAL)NULL) {
225       mem2=mem2a;
226     }
227     mem2ptr=GlobalLock(mem2a);
228     ok(mem2ptr!=NULL && !GlobalUnlock(mem2a)&&GetLastError()==NO_ERROR,
229         "Converting from FIXED to MOVEABLE didn't REALLY work");
230
231 /* Check that ReAllocing memory works as expected */
232     mem2a=GlobalReAlloc(mem2,2*memchunk,GMEM_MOVEABLE | GMEM_ZEROINIT);
233     ok(mem2a!=(HGLOBAL)NULL,"GlobalReAlloc failed");
234     if(mem2a) {
235       ok(GlobalSize(mem2a)>=2*memchunk,"GlobalReAlloc failed");
236       mem2ptr=(UCHAR *)GlobalLock(mem2a);
237       ok(mem2ptr!=NULL,"GlobalLock Failed.");
238       if(mem2ptr) {
239         error=0;
240         for(i=0;i<memchunk;i++) {
241           if(mem2ptr[memchunk+i]!=0) {
242             error=1;
243           }
244         }
245         ok(!error,"GlobalReAlloc should have zeroed out it's allocated memory");
246
247 /* Check that GlobalHandle works */
248         mem2b=GlobalHandle(mem2ptr);
249         ok(mem2b==mem2a,"GlobalHandle didn't return the correct memory handle");
250
251 /* Check that we can't discard locked memory */
252 #if DISCARD_DEFINED
253         /* Wine doesn't include the GlobalDiscard function */
254         mem2b=GlobalDiscard(mem2a);
255         ok(mem2b==(HGLOBAL)NULL,"Discarded memory we shouldn't have");
256 #else
257         /* This is functionally equivalent to the above */
258         mem2b=GlobalReAlloc(mem2a,0,GMEM_MOVEABLE);
259         ok(mem2b==(HGLOBAL)NULL,"Discarded memory we shouldn't have");
260 #endif
261         ok(!GlobalUnlock(mem2a) && GetLastError()==NO_ERROR,"GlobalUnlock Failed.");
262       }
263     }
264     if(mem1) {
265       ok(GlobalFree(mem1)==(HGLOBAL)NULL,"GlobalFree failed");
266     }
267     if(mem2a) {
268       ok(GlobalFree(mem2a)==(HGLOBAL)NULL,"GlobalFree failed");
269     } else {
270       ok(GlobalFree(mem2)==(HGLOBAL)NULL,"GlobalFree failed");
271     }
272 }
273
274
275 /* The following functions don't have tests, because either I don't know how
276    to test them, or they are WinNT only, or require multiple threads.
277    Since the last two issues shouldn't really stop the tests from being
278    written, assume for now that it is all due to the first case
279        LocalDiscard
280        LocalFlags
281 */
282 /* In addition, these features aren't being tested
283        LMEM_DISCADABLE
284        LMEM_NOCOMPACT
285 */
286 static void test_Local(void)
287 {
288     ULONG memchunk;
289     HLOCAL mem1,mem2,mem2a,mem2b;
290     UCHAR *mem2ptr;
291     UINT error,i;
292     memchunk=100000;
293
294 /* Check that a normal alloc works */
295     mem1=LocalAlloc((UINT)NULL,memchunk);
296     ok(mem1!=(HLOCAL)NULL,"LocalAlloc failed");
297     if(mem1) {
298       ok(LocalSize(mem1)>=memchunk, "LocalAlloc should return a big enough memory block");
299     }
300
301 /* Check that a 'zeroing' alloc works */
302     mem2=LocalAlloc(LMEM_ZEROINIT,memchunk);
303     ok(mem2!=(HLOCAL)NULL,"LocalAlloc failed");
304     if(mem2) {
305       ok(LocalSize(mem2)>=memchunk,"LocalAlloc should return a big enough memory block");
306       mem2ptr=(UCHAR *)LocalLock(mem2);
307       ok(mem2ptr==(UCHAR *)mem2,"LocalLock Didn't lock it's memory");
308       if(mem2ptr) {
309         error=0;
310         for(i=0;i<memchunk;i++) {
311           if(mem2ptr[i]!=0) {
312             error=1;
313           }
314         }
315         ok(!error,"LocalAlloc should have zeroed out it's allocated memory");
316         ok(!(error=LocalUnlock(mem2)) &&
317                 (GetLastError()==ERROR_NOT_LOCKED || GetLastError()==NO_ERROR),
318            "LocalUnlock Failed.");
319       }
320     }
321
322 /* Reallocate mem2 as moveable memory */
323    mem2a=LocalFree(mem2);
324    mem2=LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,memchunk);
325    ok(mem2a==(HLOCAL)NULL && mem2!=(HLOCAL)NULL, "LocalAlloc failed to create moveable memory");
326
327 /* Check that ReAllocing memory works as expected */
328     mem2a=LocalReAlloc(mem2,2*memchunk,LMEM_MOVEABLE | LMEM_ZEROINIT);
329     ok(mem2a!=(HLOCAL)NULL,"LocalReAlloc failed");
330     if(mem2a) {
331       ok(LocalSize(mem2a)>=2*memchunk,"LocalReAlloc failed");
332       mem2ptr=(UCHAR *)LocalLock(mem2a);
333       ok(mem2ptr!=NULL,"LocalLock Failed.");
334       if(mem2ptr) {
335         error=0;
336         for(i=0;i<memchunk;i++) {
337           if(mem2ptr[memchunk+i]!=0) {
338             error=1;
339           }
340         }
341         ok(!error,"LocalReAlloc should have zeroed out it's allocated memory");
342 /* Check that LocalHandle works */
343         mem2b=LocalHandle(mem2ptr);
344         ok(mem2b==mem2a,"LocalHandle didn't return the correct memory handle");
345 /* Check that we can't discard locked memory */
346 #if DISCARD_DEFINED
347         /* Wine doesn't include the LocalDiscard function */
348         mem2b=LocalDiscard(mem2a);
349         ok(mem2b==(HLOCAL)NULL,"Discarded memory we shouldn't have");
350 #else
351         /* This is functionally equivalent to the above */
352         mem2b=LocalReAlloc(mem2a,0,GMEM_MOVEABLE);
353         ok(mem2b==(HLOCAL)NULL,"Discarded memory we shouldn't have");
354 #endif
355         SetLastError(NO_ERROR);
356         ok(!LocalUnlock(mem2a) && GetLastError()==NO_ERROR, "LocalUnlock Failed.");
357       }
358     }
359     if(mem1) {
360       ok(LocalFree(mem1)==(HLOCAL)NULL,"LocalFree failed");
361     }
362     if(mem2a) {
363       ok(LocalFree(mem2a)==(HLOCAL)NULL,"LocalFree failed");
364     } else {
365       ok(LocalFree(mem2)==(HLOCAL)NULL,"LocalFree failed");
366     }
367 }
368
369 /* The Virtual* routines are not tested as thoroughly,
370    since I don't really understand how to use them correctly :)
371    The following routines are not tested at all
372       VirtualAllocEx
373       VirtualFreeEx
374       VirtualLock
375       VirtualProtect
376       VirtualProtectEx
377       VirtualQuery
378       VirtualQueryEx
379       VirtualUnlock
380     And the only features (flags) being tested are
381       MEM_COMMIT
382       MEM_RELEASE
383       PAGE_READWRITE
384     Testing the rest requires using exceptions, which I really don't
385     understand well
386 */
387 static void test_Virtual(void)
388 {
389     SYSTEM_INFO sysInfo;
390     ULONG memchunk;
391     UCHAR *mem1;
392     UINT error,i;
393
394 /* Retreive the page size for this system */
395     sysInfo.dwPageSize=0;
396     GetSystemInfo(&sysInfo);
397     ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size");
398
399 /* Chhose a reasonable allocation size */
400     memchunk=10*sysInfo.dwPageSize;
401
402 /* Check that a normal alloc works */
403     mem1=VirtualAlloc(NULL,memchunk,MEM_COMMIT,PAGE_READWRITE);
404     ok(mem1!=NULL,"VirtualAlloc failed");
405     if(mem1) {
406 /* check that memory is initialized to 0 */
407       error=0;
408       for(i=0;i<memchunk;i++) {
409         if(mem1[i]!=0) {
410           error=1;
411         }
412       }
413       ok(!error,"VirtualAlloc did not initialize memory to '0's");
414 /* Check that we can read/write to memory */
415       error=0;
416       for(i=0;i<memchunk;i+=100) {
417         mem1[i]='a';
418         if(mem1[i]!='a') {
419           error=1;
420         }
421       }
422       ok(!error,"Virtual memory was not writable");
423     }
424     ok(VirtualFree(mem1,0,MEM_RELEASE),"VirtualFree failed");
425 }
426 START_TEST(alloc)
427 {
428     test_Heap();
429     test_Global();
430     test_Local();
431     test_Virtual();
432 }