/* * UDP transport test. */ int transport_udp_test(void) { enum { SEND_RECV_LOOP = 8 }; pjsip_transport *udp_tp, *tp; pj_sockaddr_in addr, rem_addr; pj_str_t s; pj_status_t status; int rtt[SEND_RECV_LOOP], min_rtt; int i, pkt_lost; pj_sockaddr_in_init(&addr, NULL, TEST_UDP_PORT); /* Start UDP transport. */ status = pjsip_udp_transport_start( endpt, &addr, NULL, 1, &udp_tp); if (status != PJ_SUCCESS) { app_perror(" Error: unable to start UDP transport", status); return -10; } /* UDP transport must have initial reference counter set to 1. */ if (pj_atomic_get(udp_tp->ref_cnt) != 1) return -20; /* Test basic transport attributes */ status = generic_transport_test(udp_tp); if (status != PJ_SUCCESS) return status; /* Test that transport manager is returning the correct * transport. */ pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "1.1.1.1"), 80); status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_UDP, &rem_addr, sizeof(rem_addr), NULL, &tp); if (status != PJ_SUCCESS) return -50; if (tp != udp_tp) return -60; /* pjsip_endpt_acquire_transport() adds reference, so we need * to decrement it. */ pjsip_transport_dec_ref(tp); /* Check again that reference counter is 1. */ if (pj_atomic_get(udp_tp->ref_cnt) != 1) return -70; /* Basic transport's send/receive loopback test. */ pj_sockaddr_in_init(&rem_addr, pj_cstr(&s, "127.0.0.1"), TEST_UDP_PORT); for (i=0; i<SEND_RECV_LOOP; ++i) { status = transport_send_recv_test(PJSIP_TRANSPORT_UDP, tp, "sip:[email protected]:"TEST_UDP_PORT_STR, &rtt[i]); if (status != 0) return status; } min_rtt = 0xFFFFFFF; for (i=0; i<SEND_RECV_LOOP; ++i) if (rtt[i] < min_rtt) min_rtt = rtt[i]; report_ival("udp-rtt-usec", min_rtt, "usec", "Best UDP transport round trip time, in microseconds " "(time from sending request until response is received. " "Tests were performed on local machine only)"); /* Multi-threaded round-trip test. */ status = transport_rt_test(PJSIP_TRANSPORT_UDP, tp, "sip:[email protected]:"TEST_UDP_PORT_STR, &pkt_lost); if (status != 0) return status; if (pkt_lost != 0) PJ_LOG(3,(THIS_FILE, " note: %d packet(s) was lost", pkt_lost)); /* Check again that reference counter is 1. */ if (pj_atomic_get(udp_tp->ref_cnt) != 1) return -80; /* Destroy this transport. */ pjsip_transport_dec_ref(udp_tp); /* Force destroy this transport. */ status = pjsip_transport_destroy(udp_tp); if (status != PJ_SUCCESS) return -90; /* Flush events. */ PJ_LOG(3,(THIS_FILE, " Flushing events, 1 second...")); flush_events(1000); /* Done */ return 0; }
static int do_test(const char *title, const struct registrar_cfg *srv_cfg, const struct client *client_cfg, const pj_str_t *registrar_uri, unsigned contact_cnt, const pj_str_t contacts[], unsigned expires, pj_bool_t leave_session, pjsip_regc **p_regc) { pjsip_regc *regc; unsigned i; const pj_str_t aor = pj_str("<sip:[email protected]>"); pjsip_tx_data *tdata; pj_status_t status; PJ_LOG(3,(THIS_FILE, " %s", title)); /* Modify registrar settings */ pj_memcpy(®istrar.cfg, srv_cfg, sizeof(*srv_cfg)); pj_bzero(&client_result, sizeof(client_result)); client_result.destroy_on_cb = client_cfg->destroy_on_cb; status = pjsip_regc_create(endpt, &client_result, &client_cb, ®c); if (status != PJ_SUCCESS) return -100; status = pjsip_regc_init(regc, registrar_uri, &aor, &aor, contact_cnt, contacts, expires ? expires : 60); if (status != PJ_SUCCESS) { pjsip_regc_destroy(regc); return -110; } if (client_cfg->auth) { pjsip_cred_info cred; pj_bzero(&cred, sizeof(cred)); cred.realm = pj_str("*"); cred.scheme = pj_str("digest"); cred.username = pj_str("user"); cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; cred.data = pj_str("password"); status = pjsip_regc_set_credentials(regc, 1, &cred); if (status != PJ_SUCCESS) { pjsip_regc_destroy(regc); return -115; } } /* Register */ status = pjsip_regc_register(regc, PJ_TRUE, &tdata); if (status != PJ_SUCCESS) { pjsip_regc_destroy(regc); return -120; } status = pjsip_regc_send(regc, tdata); /* That's it, wait until the callback is sent */ for (i=0; i<600 && !client_result.done; ++i) { flush_events(100); } if (!client_result.done) { PJ_LOG(3,(THIS_FILE, " error: test has timed out")); pjsip_regc_destroy(regc); return -200; } /* Destroy the regc, we're done with the test, unless we're * instructed to leave the session open. */ if (!leave_session && !client_cfg->destroy_on_cb) pjsip_regc_destroy(regc); /* Compare results with expected results */ if (client_result.error != client_cfg->error) { PJ_LOG(3,(THIS_FILE, " error: expecting err=%d, got err=%d", client_cfg->error, client_result.error)); return -210; } if (client_result.code != client_cfg->code && client_cfg->code != 502 && client_cfg->code != 503 && client_result.code != 502 && client_result.code != 503) { PJ_LOG(3,(THIS_FILE, " error: expecting code=%d, got code=%d", client_cfg->code, client_result.code)); return -220; } if (client_result.expiration != client_cfg->expiration) { PJ_LOG(3,(THIS_FILE, " error: expecting expiration=%d, got expiration=%d", client_cfg->expiration, client_result.expiration)); return -240; } if (client_result.contact_cnt != client_cfg->contact_cnt) { PJ_LOG(3,(THIS_FILE, " error: expecting contact_cnt=%d, got contact_cnt=%d", client_cfg->contact_cnt, client_result.contact_cnt)); return -250; } if (client_result.have_reg != client_cfg->have_reg) { PJ_LOG(3,(THIS_FILE, " error: expecting have_reg=%d, got have_reg=%d", client_cfg->have_reg, client_result.have_reg)); return -260; } if (client_result.have_reg && client_result.interval != client_result.expiration) { PJ_LOG(3,(THIS_FILE, " error: interval (%d) is different than expiration (%d)", client_result.interval, client_result.expiration)); return -270; } if (client_result.interval > 0 && client_result.next_reg < 1) { PJ_LOG(3,(THIS_FILE, " error: next_reg=%d, expecting positive number because interval is %d", client_result.next_reg, client_result.interval)); return -280; } /* Looks like everything is okay. */ if (leave_session) { *p_regc = regc; } return 0; }
/* Double terminate test. */ static int double_terminate(void) { pj_str_t target, from, tsx_key; pjsip_tx_data *tdata; pjsip_transaction *tsx; pj_status_t status; PJ_LOG(3,(THIS_FILE, " double terminate test")); target = pj_str(TARGET_URI); from = pj_str(FROM_URI); /* Create request. */ status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &target, &from, &target, NULL, NULL, -1, NULL, &tdata); if (status != PJ_SUCCESS) { app_perror(" error: unable to create request", status); return -10; } /* Create transaction. */ status = pjsip_tsx_create_uac(NULL, tdata, &tsx); if (status != PJ_SUCCESS) { app_perror(" error: unable to create transaction", status); return -20; } /* Save transaction key for later. */ pj_strdup_with_null(tdata->pool, &tsx_key, &tsx->transaction_key); /* Add reference to transmit buffer (tsx_send_msg() will dec txdata). */ pjsip_tx_data_add_ref(tdata); /* Send message to start timeout timer. */ status = pjsip_tsx_send_msg(tsx, NULL); /* Terminate transaction. */ status = pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED); if (status != PJ_SUCCESS) { app_perror(" error: unable to terminate transaction", status); return -30; } tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE); if (tsx) { /* Terminate transaction again. */ pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED); if (status != PJ_SUCCESS) { app_perror(" error: unable to terminate transaction", status); return -40; } pj_mutex_unlock(tsx->mutex); } flush_events(500); if (pjsip_tx_data_dec_ref(tdata) != PJSIP_EBUFDESTROYED) { return -50; } return PJ_SUCCESS; }
int test_main(void) { pj_status_t rc; pj_caching_pool caching_pool; const char *filename; unsigned tsx_test_cnt=0; struct tsx_test_param tsx_test[10]; pj_status_t status; #if INCLUDE_TSX_TEST unsigned i; pjsip_transport *tp; #if PJ_HAS_TCP pjsip_tpfactory *tpfactory; #endif /* PJ_HAS_TCP */ #endif /* INCLUDE_TSX_TEST */ int line; pj_log_set_level(log_level); pj_log_set_decor(param_log_decor); if ((rc=pj_init()) != PJ_SUCCESS) { app_perror("pj_init", rc); return rc; } if ((rc=pjlib_util_init()) != PJ_SUCCESS) { app_perror("pj_init", rc); return rc; } status = init_report(); if (status != PJ_SUCCESS) return status; pj_dump_config(); pj_caching_pool_init( &caching_pool, &pj_pool_factory_default_policy, PJSIP_TEST_MEM_SIZE ); rc = pjsip_endpt_create(&caching_pool.factory, "endpt", &endpt); if (rc != PJ_SUCCESS) { app_perror("pjsip_endpt_create", rc); pj_caching_pool_destroy(&caching_pool); return rc; } PJ_LOG(3,(THIS_FILE,"")); /* Init logger module. */ init_msg_logger(); msg_logger_set_enabled(1); /* Start transaction layer module. */ rc = pjsip_tsx_layer_init_module(endpt); if (rc != PJ_SUCCESS) { app_perror(" Error initializing transaction module", rc); goto on_return; } /* Create loop transport. */ rc = pjsip_loop_start(endpt, NULL); if (rc != PJ_SUCCESS) { app_perror(" error: unable to create datagram loop transport", rc); goto on_return; } tsx_test[tsx_test_cnt].port = 5060; tsx_test[tsx_test_cnt].tp_type = "loop-dgram"; tsx_test[tsx_test_cnt].type = PJSIP_TRANSPORT_LOOP_DGRAM; ++tsx_test_cnt; #if INCLUDE_URI_TEST DO_TEST(uri_test()); #endif #if INCLUDE_MSG_TEST DO_TEST(msg_test()); DO_TEST(msg_err_test()); #endif #if INCLUDE_MULTIPART_TEST DO_TEST(multipart_test()); #endif #if INCLUDE_TXDATA_TEST DO_TEST(txdata_test()); #endif #if INCLUDE_TSX_BENCH DO_TEST(tsx_bench()); #endif #if INCLUDE_UDP_TEST DO_TEST(transport_udp_test()); #endif #if INCLUDE_LOOP_TEST DO_TEST(transport_loop_test()); #endif #if INCLUDE_TCP_TEST DO_TEST(transport_tcp_test()); #endif #if INCLUDE_RESOLVE_TEST DO_TEST(resolve_test()); #endif #if INCLUDE_TSX_TEST status = pjsip_udp_transport_start(endpt, NULL, NULL, 1, &tp); if (status == PJ_SUCCESS) { tsx_test[tsx_test_cnt].port = tp->local_name.port; tsx_test[tsx_test_cnt].tp_type = "udp"; tsx_test[tsx_test_cnt].type = PJSIP_TRANSPORT_UDP; ++tsx_test_cnt; } #if PJ_HAS_TCP status = pjsip_tcp_transport_start(endpt, NULL, 1, &tpfactory); if (status == PJ_SUCCESS) { tsx_test[tsx_test_cnt].port = tpfactory->addr_name.port; tsx_test[tsx_test_cnt].tp_type = "tcp"; tsx_test[tsx_test_cnt].type = PJSIP_TRANSPORT_TCP; ++tsx_test_cnt; } else { app_perror("Unable to create TCP", status); rc = -4; goto on_return; } #endif for (i=0; i<tsx_test_cnt; ++i) { DO_TSX_TEST(tsx_basic_test, &tsx_test[i]); DO_TSX_TEST(tsx_uac_test, &tsx_test[i]); DO_TSX_TEST(tsx_uas_test, &tsx_test[i]); } #endif #if INCLUDE_INV_OA_TEST DO_TEST(inv_offer_answer_test()); #endif #if INCLUDE_REGC_TEST DO_TEST(regc_test()); #endif on_return: flush_events(500); /* Dumping memory pool usage */ PJ_LOG(3,(THIS_FILE, "Peak memory size=%u MB", caching_pool.peak_used_size / 1000000)); pjsip_endpt_destroy(endpt); pj_caching_pool_destroy(&caching_pool); PJ_LOG(3,(THIS_FILE, "")); pj_thread_get_stack_info(pj_thread_this(), &filename, &line); PJ_LOG(3,(THIS_FILE, "Stack max usage: %u, deepest: %s:%u", pj_thread_get_stack_max_usage(pj_thread_this()), filename, line)); if (rc == 0) PJ_LOG(3,(THIS_FILE, "Looks like everything is okay!..")); else PJ_LOG(3,(THIS_FILE, "Test completed with error(s)")); report_ival("test-status", rc, "", "Overall test status/result (0==success)"); close_report(); return rc; }
static int uas_tsx_bench(unsigned working_set, pj_timestamp *p_elapsed) { unsigned i; pjsip_tx_data *request; pjsip_via_hdr *via; pjsip_rx_data rdata; pj_sockaddr_in remote; pjsip_transaction **tsx; pj_timestamp t1, t2, elapsed; char branch_buf[80] = PJSIP_RFC3261_BRANCH_ID "0000000000"; pj_status_t status; /* Create the request first. */ pj_str_t str_target = pj_str("sip:[email protected]"); pj_str_t str_from = pj_str("\"Local User\" <sip:[email protected]>"); pj_str_t str_to = pj_str("\"Remote User\" <sip:[email protected]>"); pj_str_t str_contact = str_from; status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &str_target, &str_from, &str_to, &str_contact, NULL, -1, NULL, &request); if (status != PJ_SUCCESS) { app_perror(" error: unable to create request", status); return status; } /* Create Via */ via = pjsip_via_hdr_create(request->pool); via->sent_by.host = pj_str("192.168.0.7"); via->sent_by.port = 5061; via->transport = pj_str("udp"); via->rport_param = 1; via->recvd_param = pj_str("192.168.0.7"); pjsip_msg_insert_first_hdr(request->msg, (pjsip_hdr*)via); /* Create "dummy" rdata from the tdata */ pj_bzero(&rdata, sizeof(pjsip_rx_data)); rdata.tp_info.pool = request->pool; rdata.msg_info.msg = request->msg; rdata.msg_info.from = (pjsip_from_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL); rdata.msg_info.to = (pjsip_to_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_TO, NULL); rdata.msg_info.cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_CSEQ, NULL); rdata.msg_info.cid = (pjsip_cid_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_FROM, NULL); rdata.msg_info.via = via; pj_sockaddr_in_init(&remote, 0, 0); status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, &remote, sizeof(pj_sockaddr_in), NULL, &rdata.tp_info.transport); if (status != PJ_SUCCESS) { app_perror(" error: unable to get loop transport", status); return status; } /* Create transaction array */ tsx = (pjsip_transaction**) pj_pool_zalloc(request->pool, working_set * sizeof(pj_pool_t*)); pj_bzero(&mod_tsx_user, sizeof(mod_tsx_user)); mod_tsx_user.id = -1; /* Benchmark */ elapsed.u64 = 0; pj_get_timestamp(&t1); for (i=0; i<working_set; ++i) { via->branch_param.ptr = branch_buf; via->branch_param.slen = PJSIP_RFC3261_BRANCH_LEN + pj_ansi_sprintf(branch_buf+PJSIP_RFC3261_BRANCH_LEN, "-%d", i); status = pjsip_tsx_create_uas(&mod_tsx_user, &rdata, &tsx[i]); if (status != PJ_SUCCESS) goto on_error; } pj_get_timestamp(&t2); pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&elapsed, &t2); p_elapsed->u64 = elapsed.u64; status = PJ_SUCCESS; on_error: for (i=0; i<working_set; ++i) { if (tsx[i]) { pjsip_tsx_terminate(tsx[i], 601); tsx[i] = NULL; } } pjsip_tx_data_dec_ref(request); flush_events(2000); return status; }
static int uac_tsx_bench(unsigned working_set, pj_timestamp *p_elapsed) { unsigned i; pjsip_tx_data *request; pjsip_transaction **tsx; pj_timestamp t1, t2, elapsed; pjsip_via_hdr *via; pj_status_t status; /* Create the request first. */ pj_str_t str_target = pj_str("sip:[email protected]"); pj_str_t str_from = pj_str("\"Local User\" <sip:[email protected]>"); pj_str_t str_to = pj_str("\"Remote User\" <sip:[email protected]>"); pj_str_t str_contact = str_from; status = pjsip_endpt_create_request(endpt, &pjsip_invite_method, &str_target, &str_from, &str_to, &str_contact, NULL, -1, NULL, &request); if (status != PJ_SUCCESS) { app_perror(" error: unable to create request", status); return status; } via = (pjsip_via_hdr*) pjsip_msg_find_hdr(request->msg, PJSIP_H_VIA, NULL); /* Create transaction array */ tsx = (pjsip_transaction**) pj_pool_zalloc(request->pool, working_set * sizeof(pj_pool_t*)); pj_bzero(&mod_tsx_user, sizeof(mod_tsx_user)); mod_tsx_user.id = -1; /* Benchmark */ elapsed.u64 = 0; pj_get_timestamp(&t1); for (i=0; i<working_set; ++i) { status = pjsip_tsx_create_uac(&mod_tsx_user, request, &tsx[i]); if (status != PJ_SUCCESS) goto on_error; /* Reset branch param */ via->branch_param.slen = 0; } pj_get_timestamp(&t2); pj_sub_timestamp(&t2, &t1); pj_add_timestamp(&elapsed, &t2); p_elapsed->u64 = elapsed.u64; status = PJ_SUCCESS; on_error: for (i=0; i<working_set; ++i) { if (tsx[i]) { pjsip_tsx_terminate(tsx[i], 601); tsx[i] = NULL; } } pjsip_tx_data_dec_ref(request); flush_events(2000); return status; }
static void test_customdraw(void) { static struct { LRESULT FirstReturnValue; int ExpectedCalls; } expectedResults[] = { /* Valid notification responses */ {CDRF_DODEFAULT, TEST_CDDS_PREPAINT}, {CDRF_SKIPDEFAULT, TEST_CDDS_PREPAINT}, {CDRF_NOTIFYPOSTPAINT, TEST_CDDS_PREPAINT | TEST_CDDS_POSTPAINT}, /* Invalid notification responses */ {CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT}, {CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT}, {CDRF_NEWFONT, TEST_CDDS_PREPAINT} }; DWORD iterationNumber; WNDCLASSA wc; LRESULT lResult; POINT orig_pos; /* Create a class to use the custom draw wndproc */ wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = GetModuleHandleA(NULL); wc.hIcon = NULL; wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW); wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW); wc.lpszMenuName = NULL; wc.lpszClassName = "CustomDrawClass"; wc.lpfnWndProc = custom_draw_wnd_proc; RegisterClassA(&wc); GetCursorPos(&orig_pos); for (iterationNumber = 0; iterationNumber < sizeof(expectedResults)/sizeof(expectedResults[0]); iterationNumber++) { HWND parent, hwndTip; RECT rect; TTTOOLINFOA toolInfo = { 0 }; /* Create a main window */ parent = CreateWindowExA(0, "CustomDrawClass", NULL, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 50, 50, 300, 300, NULL, NULL, NULL, 0); ok(parent != NULL, "Creation of main window failed\n"); /* Make it show */ ShowWindow(parent, SW_SHOWNORMAL); flush_events(100); /* Create Tooltip */ hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parent, NULL, GetModuleHandleA(NULL), 0); ok(hwndTip != NULL, "Creation of tooltip window failed\n"); /* Set up parms for the wndproc to handle */ CD_Stages = 0; CD_Result = expectedResults[iterationNumber].FirstReturnValue; g_hwnd = hwndTip; /* Make it topmost, as per the MSDN */ SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); /* Create a tool */ toolInfo.cbSize = TTTOOLINFOA_V1_SIZE; toolInfo.hwnd = parent; toolInfo.hinst = GetModuleHandleA(NULL); toolInfo.uFlags = TTF_SUBCLASS; toolInfo.uId = 0x1234ABCD; toolInfo.lpszText = (LPSTR)"This is a test tooltip"; toolInfo.lParam = 0xdeadbeef; GetClientRect (parent, &toolInfo.rect); lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo); ok(lResult, "Adding the tool to the tooltip failed\n"); /* Make tooltip appear quickly */ SendMessageA(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0)); /* Put cursor inside window, tooltip will appear immediately */ GetWindowRect( parent, &rect ); SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 ); flush_events(200); if (CD_Stages) { /* Check CustomDraw results */ ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls || broken(CD_Stages == (expectedResults[iterationNumber].ExpectedCalls & ~TEST_CDDS_POSTPAINT)), /* nt4 */ "CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages, expectedResults[iterationNumber].ExpectedCalls); } /* Clean up */ DestroyWindow(hwndTip); DestroyWindow(parent); } SetCursorPos(orig_pos.x, orig_pos.y); }
/* * Tests if a progress bar repaints itself immediately when it receives * some specific messages. */ static void test_redraw(void) { RECT client_rect, rect; HWND hProgressWnd; LRESULT ret; GetClientRect(hProgressParentWnd, &rect); hProgressWnd = CreateWindowExA(0, PROGRESS_CLASSA, "", WS_CHILD | WS_VISIBLE, 0, 0, rect.right, rect.bottom, hProgressParentWnd, NULL, GetModuleHandleA(NULL), 0); ok(hProgressWnd != NULL, "Failed to create progress bar.\n"); progress_wndproc = (WNDPROC)SetWindowLongPtrA(hProgressWnd, GWLP_WNDPROC, (LPARAM)progress_subclass_proc); ShowWindow(hProgressParentWnd, SW_SHOWNORMAL); ok(GetUpdateRect(hProgressParentWnd, NULL, FALSE), "GetUpdateRect: There should be a region that needs to be updated\n"); flush_events(); update_window(hProgressParentWnd); SendMessageA(hProgressWnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); SendMessageA(hProgressWnd, PBM_SETPOS, 10, 0); SendMessageA(hProgressWnd, PBM_SETSTEP, 20, 0); update_window(hProgressWnd); /* PBM_SETPOS */ ok(SendMessageA(hProgressWnd, PBM_SETPOS, 50, 0) == 10, "PBM_SETPOS must return the previous position\n"); ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_SETPOS: The progress bar should be redrawn immediately\n"); /* PBM_DELTAPOS */ ok(SendMessageA(hProgressWnd, PBM_DELTAPOS, 15, 0) == 50, "PBM_DELTAPOS must return the previous position\n"); ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_DELTAPOS: The progress bar should be redrawn immediately\n"); /* PBM_SETPOS */ ok(SendMessageA(hProgressWnd, PBM_SETPOS, 80, 0) == 65, "PBM_SETPOS must return the previous position\n"); ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_SETPOS: The progress bar should be redrawn immediately\n"); /* PBM_STEPIT */ ok(SendMessageA(hProgressWnd, PBM_STEPIT, 0, 0) == 80, "PBM_STEPIT must return the previous position\n"); ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_STEPIT: The progress bar should be redrawn immediately\n"); ret = SendMessageA(hProgressWnd, PBM_GETPOS, 0, 0); if (ret == 0) win_skip("PBM_GETPOS needs comctl32 > 4.70\n"); else ok(ret == 100, "PBM_GETPOS returned a wrong position : %d\n", (UINT)ret); /* PBM_SETRANGE and PBM_SETRANGE32: Usually the progress bar doesn't repaint itself immediately. If the position is not in the new range, it does. Don't test this, it may change in future Windows versions. */ SendMessageA(hProgressWnd, PBM_SETPOS, 0, 0); update_window(hProgressWnd); /* increase to 10 - no background erase required */ erased = FALSE; SetRectEmpty(&last_paint_rect); SendMessageA(hProgressWnd, PBM_SETPOS, 10, 0); GetClientRect(hProgressWnd, &client_rect); ok(EqualRect(&last_paint_rect, &client_rect), "last_paint_rect was %s instead of %s\n", wine_dbgstr_rect(&last_paint_rect), wine_dbgstr_rect(&client_rect)); update_window(hProgressWnd); ok(!erased, "Progress bar shouldn't have erased the background\n"); /* decrease to 0 - background erase will be required */ erased = FALSE; SetRectEmpty(&last_paint_rect); SendMessageA(hProgressWnd, PBM_SETPOS, 0, 0); GetClientRect(hProgressWnd, &client_rect); ok(EqualRect(&last_paint_rect, &client_rect), "last_paint_rect was %s instead of %s\n", wine_dbgstr_rect(&last_paint_rect), wine_dbgstr_rect(&client_rect)); update_window(hProgressWnd); ok(erased, "Progress bar should have erased the background\n"); DestroyWindow(hProgressWnd); }
/***************************************************************************** ** ** UAC Transaction Test. ** ***************************************************************************** */ int tsx_uac_test(struct tsx_test_param *param) { pj_sockaddr_in addr; pj_status_t status; timer.tsx_key.ptr = timer.key_buf; test_param = param; /* Get transport flag */ tp_flag = pjsip_transport_get_flag_from_type(test_param->type); pj_ansi_sprintf(TARGET_URI, "sip:[email protected]:%d;transport=%s", param->port, param->tp_type); pj_ansi_sprintf(FROM_URI, "sip:[email protected]:%d;transport=%s", param->port, param->tp_type); /* Check if loop transport is configured. */ status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, &addr, sizeof(addr), NULL, &loop); if (status != PJ_SUCCESS) { PJ_LOG(3,(THIS_FILE, " Error: loop transport is not configured!")); return -10; } /* Register modules. */ status = pjsip_endpt_register_module(endpt, &tsx_user); if (status != PJ_SUCCESS) { app_perror(" Error: unable to register module", status); return -30; } status = pjsip_endpt_register_module(endpt, &msg_receiver); if (status != PJ_SUCCESS) { app_perror(" Error: unable to register module", status); return -40; } /* TEST1_BRANCH_ID: Basic retransmit and timeout test. */ status = tsx_uac_retransmit_test(); if (status != 0) return status; /* TEST2_BRANCH_ID: Resolve error test. */ status = tsx_resolve_error_test(); if (status != 0) return status; /* TEST3_BRANCH_ID: UAC terminate while resolving test. */ status = tsx_terminate_resolving_test(); if (status != 0) return status; /* TEST4_BRANCH_ID: Transport failed after several retransmissions. * Only applies to loop transport. */ if (test_param->type == PJSIP_TRANSPORT_LOOP_DGRAM) { status = tsx_retransmit_fail_test(); if (status != 0) return status; } /* TEST5_BRANCH_ID: Terminate transaction after several retransmissions * Only applicable to non-reliable transports. */ if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) { status = tsx_terminate_after_retransmit_test(); if (status != 0) return status; } /* TEST6_BRANCH_ID: Successfull non-invite transaction */ status = perform_generic_test("test6: 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("test7: 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("test8: 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("test9: failed invite transaction with " "provisional response", TEST9_BRANCH_ID, &pjsip_invite_method); if (status != 0) return status; pjsip_transport_dec_ref(loop); flush_events(500); /* Unregister modules. */ status = pjsip_endpt_unregister_module(endpt, &tsx_user); if (status != PJ_SUCCESS) { app_perror(" Error: unable to unregister module", status); return -31; } status = pjsip_endpt_unregister_module(endpt, &msg_receiver); if (status != PJ_SUCCESS) { app_perror(" Error: unable to unregister module", status); return -41; } return 0; }
/* * The generic test framework, used by most of the tests. */ static int perform_tsx_test(int dummy, char *target_uri, char *from_uri, char *branch_param, int test_time, const pjsip_method *method) { pjsip_tx_data *tdata; pjsip_transaction *tsx; pj_str_t target, from, tsx_key; pjsip_via_hdr *via; pj_time_val timeout; pj_status_t status; PJ_LOG(3,(THIS_FILE, " please standby, this will take at most %d seconds..", test_time)); /* Reset test. */ recv_count = 0; test_complete = 0; /* Init headers. */ target = pj_str(target_uri); from = pj_str(from_uri); /* Create request. */ status = pjsip_endpt_create_request( endpt, method, &target, &from, &target, NULL, NULL, -1, NULL, &tdata); if (status != PJ_SUCCESS) { app_perror(" Error: unable to create request", status); return -100; } /* Set the branch param for test 1. */ via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); via->branch_param = pj_str(branch_param); /* Add additional reference to tdata to prevent transaction from * deleting it. */ pjsip_tx_data_add_ref(tdata); /* Create transaction. */ status = pjsip_tsx_create_uac( &tsx_user, tdata, &tsx); if (status != PJ_SUCCESS) { app_perror(" Error: unable to create UAC transaction", status); pjsip_tx_data_dec_ref(tdata); return -110; } /* Get transaction key. */ pj_strdup(tdata->pool, &tsx_key, &tsx->transaction_key); /* Send the message. */ status = pjsip_tsx_send_msg(tsx, NULL); // Ignore send result. Some tests do deliberately triggers error // when sending message. if (status != PJ_SUCCESS) { // app_perror(" Error: unable to send request", status); pjsip_tx_data_dec_ref(tdata); // return -120; } /* Set test completion time. */ pj_gettimeofday(&timeout); timeout.sec += test_time; /* Wait until test complete. */ while (!test_complete) { pj_time_val now, poll_delay = {0, 10}; pjsip_endpt_handle_events(endpt, &poll_delay); pj_gettimeofday(&now); if (now.sec > timeout.sec) { PJ_LOG(3,(THIS_FILE, " Error: test has timed out")); pjsip_tx_data_dec_ref(tdata); return -130; } } if (test_complete < 0) { tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE); if (tsx) { pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED); pj_mutex_unlock(tsx->mutex); flush_events(1000); } pjsip_tx_data_dec_ref(tdata); return test_complete; } else { pj_time_val now; /* Allow transaction to destroy itself */ flush_events(500); /* Wait until test completes */ pj_gettimeofday(&now); if (PJ_TIME_VAL_LT(now, timeout)) { pj_time_val interval; interval = timeout; PJ_TIME_VAL_SUB(interval, now); flush_events(PJ_TIME_VAL_MSEC(interval)); } } /* Make sure transaction has been destroyed. */ if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) { PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed")); pjsip_tx_data_dec_ref(tdata); return -140; } /* Check tdata reference counter. */ if (pj_atomic_get(tdata->ref_cnt) != 1) { PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d", pj_atomic_get(tdata->ref_cnt))); pjsip_tx_data_dec_ref(tdata); return -150; } /* Destroy txdata */ pjsip_tx_data_dec_ref(tdata); return PJ_SUCCESS; }
static int perform_test(inv_test_param_t *param) { pj_str_t uri; pjsip_dialog *dlg; pjmedia_sdp_session *sdp; pjsip_tx_data *tdata; pj_status_t status; PJ_LOG(3,(THIS_FILE, " %s", param->title)); pj_bzero(&inv_test, sizeof(inv_test)); pj_memcpy(&inv_test.param, param, sizeof(*param)); job_cnt = 0; uri = pj_str(CONTACT); /* * Create UAC */ status = pjsip_dlg_create_uac(pjsip_ua_instance(), &uri, &uri, &uri, &uri, &dlg); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -10); if (inv_test.param.oa[0] == OFFERER_UAC) sdp = create_sdp(dlg->pool, oa_sdp[0].offer); else sdp = NULL; status = pjsip_inv_create_uac(dlg, sdp, inv_test.param.inv_option, &inv_test.uac); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -20); TRACE_((THIS_FILE, " Sending INVITE %s offer", (sdp ? "with" : "without"))); /* * Make call! */ status = pjsip_inv_invite(inv_test.uac, &tdata); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30); status = pjsip_inv_send_msg(inv_test.uac, tdata); PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30); /* * Wait until test completes */ while (!inv_test.complete) { pj_time_val delay = {0, 20}; pjsip_endpt_handle_events(endpt, &delay); while (job_cnt) { job_t j; j = jobs[0]; pj_array_erase(jobs, sizeof(jobs[0]), job_cnt, 0); --job_cnt; run_job(&j); } } flush_events(100); /* * Hangup */ TRACE_((THIS_FILE, " Disconnecting call")); status = pjsip_inv_end_session(inv_test.uas, PJSIP_SC_DECLINE, 0, &tdata); pj_assert(status == PJ_SUCCESS); status = pjsip_inv_send_msg(inv_test.uas, tdata); pj_assert(status == PJ_SUCCESS); flush_events(500); return 0; }
static void test_button_messages(void) { static const struct { DWORD style; DWORD dlg_code; const struct message *setfocus; const struct message *killfocus; const struct message *setstyle; const struct message *setstate; const struct message *clearstate; const struct message *setcheck; } button[] = { { BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_seq, setstate_seq, setstate_seq, setcheck_ignored_seq }, { BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_seq, setstate_seq, setstate_seq, setcheck_ignored_seq }, { BS_CHECKBOX, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, setstate_static_seq, setstate_static_seq, setcheck_static_seq }, { BS_AUTOCHECKBOX, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, setstate_static_seq, setstate_static_seq, setcheck_static_seq }, { BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq }, { BS_3STATE, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, setstate_static_seq, setstate_static_seq, setcheck_static_seq }, { BS_AUTO3STATE, DLGC_BUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, setstate_static_seq, setstate_static_seq, setcheck_static_seq }, { BS_GROUPBOX, DLGC_STATIC, setfocus_groupbox_seq, killfocus_static_seq, setstyle_static_seq, setstate_static_seq, setstate_static_seq, setcheck_ignored_seq }, { BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON, setfocus_seq, killfocus_seq, setstyle_user_seq, setstate_user_seq, clearstate_seq, setcheck_ignored_seq }, { BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON, setfocus_static_seq, killfocus_static_seq, setstyle_static_seq, setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq }, { BS_OWNERDRAW, DLGC_BUTTON, setfocus_ownerdraw_seq, killfocus_ownerdraw_seq, setstyle_ownerdraw_seq, setstate_ownerdraw_seq, clearstate_ownerdraw_seq, setcheck_ignored_seq }, }; const struct message *seq; unsigned int i; HWND hwnd, parent; DWORD dlg_code; HFONT zfont; BOOL todo; /* selection with VK_SPACE should capture button window */ hwnd = create_button(BS_CHECKBOX | WS_VISIBLE | WS_POPUP, NULL); ok(hwnd != 0, "Failed to create button window\n"); ReleaseCapture(); SetFocus(hwnd); SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); ok(GetCapture() == hwnd, "Should be captured on VK_SPACE WM_KEYDOWN\n"); SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); DestroyWindow(hwnd); parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok(parent != 0, "Failed to create parent window\n"); for (i = 0; i < sizeof(button)/sizeof(button[0]); i++) { MSG msg; DWORD style, state; trace("%d: button test sequence\n", i); hwnd = create_button(button[i].style, parent); style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY); /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ if (button[i].style == BS_USERBUTTON) ok(style == BS_PUSHBUTTON, "expected style BS_PUSHBUTTON got %x\n", style); else ok(style == button[i].style, "expected style %x got %x\n", button[i].style, style); dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0); ok(dlg_code == button[i].dlg_code, "%u: wrong dlg_code %08x\n", i, dlg_code); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); SetFocus(0); flush_events(); SetFocus(0); flush_sequences(sequences, NUM_MSG_SEQUENCES); todo = button[i].style != BS_OWNERDRAW; ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); SetFocus(hwnd); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setfocus, "SetFocus(hwnd) on a button", todo); todo = button[i].style == BS_OWNERDRAW; SetFocus(0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", todo); ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus()); SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstyle, "BM_SETSTYLE on a button", TRUE); style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY); /* XP doesn't turn a BS_USERBUTTON into BS_PUSHBUTTON here! */ ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == 0, "expected state 0, got %04x\n", state); flush_sequences(sequences, NUM_MSG_SEQUENCES); SendMessageA(hwnd, BM_SETSTATE, TRUE, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstate, "BM_SETSTATE/TRUE on a button", TRUE); state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == BST_PUSHED, "expected state 0x0004, got %04x\n", state); style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); flush_sequences(sequences, NUM_MSG_SEQUENCES); SendMessageA(hwnd, BM_SETSTATE, FALSE, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].clearstate, "BM_SETSTATE/FALSE on a button", TRUE); state = SendMessageA(hwnd, BM_GETSTATE, 0, 0); ok(state == 0, "expected state 0, got %04x\n", state); style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); flush_sequences(sequences, NUM_MSG_SEQUENCES); if (button[i].style == BS_RADIOBUTTON || button[i].style == BS_AUTORADIOBUTTON) { seq = setcheck_radio_seq; todo = TRUE; } else { seq = setcheck_ignored_seq; todo = FALSE; } SendMessageA(hwnd, BM_SETCHECK, BST_UNCHECKED, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); ok_sequence(sequences, COMBINED_SEQ_INDEX, seq, "BM_SETCHECK on a button", todo); state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state); style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); flush_sequences(sequences, NUM_MSG_SEQUENCES); SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0); SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); if (button[i].style == BS_PUSHBUTTON || button[i].style == BS_DEFPUSHBUTTON || button[i].style == BS_GROUPBOX || button[i].style == BS_USERBUTTON || button[i].style == BS_OWNERDRAW) { ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setcheck, "BM_SETCHECK on a button", FALSE); state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_UNCHECKED, "expected check BST_UNCHECKED, got %04x\n", state); } else { ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setcheck, "BM_SETCHECK on a button", TRUE); state = SendMessageA(hwnd, BM_GETCHECK, 0, 0); ok(state == BST_CHECKED, "expected check BST_CHECKED, got %04x\n", state); } style = GetWindowLongA(hwnd, GWL_STYLE); style &= ~(WS_CHILD | BS_NOTIFY | WS_VISIBLE); if (button[i].style == BS_RADIOBUTTON || button[i].style == BS_AUTORADIOBUTTON) ok(style == (button[i].style | WS_TABSTOP), "expected style %04x | WS_TABSTOP got %04x\n", button[i].style, style); else ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style); DestroyWindow(hwnd); } DestroyWindow(parent); hwnd = create_button(BS_PUSHBUTTON, NULL); SetForegroundWindow(hwnd); flush_events(); SetActiveWindow(hwnd); SetFocus(0); flush_sequences(sequences, NUM_MSG_SEQUENCES); SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0); ok_sequence(sequences, COMBINED_SEQ_INDEX, lbuttondown_seq, "WM_LBUTTONDOWN on a button", FALSE); SendMessageA(hwnd, WM_LBUTTONUP, 0, 0); ok_sequence(sequences, COMBINED_SEQ_INDEX, lbuttonup_seq, "WM_LBUTTONUP on a button", TRUE); flush_sequences(sequences, NUM_MSG_SEQUENCES); zfont = GetStockObject(SYSTEM_FONT); SendMessageA(hwnd, WM_SETFONT, (WPARAM)zfont, TRUE); UpdateWindow(hwnd); ok_sequence(sequences, COMBINED_SEQ_INDEX, setfont_seq, "WM_SETFONT on a button", FALSE); DestroyWindow(hwnd); }
/* * The generic test framework, used by most of the tests. */ static int perform_test( char *target_uri, char *from_uri, char *branch_param, int test_time, const pjsip_method *method, int request_cnt, int request_interval_msec, int expecting_timeout) { pjsip_tx_data *tdata; pj_str_t target, from; pjsip_via_hdr *via; pj_time_val timeout, next_send; int sent_cnt; pj_status_t status; PJ_LOG(3,(THIS_FILE, " please standby, this will take at most %d seconds..", test_time)); /* Reset test. */ recv_count = 0; test_complete = 0; tsx_key.slen = 0; /* Init headers. */ target = pj_str(target_uri); from = pj_str(from_uri); /* Create request. */ status = pjsip_endpt_create_request( endpt, method, &target, &from, &target, NULL, NULL, -1, NULL, &tdata); if (status != PJ_SUCCESS) { app_perror(" Error: unable to create request", status); return -10; } /* Set the branch param for test 1. */ via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL); via->branch_param = pj_str(branch_param); /* Schedule first send. */ sent_cnt = 0; pj_gettimeofday(&next_send); pj_time_val_normalize(&next_send); /* Set test completion time. */ pj_gettimeofday(&timeout); timeout.sec += test_time; /* Wait until test complete. */ while (!test_complete) { pj_time_val now, poll_delay = {0, 10}; pjsip_endpt_handle_events(endpt, &poll_delay); pj_gettimeofday(&now); if (sent_cnt < request_cnt && PJ_TIME_VAL_GTE(now, next_send)) { /* Add additional reference to tdata to prevent transaction from * deleting it. */ pjsip_tx_data_add_ref(tdata); /* (Re)Send the request. */ PJ_LOG(4,(THIS_FILE, " (re)sending request %d", sent_cnt)); status = pjsip_endpt_send_request_stateless(endpt, tdata, 0, 0); if (status != PJ_SUCCESS) { app_perror(" Error: unable to send request", status); pjsip_tx_data_dec_ref(tdata); return -20; } /* Schedule next send, if any. */ sent_cnt++; if (sent_cnt < request_cnt) { pj_gettimeofday(&next_send); next_send.msec += request_interval_msec; pj_time_val_normalize(&next_send); } } if (now.sec > timeout.sec) { if (!expecting_timeout) PJ_LOG(3,(THIS_FILE, " Error: test has timed out")); pjsip_tx_data_dec_ref(tdata); return TEST_TIMEOUT_ERROR; } } if (test_complete < 0) { pjsip_transaction *tsx; tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE); if (tsx) { pjsip_tsx_terminate(tsx, PJSIP_SC_REQUEST_TERMINATED); pj_mutex_unlock(tsx->mutex); flush_events(1000); } pjsip_tx_data_dec_ref(tdata); return test_complete; } /* Allow transaction to destroy itself */ flush_events(500); /* Make sure transaction has been destroyed. */ if (pjsip_tsx_layer_find_tsx(&tsx_key, PJ_FALSE) != NULL) { PJ_LOG(3,(THIS_FILE, " Error: transaction has not been destroyed")); pjsip_tx_data_dec_ref(tdata); return -40; } /* Check tdata reference counter. */ if (pj_atomic_get(tdata->ref_cnt) != 1) { PJ_LOG(3,(THIS_FILE, " Error: tdata reference counter is %d", pj_atomic_get(tdata->ref_cnt))); pjsip_tx_data_dec_ref(tdata); return -50; } /* Destroy txdata */ pjsip_tx_data_dec_ref(tdata); return PJ_SUCCESS; }
/* Check that client is sending register refresh */ static int keep_alive_test(const pj_str_t *registrar_uri) { enum { TIMEOUT = 40 }; struct registrar_cfg server_cfg = /* respond code auth contact exp_prm expires more_contacts */ { PJ_TRUE, 200, PJ_FALSE, EXACT, TIMEOUT, 0, {NULL, 0}}; struct client client_cfg = /* error code have_reg expiration contact_cnt auth? destroy*/ { PJ_FALSE, 200, PJ_TRUE, TIMEOUT, 1, PJ_FALSE,PJ_FALSE}; pj_str_t contact = pj_str("<sip:c@C>"); pjsip_regc *regc; unsigned i; int ret; ret = do_test("register refresh (takes ~40 secs)", &server_cfg, &client_cfg, registrar_uri, 1, &contact, TIMEOUT, PJ_TRUE, ®c); if (ret != 0) return ret; /* Reset server response_cnt */ registrar.response_cnt = 0; /* Wait until keep-alive/refresh is done */ for (i=0; i<(TIMEOUT-1)*10 && registrar.response_cnt==0; ++i) { flush_events(100); } if (registrar.response_cnt==0) { PJ_LOG(3,(THIS_FILE, " error: no refresh is received")); return -400; } if (client_result.error) { PJ_LOG(3,(THIS_FILE, " error: got error")); return -410; } if (client_result.code != 200) { PJ_LOG(3,(THIS_FILE, " error: expecting code=%d, got code=%d", 200, client_result.code)); return -420; } if (client_result.expiration != TIMEOUT) { PJ_LOG(3,(THIS_FILE, " error: expecting expiration=%d, got expiration=%d", TIMEOUT, client_result.expiration)); return -440; } if (client_result.contact_cnt != 1) { PJ_LOG(3,(THIS_FILE, " error: expecting contact_cnt=%d, got contact_cnt=%d", TIMEOUT, client_result.contact_cnt)); return -450; } if (client_result.have_reg == 0) { PJ_LOG(3,(THIS_FILE, " error: expecting have_reg=%d, got have_reg=%d", 1, client_result.have_reg)); return -460; } if (client_result.interval != TIMEOUT) { PJ_LOG(3,(THIS_FILE, " error: interval (%d) is different than expiration (%d)", client_result.interval, TIMEOUT)); return -470; } if (client_result.expiration > 0 && client_result.next_reg < 1) { PJ_LOG(3,(THIS_FILE, " error: next_reg=%d, expecting positive number because expiration is %d", client_result.next_reg, client_result.expiration)); return -480; } /* Success */ pjsip_regc_destroy(regc); return 0; }
static void test_setinfo(void) { WNDCLASSA wc; LRESULT lResult; HWND parent, parent2, hwndTip, hwndTip2; TTTOOLINFOA toolInfo = { 0 }; TTTOOLINFOA toolInfo2 = { 0 }; WNDPROC wndProc; /* Create a class to use the custom draw wndproc */ wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = GetModuleHandleA(NULL); wc.hIcon = NULL; wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW); wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW); wc.lpszMenuName = NULL; wc.lpszClassName = "SetInfoClass"; wc.lpfnWndProc = info_wnd_proc; RegisterClassA(&wc); /* Create a main window */ parent = CreateWindowExA(0, "SetInfoClass", NULL, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 50, 50, 300, 300, NULL, NULL, NULL, 0); ok(parent != NULL, "Creation of main window failed\n"); parent2 = CreateWindowExA(0, "SetInfoClass", NULL, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 50, 50, 300, 300, NULL, NULL, NULL, 0); ok(parent2 != NULL, "Creation of main window failed\n"); /* Make it show */ ShowWindow(parent2, SW_SHOWNORMAL); flush_events(100); /* Create Tooltip */ hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parent, NULL, GetModuleHandleA(NULL), 0); ok(hwndTip != NULL, "Creation of tooltip window failed\n"); hwndTip2 = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parent, NULL, GetModuleHandleA(NULL), 0); ok(hwndTip2 != NULL, "Creation of tooltip window failed\n"); /* Make it topmost, as per the MSDN */ SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); /* Create a tool */ toolInfo.cbSize = TTTOOLINFOA_V1_SIZE; toolInfo.hwnd = parent; toolInfo.hinst = GetModuleHandleA(NULL); toolInfo.uFlags = TTF_SUBCLASS; toolInfo.uId = 0x1234ABCD; toolInfo.lpszText = (LPSTR)"This is a test tooltip"; toolInfo.lParam = 0xdeadbeef; GetClientRect (parent, &toolInfo.rect); lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo); ok(lResult, "Adding the tool to the tooltip failed\n"); toolInfo.cbSize = TTTOOLINFOA_V1_SIZE; toolInfo.hwnd = parent2; toolInfo.hinst = GetModuleHandleA(NULL); toolInfo.uFlags = 0; toolInfo.uId = 0x1234ABCE; toolInfo.lpszText = (LPSTR)"This is a test tooltip"; toolInfo.lParam = 0xdeadbeef; GetClientRect (parent, &toolInfo.rect); lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo); ok(lResult, "Adding the tool to the tooltip failed\n"); /* Try to Remove Subclass */ toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE; toolInfo2.hwnd = parent; toolInfo2.uId = 0x1234ABCD; lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); ok(lResult, "GetToolInfo failed\n"); ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n"); wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC); ok (wndProc != info_wnd_proc, "Window Proc is wrong\n"); toolInfo2.uFlags &= ~TTF_SUBCLASS; SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2); lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); ok(lResult, "GetToolInfo failed\n"); ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n"); wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC); ok (wndProc != info_wnd_proc, "Window Proc is wrong\n"); /* Try to Add Subclass */ /* Make it topmost, as per the MSDN */ SetWindowPos(hwndTip2, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE; toolInfo2.hwnd = parent2; toolInfo2.uId = 0x1234ABCE; lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); ok(lResult, "GetToolInfo failed\n"); ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n"); wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC); ok (wndProc == info_wnd_proc, "Window Proc is wrong\n"); toolInfo2.uFlags |= TTF_SUBCLASS; SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2); lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); ok(lResult, "GetToolInfo failed\n"); ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n"); wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC); ok (wndProc == info_wnd_proc, "Window Proc is wrong\n"); /* Clean up */ DestroyWindow(hwndTip); DestroyWindow(hwndTip2); DestroyWindow(parent); DestroyWindow(parent2); }
int transport_rt_test( pjsip_transport_type_e tp_type, pjsip_transport *ref_tp, char *target_url, int *lost) { enum { THREADS = 4, INTERVAL = 10 }; int i; pj_status_t status; pj_pool_t *pool; pj_bool_t logger_enabled; pj_timestamp zero_time, total_time; unsigned usec_rt; unsigned total_sent; unsigned total_recv; PJ_UNUSED_ARG(tp_type); PJ_UNUSED_ARG(ref_tp); PJ_LOG(3,(THIS_FILE, " multithreaded round-trip test (%d threads)...", THREADS)); PJ_LOG(3,(THIS_FILE, " this will take approx %d seconds, please wait..", INTERVAL)); /* Make sure msg logger is disabled. */ logger_enabled = msg_logger_set_enabled(0); /* Register module (if not yet registered) */ if (rt_module.id == -1) { status = pjsip_endpt_register_module( endpt, &rt_module ); if (status != PJ_SUCCESS) { app_perror(" error: unable to register module", status); return -600; } } /* Create pool for this test. */ pool = pjsip_endpt_create_pool(endpt, NULL, 4000, 4000); if (!pool) return -610; /* Initialize static test data. */ pj_ansi_strcpy(rt_target_uri, target_url); rt_call_id = pj_str("RT-Call-Id/"); rt_stop = PJ_FALSE; /* Initialize thread data. */ for (i=0; i<THREADS; ++i) { char buf[1]; pj_str_t str_id; pj_strset(&str_id, buf, 1); pj_bzero(&rt_test_data[i], sizeof(rt_test_data[i])); /* Init timer entry */ rt_test_data[i].tx_timer.id = i; rt_test_data[i].tx_timer.cb = &rt_tx_timer; rt_test_data[i].timeout_timer.id = i; rt_test_data[i].timeout_timer.cb = &rt_timeout_timer; /* Generate Call-ID for each thread. */ rt_test_data[i].call_id.ptr = (char*) pj_pool_alloc(pool, rt_call_id.slen+1); pj_strcpy(&rt_test_data[i].call_id, &rt_call_id); buf[0] = '0' + (char)i; pj_strcat(&rt_test_data[i].call_id, &str_id); /* Init mutex. */ status = pj_mutex_create_recursive(pool, "rt", &rt_test_data[i].mutex); if (status != PJ_SUCCESS) { app_perror(" error: unable to create mutex", status); return -615; } /* Create thread, suspended. */ status = pj_thread_create(pool, "rttest%p", &rt_worker_thread, (void*)(long)i, 0, PJ_THREAD_SUSPENDED, &rt_test_data[i].thread); if (status != PJ_SUCCESS) { app_perror(" error: unable to create thread", status); return -620; } } /* Start threads! */ for (i=0; i<THREADS; ++i) { pj_time_val delay = {0,0}; pj_thread_resume(rt_test_data[i].thread); /* Schedule first message transmissions. */ rt_test_data[i].tx_timer.user_data = (void*)1; pjsip_endpt_schedule_timer(endpt, &rt_test_data[i].tx_timer, &delay); } /* Sleep for some time. */ pj_thread_sleep(INTERVAL * 1000); /* Signal thread to stop. */ rt_stop = PJ_TRUE; /* Wait threads to complete. */ for (i=0; i<THREADS; ++i) { pj_thread_join(rt_test_data[i].thread); pj_thread_destroy(rt_test_data[i].thread); } /* Destroy rt_test_data */ for (i=0; i<THREADS; ++i) { pj_mutex_destroy(rt_test_data[i].mutex); pjsip_endpt_cancel_timer(endpt, &rt_test_data[i].timeout_timer); } /* Gather statistics. */ pj_bzero(&total_time, sizeof(total_time)); pj_bzero(&zero_time, sizeof(zero_time)); usec_rt = total_sent = total_recv = 0; for (i=0; i<THREADS; ++i) { total_sent += rt_test_data[i].sent_request_count; total_recv += rt_test_data[i].recv_response_count; pj_add_timestamp(&total_time, &rt_test_data[i].total_rt_time); } /* Display statistics. */ if (total_recv) total_time.u64 = total_time.u64/total_recv; else total_time.u64 = 0; usec_rt = pj_elapsed_usec(&zero_time, &total_time); PJ_LOG(3,(THIS_FILE, " done.")); PJ_LOG(3,(THIS_FILE, " total %d messages sent", total_sent)); PJ_LOG(3,(THIS_FILE, " average round-trip=%d usec", usec_rt)); pjsip_endpt_release_pool(endpt, pool); *lost = total_sent-total_recv; /* Flush events. */ flush_events(500); /* Restore msg logger. */ msg_logger_set_enabled(logger_enabled); return 0; }
int transport_tcp_test(void) { enum { SEND_RECV_LOOP = 8 }; pjsip_tpfactory *tpfactory; pjsip_transport *tcp; pj_sockaddr_in rem_addr; pj_status_t status; char url[PJSIP_MAX_URL_SIZE]; int rtt[SEND_RECV_LOOP], min_rtt; int i, pkt_lost; /* Start TCP listener on arbitrary port. */ status = pjsip_tcp_transport_start(endpt, NULL, 1, &tpfactory); if (status != PJ_SUCCESS) { app_perror(" Error: unable to start TCP transport", status); return -10; } /* Get the listener address */ status = pj_sockaddr_in_init(&rem_addr, &tpfactory->addr_name.host, (pj_uint16_t)tpfactory->addr_name.port); if (status != PJ_SUCCESS) { app_perror(" Error: possibly invalid TCP address name", status); return -14; } pj_ansi_sprintf(url, "sip:alice@%s:%d;transport=tcp", pj_inet_ntoa(rem_addr.sin_addr), pj_ntohs(rem_addr.sin_port)); /* Acquire one TCP transport. */ status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_TCP, &rem_addr, sizeof(rem_addr), NULL, &tcp); if (status != PJ_SUCCESS || tcp == NULL) { app_perror(" Error: unable to acquire TCP transport", status); return -17; } /* After pjsip_endpt_acquire_transport, TCP transport must have * reference counter 1. */ if (pj_atomic_get(tcp->ref_cnt) != 1) return -20; /* Test basic transport attributes */ status = generic_transport_test(tcp); if (status != PJ_SUCCESS) return status; /* Check again that reference counter is 1. */ if (pj_atomic_get(tcp->ref_cnt) != 1) return -40; /* Load test */ if (transport_load_test(url) != 0) return -60; /* Basic transport's send/receive loopback test. */ for (i=0; i<SEND_RECV_LOOP; ++i) { status = transport_send_recv_test(PJSIP_TRANSPORT_TCP, tcp, url, &rtt[i]); if (status != 0) { pjsip_transport_dec_ref(tcp); flush_events(500); return -72; } } min_rtt = 0xFFFFFFF; for (i=0; i<SEND_RECV_LOOP; ++i) if (rtt[i] < min_rtt) min_rtt = rtt[i]; report_ival("tcp-rtt-usec", min_rtt, "usec", "Best TCP transport round trip time, in microseconds " "(time from sending request until response is received. " "Tests were performed on local machine only, and after " "TCP socket has been established by previous test)"); /* Multi-threaded round-trip test. */ status = transport_rt_test(PJSIP_TRANSPORT_TCP, tcp, url, &pkt_lost); if (status != 0) { pjsip_transport_dec_ref(tcp); return status; } if (pkt_lost != 0) PJ_LOG(3,(THIS_FILE, " note: %d packet(s) was lost", pkt_lost)); /* Check again that reference counter is still 1. */ if (pj_atomic_get(tcp->ref_cnt) != 1) return -80; /* Destroy this transport. */ pjsip_transport_dec_ref(tcp); /* Force destroy this transport. */ status = pjsip_transport_destroy(tcp); if (status != PJ_SUCCESS) return -90; /* Unregister factory */ status = pjsip_tpmgr_unregister_tpfactory(pjsip_endpt_get_tpmgr(endpt), tpfactory); if (status != PJ_SUCCESS) return -95; /* Flush events. */ PJ_LOG(3,(THIS_FILE, " Flushing events, 1 second...")); flush_events(1000); /* Done */ return 0; }