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