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