blob: 4f0e325d1b526263ea5dd4d27509e81cba2d31de [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/string.h>
21#include <pj/pool.h>
22#include <pj/log.h>
Benny Prijonoa7944bb2005-11-21 17:01:50 +000023#include <pj/os.h>
Benny Prijono5dcb38d2005-11-21 01:55:47 +000024#include "test.h"
25
Benny Prijono7d433ec2006-02-03 15:23:28 +000026#define THIS_FILE "string.c"
27
Benny Prijono5dcb38d2005-11-21 01:55:47 +000028/**
29 * \page page_pjlib_string_test Test: String
30 *
31 * This file provides implementation of \b string_test(). It tests the
32 * functionality of the string API.
33 *
34 * \section sleep_test_sec Scope of the Test
35 *
36 * API tested:
37 * - pj_str()
38 * - pj_strcmp()
39 * - pj_strcmp2()
40 * - pj_stricmp()
41 * - pj_strlen()
42 * - pj_strncmp()
43 * - pj_strnicmp()
44 * - pj_strchr()
45 * - pj_strdup()
46 * - pj_strdup2()
47 * - pj_strcpy()
48 * - pj_strcat()
49 * - pj_strtrim()
50 * - pj_utoa()
51 * - pj_strtoul()
Benny Prijonoc7434f62007-04-15 09:58:48 +000052 * - pj_strtoul2()
Benny Prijono5dcb38d2005-11-21 01:55:47 +000053 * - pj_create_random_string()
Benny Prijono8220f902006-01-09 17:20:59 +000054 * - ... and mode..
Benny Prijono5dcb38d2005-11-21 01:55:47 +000055 *
56 * This file is <b>pjlib-test/string.c</b>
57 *
58 * \include pjlib-test/string.c
59 */
60
61#if INCLUDE_STRING_TEST
62
63#ifdef _MSC_VER
64# pragma warning(disable: 4204)
65#endif
66
67#define HELLO_WORLD "Hello World"
Benny Prijonof70f6392009-06-17 12:36:36 +000068#define HELLO_WORLD_LEN 11
Benny Prijono5dcb38d2005-11-21 01:55:47 +000069#define JUST_HELLO "Hello"
Benny Prijonof70f6392009-06-17 12:36:36 +000070#define JUST_HELLO_LEN 5
Benny Prijono5dcb38d2005-11-21 01:55:47 +000071#define UL_VALUE 3456789012UL
72
Benny Prijono7d433ec2006-02-03 15:23:28 +000073#if 1
74/* See if both integers have the same sign */
75PJ_INLINE(int) cmp(const char *expr, int i, int j)
76{
Benny Prijono18a051b2007-06-28 00:50:10 +000077 int r = !((i>0 && j>0) || (i<0 && j<0) || (i==0 && j==0));
78 if (r) {
Benny Prijono7d433ec2006-02-03 15:23:28 +000079 PJ_LOG(3,(THIS_FILE," error: %s: expecting %d, got %d", expr, j, i));
80 }
Benny Prijono18a051b2007-06-28 00:50:10 +000081 return r;
Benny Prijono7d433ec2006-02-03 15:23:28 +000082}
83#else
84/* For strict comparison, must be equal */
85PJ_INLINE(int) cmp(const char *expr, int i, int j)
86{
87 PJ_UNUSED_ARG(expr);
88 return i!=j;
89}
90#endif
91
92#define C(expr, res) cmp(#expr, expr, res)
93
Benny Prijonoa7944bb2005-11-21 17:01:50 +000094static int stricmp_test(void)
95{
Benny Prijono8220f902006-01-09 17:20:59 +000096/* This specificly tests and benchmark pj_stricmp(), pj_stricmp_alnum().
97 * In addition, it also tests pj_stricmp2(), pj_strnicmp(), and
98 * pj_strnicmp2().
99 */
Benny Prijono18a051b2007-06-28 00:50:10 +0000100#define STRTEST(res,res2,S1,S2,code) \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000101 do { \
Benny Prijonoa1e69682007-05-11 15:14:34 +0000102 s1.ptr=S1; s1.slen=(S1)?len:0; \
103 s2.ptr=S2; s2.slen=(S2)?len:0; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000104 pj_get_timestamp(&t1); \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000105 if (C(pj_stricmp(&s1,&s2),res)) return code; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000106 pj_get_timestamp(&t2); \
107 pj_sub_timestamp(&t2, &t1); \
108 pj_add_timestamp(&e1, &t2); \
109 pj_get_timestamp(&t1); \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000110 if (C(pj_stricmp_alnum(&s1,&s2),res)) return code-1; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000111 pj_get_timestamp(&t2); \
112 pj_sub_timestamp(&t2, &t1); \
113 pj_add_timestamp(&e2, &t2); \
Benny Prijono18a051b2007-06-28 00:50:10 +0000114 if (C(pj_stricmp2(&s1,S2),res2)) return code*10; \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000115 if (C(pj_strnicmp(&s1,&s2,len),res)) return code*100; \
116 if (C(pj_strnicmp2(&s1,S2,len),res)) return code*1000; \
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000117 } while (0)
118
119 char *buf;
120 pj_str_t s1, s2;
121 pj_timestamp t1, t2, e1, e2, zero;
122 pj_uint32_t c1, c2;
123 int len;
124
125 e1.u32.hi = e1.u32.lo = e2.u32.hi = e2.u32.lo = 0;
126
127 pj_thread_sleep(0);
128
Benny Prijonoa1e69682007-05-11 15:14:34 +0000129#define SNULL 0
130
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000131 /* Compare empty strings. */
132 len=0;
Benny Prijono18a051b2007-06-28 00:50:10 +0000133 STRTEST( 0, 0, "","",-500);
134 STRTEST( 0, 0, SNULL,"",-502);
135 STRTEST( 0, 0, "",SNULL,-504);
136 STRTEST( 0, 0, SNULL,SNULL,-506);
137 STRTEST( 0, -1, "hello","world",-508);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000138
139 /* equal, length=1
140 * use buffer to simulate non-aligned string.
141 */
142 buf = "a""A";
143 len=1;
Benny Prijono18a051b2007-06-28 00:50:10 +0000144 STRTEST( 0, -1, "a",buf+0,-510);
145 STRTEST( 0, 0, "a",buf+1,-512);
146 STRTEST(-1, -1, "O", "P", -514);
147 STRTEST(-1, -1, SNULL, "a", -516);
148 STRTEST( 1, 1, "a", SNULL, -518);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000149
150 /* equal, length=2
151 * use buffer to simulate non-aligned string.
152 */
153 buf = "aa""Aa""aA""AA";
154 len=2;
Benny Prijono18a051b2007-06-28 00:50:10 +0000155 STRTEST( 0, -1, "aa",buf+0,-520);
156 STRTEST( 0, -1, "aa",buf+2,-522);
157 STRTEST( 0, -1, "aa",buf+4,-524);
158 STRTEST( 0, 0, "aa",buf+6,-524);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000159
160 /* equal, length=3
161 * use buffer to simulate non-aligned string.
162 */
163 buf = "aaa""Aaa""aAa""aaA""AAa""aAA""AaA""AAA";
164 len=3;
Benny Prijono18a051b2007-06-28 00:50:10 +0000165 STRTEST( 0, -1, "aaa",buf+0,-530);
166 STRTEST( 0, -1, "aaa",buf+3,-532);
167 STRTEST( 0, -1, "aaa",buf+6,-534);
168 STRTEST( 0, -1, "aaa",buf+9,-536);
169 STRTEST( 0, -1, "aaa",buf+12,-538);
170 STRTEST( 0, -1, "aaa",buf+15,-540);
171 STRTEST( 0, -1, "aaa",buf+18,-542);
172 STRTEST( 0, 0, "aaa",buf+21,-534);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000173
174 /* equal, length=4 */
175 len=4;
Benny Prijono18a051b2007-06-28 00:50:10 +0000176 STRTEST( 0, 0, "aaaa","aaaa",-540);
177 STRTEST( 0, 0, "aaaa","Aaaa",-542);
178 STRTEST( 0, 0, "aaaa","aAaa",-544);
179 STRTEST( 0, 0, "aaaa","aaAa",-546);
180 STRTEST( 0, 0, "aaaa","aaaA",-548);
181 STRTEST( 0, 0, "aaaa","AAaa",-550);
182 STRTEST( 0, 0, "aaaa","aAAa",-552);
183 STRTEST( 0, 0, "aaaa","aaAA",-554);
184 STRTEST( 0, 0, "aaaa","AaAa",-556);
185 STRTEST( 0, 0, "aaaa","aAaA",-558);
186 STRTEST( 0, 0, "aaaa","AaaA",-560);
187 STRTEST( 0, 0, "aaaa","AAAa",-562);
188 STRTEST( 0, 0, "aaaa","aAAA",-564);
189 STRTEST( 0, 0, "aaaa","AAaA",-566);
190 STRTEST( 0, 0, "aaaa","AaAA",-568);
191 STRTEST( 0, 0, "aaaa","AAAA",-570);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000192
193 /* equal, length=5 */
194 buf = "aaaAa""AaaaA""AaAaA""AAAAA";
195 len=5;
Benny Prijono18a051b2007-06-28 00:50:10 +0000196 STRTEST( 0, -1, "aaaaa",buf+0,-580);
197 STRTEST( 0, -1, "aaaaa",buf+5,-582);
198 STRTEST( 0, -1, "aaaaa",buf+10,-584);
199 STRTEST( 0, 0, "aaaaa",buf+15,-586);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000200
201 /* not equal, length=1 */
202 len=1;
Benny Prijono18a051b2007-06-28 00:50:10 +0000203 STRTEST( -1, -1, "a", "b", -600);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000204
205 /* not equal, length=2 */
206 buf = "ab""ba";
207 len=2;
Benny Prijono18a051b2007-06-28 00:50:10 +0000208 STRTEST( -1, -1, "aa", buf+0, -610);
209 STRTEST( -1, -1, "aa", buf+2, -612);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000210
211 /* not equal, length=3 */
212 buf = "aab""aba""baa";
213 len=3;
Benny Prijono18a051b2007-06-28 00:50:10 +0000214 STRTEST( -1, -1, "aaa", buf+0, -620);
215 STRTEST( -1, -1, "aaa", buf+3, -622);
216 STRTEST( -1, -1, "aaa", buf+6, -624);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000217
218 /* not equal, length=4 */
219 buf = "aaab""aaba""abaa""baaa";
220 len=4;
Benny Prijono18a051b2007-06-28 00:50:10 +0000221 STRTEST( -1, -1, "aaaa", buf+0, -630);
222 STRTEST( -1, -1, "aaaa", buf+4, -632);
223 STRTEST( -1, -1, "aaaa", buf+8, -634);
224 STRTEST( -1, -1, "aaaa", buf+12, -636);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000225
226 /* not equal, length=5 */
227 buf="aaaab""aaaba""aabaa""abaaa""baaaa";
228 len=5;
Benny Prijono18a051b2007-06-28 00:50:10 +0000229 STRTEST( -1, -1, "aaaaa", buf+0, -640);
230 STRTEST( -1, -1, "aaaaa", buf+5, -642);
231 STRTEST( -1, -1, "aaaaa", buf+10, -644);
232 STRTEST( -1, -1, "aaaaa", buf+15, -646);
233 STRTEST( -1, -1, "aaaaa", buf+20, -648);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000234
235 zero.u32.hi = zero.u32.lo = 0;
236 c1 = pj_elapsed_cycle(&zero, &e1);
237 c2 = pj_elapsed_cycle(&zero, &e2);
238
239 if (c1 < c2) {
Benny Prijono37e8d332006-01-20 21:03:36 +0000240 PJ_LOG(3,("", " info: pj_stricmp_alnum is slower than pj_stricmp!"));
241 //return -700;
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000242 }
243
Benny Prijonof260e462007-04-30 21:03:32 +0000244 /* Avoid division by zero */
245 if (c2 == 0) c2=1;
246
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000247 PJ_LOG(3, ("", " time: stricmp=%u, stricmp_alnum=%u (speedup=%d.%02dx)",
248 c1, c2,
249 (c1 * 100 / c2) / 100,
250 (c1 * 100 / c2) % 100));
251 return 0;
252#undef STRTEST
253}
254
Benny Prijono8220f902006-01-09 17:20:59 +0000255/* This tests pj_strcmp(), pj_strcmp2(), pj_strncmp(), pj_strncmp2() */
256static int strcmp_test(void)
257{
258#define STR_TEST(res,S1,S2,code) \
259 do { \
260 s1.ptr=S1; s1.slen=S1?len:0; \
261 s2.ptr=S2; s2.slen=S2?len:0; \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000262 if (C(pj_strcmp(&s1,&s2),res)) return code; \
263 if (C(pj_strcmp2(&s1,S2),res)) return code-1; \
264 if (C(pj_strncmp(&s1,&s2,len),res)) return code-2; \
265 if (C(pj_strncmp2(&s1,S2,len),res)) return code-3; \
Benny Prijono8220f902006-01-09 17:20:59 +0000266 } while (0)
267
268 pj_str_t s1, s2;
269 int len;
270
271 /* Test with length == 0 */
272 len=0;
273 STR_TEST(0, "", "", -400);
Benny Prijonoa1e69682007-05-11 15:14:34 +0000274 STR_TEST(0, SNULL, "", -405);
275 STR_TEST(0, "", SNULL, -410);
276 STR_TEST(0, SNULL, SNULL, -415);
Benny Prijono8220f902006-01-09 17:20:59 +0000277 STR_TEST(0, "hello", "", -420);
Benny Prijonoa1e69682007-05-11 15:14:34 +0000278 STR_TEST(0, "hello", SNULL, -425);
Benny Prijono8220f902006-01-09 17:20:59 +0000279
280 /* Test with length != 0 */
281 len = 2;
282 STR_TEST(0, "12", "12", -430);
283 STR_TEST(1, "12", "1", -435);
284 STR_TEST(-1, "1", "12", -440);
Benny Prijonoa1e69682007-05-11 15:14:34 +0000285 STR_TEST(-1, SNULL, "12", -445);
286 STR_TEST(1, "12", SNULL, -450);
Benny Prijono8220f902006-01-09 17:20:59 +0000287
288 return 0;
289
290#undef STR_TEST
291}
292
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000293int string_test(void)
294{
Benny Prijonof70f6392009-06-17 12:36:36 +0000295 const pj_str_t hello_world = { HELLO_WORLD, HELLO_WORLD_LEN };
296 const pj_str_t just_hello = { JUST_HELLO, JUST_HELLO_LEN };
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000297 pj_str_t s1, s2, s3, s4, s5;
298 enum { RCOUNT = 10, RLEN = 16 };
299 pj_str_t random[RCOUNT];
300 pj_pool_t *pool;
301 int i;
302
Benny Prijonoa1e69682007-05-11 15:14:34 +0000303 pool = pj_pool_create(mem, SNULL, 4096, 0, SNULL);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000304 if (!pool) return -5;
305
306 /*
307 * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(),
308 * pj_strncmp(), pj_strchr()
309 */
310 s1 = pj_str(HELLO_WORLD);
311 if (pj_strcmp(&s1, &hello_world) != 0)
312 return -10;
313 if (pj_stricmp(&s1, &hello_world) != 0)
314 return -20;
315 if (pj_strcmp(&s1, &just_hello) <= 0)
316 return -30;
317 if (pj_stricmp(&s1, &just_hello) <= 0)
318 return -40;
319 if (pj_strlen(&s1) != strlen(HELLO_WORLD))
320 return -50;
321 if (pj_strncmp(&s1, &hello_world, 5) != 0)
322 return -60;
323 if (pj_strnicmp(&s1, &hello_world, 5) != 0)
324 return -70;
325 if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
326 return -80;
327
328 /*
329 * pj_strdup()
330 */
331 if (!pj_strdup(pool, &s2, &s1))
332 return -100;
333 if (pj_strcmp(&s1, &s2) != 0)
334 return -110;
335
336 /*
337 * pj_strcpy(), pj_strcat()
338 */
Benny Prijonof260e462007-04-30 21:03:32 +0000339 s3.ptr = (char*) pj_pool_alloc(pool, 256);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000340 if (!s3.ptr)
341 return -200;
342 pj_strcpy(&s3, &s2);
343 pj_strcat(&s3, &just_hello);
344
345 if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
346 return -210;
347
348 /*
349 * pj_strdup2(), pj_strtrim().
350 */
351 pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
352 pj_strtrim(&s4);
353 if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
354 return -250;
355
356 /*
357 * pj_utoa()
358 */
Benny Prijonof260e462007-04-30 21:03:32 +0000359 s5.ptr = (char*) pj_pool_alloc(pool, 16);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000360 if (!s5.ptr)
361 return -270;
362 s5.slen = pj_utoa(UL_VALUE, s5.ptr);
363
364 /*
365 * pj_strtoul()
366 */
367 if (pj_strtoul(&s5) != UL_VALUE)
368 return -280;
369
Benny Prijonoc7434f62007-04-15 09:58:48 +0000370 /*
371 * pj_strtoul2()
372 */
373 s5 = pj_str("123456");
374
Benny Prijonoa1e69682007-05-11 15:14:34 +0000375 pj_strtoul2(&s5, SNULL, 10); /* Crash test */
Benny Prijonoc7434f62007-04-15 09:58:48 +0000376
377 if (pj_strtoul2(&s5, &s4, 10) != 123456UL)
378 return -290;
379 if (s4.slen != 0)
380 return -291;
381 if (pj_strtoul2(&s5, &s4, 16) != 0x123456UL)
382 return -292;
383
384 s5 = pj_str("0123ABCD");
385 if (pj_strtoul2(&s5, &s4, 10) != 123)
386 return -293;
387 if (s4.slen != 4)
388 return -294;
Benny Prijonoa1e69682007-05-11 15:14:34 +0000389 if (s4.ptr == SNULL || *s4.ptr != 'A')
Benny Prijonoc7434f62007-04-15 09:58:48 +0000390 return -295;
391 if (pj_strtoul2(&s5, &s4, 16) != 0x123ABCDUL)
392 return -296;
393 if (s4.slen != 0)
394 return -297;
395
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000396 /*
397 * pj_create_random_string()
398 * Check that no duplicate strings are returned.
399 */
400 for (i=0; i<RCOUNT; ++i) {
401 int j;
402
Benny Prijonof260e462007-04-30 21:03:32 +0000403 random[i].ptr = (char*) pj_pool_alloc(pool, RLEN);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000404 if (!random[i].ptr)
405 return -320;
406
407 random[i].slen = RLEN;
408 pj_create_random_string(random[i].ptr, RLEN);
409
410 for (j=0; j<i; ++j) {
411 if (pj_strcmp(&random[i], &random[j])==0)
412 return -330;
413 }
414 }
415
416 /* Done. */
417 pj_pool_release(pool);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000418
Benny Prijono8220f902006-01-09 17:20:59 +0000419 /* Case sensitive comparison test. */
420 i = strcmp_test();
421 if (i != 0)
422 return i;
423
424 /* Caseless comparison test. */
425 i = stricmp_test();
426 if (i != 0)
427 return i;
428
429 return 0;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000430}
431
432#else
433/* To prevent warning about "translation unit is empty"
434 * when this test is disabled.
435 */
436int dummy_string_test;
437#endif /* INCLUDE_STRING_TEST */
438