diff options
Diffstat (limited to 'pjsip/src/test-pjsip')
-rw-r--r-- | pjsip/src/test-pjsip/main.c | 46 | ||||
-rw-r--r-- | pjsip/src/test-pjsip/test.c | 3 | ||||
-rw-r--r-- | pjsip/src/test-pjsip/test.h | 3 | ||||
-rw-r--r-- | pjsip/src/test-pjsip/tsx_uac_test.c | 476 |
4 files changed, 506 insertions, 22 deletions
diff --git a/pjsip/src/test-pjsip/main.c b/pjsip/src/test-pjsip/main.c index 3c5f0800..7994504d 100644 --- a/pjsip/src/test-pjsip/main.c +++ b/pjsip/src/test-pjsip/main.c @@ -18,10 +18,54 @@ */ #include "test.h" #include <stdio.h> +#include <string.h> +#include <stdlib.h> + +static void usage() +{ + puts("Usage: test-pjsip"); + puts("Options:"); + puts(" -i,--interractive Key input at the end."); + puts(" -h,--help Show this screen"); + puts(" -l,--log-level N Set log level (0-6)"); +} int main(int argc, char *argv[]) { - int retval = test_main(); + int interractive = 0; + int retval; + char **opt_arg; + + /* Parse arguments. */ + opt_arg = argv+1; + while (*opt_arg) { + if (strcmp(*opt_arg, "-i") == 0 || + strcmp(*opt_arg, "--interractive") == 0) + { + interractive = 1; + } else if (strcmp(*opt_arg, "-h") == 0 || + strcmp(*opt_arg, "--help") == 0) + { + usage(); + return 1; + } else if (strcmp(*opt_arg, "-l") == 0 || + strcmp(*opt_arg, "--log-level") == 0) + { + ++opt_arg; + if (!opt_arg) { + usage(); + return 1; + } + log_level = atoi(*opt_arg); + } else { + usage(); + return 1; + } + + ++opt_arg; + } + + retval = test_main(); if (argc != 1) { char s[10]; diff --git a/pjsip/src/test-pjsip/test.c b/pjsip/src/test-pjsip/test.c index fdc6a7d8..4294225c 100644 --- a/pjsip/src/test-pjsip/test.c +++ b/pjsip/src/test-pjsip/test.c @@ -36,6 +36,7 @@ pjsip_endpoint *endpt; +int log_level = 5; void app_perror(const char *msg, pj_status_t rc) { @@ -81,7 +82,7 @@ int test_main(void) const char *filename; int line; - pj_log_set_level(5); + pj_log_set_level(log_level); /* pj_log_set_decor(PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC); diff --git a/pjsip/src/test-pjsip/test.h b/pjsip/src/test-pjsip/test.h index 2012781c..3356d537 100644 --- a/pjsip/src/test-pjsip/test.h +++ b/pjsip/src/test-pjsip/test.h @@ -54,4 +54,7 @@ int init_msg_logger(void); int msg_logger_set_enabled(pj_bool_t enabled); void flush_events(unsigned duration); +/* Settings. */ +extern int log_level; + #endif /* __TEST_H__ */ diff --git a/pjsip/src/test-pjsip/tsx_uac_test.c b/pjsip/src/test-pjsip/tsx_uac_test.c index cf40e5d5..19bc063f 100644 --- a/pjsip/src/test-pjsip/tsx_uac_test.c +++ b/pjsip/src/test-pjsip/tsx_uac_test.c @@ -145,6 +145,9 @@ static pj_bool_t test_complete; /* Loop transport instance. */ static pjsip_transport *loop; +/* General timer entry to be used by tests. */ +static pj_timer_entry timer; + /* * This is the handler to receive state changed notification from the * transaction. It is used to verify that the transaction behaves according @@ -303,10 +306,226 @@ static void tsx_user_on_tsx_state(pjsip_transaction *tsx, pjsip_event *e) test_complete = 1; pjsip_tsx_terminate(tsx, 202); } + + } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { + + /* Previous state must be COMPLETED. */ + if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { + test_complete = -7381; + } + + } + + } else if (pj_strcmp2(&tsx->branch, TEST7_BRANCH_ID)==0) { + /* + * Successfull non-INVITE transaction. + */ + if (tsx->state == PJSIP_TSX_STATE_COMPLETED) { + + /* Check prev state. */ + if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) { + PJ_LOG(3,(THIS_FILE, + " error: prev state is %s instead of %s", + pjsip_tsx_state_str(e->body.tsx_state.prev_state), + pjsip_tsx_state_str(PJSIP_TSX_STATE_PROCEEDING))); + test_complete = -739; + } + + /* Status code must be 202. */ + if (tsx->status_code != 202) { + PJ_LOG(3,(THIS_FILE, + " error: status code is %d instead of %d", + tsx->status_code, 202)); + test_complete = -740; + } + + /* Must have correct retransmission count. */ + if (tsx->retransmit_count != 0) { + PJ_LOG(3,(THIS_FILE, + " error: retransmit cnt is %d instead of %d", + tsx->retransmit_count, 0)); + test_complete = -741; + } + + /* Must still keep last_tx */ + if (tsx->last_tx == NULL) { + PJ_LOG(3,(THIS_FILE, + " error: transaction lost last_tx")); + test_complete = -741; + } + + if (test_complete == 0) { + test_complete = 1; + pjsip_tsx_terminate(tsx, 202); + } + + } else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { + + /* Previous state must be COMPLETED. */ + if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { + test_complete = -742; + } + + } + + + } else if (pj_strcmp2(&tsx->branch, TEST8_BRANCH_ID)==0) { + /* + * Failed INVITE transaction. + */ + if (tsx->state == PJSIP_TSX_STATE_COMPLETED) { + + /* Status code must be 301. */ + if (tsx->status_code != 301) { + PJ_LOG(3,(THIS_FILE, + " error: status code is %d instead of %d", + tsx->status_code, 301)); + test_complete = -745; + } + + /* Must have correct retransmission count. */ + if (tsx->retransmit_count != 0) { + PJ_LOG(3,(THIS_FILE, + " error: retransmit cnt is %d instead of %d", + tsx->retransmit_count, 0)); + test_complete = -746; + } + + /* Must still keep last_tx */ + if (tsx->last_tx == NULL) { + PJ_LOG(3,(THIS_FILE, + " error: transaction lost last_tx")); + test_complete = -747; + } + + /* last_tx is ACK in this case. */ + if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id != + PJSIP_ACK_METHOD) + { + PJ_LOG(3,(THIS_FILE, + " error: last_tx is not ACK")); + test_complete = -748; + } + } + else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { + + test_complete = 1; + + /* Previous state must be COMPLETED. */ + if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { + test_complete = -750; + } + + /* Status code must be 301. */ + if (tsx->status_code != 301) { + PJ_LOG(3,(THIS_FILE, + " error: status code is %d instead of %d", + tsx->status_code, 301)); + test_complete = -751; + } + + } + + + } else if (pj_strcmp2(&tsx->branch, TEST9_BRANCH_ID)==0) { + /* + * Failed INVITE transaction with provisional response. + */ + if (tsx->state == PJSIP_TSX_STATE_COMPLETED) { + + /* Previous state must be PJSIP_TSX_STATE_PROCEEDING. */ + if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) { + test_complete = -760; + } + + /* Status code must be 302. */ + if (tsx->status_code != 302) { + PJ_LOG(3,(THIS_FILE, + " error: status code is %d instead of %d", + tsx->status_code, 302)); + test_complete = -761; + } + + /* Must have correct retransmission count. */ + if (tsx->retransmit_count != 0) { + PJ_LOG(3,(THIS_FILE, + " error: retransmit cnt is %d instead of %d", + tsx->retransmit_count, 0)); + test_complete = -762; + } + + /* Must still keep last_tx */ + if (tsx->last_tx == NULL) { + PJ_LOG(3,(THIS_FILE, + " error: transaction lost last_tx")); + test_complete = -763; + } + + /* last_tx is ACK in this case. */ + if (tsx->last_tx && tsx->last_tx->msg->line.req.method.id != + PJSIP_ACK_METHOD) + { + PJ_LOG(3,(THIS_FILE, + " error: last_tx is not ACK")); + test_complete = -764; + } + + } + else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { + + test_complete = 1; + + /* Previous state must be COMPLETED. */ + if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { + test_complete = -767; + } + + /* Status code must be 302. */ + if (tsx->status_code != 302) { + PJ_LOG(3,(THIS_FILE, + " error: status code is %d instead of %d", + tsx->status_code, 302)); + test_complete = -768; + } + } + + } +} + +/* + * This timer callback is called to send delayed response. + */ +struct response +{ + pjsip_response_addr res_addr; + pjsip_tx_data *tdata; +}; + +static void send_response_callback( pj_timer_heap_t *timer_heap, + struct pj_timer_entry *entry) +{ + struct response *r = entry->user_data; + pjsip_transport *tp = r->res_addr.transport; + + pjsip_endpt_send_response(endpt, &r->res_addr, r->tdata, NULL, NULL); + if (tp) + pjsip_transport_dec_ref(tp); +} + +/* Timer callback to terminate a transaction. */ +static void terminate_tsx_callback( pj_timer_heap_t *timer_heap, + struct pj_timer_entry *entry) +{ + pjsip_transaction *tsx = entry->user_data; + int status_code = entry->id; + + if (tsx) { + pjsip_tsx_terminate(tsx, status_code); } } + #define DIFF(a,b) ((a<b) ? (b-a) : (a-b)) /* @@ -438,10 +657,8 @@ static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata) } else if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST6_BRANCH_ID) == 0) { /* - * The TEST5_BRANCH_ID test successfull non-INVITE transaction. + * The TEST6_BRANCH_ID test successfull non-INVITE transaction. */ - pjsip_tx_data *tdata; - pjsip_response_addr res_addr; pj_status_t status; recv_count++; @@ -452,26 +669,221 @@ static pj_bool_t msg_receiver_on_rx_request(pjsip_rx_data *rdata) test_complete = -635; } - status = pjsip_endpt_create_response(endpt, rdata, 202, NULL, &tdata); + status = pjsip_endpt_respond_stateless(endpt, rdata, 202, NULL, + NULL, NULL); if (status != PJ_SUCCESS) { - app_perror(" error: unable to create response", status); + app_perror(" error: unable to send response", status); test_complete = -636; } + return PJ_TRUE; + + + } else + if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST7_BRANCH_ID) == 0) { + /* + * The TEST7_BRANCH_ID test successfull non-INVITE transaction + * with provisional response. + */ + pj_status_t status; + pjsip_response_addr res_addr; + struct response *r; + pjsip_tx_data *tdata; + pj_time_val delay = { 2, 0 }; + + recv_count++; + + if (recv_count > 1) { + PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!", + recv_count)); + test_complete = -640; + return PJ_TRUE; + } + + /* Respond with provisional response */ + status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, &tdata); + pj_assert(status == PJ_SUCCESS); + status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr); - if (status != PJ_SUCCESS) { - app_perror(" error: unable to get response addr", status); - test_complete = -637; + pj_assert(status == PJ_SUCCESS); + + status = pjsip_endpt_send_response(endpt, &res_addr, tdata, + NULL, NULL); + pj_assert(status == PJ_SUCCESS); + + /* Create the final response. */ + status = pjsip_endpt_create_response(endpt, rdata, 202, NULL, &tdata); + pj_assert(status == PJ_SUCCESS); + + /* Schedule sending final response in couple of of secs. */ + r = pj_pool_alloc(tdata->pool, sizeof(*r)); + r->res_addr = res_addr; + r->tdata = tdata; + if (r->res_addr.transport) + pjsip_transport_add_ref(r->res_addr.transport); + + timer.cb = &send_response_callback; + timer.user_data = r; + pjsip_endpt_schedule_timer(endpt, &timer, &delay); + + return PJ_TRUE; + + + } else + if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST8_BRANCH_ID) == 0) { + /* + * The TEST8_BRANCH_ID test failed INVITE transaction. + */ + pjsip_method *method; + pj_status_t status; + + method = &rdata->msg_info.msg->line.req.method; + + recv_count++; + + if (method->id == PJSIP_INVITE_METHOD) { + + if (recv_count > 1) { + PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!", + recv_count)); + test_complete = -635; + } + + status = pjsip_endpt_respond_stateless(endpt, rdata, 301, NULL, + NULL, NULL); + if (status != PJ_SUCCESS) { + app_perror(" error: unable to send response", status); + test_complete = -636; + } + + } else if (method->id == PJSIP_ACK_METHOD) { + + if (recv_count == 2) { + pj_str_t key; + pj_time_val delay = { 5, 0 }; + + /* Schedule timer to destroy transaction after 5 seconds. + * This is to make sure that transaction does not + * retransmit ACK. + */ + pjsip_tsx_create_key(rdata->tp_info.pool, &key, + PJSIP_ROLE_UAC, &pjsip_invite_method, + rdata); + + timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE); + timer.id = 301; + timer.cb = &terminate_tsx_callback; + + pjsip_endpt_schedule_timer(endpt, &timer, &delay); + } + + if (recv_count > 2) { + PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!", + recv_count)); + test_complete = -638; + } + + + } else { + PJ_LOG(3,(THIS_FILE," error: not expecting %s", + pjsip_rx_data_get_info(rdata))); + test_complete = -639; + } - status = pjsip_endpt_send_response(endpt, &res_addr, tdata, NULL,NULL); - if (status != PJ_SUCCESS) { - app_perror(" error: unable to send response", status); - test_complete = -638; - pjsip_tx_data_dec_ref(tdata); + + } else + if (pj_strcmp2(&rdata->msg_info.via->branch_param, TEST9_BRANCH_ID) == 0) { + /* + * The TEST9_BRANCH_ID test failed INVITE transaction with + * provisional response. + */ + pjsip_method *method; + pj_status_t status; + + method = &rdata->msg_info.msg->line.req.method; + + recv_count++; + + if (method->id == PJSIP_INVITE_METHOD) { + + pjsip_response_addr res_addr; + struct response *r; + pjsip_tx_data *tdata; + pj_time_val delay = { 2, 0 }; + + if (recv_count > 1) { + PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!", + recv_count)); + test_complete = -650; + return PJ_TRUE; + } + + /* Respond with provisional response */ + status = pjsip_endpt_create_response(endpt, rdata, 100, NULL, + &tdata); + pj_assert(status == PJ_SUCCESS); + + status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr); + pj_assert(status == PJ_SUCCESS); + + status = pjsip_endpt_send_response(endpt, &res_addr, tdata, + NULL, NULL); + pj_assert(status == PJ_SUCCESS); + + /* Create the final response. */ + status = pjsip_endpt_create_response(endpt, rdata, 302, NULL, + &tdata); + pj_assert(status == PJ_SUCCESS); + + /* Schedule sending final response in couple of of secs. */ + r = pj_pool_alloc(tdata->pool, sizeof(*r)); + r->res_addr = res_addr; + r->tdata = tdata; + if (r->res_addr.transport) + pjsip_transport_add_ref(r->res_addr.transport); + + timer.cb = &send_response_callback; + timer.user_data = r; + pjsip_endpt_schedule_timer(endpt, &timer, &delay); + + } else if (method->id == PJSIP_ACK_METHOD) { + + if (recv_count == 2) { + pj_str_t key; + pj_time_val delay = { 5, 0 }; + + /* Schedule timer to destroy transaction after 5 seconds. + * This is to make sure that transaction does not + * retransmit ACK. + */ + pjsip_tsx_create_key(rdata->tp_info.pool, &key, + PJSIP_ROLE_UAC, &pjsip_invite_method, + rdata); + + timer.user_data = pjsip_tsx_layer_find_tsx(&key, PJ_FALSE); + timer.id = 302; + timer.cb = &terminate_tsx_callback; + + pjsip_endpt_schedule_timer(endpt, &timer, &delay); + } + + if (recv_count > 2) { + PJ_LOG(3,(THIS_FILE," error: not expecting %d-th packet!", + recv_count)); + test_complete = -638; + } + + + } else { + PJ_LOG(3,(THIS_FILE," error: not expecting %s", + pjsip_rx_data_get_info(rdata))); + test_complete = -639; + } return PJ_TRUE; + } return PJ_FALSE; @@ -826,15 +1238,20 @@ static int tsx_terminate_after_retransmit_test(void) /***************************************************************************** ** ** TEST6_BRANCH_ID: Successfull non-invite transaction + ** TEST7_BRANCH_ID: Successfull non-invite transaction with provisional + ** TEST8_BRANCH_ID: Failed invite transaction + ** TEST9_BRANCH_ID: Failed invite transaction with provisional ** ***************************************************************************** */ -static int tsx_successfull_non_invite_test(void) +static int perform_generic_test( const char *title, + char *branch_id, + const pjsip_method *method) { int i, status; unsigned delay[] = { 1, 200 }; - PJ_LOG(3,(THIS_FILE, " test6: successfull non-invite transaction")); + PJ_LOG(3,(THIS_FILE, " test6: %s", title)); /* Do the test. */ for (i=0; i<PJ_ARRAY_SIZE(delay); ++i) { @@ -847,8 +1264,8 @@ static int tsx_successfull_non_invite_test(void) status = perform_tsx_test(-1200, "sip:bob@127.0.0.1;transport=loop-dgram", "sip:alice@127.0.0.1;transport=loop-dgram", - TEST6_BRANCH_ID, - 2, &pjsip_options_method); + branch_id, + 10, method); if (status != 0) return status; } @@ -891,7 +1308,6 @@ int tsx_uac_test(void) return -40; } -#if 0 /* TEST1_BRANCH_ID: Basic retransmit and timeout test. */ status = tsx_uac_retransmit_test(); if (status != 0) @@ -916,10 +1332,30 @@ int tsx_uac_test(void) status = tsx_terminate_after_retransmit_test(); if (status != 0) return status; -#endif /* TEST6_BRANCH_ID: Successfull non-invite transaction */ - status = tsx_successfull_non_invite_test(); + status = perform_generic_test("successfull non-invite transaction", + TEST6_BRANCH_ID, &pjsip_options_method); + if (status != 0) + return status; + + /* TEST7_BRANCH_ID: Successfull non-invite transaction */ + status = perform_generic_test("successfull non-invite transaction " + "with provisional response", + TEST7_BRANCH_ID, &pjsip_options_method); + if (status != 0) + return status; + + /* TEST8_BRANCH_ID: Failed invite transaction */ + status = perform_generic_test("failed invite transaction", + TEST8_BRANCH_ID, &pjsip_invite_method); + if (status != 0) + return status; + + /* TEST9_BRANCH_ID: Failed invite transaction with provisional response */ + status = perform_generic_test("failed invite transaction with " + "provisional response", + TEST9_BRANCH_ID, &pjsip_invite_method); if (status != 0) return status; |