Win9x does not convert FIXED to MOVEABLE. It also discards locked
[wine/multimedia.git] / dlls / kernel / tests / alloc.c
blob4c4a23eb36bc8c6d4403a412eadcccad6b326c6d
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 if(mem1) {
81 HeapFree(heap,0,mem1);
85 /* Check that a normal alloc works */
86 mem1=HeapAlloc(heap,0,memchunk);
87 ok(mem1!=NULL,"HeapAlloc failed\n");
88 if(mem1) {
89 ok(HeapSize(heap,0,mem1)>=memchunk, "HeapAlloc should return a big enough memory block\n");
92 /* Check that a 'zeroing' alloc works */
93 mem2=HeapAlloc(heap,HEAP_ZERO_MEMORY,memchunk);
94 ok(mem2!=NULL,"HeapAlloc failed\n");
95 if(mem2) {
96 ok(HeapSize(heap,0,mem2)>=memchunk,"HeapAlloc should return a big enough memory block\n");
97 error=0;
98 for(i=0;i<memchunk;i++) {
99 if(mem2[i]!=0) {
100 error=1;
103 ok(!error,"HeapAlloc should have zeroed out it's allocated memory\n");
106 /* Check that HeapAlloc returns NULL when requested way too much memory */
107 mem3=HeapAlloc(heap,0,5*memchunk);
108 ok(mem3==NULL,"HeapAlloc should return NULL\n");
109 if(mem3) {
110 ok(HeapFree(heap,0,mem3),"HeapFree didn't pass successfully\n");
113 /* Check that HeapRealloc works */
114 mem2a=HeapReAlloc(heap,HEAP_ZERO_MEMORY,mem2,memchunk+5*sysInfo.dwPageSize);
115 ok(mem2a!=NULL,"HeapReAlloc failed\n");
116 if(mem2a) {
117 ok(HeapSize(heap,0,mem2a)>=memchunk+5*sysInfo.dwPageSize,"HeapReAlloc failed\n");
118 error=0;
119 for(i=0;i<5*sysInfo.dwPageSize;i++) {
120 if(mem2a[memchunk+i]!=0) {
121 error=1;
124 ok(!error,"HeapReAlloc should have zeroed out it's allocated memory\n");
127 /* Check that HeapRealloc honours HEAP_REALLOC_IN_PLACE_ONLY */
128 error=0;
129 mem1a=HeapReAlloc(heap,HEAP_REALLOC_IN_PLACE_ONLY,mem1,memchunk+sysInfo.dwPageSize);
130 if(mem1a!=NULL) {
131 if(mem1a!=mem1) {
132 error=1;
135 ok(mem1a==NULL || error==0,"HeapReAlloc didn't honour HEAP_REALLOC_IN_PLACE_ONLY\n");
137 /* Check that HeapFree works correctly */
138 if(mem1a) {
139 ok(HeapFree(heap,0,mem1a),"HeapFree failed\n");
140 } else {
141 ok(HeapFree(heap,0,mem1),"HeapFree failed\n");
143 if(mem2a) {
144 ok(HeapFree(heap,0,mem2a),"HeapFree failed\n");
145 } else {
146 ok(HeapFree(heap,0,mem2),"HeapFree failed\n");
149 /* 0-length buffer */
150 mem1 = HeapAlloc(heap, 0, 0);
151 ok(mem1 != NULL, "Reserved memory\n");
153 dwSize = HeapSize(heap, 0, mem1);
154 /* should work with 0-length buffer */
155 ok((dwSize >= 0) && (dwSize < 0xFFFFFFFF),
156 "The size of the 0-length buffer\n");
157 ok(HeapFree(heap, 0, mem1), "Freed the 0-length buffer\n");
159 /* Check that HeapDestry works */
160 ok(HeapDestroy(heap),"HeapDestroy failed\n");
163 /* The following functions don't have tests, because either I don't know how
164 to test them, or they are WinNT only, or require multiple threads.
165 Since the last two issues shouldn't really stop the tests from being
166 written, assume for now that it is all due to the first case
167 GlobalFlags
168 GlobalMemoryStatus
169 GlobalMemoryStatusEx
171 /* In addition, these features aren't being tested
172 GMEM_DISCADABLE
173 GMEM_NOCOMPACT
175 static void test_Global(void)
177 ULONG memchunk;
178 HGLOBAL mem1,mem2,mem2a,mem2b;
179 UCHAR *mem2ptr;
180 UINT error,i;
181 memchunk=100000;
183 SetLastError(NO_ERROR);
184 /* Check that a normal alloc works */
185 mem1=GlobalAlloc(0,memchunk);
186 ok(mem1!=NULL,"GlobalAlloc failed\n");
187 if(mem1) {
188 ok(GlobalSize(mem1)>=memchunk, "GlobalAlloc should return a big enough memory block\n");
191 /* Check that a 'zeroing' alloc works */
192 mem2=GlobalAlloc(GMEM_ZEROINIT,memchunk);
193 ok(mem2!=NULL,"GlobalAlloc failed: error=%ld\n",GetLastError());
194 if(mem2) {
195 ok(GlobalSize(mem2)>=memchunk,"GlobalAlloc should return a big enough memory block\n");
196 mem2ptr=GlobalLock(mem2);
197 ok(mem2ptr==mem2,"GlobalLock should have returned the same memory as was allocated\n");
198 if(mem2ptr) {
199 error=0;
200 for(i=0;i<memchunk;i++) {
201 if(mem2ptr[i]!=0) {
202 error=1;
205 ok(!error,"GlobalAlloc should have zeroed out it's allocated memory\n");
208 /* Check that GlobalReAlloc works */
209 /* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */
210 mem2a=GlobalReAlloc(mem2,0,GMEM_MODIFY | GMEM_MOVEABLE);
211 if(mem2a!=NULL) {
212 mem2=mem2a;
213 mem2ptr=GlobalLock(mem2a);
214 ok(mem2ptr!=NULL && !GlobalUnlock(mem2a)&&GetLastError()==NO_ERROR,
215 "Converting from FIXED to MOVEABLE didn't REALLY work\n");
218 /* Check that ReAllocing memory works as expected */
219 mem2a=GlobalReAlloc(mem2,2*memchunk,GMEM_MOVEABLE | GMEM_ZEROINIT);
220 ok(mem2a!=NULL,"GlobalReAlloc failed\n");
221 if(mem2a) {
222 ok(GlobalSize(mem2a)>=2*memchunk,"GlobalReAlloc failed\n");
223 mem2ptr=GlobalLock(mem2a);
224 ok(mem2ptr!=NULL,"GlobalLock Failed\n");
225 if(mem2ptr) {
226 error=0;
227 for(i=0;i<memchunk;i++) {
228 if(mem2ptr[memchunk+i]!=0) {
229 error=1;
232 ok(!error,"GlobalReAlloc should have zeroed out it's allocated memory\n");
234 /* Check that GlobalHandle works */
235 mem2b=GlobalHandle(mem2ptr);
236 ok(mem2b==mem2a,"GlobalHandle didn't return the correct memory handle\n");
238 /* Check that we can't discard locked memory */
239 mem2b=GlobalDiscard(mem2a);
240 if(mem2b==NULL) {
241 ok(!GlobalUnlock(mem2a) && GetLastError()==NO_ERROR,"GlobalUnlock Failed\n");
245 if(mem1) {
246 ok(GlobalFree(mem1)==NULL,"GlobalFree failed\n");
248 if(mem2a) {
249 ok(GlobalFree(mem2a)==NULL,"GlobalFree failed\n");
250 } else {
251 ok(GlobalFree(mem2)==NULL,"GlobalFree failed\n");
256 /* The following functions don't have tests, because either I don't know how
257 to test them, or they are WinNT only, or require multiple threads.
258 Since the last two issues shouldn't really stop the tests from being
259 written, assume for now that it is all due to the first case
260 LocalDiscard
261 LocalFlags
263 /* In addition, these features aren't being tested
264 LMEM_DISCADABLE
265 LMEM_NOCOMPACT
267 static void test_Local(void)
269 ULONG memchunk;
270 HLOCAL mem1,mem2,mem2a,mem2b;
271 UCHAR *mem2ptr;
272 UINT error,i;
273 memchunk=100000;
275 /* Check that a normal alloc works */
276 mem1=LocalAlloc(0,memchunk);
277 ok(mem1!=NULL,"LocalAlloc failed: error=%ld\n",GetLastError());
278 if(mem1) {
279 ok(LocalSize(mem1)>=memchunk, "LocalAlloc should return a big enough memory block\n");
282 /* Check that a 'zeroing' and lock alloc works */
283 mem2=LocalAlloc(LMEM_ZEROINIT|LMEM_MOVEABLE,memchunk);
284 ok(mem2!=NULL,"LocalAlloc failed: error=%ld\n",GetLastError());
285 if(mem2) {
286 ok(LocalSize(mem2)>=memchunk,"LocalAlloc should return a big enough memory block\n");
287 mem2ptr=LocalLock(mem2);
288 ok(mem2ptr!=NULL,"LocalLock: error=%ld\n",GetLastError());
289 if(mem2ptr) {
290 error=0;
291 for(i=0;i<memchunk;i++) {
292 if(mem2ptr[i]!=0) {
293 error=1;
296 ok(!error,"LocalAlloc should have zeroed out it's allocated memory\n");
297 SetLastError(0);
298 error=LocalUnlock(mem2);
299 ok(error==0 && GetLastError()==NO_ERROR,
300 "LocalUnlock Failed: rc=%d err=%ld\n",error,GetLastError());
303 mem2a=LocalFree(mem2);
304 ok(mem2a==NULL, "LocalFree failed: %p\n",mem2a);
306 /* Reallocate mem2 as moveable memory */
307 mem2=LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,memchunk);
308 ok(mem2!=NULL, "LocalAlloc failed to create moveable memory, error=%ld\n",GetLastError());
310 /* Check that ReAllocing memory works as expected */
311 mem2a=LocalReAlloc(mem2,2*memchunk,LMEM_MOVEABLE | LMEM_ZEROINIT);
312 ok(mem2a!=NULL,"LocalReAlloc failed, error=%ld\n",GetLastError());
313 if(mem2a) {
314 ok(LocalSize(mem2a)>=2*memchunk,"LocalReAlloc failed\n");
315 mem2ptr=LocalLock(mem2a);
316 ok(mem2ptr!=NULL,"LocalLock Failed\n");
317 if(mem2ptr) {
318 error=0;
319 for(i=0;i<memchunk;i++) {
320 if(mem2ptr[memchunk+i]!=0) {
321 error=1;
324 ok(!error,"LocalReAlloc should have zeroed out it's allocated memory\n");
325 /* Check that LocalHandle works */
326 mem2b=LocalHandle(mem2ptr);
327 ok(mem2b==mem2a,"LocalHandle didn't return the correct memory handle\n");
328 /* Check that we can't discard locked memory */
329 mem2b=LocalDiscard(mem2a);
330 ok(mem2b==NULL,"Discarded memory we shouldn't have\n");
331 SetLastError(NO_ERROR);
332 ok(!LocalUnlock(mem2a) && GetLastError()==NO_ERROR, "LocalUnlock Failed\n");
335 if(mem1) {
336 ok(LocalFree(mem1)==NULL,"LocalFree failed\n");
338 if(mem2a) {
339 ok(LocalFree(mem2a)==NULL,"LocalFree failed\n");
340 } else {
341 ok(LocalFree(mem2)==NULL,"LocalFree failed\n");
345 /* The Virtual* routines are not tested as thoroughly,
346 since I don't really understand how to use them correctly :)
347 The following routines are not tested at all
348 VirtualAllocEx
349 VirtualFreeEx
350 VirtualLock
351 VirtualProtect
352 VirtualProtectEx
353 VirtualQuery
354 VirtualQueryEx
355 VirtualUnlock
356 And the only features (flags) being tested are
357 MEM_COMMIT
358 MEM_RELEASE
359 PAGE_READWRITE
360 Testing the rest requires using exceptions, which I really don't
361 understand well
363 static void test_Virtual(void)
365 SYSTEM_INFO sysInfo;
366 ULONG memchunk;
367 UCHAR *mem1;
368 UINT error,i;
370 /* Retrieve the page size for this system */
371 sysInfo.dwPageSize=0;
372 GetSystemInfo(&sysInfo);
373 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
375 /* Choose a reasonable allocation size */
376 memchunk=10*sysInfo.dwPageSize;
378 /* Check that a normal alloc works */
379 mem1=VirtualAlloc(NULL,memchunk,MEM_COMMIT,PAGE_READWRITE);
380 ok(mem1!=NULL,"VirtualAlloc failed\n");
381 if(mem1) {
382 /* check that memory is initialized to 0 */
383 error=0;
384 for(i=0;i<memchunk;i++) {
385 if(mem1[i]!=0) {
386 error=1;
389 ok(!error,"VirtualAlloc did not initialize memory to '0's\n");
390 /* Check that we can read/write to memory */
391 error=0;
392 for(i=0;i<memchunk;i+=100) {
393 mem1[i]='a';
394 if(mem1[i]!='a') {
395 error=1;
398 ok(!error,"Virtual memory was not writable\n");
400 ok(VirtualFree(mem1,0,MEM_RELEASE),"VirtualFree failed\n");
402 START_TEST(alloc)
404 test_Heap();
405 test_Global();
406 test_Local();
407 test_Virtual();