1 | /* ---------------------------------------------------------------------------- |
2 | Copyright (c) 2018, Microsoft Research, Daan Leijen |
3 | This is free software; you can redistribute it and/or modify it under the |
4 | terms of the MIT license. A copy of the license can be found in the file |
5 | "LICENSE" at the root of this distribution. |
6 | -----------------------------------------------------------------------------*/ |
7 | |
8 | /* |
9 | Testing allocators is difficult as bugs may only surface after particular |
10 | allocation patterns. The main approach to testing _mimalloc_ is therefore |
11 | to have extensive internal invariant checking (see `page_is_valid` in `page.c` |
12 | for example), which is enabled in debug mode with `-DMI_CHECK_FULL=ON`. |
13 | The main testing is then to run `mimalloc-bench` [1] using full invariant checking |
14 | to catch any potential problems over a wide range of intensive allocation bench |
15 | marks. |
16 | |
17 | However, this does not test well for the entire API surface. In this test file |
18 | we therefore test the API over various inputs. Please add more tests :-) |
19 | |
20 | [1] https://github.com/daanx/mimalloc-bench |
21 | */ |
22 | |
23 | #include <stdio.h> |
24 | #include <assert.h> |
25 | #include <stdbool.h> |
26 | #include <stdint.h> |
27 | #include <errno.h> |
28 | #include "mimalloc.h" |
29 | #include "mimalloc-internal.h" |
30 | |
31 | // --------------------------------------------------------------------------- |
32 | // Test macros: CHECK(name,predicate) and CHECK_BODY(name,body) |
33 | // --------------------------------------------------------------------------- |
34 | static int ok = 0; |
35 | static int failed = 0; |
36 | |
37 | #define CHECK_BODY(name,body) \ |
38 | do { \ |
39 | fprintf(stderr,"test: %s... ", name ); \ |
40 | bool result = true; \ |
41 | do { body } while(false); \ |
42 | if (!(result)) { \ |
43 | failed++; \ |
44 | fprintf(stderr, \ |
45 | "\n FAILED: %s:%d:\n %s\n", \ |
46 | __FILE__, \ |
47 | __LINE__, \ |
48 | #body); \ |
49 | /* exit(1); */ \ |
50 | } \ |
51 | else { \ |
52 | ok++; \ |
53 | fprintf(stderr,"ok.\n"); \ |
54 | } \ |
55 | } while (false) |
56 | |
57 | #define CHECK(name,expr) CHECK_BODY(name,{ result = (expr); }) |
58 | |
59 | // --------------------------------------------------------------------------- |
60 | // Test functions |
61 | // --------------------------------------------------------------------------- |
62 | bool test_heap1(); |
63 | bool test_heap2(); |
64 | |
65 | // --------------------------------------------------------------------------- |
66 | // Main testing |
67 | // --------------------------------------------------------------------------- |
68 | int main() { |
69 | mi_option_disable(mi_option_verbose); |
70 | |
71 | // --------------------------------------------------- |
72 | // Malloc |
73 | // --------------------------------------------------- |
74 | |
75 | CHECK_BODY("malloc-zero" ,{ |
76 | void* p = mi_malloc(0); mi_free(p); |
77 | }); |
78 | CHECK_BODY("malloc-nomem1" ,{ |
79 | result = (mi_malloc(SIZE_MAX/2) == NULL); |
80 | }); |
81 | CHECK_BODY("malloc-null" ,{ |
82 | mi_free(NULL); |
83 | }); |
84 | |
85 | // --------------------------------------------------- |
86 | // Extended |
87 | // --------------------------------------------------- |
88 | #if defined(MI_MALLOC_OVERRIDE) && !defined(_WIN32) |
89 | CHECK_BODY("posix_memalign1" , { |
90 | void* p = &p; |
91 | int err = posix_memalign(&p, sizeof(void*), 32); |
92 | mi_assert((err==0 && (uintptr_t)p % sizeof(void*) == 0) || p==&p); |
93 | mi_free(p); |
94 | result = (err==0); |
95 | }); |
96 | CHECK_BODY("posix_memalign_no_align" , { |
97 | void* p = &p; |
98 | int err = posix_memalign(&p, 3, 32); |
99 | mi_assert(p==&p); |
100 | result = (err==EINVAL); |
101 | }); |
102 | CHECK_BODY("posix_memalign_zero" , { |
103 | void* p = &p; |
104 | int err = posix_memalign(&p, sizeof(void*), 0); |
105 | mi_free(p); |
106 | result = (err==0); |
107 | }); |
108 | CHECK_BODY("posix_memalign_nopow2" , { |
109 | void* p = &p; |
110 | int err = posix_memalign(&p, 3*sizeof(void*), 32); |
111 | result = (err==EINVAL && p==&p); |
112 | }); |
113 | CHECK_BODY("posix_memalign_nomem" , { |
114 | void* p = &p; |
115 | int err = posix_memalign(&p, sizeof(void*), SIZE_MAX); |
116 | result = (err==ENOMEM && p==&p); |
117 | }); |
118 | #endif |
119 | |
120 | // --------------------------------------------------- |
121 | // Aligned API |
122 | // --------------------------------------------------- |
123 | CHECK_BODY("malloc-aligned1" , { |
124 | void* p = mi_malloc_aligned(32,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p); |
125 | }); |
126 | CHECK_BODY("malloc-aligned2" , { |
127 | void* p = mi_malloc_aligned(48,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p); |
128 | }); |
129 | CHECK_BODY("malloc-aligned-at1" , { |
130 | void* p = mi_malloc_aligned_at(48,32,0); result = (p != NULL && ((uintptr_t)(p) + 0) % 32 == 0); mi_free(p); |
131 | }); |
132 | CHECK_BODY("malloc-aligned-at2" , { |
133 | void* p = mi_malloc_aligned_at(50,32,8); result = (p != NULL && ((uintptr_t)(p) + 8) % 32 == 0); mi_free(p); |
134 | }); |
135 | |
136 | // --------------------------------------------------- |
137 | // Heaps |
138 | // --------------------------------------------------- |
139 | CHECK("heap_destroy" , test_heap1()); |
140 | CHECK("heap_delete" , test_heap2()); |
141 | |
142 | //mi_stats_print(NULL); |
143 | |
144 | // --------------------------------------------------- |
145 | // various |
146 | // --------------------------------------------------- |
147 | CHECK_BODY("realpath" , { |
148 | char* s = mi_realpath( "." , NULL ); |
149 | // printf("realpath: %s\n",s); |
150 | mi_free(s); |
151 | }); |
152 | |
153 | // --------------------------------------------------- |
154 | // Done |
155 | // ---------------------------------------------------[] |
156 | fprintf(stderr,"\n\n---------------------------------------------\n" |
157 | "succeeded: %i\n" |
158 | "failed : %i\n\n" , ok, failed); |
159 | return failed; |
160 | } |
161 | |
162 | // --------------------------------------------------- |
163 | // Larger test functions |
164 | // --------------------------------------------------- |
165 | |
166 | bool test_heap1() { |
167 | mi_heap_t* heap = mi_heap_new(); |
168 | int* p1 = mi_heap_malloc_tp(heap,int); |
169 | int* p2 = mi_heap_malloc_tp(heap,int); |
170 | *p1 = *p2 = 43; |
171 | mi_heap_destroy(heap); |
172 | return true; |
173 | } |
174 | |
175 | bool test_heap2() { |
176 | mi_heap_t* heap = mi_heap_new(); |
177 | int* p1 = mi_heap_malloc_tp(heap,int); |
178 | int* p2 = mi_heap_malloc_tp(heap,int); |
179 | mi_heap_delete(heap); |
180 | *p1 = 42; |
181 | mi_free(p1); |
182 | mi_free(p2); |
183 | return true; |
184 | } |
185 | |