blob: 8ca2de0de6d915ecdf32bcc22bb39caaafeda7ab [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/string.h>
20#include <pj/pool.h>
21#include <pj/log.h>
Benny Prijonoa7944bb2005-11-21 17:01:50 +000022#include <pj/os.h>
Benny Prijono5dcb38d2005-11-21 01:55:47 +000023#include "test.h"
24
25/**
26 * \page page_pjlib_string_test Test: String
27 *
28 * This file provides implementation of \b string_test(). It tests the
29 * functionality of the string API.
30 *
31 * \section sleep_test_sec Scope of the Test
32 *
33 * API tested:
34 * - pj_str()
35 * - pj_strcmp()
36 * - pj_strcmp2()
37 * - pj_stricmp()
38 * - pj_strlen()
39 * - pj_strncmp()
40 * - pj_strnicmp()
41 * - pj_strchr()
42 * - pj_strdup()
43 * - pj_strdup2()
44 * - pj_strcpy()
45 * - pj_strcat()
46 * - pj_strtrim()
47 * - pj_utoa()
48 * - pj_strtoul()
49 * - pj_create_random_string()
Benny Prijono8220f902006-01-09 17:20:59 +000050 * - ... and mode..
Benny Prijono5dcb38d2005-11-21 01:55:47 +000051 *
52 * This file is <b>pjlib-test/string.c</b>
53 *
54 * \include pjlib-test/string.c
55 */
56
57#if INCLUDE_STRING_TEST
58
59#ifdef _MSC_VER
60# pragma warning(disable: 4204)
61#endif
62
63#define HELLO_WORLD "Hello World"
64#define JUST_HELLO "Hello"
65#define UL_VALUE 3456789012UL
66
Benny Prijonoa7944bb2005-11-21 17:01:50 +000067static int stricmp_test(void)
68{
Benny Prijono8220f902006-01-09 17:20:59 +000069/* This specificly tests and benchmark pj_stricmp(), pj_stricmp_alnum().
70 * In addition, it also tests pj_stricmp2(), pj_strnicmp(), and
71 * pj_strnicmp2().
72 */
Benny Prijonoa7944bb2005-11-21 17:01:50 +000073#define STRTEST(res,S1,S2,code) \
74 do { \
Benny Prijono8220f902006-01-09 17:20:59 +000075 s1.ptr=S1; s1.slen=S1?len:0; \
76 s2.ptr=S2; s2.slen=S2?len:0; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +000077 pj_get_timestamp(&t1); \
78 if (pj_stricmp(&s1,&s2)!=res) return code; \
79 pj_get_timestamp(&t2); \
80 pj_sub_timestamp(&t2, &t1); \
81 pj_add_timestamp(&e1, &t2); \
82 pj_get_timestamp(&t1); \
83 if (pj_stricmp_alnum(&s1,&s2)!=res) return code-1; \
84 pj_get_timestamp(&t2); \
85 pj_sub_timestamp(&t2, &t1); \
86 pj_add_timestamp(&e2, &t2); \
Benny Prijono8220f902006-01-09 17:20:59 +000087 if (pj_stricmp2(&s1,S2)!=res) return code*10; \
88 if (pj_strnicmp(&s1,&s2,len)!=res) return code*100; \
89 if (pj_strnicmp2(&s1,S2,len)!=res) return code*1000; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +000090 } while (0)
91
92 char *buf;
93 pj_str_t s1, s2;
94 pj_timestamp t1, t2, e1, e2, zero;
95 pj_uint32_t c1, c2;
96 int len;
97
98 e1.u32.hi = e1.u32.lo = e2.u32.hi = e2.u32.lo = 0;
99
100 pj_thread_sleep(0);
101
102 /* Compare empty strings. */
103 len=0;
104 STRTEST( 0, "","",-500);
Benny Prijono8220f902006-01-09 17:20:59 +0000105 STRTEST( 0, NULL,"",-502);
106 STRTEST( 0, "",NULL,-504);
107 STRTEST( 0, NULL,NULL,-506);
108 STRTEST( 0, "hello","world",-508);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000109
110 /* equal, length=1
111 * use buffer to simulate non-aligned string.
112 */
113 buf = "a""A";
114 len=1;
115 STRTEST( 0, "a",buf+0,-510);
116 STRTEST( 0, "a",buf+1,-512);
Benny Prijonocec5f4a2005-11-22 23:51:50 +0000117 STRTEST( -1, "0", "P", -514);
Benny Prijono8220f902006-01-09 17:20:59 +0000118 STRTEST(-1, NULL, "a", -516);
119 STRTEST(1, "a", NULL, -518);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000120
121 /* equal, length=2
122 * use buffer to simulate non-aligned string.
123 */
124 buf = "aa""Aa""aA""AA";
125 len=2;
126 STRTEST( 0, "aa",buf+0,-520);
127 STRTEST( 0, "aa",buf+2,-522);
128 STRTEST( 0, "aa",buf+4,-524);
129 STRTEST( 0, "aa",buf+6,-524);
130
131 /* equal, length=3
132 * use buffer to simulate non-aligned string.
133 */
134 buf = "aaa""Aaa""aAa""aaA""AAa""aAA""AaA""AAA";
135 len=3;
136 STRTEST( 0, "aaa",buf+0,-530);
137 STRTEST( 0, "aaa",buf+3,-532);
138 STRTEST( 0, "aaa",buf+6,-534);
139 STRTEST( 0, "aaa",buf+9,-536);
140 STRTEST( 0, "aaa",buf+12,-538);
141 STRTEST( 0, "aaa",buf+15,-540);
142 STRTEST( 0, "aaa",buf+18,-542);
143 STRTEST( 0, "aaa",buf+21,-534);
144
145 /* equal, length=4 */
146 len=4;
147 STRTEST( 0, "aaaa","aaaa",-540);
148 STRTEST( 0, "aaaa","Aaaa",-542);
149 STRTEST( 0, "aaaa","aAaa",-544);
150 STRTEST( 0, "aaaa","aaAa",-546);
151 STRTEST( 0, "aaaa","aaaA",-548);
152 STRTEST( 0, "aaaa","AAaa",-550);
153 STRTEST( 0, "aaaa","aAAa",-552);
154 STRTEST( 0, "aaaa","aaAA",-554);
155 STRTEST( 0, "aaaa","AaAa",-556);
156 STRTEST( 0, "aaaa","aAaA",-558);
157 STRTEST( 0, "aaaa","AaaA",-560);
158 STRTEST( 0, "aaaa","AAAa",-562);
159 STRTEST( 0, "aaaa","aAAA",-564);
160 STRTEST( 0, "aaaa","AAaA",-566);
161 STRTEST( 0, "aaaa","AaAA",-568);
162 STRTEST( 0, "aaaa","AAAA",-570);
163
164 /* equal, length=5 */
165 buf = "aaaAa""AaaaA""AaAaA""AAAAA";
166 len=5;
167 STRTEST( 0, "aaaaa",buf+0,-580);
168 STRTEST( 0, "aaaaa",buf+5,-582);
169 STRTEST( 0, "aaaaa",buf+10,-584);
170 STRTEST( 0, "aaaaa",buf+15,-586);
171
172 /* not equal, length=1 */
173 len=1;
174 STRTEST( -1, "a", "b", -600);
175
176 /* not equal, length=2 */
177 buf = "ab""ba";
178 len=2;
179 STRTEST( -1, "aa", buf+0, -610);
180 STRTEST( -1, "aa", buf+2, -612);
181
182 /* not equal, length=3 */
183 buf = "aab""aba""baa";
184 len=3;
185 STRTEST( -1, "aaa", buf+0, -620);
186 STRTEST( -1, "aaa", buf+3, -622);
187 STRTEST( -1, "aaa", buf+6, -624);
188
189 /* not equal, length=4 */
190 buf = "aaab""aaba""abaa""baaa";
191 len=4;
192 STRTEST( -1, "aaaa", buf+0, -630);
193 STRTEST( -1, "aaaa", buf+4, -632);
194 STRTEST( -1, "aaaa", buf+8, -634);
195 STRTEST( -1, "aaaa", buf+12, -636);
196
197 /* not equal, length=5 */
198 buf="aaaab""aaaba""aabaa""abaaa""baaaa";
199 len=5;
200 STRTEST( -1, "aaaaa", buf+0, -640);
201 STRTEST( -1, "aaaaa", buf+5, -642);
202 STRTEST( -1, "aaaaa", buf+10, -644);
203 STRTEST( -1, "aaaaa", buf+15, -646);
204 STRTEST( -1, "aaaaa", buf+20, -648);
205
206 zero.u32.hi = zero.u32.lo = 0;
207 c1 = pj_elapsed_cycle(&zero, &e1);
208 c2 = pj_elapsed_cycle(&zero, &e2);
209
210 if (c1 < c2) {
211 PJ_LOG(3,("", " error: pj_stricmp_alnum is slower than pj_stricmp!"));
212 return -700;
213 }
214
215 PJ_LOG(3, ("", " time: stricmp=%u, stricmp_alnum=%u (speedup=%d.%02dx)",
216 c1, c2,
217 (c1 * 100 / c2) / 100,
218 (c1 * 100 / c2) % 100));
219 return 0;
220#undef STRTEST
221}
222
Benny Prijono8220f902006-01-09 17:20:59 +0000223/* This tests pj_strcmp(), pj_strcmp2(), pj_strncmp(), pj_strncmp2() */
224static int strcmp_test(void)
225{
226#define STR_TEST(res,S1,S2,code) \
227 do { \
228 s1.ptr=S1; s1.slen=S1?len:0; \
229 s2.ptr=S2; s2.slen=S2?len:0; \
230 if (pj_strcmp(&s1,&s2)!=res) return code; \
231 if (pj_strcmp2(&s1,S2)!=res) return code-1; \
232 if (pj_strncmp(&s1,&s2,len)!=res) return code-2; \
233 if (pj_strncmp2(&s1,S2,len)!=res) return code-3; \
234 } while (0)
235
236 pj_str_t s1, s2;
237 int len;
238
239 /* Test with length == 0 */
240 len=0;
241 STR_TEST(0, "", "", -400);
242 STR_TEST(0, NULL, "", -405);
243 STR_TEST(0, "", NULL, -410);
244 STR_TEST(0, NULL, NULL, -415);
245 STR_TEST(0, "hello", "", -420);
246 STR_TEST(0, "hello", NULL, -425);
247
248 /* Test with length != 0 */
249 len = 2;
250 STR_TEST(0, "12", "12", -430);
251 STR_TEST(1, "12", "1", -435);
252 STR_TEST(-1, "1", "12", -440);
253 STR_TEST(-1, NULL, "12", -445);
254 STR_TEST(1, "12", NULL, -450);
255
256 return 0;
257
258#undef STR_TEST
259}
260
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000261int string_test(void)
262{
263 const pj_str_t hello_world = { HELLO_WORLD, strlen(HELLO_WORLD) };
264 const pj_str_t just_hello = { JUST_HELLO, strlen(JUST_HELLO) };
265 pj_str_t s1, s2, s3, s4, s5;
266 enum { RCOUNT = 10, RLEN = 16 };
267 pj_str_t random[RCOUNT];
268 pj_pool_t *pool;
269 int i;
270
271 pool = pj_pool_create(mem, NULL, 4096, 0, NULL);
272 if (!pool) return -5;
273
274 /*
275 * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(),
276 * pj_strncmp(), pj_strchr()
277 */
278 s1 = pj_str(HELLO_WORLD);
279 if (pj_strcmp(&s1, &hello_world) != 0)
280 return -10;
281 if (pj_stricmp(&s1, &hello_world) != 0)
282 return -20;
283 if (pj_strcmp(&s1, &just_hello) <= 0)
284 return -30;
285 if (pj_stricmp(&s1, &just_hello) <= 0)
286 return -40;
287 if (pj_strlen(&s1) != strlen(HELLO_WORLD))
288 return -50;
289 if (pj_strncmp(&s1, &hello_world, 5) != 0)
290 return -60;
291 if (pj_strnicmp(&s1, &hello_world, 5) != 0)
292 return -70;
293 if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
294 return -80;
295
296 /*
297 * pj_strdup()
298 */
299 if (!pj_strdup(pool, &s2, &s1))
300 return -100;
301 if (pj_strcmp(&s1, &s2) != 0)
302 return -110;
303
304 /*
305 * pj_strcpy(), pj_strcat()
306 */
307 s3.ptr = pj_pool_alloc(pool, 256);
308 if (!s3.ptr)
309 return -200;
310 pj_strcpy(&s3, &s2);
311 pj_strcat(&s3, &just_hello);
312
313 if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
314 return -210;
315
316 /*
317 * pj_strdup2(), pj_strtrim().
318 */
319 pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
320 pj_strtrim(&s4);
321 if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
322 return -250;
323
324 /*
325 * pj_utoa()
326 */
327 s5.ptr = pj_pool_alloc(pool, 16);
328 if (!s5.ptr)
329 return -270;
330 s5.slen = pj_utoa(UL_VALUE, s5.ptr);
331
332 /*
333 * pj_strtoul()
334 */
335 if (pj_strtoul(&s5) != UL_VALUE)
336 return -280;
337
338 /*
339 * pj_create_random_string()
340 * Check that no duplicate strings are returned.
341 */
342 for (i=0; i<RCOUNT; ++i) {
343 int j;
344
345 random[i].ptr = pj_pool_alloc(pool, RLEN);
346 if (!random[i].ptr)
347 return -320;
348
349 random[i].slen = RLEN;
350 pj_create_random_string(random[i].ptr, RLEN);
351
352 for (j=0; j<i; ++j) {
353 if (pj_strcmp(&random[i], &random[j])==0)
354 return -330;
355 }
356 }
357
358 /* Done. */
359 pj_pool_release(pool);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000360
Benny Prijono8220f902006-01-09 17:20:59 +0000361 /* Case sensitive comparison test. */
362 i = strcmp_test();
363 if (i != 0)
364 return i;
365
366 /* Caseless comparison test. */
367 i = stricmp_test();
368 if (i != 0)
369 return i;
370
371 return 0;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000372}
373
374#else
375/* To prevent warning about "translation unit is empty"
376 * when this test is disabled.
377 */
378int dummy_string_test;
379#endif /* INCLUDE_STRING_TEST */
380