blob: 21b2205ac2a9abe25a0f4302861437141822f376 [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono5dcb38d2005-11-21 01:55:47 +00005 *
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>
Benny Prijono83217fa2007-02-16 21:44:36 +000021#include <pj/pool_buf.h>
Benny Prijono5dcb38d2005-11-21 01:55:47 +000022#include <pj/rand.h>
23#include <pj/log.h>
Benny Prijono83217fa2007-02-16 21:44:36 +000024#include <pj/except.h>
Benny Prijono5dcb38d2005-11-21 01:55:47 +000025#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
Benny Prijonoba858ec2010-01-29 10:10:49 +000082/* Test that the alignment works. */
83static int pool_alignment_test(void)
84{
85 pj_pool_t *pool;
86 void *ptr;
Benny Prijono4969f372010-01-29 11:20:43 +000087 enum { MEMSIZE = 64, LOOP = 100 };
88 unsigned i;
Benny Prijonoba858ec2010-01-29 10:10:49 +000089
90 PJ_LOG(3,("test", "...alignment test"));
91
Benny Prijono4969f372010-01-29 11:20:43 +000092 pool = pj_pool_create(mem, NULL, PJ_POOL_SIZE+MEMSIZE, MEMSIZE, NULL);
Benny Prijonoba858ec2010-01-29 10:10:49 +000093 if (!pool)
94 return -300;
95
96#define IS_ALIGNED(p) ((((unsigned long)p) & (PJ_POOL_ALIGNMENT-1)) == 0)
97
Benny Prijono4969f372010-01-29 11:20:43 +000098 for (i=0; i<LOOP; ++i) {
99 /* Test first allocation */
100 ptr = pj_pool_alloc(pool, 1);
101 if (!IS_ALIGNED(ptr)) {
102 pj_pool_release(pool);
103 return -310;
104 }
Benny Prijonoba858ec2010-01-29 10:10:49 +0000105
Benny Prijono4969f372010-01-29 11:20:43 +0000106 /* Test subsequent allocation */
107 ptr = pj_pool_alloc(pool, 1);
108 if (!IS_ALIGNED(ptr)) {
109 pj_pool_release(pool);
110 return -320;
111 }
Benny Prijonoba858ec2010-01-29 10:10:49 +0000112
Benny Prijono4969f372010-01-29 11:20:43 +0000113 /* Test allocation after new block is created */
114 ptr = pj_pool_alloc(pool, MEMSIZE*2+1);
115 if (!IS_ALIGNED(ptr)) {
116 pj_pool_release(pool);
117 return -330;
118 }
Benny Prijonoba858ec2010-01-29 10:10:49 +0000119
Benny Prijono4969f372010-01-29 11:20:43 +0000120 /* Reset the pool */
121 pj_pool_reset(pool);
Benny Prijonoba858ec2010-01-29 10:10:49 +0000122 }
123
124 /* Done */
125 pj_pool_release(pool);
126
127 return 0;
128}
129
130/* Test that the alignment works for pool on buf. */
131static int pool_buf_alignment_test(void)
132{
133 pj_pool_t *pool;
Benny Prijono4969f372010-01-29 11:20:43 +0000134 char buf[512];
Benny Prijonoba858ec2010-01-29 10:10:49 +0000135 void *ptr;
Benny Prijono4969f372010-01-29 11:20:43 +0000136 enum { LOOP = 100 };
137 unsigned i;
Benny Prijonoba858ec2010-01-29 10:10:49 +0000138
139 PJ_LOG(3,("test", "...pool_buf alignment test"));
140
141 pool = pj_pool_create_on_buf(NULL, buf, sizeof(buf));
142 if (!pool)
143 return -400;
144
Benny Prijono4969f372010-01-29 11:20:43 +0000145 for (i=0; i<LOOP; ++i) {
146 /* Test first allocation */
147 ptr = pj_pool_alloc(pool, 1);
148 if (!IS_ALIGNED(ptr)) {
149 pj_pool_release(pool);
150 return -410;
151 }
Benny Prijonoba858ec2010-01-29 10:10:49 +0000152
Benny Prijono4969f372010-01-29 11:20:43 +0000153 /* Test subsequent allocation */
154 ptr = pj_pool_alloc(pool, 1);
155 if (!IS_ALIGNED(ptr)) {
156 pj_pool_release(pool);
157 return -420;
158 }
Benny Prijonoba858ec2010-01-29 10:10:49 +0000159
Benny Prijono4969f372010-01-29 11:20:43 +0000160 /* Reset the pool */
161 pj_pool_reset(pool);
Benny Prijonoba858ec2010-01-29 10:10:49 +0000162 }
163
164 /* Done */
165 return 0;
166}
167
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000168/* Test function to drain the pool's space.
169 */
170static int drain_test(pj_size_t size, pj_size_t increment)
171{
172 pj_pool_t *pool = pj_pool_create(mem, NULL, size, increment,
173 &null_callback);
174 pj_size_t freesize;
175 void *p;
176 int status = 0;
177
178 PJ_LOG(3,("test", "...drain_test(%d,%d)", size, increment));
179
180 if (!pool)
181 return -10;
182
183 /* Get free size */
184 freesize = GET_FREE(pool);
185 if (freesize < 1) {
186 status=-15;
187 goto on_error;
188 }
189
190 /* Drain the pool until there's nothing left. */
191 while (freesize > 0) {
192 int size;
193
194 if (freesize > 255)
Nanang Izzuddin9375aca2008-04-23 14:35:24 +0000195 size = ((pj_rand() & 0x000000FF) + PJ_POOL_ALIGNMENT) &
196 ~(PJ_POOL_ALIGNMENT - 1);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000197 else
198 size = freesize;
199
200 p = pj_pool_alloc(pool, size);
201 if (!p) {
202 status=-20; goto on_error;
203 }
204
205 freesize -= size;
206 }
207
208 /* Check that capacity is zero. */
209 if (GET_FREE(pool) != 0) {
210 PJ_LOG(3,("test", "....error: returned free=%u (expecting 0)",
211 GET_FREE(pool)));
212 status=-30; goto on_error;
213 }
214
215 /* Try to allocate once more */
216 p = pj_pool_alloc(pool, 257);
217 if (!p) {
218 status=-40; goto on_error;
219 }
220
221 /* Check that capacity is NOT zero. */
222 if (GET_FREE(pool) == 0) {
223 status=-50; goto on_error;
224 }
225
226
227on_error:
228 pj_pool_release(pool);
229 return status;
230}
231
Benny Prijono83217fa2007-02-16 21:44:36 +0000232/* Test the buffer based pool */
233static int pool_buf_test(void)
234{
235 enum { STATIC_BUF_SIZE = 40 };
236 /* 16 is the internal struct in pool_buf */
237 static char buf[ STATIC_BUF_SIZE + sizeof(pj_pool_t) +
Benny Prijonoba858ec2010-01-29 10:10:49 +0000238 sizeof(pj_pool_block) + 2 * PJ_POOL_ALIGNMENT];
Benny Prijono83217fa2007-02-16 21:44:36 +0000239 pj_pool_t *pool;
240 void *p;
241 PJ_USE_EXCEPTION;
242
243 PJ_LOG(3,("test", "...pool_buf test"));
244
245 pool = pj_pool_create_on_buf("no name", buf, sizeof(buf));
246 if (!pool)
247 return -70;
248
249 /* Drain the pool */
250 PJ_TRY {
251 if ((p=pj_pool_alloc(pool, STATIC_BUF_SIZE/2)) == NULL)
252 return -75;
253
254 if ((p=pj_pool_alloc(pool, STATIC_BUF_SIZE/2)) == NULL)
255 return -76;
256 }
257 PJ_CATCH_ANY {
258 return -77;
259 }
260 PJ_END;
261
262 /* On the next alloc, exception should be thrown */
263 PJ_TRY {
264 p = pj_pool_alloc(pool, STATIC_BUF_SIZE);
265 if (p != NULL) {
266 /* This is unexpected, the alloc should fail */
267 return -78;
268 }
269 }
270 PJ_CATCH_ANY {
271 /* This is the expected result */
272 }
273 PJ_END;
274
275 /* Done */
276 return 0;
277}
278
279
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000280int pool_test(void)
281{
282 enum { LOOP = 2 };
283 int loop;
284 int rc;
285
286 rc = capacity_test();
287 if (rc) return rc;
288
Benny Prijonoba858ec2010-01-29 10:10:49 +0000289 rc = pool_alignment_test();
290 if (rc) return rc;
291
292 rc = pool_buf_alignment_test();
293 if (rc) return rc;
294
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000295 for (loop=0; loop<LOOP; ++loop) {
296 /* Test that the pool should grow automaticly. */
297 rc = drain_test(SIZE, SIZE);
298 if (rc != 0) return rc;
299
300 /* Test situation where pool is not allowed to grow.
301 * We expect the test to return correct error.
302 */
303 rc = drain_test(SIZE, 0);
304 if (rc != -40) return rc;
305 }
306
Benny Prijono83217fa2007-02-16 21:44:36 +0000307 rc = pool_buf_test();
308 if (rc != 0)
309 return rc;
310
311
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000312 return 0;
313}
314
315#else
316/* To prevent warning about "translation unit is empty"
317 * when this test is disabled.
318 */
319int dummy_pool_test;
320#endif /* INCLUDE_POOL_TEST */
321