blob: a436c9eefb6de01dfb07cebe716a364096826129 [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono5dcb38d2005-11-21 01:55:47 +00004 *
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
Benny Prijono7d433ec2006-02-03 15:23:28 +000025#define THIS_FILE "string.c"
26
Benny Prijono5dcb38d2005-11-21 01:55:47 +000027/**
28 * \page page_pjlib_string_test Test: String
29 *
30 * This file provides implementation of \b string_test(). It tests the
31 * functionality of the string API.
32 *
33 * \section sleep_test_sec Scope of the Test
34 *
35 * API tested:
36 * - pj_str()
37 * - pj_strcmp()
38 * - pj_strcmp2()
39 * - pj_stricmp()
40 * - pj_strlen()
41 * - pj_strncmp()
42 * - pj_strnicmp()
43 * - pj_strchr()
44 * - pj_strdup()
45 * - pj_strdup2()
46 * - pj_strcpy()
47 * - pj_strcat()
48 * - pj_strtrim()
49 * - pj_utoa()
50 * - pj_strtoul()
Benny Prijonoc7434f62007-04-15 09:58:48 +000051 * - pj_strtoul2()
Benny Prijono5dcb38d2005-11-21 01:55:47 +000052 * - pj_create_random_string()
Benny Prijono8220f902006-01-09 17:20:59 +000053 * - ... and mode..
Benny Prijono5dcb38d2005-11-21 01:55:47 +000054 *
55 * This file is <b>pjlib-test/string.c</b>
56 *
57 * \include pjlib-test/string.c
58 */
59
60#if INCLUDE_STRING_TEST
61
62#ifdef _MSC_VER
63# pragma warning(disable: 4204)
64#endif
65
66#define HELLO_WORLD "Hello World"
67#define JUST_HELLO "Hello"
68#define UL_VALUE 3456789012UL
69
Benny Prijono7d433ec2006-02-03 15:23:28 +000070#if 1
71/* See if both integers have the same sign */
72PJ_INLINE(int) cmp(const char *expr, int i, int j)
73{
Benny Prijono18a051b2007-06-28 00:50:10 +000074 int r = !((i>0 && j>0) || (i<0 && j<0) || (i==0 && j==0));
75 if (r) {
Benny Prijono7d433ec2006-02-03 15:23:28 +000076 PJ_LOG(3,(THIS_FILE," error: %s: expecting %d, got %d", expr, j, i));
77 }
Benny Prijono18a051b2007-06-28 00:50:10 +000078 return r;
Benny Prijono7d433ec2006-02-03 15:23:28 +000079}
80#else
81/* For strict comparison, must be equal */
82PJ_INLINE(int) cmp(const char *expr, int i, int j)
83{
84 PJ_UNUSED_ARG(expr);
85 return i!=j;
86}
87#endif
88
89#define C(expr, res) cmp(#expr, expr, res)
90
Benny Prijonoa7944bb2005-11-21 17:01:50 +000091static int stricmp_test(void)
92{
Benny Prijono8220f902006-01-09 17:20:59 +000093/* This specificly tests and benchmark pj_stricmp(), pj_stricmp_alnum().
94 * In addition, it also tests pj_stricmp2(), pj_strnicmp(), and
95 * pj_strnicmp2().
96 */
Benny Prijono18a051b2007-06-28 00:50:10 +000097#define STRTEST(res,res2,S1,S2,code) \
Benny Prijonoa7944bb2005-11-21 17:01:50 +000098 do { \
Benny Prijonoa1e69682007-05-11 15:14:34 +000099 s1.ptr=S1; s1.slen=(S1)?len:0; \
100 s2.ptr=S2; s2.slen=(S2)?len:0; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000101 pj_get_timestamp(&t1); \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000102 if (C(pj_stricmp(&s1,&s2),res)) return code; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000103 pj_get_timestamp(&t2); \
104 pj_sub_timestamp(&t2, &t1); \
105 pj_add_timestamp(&e1, &t2); \
106 pj_get_timestamp(&t1); \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000107 if (C(pj_stricmp_alnum(&s1,&s2),res)) return code-1; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000108 pj_get_timestamp(&t2); \
109 pj_sub_timestamp(&t2, &t1); \
110 pj_add_timestamp(&e2, &t2); \
Benny Prijono18a051b2007-06-28 00:50:10 +0000111 if (C(pj_stricmp2(&s1,S2),res2)) return code*10; \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000112 if (C(pj_strnicmp(&s1,&s2,len),res)) return code*100; \
113 if (C(pj_strnicmp2(&s1,S2,len),res)) return code*1000; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000114 } while (0)
115
116 char *buf;
117 pj_str_t s1, s2;
118 pj_timestamp t1, t2, e1, e2, zero;
119 pj_uint32_t c1, c2;
120 int len;
121
122 e1.u32.hi = e1.u32.lo = e2.u32.hi = e2.u32.lo = 0;
123
124 pj_thread_sleep(0);
125
Benny Prijonoa1e69682007-05-11 15:14:34 +0000126#define SNULL 0
127
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000128 /* Compare empty strings. */
129 len=0;
Benny Prijono18a051b2007-06-28 00:50:10 +0000130 STRTEST( 0, 0, "","",-500);
131 STRTEST( 0, 0, SNULL,"",-502);
132 STRTEST( 0, 0, "",SNULL,-504);
133 STRTEST( 0, 0, SNULL,SNULL,-506);
134 STRTEST( 0, -1, "hello","world",-508);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000135
136 /* equal, length=1
137 * use buffer to simulate non-aligned string.
138 */
139 buf = "a""A";
140 len=1;
Benny Prijono18a051b2007-06-28 00:50:10 +0000141 STRTEST( 0, -1, "a",buf+0,-510);
142 STRTEST( 0, 0, "a",buf+1,-512);
143 STRTEST(-1, -1, "O", "P", -514);
144 STRTEST(-1, -1, SNULL, "a", -516);
145 STRTEST( 1, 1, "a", SNULL, -518);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000146
147 /* equal, length=2
148 * use buffer to simulate non-aligned string.
149 */
150 buf = "aa""Aa""aA""AA";
151 len=2;
Benny Prijono18a051b2007-06-28 00:50:10 +0000152 STRTEST( 0, -1, "aa",buf+0,-520);
153 STRTEST( 0, -1, "aa",buf+2,-522);
154 STRTEST( 0, -1, "aa",buf+4,-524);
155 STRTEST( 0, 0, "aa",buf+6,-524);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000156
157 /* equal, length=3
158 * use buffer to simulate non-aligned string.
159 */
160 buf = "aaa""Aaa""aAa""aaA""AAa""aAA""AaA""AAA";
161 len=3;
Benny Prijono18a051b2007-06-28 00:50:10 +0000162 STRTEST( 0, -1, "aaa",buf+0,-530);
163 STRTEST( 0, -1, "aaa",buf+3,-532);
164 STRTEST( 0, -1, "aaa",buf+6,-534);
165 STRTEST( 0, -1, "aaa",buf+9,-536);
166 STRTEST( 0, -1, "aaa",buf+12,-538);
167 STRTEST( 0, -1, "aaa",buf+15,-540);
168 STRTEST( 0, -1, "aaa",buf+18,-542);
169 STRTEST( 0, 0, "aaa",buf+21,-534);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000170
171 /* equal, length=4 */
172 len=4;
Benny Prijono18a051b2007-06-28 00:50:10 +0000173 STRTEST( 0, 0, "aaaa","aaaa",-540);
174 STRTEST( 0, 0, "aaaa","Aaaa",-542);
175 STRTEST( 0, 0, "aaaa","aAaa",-544);
176 STRTEST( 0, 0, "aaaa","aaAa",-546);
177 STRTEST( 0, 0, "aaaa","aaaA",-548);
178 STRTEST( 0, 0, "aaaa","AAaa",-550);
179 STRTEST( 0, 0, "aaaa","aAAa",-552);
180 STRTEST( 0, 0, "aaaa","aaAA",-554);
181 STRTEST( 0, 0, "aaaa","AaAa",-556);
182 STRTEST( 0, 0, "aaaa","aAaA",-558);
183 STRTEST( 0, 0, "aaaa","AaaA",-560);
184 STRTEST( 0, 0, "aaaa","AAAa",-562);
185 STRTEST( 0, 0, "aaaa","aAAA",-564);
186 STRTEST( 0, 0, "aaaa","AAaA",-566);
187 STRTEST( 0, 0, "aaaa","AaAA",-568);
188 STRTEST( 0, 0, "aaaa","AAAA",-570);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000189
190 /* equal, length=5 */
191 buf = "aaaAa""AaaaA""AaAaA""AAAAA";
192 len=5;
Benny Prijono18a051b2007-06-28 00:50:10 +0000193 STRTEST( 0, -1, "aaaaa",buf+0,-580);
194 STRTEST( 0, -1, "aaaaa",buf+5,-582);
195 STRTEST( 0, -1, "aaaaa",buf+10,-584);
196 STRTEST( 0, 0, "aaaaa",buf+15,-586);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000197
198 /* not equal, length=1 */
199 len=1;
Benny Prijono18a051b2007-06-28 00:50:10 +0000200 STRTEST( -1, -1, "a", "b", -600);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000201
202 /* not equal, length=2 */
203 buf = "ab""ba";
204 len=2;
Benny Prijono18a051b2007-06-28 00:50:10 +0000205 STRTEST( -1, -1, "aa", buf+0, -610);
206 STRTEST( -1, -1, "aa", buf+2, -612);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000207
208 /* not equal, length=3 */
209 buf = "aab""aba""baa";
210 len=3;
Benny Prijono18a051b2007-06-28 00:50:10 +0000211 STRTEST( -1, -1, "aaa", buf+0, -620);
212 STRTEST( -1, -1, "aaa", buf+3, -622);
213 STRTEST( -1, -1, "aaa", buf+6, -624);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000214
215 /* not equal, length=4 */
216 buf = "aaab""aaba""abaa""baaa";
217 len=4;
Benny Prijono18a051b2007-06-28 00:50:10 +0000218 STRTEST( -1, -1, "aaaa", buf+0, -630);
219 STRTEST( -1, -1, "aaaa", buf+4, -632);
220 STRTEST( -1, -1, "aaaa", buf+8, -634);
221 STRTEST( -1, -1, "aaaa", buf+12, -636);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000222
223 /* not equal, length=5 */
224 buf="aaaab""aaaba""aabaa""abaaa""baaaa";
225 len=5;
Benny Prijono18a051b2007-06-28 00:50:10 +0000226 STRTEST( -1, -1, "aaaaa", buf+0, -640);
227 STRTEST( -1, -1, "aaaaa", buf+5, -642);
228 STRTEST( -1, -1, "aaaaa", buf+10, -644);
229 STRTEST( -1, -1, "aaaaa", buf+15, -646);
230 STRTEST( -1, -1, "aaaaa", buf+20, -648);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000231
232 zero.u32.hi = zero.u32.lo = 0;
233 c1 = pj_elapsed_cycle(&zero, &e1);
234 c2 = pj_elapsed_cycle(&zero, &e2);
235
236 if (c1 < c2) {
Benny Prijono37e8d332006-01-20 21:03:36 +0000237 PJ_LOG(3,("", " info: pj_stricmp_alnum is slower than pj_stricmp!"));
238 //return -700;
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000239 }
240
Benny Prijonof260e462007-04-30 21:03:32 +0000241 /* Avoid division by zero */
242 if (c2 == 0) c2=1;
243
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000244 PJ_LOG(3, ("", " time: stricmp=%u, stricmp_alnum=%u (speedup=%d.%02dx)",
245 c1, c2,
246 (c1 * 100 / c2) / 100,
247 (c1 * 100 / c2) % 100));
248 return 0;
249#undef STRTEST
250}
251
Benny Prijono8220f902006-01-09 17:20:59 +0000252/* This tests pj_strcmp(), pj_strcmp2(), pj_strncmp(), pj_strncmp2() */
253static int strcmp_test(void)
254{
255#define STR_TEST(res,S1,S2,code) \
256 do { \
257 s1.ptr=S1; s1.slen=S1?len:0; \
258 s2.ptr=S2; s2.slen=S2?len:0; \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000259 if (C(pj_strcmp(&s1,&s2),res)) return code; \
260 if (C(pj_strcmp2(&s1,S2),res)) return code-1; \
261 if (C(pj_strncmp(&s1,&s2,len),res)) return code-2; \
262 if (C(pj_strncmp2(&s1,S2,len),res)) return code-3; \
Benny Prijono8220f902006-01-09 17:20:59 +0000263 } while (0)
264
265 pj_str_t s1, s2;
266 int len;
267
268 /* Test with length == 0 */
269 len=0;
270 STR_TEST(0, "", "", -400);
Benny Prijonoa1e69682007-05-11 15:14:34 +0000271 STR_TEST(0, SNULL, "", -405);
272 STR_TEST(0, "", SNULL, -410);
273 STR_TEST(0, SNULL, SNULL, -415);
Benny Prijono8220f902006-01-09 17:20:59 +0000274 STR_TEST(0, "hello", "", -420);
Benny Prijonoa1e69682007-05-11 15:14:34 +0000275 STR_TEST(0, "hello", SNULL, -425);
Benny Prijono8220f902006-01-09 17:20:59 +0000276
277 /* Test with length != 0 */
278 len = 2;
279 STR_TEST(0, "12", "12", -430);
280 STR_TEST(1, "12", "1", -435);
281 STR_TEST(-1, "1", "12", -440);
Benny Prijonoa1e69682007-05-11 15:14:34 +0000282 STR_TEST(-1, SNULL, "12", -445);
283 STR_TEST(1, "12", SNULL, -450);
Benny Prijono8220f902006-01-09 17:20:59 +0000284
285 return 0;
286
287#undef STR_TEST
288}
289
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000290int string_test(void)
291{
292 const pj_str_t hello_world = { HELLO_WORLD, strlen(HELLO_WORLD) };
293 const pj_str_t just_hello = { JUST_HELLO, strlen(JUST_HELLO) };
294 pj_str_t s1, s2, s3, s4, s5;
295 enum { RCOUNT = 10, RLEN = 16 };
296 pj_str_t random[RCOUNT];
297 pj_pool_t *pool;
298 int i;
299
Benny Prijonoa1e69682007-05-11 15:14:34 +0000300 pool = pj_pool_create(mem, SNULL, 4096, 0, SNULL);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000301 if (!pool) return -5;
302
303 /*
304 * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(),
305 * pj_strncmp(), pj_strchr()
306 */
307 s1 = pj_str(HELLO_WORLD);
308 if (pj_strcmp(&s1, &hello_world) != 0)
309 return -10;
310 if (pj_stricmp(&s1, &hello_world) != 0)
311 return -20;
312 if (pj_strcmp(&s1, &just_hello) <= 0)
313 return -30;
314 if (pj_stricmp(&s1, &just_hello) <= 0)
315 return -40;
316 if (pj_strlen(&s1) != strlen(HELLO_WORLD))
317 return -50;
318 if (pj_strncmp(&s1, &hello_world, 5) != 0)
319 return -60;
320 if (pj_strnicmp(&s1, &hello_world, 5) != 0)
321 return -70;
322 if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
323 return -80;
324
325 /*
326 * pj_strdup()
327 */
328 if (!pj_strdup(pool, &s2, &s1))
329 return -100;
330 if (pj_strcmp(&s1, &s2) != 0)
331 return -110;
332
333 /*
334 * pj_strcpy(), pj_strcat()
335 */
Benny Prijonof260e462007-04-30 21:03:32 +0000336 s3.ptr = (char*) pj_pool_alloc(pool, 256);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000337 if (!s3.ptr)
338 return -200;
339 pj_strcpy(&s3, &s2);
340 pj_strcat(&s3, &just_hello);
341
342 if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
343 return -210;
344
345 /*
346 * pj_strdup2(), pj_strtrim().
347 */
348 pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
349 pj_strtrim(&s4);
350 if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
351 return -250;
352
353 /*
354 * pj_utoa()
355 */
Benny Prijonof260e462007-04-30 21:03:32 +0000356 s5.ptr = (char*) pj_pool_alloc(pool, 16);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000357 if (!s5.ptr)
358 return -270;
359 s5.slen = pj_utoa(UL_VALUE, s5.ptr);
360
361 /*
362 * pj_strtoul()
363 */
364 if (pj_strtoul(&s5) != UL_VALUE)
365 return -280;
366
Benny Prijonoc7434f62007-04-15 09:58:48 +0000367 /*
368 * pj_strtoul2()
369 */
370 s5 = pj_str("123456");
371
Benny Prijonoa1e69682007-05-11 15:14:34 +0000372 pj_strtoul2(&s5, SNULL, 10); /* Crash test */
Benny Prijonoc7434f62007-04-15 09:58:48 +0000373
374 if (pj_strtoul2(&s5, &s4, 10) != 123456UL)
375 return -290;
376 if (s4.slen != 0)
377 return -291;
378 if (pj_strtoul2(&s5, &s4, 16) != 0x123456UL)
379 return -292;
380
381 s5 = pj_str("0123ABCD");
382 if (pj_strtoul2(&s5, &s4, 10) != 123)
383 return -293;
384 if (s4.slen != 4)
385 return -294;
Benny Prijonoa1e69682007-05-11 15:14:34 +0000386 if (s4.ptr == SNULL || *s4.ptr != 'A')
Benny Prijonoc7434f62007-04-15 09:58:48 +0000387 return -295;
388 if (pj_strtoul2(&s5, &s4, 16) != 0x123ABCDUL)
389 return -296;
390 if (s4.slen != 0)
391 return -297;
392
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000393 /*
394 * pj_create_random_string()
395 * Check that no duplicate strings are returned.
396 */
397 for (i=0; i<RCOUNT; ++i) {
398 int j;
399
Benny Prijonof260e462007-04-30 21:03:32 +0000400 random[i].ptr = (char*) pj_pool_alloc(pool, RLEN);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000401 if (!random[i].ptr)
402 return -320;
403
404 random[i].slen = RLEN;
405 pj_create_random_string(random[i].ptr, RLEN);
406
407 for (j=0; j<i; ++j) {
408 if (pj_strcmp(&random[i], &random[j])==0)
409 return -330;
410 }
411 }
412
413 /* Done. */
414 pj_pool_release(pool);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000415
Benny Prijono8220f902006-01-09 17:20:59 +0000416 /* Case sensitive comparison test. */
417 i = strcmp_test();
418 if (i != 0)
419 return i;
420
421 /* Caseless comparison test. */
422 i = stricmp_test();
423 if (i != 0)
424 return i;
425
426 return 0;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000427}
428
429#else
430/* To prevent warning about "translation unit is empty"
431 * when this test is disabled.
432 */
433int dummy_string_test;
434#endif /* INCLUDE_STRING_TEST */
435