string.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 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/assert.h>
  21. #include <pj/errno.h>
  22. #include <pj/pool.h>
  23. #include <pj/log.h>
  24. #include <pj/os.h>
  25. #include "test.h"
  26. #define THIS_FILE "string.c"
  27. /**
  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()
  51. * - pj_strtoul2()
  52. * - pj_create_random_string()
  53. * - ... and mode..
  54. *
  55. * This file is <b>pjlib-test/string.c</b>
  56. *
  57. * \include pjlib-test/string.c
  58. */
  59. #if INCLUDE_STRING_TEST
  60. #ifdef _MSC_VER
  61. # pragma warning(disable: 4204)
  62. #endif
  63. #define HELLO_WORLD "Hello World"
  64. #define HELLO_WORLD_LEN 11
  65. #define JUST_HELLO "Hello"
  66. #define JUST_HELLO_LEN 5
  67. #define UL_VALUE 3456789012UL
  68. #if 1
  69. /* See if both integers have the same sign */
  70. PJ_INLINE(int) cmp(const char *expr, int i, int j)
  71. {
  72. int r = !((i>0 && j>0) || (i<0 && j<0) || (i==0 && j==0));
  73. if (r) {
  74. PJ_LOG(3,(THIS_FILE," error: %s: expecting %d, got %d", expr, j, i));
  75. }
  76. return r;
  77. }
  78. #else
  79. /* For strict comparison, must be equal */
  80. PJ_INLINE(int) cmp(const char *expr, int i, int j)
  81. {
  82. PJ_UNUSED_ARG(expr);
  83. return i!=j;
  84. }
  85. #endif
  86. #define C(expr, res) cmp(#expr, expr, res)
  87. static int stricmp_test(void)
  88. {
  89. /* This specificly tests and benchmark pj_stricmp(), pj_stricmp_alnum().
  90. * In addition, it also tests pj_stricmp2(), pj_strnicmp(), and
  91. * pj_strnicmp2().
  92. */
  93. #define STRTEST(res,res2,S1,S2,code) \
  94. do { \
  95. s1.ptr=S1; s1.slen=(S1)?len:0; \
  96. s2.ptr=S2; s2.slen=(S2)?len:0; \
  97. pj_get_timestamp(&t1); \
  98. if (C(pj_stricmp(&s1,&s2),res)) return code; \
  99. pj_get_timestamp(&t2); \
  100. pj_sub_timestamp(&t2, &t1); \
  101. pj_add_timestamp(&e1, &t2); \
  102. pj_get_timestamp(&t1); \
  103. if (C(pj_stricmp_alnum(&s1,&s2),res)) return code-1; \
  104. pj_get_timestamp(&t2); \
  105. pj_sub_timestamp(&t2, &t1); \
  106. pj_add_timestamp(&e2, &t2); \
  107. if (C(pj_stricmp2(&s1,S2),res2)) return code*10; \
  108. if (C(pj_strnicmp(&s1,&s2,len),res)) return code*100; \
  109. if (C(pj_strnicmp2(&s1,S2,len),res)) return code*1000; \
  110. } while (0)
  111. char *buf;
  112. pj_str_t s1, s2;
  113. pj_timestamp t1, t2, e1, e2, zero;
  114. pj_uint32_t c1, c2;
  115. int len;
  116. e1.u32.hi = e1.u32.lo = e2.u32.hi = e2.u32.lo = 0;
  117. pj_thread_sleep(0);
  118. #define SNULL 0
  119. /* Compare empty strings. */
  120. len=0;
  121. STRTEST( 0, 0, "","",-500);
  122. STRTEST( 0, 0, SNULL,"",-502);
  123. STRTEST( 0, 0, "",SNULL,-504);
  124. STRTEST( 0, 0, SNULL,SNULL,-506);
  125. STRTEST( 0, -1, "hello","world",-508);
  126. /* equal, length=1
  127. * use buffer to simulate non-aligned string.
  128. */
  129. buf = "a""A";
  130. len=1;
  131. STRTEST( 0, -1, "a",buf+0,-510);
  132. STRTEST( 0, 0, "a",buf+1,-512);
  133. STRTEST(-1, -1, "O", "P", -514);
  134. STRTEST(-1, -1, SNULL, "a", -516);
  135. STRTEST( 1, 1, "a", SNULL, -518);
  136. /* equal, length=2
  137. * use buffer to simulate non-aligned string.
  138. */
  139. buf = "aa""Aa""aA""AA";
  140. len=2;
  141. STRTEST( 0, -1, "aa",buf+0,-520);
  142. STRTEST( 0, -1, "aa",buf+2,-522);
  143. STRTEST( 0, -1, "aa",buf+4,-524);
  144. STRTEST( 0, 0, "aa",buf+6,-524);
  145. /* equal, length=3
  146. * use buffer to simulate non-aligned string.
  147. */
  148. buf = "aaa""Aaa""aAa""aaA""AAa""aAA""AaA""AAA";
  149. len=3;
  150. STRTEST( 0, -1, "aaa",buf+0,-530);
  151. STRTEST( 0, -1, "aaa",buf+3,-532);
  152. STRTEST( 0, -1, "aaa",buf+6,-534);
  153. STRTEST( 0, -1, "aaa",buf+9,-536);
  154. STRTEST( 0, -1, "aaa",buf+12,-538);
  155. STRTEST( 0, -1, "aaa",buf+15,-540);
  156. STRTEST( 0, -1, "aaa",buf+18,-542);
  157. STRTEST( 0, 0, "aaa",buf+21,-534);
  158. /* equal, length=4 */
  159. len=4;
  160. STRTEST( 0, 0, "aaaa","aaaa",-540);
  161. STRTEST( 0, 0, "aaaa","Aaaa",-542);
  162. STRTEST( 0, 0, "aaaa","aAaa",-544);
  163. STRTEST( 0, 0, "aaaa","aaAa",-546);
  164. STRTEST( 0, 0, "aaaa","aaaA",-548);
  165. STRTEST( 0, 0, "aaaa","AAaa",-550);
  166. STRTEST( 0, 0, "aaaa","aAAa",-552);
  167. STRTEST( 0, 0, "aaaa","aaAA",-554);
  168. STRTEST( 0, 0, "aaaa","AaAa",-556);
  169. STRTEST( 0, 0, "aaaa","aAaA",-558);
  170. STRTEST( 0, 0, "aaaa","AaaA",-560);
  171. STRTEST( 0, 0, "aaaa","AAAa",-562);
  172. STRTEST( 0, 0, "aaaa","aAAA",-564);
  173. STRTEST( 0, 0, "aaaa","AAaA",-566);
  174. STRTEST( 0, 0, "aaaa","AaAA",-568);
  175. STRTEST( 0, 0, "aaaa","AAAA",-570);
  176. /* equal, length=5 */
  177. buf = "aaaAa""AaaaA""AaAaA""AAAAA";
  178. len=5;
  179. STRTEST( 0, -1, "aaaaa",buf+0,-580);
  180. STRTEST( 0, -1, "aaaaa",buf+5,-582);
  181. STRTEST( 0, -1, "aaaaa",buf+10,-584);
  182. STRTEST( 0, 0, "aaaaa",buf+15,-586);
  183. /* not equal, length=1 */
  184. len=1;
  185. STRTEST( -1, -1, "a", "b", -600);
  186. /* not equal, length=2 */
  187. buf = "ab""ba";
  188. len=2;
  189. STRTEST( -1, -1, "aa", buf+0, -610);
  190. STRTEST( -1, -1, "aa", buf+2, -612);
  191. /* not equal, length=3 */
  192. buf = "aab""aba""baa";
  193. len=3;
  194. STRTEST( -1, -1, "aaa", buf+0, -620);
  195. STRTEST( -1, -1, "aaa", buf+3, -622);
  196. STRTEST( -1, -1, "aaa", buf+6, -624);
  197. /* not equal, length=4 */
  198. buf = "aaab""aaba""abaa""baaa";
  199. len=4;
  200. STRTEST( -1, -1, "aaaa", buf+0, -630);
  201. STRTEST( -1, -1, "aaaa", buf+4, -632);
  202. STRTEST( -1, -1, "aaaa", buf+8, -634);
  203. STRTEST( -1, -1, "aaaa", buf+12, -636);
  204. /* not equal, length=5 */
  205. buf="aaaab""aaaba""aabaa""abaaa""baaaa";
  206. len=5;
  207. STRTEST( -1, -1, "aaaaa", buf+0, -640);
  208. STRTEST( -1, -1, "aaaaa", buf+5, -642);
  209. STRTEST( -1, -1, "aaaaa", buf+10, -644);
  210. STRTEST( -1, -1, "aaaaa", buf+15, -646);
  211. STRTEST( -1, -1, "aaaaa", buf+20, -648);
  212. zero.u32.hi = zero.u32.lo = 0;
  213. c1 = pj_elapsed_cycle(&zero, &e1);
  214. c2 = pj_elapsed_cycle(&zero, &e2);
  215. if (c1 < c2) {
  216. PJ_LOG(3,("", " info: pj_stricmp_alnum is slower than pj_stricmp!"));
  217. //return -700;
  218. }
  219. /* Avoid division by zero */
  220. if (c2 == 0) c2=1;
  221. PJ_LOG(3, ("", " time: stricmp=%u, stricmp_alnum=%u (speedup=%d.%02dx)",
  222. c1, c2,
  223. (c1 * 100 / c2) / 100,
  224. (c1 * 100 / c2) % 100));
  225. return 0;
  226. #undef STRTEST
  227. }
  228. /* This tests pj_strcmp(), pj_strcmp2(), pj_strncmp(), pj_strncmp2() */
  229. static int strcmp_test(void)
  230. {
  231. #define STR_TEST(res,S1,S2,code) \
  232. do { \
  233. s1.ptr=S1; s1.slen=S1?len:0; \
  234. s2.ptr=S2; s2.slen=S2?len:0; \
  235. if (C(pj_strcmp(&s1,&s2),res)) return code; \
  236. if (C(pj_strcmp2(&s1,S2),res)) return code-1; \
  237. if (C(pj_strncmp(&s1,&s2,len),res)) return code-2; \
  238. if (C(pj_strncmp2(&s1,S2,len),res)) return code-3; \
  239. } while (0)
  240. pj_str_t s1, s2;
  241. int len;
  242. /* Test with length == 0 */
  243. len=0;
  244. STR_TEST(0, "", "", -400);
  245. STR_TEST(0, SNULL, "", -405);
  246. STR_TEST(0, "", SNULL, -410);
  247. STR_TEST(0, SNULL, SNULL, -415);
  248. STR_TEST(0, "hello", "", -420);
  249. STR_TEST(0, "hello", SNULL, -425);
  250. /* Test with length != 0 */
  251. len = 2;
  252. STR_TEST(0, "12", "12", -430);
  253. STR_TEST(1, "12", "1", -435);
  254. STR_TEST(-1, "1", "12", -440);
  255. STR_TEST(-1, SNULL, "12", -445);
  256. STR_TEST(1, "12", SNULL, -450);
  257. return 0;
  258. #undef STR_TEST
  259. }
  260. static int verify_strxcpy(const char *src, int dst_size, int exp_ret,
  261. const char *exp_dst)
  262. {
  263. char dst[6];
  264. const char GUARDS[2] = {'@', '\0'};
  265. int i, ig, ret;
  266. PJ_ASSERT_RETURN(src && dst_size <= 5, -700);
  267. for (ig=0; ig<(int)sizeof(GUARDS); ++ig) {
  268. char GUARD = GUARDS[ig];
  269. memset(dst, GUARD, sizeof(dst));
  270. ret = pj_ansi_strxcpy(dst, src, dst_size);
  271. /* verify return value */
  272. if (ret != exp_ret) {
  273. PJ_LOG(3,("", " strxcpy \"%s\", dst_size=%d: ret %d != %d",
  274. src, dst_size, ret, exp_ret));
  275. return -704;
  276. }
  277. /* expected dst content */
  278. if (exp_dst) {
  279. if (strcmp(dst, exp_dst)) {
  280. PJ_LOG(3,("", " strxcpy \"%s\", dst_size=%d: "
  281. "dst content mismatch: \"%s\"!=\"%s\"",
  282. src, dst_size, dst, exp_dst));
  283. return -708;
  284. }
  285. }
  286. /* verify not writing pass buffer */
  287. for (i=exp_dst?strlen(exp_dst)+1:0; i<(int)sizeof(dst); ++i) {
  288. if (dst[i] != GUARD) {
  289. PJ_LOG(3,("", " strxcpy \"%s\", dst_size=%d: overflow at %d",
  290. src, dst_size, i));
  291. return -710;
  292. }
  293. }
  294. }
  295. return 0;
  296. }
  297. static int strxcpy_test(void)
  298. {
  299. int rc;
  300. #define CHECK_(src, dst_size, exp_ret, exp_dst) \
  301. rc = verify_strxcpy(src, dst_size, exp_ret, exp_dst); \
  302. if (rc) return rc
  303. CHECK_( "", 0, -PJ_ETOOBIG, NULL);
  304. CHECK_( "a", 0, -PJ_ETOOBIG, NULL);
  305. {
  306. /* special test 1 (dst contains null) */
  307. char dst[4];
  308. pj_bzero(dst, sizeof(dst));
  309. rc = pj_ansi_strxcpy(dst, "a", 1);
  310. if (rc != -PJ_ETOOBIG) {
  311. PJ_LOG(3,("", " pj_ansi_strxcpy special test 1: ret %d!=%d",
  312. rc, -PJ_ETOOBIG));
  313. return -700;
  314. }
  315. }
  316. CHECK_( "", 1, 0, "");
  317. CHECK_( "a", 1, -PJ_ETOOBIG, "");
  318. CHECK_( "ab", 1, -PJ_ETOOBIG, "");
  319. CHECK_( "abcd", 1, -PJ_ETOOBIG, "");
  320. CHECK_( "abc", 2, -PJ_ETOOBIG, "a");
  321. CHECK_( "ab", 2, -PJ_ETOOBIG, "a");
  322. CHECK_( "a", 2, 1, "a");
  323. CHECK_( "", 2, 0, "");
  324. CHECK_( "abcd", 3, -PJ_ETOOBIG, "ab");
  325. CHECK_( "abc", 3, -PJ_ETOOBIG, "ab");
  326. CHECK_( "ab", 3, 2, "ab");
  327. CHECK_( "a", 3, 1, "a");
  328. CHECK_( "", 3, 0, "");
  329. CHECK_( "abcde", 4, -PJ_ETOOBIG, "abc");
  330. CHECK_( "abcd", 4, -PJ_ETOOBIG, "abc");
  331. CHECK_( "abc", 4, 3, "abc");
  332. CHECK_( "ab", 4, 2, "ab");
  333. CHECK_( "a", 4, 1, "a");
  334. CHECK_( "", 4, 0, "");
  335. CHECK_( "abcdef", 5, -PJ_ETOOBIG, "abcd");
  336. CHECK_( "abcde", 5, -PJ_ETOOBIG, "abcd");
  337. CHECK_( "abcd", 5, 4, "abcd");
  338. CHECK_( "abc", 5, 3, "abc");
  339. CHECK_( "ab", 5, 2, "ab");
  340. CHECK_( "a", 5, 1, "a");
  341. CHECK_( "", 5, 0, "");
  342. #undef CHECK_
  343. return 0;
  344. }
  345. static int verify_strxcpy2(const pj_str_t *src, int dst_size, int exp_ret,
  346. const char *exp_dst)
  347. {
  348. char dst[6];
  349. const char GUARDS[2] = {'@', '\0'};
  350. int i, ret, ig;
  351. PJ_ASSERT_RETURN(src && dst_size <= 5, -720);
  352. for (ig=0; ig<(int)sizeof(GUARDS); ++ig) {
  353. char GUARD = GUARDS[ig];
  354. memset(dst, GUARD, sizeof(dst));
  355. ret = pj_ansi_strxcpy2(dst, src, dst_size);
  356. /* verify return value */
  357. if (ret != exp_ret) {
  358. PJ_LOG(3,("", " strxcpy2 \"%.*s\" slen=%ld, dst_size=%d: "
  359. "ret %d!=%d",
  360. (int)src->slen, src->ptr, src->slen, dst_size,
  361. ret, exp_ret));
  362. return -724;
  363. }
  364. /* expected dst content */
  365. if (exp_dst) {
  366. if (strcmp(dst, exp_dst)) {
  367. PJ_LOG(3,("", " strxcpy2 \"%.*s\" slen=%ld, dst_size=%d: "
  368. "dst content mismatch: \"%s\"!=\"%s\"",
  369. (int)src->slen, src->ptr, src->slen, dst_size, dst,
  370. exp_dst));
  371. return -726;
  372. }
  373. }
  374. /* verify not writing pass buffer */
  375. for (i=dst_size; i<(int)sizeof(dst); ++i) {
  376. if (dst[i] != GUARD) {
  377. PJ_LOG(3,("", " strxcpy2 \"%.*s\" slen=%ld, dst_size=%d: "
  378. "overflow at %d (chr %d)",
  379. (int)src->slen, src->ptr, src->slen, dst_size, i,
  380. (char)(dst[i] & 0xFF)));
  381. return -728;
  382. }
  383. }
  384. }
  385. return 0;
  386. }
  387. static int strxcpy2_test(void)
  388. {
  389. pj_str_t src;
  390. char nulls[6];
  391. int rc;
  392. pj_bzero(nulls, sizeof(nulls));
  393. #define CHECK2_(s, src_len, dst_size, exp_ret, exp_dst) \
  394. src.ptr = s; src.slen = src_len; \
  395. rc = verify_strxcpy2(&src, dst_size, exp_ret, exp_dst); \
  396. if (rc) return rc
  397. CHECK2_( NULL, 0, 0, -PJ_ETOOBIG, NULL);
  398. CHECK2_( "a!", 1, 0, -PJ_ETOOBIG, NULL);
  399. CHECK2_( "abc!", 3, 1, -PJ_ETOOBIG, "");
  400. CHECK2_( "ab!", 2, 1, -PJ_ETOOBIG, "");
  401. /* note for test below: although src contains null and the strlen
  402. of result (i.e. dst) is zero, strxcpy2 would still return
  403. -PJ_ETOOBIG because the required buffer size is assumed to
  404. be 2 (one for the src->ptr content (although the content is a
  405. null character), one for the null terminator)
  406. */
  407. CHECK2_( nulls, 1, 1, 0, "");
  408. CHECK2_( "a!", 1, 1, -PJ_ETOOBIG, "");
  409. CHECK2_( "a", 1, 1, -PJ_ETOOBIG, "");
  410. CHECK2_( "", 0, 1, 0, "");
  411. CHECK2_( NULL, 0, 1, 0, "");
  412. CHECK2_( "abc", 3, 2, -PJ_ETOOBIG, "a");
  413. CHECK2_( "ab", 2, 2, -PJ_ETOOBIG, "a");
  414. CHECK2_( "a!", 1, 2, 1, "a");
  415. CHECK2_( nulls, 1, 2, 0, "");
  416. CHECK2_( "!", 0, 2, 0, "");
  417. CHECK2_( NULL, 0, 2, 0, "");
  418. CHECK2_( "abc", 3, 3, -PJ_ETOOBIG, "ab");
  419. CHECK2_( "ab", 3, 3, 2, "ab");
  420. CHECK2_( nulls, 3, 3, 0, "");
  421. CHECK2_( "abc", 2, 3, 2, "ab");
  422. CHECK2_( "ab", 2, 3, 2, "ab");
  423. CHECK2_( "a", 2, 3, 1, "a");
  424. CHECK2_( nulls, 2, 3, 0, "");
  425. CHECK2_( "a", 1, 3, 1, "a");
  426. CHECK2_( "", 1, 3, 0, "");
  427. CHECK2_( "", 0, 3, 0, "");
  428. CHECK2_( NULL, 0, 3, 0, "");
  429. CHECK2_( "abcde",5, 4, -PJ_ETOOBIG, "abc");
  430. CHECK2_( "abcd", 4, 4, -PJ_ETOOBIG, "abc");
  431. CHECK2_( "abc", 4, 4, 3, "abc");
  432. CHECK2_( "ab", 4, 4, 2, "ab");
  433. CHECK2_( "a", 4, 4, 1, "a");
  434. CHECK2_( nulls, 4, 4, 0, "");
  435. CHECK2_( "abc", 3, 4, 3, "abc");
  436. CHECK2_( "ab", 3, 4, 2, "ab");
  437. CHECK2_( "ab", 2, 4, 2, "ab");
  438. CHECK2_( "a", 2, 4, 1, "a");
  439. CHECK2_( "", 2, 4, 0, "");
  440. CHECK2_( nulls, 2, 4, 0, "");
  441. CHECK2_( "a", 1, 4, 1, "a");
  442. CHECK2_( nulls, 1, 4, 0, "");
  443. CHECK2_( "a", 0, 4, 0, "");
  444. CHECK2_( "", 0, 4, 0, "");
  445. CHECK2_( NULL, 0, 4, 0, "");
  446. #undef CHECK2_
  447. return 0;
  448. }
  449. static int verify_strxcat(const char *cdst, const char *src, int dst_size,
  450. int exp_ret, const char *exp_dst)
  451. {
  452. char dst[6];
  453. const char GUARDS[2] = {'@', '\0'};
  454. int i, ret, ig;
  455. PJ_ASSERT_RETURN(src && strlen(cdst) <= 4, -730);
  456. PJ_ASSERT_RETURN((int)strlen(cdst) < dst_size ||
  457. (strlen(cdst)==0 && dst_size==0), -731);
  458. for (ig=0; ig<(int)sizeof(GUARDS); ++ig) {
  459. char GUARD = GUARDS[ig];
  460. memset(dst, GUARD, sizeof(dst));
  461. if (dst_size) {
  462. ret = pj_ansi_strxcpy(dst, cdst, dst_size);
  463. PJ_ASSERT_RETURN(ret==(int)strlen(cdst), -732);
  464. }
  465. ret = pj_ansi_strxcat(dst, src, dst_size);
  466. /* verify return value */
  467. if (ret != exp_ret) {
  468. PJ_LOG(3,("", " strxcat \"%s\", \"%s\", dst_size=%d: ret %d!=%d",
  469. cdst, src, dst_size, ret, exp_ret));
  470. return -734;
  471. }
  472. /* expected dst content */
  473. if (exp_dst) {
  474. if (strcmp(dst, exp_dst)) {
  475. PJ_LOG(3,("", " strxcat \"%s\", \"%s\", dst_size=%d: "
  476. "dst content mismatch: \"%s\"!=\"%s\"",
  477. cdst, src, dst_size, dst, exp_dst));
  478. return -736;
  479. }
  480. }
  481. /* verify not writing past buffer */
  482. for (i=exp_dst?strlen(exp_dst)+1:0; i<(int)sizeof(dst); ++i) {
  483. if (dst[i] != GUARD) {
  484. PJ_LOG(3,("", " strxcat \"%s\", \"%s\", dst_size=%d: "
  485. "overflow at %d",
  486. cdst, src, dst_size, i));
  487. return -738;
  488. }
  489. }
  490. }
  491. return 0;
  492. }
  493. static int strxcat_test(void)
  494. {
  495. int rc;
  496. #define CHECK3_(dst, src, dst_size, exp_ret, exp_dst) \
  497. rc = verify_strxcat(dst, src, dst_size, exp_ret, exp_dst); \
  498. if (rc) return rc
  499. CHECK3_( "", "", 0, -PJ_ETOOBIG, NULL);
  500. CHECK3_( "", "a", 0, -PJ_ETOOBIG, NULL);
  501. CHECK3_( "", "", 1, 0, "");
  502. CHECK3_( "", "a", 1, -PJ_ETOOBIG, "");
  503. CHECK3_( "", "a", 2, 1, "a");
  504. CHECK3_( "", "ab", 2, -PJ_ETOOBIG, "a");
  505. CHECK3_( "0", "", 2, 1, "0");
  506. CHECK3_( "0", "a", 2, -PJ_ETOOBIG, "0");
  507. CHECK3_( "", "a", 3, 1, "a");
  508. CHECK3_( "", "ab", 3, 2, "ab");
  509. CHECK3_( "", "abc", 3, -PJ_ETOOBIG, "ab");
  510. CHECK3_( "0", "", 3, 1, "0");
  511. CHECK3_( "0", "a", 3, 2, "0a");
  512. CHECK3_( "0", "ab", 3, -PJ_ETOOBIG, "0a");
  513. CHECK3_( "01", "", 3, 2, "01");
  514. CHECK3_( "01", "a", 3, -PJ_ETOOBIG, "01");
  515. CHECK3_( "01", "ab", 3, -PJ_ETOOBIG, "01");
  516. CHECK3_( "", "a", 4, 1, "a");
  517. CHECK3_( "", "ab", 4, 2, "ab");
  518. CHECK3_( "", "abc", 4, 3, "abc");
  519. CHECK3_( "", "abcd", 4, -PJ_ETOOBIG, "abc");
  520. CHECK3_( "0", "", 4, 1, "0");
  521. CHECK3_( "0", "a", 4, 2, "0a");
  522. CHECK3_( "0", "ab", 4, 3, "0ab");
  523. CHECK3_( "0", "abc", 4, -PJ_ETOOBIG, "0ab");
  524. CHECK3_( "01", "", 4, 2, "01");
  525. CHECK3_( "01", "a", 4, 3, "01a");
  526. CHECK3_( "01", "ab", 4, -PJ_ETOOBIG, "01a");
  527. CHECK3_( "01", "abc", 4, -PJ_ETOOBIG, "01a");
  528. CHECK3_( "012", "", 4, 3, "012");
  529. CHECK3_( "012", "a", 4, -PJ_ETOOBIG, "012");
  530. CHECK3_( "012", "ab", 4, -PJ_ETOOBIG, "012");
  531. CHECK3_( "012", "abc",4, -PJ_ETOOBIG, "012");
  532. #undef CHECK3_
  533. return 0;
  534. }
  535. int string_test(void)
  536. {
  537. const pj_str_t hello_world = { HELLO_WORLD, HELLO_WORLD_LEN };
  538. const pj_str_t just_hello = { JUST_HELLO, JUST_HELLO_LEN };
  539. pj_str_t s1, s2, s3, s4, s5;
  540. enum { RCOUNT = 10, RLEN = 16 };
  541. pj_str_t random[RCOUNT];
  542. pj_pool_t *pool;
  543. int i;
  544. pool = pj_pool_create(mem, SNULL, 4096, 0, SNULL);
  545. if (!pool) return -5;
  546. /*
  547. * pj_str(), pj_strcmp(), pj_stricmp(), pj_strlen(),
  548. * pj_strncmp(), pj_strchr()
  549. */
  550. s1 = pj_str(HELLO_WORLD);
  551. if (pj_strcmp(&s1, &hello_world) != 0)
  552. return -10;
  553. if (pj_stricmp(&s1, &hello_world) != 0)
  554. return -20;
  555. if (pj_strcmp(&s1, &just_hello) <= 0)
  556. return -30;
  557. if (pj_stricmp(&s1, &just_hello) <= 0)
  558. return -40;
  559. if (pj_strlen(&s1) != strlen(HELLO_WORLD))
  560. return -50;
  561. if (pj_strncmp(&s1, &hello_world, 5) != 0)
  562. return -60;
  563. if (pj_strnicmp(&s1, &hello_world, 5) != 0)
  564. return -70;
  565. if (pj_strchr(&s1, HELLO_WORLD[1]) != s1.ptr+1)
  566. return -80;
  567. /*
  568. * pj_strdup()
  569. */
  570. if (!pj_strdup(pool, &s2, &s1))
  571. return -100;
  572. if (pj_strcmp(&s1, &s2) != 0)
  573. return -110;
  574. /*
  575. * pj_strcpy(), pj_strcat()
  576. */
  577. s3.ptr = (char*) pj_pool_alloc(pool, 256);
  578. if (!s3.ptr)
  579. return -200;
  580. pj_strcpy(&s3, &s2);
  581. pj_strcat(&s3, &just_hello);
  582. if (pj_strcmp2(&s3, HELLO_WORLD JUST_HELLO) != 0)
  583. return -210;
  584. /*
  585. * pj_strdup2(), pj_strtrim().
  586. */
  587. pj_strdup2(pool, &s4, " " HELLO_WORLD "\t ");
  588. pj_strtrim(&s4);
  589. if (pj_strcmp2(&s4, HELLO_WORLD) != 0)
  590. return -250;
  591. /*
  592. * pj_utoa()
  593. */
  594. s5.ptr = (char*) pj_pool_alloc(pool, 16);
  595. if (!s5.ptr)
  596. return -270;
  597. s5.slen = pj_utoa(UL_VALUE, s5.ptr);
  598. /*
  599. * pj_strtoul()
  600. */
  601. if (pj_strtoul(&s5) != UL_VALUE)
  602. return -280;
  603. /*
  604. * pj_strtoul2()
  605. */
  606. s5 = pj_str("123456");
  607. pj_strtoul2(&s5, SNULL, 10); /* Crash test */
  608. if (pj_strtoul2(&s5, &s4, 10) != 123456UL)
  609. return -290;
  610. if (s4.slen != 0)
  611. return -291;
  612. if (pj_strtoul2(&s5, &s4, 16) != 0x123456UL)
  613. return -292;
  614. s5 = pj_str("0123ABCD");
  615. if (pj_strtoul2(&s5, &s4, 10) != 123)
  616. return -293;
  617. if (s4.slen != 4)
  618. return -294;
  619. if (s4.ptr == SNULL || *s4.ptr != 'A')
  620. return -295;
  621. if (pj_strtoul2(&s5, &s4, 16) != 0x123ABCDUL)
  622. return -296;
  623. if (s4.slen != 0)
  624. return -297;
  625. /*
  626. * pj_create_random_string()
  627. * Check that no duplicate strings are returned.
  628. */
  629. for (i=0; i<RCOUNT; ++i) {
  630. int j;
  631. random[i].ptr = (char*) pj_pool_alloc(pool, RLEN);
  632. if (!random[i].ptr)
  633. return -320;
  634. random[i].slen = RLEN;
  635. pj_create_random_string(random[i].ptr, RLEN);
  636. for (j=0; j<i; ++j) {
  637. if (pj_strcmp(&random[i], &random[j])==0)
  638. return -330;
  639. }
  640. }
  641. /* Done. */
  642. pj_pool_release(pool);
  643. /* Case sensitive comparison test. */
  644. i = strcmp_test();
  645. if (i != 0)
  646. return i;
  647. /* Caseless comparison test. */
  648. i = stricmp_test();
  649. if (i != 0)
  650. return i;
  651. /* strxcpy test */
  652. i = strxcpy_test();
  653. if (i != 0)
  654. return i;
  655. /* strxcpy2 test */
  656. i = strxcpy2_test();
  657. if (i != 0)
  658. return i;
  659. /* strxcat test */
  660. i = strxcat_test();
  661. if (i != 0)
  662. return i;
  663. return 0;
  664. }
  665. #else
  666. /* To prevent warning about "translation unit is empty"
  667. * when this test is disabled.
  668. */
  669. int dummy_string_test;
  670. #endif /* INCLUDE_STRING_TEST */