2 * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <ecoli_log.h>
33 #include <ecoli_malloc.h>
34 #include <ecoli_test.h>
37 static struct ec_test_list test_list = TAILQ_HEAD_INITIALIZER(test_list);
39 /* register a driver */
40 void ec_test_register(struct ec_test *test)
42 TAILQ_INSERT_TAIL(&test_list, test, next);
45 int ec_test_check_tk_parse(const struct ec_tk *tk, const char *input,
48 struct ec_parsed_tk *p;
52 p = ec_tk_parse(tk, input);
53 s = ec_parsed_tk_to_string(p);
54 if (s == NULL && expected == NULL)
56 else if (s != NULL && expected != NULL &&
60 if (expected == NULL && ret != 0)
61 ec_log(EC_LOG_ERR, "tk should not match but matches <%s>\n", s);
62 if (expected != NULL && ret != 0)
63 ec_log(EC_LOG_ERR, "tk should match <%s> but matches <%s>\n",
71 int ec_test_check_tk_complete(const struct ec_tk *tk, const char *input,
74 struct ec_completed_tk *c;
78 c = ec_tk_complete(tk, input);
79 s = ec_completed_tk_smallest_start(c);
80 if (s == NULL && expected == NULL)
82 else if (s != NULL && expected != NULL &&
86 if (expected == NULL && ret != 0)
88 "tk should not complete but completes with <%s>\n", s);
89 if (expected != NULL && ret != 0)
91 "tk should complete with <%s> but completes with <%s>\n",
94 ec_completed_tk_free(c);
99 int ec_test_check_tk_complete_list(const struct ec_tk *tk,
100 const char *input, ...)
102 struct ec_completed_tk *c = NULL;
103 struct ec_completed_tk_elt *elt;
106 unsigned int count = 0;
111 c = ec_tk_complete(tk, input);
115 for (s = va_arg(ap, const char *);
117 s = va_arg(ap, const char *)) {
122 TAILQ_FOREACH(elt, &c->elts, next) {
123 if (strcmp(elt->add, s) == 0)
129 "completion <%s> not in list\n", s);
134 if (count != ec_completed_tk_count(c)) {
136 "nb_completion (%d) does not match (%d)\n",
137 count, ec_completed_tk_count(c));
144 ec_completed_tk_free(c);
149 TAILQ_HEAD(debug_alloc_hdr_list, debug_alloc_hdr);
150 static struct debug_alloc_hdr_list debug_alloc_hdr_list =
151 TAILQ_HEAD_INITIALIZER(debug_alloc_hdr_list);
153 struct debug_alloc_hdr {
154 TAILQ_ENTRY(debug_alloc_hdr) next;
161 struct debug_alloc_ftr {
163 } __attribute__((packed));
165 static void *debug_malloc(size_t size, const char *file, unsigned int line)
167 struct debug_alloc_hdr *hdr;
168 struct debug_alloc_ftr *ftr;
169 size_t new_size = size + sizeof(*hdr) + sizeof(*ftr);
172 hdr = malloc(new_size);
179 hdr->cookie = 0x12345678;
180 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, hdr, next);
182 ftr = (struct debug_alloc_ftr *)(
183 (char *)hdr + size + sizeof(*hdr));
184 ftr->cookie = 0x12345678;
187 ec_log(EC_LOG_INFO, "%s:%d: info: malloc(%zd) -> %p\n",
188 file, line, size, ret);
193 static void debug_free(void *ptr, const char *file, unsigned int line)
195 struct debug_alloc_hdr *hdr, *h;
196 struct debug_alloc_ftr *ftr;
201 ec_log(EC_LOG_INFO, "%s:%d: info: free(%p)\n", file, line, ptr);
206 hdr = (ptr - sizeof(*hdr));
207 if (hdr->cookie != 0x12345678) {
208 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad start cookie\n",
213 ftr = (ptr + hdr->size);
214 if (ftr->cookie != 0x12345678) {
215 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad end cookie\n",
220 TAILQ_FOREACH(h, &debug_alloc_hdr_list, next) {
226 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad ptr\n",
231 TAILQ_REMOVE(&debug_alloc_hdr_list, hdr, next);
235 void *debug_realloc(void *ptr, size_t size, const char *file, unsigned int line)
237 struct debug_alloc_hdr *hdr, *h;
238 struct debug_alloc_ftr *ftr;
239 size_t new_size = size + sizeof(*hdr) + sizeof(unsigned int);
243 hdr = (ptr - sizeof(*hdr));
244 if (hdr->cookie != 0x12345678) {
246 "%s:%d: error: realloc(%p): bad start cookie\n",
251 ftr = (ptr + hdr->size);
252 if (ftr->cookie != 0x12345678) {
254 "%s:%d: error: realloc(%p): bad end cookie\n",
259 TAILQ_FOREACH(h, &debug_alloc_hdr_list, next) {
265 ec_log(EC_LOG_ERR, "%s:%d: error: realloc(%p): bad ptr\n",
270 TAILQ_REMOVE(&debug_alloc_hdr_list, h, next);
271 hdr = realloc(hdr, new_size);
273 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, h, next);
279 hdr = realloc(NULL, new_size);
290 hdr->cookie = 0x12345678;
291 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, hdr, next);
292 ftr = (struct debug_alloc_ftr *)(
293 (char *)hdr + size + sizeof(*hdr));
294 ftr->cookie = 0x12345678;
297 ec_log(EC_LOG_INFO, "%s:%d: info: realloc(%p, %zd) -> %p\n",
298 file, line, ptr, size, ret);
303 void debug_alloc_dump(void)
305 struct debug_alloc_hdr *hdr;
307 TAILQ_FOREACH(hdr, &debug_alloc_hdr_list, next) {
308 ec_log(EC_LOG_ERR, "%s:%d: error: memory leak size=%zd ptr=%p\n",
309 hdr->file, hdr->line, hdr->size, hdr + 1);
314 /* int ec_test_check_tk_complete_list(const struct ec_tk *tk, */
315 /* const char *input, ...) */
317 int ec_test_all(void)
319 struct ec_test *test;
322 TAILQ_INIT(&debug_alloc_hdr_list);
324 /* register a new malloc to trac memleaks */
325 if (0 && ec_malloc_register(debug_malloc, debug_free, debug_realloc) < 0) {
326 ec_log(EC_LOG_ERR, "cannot register new malloc\n");
330 TAILQ_FOREACH(test, &test_list, next) {
331 if (test->test() == 0) {
332 ec_log(EC_LOG_INFO, "== test %-20s success\n",
335 ec_log(EC_LOG_INFO, "== test %-20s failed\n",
341 ec_malloc_unregister();