blob: e3fbb5557d7cc1404b5c16335ddc945091ee99f6 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/pool.h>
21#include <pj/pool_buf.h>
22#include <pj/rand.h>
23#include <pj/log.h>
24#include <pj/except.h>
25#include "test.h"
26
27/**
28 * \page page_pjlib_pool_test Test: Pool
29 *
30 * This file provides implementation of \b pool_test(). It tests the
31 * functionality of the memory pool.
32 *
33 *
34 * This file is <b>pjlib-test/pool.c</b>
35 *
36 * \include pjlib-test/pool.c
37 */
38
39
40#if INCLUDE_POOL_TEST
41
42#define SIZE 4096
43
44/* Normally we should throw exception when memory alloc fails.
45 * Here we do nothing so that the flow will go back to original caller,
46 * which will test the result using NULL comparison. Normally caller will
47 * catch the exception instead of checking for NULLs.
48 */
49static void null_callback(pj_pool_t *pool, pj_size_t size)
50{
51 PJ_UNUSED_ARG(pool);
52 PJ_UNUSED_ARG(size);
53}
54
55#define GET_FREE(p) (pj_pool_get_capacity(p)-pj_pool_get_used_size(p))
56
57/* Test that the capacity and used size reported by the pool is correct.
58 */
59static int capacity_test(void)
60{
61 pj_pool_t *pool = pj_pool_create(mem, NULL, SIZE, 0, &null_callback);
62 pj_size_t freesize;
63
64 PJ_LOG(3,("test", "...capacity_test()"));
65
66 if (!pool)
67 return -200;
68
69 freesize = GET_FREE(pool);
70
71 if (pj_pool_alloc(pool, freesize) == NULL) {
72 PJ_LOG(3,("test", "...error: wrong freesize %u reported",
73 freesize));
74 pj_pool_release(pool);
75 return -210;
76 }
77
78 pj_pool_release(pool);
79 return 0;
80}
81
82/* Test that the alignment works. */
83static int pool_alignment_test(void)
84{
85 pj_pool_t *pool;
86 void *ptr;
87 enum { MEMSIZE = 64, LOOP = 100 };
88 unsigned i;
89
90 PJ_LOG(3,("test", "...alignment test"));
91
92 pool = pj_pool_create(mem, NULL, PJ_POOL_SIZE+MEMSIZE, MEMSIZE, NULL);
93 if (!pool)
94 return -300;
95
96#define IS_ALIGNED(p) ((((unsigned long)(pj_ssize_t)p) & \
97 (PJ_POOL_ALIGNMENT-1)) == 0)
98
99 for (i=0; i<LOOP; ++i) {
100 /* Test first allocation */
101 ptr = pj_pool_alloc(pool, 1);
102 if (!IS_ALIGNED(ptr)) {
103 pj_pool_release(pool);
104 return -310;
105 }
106
107 /* Test subsequent allocation */
108 ptr = pj_pool_alloc(pool, 1);
109 if (!IS_ALIGNED(ptr)) {
110 pj_pool_release(pool);
111 return -320;
112 }
113
114 /* Test allocation after new block is created */
115 ptr = pj_pool_alloc(pool, MEMSIZE*2+1);
116 if (!IS_ALIGNED(ptr)) {
117 pj_pool_release(pool);
118 return -330;
119 }
120
121 /* Reset the pool */
122 pj_pool_reset(pool);
123 }
124
125 /* Done */
126 pj_pool_release(pool);
127
128 return 0;
129}
130
131/* Test that the alignment works for pool on buf. */
132static int pool_buf_alignment_test(void)
133{
134 pj_pool_t *pool;
135 char buf[512];
136 void *ptr;
137 enum { LOOP = 100 };
138 unsigned i;
139
140 PJ_LOG(3,("test", "...pool_buf alignment test"));
141
142 pool = pj_pool_create_on_buf(NULL, buf, sizeof(buf));
143 if (!pool)
144 return -400;
145
146 for (i=0; i<LOOP; ++i) {
147 /* Test first allocation */
148 ptr = pj_pool_alloc(pool, 1);
149 if (!IS_ALIGNED(ptr)) {
150 pj_pool_release(pool);
151 return -410;
152 }
153
154 /* Test subsequent allocation */
155 ptr = pj_pool_alloc(pool, 1);
156 if (!IS_ALIGNED(ptr)) {
157 pj_pool_release(pool);
158 return -420;
159 }
160
161 /* Reset the pool */
162 pj_pool_reset(pool);
163 }
164
165 /* Done */
166 return 0;
167}
168
169/* Test function to drain the pool's space.
170 */
171static int drain_test(pj_size_t size, pj_size_t increment)
172{
173 pj_pool_t *pool = pj_pool_create(mem, NULL, size, increment,
174 &null_callback);
175 pj_size_t freesize;
176 void *p;
177 int status = 0;
178
179 PJ_LOG(3,("test", "...drain_test(%d,%d)", size, increment));
180
181 if (!pool)
182 return -10;
183
184 /* Get free size */
185 freesize = GET_FREE(pool);
186 if (freesize < 1) {
187 status=-15;
188 goto on_error;
189 }
190
191 /* Drain the pool until there's nothing left. */
192 while (freesize > 0) {
193 int size;
194
195 if (freesize > 255)
196 size = ((pj_rand() & 0x000000FF) + PJ_POOL_ALIGNMENT) &
197 ~(PJ_POOL_ALIGNMENT - 1);
198 else
199 size = (int)freesize;
200
201 p = pj_pool_alloc(pool, size);
202 if (!p) {
203 status=-20; goto on_error;
204 }
205
206 freesize -= size;
207 }
208
209 /* Check that capacity is zero. */
210 if (GET_FREE(pool) != 0) {
211 PJ_LOG(3,("test", "....error: returned free=%u (expecting 0)",
212 GET_FREE(pool)));
213 status=-30; goto on_error;
214 }
215
216 /* Try to allocate once more */
217 p = pj_pool_alloc(pool, 257);
218 if (!p) {
219 status=-40; goto on_error;
220 }
221
222 /* Check that capacity is NOT zero. */
223 if (GET_FREE(pool) == 0) {
224 status=-50; goto on_error;
225 }
226
227
228on_error:
229 pj_pool_release(pool);
230 return status;
231}
232
233/* Test the buffer based pool */
234static int pool_buf_test(void)
235{
236 enum { STATIC_BUF_SIZE = 40 };
237 /* 16 is the internal struct in pool_buf */
238 static char buf[ STATIC_BUF_SIZE + sizeof(pj_pool_t) +
239 sizeof(pj_pool_block) + 2 * PJ_POOL_ALIGNMENT];
240 pj_pool_t *pool;
241 void *p;
242 PJ_USE_EXCEPTION;
243
244 PJ_LOG(3,("test", "...pool_buf test"));
245
246 pool = pj_pool_create_on_buf("no name", buf, sizeof(buf));
247 if (!pool)
248 return -70;
249
250 /* Drain the pool */
251 PJ_TRY {
252 if ((p=pj_pool_alloc(pool, STATIC_BUF_SIZE/2)) == NULL)
253 return -75;
254
255 if ((p=pj_pool_alloc(pool, STATIC_BUF_SIZE/2)) == NULL)
256 return -76;
257 }
258 PJ_CATCH_ANY {
259 return -77;
260 }
261 PJ_END;
262
263 /* On the next alloc, exception should be thrown */
264 PJ_TRY {
265 p = pj_pool_alloc(pool, STATIC_BUF_SIZE);
266 if (p != NULL) {
267 /* This is unexpected, the alloc should fail */
268 return -78;
269 }
270 }
271 PJ_CATCH_ANY {
272 /* This is the expected result */
273 }
274 PJ_END;
275
276 /* Done */
277 return 0;
278}
279
280
281int pool_test(void)
282{
283 enum { LOOP = 2 };
284 int loop;
285 int rc;
286
287 rc = capacity_test();
288 if (rc) return rc;
289
290 rc = pool_alignment_test();
291 if (rc) return rc;
292
293 rc = pool_buf_alignment_test();
294 if (rc) return rc;
295
296 for (loop=0; loop<LOOP; ++loop) {
297 /* Test that the pool should grow automaticly. */
298 rc = drain_test(SIZE, SIZE);
299 if (rc != 0) return rc;
300
301 /* Test situation where pool is not allowed to grow.
302 * We expect the test to return correct error.
303 */
304 rc = drain_test(SIZE, 0);
305 if (rc != -40) return rc;
306 }
307
308 rc = pool_buf_test();
309 if (rc != 0)
310 return rc;
311
312
313 return 0;
314}
315
316#else
317/* To prevent warning about "translation unit is empty"
318 * when this test is disabled.
319 */
320int dummy_pool_test;
321#endif /* INCLUDE_POOL_TEST */
322