msvcrt: Test and fix _mbsinc/_mbsninc.
[wine] / dlls / msvcrt / tests / heap.c
1 /*
2  * Unit test suite for memory functions
3  *
4  * Copyright 2003 Dimitrie O. Paun
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 <stdlib.h>
22 #include <malloc.h>
23 #include <errno.h>
24 #include "wine/test.h"
25
26 static void (*p_aligned_free)(void*) = NULL;
27 static void * (*p_aligned_malloc)(size_t,size_t) = NULL;
28 static void * (*p_aligned_offset_malloc)(size_t,size_t,size_t) = NULL;
29 static void * (*p_aligned_realloc)(void*,size_t,size_t) = NULL;
30 static void * (*p_aligned_offset_realloc)(void*,size_t,size_t,size_t) = NULL;
31
32 static void test_aligned_malloc(size_t size, size_t alignment)
33 {
34     void *mem;
35
36     mem = p_aligned_malloc(size, alignment);
37
38     if ((alignment & (alignment - 1)) == 0)
39         ok(mem != NULL, "_aligned_malloc(%d, %d) failed\n", size, alignment);
40     else
41         ok(mem == NULL, "_aligned_malloc(%d, %d) should have failed\n", size, alignment);
42
43     if (mem)
44     {
45         ok(((DWORD_PTR)mem & (alignment ? alignment - 1 : 0)) == 0,
46            "_aligned_malloc(%d, %d) not aligned: %p\n", size, alignment, mem);
47         if (winetest_debug > 1)
48         {
49             void *saved;
50             saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1));
51             trace("_aligned_malloc(%3d, %3d) returns %p, saved = %p, diff = %d\n",
52                   size, alignment, mem, saved, (char *)saved - (char *)mem);
53         }
54         p_aligned_free(mem);
55     }
56     else
57         ok(errno == EINVAL, "_aligned_malloc(%d, %d) errno: %d != %d\n", size, alignment, errno, EINVAL);
58 }
59
60 static void test_aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
61 {
62     void *mem;
63
64     mem = p_aligned_offset_malloc(size, alignment, offset);
65
66     if ((alignment & (alignment - 1)) == 0)
67         if (offset < size)
68             ok(mem != NULL, "_aligned_offset_malloc(%d, %d, %d) failed\n", size, alignment, offset);
69         else
70             ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d, %d) errno: %d != %d\n", size, alignment, offset, errno, EINVAL);
71     else
72         ok(mem == NULL, "_aligned_offset_malloc(%d, %d, %d) should have failed\n", size, alignment, offset);
73
74     if (mem)
75     {
76         ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0,
77            "_aligned_offset_malloc(%d, %d, %d) not aligned: %p\n", size, alignment, offset, mem);
78         if (winetest_debug > 1)
79         {
80             void *saved;
81             saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1));
82             trace("_aligned_offset_malloc(%3d, %3d, %3d) returns %p, saved = %p, diff = %d\n",
83                   size, alignment, offset, mem, saved, (char *)saved - (char *)mem);
84         }
85         p_aligned_free(mem);
86     }
87     else
88         ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d, %d) errno: %d != %d\n", size, alignment, offset, errno, EINVAL);
89 }
90
91 static void test_aligned_realloc(size_t size1, size_t size2, size_t alignment)
92 {
93     void *mem, *mem1, *mem2;
94
95     mem = p_aligned_malloc(size1, alignment);
96
97     if ((alignment & (alignment - 1)) == 0)
98         ok(mem != NULL, "_aligned_malloc(%d, %d) failed\n", size1, alignment);
99     else
100         ok(mem == NULL, "_aligned_malloc(%d, %d) should have failed\n", size1, alignment);
101
102     if (mem)
103     {
104         mem1 = malloc(size1);
105         if (mem1)
106         {
107             int i;
108             for (i = 0; i < size1; i++)
109                 ((char *)mem)[i] = i + 1;
110             memcpy(mem1, mem, size1);
111         }
112
113         ok(((DWORD_PTR)mem & (alignment ? alignment - 1 : 0)) == 0,
114            "_aligned_malloc(%d, %d) not aligned: %p\n", size1, alignment, mem);
115         if (winetest_debug > 1)
116         {
117             void *saved;
118             saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1));
119             trace("_aligned_malloc(%3d, %3d) returns %p, saved = %p, diff = %d\n",
120                   size1, alignment, mem, saved, (char *)saved - (char *)mem);
121         }
122
123         mem2 = p_aligned_realloc(mem, size2, alignment);
124
125         ok(mem2 != NULL, "_aligned_realloc(%p, %d, %d) failed\n", mem, size2, alignment);
126
127         if (mem2)
128         {
129             ok(((DWORD_PTR)mem2 & (alignment ? alignment - 1 : 0)) == 0,
130                "_aligned_realloc(%p, %d, %d) not aligned: %p\n", mem, size2, alignment, mem2);
131             if (winetest_debug > 1)
132             {
133                 void *saved;
134                 saved = *(void **)((DWORD_PTR)((char *)mem2 - sizeof(void *)) & ~(sizeof(void *) - 1));
135                 trace("_aligned_realloc(%p, %3d, %3d) returns %p, saved = %p, diff = %d\n",
136                       mem, size2, alignment, mem2, saved, (char *)saved - (char *)mem2);
137             }
138             if (mem1)
139             {
140                 ok(memcmp(mem2, mem1, min(size1, size2))==0, "_aligned_realloc(%p, %d, %d) has different data\n", mem, size2, alignment);
141                 if (memcmp(mem2, mem1, min(size1, size2)) && winetest_debug > 1)
142                 {
143                     int i;
144                     for (i = 0; i < min(size1, size2); i++)
145                     {
146                         if (((char *)mem2)[i] != ((char *)mem1)[i])
147                             trace("%d: %02x != %02x\n", i, ((char *)mem2)[i] & 0xff, ((char *)mem1)[i] & 0xff);
148                     }
149                 }
150             }
151         }
152         else
153             ok(errno == EINVAL, "_aligned_realloc(%p, %d, %d) errno: %d != %d\n", mem, size2, alignment, errno, EINVAL);
154
155         p_aligned_free(mem);
156         free(mem1);
157     }
158     else
159         ok(errno == EINVAL, "_aligned_malloc(%d, %d) errno: %d != %d\n", size1, alignment, errno, EINVAL);
160 }
161
162 static void test_aligned_offset_realloc(size_t size1, size_t size2, size_t alignment, size_t offset)
163 {
164     void *mem, *mem1, *mem2;
165
166     mem = p_aligned_offset_malloc(size1, alignment, offset);
167
168     if ((alignment & (alignment - 1)) == 0)
169         ok(mem != NULL, "_aligned_offset_malloc(%d, %d, %d) failed\n", size1, alignment, offset);
170     else
171         ok(mem == NULL, "_aligned_offset_malloc(%d, %d, %d) should have failed\n", size1, alignment, offset);
172
173     if (mem)
174     {
175         mem1 = malloc(size1);
176         if (mem1)
177         {
178             int i;
179             for (i = 0; i < size1; i++)
180                 ((char *)mem)[i] = i + 1;
181             memcpy(mem1, mem, size1);
182         }
183
184         ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0,
185            "_aligned_offset_malloc(%d, %d, %d) not aligned: %p\n", size1, alignment, offset, mem);
186         if (winetest_debug > 1)
187         {
188             void *saved;
189             saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1));
190             trace("_aligned_offset_malloc(%3d, %3d, %3d) returns %p, saved = %p, diff = %d\n",
191                   size1, alignment, offset, mem, saved, (char *)saved - (char *)mem);
192         }
193
194         mem2 = p_aligned_offset_realloc(mem, size2, alignment, offset);
195
196         ok(mem2 != NULL, "_aligned_offset_realloc(%p, %d, %d, %d) failed\n", mem, size2, alignment, offset);
197
198         if (mem2)
199         {
200             ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0,
201                "_aligned_offset_realloc(%p, %d, %d, %d) not aligned: %p\n", mem, size2, alignment, offset, mem2);
202             if (winetest_debug > 1)
203             {
204                 void *saved;
205                 saved = *(void **)((DWORD_PTR)((char *)mem2 - sizeof(void *)) & ~(sizeof(void *) - 1));
206                 trace("_aligned_offset_realloc(%p, %3d, %3d, %3d) returns %p, saved = %p, diff = %d\n",
207                       mem, size2, alignment, offset, mem2, saved, (char *)saved - (char *)mem2);
208             }
209             if (mem1)
210             {
211                 ok(memcmp(mem2, mem1, min(size1, size2))==0, "_aligned_offset_realloc(%p, %d, %d, %d) has different data\n", mem, size2, alignment, offset);
212                 if (memcmp(mem2, mem1, min(size1, size2)) && winetest_debug > 1)
213                 {
214                     int i;
215                     for (i = 0; i < min(size1, size2); i++)
216                     {
217                         if (((char *)mem2)[i] != ((char *)mem1)[i])
218                             trace("%d: %02x != %02x\n", i, ((char *)mem2)[i] & 0xff, ((char *)mem1)[i] & 0xff);
219                     }
220                 }
221             }
222         }
223         else
224             ok(errno == EINVAL, "_aligned_offset_realloc(%p, %d, %d, %d) errno: %d != %d\n", mem, size2, alignment, offset, errno, EINVAL);
225
226         p_aligned_free(mem);
227         free(mem1);
228     }
229     else
230         ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d) errno: %d != %d\n", size1, alignment, errno, EINVAL);
231 }
232
233 static void test_aligned(void)
234 {
235     HMODULE msvcrt = GetModuleHandle("msvcrt.dll");
236
237     if (msvcrt == NULL)
238         return;
239
240     p_aligned_free = (void*)GetProcAddress(msvcrt, "_aligned_free");
241     p_aligned_malloc = (void*)GetProcAddress(msvcrt, "_aligned_malloc");
242     p_aligned_offset_malloc = (void*)GetProcAddress(msvcrt, "_aligned_offset_malloc");
243     p_aligned_realloc = (void*)GetProcAddress(msvcrt, "_aligned_realloc");
244     p_aligned_offset_realloc = (void*)GetProcAddress(msvcrt, "_aligned_offset_realloc");
245
246     if (!p_aligned_free || !p_aligned_malloc || !p_aligned_offset_malloc || !p_aligned_realloc || !p_aligned_offset_realloc)
247     {
248         skip("aligned memory tests skipped\n");
249         return;
250     }
251
252     test_aligned_malloc(256, 0);
253     test_aligned_malloc(256, 1);
254     test_aligned_malloc(256, 2);
255     test_aligned_malloc(256, 3);
256     test_aligned_malloc(256, 4);
257     test_aligned_malloc(256, 8);
258     test_aligned_malloc(256, 16);
259     test_aligned_malloc(256, 32);
260     test_aligned_malloc(256, 64);
261     test_aligned_malloc(256, 127);
262     test_aligned_malloc(256, 128);
263
264     test_aligned_offset_malloc(256, 0, 0);
265     test_aligned_offset_malloc(256, 1, 0);
266     test_aligned_offset_malloc(256, 2, 0);
267     test_aligned_offset_malloc(256, 3, 0);
268     test_aligned_offset_malloc(256, 4, 0);
269     test_aligned_offset_malloc(256, 8, 0);
270     test_aligned_offset_malloc(256, 16, 0);
271     test_aligned_offset_malloc(256, 32, 0);
272     test_aligned_offset_malloc(256, 64, 0);
273     test_aligned_offset_malloc(256, 127, 0);
274     test_aligned_offset_malloc(256, 128, 0);
275
276     test_aligned_offset_malloc(256, 0, 4);
277     test_aligned_offset_malloc(256, 1, 4);
278     test_aligned_offset_malloc(256, 2, 4);
279     test_aligned_offset_malloc(256, 3, 4);
280     test_aligned_offset_malloc(256, 4, 4);
281     test_aligned_offset_malloc(256, 8, 4);
282     test_aligned_offset_malloc(256, 16, 4);
283     test_aligned_offset_malloc(256, 32, 4);
284     test_aligned_offset_malloc(256, 64, 4);
285     test_aligned_offset_malloc(256, 127, 4);
286     test_aligned_offset_malloc(256, 128, 4);
287
288     test_aligned_offset_malloc(256, 8, 7);
289     test_aligned_offset_malloc(256, 8, 9);
290     test_aligned_offset_malloc(256, 8, 16);
291     test_aligned_offset_malloc(256, 8, 17);
292     test_aligned_offset_malloc(256, 8, 254);
293     test_aligned_offset_malloc(256, 8, 255);
294     test_aligned_offset_malloc(256, 8, 256);
295     test_aligned_offset_malloc(256, 8, 512);
296
297     test_aligned_realloc(256, 512, 0);
298     test_aligned_realloc(256, 128, 0);
299     test_aligned_realloc(256, 512, 4);
300     test_aligned_realloc(256, 128, 4);
301     test_aligned_realloc(256, 512, 8);
302     test_aligned_realloc(256, 128, 8);
303     test_aligned_realloc(256, 512, 16);
304     test_aligned_realloc(256, 128, 16);
305     test_aligned_realloc(256, 512, 32);
306     test_aligned_realloc(256, 128, 32);
307     test_aligned_realloc(256, 512, 64);
308     test_aligned_realloc(256, 128, 64);
309
310     test_aligned_offset_realloc(256, 512, 0, 0);
311     test_aligned_offset_realloc(256, 128, 0, 0);
312     test_aligned_offset_realloc(256, 512, 4, 0);
313     test_aligned_offset_realloc(256, 128, 4, 0);
314     test_aligned_offset_realloc(256, 512, 8, 0);
315     test_aligned_offset_realloc(256, 128, 8, 0);
316     test_aligned_offset_realloc(256, 512, 16, 0);
317     test_aligned_offset_realloc(256, 128, 16, 0);
318     test_aligned_offset_realloc(256, 512, 32, 0);
319     test_aligned_offset_realloc(256, 128, 32, 0);
320     test_aligned_offset_realloc(256, 512, 64, 0);
321     test_aligned_offset_realloc(256, 128, 64, 0);
322
323     test_aligned_offset_realloc(256, 512, 0, 4);
324     test_aligned_offset_realloc(256, 128, 0, 4);
325     test_aligned_offset_realloc(256, 512, 4, 4);
326     test_aligned_offset_realloc(256, 128, 4, 4);
327     test_aligned_offset_realloc(256, 512, 8, 4);
328     test_aligned_offset_realloc(256, 128, 8, 4);
329     test_aligned_offset_realloc(256, 512, 16, 4);
330     test_aligned_offset_realloc(256, 128, 16, 4);
331     test_aligned_offset_realloc(256, 512, 32, 4);
332     test_aligned_offset_realloc(256, 128, 32, 4);
333     test_aligned_offset_realloc(256, 512, 64, 4);
334     test_aligned_offset_realloc(256, 128, 64, 4);
335 }
336
337 START_TEST(heap)
338 {
339     void *mem;
340
341     mem = malloc(0);
342     ok(mem != NULL, "memory not allocated for size 0\n");
343
344     mem = realloc(NULL, 10);
345     ok(mem != NULL, "memory not allocated\n");
346     
347     mem = realloc(mem, 20);
348     ok(mem != NULL, "memory not reallocated\n");
349  
350     mem = realloc(mem, 0);
351     ok(mem == NULL, "memory not freed\n");
352     
353     mem = realloc(NULL, 0);
354     ok(mem != NULL, "memory not (re)allocated for size 0\n");
355
356     test_aligned();
357 }