blob: d8bc54fdf5e7f51fca8564af1cdd444f2f88dc09 [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{
74 i = !((i>0 && j>0) || (i<0 && j<0) || (i==0 && j==0));
75 if (i) {
76 PJ_LOG(3,(THIS_FILE," error: %s: expecting %d, got %d", expr, j, i));
77 }
78 return i;
79}
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 Prijonoa7944bb2005-11-21 17:01:50 +000097#define STRTEST(res,S1,S2,code) \
98 do { \
Benny Prijono8220f902006-01-09 17:20:59 +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 Prijono7d433ec2006-02-03 15:23:28 +0000111 if (C(pj_stricmp2(&s1,S2),res)) return code*10; \
112 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
126 /* Compare empty strings. */
127 len=0;
128 STRTEST( 0, "","",-500);
Benny Prijono8220f902006-01-09 17:20:59 +0000129 STRTEST( 0, NULL,"",-502);
130 STRTEST( 0, "",NULL,-504);
131 STRTEST( 0, NULL,NULL,-506);
132 STRTEST( 0, "hello","world",-508);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000133
134 /* equal, length=1
135 * use buffer to simulate non-aligned string.
136 */
137 buf = "a""A";
138 len=1;
139 STRTEST( 0, "a",buf+0,-510);
140 STRTEST( 0, "a",buf+1,-512);
Benny Prijono7d433ec2006-02-03 15:23:28 +0000141 STRTEST( -1, "O", "P", -514);
Benny Prijono8220f902006-01-09 17:20:59 +0000142 STRTEST(-1, NULL, "a", -516);
143 STRTEST(1, "a", NULL, -518);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000144
145 /* equal, length=2
146 * use buffer to simulate non-aligned string.
147 */
148 buf = "aa""Aa""aA""AA";
149 len=2;
150 STRTEST( 0, "aa",buf+0,-520);
151 STRTEST( 0, "aa",buf+2,-522);
152 STRTEST( 0, "aa",buf+4,-524);
153 STRTEST( 0, "aa",buf+6,-524);
154
155 /* equal, length=3
156 * use buffer to simulate non-aligned string.
157 */
158 buf = "aaa""Aaa""aAa""aaA""AAa""aAA""AaA""AAA";
159 len=3;
160 STRTEST( 0, "aaa",buf+0,-530);
161 STRTEST( 0, "aaa",buf+3,-532);
162 STRTEST( 0, "aaa",buf+6,-534);
163 STRTEST( 0, "aaa",buf+9,-536);
164 STRTEST( 0, "aaa",buf+12,-538);
165 STRTEST( 0, "aaa",buf+15,-540);
166 STRTEST( 0, "aaa",buf+18,-542);
167 STRTEST( 0, "aaa",buf+21,-534);
168
169 /* equal, length=4 */
170 len=4;
171 STRTEST( 0, "aaaa","aaaa",-540);
172 STRTEST( 0, "aaaa","Aaaa",-542);
173 STRTEST( 0, "aaaa","aAaa",-544);
174 STRTEST( 0, "aaaa","aaAa",-546);
175 STRTEST( 0, "aaaa","aaaA",-548);
176 STRTEST( 0, "aaaa","AAaa",-550);
177 STRTEST( 0, "aaaa","aAAa",-552);
178 STRTEST( 0, "aaaa","aaAA",-554);
179 STRTEST( 0, "aaaa","AaAa",-556);
180 STRTEST( 0, "aaaa","aAaA",-558);
181 STRTEST( 0, "aaaa","AaaA",-560);
182 STRTEST( 0, "aaaa","AAAa",-562);
183 STRTEST( 0, "aaaa","aAAA",-564);
184 STRTEST( 0, "aaaa","AAaA",-566);
185 STRTEST( 0, "aaaa","AaAA",-568);
186 STRTEST( 0, "aaaa","AAAA",-570);
187
188 /* equal, length=5 */
189 buf = "aaaAa""AaaaA""AaAaA""AAAAA";
190 len=5;
191 STRTEST( 0, "aaaaa",buf+0,-580);
192 STRTEST( 0, "aaaaa",buf+5,-582);
193 STRTEST( 0, "aaaaa",buf+10,-584);
194 STRTEST( 0, "aaaaa",buf+15,-586);
195
196 /* not equal, length=1 */
197 len=1;
198 STRTEST( -1, "a", "b", -600);
199
200 /* not equal, length=2 */
201 buf = "ab""ba";
202 len=2;
203 STRTEST( -1, "aa", buf+0, -610);
204 STRTEST( -1, "aa", buf+2, -612);
205
206 /* not equal, length=3 */
207 buf = "aab""aba""baa";
208 len=3;
209 STRTEST( -1, "aaa", buf+0, -620);
210 STRTEST( -1, "aaa", buf+3, -622);
211 STRTEST( -1, "aaa", buf+6, -624);
212
213 /* not equal, length=4 */
214 buf = "aaab""aaba""abaa""baaa";
215 len=4;
216 STRTEST( -1, "aaaa", buf+0, -630);
217 STRTEST( -1, "aaaa", buf+4, -632);
218 STRTEST( -1, "aaaa", buf+8, -634);
219 STRTEST( -1, "aaaa", buf+12, -636);
220
221 /* not equal, length=5 */
222 buf="aaaab""aaaba""aabaa""abaaa""baaaa";
223 len=5;
224 STRTEST( -1, "aaaaa", buf+0, -640);
225 STRTEST( -1, "aaaaa", buf+5, -642);
226 STRTEST( -1, "aaaaa", buf+10, -644);
227 STRTEST( -1, "aaaaa", buf+15, -646);
228 STRTEST( -1, "aaaaa", buf+20, -648);
229
230 zero.u32.hi = zero.u32.lo = 0;
231 c1 = pj_elapsed_cycle(&zero, &e1);
232 c2 = pj_elapsed_cycle(&zero, &e2);
233
234 if (c1 < c2) {
Benny Prijono37e8d332006-01-20 21:03:36 +0000235 PJ_LOG(3,("", " info: pj_stricmp_alnum is slower than pj_stricmp!"));
236 //return -700;
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000237 }
238
Benny Prijonof260e462007-04-30 21:03:32 +0000239 /* Avoid division by zero */
240 if (c2 == 0) c2=1;
241
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000242 PJ_LOG(3, ("", " time: stricmp=%u, stricmp_alnum=%u (speedup=%d.%02dx)",
243 c1, c2,
244 (c1 * 100 / c2) / 100,
245 (c1 * 100 / c2) % 100));
246 return 0;
247#undef STRTEST
248}
249
Benny Prijono8220f902006-01-09 17:20:59 +0000250/* This tests pj_strcmp(), pj_strcmp2(), pj_strncmp(), pj_strncmp2() */
251static int strcmp_test(void)
252{
253#define STR_TEST(res,S1,S2,code) \
254 do { \
255 s1.ptr=S1; s1.slen=S1?len:0; \
256 s2.ptr=S2; s2.slen=S2?len:0; \
Benny Prijono7d433ec2006-02-03 15:23:28 +0000257 if (C(pj_strcmp(&s1,&s2),res)) return code; \
258 if (C(pj_strcmp2(&s1,S2),res)) return code-1; \
259 if (C(pj_strncmp(&s1,&s2,len),res)) return code-2; \
260 if (C(pj_strncmp2(&s1,S2,len),res)) return code-3; \
Benny Prijono8220f902006-01-09 17:20:59 +0000261 } while (0)
262
263 pj_str_t s1, s2;
264 int len;
265
266 /* Test with length == 0 */
267 len=0;
268 STR_TEST(0, "", "", -400);
269 STR_TEST(0, NULL, "", -405);
270 STR_TEST(0, "", NULL, -410);
271 STR_TEST(0, NULL, NULL, -415);
272 STR_TEST(0, "hello", "", -420);
273 STR_TEST(0, "hello", NULL, -425);
274
275 /* Test with length != 0 */
276 len = 2;
277 STR_TEST(0, "12", "12", -430);
278 STR_TEST(1, "12", "1", -435);
279 STR_TEST(-1, "1", "12", -440);
280 STR_TEST(-1, NULL, "12", -445);
281 STR_TEST(1, "12", NULL, -450);
282
283 return 0;
284
285#undef STR_TEST
286}
287
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000288int string_test(void)
289{
290 const pj_str_t hello_world = { HELLO_WORLD, strlen(HELLO_WORLD) };
291 const pj_str_t just_hello = { JUST_HELLO, strlen(JUST_HELLO) };
292 pj_str_t s1, s2, s3, s4, s5;
293 enum { RCOUNT = 10, RLEN = 16 };
294 pj_str_t random[RCOUNT];
295 pj_pool_t *pool;
296 int i;
297
298 pool = pj_pool_create(mem, NULL, 4096, 0, NULL);
299 if (!pool) return -5;
300
301 /*
302 * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(),
303 * pj_strncmp(), pj_strchr()
304 */
305 s1 = pj_str(HELLO_WORLD);
306 if (pj_strcmp(&s1, &hello_world) != 0)
307 return -10;
308 if (pj_stricmp(&s1, &hello_world) != 0)
309 return -20;
310 if (pj_strcmp(&s1, &just_hello) <= 0)
311 return -30;
312 if (pj_stricmp(&s1, &just_hello) <= 0)
313 return -40;
314 if (pj_strlen(&s1) != strlen(HELLO_WORLD))
315 return -50;
316 if (pj_strncmp(&s1, &hello_world, 5) != 0)
317 return -60;
318 if (pj_strnicmp(&s1, &hello_world, 5) != 0)
319 return -70;
320 if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
321 return -80;
322
323 /*
324 * pj_strdup()
325 */
326 if (!pj_strdup(pool, &s2, &s1))
327 return -100;
328 if (pj_strcmp(&s1, &s2) != 0)
329 return -110;
330
331 /*
332 * pj_strcpy(), pj_strcat()
333 */
Benny Prijonof260e462007-04-30 21:03:32 +0000334 s3.ptr = (char*) pj_pool_alloc(pool, 256);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000335 if (!s3.ptr)
336 return -200;
337 pj_strcpy(&s3, &s2);
338 pj_strcat(&s3, &just_hello);
339
340 if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
341 return -210;
342
343 /*
344 * pj_strdup2(), pj_strtrim().
345 */
346 pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
347 pj_strtrim(&s4);
348 if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
349 return -250;
350
351 /*
352 * pj_utoa()
353 */
Benny Prijonof260e462007-04-30 21:03:32 +0000354 s5.ptr = (char*) pj_pool_alloc(pool, 16);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000355 if (!s5.ptr)
356 return -270;
357 s5.slen = pj_utoa(UL_VALUE, s5.ptr);
358
359 /*
360 * pj_strtoul()
361 */
362 if (pj_strtoul(&s5) != UL_VALUE)
363 return -280;
364
Benny Prijonoc7434f62007-04-15 09:58:48 +0000365 /*
366 * pj_strtoul2()
367 */
368 s5 = pj_str("123456");
369
370 pj_strtoul2(&s5, NULL, 10); /* Crash test */
371
372 if (pj_strtoul2(&s5, &s4, 10) != 123456UL)
373 return -290;
374 if (s4.slen != 0)
375 return -291;
376 if (pj_strtoul2(&s5, &s4, 16) != 0x123456UL)
377 return -292;
378
379 s5 = pj_str("0123ABCD");
380 if (pj_strtoul2(&s5, &s4, 10) != 123)
381 return -293;
382 if (s4.slen != 4)
383 return -294;
384 if (s4.ptr == NULL || *s4.ptr != 'A')
385 return -295;
386 if (pj_strtoul2(&s5, &s4, 16) != 0x123ABCDUL)
387 return -296;
388 if (s4.slen != 0)
389 return -297;
390
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000391 /*
392 * pj_create_random_string()
393 * Check that no duplicate strings are returned.
394 */
395 for (i=0; i<RCOUNT; ++i) {
396 int j;
397
Benny Prijonof260e462007-04-30 21:03:32 +0000398 random[i].ptr = (char*) pj_pool_alloc(pool, RLEN);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000399 if (!random[i].ptr)
400 return -320;
401
402 random[i].slen = RLEN;
403 pj_create_random_string(random[i].ptr, RLEN);
404
405 for (j=0; j<i; ++j) {
406 if (pj_strcmp(&random[i], &random[j])==0)
407 return -330;
408 }
409 }
410
411 /* Done. */
412 pj_pool_release(pool);
Benny Prijonoa7944bb2005-11-21 17:01:50 +0000413
Benny Prijono8220f902006-01-09 17:20:59 +0000414 /* Case sensitive comparison test. */
415 i = strcmp_test();
416 if (i != 0)
417 return i;
418
419 /* Caseless comparison test. */
420 i = stricmp_test();
421 if (i != 0)
422 return i;
423
424 return 0;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000425}
426
427#else
428/* To prevent warning about "translation unit is empty"
429 * when this test is disabled.
430 */
431int dummy_string_test;
432#endif /* INCLUDE_STRING_TEST */
433