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 *p;
78 p = ec_tk_complete(tk, input);
79 s = ec_completed_tk_smallest_start(p);
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(p);
99 TAILQ_HEAD(debug_alloc_hdr_list, debug_alloc_hdr);
100 static struct debug_alloc_hdr_list debug_alloc_hdr_list =
101 TAILQ_HEAD_INITIALIZER(debug_alloc_hdr_list);
103 struct debug_alloc_hdr {
104 TAILQ_ENTRY(debug_alloc_hdr) next;
111 static void *debug_malloc(size_t size, const char *file, unsigned int line)
113 struct debug_alloc_hdr *hdr;
114 size_t new_size = size + sizeof(*hdr) + sizeof(unsigned int);
117 hdr = malloc(new_size);
124 hdr->cookie = 0x12345678;
125 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, hdr, next);
129 ec_log(EC_LOG_INFO, "%s:%d: info: malloc(%zd) -> %p\n",
130 file, line, size, ret);
135 static void debug_free(void *ptr, const char *file, unsigned int line)
137 struct debug_alloc_hdr *hdr, *h;
142 ec_log(EC_LOG_INFO, "%s:%d: info: free(%p)\n", file, line, ptr);
147 hdr = (ptr - sizeof(*hdr));
148 if (hdr->cookie != 0x12345678) {
149 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad start cookie\n",
154 TAILQ_FOREACH(h, &debug_alloc_hdr_list, next) {
160 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad ptr\n",
165 TAILQ_REMOVE(&debug_alloc_hdr_list, hdr, next);
169 void *debug_realloc(void *ptr, size_t size, const char *file, unsigned int line)
171 struct debug_alloc_hdr *hdr = (ptr - sizeof(*hdr));
172 struct debug_alloc_hdr *h;
173 size_t new_size = size + sizeof(*hdr) + sizeof(unsigned int);
177 if (hdr->cookie != 0x12345678) {
178 ec_log(EC_LOG_ERR, "%s:%d: error: realloc(%p): bad start cookie\n",
183 TAILQ_FOREACH(h, &debug_alloc_hdr_list, next) {
189 ec_log(EC_LOG_ERR, "%s:%d: error: realloc(%p): bad ptr\n",
194 TAILQ_REMOVE(&debug_alloc_hdr_list, h, next);
195 hdr = realloc(hdr, new_size);
197 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, h, next);
203 hdr = realloc(NULL, new_size);
214 hdr->cookie = 0x12345678;
215 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, hdr, next);
218 ec_log(EC_LOG_INFO, "%s:%d: info: realloc(%p, %zd) -> %p\n",
219 file, line, ptr, size, ret);
224 void debug_alloc_dump(void)
226 struct debug_alloc_hdr *hdr;
228 TAILQ_FOREACH(hdr, &debug_alloc_hdr_list, next) {
229 ec_log(EC_LOG_ERR, "%s:%d: error: memory leak size=%zd ptr=%p\n",
230 hdr->file, hdr->line, hdr->size, hdr + 1);
235 /* int ec_test_check_tk_complete_list(const struct ec_tk *tk, */
236 /* const char *input, ...) */
238 int ec_test_all(void)
240 struct ec_test *test;
243 TAILQ_INIT(&debug_alloc_hdr_list);
245 /* register a new malloc to trac memleaks */
246 if (ec_malloc_register(debug_malloc, debug_free, debug_realloc) < 0) {
247 ec_log(EC_LOG_ERR, "cannot register new malloc\n");
251 TAILQ_FOREACH(test, &test_list, next) {
252 if (test->test() == 0) {
253 ec_log(EC_LOG_INFO, "== test %-20s success\n",
256 ec_log(EC_LOG_INFO, "== test %-20s failed\n",
262 ec_malloc_unregister();