1
/* $Id: string.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
20
#include <pj/string.h>
26
#define THIS_FILE "string.c"
29
* \page page_pjlib_string_test Test: String
31
* This file provides implementation of \b string_test(). It tests the
32
* functionality of the string API.
34
* \section sleep_test_sec Scope of the Test
53
* - pj_create_random_string()
56
* This file is <b>pjlib-test/string.c</b>
58
* \include pjlib-test/string.c
61
#if INCLUDE_STRING_TEST
64
# pragma warning(disable: 4204)
67
#define HELLO_WORLD "Hello World"
68
#define HELLO_WORLD_LEN 11
69
#define JUST_HELLO "Hello"
70
#define JUST_HELLO_LEN 5
71
#define UL_VALUE 3456789012UL
74
/* See if both integers have the same sign */
75
PJ_INLINE(int) cmp(const char *expr, int i, int j)
77
int r = !((i>0 && j>0) || (i<0 && j<0) || (i==0 && j==0));
79
PJ_LOG(3,(THIS_FILE," error: %s: expecting %d, got %d", expr, j, i));
84
/* For strict comparison, must be equal */
85
PJ_INLINE(int) cmp(const char *expr, int i, int j)
92
#define C(expr, res) cmp(#expr, expr, res)
94
static int stricmp_test(void)
96
/* This specificly tests and benchmark pj_stricmp(), pj_stricmp_alnum().
97
* In addition, it also tests pj_stricmp2(), pj_strnicmp(), and
100
#define STRTEST(res,res2,S1,S2,code) \
102
s1.ptr=S1; s1.slen=(S1)?len:0; \
103
s2.ptr=S2; s2.slen=(S2)?len:0; \
104
pj_get_timestamp(&t1); \
105
if (C(pj_stricmp(&s1,&s2),res)) return code; \
106
pj_get_timestamp(&t2); \
107
pj_sub_timestamp(&t2, &t1); \
108
pj_add_timestamp(&e1, &t2); \
109
pj_get_timestamp(&t1); \
110
if (C(pj_stricmp_alnum(&s1,&s2),res)) return code-1; \
111
pj_get_timestamp(&t2); \
112
pj_sub_timestamp(&t2, &t1); \
113
pj_add_timestamp(&e2, &t2); \
114
if (C(pj_stricmp2(&s1,S2),res2)) return code*10; \
115
if (C(pj_strnicmp(&s1,&s2,len),res)) return code*100; \
116
if (C(pj_strnicmp2(&s1,S2,len),res)) return code*1000; \
121
pj_timestamp t1, t2, e1, e2, zero;
125
e1.u32.hi = e1.u32.lo = e2.u32.hi = e2.u32.lo = 0;
131
/* Compare empty strings. */
133
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);
140
* use buffer to simulate non-aligned string.
144
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);
151
* use buffer to simulate non-aligned string.
153
buf = "aa""Aa""aA""AA";
155
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);
161
* use buffer to simulate non-aligned string.
163
buf = "aaa""Aaa""aAa""aaA""AAa""aAA""AaA""AAA";
165
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);
174
/* equal, length=4 */
176
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);
193
/* equal, length=5 */
194
buf = "aaaAa""AaaaA""AaAaA""AAAAA";
196
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);
201
/* not equal, length=1 */
203
STRTEST( -1, -1, "a", "b", -600);
205
/* not equal, length=2 */
208
STRTEST( -1, -1, "aa", buf+0, -610);
209
STRTEST( -1, -1, "aa", buf+2, -612);
211
/* not equal, length=3 */
212
buf = "aab""aba""baa";
214
STRTEST( -1, -1, "aaa", buf+0, -620);
215
STRTEST( -1, -1, "aaa", buf+3, -622);
216
STRTEST( -1, -1, "aaa", buf+6, -624);
218
/* not equal, length=4 */
219
buf = "aaab""aaba""abaa""baaa";
221
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);
226
/* not equal, length=5 */
227
buf="aaaab""aaaba""aabaa""abaaa""baaaa";
229
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);
235
zero.u32.hi = zero.u32.lo = 0;
236
c1 = pj_elapsed_cycle(&zero, &e1);
237
c2 = pj_elapsed_cycle(&zero, &e2);
240
PJ_LOG(3,("", " info: pj_stricmp_alnum is slower than pj_stricmp!"));
244
/* Avoid division by zero */
247
PJ_LOG(3, ("", " time: stricmp=%u, stricmp_alnum=%u (speedup=%d.%02dx)",
249
(c1 * 100 / c2) / 100,
250
(c1 * 100 / c2) % 100));
255
/* This tests pj_strcmp(), pj_strcmp2(), pj_strncmp(), pj_strncmp2() */
256
static int strcmp_test(void)
258
#define STR_TEST(res,S1,S2,code) \
260
s1.ptr=S1; s1.slen=S1?len:0; \
261
s2.ptr=S2; s2.slen=S2?len:0; \
262
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; \
271
/* Test with length == 0 */
273
STR_TEST(0, "", "", -400);
274
STR_TEST(0, SNULL, "", -405);
275
STR_TEST(0, "", SNULL, -410);
276
STR_TEST(0, SNULL, SNULL, -415);
277
STR_TEST(0, "hello", "", -420);
278
STR_TEST(0, "hello", SNULL, -425);
280
/* Test with length != 0 */
282
STR_TEST(0, "12", "12", -430);
283
STR_TEST(1, "12", "1", -435);
284
STR_TEST(-1, "1", "12", -440);
285
STR_TEST(-1, SNULL, "12", -445);
286
STR_TEST(1, "12", SNULL, -450);
293
int string_test(void)
295
const pj_str_t hello_world = { HELLO_WORLD, HELLO_WORLD_LEN };
296
const pj_str_t just_hello = { JUST_HELLO, JUST_HELLO_LEN };
297
pj_str_t s1, s2, s3, s4, s5;
298
enum { RCOUNT = 10, RLEN = 16 };
299
pj_str_t random[RCOUNT];
303
pool = pj_pool_create(mem, SNULL, 4096, 0, SNULL);
304
if (!pool) return -5;
307
* pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(),
308
* pj_strncmp(), pj_strchr()
310
s1 = pj_str(HELLO_WORLD);
311
if (pj_strcmp(&s1, &hello_world) != 0)
313
if (pj_stricmp(&s1, &hello_world) != 0)
315
if (pj_strcmp(&s1, &just_hello) <= 0)
317
if (pj_stricmp(&s1, &just_hello) <= 0)
319
if (pj_strlen(&s1) != strlen(HELLO_WORLD))
321
if (pj_strncmp(&s1, &hello_world, 5) != 0)
323
if (pj_strnicmp(&s1, &hello_world, 5) != 0)
325
if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
331
if (!pj_strdup(pool, &s2, &s1))
333
if (pj_strcmp(&s1, &s2) != 0)
337
* pj_strcpy(), pj_strcat()
339
s3.ptr = (char*) pj_pool_alloc(pool, 256);
343
pj_strcat(&s3, &just_hello);
345
if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
349
* pj_strdup2(), pj_strtrim().
351
pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
353
if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
359
s5.ptr = (char*) pj_pool_alloc(pool, 16);
362
s5.slen = pj_utoa(UL_VALUE, s5.ptr);
367
if (pj_strtoul(&s5) != UL_VALUE)
373
s5 = pj_str("123456");
375
pj_strtoul2(&s5, SNULL, 10); /* Crash test */
377
if (pj_strtoul2(&s5, &s4, 10) != 123456UL)
381
if (pj_strtoul2(&s5, &s4, 16) != 0x123456UL)
384
s5 = pj_str("0123ABCD");
385
if (pj_strtoul2(&s5, &s4, 10) != 123)
389
if (s4.ptr == SNULL || *s4.ptr != 'A')
391
if (pj_strtoul2(&s5, &s4, 16) != 0x123ABCDUL)
397
* pj_create_random_string()
398
* Check that no duplicate strings are returned.
400
for (i=0; i<RCOUNT; ++i) {
403
random[i].ptr = (char*) pj_pool_alloc(pool, RLEN);
407
random[i].slen = RLEN;
408
pj_create_random_string(random[i].ptr, RLEN);
410
for (j=0; j<i; ++j) {
411
if (pj_strcmp(&random[i], &random[j])==0)
417
pj_pool_release(pool);
419
/* Case sensitive comparison test. */
424
/* Caseless comparison test. */
433
/* To prevent warning about "translation unit is empty"
434
* when this test is disabled.
436
int dummy_string_test;
437
#endif /* INCLUDE_STRING_TEST */