Index: pjproject/trunk/pjsip/src/test-pjsip/uri.c
===================================================================
--- pjproject/trunk/pjsip/src/test-pjsip/uri.c	(revision 64)
+++ pjproject/trunk/pjsip/src/test-pjsip/uri.c	(revision 65)
@@ -26,14 +26,19 @@
 		    "0123456789"
 #define MARK	    "-_.!~*'()"
-#define USER	    "&=+$,;?/%"
-#define PASS	    "&=+$,%"
-#define PARAM_CHAR  "[]/:&+$" MARK "%"
-
-#define POOL_SIZE	4096
-
-static pj_uint32_t parse_len, parse_time, print_time;
+#define USER_CHAR   ALPHANUM MARK "&=+$,;?/"
+#define PASS_CHAR   ALPHANUM MARK "&=+$,"
+#define PARAM_CHAR  ALPHANUM MARK "[]/:&+$"
+
+#define POOL_SIZE	4000
+#define LOOP_COUNT	1000
+#define AVERAGE_URL_LEN	80
+#define THREAD_COUNT	4
+
+static pj_uint32_t parse_len;
+static pj_timestamp parse_time, print_time;
 
 
 /* URI creator functions. */
+static pjsip_uri *create_uri0( pj_pool_t *pool );
 static pjsip_uri *create_uri1( pj_pool_t *pool );
 static pjsip_uri *create_uri2( pj_pool_t *pool );
@@ -53,6 +58,4 @@
 static pjsip_uri *create_uri16( pj_pool_t *pool );
 static pjsip_uri *create_uri17( pj_pool_t *pool );
-static pjsip_uri *create_uri18( pj_pool_t *pool );
-static pjsip_uri *create_uri19( pj_pool_t *pool );
 static pjsip_uri *create_dummy( pj_pool_t *pool );
 
@@ -71,15 +74,15 @@
 	PJ_SUCCESS,
 	"sip:localhost",
+	&create_uri0
+    },
+    {
+	PJ_SUCCESS,
+	"sip:user@localhost",
 	&create_uri1
     },
     {
 	PJ_SUCCESS,
-	"sip:user@localhost",
-	&create_uri2
-    },
-    {
-	PJ_SUCCESS,
 	"sip:user:password@localhost:5060",
-	&create_uri3,
+	&create_uri2,
     },
     {
@@ -87,11 +90,11 @@
 	ERR_NOT_EQUAL,
 	"sip:localhost:5060",
+	&create_uri3
+    },
+    {
+	/* All recognized parameters. */
+	PJ_SUCCESS,
+	"sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK",
 	&create_uri4
-    },
-    {
-	/* All recognized parameters. */
-	PJ_SUCCESS,
-	"sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK",
-	&create_uri5
     },
     {
@@ -100,5 +103,5 @@
 	"sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
 	"?Subject=Hello%20There&Server=SIP%20Server",
-	&create_uri6
+	&create_uri5
     },
     {
@@ -106,5 +109,5 @@
 	PJ_SUCCESS,
 	"sips:localhost",
-	&create_uri7,
+	&create_uri6,
     },
     {
@@ -112,5 +115,5 @@
 	PJ_SUCCESS,
 	"<sip:localhost>",
-	&create_uri8
+	&create_uri7
     },
     {
@@ -120,35 +123,35 @@
 	PJ_SUCCESS,
 	"  Power Administrator  <sips:localhost>",
+	&create_uri8
+    },
+    {
+	/* Name address. */
+	PJ_SUCCESS,
+	" \"User\" <sip:user@localhost:5071>",
 	&create_uri9
     },
     {
-	/* Name address. */
-	PJ_SUCCESS,
-	" \"User\" <sip:user@localhost:5071>",
-	&create_uri10
-    },
-    {
 	/* Escaped sequence in display name (display=Strange User\"\\\"). */
 	PJ_SUCCESS,
 	" \"Strange User\\\"\\\\\\\"\" <sip:localhost>",
+	&create_uri10,
+    },
+    {
+	/* Errorneous escaping in display name. */
+	ERR_SYNTAX_ERR,
+	" \"Rogue User\\\" <sip:localhost>",
 	&create_uri11,
     },
     {
-	/* Errorneous escaping in display name. */
-	ERR_SYNTAX_ERR,
-	" \"Rogue User\\\" <sip:localhost>",
+	/* Dangling quote in display name, but that should be OK. */
+	PJ_SUCCESS,
+	"Strange User\" <sip:localhost>",
 	&create_uri12,
     },
     {
-	/* Dangling quote in display name, but that should be OK. */
-	PJ_SUCCESS,
-	"Strange User\" <sip:localhost>",
+	/* Special characters in parameter value must be quoted. */
+	PJ_SUCCESS,
+	"sip:localhost;pvalue=\"hello world\"",
 	&create_uri13,
-    },
-    {
-	/* Special characters in parameter value must be quoted. */
-	PJ_SUCCESS,
-	"sip:localhost;pvalue=\"hello world\"",
-	&create_uri14,
     },
     {
@@ -157,13 +160,13 @@
 	 */
 	PJ_SUCCESS,
-	"This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%09a&Zz=+$,@"
+	"This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@"
 	"my_proxy09.MY-domain.com:9801>",
+	&create_uri14,
+    },
+    {
+	/* Another excercise to the allowed character sets to the hostname. */
+	PJ_SUCCESS,
+	"sip:" ALPHANUM "-_.com",
 	&create_uri15,
-    },
-    {
-	/* Another excercise to the allowed character sets to the hostname. */
-	PJ_SUCCESS,
-	"sip:" ALPHANUM "-_.com",
-	&create_uri16,
     },
     {
@@ -172,6 +175,6 @@
 	 */
 	PJ_SUCCESS,
-	"sip:" ALPHANUM USER ":" ALPHANUM PASS "@host",
-	&create_uri17,
+	"sip:" USER_CHAR ":" PASS_CHAR "@host",
+	&create_uri16,
     },
     {
@@ -180,10 +183,10 @@
 	 */
 	PJ_SUCCESS,
-	"sip:host;user=ip;" ALPHANUM PARAM_CHAR "=" ALPHANUM PARAM_CHAR 
+	"sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21"
 	";lr;other=1;transport=sctp;other2",
-	&create_uri18,
-    },
-    {
-	/* This should trigger syntax error. */
+	&create_uri17,
+    },
+    {
+	/* 18: This should trigger syntax error. */
 	ERR_SYNTAX_ERR,
 	"sip:",
@@ -191,5 +194,5 @@
     },
     {
-	/* Syntax error: whitespace after scheme. */
+	/* 19: Syntax error: whitespace after scheme. */
 	ERR_SYNTAX_ERR,
 	"sip :host",
@@ -197,5 +200,5 @@
     },
     {
-	/* Syntax error: whitespace before hostname. */
+	/* 20: Syntax error: whitespace before hostname. */
 	ERR_SYNTAX_ERR,
 	"sip: host",
@@ -203,5 +206,5 @@
     },
     {
-	/* Syntax error: invalid port. */
+	/* 21: Syntax error: invalid port. */
 	ERR_SYNTAX_ERR,
 	"sip:user:password",
@@ -209,5 +212,5 @@
     },
     {
-	/* Syntax error: no host. */
+	/* 22: Syntax error: no host. */
 	ERR_SYNTAX_ERR,
 	"sip:user@",
@@ -215,5 +218,5 @@
     },
     {
-	/* Syntax error: no user/host. */
+	/* 23: Syntax error: no user/host. */
 	ERR_SYNTAX_ERR,
 	"sip:@",
@@ -221,5 +224,5 @@
     },
     {
-	/* Syntax error: empty string. */
+	/* 24: Syntax error: empty string. */
 	ERR_SYNTAX_ERR,
 	"",
@@ -228,5 +231,5 @@
 };
 
-static pjsip_uri *create_uri1(pj_pool_t *pool)
+static pjsip_uri *create_uri0(pj_pool_t *pool)
 {
     /* "sip:localhost" */
@@ -237,5 +240,5 @@
 }
 
-static pjsip_uri *create_uri2(pj_pool_t *pool)
+static pjsip_uri *create_uri1(pj_pool_t *pool)
 {
     /* "sip:user@localhost" */
@@ -248,5 +251,5 @@
 }
 
-static pjsip_uri *create_uri3(pj_pool_t *pool)
+static pjsip_uri *create_uri2(pj_pool_t *pool)
 {
     /* "sip:user:password@localhost:5060" */
@@ -261,5 +264,5 @@
 }
 
-static pjsip_uri *create_uri4(pj_pool_t *pool)
+static pjsip_uri *create_uri3(pj_pool_t *pool)
 {
     /* Like: "sip:localhost:5060", but without the port. */
@@ -270,5 +273,5 @@
 }
 
-static pjsip_uri *create_uri5(pj_pool_t *pool)
+static pjsip_uri *create_uri4(pj_pool_t *pool)
 {
     /* "sip:localhost;transport=tcp;user=ip;ttl=255;lr;maddr=127.0.0.1;method=ACK" */
@@ -286,5 +289,14 @@
 }
 
-static pjsip_uri *create_uri6(pj_pool_t *pool)
+#define param_add(list,pname,pvalue)  \
+	do { \
+	    pjsip_param *param; \
+	    param=pj_pool_alloc(pool, sizeof(pjsip_param)); \
+	    param->name = pj_str(pname); \
+	    param->value = pj_str(pvalue); \
+	    pj_list_insert_before(&list, param); \
+	} while (0)
+
+static pjsip_uri *create_uri5(pj_pool_t *pool)
 {
     /* "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry"
@@ -295,11 +307,17 @@
     pj_strdup2(pool, &url->host, "localhost");
     pj_strdup2(pool, &url->user_param, "phone");
-    pj_strdup2(pool, &url->other_param, ";pickup=hurry;message=I%20am%20sorry");
-    pj_strdup2(pool, &url->header_param, "?Subject=Hello%20There&Server=SIP%20Server");
-    return (pjsip_uri*)url;
-
-}
-
-static pjsip_uri *create_uri7(pj_pool_t *pool)
+
+    //pj_strdup2(pool, &url->other_param, ";pickup=hurry;message=I%20am%20sorry");
+    param_add(url->other_param, "pickup", "hurry");
+    param_add(url->other_param, "message", "I am sorry");
+
+    //pj_strdup2(pool, &url->header_param, "?Subject=Hello%20There&Server=SIP%20Server");
+    param_add(url->header_param, "Subject", "Hello There");
+    param_add(url->header_param, "Server", "SIP Server");
+    return (pjsip_uri*)url;
+
+}
+
+static pjsip_uri *create_uri6(pj_pool_t *pool)
 {
     /* "sips:localhost" */
@@ -310,5 +328,5 @@
 }
 
-static pjsip_uri *create_uri8(pj_pool_t *pool)
+static pjsip_uri *create_uri7(pj_pool_t *pool)
 {
     /* "<sip:localhost>" */
@@ -323,5 +341,5 @@
 }
 
-static pjsip_uri *create_uri9(pj_pool_t *pool)
+static pjsip_uri *create_uri8(pj_pool_t *pool)
 {
     /* "  Power Administrator <sips:localhost>" */
@@ -337,5 +355,5 @@
 }
 
-static pjsip_uri *create_uri10(pj_pool_t *pool)
+static pjsip_uri *create_uri9(pj_pool_t *pool)
 {
     /* " \"User\" <sip:user@localhost:5071>" */
@@ -346,5 +364,5 @@
     name_addr->uri = (pjsip_uri*) url;
 
-    pj_strdup2(pool, &name_addr->display, "\"User\"");
+    pj_strdup2(pool, &name_addr->display, "User");
     pj_strdup2(pool, &url->user, "user");
     pj_strdup2(pool, &url->host, "localhost");
@@ -353,5 +371,5 @@
 }
 
-static pjsip_uri *create_uri11(pj_pool_t *pool)
+static pjsip_uri *create_uri10(pj_pool_t *pool)
 {
     /* " \"Strange User\\\"\\\\\\\"\" <sip:localhost>" */
@@ -362,10 +380,10 @@
     name_addr->uri = (pjsip_uri*) url;
 
-    pj_strdup2(pool, &name_addr->display, "\"Strange User\\\"\\\\\\\"\"");
+    pj_strdup2(pool, &name_addr->display, "Strange User\\\"\\\\\\\"");
     pj_strdup2(pool, &url->host, "localhost");
     return (pjsip_uri*)name_addr;
 }
 
-static pjsip_uri *create_uri12(pj_pool_t *pool)
+static pjsip_uri *create_uri11(pj_pool_t *pool)
 {
     /* " \"Rogue User\\\" <sip:localhost>" */
@@ -376,10 +394,10 @@
     name_addr->uri = (pjsip_uri*) url;
 
-    pj_strdup2(pool, &name_addr->display, "\"Rogue User\\\"");
+    pj_strdup2(pool, &name_addr->display, "Rogue User\\");
     pj_strdup2(pool, &url->host, "localhost");
     return (pjsip_uri*)name_addr;
 }
 
-static pjsip_uri *create_uri13(pj_pool_t *pool)
+static pjsip_uri *create_uri12(pj_pool_t *pool)
 {
     /* "Strange User\" <sip:localhost>" */
@@ -395,17 +413,18 @@
 }
 
+static pjsip_uri *create_uri13(pj_pool_t *pool)
+{
+    /* "sip:localhost;pvalue=\"hello world\"" */
+    pjsip_url *url;
+    url = pjsip_url_create(pool, 0);
+    pj_strdup2(pool, &url->host, "localhost");
+    //pj_strdup2(pool, &url->other_param, ";pvalue=\"hello world\"");
+    param_add(url->other_param, "pvalue", "hello world");
+    return (pjsip_uri*)url;
+}
+
 static pjsip_uri *create_uri14(pj_pool_t *pool)
 {
-    /* "sip:localhost;pvalue=\"hello world\"" */
-    pjsip_url *url;
-    url = pjsip_url_create(pool, 0);
-    pj_strdup2(pool, &url->host, "localhost");
-    pj_strdup2(pool, &url->other_param, ";pvalue=\"hello world\"");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri15(pj_pool_t *pool)
-{
-    /* "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%09a&Zz=+$,@my_proxy09.my-domain.com:9801>" */
+    /* "This is -. !% *_+`'~ me <sip:a19A&=+$,;?/%2c:%40a&Zz=+$,@my_proxy09.my-domain.com:9801>" */
     pjsip_name_addr *name_addr = pjsip_name_addr_create(pool);
     pjsip_url *url;
@@ -415,6 +434,6 @@
 
     pj_strdup2(pool, &name_addr->display, "This is -. !% *_+`'~ me");
-    pj_strdup2(pool, &url->user, "a19A&=+$,;?/%2c");
-    pj_strdup2(pool, &url->passwd, "%09a&Zz=+$,");
+    pj_strdup2(pool, &url->user, "a19A&=+$,;?/,");
+    pj_strdup2(pool, &url->passwd, "@a&Zz=+$,");
     pj_strdup2(pool, &url->host, "my_proxy09.MY-domain.com");
     url->port = 9801;
@@ -422,10 +441,21 @@
 }
 
+static pjsip_uri *create_uri15(pj_pool_t *pool)
+{
+    /* "sip:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.com" */
+    pjsip_url *url;
+    url = pjsip_url_create(pool, 0);
+    pj_strdup2(pool, &url->host, ALPHANUM "-_.com");
+    return (pjsip_uri*)url;
+}
+
 static pjsip_uri *create_uri16(pj_pool_t *pool)
 {
-    /* "sip:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.com" */
-    pjsip_url *url;
-    url = pjsip_url_create(pool, 0);
-    pj_strdup2(pool, &url->host, ALPHANUM "-_.com");
+    /* "sip:" USER_CHAR ":" PASS_CHAR "@host" */
+    pjsip_url *url;
+    url = pjsip_url_create(pool, 0);
+    pj_strdup2(pool, &url->user, USER_CHAR);
+    pj_strdup2(pool, &url->passwd, PASS_CHAR);
+    pj_strdup2(pool, &url->host, "host");
     return (pjsip_uri*)url;
 }
@@ -433,16 +463,5 @@
 static pjsip_uri *create_uri17(pj_pool_t *pool)
 {
-    /* "sip:" ALPHANUM USER ":" ALPHANUM PASS "@host" */
-    pjsip_url *url;
-    url = pjsip_url_create(pool, 0);
-    pj_strdup2(pool, &url->user, ALPHANUM USER);
-    pj_strdup2(pool, &url->passwd, ALPHANUM PASS);
-    pj_strdup2(pool, &url->host, "host");
-    return (pjsip_uri*)url;
-}
-
-static pjsip_uri *create_uri18(pj_pool_t *pool)
-{
-    /* "sip:host;user=ip;" ALPHANUM PARAM_CHAR "=" ALPHANUM PARAM_CHAR ";lr;other=1;transport=sctp;other2" */
+    /* "sip:host;user=ip;" PARAM_CHAR "%21=" PARAM_CHAR "%21;lr;other=1;transport=sctp;other2" */
     pjsip_url *url;
     url = pjsip_url_create(pool, 0);
@@ -450,5 +469,7 @@
     pj_strdup2(pool, &url->user_param, "ip");
     pj_strdup2(pool, &url->transport_param, "sctp");
-    pj_strdup2(pool, &url->other_param, ";" ALPHANUM PARAM_CHAR "=" ALPHANUM PARAM_CHAR ";other=1;other2");    
+    param_add(url->other_param, PARAM_CHAR "!", PARAM_CHAR "!");
+    param_add(url->other_param, "other", "1");
+    param_add(url->other_param, "other2", "");
     url->lr_param = 1;
     return (pjsip_uri*)url;
@@ -485,8 +506,14 @@
 	 */
 	status = entry->status==ERR_SYNTAX_ERR ? PJ_SUCCESS : -10;
+	if (status != 0) {
+	    PJ_LOG(3,("", "   uri parse error!\n"
+			  "   uri='%s'\n",
+			  entry->str));
+	}
 	goto on_return;
     }
     pj_get_timestamp(&t2);
-    parse_time += t2.u32.lo - t1.u32.lo;
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&parse_time, &t2);
 
     /* Create the reference URI. */
@@ -503,5 +530,10 @@
 	goto on_return;
     }
+    s1.ptr[len] = '\0';
     s1.slen = len;
+
+    pj_get_timestamp(&t2);
+    pj_sub_timestamp(&t2, &t1);
+    pj_add_timestamp(&print_time, &t2);
 
     len = pjsip_uri_print( PJSIP_URI_IN_OTHER, ref_uri, s2.ptr, PJSIP_MAX_URL_SIZE);
@@ -510,12 +542,18 @@
 	goto on_return;
     }
+    s2.ptr[len] = '\0';
     s2.slen = len;
-    pj_get_timestamp(&t2);
-    print_time += t2.u32.lo - t1.u32.lo;
 
     /* Full comparison of parsed URI with reference URI. */
-    if (pjsip_uri_cmp(PJSIP_URI_IN_OTHER, parsed_uri, ref_uri) != 0) {
+    status = pjsip_uri_cmp(PJSIP_URI_IN_OTHER, parsed_uri, ref_uri);
+    if (status != 0) {
 	/* Not equal. See if this is the expected status. */
 	status = entry->status==ERR_NOT_EQUAL ? PJ_SUCCESS : -40;
+	if (status != 0) {
+	    PJ_LOG(3,("", "   uri comparison mismatch, status=%d:\n"
+			  "    uri1='%s'\n"
+			  "    uri2='%s'",
+			  status, s1.ptr, s2.ptr));
+	}
 	goto on_return;
 
@@ -540,10 +578,14 @@
 pj_status_t uri_test()
 {
-    unsigned i;
+    unsigned i, loop;
     pj_pool_t *pool;
     pj_status_t status;
-
-    pool = pjsip_endpt_create_pool(endpt, "", 4000, 4000);
-
+    pj_timestamp zero;
+    pj_highprec_t avg_parse, avg_print;
+
+    zero.u32.hi = zero.u32.lo = 0;
+
+    PJ_LOG(3,("", "  simple test"));
+    pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
     for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
 	status = do_uri_test(pool, &uri_test_array[i]);
@@ -551,8 +593,42 @@
 	    PJ_LOG(3,("uri_test", "  error %d when testing entry %d",
 		      status, i));
-	    break;
+	    goto on_return;
 	}
     }
-
+    pjsip_endpt_destroy_pool(endpt, pool);
+
+    PJ_LOG(3,("", "  benchmarking..."));
+    parse_len = 0;
+    parse_time.u32.hi = parse_time.u32.lo = 0;
+    print_time.u32.hi = print_time.u32.lo = 0;
+    pool = pjsip_endpt_create_pool(endpt, "", POOL_SIZE, POOL_SIZE);
+    for (loop=0; loop<LOOP_COUNT; ++loop) {
+	for (i=0; i<PJ_ARRAY_SIZE(uri_test_array); ++i) {
+	    status = do_uri_test(pool, &uri_test_array[i]);
+	    if (status != PJ_SUCCESS) {
+		PJ_LOG(3,("uri_test", "  error %d when testing entry %d",
+			  status, i));
+		goto on_return;
+	    }
+	}
+    }
+
+    avg_parse = pj_elapsed_usec(&zero, &parse_time);
+    pj_highprec_mul(avg_parse, AVERAGE_URL_LEN);
+    pj_highprec_div(avg_parse, parse_len);
+    avg_parse = 1000000 / avg_parse;
+
+    avg_print = pj_elapsed_usec(&zero, &print_time);
+    pj_highprec_mul(avg_print, AVERAGE_URL_LEN);
+    pj_highprec_div(avg_print, parse_len);
+    avg_print = 1000000 / avg_print;
+
+    PJ_LOG(3,("", "   done. Average parse=%d url/sec, print=%d url/sec",
+		  (unsigned)avg_parse, (unsigned)avg_print));
+
+    PJ_LOG(3,("", "  multithreaded test"));
+
+
+on_return:
     pjsip_endpt_destroy_pool(endpt, pool);
     return status;
