Release 0.9.61.
[wine.git] / dlls / kernel32 / tests / alloc.c
blob8cb0915c5ea4079f10d5f25196f69f3bb9ed206a
1 /*
2 * Unit test suite for memory allocation functions.
4 * Copyright 2002 Geoffrey Hausheer
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.
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.
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
21 #include <stdarg.h>
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
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
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)
47 static void test_Heap(void)
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;
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");
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.
69 memchunk=10*sysInfo.dwPageSize;
70 heap=HeapCreate(0,2*memchunk,5*memchunk);
72 /* Check that HeapCreate allocated the right amount of ram */
73 todo_wine {
74 /* Today HeapCreate seems to return a memory block larger than specified.
75 MSDN says the maximum heap size should be dwMaximumSize rounded up to the
76 nearest page boundary
78 mem1=HeapAlloc(heap,0,5*memchunk+1);
79 ok(mem1==NULL,"HeapCreate allocated more Ram than it should have\n");
80 HeapFree(heap,0,mem1);
83 /* Check that a normal alloc works */
84 mem1=HeapAlloc(heap,0,memchunk);
85 ok(mem1!=NULL,"HeapAlloc failed\n");
86 if(mem1) {
87 ok(HeapSize(heap,0,mem1)>=memchunk, "HeapAlloc should return a big enough memory block\n");
90 /* Check that a 'zeroing' alloc works */
91 mem2=HeapAlloc(heap,HEAP_ZERO_MEMORY,memchunk);
92 ok(mem2!=NULL,"HeapAlloc failed\n");
93 if(mem2) {
94 ok(HeapSize(heap,0,mem2)>=memchunk,"HeapAlloc should return a big enough memory block\n");
95 error=0;
96 for(i=0;i<memchunk;i++) {
97 if(mem2[i]!=0) {
98 error=1;
101 ok(!error,"HeapAlloc should have zeroed out it's allocated memory\n");
104 /* Check that HeapAlloc returns NULL when requested way too much memory */
105 mem3=HeapAlloc(heap,0,5*memchunk);
106 ok(mem3==NULL,"HeapAlloc should return NULL\n");
107 if(mem3) {
108 ok(HeapFree(heap,0,mem3),"HeapFree didn't pass successfully\n");
111 /* Check that HeapRealloc works */
112 mem2a=HeapReAlloc(heap,HEAP_ZERO_MEMORY,mem2,memchunk+5*sysInfo.dwPageSize);
113 ok(mem2a!=NULL,"HeapReAlloc failed\n");
114 if(mem2a) {
115 ok(HeapSize(heap,0,mem2a)>=memchunk+5*sysInfo.dwPageSize,"HeapReAlloc failed\n");
116 error=0;
117 for(i=0;i<5*sysInfo.dwPageSize;i++) {
118 if(mem2a[memchunk+i]!=0) {
119 error=1;
122 ok(!error,"HeapReAlloc should have zeroed out it's allocated memory\n");
125 /* Check that HeapRealloc honours HEAP_REALLOC_IN_PLACE_ONLY */
126 error=0;
127 mem1a=HeapReAlloc(heap,HEAP_REALLOC_IN_PLACE_ONLY,mem1,memchunk+sysInfo.dwPageSize);
128 if(mem1a!=NULL) {
129 if(mem1a!=mem1) {
130 error=1;
133 ok(mem1a==NULL || error==0,"HeapReAlloc didn't honour HEAP_REALLOC_IN_PLACE_ONLY\n");
135 /* Check that HeapFree works correctly */
136 if(mem1a) {
137 ok(HeapFree(heap,0,mem1a),"HeapFree failed\n");
138 } else {
139 ok(HeapFree(heap,0,mem1),"HeapFree failed\n");
141 if(mem2a) {
142 ok(HeapFree(heap,0,mem2a),"HeapFree failed\n");
143 } else {
144 ok(HeapFree(heap,0,mem2),"HeapFree failed\n");
147 /* 0-length buffer */
148 mem1 = HeapAlloc(heap, 0, 0);
149 ok(mem1 != NULL, "Reserved memory\n");
151 dwSize = HeapSize(heap, 0, mem1);
152 /* should work with 0-length buffer */
153 ok(dwSize < 0xFFFFFFFF, "The size of the 0-length buffer\n");
154 ok(HeapFree(heap, 0, mem1), "Freed the 0-length buffer\n");
156 /* Check that HeapDestry works */
157 ok(HeapDestroy(heap),"HeapDestroy failed\n");
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
168 /* In addition, these features aren't being tested
169 GMEM_DISCARDABLE
170 GMEM_NOCOMPACT
172 static void test_Global(void)
174 ULONG memchunk;
175 HGLOBAL mem1,mem2,mem2a,mem2b;
176 UCHAR *mem2ptr;
177 UINT error,i;
178 memchunk=100000;
180 SetLastError(NO_ERROR);
181 /* Check that a normal alloc works */
182 mem1=GlobalAlloc(0,memchunk);
183 ok(mem1!=NULL,"GlobalAlloc failed\n");
184 if(mem1) {
185 ok(GlobalSize(mem1)>=memchunk, "GlobalAlloc should return a big enough memory block\n");
188 /* Check that a 'zeroing' alloc works */
189 mem2=GlobalAlloc(GMEM_ZEROINIT,memchunk);
190 ok(mem2!=NULL,"GlobalAlloc failed: error=%d\n",GetLastError());
191 if(mem2) {
192 ok(GlobalSize(mem2)>=memchunk,"GlobalAlloc should return a big enough memory block\n");
193 mem2ptr=GlobalLock(mem2);
194 ok(mem2ptr==mem2,"GlobalLock should have returned the same memory as was allocated\n");
195 if(mem2ptr) {
196 error=0;
197 for(i=0;i<memchunk;i++) {
198 if(mem2ptr[i]!=0) {
199 error=1;
202 ok(!error,"GlobalAlloc should have zeroed out it's allocated memory\n");
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 if(mem2a!=NULL) {
209 mem2=mem2a;
210 mem2ptr=GlobalLock(mem2a);
211 ok(mem2ptr!=NULL && !GlobalUnlock(mem2a)&&GetLastError()==NO_ERROR,
212 "Converting from FIXED to MOVEABLE didn't REALLY work\n");
215 /* Check that ReAllocing memory works as expected */
216 mem2a=GlobalReAlloc(mem2,2*memchunk,GMEM_MOVEABLE | GMEM_ZEROINIT);
217 ok(mem2a!=NULL,"GlobalReAlloc failed\n");
218 if(mem2a) {
219 ok(GlobalSize(mem2a)>=2*memchunk,"GlobalReAlloc failed\n");
220 mem2ptr=GlobalLock(mem2a);
221 ok(mem2ptr!=NULL,"GlobalLock Failed\n");
222 if(mem2ptr) {
223 error=0;
224 for(i=0;i<memchunk;i++) {
225 if(mem2ptr[memchunk+i]!=0) {
226 error=1;
229 ok(!error,"GlobalReAlloc should have zeroed out it's allocated memory\n");
231 /* Check that GlobalHandle works */
232 mem2b=GlobalHandle(mem2ptr);
233 ok(mem2b==mem2a,"GlobalHandle didn't return the correct memory handle\n");
235 /* Check that we can't discard locked memory */
236 mem2b=GlobalDiscard(mem2a);
237 if(mem2b==NULL) {
238 ok(!GlobalUnlock(mem2a) && GetLastError()==NO_ERROR,"GlobalUnlock Failed\n");
242 if(mem1) {
243 ok(GlobalFree(mem1)==NULL,"GlobalFree failed\n");
245 if(mem2a) {
246 ok(GlobalFree(mem2a)==NULL,"GlobalFree failed\n");
247 } else {
248 ok(GlobalFree(mem2)==NULL,"GlobalFree failed\n");
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
260 /* In addition, these features aren't being tested
261 LMEM_DISCARDABLE
262 LMEM_NOCOMPACT
264 static void test_Local(void)
266 ULONG memchunk;
267 HLOCAL mem1,mem2,mem2a,mem2b;
268 UCHAR *mem2ptr;
269 UINT error,i;
270 memchunk=100000;
272 /* Check that a normal alloc works */
273 mem1=LocalAlloc(0,memchunk);
274 ok(mem1!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
275 if(mem1) {
276 ok(LocalSize(mem1)>=memchunk, "LocalAlloc should return a big enough memory block\n");
279 /* Check that a 'zeroing' and lock alloc works */
280 mem2=LocalAlloc(LMEM_ZEROINIT|LMEM_MOVEABLE,memchunk);
281 ok(mem2!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
282 if(mem2) {
283 ok(LocalSize(mem2)>=memchunk,"LocalAlloc should return a big enough memory block\n");
284 mem2ptr=LocalLock(mem2);
285 ok(mem2ptr!=NULL,"LocalLock: error=%d\n",GetLastError());
286 if(mem2ptr) {
287 error=0;
288 for(i=0;i<memchunk;i++) {
289 if(mem2ptr[i]!=0) {
290 error=1;
293 ok(!error,"LocalAlloc should have zeroed out it's allocated memory\n");
294 SetLastError(0);
295 error=LocalUnlock(mem2);
296 ok(error==0 && GetLastError()==NO_ERROR,
297 "LocalUnlock Failed: rc=%d err=%d\n",error,GetLastError());
300 mem2a=LocalFree(mem2);
301 ok(mem2a==NULL, "LocalFree failed: %p\n",mem2a);
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=%d\n",GetLastError());
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=%d\n",GetLastError());
310 if(mem2a) {
311 ok(LocalSize(mem2a)>=2*memchunk,"LocalReAlloc failed\n");
312 mem2ptr=LocalLock(mem2a);
313 ok(mem2ptr!=NULL,"LocalLock Failed\n");
314 if(mem2ptr) {
315 error=0;
316 for(i=0;i<memchunk;i++) {
317 if(mem2ptr[memchunk+i]!=0) {
318 error=1;
321 ok(!error,"LocalReAlloc should have zeroed out it's allocated memory\n");
322 /* Check that LocalHandle works */
323 mem2b=LocalHandle(mem2ptr);
324 ok(mem2b==mem2a,"LocalHandle didn't return the correct memory handle\n");
325 /* Check that we can't discard locked memory */
326 mem2b=LocalDiscard(mem2a);
327 ok(mem2b==NULL,"Discarded memory we shouldn't have\n");
328 SetLastError(NO_ERROR);
329 ok(!LocalUnlock(mem2a) && GetLastError()==NO_ERROR, "LocalUnlock Failed\n");
332 if(mem1) {
333 ok(LocalFree(mem1)==NULL,"LocalFree failed\n");
335 if(mem2a) {
336 ok(LocalFree(mem2a)==NULL,"LocalFree failed\n");
337 } else {
338 ok(LocalFree(mem2)==NULL,"LocalFree failed\n");
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
360 static void test_Virtual(void)
362 SYSTEM_INFO sysInfo;
363 ULONG memchunk;
364 UCHAR *mem1;
365 UINT error,i;
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\n");
372 /* Choose a reasonable allocation size */
373 memchunk=10*sysInfo.dwPageSize;
375 /* Check that a normal alloc works */
376 mem1=VirtualAlloc(NULL,memchunk,MEM_COMMIT,PAGE_READWRITE);
377 ok(mem1!=NULL,"VirtualAlloc failed\n");
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;
386 ok(!error,"VirtualAlloc did not initialize memory to '0's\n");
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;
395 ok(!error,"Virtual memory was not writable\n");
397 ok(VirtualFree(mem1,0,MEM_RELEASE),"VirtualFree failed\n");
399 START_TEST(alloc)
401 test_Heap();
402 test_Global();
403 test_Local();
404 test_Virtual();