From f3ab456a17af1c89a6e3be4d20c5944853df1cb0 Mon Sep 17 00:00:00 2001 From: "David M. Lee" Date: Mon, 7 Jan 2013 14:24:28 -0600 Subject: Import pjproject-2.0.1 --- tests/automated/README.txt | 4 + tests/automated/configure.py | 354 +++++++++++++++ tests/automated/gnu-ipp.xml.template | 28 ++ tests/automated/gnu.xml.template | 29 ++ tests/automated/iphone.xml.template | 23 + tests/automated/msvc.xml.template | 24 + tests/automated/prepare.xml.template | 46 ++ tests/automated/run_continuous.py | 140 ++++++ tests/automated/run_scenario.py | 11 + tests/automated/symbian-aps.xml.template | 78 ++++ tests/automated/symbian-vas.xml.template | 79 ++++ tests/automated/symbian.xml.template | 20 + tests/automated/testvars.template | 33 ++ tests/cdash/README.TXT | 59 +++ tests/cdash/builder.py | 501 +++++++++++++++++++++ tests/cdash/cfg_gnu.py | 73 +++ tests/cdash/cfg_msvc.py | 82 ++++ tests/cdash/cfg_site_sample.py | 50 ++ tests/cdash/cfg_symbian.py | 86 ++++ tests/cdash/inc_test.py | 1 + tests/cdash/main.py | 42 ++ tests/cdash/starttest_sample.bat | 44 ++ tests/pjsua/README.TXT | 65 +++ tests/pjsua/config_site.py | 4 + tests/pjsua/inc_cfg.py | 107 +++++ tests/pjsua/inc_const.py | 64 +++ tests/pjsua/inc_sdp.py | 38 ++ tests/pjsua/inc_sip.py | 343 ++++++++++++++ tests/pjsua/mod_call.py | 226 ++++++++++ tests/pjsua/mod_media_playrec.py | 108 +++++ tests/pjsua/mod_pesq.py | 167 +++++++ tests/pjsua/mod_pres.py | 125 +++++ tests/pjsua/mod_recvfrom.py | 97 ++++ tests/pjsua/mod_run.py | 11 + tests/pjsua/mod_sendto.py | 53 +++ tests/pjsua/mod_sipp.py | 275 +++++++++++ tests/pjsua/run.py | 289 ++++++++++++ tests/pjsua/runall.py | 187 ++++++++ tests/pjsua/scripts-call/100_simplecall.py | 12 + tests/pjsua/scripts-call/150_srtp_0_1.py | 11 + tests/pjsua/scripts-call/150_srtp_0_3.py | 11 + tests/pjsua/scripts-call/150_srtp_1_0.py | 11 + tests/pjsua/scripts-call/150_srtp_1_1.py | 11 + tests/pjsua/scripts-call/150_srtp_1_2.py | 11 + tests/pjsua/scripts-call/150_srtp_1_3.py | 11 + tests/pjsua/scripts-call/150_srtp_2_1.py | 12 + tests/pjsua/scripts-call/150_srtp_2_2.py | 11 + tests/pjsua/scripts-call/150_srtp_2_3.py | 11 + tests/pjsua/scripts-call/150_srtp_3_0.py | 11 + tests/pjsua/scripts-call/150_srtp_3_1.py | 11 + tests/pjsua/scripts-call/150_srtp_3_2.py | 11 + tests/pjsua/scripts-call/150_srtp_3_3.py | 11 + tests/pjsua/scripts-call/200_tcp.py | 12 + tests/pjsua/scripts-call/300_ice_0_1.py | 12 + tests/pjsua/scripts-call/300_ice_1_0.py | 12 + tests/pjsua/scripts-call/300_ice_1_1.py | 12 + tests/pjsua/scripts-call/301_ice_public_a.py | 22 + tests/pjsua/scripts-call/301_ice_public_b.py | 25 + tests/pjsua/scripts-call/305_ice_comp_1_2.py | 12 + tests/pjsua/scripts-call/305_ice_comp_2_1.py | 12 + tests/pjsua/scripts-call/350_prack_a.py | 12 + tests/pjsua/scripts-call/350_prack_b.py | 12 + tests/pjsua/scripts-call/400_tel_uri.py | 12 + .../scripts-media-playrec/100_resample_lf_11_16.py | 11 + .../scripts-media-playrec/100_resample_lf_11_22.py | 11 + .../scripts-media-playrec/100_resample_lf_11_32.py | 11 + .../scripts-media-playrec/100_resample_lf_11_44.py | 11 + .../scripts-media-playrec/100_resample_lf_11_48.py | 11 + .../scripts-media-playrec/100_resample_lf_11_8.py | 11 + .../scripts-media-playrec/100_resample_lf_8_11.py | 11 + .../scripts-media-playrec/100_resample_lf_8_16.py | 11 + .../scripts-media-playrec/100_resample_lf_8_22.py | 11 + .../scripts-media-playrec/100_resample_lf_8_32.py | 11 + .../scripts-media-playrec/100_resample_lf_8_44.py | 11 + .../scripts-media-playrec/100_resample_lf_8_48.py | 11 + tests/pjsua/scripts-pesq/100_defaults.py | 19 + tests/pjsua/scripts-pesq/101_defaults.py | 18 + tests/pjsua/scripts-pesq/200_codec_g711a.py | 19 + tests/pjsua/scripts-pesq/200_codec_g711u.py | 19 + tests/pjsua/scripts-pesq/200_codec_g722.py | 19 + tests/pjsua/scripts-pesq/200_codec_gsm.py | 19 + tests/pjsua/scripts-pesq/200_codec_ilbc.py | 19 + tests/pjsua/scripts-pesq/200_codec_l16_16000.py | 19 + .../scripts-pesq/200_codec_l16_16000_stereo.py | 19 + tests/pjsua/scripts-pesq/200_codec_l16_8000.py | 19 + .../scripts-pesq/200_codec_l16_8000_stereo.py | 19 + tests/pjsua/scripts-pesq/200_codec_speex_16000.py | 19 + tests/pjsua/scripts-pesq/200_codec_speex_8000.py | 19 + tests/pjsua/scripts-pesq/201_codec_g711a.py | 17 + tests/pjsua/scripts-pesq/201_codec_g711u.py | 17 + tests/pjsua/scripts-pesq/201_codec_g722.py | 17 + tests/pjsua/scripts-pesq/201_codec_gsm.py | 17 + tests/pjsua/scripts-pesq/201_codec_ilbc.py | 17 + tests/pjsua/scripts-pesq/201_codec_l16_16000.py | 17 + .../scripts-pesq/201_codec_l16_16000_stereo.py | 17 + tests/pjsua/scripts-pesq/201_codec_l16_8000.py | 17 + .../scripts-pesq/201_codec_l16_8000_stereo.py | 17 + tests/pjsua/scripts-pesq/201_codec_speex_16000.py | 17 + tests/pjsua/scripts-pesq/201_codec_speex_8000.py | 17 + tests/pjsua/scripts-pres/100_peertopeer.py | 12 + tests/pjsua/scripts-pres/200_publish.py | 35 ++ tests/pjsua/scripts-recvfrom/100_simple.py | 16 + .../200_reg_good_enocredentiall.py | 15 + tests/pjsua/scripts-recvfrom/201_reg_good_ok.py | 23 + .../scripts-recvfrom/202_reg_good_ok_wildcard.py | 23 + .../scripts-recvfrom/203_reg_good_empty_realm.py | 31 ++ .../scripts-recvfrom/205_reg_good_no_realm.py | 16 + .../206_reg_good_efailedcredential.py | 26 ++ .../208_reg_good_retry_nonce_ok.py | 29 ++ .../scripts-recvfrom/209a_reg_handle_423_ok.py | 31 ++ .../209b_reg_handle_423_bad_min_expires1.py | 20 + .../209c_reg_handle_423_bad_min_expires2.py | 25 + .../scripts-recvfrom/215_reg_good_multi_ok.py | 28 ++ .../pjsua/scripts-recvfrom/220_reg_good_ims_ok.py | 26 ++ .../230_reg_bad_fail_stale_true.py | 41 ++ .../231_reg_bad_fail_stale_false_nonce_changed.py | 41 ++ .../pjsua/scripts-recvfrom/234_reg_bad_stale_ok.py | 41 ++ .../235_reg_good_tel_uri_enocredential.py | 15 + .../scripts-recvfrom/240_publish_scenarios.py | 51 +++ tests/pjsua/scripts-recvfrom/300_timer_good.py | 17 + .../301_timer_good_retry_after_422.py | 30 ++ .../400_inv_answered_with_less_media.py | 32 ++ tests/pjsua/scripts-run/100_simple.py | 13 + tests/pjsua/scripts-run/200_register.py | 20 + .../scripts-sendto/001_torture_4475_3_1_1_1.py | 52 +++ .../scripts-sendto/001_torture_4475_3_1_1_2.py | 25 + .../scripts-sendto/001_torture_4475_3_1_1_3.py | 35 ++ .../scripts-sendto/001_torture_4475_3_1_1_4.py | 25 + .../scripts-sendto/001_torture_4475_3_1_1_5.py | 25 + tests/pjsua/scripts-sendto/100_simplecall.py | 20 + tests/pjsua/scripts-sendto/110_tel_uri.py | 46 ++ .../scripts-sendto/120_sdp_with_video_dynamic_1.py | 28 ++ .../scripts-sendto/120_sdp_with_video_dynamic_2.py | 28 ++ .../scripts-sendto/121_sdp_with_video_static_1.py | 28 ++ .../scripts-sendto/121_sdp_with_video_static_2.py | 28 ++ .../122_sdp_with_unknown_dynamic_1.py | 27 ++ .../122_sdp_with_unknown_dynamic_2.py | 27 ++ .../123_sdp_with_unknown_static_1.py | 27 ++ .../123_sdp_with_unknown_static_2.py | 27 ++ ...24_sdp_with_unknown_static_unknown_transport.py | 27 ++ .../scripts-sendto/125_sdp_with_multi_audio_0.py | 29 ++ .../scripts-sendto/125_sdp_with_multi_audio_1.py | 27 ++ .../scripts-sendto/125_sdp_with_multi_audio_2.py | 27 ++ .../scripts-sendto/125_sdp_with_multi_audio_3.py | 28 ++ .../scripts-sendto/125_sdp_with_multi_audio_4.py | 27 ++ ...sdp_with_port_0_and_no_rtpmap_for_dynamic_pt.py | 26 ++ .../140_sdp_with_direction_attr_in_session_1.py | 28 ++ .../140_sdp_with_direction_attr_in_session_2.py | 30 ++ tests/pjsua/scripts-sendto/150_err_extension.py | 27 ++ tests/pjsua/scripts-sendto/151_err_sdp_video.py | 23 + tests/pjsua/scripts-sendto/152_err_sdp_no_media.py | 22 + .../153_err_sdp_unsupported_codec.py | 24 + .../pjsua/scripts-sendto/155_err_sdp_bad_syntax.py | 23 + .../scripts-sendto/156_err_sdp_bad_net_type.py | 27 ++ .../scripts-sendto/157_err_sdp_bad_addr_type.py | 27 ++ .../158_err_sdp_bad_transport_type.py | 27 ++ tests/pjsua/scripts-sendto/159_no_rport.py | 38 ++ tests/pjsua/scripts-sendto/159_no_rport_nit.py | 25 + .../scripts-sendto/160_err_duplicate_replaces.py | 23 + .../161_err_replaces_dlg_not_found.py | 23 + tests/pjsua/scripts-sendto/170_timer_required.py | 27 ++ .../scripts-sendto/171_timer_initiated_by_uas.py | 36 ++ .../172_timer_supported_but_not_used.py | 26 ++ .../scripts-sendto/173_timer_offer_no_refresher.py | 26 ++ .../173_timer_offer_refresher_uac.py | 26 ++ .../173_timer_offer_refresher_uas.py | 26 ++ .../pjsua/scripts-sendto/174_timer_se_too_small.py | 26 ++ tests/pjsua/scripts-sendto/200_ice_no_ice.py | 26 ++ tests/pjsua/scripts-sendto/200_ice_success_1.py | 31 ++ tests/pjsua/scripts-sendto/200_ice_success_2.py | 36 ++ tests/pjsua/scripts-sendto/200_ice_success_3.py | 35 ++ tests/pjsua/scripts-sendto/200_ice_success_4.py | 35 ++ tests/pjsua/scripts-sendto/201_ice_mismatch_1.py | 29 ++ tests/pjsua/scripts-sendto/201_ice_mismatch_2.py | 31 ++ tests/pjsua/scripts-sendto/201_ice_mismatch_3.py | 30 ++ .../scripts-sendto/251_multipart_ok_simple.py | 38 ++ .../scripts-sendto/252_multipart_ok_clutter.py | 47 ++ .../scripts-sendto/260_multipart_err_no_sdp.py | 38 ++ .../300_srtp_crypto_case_insensitive.py | 27 ++ .../300_srtp_duplicated_crypto_tag.py | 27 ++ .../300_srtp_invalid_crypto_tag_non_numeric.py | 27 ++ .../300_srtp_receive_crypto_tag_zero.py | 26 ++ .../scripts-sendto/300_srtp_receive_no_key_1.py | 26 ++ .../scripts-sendto/300_srtp_receive_no_key_2.py | 26 ++ .../scripts-sendto/300_srtp_receive_no_key_3.py | 26 ++ tests/pjsua/scripts-sendto/301_srtp0_recv_avp.py | 28 ++ tests/pjsua/scripts-sendto/301_srtp0_recv_savp.py | 28 ++ tests/pjsua/scripts-sendto/310_srtp1_no_crypto.py | 26 ++ tests/pjsua/scripts-sendto/311_srtp1_recv_avp.py | 28 ++ tests/pjsua/scripts-sendto/312_srtp1_recv_savp.py | 28 ++ .../scripts-sendto/313_srtp1_unsupported_crypto.py | 26 ++ tests/pjsua/scripts-sendto/320_srtp2_no_crypto.py | 26 ++ .../320_srtp_with_unknown_media_1.py | 28 ++ .../320_srtp_with_unknown_media_2.py | 28 ++ .../320_srtp_with_unknown_transport_1.py | 27 ++ .../320_srtp_with_unknown_transport_2.py | 27 ++ tests/pjsua/scripts-sendto/321_srtp2_recv_avp.py | 28 ++ tests/pjsua/scripts-sendto/322_srtp2_recv_savp.py | 28 ++ .../323_srtp2_receive_too_long_key.py | 25 + .../scripts-sendto/323_srtp2_unsupported_crypto.py | 26 ++ .../scripts-sendto/330_srtp_prefer_rtp_savp.py | 30 ++ .../scripts-sendto/331_srtp_prefer_rtp_avp.py | 29 ++ tests/pjsua/scripts-sendto/360_non_sip_uri.py | 27 ++ tests/pjsua/scripts-sendto/361_non_sip_uri.py | 26 ++ tests/pjsua/scripts-sendto/362_non_sip_uri.py | 27 ++ .../scripts-sendto/363_non_sip_uri_subscribe.py | 31 ++ .../scripts-sendto/364_non_sip_uri_subscribe.py | 30 ++ .../scripts-sendto/400_fmtp_g7221_with_bitrate.py | 34 ++ .../401_fmtp_g7221_with_bitrate_24000.py | 35 ++ .../401_fmtp_g7221_with_bitrate_32000.py | 35 ++ .../410_fmtp_amrnb_offer_octet_align.py | 32 ++ .../411_fmtp_amrnb_offer_band_eff.py | 31 ++ .../412_fmtp_amrnb_offer_band_eff2.py | 32 ++ .../500_pres_subscribe_with_bad_event.py | 28 ++ tests/pjsua/scripts-sendto/999_asterisk_err.py | 45 ++ tests/pjsua/scripts-sendto/999_message_no_body.py | 24 + tests/pjsua/scripts-sipp/strict-route.py | 9 + tests/pjsua/scripts-sipp/strict-route.xml | 161 +++++++ tests/pjsua/scripts-sipp/transfer-attended.py | 52 +++ tests/pjsua/scripts-sipp/transfer-attended.xml | 26 ++ tests/pjsua/scripts-sipp/transfer-unattended.py | 30 ++ tests/pjsua/scripts-sipp/transfer-unattended.xml | 26 ++ tests/pjsua/scripts-sipp/uac-bad-ack.xml | 132 ++++++ .../scripts-sipp/uac-inv-and-ack-without-sdp.xml | 91 ++++ .../scripts-sipp/uac-inv-multiple-require.xml | 67 +++ ...uac-inv-two-media-but-one-disabled-no-rtpmap.py | 7 + ...ac-inv-two-media-but-one-disabled-no-rtpmap.xml | 97 ++++ tests/pjsua/scripts-sipp/uac-inv-without-sdp.py | 11 + tests/pjsua/scripts-sipp/uac-inv-without-sdp.xml | 110 +++++ tests/pjsua/scripts-sipp/uac-message-no-body.xml | 32 ++ tests/pjsua/scripts-sipp/uac-options.xml | 54 +++ .../scripts-sipp/uac-reinvite-bad-via-branch.xml | 173 +++++++ .../scripts-sipp/uac-reinvite-port-0-bad-sdp.xml | 207 +++++++++ tests/pjsua/scripts-sipp/uac-subscribe.xml | 113 +++++ tests/pjsua/scripts-sipp/uac-ticket-1148.py | 7 + tests/pjsua/scripts-sipp/uac-ticket-1148.xml | 98 ++++ .../pjsua/scripts-sipp/uas-422-then-200-bad-se.xml | 118 +++++ ...uas-answer-180-multiple-fmts-support-update.xml | 168 +++++++ .../scripts-sipp/uas-answer-180-multiple-fmts.xml | 171 +++++++ .../uas-answer-200-inv-without-sdp.xml | 80 ++++ ...uas-answer-200-multiple-fmts-support-update.xml | 138 ++++++ .../scripts-sipp/uas-answer-200-multiple-fmts.xml | 138 ++++++ .../uas-answer-200-reinvite-without-sdp.py | 7 + .../uas-answer-200-reinvite-without-sdp.xml | 86 ++++ .../uas-answer-200-update-without-sdp.py | 7 + .../uas-answer-200-update-without-sdp.xml | 83 ++++ tests/pjsua/scripts-sipp/uas-auth.py | 7 + tests/pjsua/scripts-sipp/uas-auth.xml | 64 +++ tests/pjsua/scripts-sipp/uas-cancel-no-final.py | 7 + tests/pjsua/scripts-sipp/uas-cancel-no-final.xml | 62 +++ tests/pjsua/scripts-sipp/uas-early-bye.xml | 68 +++ tests/pjsua/scripts-sipp/uas-forked-100rel.xml | 225 +++++++++ tests/pjsua/scripts-sipp/uas-forked-200.xml | 128 ++++++ .../scripts-sipp/uas-inv-answered-with-srtp.xml | 77 ++++ .../scripts-sipp/uas-inv_401_retry_after_100.xml | 106 +++++ tests/pjsua/scripts-sipp/uas-mwi-0.py | 7 + tests/pjsua/scripts-sipp/uas-mwi-0.xml | 79 ++++ tests/pjsua/scripts-sipp/uas-mwi.py | 7 + tests/pjsua/scripts-sipp/uas-mwi.xml | 105 +++++ tests/pjsua/scripts-sipp/uas-prack_fork.xml | 130 ++++++ .../uas-reinv-and-ack-same-branch-without-sdp.xml | 118 +++++ .../scripts-sipp/uas-reinv-and-ack-without-sdp.xml | 118 +++++ tests/pjsua/scripts-sipp/uas-reinv-glare.py | 7 + tests/pjsua/scripts-sipp/uas-reinv-glare.xml | 153 +++++++ tests/pjsua/scripts-sipp/uas-reinv-no-media.xml | 116 +++++ .../scripts-sipp/uas-subscribe-late-notify.py | 11 + .../scripts-sipp/uas-subscribe-late-notify.xml | 152 +++++++ .../scripts-sipp/uas-subscribe-multipart-notify.py | 11 + .../uas-subscribe-multipart-notify.xml | 119 +++++ .../scripts-sipp/uas-subscribe-notify-terminate.py | 10 + .../uas-subscribe-notify-terminate.xml | 108 +++++ .../scripts-sipp/uas-subscribe-refresh-481.py | 11 + .../scripts-sipp/uas-subscribe-refresh-481.xml | 109 +++++ .../scripts-sipp/uas-subscribe-terminated-retry.py | 11 + .../uas-subscribe-terminated-retry.xml | 120 +++++ tests/pjsua/scripts-sipp/uas-template.xml | 84 ++++ tests/pjsua/scripts-sipp/uas-timer-reinvite.xml | 108 +++++ tests/pjsua/scripts-sipp/uas-timer-update.xml | 126 ++++++ tests/pjsua/tools/Makefile | 21 + tests/pjsua/tools/cmp_wav.c | 262 +++++++++++ tests/pjsua/wavs/.keep | 0 281 files changed, 13508 insertions(+) create mode 100644 tests/automated/README.txt create mode 100755 tests/automated/configure.py create mode 100644 tests/automated/gnu-ipp.xml.template create mode 100644 tests/automated/gnu.xml.template create mode 100644 tests/automated/iphone.xml.template create mode 100644 tests/automated/msvc.xml.template create mode 100644 tests/automated/prepare.xml.template create mode 100755 tests/automated/run_continuous.py create mode 100644 tests/automated/run_scenario.py create mode 100644 tests/automated/symbian-aps.xml.template create mode 100644 tests/automated/symbian-vas.xml.template create mode 100644 tests/automated/symbian.xml.template create mode 100644 tests/automated/testvars.template create mode 100644 tests/cdash/README.TXT create mode 100644 tests/cdash/builder.py create mode 100644 tests/cdash/cfg_gnu.py create mode 100644 tests/cdash/cfg_msvc.py create mode 100644 tests/cdash/cfg_site_sample.py create mode 100644 tests/cdash/cfg_symbian.py create mode 100644 tests/cdash/inc_test.py create mode 100644 tests/cdash/main.py create mode 100644 tests/cdash/starttest_sample.bat create mode 100644 tests/pjsua/README.TXT create mode 100644 tests/pjsua/config_site.py create mode 100644 tests/pjsua/inc_cfg.py create mode 100644 tests/pjsua/inc_const.py create mode 100644 tests/pjsua/inc_sdp.py create mode 100644 tests/pjsua/inc_sip.py create mode 100644 tests/pjsua/mod_call.py create mode 100644 tests/pjsua/mod_media_playrec.py create mode 100644 tests/pjsua/mod_pesq.py create mode 100644 tests/pjsua/mod_pres.py create mode 100644 tests/pjsua/mod_recvfrom.py create mode 100644 tests/pjsua/mod_run.py create mode 100644 tests/pjsua/mod_sendto.py create mode 100644 tests/pjsua/mod_sipp.py create mode 100644 tests/pjsua/run.py create mode 100644 tests/pjsua/runall.py create mode 100644 tests/pjsua/scripts-call/100_simplecall.py create mode 100644 tests/pjsua/scripts-call/150_srtp_0_1.py create mode 100644 tests/pjsua/scripts-call/150_srtp_0_3.py create mode 100644 tests/pjsua/scripts-call/150_srtp_1_0.py create mode 100644 tests/pjsua/scripts-call/150_srtp_1_1.py create mode 100644 tests/pjsua/scripts-call/150_srtp_1_2.py create mode 100644 tests/pjsua/scripts-call/150_srtp_1_3.py create mode 100644 tests/pjsua/scripts-call/150_srtp_2_1.py create mode 100644 tests/pjsua/scripts-call/150_srtp_2_2.py create mode 100644 tests/pjsua/scripts-call/150_srtp_2_3.py create mode 100644 tests/pjsua/scripts-call/150_srtp_3_0.py create mode 100644 tests/pjsua/scripts-call/150_srtp_3_1.py create mode 100644 tests/pjsua/scripts-call/150_srtp_3_2.py create mode 100644 tests/pjsua/scripts-call/150_srtp_3_3.py create mode 100644 tests/pjsua/scripts-call/200_tcp.py create mode 100644 tests/pjsua/scripts-call/300_ice_0_1.py create mode 100644 tests/pjsua/scripts-call/300_ice_1_0.py create mode 100644 tests/pjsua/scripts-call/300_ice_1_1.py create mode 100644 tests/pjsua/scripts-call/301_ice_public_a.py create mode 100644 tests/pjsua/scripts-call/301_ice_public_b.py create mode 100644 tests/pjsua/scripts-call/305_ice_comp_1_2.py create mode 100644 tests/pjsua/scripts-call/305_ice_comp_2_1.py create mode 100644 tests/pjsua/scripts-call/350_prack_a.py create mode 100644 tests/pjsua/scripts-call/350_prack_b.py create mode 100644 tests/pjsua/scripts-call/400_tel_uri.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_11_16.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_11_22.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_11_32.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_11_44.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_11_48.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_11_8.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_8_11.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_8_16.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_8_22.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_8_32.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_8_44.py create mode 100644 tests/pjsua/scripts-media-playrec/100_resample_lf_8_48.py create mode 100644 tests/pjsua/scripts-pesq/100_defaults.py create mode 100644 tests/pjsua/scripts-pesq/101_defaults.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_g711a.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_g711u.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_g722.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_gsm.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_ilbc.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_l16_16000.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_l16_16000_stereo.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_l16_8000.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_l16_8000_stereo.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_speex_16000.py create mode 100644 tests/pjsua/scripts-pesq/200_codec_speex_8000.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_g711a.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_g711u.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_g722.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_gsm.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_ilbc.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_l16_16000.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_l16_16000_stereo.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_l16_8000.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_l16_8000_stereo.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_speex_16000.py create mode 100644 tests/pjsua/scripts-pesq/201_codec_speex_8000.py create mode 100644 tests/pjsua/scripts-pres/100_peertopeer.py create mode 100644 tests/pjsua/scripts-pres/200_publish.py create mode 100644 tests/pjsua/scripts-recvfrom/100_simple.py create mode 100644 tests/pjsua/scripts-recvfrom/200_reg_good_enocredentiall.py create mode 100644 tests/pjsua/scripts-recvfrom/201_reg_good_ok.py create mode 100644 tests/pjsua/scripts-recvfrom/202_reg_good_ok_wildcard.py create mode 100644 tests/pjsua/scripts-recvfrom/203_reg_good_empty_realm.py create mode 100644 tests/pjsua/scripts-recvfrom/205_reg_good_no_realm.py create mode 100644 tests/pjsua/scripts-recvfrom/206_reg_good_efailedcredential.py create mode 100644 tests/pjsua/scripts-recvfrom/208_reg_good_retry_nonce_ok.py create mode 100644 tests/pjsua/scripts-recvfrom/209a_reg_handle_423_ok.py create mode 100644 tests/pjsua/scripts-recvfrom/209b_reg_handle_423_bad_min_expires1.py create mode 100644 tests/pjsua/scripts-recvfrom/209c_reg_handle_423_bad_min_expires2.py create mode 100644 tests/pjsua/scripts-recvfrom/215_reg_good_multi_ok.py create mode 100644 tests/pjsua/scripts-recvfrom/220_reg_good_ims_ok.py create mode 100644 tests/pjsua/scripts-recvfrom/230_reg_bad_fail_stale_true.py create mode 100644 tests/pjsua/scripts-recvfrom/231_reg_bad_fail_stale_false_nonce_changed.py create mode 100644 tests/pjsua/scripts-recvfrom/234_reg_bad_stale_ok.py create mode 100644 tests/pjsua/scripts-recvfrom/235_reg_good_tel_uri_enocredential.py create mode 100644 tests/pjsua/scripts-recvfrom/240_publish_scenarios.py create mode 100644 tests/pjsua/scripts-recvfrom/300_timer_good.py create mode 100644 tests/pjsua/scripts-recvfrom/301_timer_good_retry_after_422.py create mode 100644 tests/pjsua/scripts-recvfrom/400_inv_answered_with_less_media.py create mode 100644 tests/pjsua/scripts-run/100_simple.py create mode 100644 tests/pjsua/scripts-run/200_register.py create mode 100644 tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py create mode 100644 tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py create mode 100644 tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py create mode 100644 tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py create mode 100644 tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py create mode 100644 tests/pjsua/scripts-sendto/100_simplecall.py create mode 100644 tests/pjsua/scripts-sendto/110_tel_uri.py create mode 100644 tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_1.py create mode 100644 tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_2.py create mode 100644 tests/pjsua/scripts-sendto/121_sdp_with_video_static_1.py create mode 100644 tests/pjsua/scripts-sendto/121_sdp_with_video_static_2.py create mode 100644 tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_1.py create mode 100644 tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_2.py create mode 100644 tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_1.py create mode 100644 tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_2.py create mode 100644 tests/pjsua/scripts-sendto/124_sdp_with_unknown_static_unknown_transport.py create mode 100644 tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_0.py create mode 100644 tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_1.py create mode 100644 tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_2.py create mode 100644 tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_3.py create mode 100644 tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_4.py create mode 100644 tests/pjsua/scripts-sendto/126_sdp_with_port_0_and_no_rtpmap_for_dynamic_pt.py create mode 100644 tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_1.py create mode 100644 tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_2.py create mode 100644 tests/pjsua/scripts-sendto/150_err_extension.py create mode 100644 tests/pjsua/scripts-sendto/151_err_sdp_video.py create mode 100644 tests/pjsua/scripts-sendto/152_err_sdp_no_media.py create mode 100644 tests/pjsua/scripts-sendto/153_err_sdp_unsupported_codec.py create mode 100644 tests/pjsua/scripts-sendto/155_err_sdp_bad_syntax.py create mode 100644 tests/pjsua/scripts-sendto/156_err_sdp_bad_net_type.py create mode 100644 tests/pjsua/scripts-sendto/157_err_sdp_bad_addr_type.py create mode 100644 tests/pjsua/scripts-sendto/158_err_sdp_bad_transport_type.py create mode 100644 tests/pjsua/scripts-sendto/159_no_rport.py create mode 100644 tests/pjsua/scripts-sendto/159_no_rport_nit.py create mode 100644 tests/pjsua/scripts-sendto/160_err_duplicate_replaces.py create mode 100644 tests/pjsua/scripts-sendto/161_err_replaces_dlg_not_found.py create mode 100644 tests/pjsua/scripts-sendto/170_timer_required.py create mode 100644 tests/pjsua/scripts-sendto/171_timer_initiated_by_uas.py create mode 100644 tests/pjsua/scripts-sendto/172_timer_supported_but_not_used.py create mode 100644 tests/pjsua/scripts-sendto/173_timer_offer_no_refresher.py create mode 100644 tests/pjsua/scripts-sendto/173_timer_offer_refresher_uac.py create mode 100644 tests/pjsua/scripts-sendto/173_timer_offer_refresher_uas.py create mode 100644 tests/pjsua/scripts-sendto/174_timer_se_too_small.py create mode 100644 tests/pjsua/scripts-sendto/200_ice_no_ice.py create mode 100644 tests/pjsua/scripts-sendto/200_ice_success_1.py create mode 100644 tests/pjsua/scripts-sendto/200_ice_success_2.py create mode 100644 tests/pjsua/scripts-sendto/200_ice_success_3.py create mode 100644 tests/pjsua/scripts-sendto/200_ice_success_4.py create mode 100644 tests/pjsua/scripts-sendto/201_ice_mismatch_1.py create mode 100644 tests/pjsua/scripts-sendto/201_ice_mismatch_2.py create mode 100644 tests/pjsua/scripts-sendto/201_ice_mismatch_3.py create mode 100644 tests/pjsua/scripts-sendto/251_multipart_ok_simple.py create mode 100644 tests/pjsua/scripts-sendto/252_multipart_ok_clutter.py create mode 100644 tests/pjsua/scripts-sendto/260_multipart_err_no_sdp.py create mode 100644 tests/pjsua/scripts-sendto/300_srtp_crypto_case_insensitive.py create mode 100644 tests/pjsua/scripts-sendto/300_srtp_duplicated_crypto_tag.py create mode 100644 tests/pjsua/scripts-sendto/300_srtp_invalid_crypto_tag_non_numeric.py create mode 100644 tests/pjsua/scripts-sendto/300_srtp_receive_crypto_tag_zero.py create mode 100644 tests/pjsua/scripts-sendto/300_srtp_receive_no_key_1.py create mode 100644 tests/pjsua/scripts-sendto/300_srtp_receive_no_key_2.py create mode 100644 tests/pjsua/scripts-sendto/300_srtp_receive_no_key_3.py create mode 100644 tests/pjsua/scripts-sendto/301_srtp0_recv_avp.py create mode 100644 tests/pjsua/scripts-sendto/301_srtp0_recv_savp.py create mode 100644 tests/pjsua/scripts-sendto/310_srtp1_no_crypto.py create mode 100644 tests/pjsua/scripts-sendto/311_srtp1_recv_avp.py create mode 100644 tests/pjsua/scripts-sendto/312_srtp1_recv_savp.py create mode 100644 tests/pjsua/scripts-sendto/313_srtp1_unsupported_crypto.py create mode 100644 tests/pjsua/scripts-sendto/320_srtp2_no_crypto.py create mode 100644 tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_1.py create mode 100644 tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_2.py create mode 100644 tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_1.py create mode 100644 tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_2.py create mode 100644 tests/pjsua/scripts-sendto/321_srtp2_recv_avp.py create mode 100644 tests/pjsua/scripts-sendto/322_srtp2_recv_savp.py create mode 100644 tests/pjsua/scripts-sendto/323_srtp2_receive_too_long_key.py create mode 100644 tests/pjsua/scripts-sendto/323_srtp2_unsupported_crypto.py create mode 100644 tests/pjsua/scripts-sendto/330_srtp_prefer_rtp_savp.py create mode 100644 tests/pjsua/scripts-sendto/331_srtp_prefer_rtp_avp.py create mode 100644 tests/pjsua/scripts-sendto/360_non_sip_uri.py create mode 100644 tests/pjsua/scripts-sendto/361_non_sip_uri.py create mode 100644 tests/pjsua/scripts-sendto/362_non_sip_uri.py create mode 100644 tests/pjsua/scripts-sendto/363_non_sip_uri_subscribe.py create mode 100644 tests/pjsua/scripts-sendto/364_non_sip_uri_subscribe.py create mode 100644 tests/pjsua/scripts-sendto/400_fmtp_g7221_with_bitrate.py create mode 100644 tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_24000.py create mode 100644 tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_32000.py create mode 100644 tests/pjsua/scripts-sendto/410_fmtp_amrnb_offer_octet_align.py create mode 100644 tests/pjsua/scripts-sendto/411_fmtp_amrnb_offer_band_eff.py create mode 100644 tests/pjsua/scripts-sendto/412_fmtp_amrnb_offer_band_eff2.py create mode 100644 tests/pjsua/scripts-sendto/500_pres_subscribe_with_bad_event.py create mode 100644 tests/pjsua/scripts-sendto/999_asterisk_err.py create mode 100644 tests/pjsua/scripts-sendto/999_message_no_body.py create mode 100644 tests/pjsua/scripts-sipp/strict-route.py create mode 100644 tests/pjsua/scripts-sipp/strict-route.xml create mode 100644 tests/pjsua/scripts-sipp/transfer-attended.py create mode 100644 tests/pjsua/scripts-sipp/transfer-attended.xml create mode 100644 tests/pjsua/scripts-sipp/transfer-unattended.py create mode 100644 tests/pjsua/scripts-sipp/transfer-unattended.xml create mode 100644 tests/pjsua/scripts-sipp/uac-bad-ack.xml create mode 100644 tests/pjsua/scripts-sipp/uac-inv-and-ack-without-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml create mode 100644 tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.py create mode 100644 tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.xml create mode 100644 tests/pjsua/scripts-sipp/uac-inv-without-sdp.py create mode 100644 tests/pjsua/scripts-sipp/uac-inv-without-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uac-message-no-body.xml create mode 100644 tests/pjsua/scripts-sipp/uac-options.xml create mode 100644 tests/pjsua/scripts-sipp/uac-reinvite-bad-via-branch.xml create mode 100644 tests/pjsua/scripts-sipp/uac-reinvite-port-0-bad-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uac-subscribe.xml create mode 100644 tests/pjsua/scripts-sipp/uac-ticket-1148.py create mode 100644 tests/pjsua/scripts-sipp/uac-ticket-1148.xml create mode 100644 tests/pjsua/scripts-sipp/uas-422-then-200-bad-se.xml create mode 100644 tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts-support-update.xml create mode 100644 tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts.xml create mode 100644 tests/pjsua/scripts-sipp/uas-answer-200-inv-without-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts-support-update.xml create mode 100644 tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts.xml create mode 100644 tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.py create mode 100644 tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.py create mode 100644 tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uas-auth.py create mode 100644 tests/pjsua/scripts-sipp/uas-auth.xml create mode 100644 tests/pjsua/scripts-sipp/uas-cancel-no-final.py create mode 100644 tests/pjsua/scripts-sipp/uas-cancel-no-final.xml create mode 100644 tests/pjsua/scripts-sipp/uas-early-bye.xml create mode 100644 tests/pjsua/scripts-sipp/uas-forked-100rel.xml create mode 100644 tests/pjsua/scripts-sipp/uas-forked-200.xml create mode 100644 tests/pjsua/scripts-sipp/uas-inv-answered-with-srtp.xml create mode 100644 tests/pjsua/scripts-sipp/uas-inv_401_retry_after_100.xml create mode 100644 tests/pjsua/scripts-sipp/uas-mwi-0.py create mode 100644 tests/pjsua/scripts-sipp/uas-mwi-0.xml create mode 100644 tests/pjsua/scripts-sipp/uas-mwi.py create mode 100644 tests/pjsua/scripts-sipp/uas-mwi.xml create mode 100644 tests/pjsua/scripts-sipp/uas-prack_fork.xml create mode 100644 tests/pjsua/scripts-sipp/uas-reinv-and-ack-same-branch-without-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uas-reinv-and-ack-without-sdp.xml create mode 100644 tests/pjsua/scripts-sipp/uas-reinv-glare.py create mode 100644 tests/pjsua/scripts-sipp/uas-reinv-glare.xml create mode 100644 tests/pjsua/scripts-sipp/uas-reinv-no-media.xml create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-late-notify.py create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-late-notify.xml create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.py create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.py create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.xml create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.py create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.xml create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.py create mode 100644 tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.xml create mode 100644 tests/pjsua/scripts-sipp/uas-template.xml create mode 100644 tests/pjsua/scripts-sipp/uas-timer-reinvite.xml create mode 100644 tests/pjsua/scripts-sipp/uas-timer-update.xml create mode 100644 tests/pjsua/tools/Makefile create mode 100644 tests/pjsua/tools/cmp_wav.c create mode 100644 tests/pjsua/wavs/.keep (limited to 'tests') diff --git a/tests/automated/README.txt b/tests/automated/README.txt new file mode 100644 index 0000000..1d1cb81 --- /dev/null +++ b/tests/automated/README.txt @@ -0,0 +1,4 @@ +This directory contains files to run automated/unattended tests for PJSIP. + +See https://trac.pjsip.org/repos/wiki/AutomatedTesting for more info. + diff --git a/tests/automated/configure.py b/tests/automated/configure.py new file mode 100755 index 0000000..d277471 --- /dev/null +++ b/tests/automated/configure.py @@ -0,0 +1,354 @@ +#!/usr/bin/python + +import optparse +import os +import platform +import socket +import subprocess +import sys + +PROG = "r" + "$Rev: 17 $".strip("$ ").replace("Rev: ", "") +PYTHON = os.path.basename(sys.executable) +build_type = "" +vs_target = "" +s60_target = "" +no_test = False +no_pjsua_test = False + +# +# Get gcc version +# +def gcc_version(gcc): + proc = subprocess.Popen(gcc + " -v", stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, shell=True) + ver = "" + while True: + s = proc.stdout.readline() + if not s: + break + if s.find("gcc version") >= 0: + ver = s.split(None, 3)[2] + break + proc.wait() + return "gcc-" + ver + +# +# Get Visual Studio info +# +class VSVersion: + def __init__(self): + self.version = "8" + self.release = "2005" + + proc = subprocess.Popen("cl", stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + while True: + s = proc.stdout.readline() + if s=="": + break + pos = s.find("Version") + if pos > 0: + proc.wait() + s = s[pos+8:] + ver = s.split(None, 1)[0] + major = ver[0:2] + if major=="12": + self.version = "6" + self.release = "98" + break + elif major=="13": + self.version = "7" + self.release = "2003" + break + elif major=="14": + self.version = "8" + self.release = "2005" + break + elif major=="15": + self.version = "9" + self.release = "2008" + break + elif major=="16": + self.version = "10" + self.release = "2010" + break + else: + self.version = "11" + self.release = "2012" + break + proc.wait() + self.vs_version = "vs" + self.version + self.vs_release = "vs" + self.release + + +# +# Get S60 SDK info +# +class S60SDK: + def __init__(self): + self.epocroot = "" + self.sdk = "" + self.device = "" + + # Check that EPOCROOT is set + if not "EPOCROOT" in os.environ: + sys.stderr.write("Error: EPOCROOT environment variable is not set\n") + sys.exit(1) + epocroot = os.environ["EPOCROOT"] + # EPOCROOT must have trailing backslash + if epocroot[-1] != "\\": + epocroot = epocroot + "\\" + os.environ["EPOCROOT"] = epocroot + self.epocroot = epocroot + self.sdk = sdk1 = epocroot.split("\\")[-2] + self.device = "@" + self.sdk + ":com.nokia.s60" + + # Check that correct device is set + proc = subprocess.Popen("devices", stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, shell=True) + sdk2 = "" + while True: + line = proc.stdout.readline() + if line.find("- default") > 0: + sdk2 = line.split(":",1)[0] + break + proc.wait() + + if sdk1 != sdk2: + sys.stderr.write("Error: default SDK in device doesn't match EPOCROOT\n") + sys.stderr.write("Default device SDK = '" + sdk2 + "'\n") + sys.stderr.write("EPOCROOT SDK = '" + sdk1 + "'\n") + sys.exit(1) + + self.name = sdk2.replace("_", "-") + + + +def replace_vars(text): + global vs_target, s60_target, build_type, no_test, no_pjsua_test + suffix = "" + + os_info = platform.system() + platform.release() + "-" + platform.machine() + + # osinfo + s60sdk_var = None + if build_type == "s60": + s60sdk_var = S60SDK() + os_info = s60sdk_var.name + elif platform.system().lower() == "windows" or platform.system().lower() == "microsoft": + if platform.system().lower() == "microsoft": + os_info = platform.release() + "-" + platform.version() + "-" + platform.win32_ver()[2] + elif platform.system().lower() == "linux": + os_info = "-" + "-".join(platform.linux_distribution()[0:2]) + + # vs_target + if not vs_target and text.find("$(VSTARGET)") >= 0: + if build_type != "vs": + sys.stderr.write("Warning: $(VSTARGET) only valid for Visual Studio\n") + print "Enter Visual Studio vs_target name (e.g. Release, Debug) [Release]: ", + vs_target = sys.stdin.readline().replace("\n", "").replace("\r", "") + if not vs_target: + vs_target = "Release" + + # s60_target + if not s60_target and text.find("$(S60TARGET)") >= 0: + if build_type != "s60": + sys.stderr.write("Warning: $(S60TARGET) only valid for S60\n") + print "Enter S60 target name (e.g. \"gcce urel\") [gcce urel]: ", + s60_target = sys.stdin.readline().replace("\n", "").replace("\r", "") + if not s60_target: + s60_target = "gcce urel" + + # Suffix + if build_type == "vs": + suffix = "i386-Win32-vc8-" + vs_target + elif build_type == "s60": + suffix = s60sdk_var.name + "-" + s60_target.replace(" ", "-") + elif build_type == "gnu": + proc = subprocess.Popen("sh config.guess", cwd="../..", + shell=True, stdout=subprocess.PIPE) + suffix = proc.stdout.readline().rstrip(" \r\n") + else: + sys.stderr.write("Error: unsupported build type '" + build_type + "'\n") + sys.exit(1) + + while True: + if text.find("$(PJSUA-TESTS)") >= 0: + if no_test==False and no_pjsua_test==False: + # Determine pjsua exe to use + exe = "../../pjsip-apps/bin/pjsua-" + suffix + proc = subprocess.Popen(PYTHON + " runall.py --list-xml -e " + exe, + cwd="../pjsua", + shell=True, stdout=subprocess.PIPE) + content = proc.stdout.read() + else: + content = "" + text = text.replace("$(PJSUA-TESTS)", content) + elif text.find("$(GCC)") >= 0: + text = text.replace("$(GCC)", gcc_version("gcc")) + elif text.find("$(VS)") >= 0: + vsver = VSVersion() + text = text.replace("$(VS)", VSVersion().vs_release) + elif text.find("$(VSTARGET)") >= 0: + text = text.replace("$(VSTARGET)", vs_target) + elif text.find("$(S60TARGET)") >= 0: + text = text.replace("$(S60TARGET)", s60_target) + elif text.find("$(S60TARGETNAME)") >= 0: + text = text.replace("$(S60TARGETNAME)", s60_target.replace(" ", "-")) + elif text.find("$(S60DEVICE)") >= 0: + text = text.replace("$(S60DEVICE)", s60sdk_var.device) + elif text.find("$(EPOCROOT)") >= 0: + text = text.replace("$(EPOCROOT)", s60sdk_var.epocroot) + elif text.find("$(DISABLED)") >= 0: + text = text.replace("$(DISABLED)", "0") + elif text.find("$(IPPROOT)") >= 0: + if not os.environ.has_key("IPPROOT"): + sys.stderr.write("Error: environment variable IPPROOT is needed but not set\n") + sys.exit(1) + text = text.replace("$(IPPROOT)", os.environ["IPPROOT"]) + elif text.find("$(IPPSAMPLES)") >= 0: + if not os.environ.has_key("IPPSAMPLES"): + sys.stderr.write("Error: environment variable IPPSAMPLES is needed but not set\n") + sys.exit(1) + text = text.replace("$(IPPSAMPLES)", os.environ["IPPSAMPLES"]) + elif text.find("$(IPPARCH)") >= 0: + if not os.environ.has_key("IPPARCH"): + text = text.replace("$(IPPARCH)", "") + else: + text = text.replace("$(IPPARCH)", os.environ["IPPARCH"]) + elif text.find("$(OS)") >= 0: + text = text.replace("$(OS)", os_info) + elif text.find("$(SUFFIX)") >= 0: + text = text.replace("$(SUFFIX)", suffix) + elif text.find("$(HOSTNAME)") >= 0: + text = text.replace("$(HOSTNAME)", socket.gethostname()) + elif text.find("$(PJDIR)") >= 0: + wdir = os.path.join(os.getcwd(), "../..") + wdir = os.path.normpath(wdir) + text = text.replace("$(PJDIR)", wdir) + elif text.find("$(NOP)") >= 0: + if platform.system().lower() == "windows" or platform.system().lower() == "microsoft": + cmd = "CMD /C echo Success" + else: + cmd = "echo Success" + text = text.replace("$(NOP)", cmd) + elif text.find("$(NOTEST)") >= 0: + if no_test: + str = '"1"' + else: + str = '"0"' + text = text.replace("$(NOTEST)", str) + else: + break + return text + + +def main(args): + global vs_target, s60_target, build_type, no_test, no_pjsua_test + output = sys.stdout + usage = """Usage: configure.py [OPTIONS] scenario_template_file + +Where OPTIONS: + -o FILE Output to file, otherwise to stdout. + -t TYPE Specify build type. If not specified, it will be + asked if necessary. Values are: + vs: Visual Studio + gnu: Makefile based + s60: Symbian S60 + -vstarget TARGETNAME Specify Visual Studio target name if build type is set + to vs. If not specified then it will be asked. + Sample target names: + - Debug + - Release + - or any other target in the project file + -s60target TARGETNAME Specify S60 target name if build type is set to s60. + If not specified then it will be asked. Sample target + names: + - "gcce udeb" + - "gcce urel" + -notest Disable all tests in the scenario. + -nopjsuatest Disable pjsua tests in the scenario. +""" + + args.pop(0) + while len(args): + if args[0]=='-o': + args.pop(0) + if len(args): + output = open(args[0], "wt") + args.pop(0) + else: + sys.stderr.write("Error: needs value for -o\n") + sys.exit(1) + elif args[0]=='-vstarget': + args.pop(0) + if len(args): + vs_target = args[0] + args.pop(0) + else: + sys.stderr.write("Error: needs value for -vstarget\n") + sys.exit(1) + elif args[0]=='-s60target': + args.pop(0) + if len(args): + s60_target = args[0] + args.pop(0) + else: + sys.stderr.write("Error: needs value for -s60target\n") + sys.exit(1) + elif args[0]=='-t': + args.pop(0) + if len(args): + build_type = args[0].lower() + args.pop(0) + else: + sys.stderr.write("Error: needs value for -t\n") + sys.exit(1) + if not ["vs", "gnu", "s60"].count(build_type): + sys.stderr.write("Error: invalid -t argument value\n") + sys.exit(1) + elif args[0]=='-notest' or args[0]=='-notests': + args.pop(0) + no_test = True + elif args[0]=='-nopjsuatest' or args[0]=='-nopjsuatests': + args.pop(0) + no_pjsua_test = True + else: + break + + if len(args) != 1: + sys.stderr.write(usage + "\n") + return 1 + + if not build_type: + defval = "vs" + if "SHELL" in os.environ: + shell = os.environ["SHELL"] + if shell.find("sh") > -1: + defval = "gnu" + print "Enter the build type (values: vs, gnu, s60) [%s]: " % (defval), + build_type = sys.stdin.readline().replace("\n", "").replace("\r", "") + if not build_type: + build_type = defval + + + tpl_file = args[len(args)-1] + if not os.path.isfile(tpl_file): + print "Error: unable to find template file '%s'" % (tpl_file) + return 1 + + f = open(tpl_file, "r") + tpl = f.read() + f.close() + + tpl = replace_vars(tpl) + output.write(tpl) + if output != sys.stdout: + output.close() + return 0 + + +if __name__ == "__main__": + rc = main(sys.argv) + sys.exit(rc) + diff --git a/tests/automated/gnu-ipp.xml.template b/tests/automated/gnu-ipp.xml.template new file mode 100644 index 0000000..f6daf51 --- /dev/null +++ b/tests/automated/gnu-ipp.xml.template @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + $(PJSUA-TESTS) + + diff --git a/tests/automated/gnu.xml.template b/tests/automated/gnu.xml.template new file mode 100644 index 0000000..d453f44 --- /dev/null +++ b/tests/automated/gnu.xml.template @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + $(PJSUA-TESTS) + + + diff --git a/tests/automated/iphone.xml.template b/tests/automated/iphone.xml.template new file mode 100644 index 0000000..b4b0c9d --- /dev/null +++ b/tests/automated/iphone.xml.template @@ -0,0 +1,23 @@ + + + + + + + + + + +]]> + + + + + + diff --git a/tests/automated/msvc.xml.template b/tests/automated/msvc.xml.template new file mode 100644 index 0000000..d4dc8ff --- /dev/null +++ b/tests/automated/msvc.xml.template @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + $(PJSUA-TESTS) + + + diff --git a/tests/automated/prepare.xml.template b/tests/automated/prepare.xml.template new file mode 100644 index 0000000..cadfb34 --- /dev/null +++ b/tests/automated/prepare.xml.template @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/automated/run_continuous.py b/tests/automated/run_continuous.py new file mode 100755 index 0000000..07e45ab --- /dev/null +++ b/tests/automated/run_continuous.py @@ -0,0 +1,140 @@ +#!/usr/bin/python +import os +import sys +import time +import datetime +import ccdash + +INTERVAL = 300 +DELAY = 0 +ONCE = False +SUFFIX = "" +FORCE = False + +def run_scenarios(scenarios, group): + # Run each scenario + rc = 0 + for scenario in scenarios: + argv = [] + argv.append("ccdash.py") + argv.append("scenario") + argv.append(scenario) + argv.append("--group") + argv.append(group) + thisrc = ccdash.main(argv) + if rc==0 and thisrc: + rc = thisrc + return rc + + +def usage(): + print """Periodically monitor working directory for Continuous and Nightly builds + +Usage: + run_continuous.py [options] scenario1.xml [scenario2.xml ...] + +options: + These are options which will be processed by run_continuous.py: + + --delay MIN Delay both Continuous and Nightly builds by MIN minutes. + This is useful to coordinate the build with other build + machines. By default, Continuous build will be done right + after changes are detected, and Nightly build will be done + at 00:00 GMT. MIN is a float number. + + --once Just run one loop to see if anything needs to be done and + if so just do it once. Quit after that. + + --suffix SFX Set group suffix to SFX. For example, if SFX is "-2.x", then + tests will be submitted to "Nightly-2.x", "Continuous-2.x", + and "Experimental-2.x" + + --force Force running the test even when nothing has changed. +""" + sys.exit(1) + +if __name__ == "__main__": + if len(sys.argv)<=1 or sys.argv[1]=="-h" or sys.argv[1]=="--h" or sys.argv[1]=="--help" or sys.argv[1]=="/h": + usage() + + # Splice list + scenarios = [] + i = 1 + while i < len(sys.argv): + if sys.argv[i]=="--delay": + i = i + 1 + if i >= len(sys.argv): + print "Error: missing argument" + sys.exit(1) + DELAY = float(sys.argv[i]) * 60 + print "Delay is set to %f minute(s)" % (DELAY / 60) + elif sys.argv[i]=="--suffix": + i = i + 1 + if i >= len(sys.argv): + print "Error: missing argument" + sys.exit(1) + SUFFIX = sys.argv[i] + print "Suffix is set to %s" % (SUFFIX) + elif sys.argv[i]=="--once": + ONCE = True + elif sys.argv[i]=="--force": + FORCE = True + else: + # Check if scenario exists + scenario = sys.argv[i] + if not os.path.exists(scenario): + print "Error: file " + scenario + " does not exist" + sys.exit(1) + scenarios.append(scenario) + print "Scenario %s added" % (scenario) + i = i + 1 + + if len(scenarios) < 1: + print "Error: scenario is required" + sys.exit(1) + + # Current date + utc = time.gmtime(None) + day = utc.tm_mday + + # Loop foreva + while True: + argv = [] + + # Anything changed recently? + argv.append("ccdash.py") + argv.append("status") + argv.append("-w") + argv.append("../..") + rc = ccdash.main(argv) + + utc = time.gmtime(None) + + if utc.tm_mday != day or rc != 0 or FORCE: + group = "" + if utc.tm_mday != day: + day = utc.tm_mday + group = "Nightly" + SUFFIX + elif rc != 0: + group = "Continuous" + SUFFIX + else: + group = "Experimental" + SUFFIX + if DELAY > 0: + print "Will run %s after %f s.." % (group, DELAY) + time.sleep(DELAY) + rc = run_scenarios(scenarios, group) + msg = str(datetime.datetime.now()) + \ + ": done running " + group + \ + "tests, will check again in " + str(INTERVAL) + "s.." + if ONCE: + sys.exit(0) + else: + # Nothing changed + msg = str(datetime.datetime.now()) + \ + ": No update, will check again in " + str(INTERVAL) + "s.." + if ONCE: + sys.exit(1) + + print msg + time.sleep(INTERVAL) + diff --git a/tests/automated/run_scenario.py b/tests/automated/run_scenario.py new file mode 100644 index 0000000..bfd06d1 --- /dev/null +++ b/tests/automated/run_scenario.py @@ -0,0 +1,11 @@ +#!/usr/bin/python +import sys +import ccdash + +if __name__ == "__main__": + sys.argv[0] = "ccdash.py" + sys.argv.insert(1, "scenario") + rc = ccdash.main(sys.argv) + sys.exit(rc) + + diff --git a/tests/automated/symbian-aps.xml.template b/tests/automated/symbian-aps.xml.template new file mode 100644 index 0000000..1a7befc --- /dev/null +++ b/tests/automated/symbian-aps.xml.template @@ -0,0 +1,78 @@ + + + + + + + + + + +]]> + + + + + + + + + + + + + + + + + + + + +]]> + + + + + + + + + + + + + + + + + diff --git a/tests/automated/symbian-vas.xml.template b/tests/automated/symbian-vas.xml.template new file mode 100644 index 0000000..119d1e5 --- /dev/null +++ b/tests/automated/symbian-vas.xml.template @@ -0,0 +1,79 @@ + + + + + + + + + + +]]> + + + + + + + + + + + + + + + + + + + + +]]> + + + + + + + + + + + + + + + + + diff --git a/tests/automated/symbian.xml.template b/tests/automated/symbian.xml.template new file mode 100644 index 0000000..4f36dd9 --- /dev/null +++ b/tests/automated/symbian.xml.template @@ -0,0 +1,20 @@ + + + + + + + +#undef PJ_HAS_IPV6 +#define PJ_HAS_IPV6 1 +#undef PJMEDIA_HAS_G7221_CODEC +#define PJMEDIA_HAS_G7221_CODEC 1 +]]> + + + + + + diff --git a/tests/automated/testvars.template b/tests/automated/testvars.template new file mode 100644 index 0000000..e3f5cf0 --- /dev/null +++ b/tests/automated/testvars.template @@ -0,0 +1,33 @@ +Variables: +----------------------------- +DISABLED = "$(DISABLED)" +GCC = "$(GCC)" +HOSTNAME = "$(HOSTNAME)" +OS = "$(OS)" +PJDIR = "$(PJDIR)" +SUFFIX = "$(SUFFIX)" +NOTEST = "$(NOTEST)" + +S60 only: +------------------------------ +S60TARGET = "$(S60TARGET)" +S60TARGETNAME = "$(S60TARGETNAME)" +S60DEVICE = "$(S60DEVICE)" +EPOCROOT = "$(EPOCROOT)" + +VS only: +------------------------------ +VS = "$(VS)" +VSTARGET = "$(VSTARGET)" + +PJSUA-TESTS: +------------------------------ +$(PJSUA-TESTS) +------------------------------ + +OTHER: +------------------------------ +IPPROOT +IPPSAMPLES +IPPARCH +NOP (cmdline to do nothing) diff --git a/tests/cdash/README.TXT b/tests/cdash/README.TXT new file mode 100644 index 0000000..69728b7 --- /dev/null +++ b/tests/cdash/README.TXT @@ -0,0 +1,59 @@ + + PJSIP CDASH AUTOMATED TESTS + -------------------------------- + + +1. What is this + + This directory contains the scripts to run the automated, Python based tests +of PJSIP source codes, across platforms, and submit the test results to a CDash +test monitoring dashboard. + + Stuffs that are included in the test scope: + - configure (for GNU platforms, e.g. Linux, msys, and MacOS X) + - build + - standard unit tests (pjlib-test, pjsip-test, etc.) + - pjsua's Python based blackbox tests + + +2. Requirements + + To run this test, you will need: + - Python (2.4 or later) + - curl (http://curl.haxx.se) + - a CDash server to receive test submissions (http://www.cdash.org) + - ccdash to submit the tests (http://trac.pjsip.org/ccdash) + + +3. Configuration + + Create a Python configuration file by copying from "cfg_site_sample.py". +Save it as "cfg_site.py". You may create more than one configurations for your +site and save them as different files. + + +4. Running + + To execute tests for GNU based targets: + + $ python main.py cfg_gnu + + + To execute tests for MSVC based target: + + $ python main.py cfg_msvc + + To execute tests for Symbian target: + + $ python main.py cfg_symbian + + + If you have a different site configuration file, you may specify it in the +arguments, e.g.: + + $ python main.py cfg_gnu my_site_config + + For more information you can also pass "-h" or "--help", e.g.: + + $ python main.py cfg_gnu --help + diff --git a/tests/cdash/builder.py b/tests/cdash/builder.py new file mode 100644 index 0000000..79066e8 --- /dev/null +++ b/tests/cdash/builder.py @@ -0,0 +1,501 @@ +# +# builder.py - PJSIP test scenarios builder +# +# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import ccdash +import os +import platform +import re +import subprocess +import sys +import time + +class Operation: + """\ + The Operation class describes the individual ccdash operation to be + performed. + + """ + # Types: + UPDATE = "update" # Update operation + CONFIGURE = "configure" # Configure operation + BUILD = "build" # Build operation + TEST = "test" # Unit test operation + + def __init__(self, type, cmdline, name="", wdir=""): + self.type = type + self.cmdline = cmdline + self.name = name + self.wdir = wdir + if self.type==self.TEST and not self.name: + raise "name required for tests" + + def encode(self, base_dir): + s = [self.type] + if self.type == self.TEST: + s.append(self.name) + if self.type != self.UPDATE: + s.append(self.cmdline) + s.append("-w") + if self.wdir: + s.append(base_dir + "/" + self.wdir) + else: + s.append(base_dir) + return s + + +# +# Update operation +# +update_ops = [Operation(Operation.UPDATE, "")] + +# +# The standard library tests (e.g. pjlib-test, pjsip-test, etc.) +# +std_test_ops= [ + Operation(Operation.TEST, "./pjlib-test$SUFFIX", name="pjlib test", + wdir="pjlib/bin"), + Operation(Operation.TEST, "./pjlib-util-test$SUFFIX", + name="pjlib-util test", wdir="pjlib-util/bin"), + Operation(Operation.TEST, "./pjnath-test$SUFFIX", name="pjnath test", + wdir="pjnath/bin"), + Operation(Operation.TEST, "./pjmedia-test$SUFFIX", name="pjmedia test", + wdir="pjmedia/bin"), + Operation(Operation.TEST, "./pjsip-test$SUFFIX", name="pjsip test", + wdir="pjsip/bin") +] + +# +# These are pjsua Python based unit test operations +# +def build_pjsua_test_ops(pjsua_exe=""): + ops = [] + if pjsua_exe: + exe = " -e ../../pjsip-apps/bin/" + pjsua_exe + else: + exe = "" + cwd = os.getcwd() + os.chdir("../pjsua") + os.system("python runall.py --list > list") + f = open("list", "r") + for e in f: + e = e.rstrip("\r\n ") + (mod,param) = e.split(None,2) + name = mod[4:mod.find(".py")] + "_" + \ + param[param.find("/")+1:param.find(".py")] + ops.append(Operation(Operation.TEST, "python run.py" + exe + " " + \ + e, name=name, wdir="tests/pjsua")) + f.close() + os.remove("list") + os.chdir(cwd) + return ops + +# +# Get gcc version +# +def gcc_version(gcc): + proc = subprocess.Popen(gcc + " -v", stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, shell=True) + ver = "" + while True: + s = proc.stdout.readline() + if not s: + break + if s.find("gcc version") >= 0: + ver = s.split(None, 3)[2] + break + proc.wait() + return "gcc-" + ver + +# +# Get Visual Studio version +# +def vs_get_version(): + proc = subprocess.Popen("cl", stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + while True: + s = proc.stdout.readline() + if s=="": + break + pos = s.find("Version") + if pos > 0: + proc.wait() + s = s[pos+8:] + ver = s.split(None, 1)[0] + major = ver[0:2] + if major=="12": + return "vs6" + elif major=="13": + return "vs2003" + elif major=="14": + return "vs2005" + elif major=="15": + return "vs2008" + else: + return "vs-" + major + proc.wait() + return "vs-unknown" + + +# +# Test config +# +class BaseConfig: + def __init__(self, base_dir, url, site, group, options=None): + self.base_dir = base_dir + self.url = url + self.site = site + self.group = group + self.options = options + +# +# Base class for test configurator +# +class TestBuilder: + def __init__(self, config, build_config_name="", + user_mak="", config_site="", exclude=[], not_exclude=[]): + self.config = config # BaseConfig instance + self.build_config_name = build_config_name # Optional build suffix + self.user_mak = user_mak # To be put in user.mak + self.config_site = config_site # To be put in config_s.. + self.saved_user_mak = "" # To restore user.mak + self.saved_config_site = "" # To restore config_s.. + self.exclude = exclude # List of exclude pattern + self.not_exclude = not_exclude # List of include pattern + self.ccdash_args = [] # ccdash cmd line + + def stamp(self): + return time.strftime("%Y%m%d-%H%M", time.localtime()) + + def pre_action(self): + # Override user.mak + name = self.config.base_dir + "/user.mak" + if os.access(name, os.F_OK): + f = open(name, "r") + self.saved_user_mak = f.read() + f.close() + if True: + f = open(name, "w") + f.write(self.user_mak) + f.close() + # Override config_site.h + name = self.config.base_dir + "/pjlib/include/pj/config_site.h" + if os.access(name, os.F_OK): + f = open(name, "r") + self.saved_config_site= f.read() + f.close() + if True: + f = open(name, "wt") + f.write(self.config_site) + f.close() + + + def post_action(self): + # Restore user.mak + name = self.config.base_dir + "/user.mak" + f = open(name, "wt") + f.write(self.saved_user_mak) + f.close() + # Restore config_site.h + name = self.config.base_dir + "/pjlib/include/pj/config_site.h" + f = open(name, "wt") + f.write(self.saved_config_site) + f.close() + + def build_tests(self): + # This should be overridden by subclasses + pass + + def execute(self): + if len(self.ccdash_args)==0: + self.build_tests() + self.pre_action() + mandatory_op = ["update", "configure", "build"] + counter = 0 + for a in self.ccdash_args: + # Check if this test is in exclusion list + fullcmd = " ".join(a) + excluded = False + included = False + for pat in self.exclude: + if pat and re.search(pat, fullcmd) != None: + excluded = True + break + if excluded: + for pat in self.not_exclude: + if pat and re.search(pat, fullcmd) != None: + included = True + break + if excluded and not included: + if len(fullcmd)>60: + fullcmd = fullcmd[0:60] + ".." + print "Skipping '%s'" % (fullcmd) + continue + + b = ["ccdash.py"] + b.extend(a) + a = b + #print a + try: + rc = ccdash.main(a) + except Exception, e: + errmsg = str(e) + print "**** Error: ccdash got exception %s ****" % errmsg + rc = -1 + except: + print "**** Error: ccdash got unknown exception ****" + rc = -1 + + if rc!=0 and a[1] in mandatory_op: + print "Stopping because of error.." + break + counter = counter + 1 + self.post_action() + + +# +# GNU test configurator +# +class GNUTestBuilder(TestBuilder): + """\ + This class creates list of tests suitable for GNU targets. + + """ + def __init__(self, config, build_config_name="", user_mak="", \ + config_site="", cross_compile="", exclude=[], not_exclude=[]): + """\ + Parameters: + config - BaseConfig instance + build_config_name - Optional name to be added as suffix to the build + name. Sample: "min-size", "O4", "TLS", etc. + user_mak - Contents to be put on user.mak + config_site - Contents to be put on config_site.h + cross_compile - Optional cross-compile prefix. Must include the + trailing dash, e.g. "arm-unknown-linux-" + exclude - List of regular expression patterns for tests + that will be excluded from the run + not_exclude - List of regular expression patterns for tests + that will be run regardless of whether they + match the excluded pattern. + + """ + TestBuilder.__init__(self, config, build_config_name=build_config_name, + user_mak=user_mak, config_site=config_site, + exclude=exclude, not_exclude=not_exclude) + self.cross_compile = cross_compile + if self.cross_compile and self.cross_compile[-1] != '-': + self.cross_compile.append("-") + + def build_tests(self): + if self.cross_compile: + suffix = "-" + self.cross_compile[0:-1] + build_name = self.cross_compile + \ + gcc_version(self.cross_compile + "gcc") + else: + proc = subprocess.Popen("sh "+self.config.base_dir+"/config.guess", + shell=True, stdout=subprocess.PIPE) + plat = proc.stdout.readline().rstrip(" \r\n") + build_name = plat + "-"+gcc_version(self.cross_compile + "gcc") + suffix = "-" + plat + + if self.build_config_name: + build_name = build_name + "-" + self.build_config_name + cmds = [] + cmds.extend(update_ops) + cmds.append(Operation(Operation.CONFIGURE, "sh ./configure")) + if sys.platform=="win32": + # Don't build python module on Mingw + cmds.append(Operation(Operation.BUILD, + "sh -c 'make distclean && make dep && make'")) + else: + cmds.append(Operation(Operation.BUILD, + "sh -c 'make distclean && make dep && make" + \ + " && cd pjsip-apps/src/python && " + \ + "python setup.py clean build'")) + + cmds.extend(std_test_ops) + cmds.extend(build_pjsua_test_ops()) + self.ccdash_args = [] + for c in cmds: + c.cmdline = c.cmdline.replace("$SUFFIX", suffix) + args = c.encode(self.config.base_dir) + args.extend(["-U", self.config.url, + "-S", self.config.site, + "-T", self.stamp(), + "-B", build_name, + "-G", self.config.group]) + args.extend(self.config.options) + self.ccdash_args.append(args) + +# +# MSVC test configurator +# +class MSVCTestBuilder(TestBuilder): + """\ + This class creates list of tests suitable for Visual Studio builds. + You need to set the MSVC environment variables (typically by calling + vcvars32.bat) prior to running this class. + + """ + def __init__(self, config, target="Release|Win32", build_config_name="", + config_site="", exclude=[], not_exclude=[]): + """\ + Parameters: + config - BaseConfig instance + target - Visual Studio build configuration to build. + Sample: "Debug|Win32", "Release|Win32". + build_config_name - Optional name to be added as suffix to the build + name. Sample: "Debug", "Release", "IPv6", etc. + config_site - Contents to be put on config_site.h + exclude - List of regular expression patterns for tests + that will be excluded from the run + not_exclude - List of regular expression patterns for tests + that will be run regardless of whether they + match the excluded pattern. + + """ + TestBuilder.__init__(self, config, build_config_name=build_config_name, + config_site=config_site, exclude=exclude, + not_exclude=not_exclude) + self.target = target.lower() + + def build_tests(self): + + (vsbuild,sys) = self.target.split("|",2) + + build_name = sys + "-" + vs_get_version() + "-" + vsbuild + + if self.build_config_name: + build_name = build_name + "-" + self.build_config_name + + vccmd = "vcbuild.exe /nologo /nohtmllog /nocolor /rebuild " + \ + "pjproject-vs8.sln " + " \"" + self.target + "\"" + + suffix = "-i386-win32-vc8-" + vsbuild + pjsua = "pjsua_vc8" + if vsbuild=="debug": + pjsua = pjsua + "d" + + cmds = [] + cmds.extend(update_ops) + cmds.append(Operation(Operation.CONFIGURE, "CMD /C echo Nothing to do")) + cmds.append(Operation(Operation.BUILD, vccmd)) + cmds.extend(std_test_ops) + cmds.extend(build_pjsua_test_ops(pjsua)) + + self.ccdash_args = [] + for c in cmds: + c.cmdline = c.cmdline.replace("$SUFFIX", suffix) + args = c.encode(self.config.base_dir) + args.extend(["-U", self.config.url, + "-S", self.config.site, + "-T", self.stamp(), + "-B", build_name, + "-G", self.config.group]) + args.extend(self.config.options) + self.ccdash_args.append(args) + + +# +# Symbian test configurator +# +class SymbianTestBuilder(TestBuilder): + """\ + This class creates list of tests suitable for Symbian builds. You need to + set the command line build settings prior to running this class (typically + that involves setting the EPOCROOT variable and current device). + + """ + def __init__(self, config, target="gcce urel", build_config_name="", + config_site="", exclude=[], not_exclude=[]): + """\ + Parameters: + config - BaseConfig instance + target - Symbian target to build. Default is "gcce urel". + build_config_name - Optional name to be added as suffix to the build + name. Sample: "APS", "VAS", etc. + config_site - Contents to be put on config_site.h + exclude - List of regular expression patterns for tests + that will be excluded from the run + not_exclude - List of regular expression patterns for tests + that will be run regardless of whether they + match the excluded pattern. + + """ + TestBuilder.__init__(self, config, build_config_name=build_config_name, + config_site=config_site, exclude=exclude, + not_exclude=not_exclude) + self.target = target.lower() + + def build_tests(self): + + # Check that EPOCROOT is set + if not "EPOCROOT" in os.environ: + print "Error: EPOCROOT environment variable is not set" + sys.exit(1) + epocroot = os.environ["EPOCROOT"] + # EPOCROOT must have trailing backslash + if epocroot[-1] != "\\": + epocroot = epocroot + "\\" + os.environ["EPOCROOT"] = epocroot + sdk1 = epocroot.split("\\")[-2] + + # Check that correct device is set + proc = subprocess.Popen("devices", stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, shell=True) + sdk2 = "" + while True: + line = proc.stdout.readline() + if line.find("- default") > 0: + sdk2 = line.split(":",1)[0] + break + proc.wait() + + if sdk1 != sdk2: + print "Error: default SDK in device doesn't match EPOCROOT" + print "Default device SDK =", sdk2 + print "EPOCROOT SDK =", sdk1 + sys.exit(1) + + build_name = sdk2.replace("_", "-") + "-" + \ + self.target.replace(" ", "-") + + if self.build_config_name: + build_name = build_name + "-" + self.build_config_name + + cmdline = "cmd /C \"cd build.symbian && bldmake bldfiles && abld build %s\"" % (self.target) + + cmds = [] + cmds.extend(update_ops) + cmds.append(Operation(Operation.CONFIGURE, "CMD /C echo Nothing to do")) + cmds.extend([Operation(Operation.BUILD, cmdline)]) + + self.ccdash_args = [] + suffix = "" + for c in cmds: + c.cmdline = c.cmdline.replace("$SUFFIX", suffix) + args = c.encode(self.config.base_dir) + args.extend(["-U", self.config.url, + "-S", self.config.site, + "-T", self.stamp(), + "-B", build_name, + "-G", self.config.group]) + args.extend(self.config.options) + self.ccdash_args.append(args) + diff --git a/tests/cdash/cfg_gnu.py b/tests/cdash/cfg_gnu.py new file mode 100644 index 0000000..8411b65 --- /dev/null +++ b/tests/cdash/cfg_gnu.py @@ -0,0 +1,73 @@ +# +# cfg_gnu.py - GNU target configurator +# +# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +import builder +import os +import sys + +# Each configurator must export this function +def create_builder(args): + usage = """\ +Usage: + main.py cfg_gnu [-h|--help] [cfg_site] + +Arguments: + cfg_site: site configuration module. If not specified, "cfg_site" + is implied + -h, --help Show this help screen + +""" + # (optional) args format: + # site configuration module. If not specified, "cfg_site" is implied + + cfg_site = "cfg_site" + + for arg in args: + if arg=="-h" or arg=="--help": + print usage + sys.exit(0) + elif arg[0]=="-": + print usage + sys.exit(1) + else: + cfg_site = arg + + if os.access(cfg_site+".py", os.F_OK) == False: + print "Error: file '%s.py' doesn't exist." % (cfg_site) + sys.exit(1) + + cfg_site = __import__(cfg_site) + test_cfg = builder.BaseConfig(cfg_site.BASE_DIR, \ + cfg_site.URL, \ + cfg_site.SITE_NAME, \ + cfg_site.GROUP, \ + cfg_site.OPTIONS) + + config_site = "#define PJ_TODO(x)\n" + cfg_site.CONFIG_SITE + user_mak = "export CFLAGS+=-Wall\n" + cfg_site.USER_MAK + + builders = [ + builder.GNUTestBuilder(test_cfg, build_config_name="default", + user_mak=user_mak, + config_site=config_site, + exclude=cfg_site.EXCLUDE, + not_exclude=cfg_site.NOT_EXCLUDE) + ] + + return builders diff --git a/tests/cdash/cfg_msvc.py b/tests/cdash/cfg_msvc.py new file mode 100644 index 0000000..26b0785 --- /dev/null +++ b/tests/cdash/cfg_msvc.py @@ -0,0 +1,82 @@ +# +# cfg_msvc.py - MSVC/Visual Studio target configurator +# +# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +import builder +import os +import sys + +# Each configurator must export this function +def create_builder(args): + usage = """\ +Usage: + main.py cfg_msvc [-h|--help] [-t|--target TARGET] [cfg_site] + +Arguments: + cfg_site: site configuration module. If not specified, "cfg_site" + is implied + -t,--target TARGET: Visual Studio build configuration to build. Default is + "Release|Win32". Sample values: "Debug|Win32" + -h, --help Show this help screen + +""" + + cfg_site = "cfg_site" + target = "Release|Win32" + in_option = "" + + for arg in args: + if in_option=="-t": + target = arg + in_option = "" + elif arg=="--target" or arg=="-t": + in_option = "-t" + elif arg=="-h" or arg=="--help": + print usage + sys.exit(0) + elif arg[0]=="-": + print usage + sys.exit(1) + else: + cfg_site = arg + + if os.access(cfg_site+".py", os.F_OK) == False: + print "Error: file '%s.py' doesn't exist." % (cfg_site) + sys.exit(1) + + cfg_site = __import__(cfg_site) + test_cfg = builder.BaseConfig(cfg_site.BASE_DIR, \ + cfg_site.URL, \ + cfg_site.SITE_NAME, \ + cfg_site.GROUP, \ + cfg_site.OPTIONS) + + config_site = "#define PJ_TODO(x)\n" + cfg_site.CONFIG_SITE + user_mak = cfg_site.USER_MAK + + builders = [ + builder.MSVCTestBuilder(test_cfg, + target=target, + build_config_name="default", + config_site=config_site, + exclude=cfg_site.EXCLUDE, + not_exclude=cfg_site.NOT_EXCLUDE) + ] + + return builders + diff --git a/tests/cdash/cfg_site_sample.py b/tests/cdash/cfg_site_sample.py new file mode 100644 index 0000000..b059642 --- /dev/null +++ b/tests/cdash/cfg_site_sample.py @@ -0,0 +1,50 @@ +# +# cfg_site_sample.py - Sample site configuration +# +# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +import builder + +# Your site name +SITE_NAME="Newham3" + +# The URL where tests will be submitted to +URL = "http://192.168.0.2/dash/submit.php?project=PJSIP" + +# Test group +GROUP = "Experimental" + +# PJSIP base directory +BASE_DIR = "/root/project/pjproject" + +# List of additional ccdash options +#OPTIONS = ["-o", "out.xml", "-y"] +OPTIONS = [] + +# What's the content of config_site.h +CONFIG_SITE = "" + +# What's the content of user.mak +USER_MAK = "" + +# List of regular expression of test patterns to be excluded +EXCLUDE = [] + +# List of regular expression of test patterns to be included (even +# if they match EXCLUDE patterns) +NOT_EXCLUDE = [] +#"configure", "update", "build.*make", "build", "run.py mod_run.*100_simple"] diff --git a/tests/cdash/cfg_symbian.py b/tests/cdash/cfg_symbian.py new file mode 100644 index 0000000..94f5f3f --- /dev/null +++ b/tests/cdash/cfg_symbian.py @@ -0,0 +1,86 @@ +# +# cfg_symbian.py - Symbian target configurator +# +# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +import builder +import os +import sys + +# Each configurator must export this function +def create_builder(args): + usage = """\ +Usage: + main.py cfg_symbian [-h|--help] [-t|--target TARGET] [cfg_site] + +Arguments: + cfg_site: site configuration module. If not specified, "cfg_site" + is implied + -t,--target TARGET: Symbian target to build. Default is "gcce urel". + Other values: + "winscw udeb", "gcce udeb", etc. + -h, --help Show this help screen +""" + + cfg_site = "cfg_site" + target = "gcce urel" + in_option = "" + + for arg in args: + if in_option=="-t": + target = arg + in_option = "" + elif arg=="--target" or arg=="-t": + in_option = "-t" + elif arg=="--help" or arg=="-h": + print usage + sys.exit(0) + elif arg[0]=="-": + print usage + sys.exit(1) + else: + cfg_site = arg + + if os.access(cfg_site+".py", os.F_OK) == False: + print "Error: file '%s.py' doesn't exist." % (cfg_site) + sys.exit(1) + + cfg_site = __import__(cfg_site) + test_cfg = builder.BaseConfig(cfg_site.BASE_DIR, \ + cfg_site.URL, \ + cfg_site.SITE_NAME, \ + cfg_site.GROUP, \ + cfg_site.OPTIONS) + config_site1 = """\ +#define PJ_TODO(x) +#include + +""" + + config_Site = config_site1 + cfg_site.CONFIG_SITE + + builders = [ + builder.SymbianTestBuilder(test_cfg, + target=target, + build_config_name="default", + config_site=config_site1, + exclude=cfg_site.EXCLUDE, + not_exclude=cfg_site.NOT_EXCLUDE) + ] + + return builders + diff --git a/tests/cdash/inc_test.py b/tests/cdash/inc_test.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/cdash/inc_test.py @@ -0,0 +1 @@ + diff --git a/tests/cdash/main.py b/tests/cdash/main.py new file mode 100644 index 0000000..8a99371 --- /dev/null +++ b/tests/cdash/main.py @@ -0,0 +1,42 @@ +#!/bin/env python + +# +# main.py - main entry for PJSIP's CDash tests +# +# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import sys + +if len(sys.argv)==1: + print "Usage: main.py cfg_file [cfg_site]" + print "Example:" + print " main.py cfg_gnu" + print " main.py cfg_gnu custom_cfg_site" + sys.exit(1) + + +args = [] +args.extend(sys.argv) +args.remove(args[1]) +args.remove(args[0]) + +cfg_file = __import__(sys.argv[1]) +builders = cfg_file.create_builder(args) + +for builder in builders: + builder.execute() diff --git a/tests/cdash/starttest_sample.bat b/tests/cdash/starttest_sample.bat new file mode 100644 index 0000000..752e38d --- /dev/null +++ b/tests/cdash/starttest_sample.bat @@ -0,0 +1,44 @@ +@echo off + +rem *** +rem ************** VS 2005 ************** +rem *** +set OLD_PATH=%PATH% +set OLD_INCLUDE=%INCLUDE% +set OLD_LIB=%LIB% +set OLD_LIBPATH=%LIBPATH% + +call "C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat" x86 +python main.py cfg_msvc -t "Debug|Win32" +python main.py cfg_msvc -t "Release|Win32" + +set PATH=%OLD_PATH% +set INCLUDE=%OLD_INCLUDE% +set LIB=%OLD_LIB% +set LIBPATH=%OLD_LIBPATH% + + +rem *** +rem ************** S60 3rd FP1 ************** +rem *** +set EPOCROOT=\symbian\9.2\S60_3rd_FP1\ +devices -setdefault @S60_3rd_FP1:com.nokia.s60 +python main.py cfg_symbian -t "winscw udeb" +python main.py cfg_symbian -t "gcce udeb" +python main.py cfg_symbian -t "gcce urel" + + +rem *** +rem ************** Mingw ************** +rem *** +set MSYSTEM=MINGW32 +set DISPLAY= +C:\msys\1.0\bin\sh -c "python main.py cfg_gnu" + + +rem *** +rem ************** Linux ************** +rem *** +set PATH=%PATH%;c:\msys\1.0\bin +set HOME=C:\msys\1.0\home\Administrator +C:\mingw\bin\ssh test@192.168.0.12 "cd project/pjproject/tests/cdash && python main.py cfg_gnu" diff --git a/tests/pjsua/README.TXT b/tests/pjsua/README.TXT new file mode 100644 index 0000000..0475bac --- /dev/null +++ b/tests/pjsua/README.TXT @@ -0,0 +1,65 @@ + + PJSUA TEST FRAMEWORK + ========================= + +0. What is this +--------------- +This is the automated testing scripts for pjsua. It can do many things (just +don't ask it to write good documentation :) ). + + +1. Requirements +--------------- +To run the tests you need: + - Python (tested with Python 2.5.2) + - pjsua application, built and placed in pjsip-apps/bin directory + - the pjsua must be built with: + - SRTP enabled (the default) + + +2. Using +-------- +To run all the tests: + $ python [OPTIONS] runall.py + +To run individual test: + $ python [OPTIONS] run.py MODULE CONFIG + +Where options: + -e EXE use EXE as pjsua executable + -n use null audio + -r TEST (for runall.py only) resume test at TEST + + +For each individual tests, the run.py is the main entry for the test. It +imports the various inc_xxx.py files, and it will load the MODULE. The MODULE +contains specific test flows, and we have few of them: + + - mod_run.py: + a simple test which just run pjsua with the configuration from CONFIG + file and checks if pjsua can start properly. + + - mod_call.py: + call testing where it spawns two pjsua instances each with configura- + tions as specified in CONFIG file, makes one pjsua call the other, and + checks if the call can be established. + + - mod_pres.py: + presence testing + + - mod_sendto.py: + Simple UAC to send arbitrary SIP message to pjsua. Good to test + various incoming INVITE scenarios + + - mod_media_playrec.py: + Mainly for resampling quality testing + + - mod_pesq.py + Measure call quality of various call settings with PESQ, for people + who have PESQ tool and license + +Example: + $ python run.py mod_run.py scripts-run/100_simple.py + $ python run.py mod_call.py scripts-call/100_simple.py + + diff --git a/tests/pjsua/config_site.py b/tests/pjsua/config_site.py new file mode 100644 index 0000000..a626e56 --- /dev/null +++ b/tests/pjsua/config_site.py @@ -0,0 +1,4 @@ +# $Id: config_site.py 2237 2008-08-26 12:13:25Z bennylp $ + +# Specify if host has sound device, or test should be performed using sound device +HAS_SND_DEV = 0 diff --git a/tests/pjsua/inc_cfg.py b/tests/pjsua/inc_cfg.py new file mode 100644 index 0000000..3661b64 --- /dev/null +++ b/tests/pjsua/inc_cfg.py @@ -0,0 +1,107 @@ +# $Id: inc_cfg.py 2237 2008-08-26 12:13:25Z bennylp $ +import random +import config_site + +DEFAULT_ECHO = True +DEFAULT_TRACE = True +DEFAULT_START_SIP_PORT = 50000 + +# Shared vars +ARGS = [] # arguments containing script module & config +HAS_SND_DEV = config_site.HAS_SND_DEV + +# Individual pjsua instance configuration class +class InstanceParam: + # Name to identify this pjsua instance (e.g. "caller", "callee", etc.) + name = "" + # pjsua command line arguments, concatenated in string + arg = "" + # Specify whether pjsua output should be echoed to stdout + echo_enabled = DEFAULT_ECHO + # Enable/disable test tracing + trace_enabled = DEFAULT_TRACE + # SIP URI to send request to this instance + uri = "" + # SIP port number, zero to automatically assign + sip_port = 0 + # Does this have registration? If yes then the test function will + # wait until the UA is registered before doing anything else + have_reg = False + # Does this have PUBLISH? + have_publish = False + # Enable stdout buffer? + enable_buffer = False + def __init__( self, + name, # Instance name + arg, # Cmd-line arguments + uri="", # URI + uri_param="", # Additional URI param + sip_port=0, # SIP port + have_reg=False, # Have registration? + have_publish=False, # Have publish? + echo_enabled=DEFAULT_ECHO, + trace_enabled=DEFAULT_TRACE, + enable_buffer = False): + # Instance name + self.name = name + # Give random sip_port if it's not specified + if sip_port==0: + self.sip_port = random.randint(DEFAULT_START_SIP_PORT, 65534) + else: + self.sip_port = sip_port + # Autogenerate URI if it's empty. + self.uri = uri + if self.uri=="": + self.uri = "sip:pjsip@127.0.0.1:" + str(self.sip_port) + # Add uri_param to the URI + self.uri = self.uri + uri_param + # Add bracket to the URI + if self.uri[0] != "<": + self.uri = "<" + self.uri + ">" + # Add SIP local port to the argument + self.arg = arg + " --local-port=" + str(self.sip_port) + self.have_reg = have_reg + self.have_publish = have_publish + if have_publish and have_reg and not ("--publish" in self.arg): + self.arg = self.arg + " --publish" + self.echo_enabled = echo_enabled + self.trace_enabled = trace_enabled + self.enable_buffer = enable_buffer + + +############################################ +# Test parameter class +class TestParam: + title = "" + # params is list containing InstanceParams objects + inst_params = [] + # flag if this tes should be skipped + skip = None + # list of Expect instances, to be filled at run-time by + # the test program + process = [] + # the function for test body + test_func = None + post_func = None + def __init__( self, + title, # Test title + inst_params, # InstanceParam's as list + func=None, + skip=False, + post_func=None, + need_stdout_buffer=False): + self.title = title + self.inst_params = inst_params + self.skip = skip + self.test_func = func + self.post_func = post_func + + +################################### +# TestError exception +class TestError: + desc = "" + def __init__(self, desc): + self.desc = desc + + diff --git a/tests/pjsua/inc_const.py b/tests/pjsua/inc_const.py new file mode 100644 index 0000000..9edcfef --- /dev/null +++ b/tests/pjsua/inc_const.py @@ -0,0 +1,64 @@ +# $Id: inc_const.py 4177 2012-06-26 02:28:59Z nanang $ +# Useful constants + + +########################## +# MENU OUTPUT +# + + +########################## +# EVENTS +# + +# Text to expect when there is incoming call +EVENT_INCOMING_CALL = "Press .* answer" + + +########################## +# CALL STATES +# + +# Call state is CALLING +STATE_CALLING = "state.*CALLING" +# Call state is EARLY +STATE_EARLY = "state.*EARLY" +# Call state is CONFIRMED +STATE_CONFIRMED = "state.*CONFIRMED" +# Call state is DISCONNECTED +STATE_DISCONNECTED = "Call .* DISCONNECTED" + +# Media call is put on-hold +MEDIA_HOLD = "Call [0-9]+ media [0-9]+ .*, status is .* hold" +# Media call is active +MEDIA_ACTIVE = "Call [0-9]+ media [0-9]+ .*, status is Active" +#MEDIA_ACTIVE = "Media for call [0-9]+ is active" +# RX_DTMF +RX_DTMF = "Incoming DTMF on call [0-9]+: " + +########################## +# MEDIA +# + +# Connecting/disconnecting ports +MEDIA_CONN_PORT_SUCCESS = "Port \d+ \(.+\) transmitting to port" +MEDIA_DISCONN_PORT_SUCCESS = "Port \d+ \(.+\) stop transmitting to port" + +# Filename to play / record +MEDIA_PLAY_FILE = "--play-file\s+(\S+)" +MEDIA_REC_FILE = "--rec-file\s+(\S+)" + +########################## +# MISC +# + +# The command prompt +PROMPT = ">>>" +# When pjsua has been destroyed +DESTROYED = "PJSUA destroyed" +# Assertion failure +ASSERT = "Assertion failed" +# Stdout refresh text +STDOUT_REFRESH = "XXSTDOUT_REFRESHXX" + + diff --git a/tests/pjsua/inc_sdp.py b/tests/pjsua/inc_sdp.py new file mode 100644 index 0000000..f9f26f5 --- /dev/null +++ b/tests/pjsua/inc_sdp.py @@ -0,0 +1,38 @@ +# $Id: inc_sdp.py 2392 2008-12-22 18:54:58Z bennylp $ + +# SDP template +sdp_templ = \ +"""v=0\r +o=- 1 1 $NET_TYPE $ADDR_TYPE $LOCAL_IP\r +s=pjmedia\r +t=0 0\r +$SDP_LINES""" + +sdp_media_templ = \ +"""m=$MEDIA_TYPE $PORT $TRANSPORT 0\r +c=$NET_TYPE $ADDR_TYPE $LOCAL_IP\r +$SDP_LINES""" + +# Create SDP session +def session(local_ip="127.0.0.1", extra_lines="", net_type="IN", addr_type="IP4"): + sdp = sdp_templ + sdp = sdp.replace("$NET_TYPE", net_type) + sdp = sdp.replace("$ADDR_TYPE", addr_type) + sdp = sdp.replace("$LOCAL_IP", local_ip) + sdp = sdp.replace("$SDP_LINES", extra_lines) + return sdp + +# Create basic SDP media +def media(media_type="audio", local_port=4000, local_ip="127.0.0.1", extra_lines="", + net_type = "IN", addr_type="IP4", transport="RTP/AVP"): + sdp = sdp_media_templ + sdp = sdp.replace("$MEDIA_TYPE", media_type) + sdp = sdp.replace("$LOCAL_IP", local_ip) + sdp = sdp.replace("$PORT", str(local_port)) + sdp = sdp.replace("$NET_TYPE", net_type) + sdp = sdp.replace("$ADDR_TYPE", addr_type) + sdp = sdp.replace("$TRANSPORT", transport) + sdp = sdp.replace("$SDP_LINES", extra_lines) + return sdp + + diff --git a/tests/pjsua/inc_sip.py b/tests/pjsua/inc_sip.py new file mode 100644 index 0000000..1e9a267 --- /dev/null +++ b/tests/pjsua/inc_sip.py @@ -0,0 +1,343 @@ +# $Id: inc_sip.py 3283 2010-08-18 07:37:29Z bennylp $ +# +from socket import * +import re +import random +import time +import sys +import inc_cfg as cfg +from select import * + +# SIP request template +req_templ = \ +"""$METHOD $TARGET_URI SIP/2.0\r +Via: SIP/2.0/UDP $LOCAL_IP:$LOCAL_PORT;rport;branch=z9hG4bK$BRANCH\r +Max-Forwards: 70\r +From: $FROM_TAG\r +To: <$TARGET_URI>$TO_TAG\r +Contact: \r +Call-ID: $CALL_ID@pjsip.org\r +CSeq: $CSEQ $METHOD\r +Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, REFER\r +Supported: replaces, 100rel, norefersub\r +User-Agent: pjsip.org Python tester\r +Content-Length: $CONTENT_LENGTH\r +$SIP_HEADERS""" + + +def is_request(msg): + return msg.split(" ", 1)[0] != "SIP/2.0" + +def is_response(msg): + return msg.split(" ", 1)[0] == "SIP/2.0" + +def get_code(msg): + if msg=="": + return 0 + return int(msg.split(" ", 2)[1]) + +def get_tag(msg, hdr="To"): + pat = "^" + hdr + ":.*" + result = re.search(pat, msg, re.M | re.I) + if result==None: + return "" + line = result.group() + #print "line=", line + tags = line.split(";tag=") + if len(tags)>1: + return tags[1] + return "" + #return re.split("[;& ]", s) + +def get_header(msg, hname): + headers = msg.splitlines() + for hdr in headers: + hfields = hdr.split(": ", 2) + if hfields[0]==hname: + return hfields[1] + return None + +class Dialog: + sock = None + dst_addr = "" + dst_port = 5060 + local_ip = "" + local_port = 0 + tcp = False + call_id = str(random.random()) + cseq = 0 + local_tag = ";tag=" + str(random.random()) + rem_tag = "" + last_resp_code = 0 + inv_branch = "" + trace_enabled = True + last_request = "" + def __init__(self, dst_addr, dst_port=5060, tcp=False, trace=True, local_port=0): + self.dst_addr = dst_addr + self.dst_port = dst_port + self.tcp = tcp + self.trace_enabled = trace + if tcp==True: + self.sock = socket(AF_INET, SOCK_STREAM) + self.sock.connect(dst_addr, dst_port) + else: + self.sock = socket(AF_INET, SOCK_DGRAM) + self.sock.bind(("127.0.0.1", local_port)) + + self.local_ip, self.local_port = self.sock.getsockname() + self.trace("Dialog socket bound to " + self.local_ip + ":" + str(self.local_port)) + + def trace(self, txt): + if self.trace_enabled: + print str(time.strftime("%H:%M:%S ")) + txt + + def update_fields(self, msg): + if self.tcp: + transport_param = ";transport=tcp" + else: + transport_param = "" + msg = msg.replace("$TARGET_URI", "sip:"+self.dst_addr+":"+str(self.dst_port) + transport_param) + msg = msg.replace("$LOCAL_IP", self.local_ip) + msg = msg.replace("$LOCAL_PORT", str(self.local_port)) + msg = msg.replace("$FROM_TAG", self.local_tag) + msg = msg.replace("$TO_TAG", self.rem_tag) + msg = msg.replace("$CALL_ID", self.call_id) + msg = msg.replace("$CSEQ", str(self.cseq)) + branch=str(random.random()) + msg = msg.replace("$BRANCH", branch) + return msg + + def create_req(self, method, sdp, branch="", extra_headers="", body=""): + if branch=="": + self.cseq = self.cseq + 1 + msg = req_templ + msg = msg.replace("$METHOD", method) + msg = msg.replace("$SIP_HEADERS", extra_headers) + if branch=="": + branch=str(random.random()) + msg = msg.replace("$BRANCH", branch) + if sdp!="": + msg = msg.replace("$CONTENT_LENGTH", str(len(sdp))) + msg = msg + "Content-Type: application/sdp\r\n" + msg = msg + "\r\n" + msg = msg + sdp + elif body!="": + msg = msg.replace("$CONTENT_LENGTH", str(len(body))) + msg = msg + "\r\n" + msg = msg + body + else: + msg = msg.replace("$CONTENT_LENGTH", "0") + return self.update_fields(msg) + + def create_response(self, request, code, reason, to_tag=""): + response = "SIP/2.0 " + str(code) + " " + reason + "\r\n" + lines = request.splitlines() + for line in lines: + hdr = line.split(":", 1)[0] + if hdr in ["Via", "From", "To", "CSeq", "Call-ID"]: + if hdr=="To" and to_tag!="": + line = line + ";tag=" + to_tag + elif hdr=="Via": + line = line + ";received=127.0.0.1" + response = response + line + "\r\n" + return response + + def create_invite(self, sdp, extra_headers="", body=""): + self.inv_branch = str(random.random()) + return self.create_req("INVITE", sdp, branch=self.inv_branch, extra_headers=extra_headers, body=body) + + def create_ack(self, sdp="", extra_headers=""): + return self.create_req("ACK", sdp, extra_headers=extra_headers, branch=self.inv_branch) + + def create_bye(self, extra_headers=""): + return self.create_req("BYE", "", extra_headers) + + def send_msg(self, msg, dst_addr=None): + if (is_request(msg)): + self.last_request = msg.split(" ", 1)[0] + if not dst_addr: + dst_addr = (self.dst_addr, self.dst_port) + self.trace("============== TX MSG to " + str(dst_addr) + " ============= \n" + msg) + self.sock.sendto(msg, 0, dst_addr) + + def wait_msg_from(self, timeout): + endtime = time.time() + timeout + msg = "" + src_addr = None + while time.time() < endtime: + readset = select([self.sock], [], [], 1) + if len(readset[0]) < 1 or not self.sock in readset[0]: + if len(readset[0]) < 1: + print "select() timeout (will wait for " + str(int(endtime - time.time())) + "more secs)" + elif not self.sock in readset[0]: + print "select() alien socket" + else: + print "select other error" + continue + try: + msg, src_addr = self.sock.recvfrom(4096) + break + except: + print "recv() exception: ", sys.exc_info()[0] + continue + + if msg=="": + return "", None + if self.last_request=="INVITE" and self.rem_tag=="": + self.rem_tag = get_tag(msg, "To") + self.rem_tag = self.rem_tag.rstrip("\r\n;") + if self.rem_tag != "": + self.rem_tag = ";tag=" + self.rem_tag + self.trace("=== rem_tag:" + self.rem_tag) + self.trace("=========== RX MSG from " + str(src_addr) + " ===========\n" + msg) + return (msg, src_addr) + + def wait_msg(self, timeout): + return self.wait_msg_from(timeout)[0] + + # Send request and wait for final response + def send_request_wait(self, msg, timeout): + t1 = 1.0 + endtime = time.time() + timeout + resp = "" + code = 0 + for i in range(0,5): + self.send_msg(msg) + resp = self.wait_msg(t1) + if resp!="" and is_response(resp): + code = get_code(resp) + break + last_resp = resp + while code < 200 and time.time() < endtime: + resp = self.wait_msg(endtime - time.time()) + if resp != "" and is_response(resp): + code = get_code(resp) + last_resp = resp + elif resp=="": + break + return last_resp + + def hangup(self, last_code=0): + self.trace("====== hangup =====") + if last_code!=0: + self.last_resp_code = last_code + if self.last_resp_code>0 and self.last_resp_code<200: + msg = self.create_req("CANCEL", "", branch=self.inv_branch, extra_headers="") + self.send_request_wait(msg, 5) + msg = self.create_ack() + self.send_msg(msg) + elif self.last_resp_code>=200 and self.last_resp_code<300: + msg = self.create_ack() + self.send_msg(msg) + msg = self.create_bye() + self.send_request_wait(msg, 5) + else: + msg = self.create_ack() + self.send_msg(msg) + + +class SendtoCfg: + # Test name + name = "" + # pjsua InstanceParam + inst_param = None + # Complete INVITE message. If this is not empty, then this + # message will be sent instead and the "sdp" and "extra_headers" + # settings will be ignored. + complete_msg = "" + # Initial SDP + sdp = "" + # Extra headers to add to request + extra_headers = "" + # Expected code + resp_code = 0 + # Use TCP? + use_tcp = False + # List of RE patterns that must exist in response + resp_include = [] + # List of RE patterns that must NOT exist in response + resp_exclude = [] + # Full (non-SDP) body + body = "" + # Constructor + def __init__(self, name, pjsua_args, sdp, resp_code, + resp_inc=[], resp_exc=[], use_tcp=False, + extra_headers="", body="", complete_msg="", + enable_buffer = False): + self.complete_msg = complete_msg + self.sdp = sdp + self.resp_code = resp_code + self.resp_include = resp_inc + self.resp_exclude = resp_exc + self.use_tcp = use_tcp + self.extra_headers = extra_headers + self.body = body + self.inst_param = cfg.InstanceParam("pjsua", pjsua_args) + self.inst_param.enable_buffer = enable_buffer + + +class RecvfromTransaction: + # The test title for this transaction + title = "" + # Optinal list of pjsua command and optional expect patterns + # to be invoked to make pjsua send a request + # Sample: + # (to make call and wait for INVITE to be sent) + # cmds = [ ["m"], ["sip:127.0.0.1", "INVITE sip:"] ] + cmds = [] + # Check if the CSeq must be greater than last Cseq? + check_cseq = True + # List of RE patterns that must exists in incoming request + include = [] + # List of RE patterns that MUST NOT exist in incoming request + exclude = [] + # Response code to send + resp_code = 0 + # Additional list of headers to be sent on the response + # Note: no need to add CRLF on the header + resp_hdr = [] + # Message body. This should include the Content-Type header too. + # Sample: + # body = """Content-Type: application/sdp\r\n + # \r\n + # v=0\r\n + # ... + # """ + body = None + # Pattern to be expected on pjsua when receiving the response + expect = "" + + def __init__(self, title, resp_code, check_cseq=True, + include=[], exclude=[], cmds=[], resp_hdr=[], resp_body=None, expect=""): + self.title = title + self.cmds = cmds + self.include = include + self.exclude = exclude + self.resp_code = resp_code + self.resp_hdr = resp_hdr + self.body = resp_body + self.expect = expect + + +class RecvfromCfg: + # Test name + name = "" + # pjsua InstanceParam + inst_param = None + # List of RecvfromTransaction + transaction = None + # Use TCP? + tcp = False + + # Note: + # Any "$PORT" string in the pjsua_args will be replaced + # by server port + def __init__(self, name, pjsua_args, transaction, tcp=False): + self.name = name + self.inst_param = cfg.InstanceParam("pjsua", pjsua_args) + self.transaction = transaction + self.tcp=tcp + + + + diff --git a/tests/pjsua/mod_call.py b/tests/pjsua/mod_call.py new file mode 100644 index 0000000..c725f21 --- /dev/null +++ b/tests/pjsua/mod_call.py @@ -0,0 +1,226 @@ +# $Id: mod_call.py 2078 2008-06-27 21:12:12Z nanang $ +import time +import imp +import sys +import inc_const as const +from inc_cfg import * + +# Load configuration +cfg_file = imp.load_source("cfg_file", ARGS[1]) + +# Check media flow between ua1 and ua2 +def check_media(ua1, ua2): + ua1.send("#") + ua1.expect("#") + ua1.send("1122") + ua2.expect(const.RX_DTMF + "1") + ua2.expect(const.RX_DTMF + "1") + ua2.expect(const.RX_DTMF + "2") + ua2.expect(const.RX_DTMF + "2") + + +# Test body function +def test_func(t): + callee = t.process[0] + caller = t.process[1] + + # if have_reg then wait for couple of seconds for PUBLISH + # to complete (just in case pUBLISH is used) + if callee.inst_param.have_reg: + time.sleep(1) + if caller.inst_param.have_reg: + time.sleep(1) + + # Caller making call + caller.send("m") + caller.send(t.inst_params[0].uri) + caller.expect(const.STATE_CALLING) + + # Callee waits for call and answers with 180/Ringing + time.sleep(0.2) + callee.expect(const.EVENT_INCOMING_CALL) + callee.send("a") + callee.send("180") + callee.expect("SIP/2.0 180") + caller.expect("SIP/2.0 180") + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Callee answers with 200/OK + callee.send("a") + callee.send("200") + + # Wait until call is connected in both endpoints + time.sleep(0.2) + caller.expect(const.STATE_CONFIRMED) + callee.expect(const.STATE_CONFIRMED) + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + time.sleep(0.1) + caller.sync_stdout() + callee.sync_stdout() + + # Test that media is okay + time.sleep(0.3) + check_media(caller, callee) + check_media(callee, caller) + + # Hold call by caller + caller.send("H") + caller.expect("INVITE sip:") + callee.expect("INVITE sip:") + caller.expect(const.MEDIA_HOLD) + callee.expect(const.MEDIA_HOLD) + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Release hold + time.sleep(0.5) + caller.send("v") + caller.expect("INVITE sip:") + callee.expect("INVITE sip:") + caller.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold") + callee.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold") + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Test that media is okay + check_media(caller, callee) + check_media(callee, caller) + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Hold call by callee + callee.send("H") + callee.expect("INVITE sip:") + caller.expect("INVITE sip:") + caller.expect(const.MEDIA_HOLD) + callee.expect(const.MEDIA_HOLD) + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Release hold + time.sleep(0.1) + callee.send("v") + callee.expect("INVITE sip:") + caller.expect("INVITE sip:") + callee.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold") + caller.expect(const.MEDIA_ACTIVE, title="waiting for media active after call hold") + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Test that media is okay + # Wait for some time for ICE negotiation + time.sleep(0.6) + check_media(caller, callee) + check_media(callee, caller) + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # UPDATE (by caller) + caller.send("U") + #caller.sync_stdout() + callee.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE") + caller.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE") + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Test that media is okay + time.sleep(0.1) + check_media(caller, callee) + check_media(callee, caller) + + # UPDATE (by callee) + callee.send("U") + callee.expect("UPDATE sip:") + caller.expect("UPDATE sip:") + caller.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE") + callee.expect(const.MEDIA_ACTIVE, title="waiting for media active with UPDATE") + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Test that media is okay + time.sleep(0.1) + check_media(caller, callee) + check_media(callee, caller) + + # Synchronize stdout + caller.sync_stdout() + callee.sync_stdout() + + # Set codecs in both caller and callee so that there is + # no common codec between them. + # In caller we only enable PCMU, in callee we only enable PCMA + caller.send("Cp") + caller.expect("Enter codec") + caller.send("* 0") + caller.send("Cp") + caller.expect("Enter codec") + caller.send("pcmu 120") + + callee.send("Cp") + callee.expect("Enter codec") + callee.send("* 0") + callee.send("Cp") + callee.expect("Enter codec") + callee.send("pcma 120") + + # Test when UPDATE fails (by callee) + callee.send("U") + caller.expect("SIP/2.0 488") + callee.expect("SIP/2.0 488") + callee.sync_stdout() + caller.sync_stdout() + + # Test that media is still okay + time.sleep(0.1) + check_media(caller, callee) + check_media(callee, caller) + + # Test when UPDATE fails (by caller) + caller.send("U") + caller.expect("UPDATE sip:") + callee.expect("UPDATE sip:") + callee.expect("SIP/2.0 488") + caller.expect("SIP/2.0 488") + caller.sync_stdout() + callee.sync_stdout() + + # Test that media is still okay + time.sleep(0.1) + check_media(callee, caller) + check_media(caller, callee) + + # Hangup call + time.sleep(0.1) + caller.send("h") + + # Wait until calls are cleared in both endpoints + caller.expect(const.STATE_DISCONNECTED) + callee.expect(const.STATE_DISCONNECTED) + + +# Here where it all comes together +test = cfg_file.test_param +test.test_func = test_func + diff --git a/tests/pjsua/mod_media_playrec.py b/tests/pjsua/mod_media_playrec.py new file mode 100644 index 0000000..897cb63 --- /dev/null +++ b/tests/pjsua/mod_media_playrec.py @@ -0,0 +1,108 @@ +# $Id: mod_media_playrec.py 2884 2009-08-17 08:29:47Z bennylp $ + +# PLAYFILE -> RECFILE: +# Input file is played and is recorded to output, then compare them. +# Useful to tes clock rates compatibility and resample quality +# null-audio +# port 1: wav file input xxxxxx.clock_rate.wav, e.g: test1.8.wav +# port 2: wav file ouput xxxxxx.clock_rate.wav, e.g: res1.8.wav +# wav input must be more than 3 seconds long + +import time +import imp +import sys +import re +import subprocess +import inc_const as const +from inc_cfg import * + +# Load configuration +cfg_file = imp.load_source("cfg_file", ARGS[1]) + +# WAV similarity calculator +COMPARE_WAV_EXE = "" +if sys.platform.find("win32")!=-1: + COMPARE_WAV_EXE = "tools/cmp_wav.exe" + G_INUNIX = False +else: + COMPARE_WAV_EXE = "tools/cmp_wav" + G_INUNIX = True + + +# Threshold to declare degradation is too high when result is lower than this value +COMPARE_THRESHOLD = 2 + +# COMPARE params +input_filename = "" # Input filename +output_filename = "" # Output filename + +# Test body function +def test_func(t): + global input_filename + global output_filename + + endpt = t.process[0] + + # Get input file name + input_filename = re.compile(const.MEDIA_PLAY_FILE).search(endpt.inst_param.arg).group(1) + endpt.trace("Input file = " + input_filename) + + # Get output file name + output_filename = re.compile(const.MEDIA_REC_FILE).search(endpt.inst_param.arg).group(1) + endpt.trace("Output file = " + output_filename) + + # Find appropriate clock rate for the input file + clock_rate = re.compile(".+(\.\d+\.wav)$").match(output_filename).group(1) + if (clock_rate==None): + endpt.trace("Cannot compare input & output, incorrect output filename format") + return + input_filename = re.sub("\.\d+\.wav$", clock_rate, input_filename) + endpt.trace("WAV file to be compared with output = " + input_filename) + + # Connect input-output file + endpt.sync_stdout() + + endpt.send("cc 1 2") + endpt.expect(const.MEDIA_CONN_PORT_SUCCESS) + + # Wait + time.sleep(3) + + endpt.sync_stdout() + + # Disconnect input-output file + endpt.send("cd 1 2") + endpt.expect(const.MEDIA_DISCONN_PORT_SUCCESS) + + +# Post body function +def post_func(t): + global input_filename + global output_filename + + endpt = t.process[0] + + # Check WAV similarity + fullcmd = COMPARE_WAV_EXE + " " + input_filename + " " + output_filename + " " + "3000" + endpt.trace("Popen " + fullcmd) + cmp_proc = subprocess.Popen(fullcmd, shell=G_INUNIX, stdout=subprocess.PIPE, universal_newlines=True) + + # Parse similarity ouput + line = cmp_proc.stdout.readline() + mo_sim_val = re.match(".+=\s+(\d+)", line) + if (mo_sim_val == None): + raise TestError("Error comparing WAV files") + return + + # Evaluate the similarity value + sim_val = mo_sim_val.group(1) + if (sim_val >= COMPARE_THRESHOLD): + endpt.trace("WAV similarity = " + sim_val) + else: + raise TestError("WAV degraded heavily, similarity = " + sim_val) + + +# Here where it all comes together +test = cfg_file.test_param +test.test_func = test_func +test.post_func = post_func diff --git a/tests/pjsua/mod_pesq.py b/tests/pjsua/mod_pesq.py new file mode 100644 index 0000000..e2dbb60 --- /dev/null +++ b/tests/pjsua/mod_pesq.py @@ -0,0 +1,167 @@ +# $Id: mod_pesq.py 2417 2009-01-05 15:31:25Z bennylp $ + +# Quality test of media calls. +# - UA1 calls UA2 +# - UA1 plays a file until finished to be streamed to UA2 +# - UA2 records from stream +# - Apply PESQ to played file (reference) and recorded file (degraded) +# +# File should be: +# - naming: xxxxxx.CLOCK_RATE.wav, e.g: test1.8.wav +# - clock-rate of those files can only be 8khz or 16khz + +import time +import imp +import os +import sys +import re +import subprocess +import wave +import shutil +import inc_const as const + +from inc_cfg import * + +# Load configuration +cfg_file = imp.load_source("cfg_file", ARGS[1]) + +# PESQ configs +PESQ = "tools/pesq" # PESQ executable path +PESQ_DEFAULT_THRESHOLD = 3.4 # Default minimum acceptable PESQ MOS value + +# PESQ params +pesq_sample_rate_opt = "" # Sample rate option for PESQ +input_filename = "" # Input/Reference filename +output_filename = "" # Output/Degraded filename + + +# Test body function +def test_func(t): + global pesq_sample_rate_opt + global input_filename + global output_filename + + ua1 = t.process[0] + ua2 = t.process[1] + + # Get input file name + input_filename = re.compile(const.MEDIA_PLAY_FILE).search(ua1.inst_param.arg).group(1) + + # Get output file name + output_filename = re.compile(const.MEDIA_REC_FILE).search(ua2.inst_param.arg).group(1) + + # Get WAV input length, in seconds + fin = wave.open(input_filename, "r") + if fin == None: + raise TestError("Failed opening input WAV file") + inwavlen = fin.getnframes() * 1.0 / fin.getframerate() + inwavlen += 0.2 + fin.close() + print "WAV input len = " + str(inwavlen) + "s" + + # Get clock rate of the output + mo_clock_rate = re.compile("\.(\d+)\.wav").search(output_filename) + if (mo_clock_rate==None): + raise TestError("Cannot compare input & output, incorrect output filename format") + clock_rate = mo_clock_rate.group(1) + + # Get channel count of the output + channel_count = 1 + if re.search("--stereo", ua2.inst_param.arg) != None: + channel_count = 2 + + # Get matched input file from output file + # (PESQ evaluates only files whose same clock rate & channel count) + if channel_count == 2: + if re.search("\.\d+\.\d+\.wav", input_filename) != None: + input_filename = re.sub("\.\d+\.\d+\.wav", "." + str(channel_count) + "."+clock_rate+".wav", input_filename) + else: + input_filename = re.sub("\.\d+\.wav", "." + str(channel_count) + "."+clock_rate+".wav", input_filename) + + if (clock_rate != "8") & (clock_rate != "16"): + raise TestError("PESQ only works on clock rate 8kHz or 16kHz, clock rate used = "+clock_rate+ "kHz") + + # Get conference clock rate of UA2 for PESQ sample rate option + pesq_sample_rate_opt = "+" + clock_rate + "000" + + # UA1 making call + ua1.send("m") + ua1.send(t.inst_params[1].uri) + ua1.expect(const.STATE_CALLING) + + # UA2 wait until call established + ua2.expect(const.STATE_CONFIRMED) + + ua1.sync_stdout() + ua2.sync_stdout() + time.sleep(2) + + # Disconnect mic -> rec file, to avoid echo recorded when using sound device + # Disconnect stream -> spk, make it silent + # Connect stream -> rec file, start recording + ua2.send("cd 0 1\ncd 4 0\ncc 4 1") + + # Disconnect mic -> stream, make stream purely sending from file + # Disconnect stream -> spk, make it silent + # Connect file -> stream, start sending + ua1.send("cd 0 4\ncd 4 0\ncc 1 4") + + time.sleep(inwavlen) + + # Disconnect files from bridge + ua2.send("cd 4 1") + ua2.expect(const.MEDIA_DISCONN_PORT_SUCCESS) + ua1.send("cd 1 4") + ua1.expect(const.MEDIA_DISCONN_PORT_SUCCESS) + + +# Post body function +def post_func(t): + global pesq_sample_rate_opt + global input_filename + global output_filename + + endpt = t.process[0] + + # Execute PESQ + fullcmd = os.path.normpath(PESQ) + " " + pesq_sample_rate_opt + " " + input_filename + " " + output_filename + endpt.trace("Popen " + fullcmd) + pesq_proc = subprocess.Popen(fullcmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True) + pesq_out = pesq_proc.communicate() + + # Parse ouput + mo_pesq_out = re.compile("Prediction[^=]+=\s+([\-\d\.]+)\s*").search(pesq_out[0]) + if (mo_pesq_out == None): + raise TestError("Failed to fetch PESQ result") + + # Get threshold + if (cfg_file.pesq_threshold != None) | (cfg_file.pesq_threshold > -0.5 ): + threshold = cfg_file.pesq_threshold + else: + threshold = PESQ_DEFAULT_THRESHOLD + + # Evaluate the PESQ MOS value + pesq_res = mo_pesq_out.group(1) + if (float(pesq_res) >= threshold): + endpt.trace("Success, PESQ result = " + pesq_res + " (target=" + str(threshold) + ").") + else: + endpt.trace("Failed, PESQ result = " + pesq_res + " (target=" + str(threshold) + ").") + # Save the wav file + wavoutname = ARGS[1] + wavoutname = re.sub("[\\\/]", "_", wavoutname) + wavoutname = re.sub("\.py$", ".wav", wavoutname) + wavoutname = "logs/" + wavoutname + try: + shutil.copyfile(output_filename, wavoutname) + print "Output WAV is copied to " + wavoutname + except: + print "Couldn't copy output WAV, please check if 'logs' directory exists." + + raise TestError("WAV seems to be degraded badly, PESQ = "+ pesq_res + " (target=" + str(threshold) + ").") + + +# Here where it all comes together +test = cfg_file.test_param +test.test_func = test_func +test.post_func = post_func + diff --git a/tests/pjsua/mod_pres.py b/tests/pjsua/mod_pres.py new file mode 100644 index 0000000..1dbcc2c --- /dev/null +++ b/tests/pjsua/mod_pres.py @@ -0,0 +1,125 @@ +# $Id: mod_pres.py 2078 2008-06-27 21:12:12Z nanang $ +import time +import imp +import sys +import inc_const as const +from inc_cfg import * + +# Load configuration +cfg_file = imp.load_source("cfg_file", ARGS[1]) + + +# Test body function +def test_func(t): + u1 = t.process[0] + uri1 = cfg_file.test_param.inst_params[0].uri + acc1 = "-1" + u2 = t.process[1] + uri2 = cfg_file.test_param.inst_params[1].uri + acc2 = "-1" + + # if have_reg then wait for couple of seconds for PUBLISH + # to complete (just in case pUBLISH is used) + if u1.inst_param.have_reg: + time.sleep(1) + if u2.inst_param.have_reg: + time.sleep(1) + + # U1 adds U2 as buddy + u1.send("+b") + u1.send(uri2) + u1.expect("Subscription state changed NULL --> SENT") + u1.expect("Presence subscription.*is ACCEPTED") + if not u2.inst_param.have_publish: + # Process incoming SUBSCRIBE in U2 + # Finds out which account gets the subscription in U2 + line = u2.expect("pjsua_pres.*subscription.*using account") + acc2 = line.split("using account ")[1] + # wait until we've got Online notification + u1.expect(uri2 + ".*Online") + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + # U2 adds U1 as buddy + u2.send("+b") + u2.send(uri1) + u2.expect("Subscription state changed NULL --> SENT") + u2.expect("Presence subscription.*is ACCEPTED") + if not u1.inst_param.have_publish: + # Process incoming SUBSCRIBE in U1 + # Finds out which account gets the subscription in U1 + line = u1.expect("pjsua_pres.*subscription.*using account") + acc1 = line.split("using account ")[1] + # wait until we've got Online notification + u2.expect(uri1 + ".*Online") + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + # Set current account in both U1 and U2 + if acc1!="-1": + u1.send(">") + u1.send(acc1) + u1.expect("Current account changed") + if acc2!="-1": + u2.send(">") + u2.send(acc2) + u2.expect("Current account changed") + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + # u2 toggles online status + u2.send("t") + u1.expect(uri2 + ".*status.*Offline") + u2.expect("offline") + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + # u1 toggles online status + u1.send("t") + u2.expect(uri1 + ".*status.*Offline") + u1.expect("offline") + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + # u2 set online status to On the phone + u2.send("T") + u2.send("3") + u1.expect(uri2 + ".*status.*On the phone") + u2.expect("On the phone") + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + # U1 send IM + im_text = "Hello World from U1" + u1.send("i") + u1.send(uri2) + u2.expect(" is typing") + u1.send(im_text) + u1.expect(im_text+".*delivered successfully") + u2.expect("MESSAGE from.*"+im_text) + + # Synchronize stdout + u1.sync_stdout() + u2.sync_stdout() + + +# Here where it all comes together +test = cfg_file.test_param +test.test_func = test_func + diff --git a/tests/pjsua/mod_recvfrom.py b/tests/pjsua/mod_recvfrom.py new file mode 100644 index 0000000..8aaa716 --- /dev/null +++ b/tests/pjsua/mod_recvfrom.py @@ -0,0 +1,97 @@ +# $Id: mod_recvfrom.py 3259 2010-08-09 07:31:34Z nanang $ +import imp +import sys +import inc_sip as sip +import inc_const as const +import re +from inc_cfg import * + +# Read configuration +cfg_file = imp.load_source("cfg_file", ARGS[1]) + +# Default server port (should we randomize?) +srv_port = 50070 + +def test_func(test): + pjsua = test.process[0] + dlg = sip.Dialog("127.0.0.1", pjsua.inst_param.sip_port, + local_port=srv_port, + tcp=cfg_file.recvfrom_cfg.tcp) + + last_cseq = 0 + last_method = "" + last_call_id = "" + for t in cfg_file.recvfrom_cfg.transaction: + # Print transaction title + if t.title != "": + dlg.trace(t.title) + # Run command and expect patterns + for c in t.cmds: + if c[0] and c[0] != "": + pjsua.send(c[0]) + if len(c)>1 and c[1] and c[1] != "": + pjsua.expect(c[1]) + # Wait for request + if t.check_cseq: + # Absorbs retransmissions + cseq = 0 + method = last_method + call_id = last_call_id + while cseq <= last_cseq and method == last_method and call_id == last_call_id: + request, src_addr = dlg.wait_msg_from(30) + if request==None or request=="": + raise TestError("Timeout waiting for request") + method = request.split(" ", 1)[0] + cseq_hval = sip.get_header(request, "CSeq") + cseq_hval = cseq_hval.split(" ")[0] + cseq = int(cseq_hval) + call_id = sip.get_header(request, "Call-ID") + last_cseq = cseq + last_method = method + else: + request, src_addr = dlg.wait_msg_from(30) + if request==None or request=="": + raise TestError("Timeout waiting for request") + + # Check for include patterns + for pat in t.include: + if re.search(pat, request, re.M | re.I)==None: + if t.title: + tname = " in " + t.title + " transaction" + else: + tname = "" + raise TestError("Pattern " + pat + " not found" + tname) + # Check for exclude patterns + for pat in t.exclude: + if re.search(pat, request, re.M | re.I)!=None: + if t.title: + tname = " in " + t.title + " transaction" + else: + tname = "" + raise TestError("Excluded pattern " + pat + " found" + tname) + # Create response + if t.resp_code!=0: + response = dlg.create_response(request, t.resp_code, "Status reason") + # Add headers to response + for h in t.resp_hdr: + response = response + h + "\r\n" + # Add message body if required + if t.body: + response = response + t.body + # Send response + dlg.send_msg(response, src_addr) + + # Expect something to happen in pjsua + if t.expect != "": + pjsua.expect(t.expect) + # Sync + pjsua.sync_stdout() + +# Replace "$PORT" with server port in pjsua args +cfg_file.recvfrom_cfg.inst_param.arg = cfg_file.recvfrom_cfg.inst_param.arg.replace("$PORT", str(srv_port)) + +# Here where it all comes together +test = TestParam(cfg_file.recvfrom_cfg.name, + [cfg_file.recvfrom_cfg.inst_param], + test_func) + diff --git a/tests/pjsua/mod_run.py b/tests/pjsua/mod_run.py new file mode 100644 index 0000000..4f2964a --- /dev/null +++ b/tests/pjsua/mod_run.py @@ -0,0 +1,11 @@ +# $Id: mod_run.py 2078 2008-06-27 21:12:12Z nanang $ +import imp +import sys + +from inc_cfg import * + +# Read configuration +cfg_file = imp.load_source("cfg_file", ARGS[1]) + +# Here where it all comes together +test = cfg_file.test_param diff --git a/tests/pjsua/mod_sendto.py b/tests/pjsua/mod_sendto.py new file mode 100644 index 0000000..09042a3 --- /dev/null +++ b/tests/pjsua/mod_sendto.py @@ -0,0 +1,53 @@ +# $Id: mod_sendto.py 3243 2010-08-01 09:48:51Z bennylp $ +import imp +import sys +import inc_sip as sip +import inc_const as const +import re +from inc_cfg import * + +# Read configuration +cfg_file = imp.load_source("cfg_file", ARGS[1]) + +# Test body function +def test_func(t): + pjsua = t.process[0] + # Create dialog + dlg = sip.Dialog("127.0.0.1", pjsua.inst_param.sip_port, + tcp=cfg_file.sendto_cfg.use_tcp) + #dlg = sip.Dialog("127.0.0.1", 5060, tcp=cfg_file.sendto_cfg.use_tcp) + cfg = cfg_file.sendto_cfg + + if len(cfg.complete_msg) != 0: + req = dlg.update_fields(cfg.complete_msg) + else: + req = dlg.create_invite(cfg.sdp, cfg.extra_headers, cfg.body) + resp = dlg.send_request_wait(req, 10) + if resp=="": + raise TestError("Timed-out waiting for response") + # Check response code + code = int(sip.get_code(resp)) + if code != cfg.resp_code: + dlg.hangup(code) + raise TestError("Expecting code " + str(cfg.resp_code) + + " got " + str(code)) + # Check for patterns that must exist + for p in cfg.resp_include: + if re.search(p, resp, re.M | re.I)==None: + dlg.hangup(code) + raise TestError("Pattern " + p + " not found") + # Check for patterns that must not exist + for p in cfg.resp_exclude: + if re.search(p, resp, re.M | re.I)!=None: + dlg.hangup(code) + raise TestError("Excluded pattern " + p + " found") + pjsua.sync_stdout() + dlg.hangup(code) + pjsua.sync_stdout() + +# Here where it all comes together +test = TestParam(cfg_file.sendto_cfg.name, + [cfg_file.sendto_cfg.inst_param], + test_func) + + diff --git a/tests/pjsua/mod_sipp.py b/tests/pjsua/mod_sipp.py new file mode 100644 index 0000000..163a8c7 --- /dev/null +++ b/tests/pjsua/mod_sipp.py @@ -0,0 +1,275 @@ +# $Id: mod_sipp.py 4188 2012-06-29 09:01:17Z nanang $ + +## Automatic test module for SIPp. +## +## This module will need a test driver for each SIPp scenario: +## - For simple scenario, i.e: make/receive call (including auth), this +## test module can auto-generate a default test driver, i.e: make call +## or apply auto answer. Just name the SIPp scenario using "uas" or +## "uac" prefix accordingly. +## - Custom test driver can be defined in a python script file containing +## a list of the PJSUA instances and another list for PJSUA expects/ +## commands. The custom test driver file must use the same filename as +## the SIPp XML scenario. See samples of SIPp scenario + its driver +## in tests/pjsua/scripts-sipp/ folder for detail. +## +## Here are defined macros that can be used in the custom driver: +## - $SIPP_PORT : SIPp binding port +## - $SIPP_URI : SIPp SIP URI +## - $PJSUA_PORT[N] : binding port of PJSUA instance #N +## - $PJSUA_URI[N] : SIP URI of PJSUA instance #N + +import ctypes +import time +import imp +import sys +import os +import re +import subprocess +from inc_cfg import * +import inc_const + +# flags that test is running in Unix +G_INUNIX = False +if sys.platform.lower().find("win32")!=-1 or sys.platform.lower().find("microsoft")!=-1: + G_INUNIX = False +else: + G_INUNIX = True + +# /dev/null handle, for redirecting output when SIPP is not in background mode +FDEVNULL = None + +# SIPp executable path and param +#SIPP_PATH = '"C:\\Program Files (x86)\\Sipp_3.2\\sipp.exe"' +SIPP_PATH = 'sipp' +SIPP_PORT = 6000 +SIPP_PARAM = "-m 1 -i 127.0.0.1 -p " + str(SIPP_PORT) +SIPP_TIMEOUT = 60 +# On BG mode, SIPp doesn't require special terminal +# On non-BG mode, on win, it needs env var: "TERMINFO=c:\cygwin\usr\share\terminfo" +# TODO: on unix with BG mode, waitpid() always fails, need to be fixed +SIPP_BG_MODE = False +#SIPP_BG_MODE = not G_INUNIX + +# Will be updated based on the test driver file (a .py file whose the same name as SIPp XML file) +PJSUA_INST_PARAM = [] +PJSUA_EXPECTS = [] + +# Default PJSUA param if test driver is not available: +# - no-tcp as SIPp is on UDP only +# - id, username, and realm: to allow PJSUA sending re-INVITE with auth after receiving 401/407 response +PJSUA_DEF_PARAM = "--null-audio --max-calls=1 --no-tcp --id=sip:a@localhost --username=a --realm=*" + +# Get SIPp scenario (XML file) +SIPP_SCEN_XML = "" +if ARGS[1].endswith('.xml'): + SIPP_SCEN_XML = ARGS[1] +else: + exit(-99) + + +# Functions for resolving macros in the test driver +def resolve_pjsua_port(mo): + return str(PJSUA_INST_PARAM[int(mo.group(1))].sip_port) + +def resolve_pjsua_uri(mo): + return PJSUA_INST_PARAM[int(mo.group(1))].uri[1:-1] + +def resolve_driver_macros(st): + st = re.sub("\$SIPP_PORT", str(SIPP_PORT), st) + st = re.sub("\$SIPP_URI", "sip:sipp@127.0.0.1:"+str(SIPP_PORT), st) + st = re.sub("\$PJSUA_PORT\[(\d+)\]", resolve_pjsua_port, st) + st = re.sub("\$PJSUA_URI\[(\d+)\]", resolve_pjsua_uri, st) + return st + + +# Init test driver +if os.access(SIPP_SCEN_XML[:-4]+".py", os.R_OK): + # Load test driver file (the corresponding .py file), if any + cfg_file = imp.load_source("cfg_file", SIPP_SCEN_XML[:-4]+".py") + for ua_idx, ua_param in enumerate(cfg_file.PJSUA): + ua_param = resolve_driver_macros(ua_param) + PJSUA_INST_PARAM.append(InstanceParam("pjsua"+str(ua_idx), ua_param)) + PJSUA_EXPECTS = cfg_file.PJSUA_EXPECTS +else: + # Generate default test driver + if os.path.basename(SIPP_SCEN_XML)[0:3] == "uas": + # auto make call when SIPp is as UAS + ua_param = PJSUA_DEF_PARAM + " sip:127.0.0.1:" + str(SIPP_PORT) + else: + # auto answer when SIPp is as UAC + ua_param = PJSUA_DEF_PARAM + " --auto-answer=200" + PJSUA_INST_PARAM.append(InstanceParam("pjsua", ua_param)) + + +# Start SIPp process, returning PID +def start_sipp(): + global SIPP_BG_MODE + sipp_proc = None + + sipp_param = SIPP_PARAM + " -sf " + SIPP_SCEN_XML + if SIPP_BG_MODE: + sipp_param = sipp_param + " -bg" + if SIPP_TIMEOUT: + sipp_param = sipp_param + " -timeout "+str(SIPP_TIMEOUT)+"s -timeout_error" + " -deadcall_wait "+str(SIPP_TIMEOUT)+"s" + + # add target param + sipp_param = sipp_param + " 127.0.0.1:" + str(PJSUA_INST_PARAM[0].sip_port) + + # run SIPp + fullcmd = os.path.normpath(SIPP_PATH) + " " + sipp_param + print "Running SIPP: " + fullcmd + if SIPP_BG_MODE: + sipp_proc = subprocess.Popen(fullcmd, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=G_INUNIX, universal_newlines=False) + else: + # redirect output to NULL + global FDEVNULL + #FDEVNULL = open(os.devnull, 'w') + FDEVNULL = open("logs/sipp_output.tmp", 'w') + sipp_proc = subprocess.Popen(fullcmd, shell=G_INUNIX, stdout=FDEVNULL, stderr=FDEVNULL) + + if not SIPP_BG_MODE: + if sipp_proc == None or sipp_proc.poll(): + return None + return sipp_proc + + else: + # get SIPp child process PID + pid = 0 + r = re.compile("PID=\[(\d+)\]", re.I) + + while True: + line = sipp_proc.stdout.readline() + pid_r = r.search(line) + if pid_r: + pid = int(pid_r.group(1)) + break + if not sipp_proc.poll(): + break + + if pid != 0: + # Win specific: get process handle from PID, as on win32, os.waitpid() takes process handle instead of pid + if (sys.platform == "win32"): + SYNCHRONIZE = 0x00100000 + PROCESS_QUERY_INFORMATION = 0x0400 + hnd = ctypes.windll.kernel32.OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, False, pid) + pid = hnd + + return pid + + +# Wait SIPp process to exit, returning SIPp exit code +def wait_sipp(sipp): + if not SIPP_BG_MODE: + global FDEVNULL + sipp.wait() + FDEVNULL.close() + return sipp.returncode + + else: + print "Waiting SIPp (PID=" + str(sipp) + ") to exit.." + wait_cnt = 0 + while True: + try: + wait_cnt = wait_cnt + 1 + [pid_, ret_code] = os.waitpid(sipp, 0) + if sipp == pid_: + #print "SIPP returned ", ret_code + ret_code = ret_code >> 8 + + # Win specific: Close process handle + if (sys.platform == "win32"): + ctypes.windll.kernel32.CloseHandle(sipp) + + return ret_code + except os.error: + if wait_cnt <= 5: + print "Retry ("+str(wait_cnt)+") waiting SIPp.." + else: + return -99 + + +# Execute PJSUA flow +def exec_pjsua_expects(t, sipp): + # Get all PJSUA instances + ua = [] + for ua_idx in range(len(PJSUA_INST_PARAM)): + ua.append(t.process[ua_idx]) + + ua_err_st = "" + while len(PJSUA_EXPECTS): + expect = PJSUA_EXPECTS.pop(0) + ua_idx = expect[0] + expect_st = expect[1] + send_cmd = resolve_driver_macros(expect[2]) + # Handle exception in pjsua flow, to avoid zombie SIPp process + try: + if expect_st != "": + ua[ua_idx].expect(expect_st, raise_on_error = True) + if send_cmd != "": + ua[ua_idx].send(send_cmd) + except TestError, e: + ua_err_st = e.desc + break; + except: + ua_err_st = "Unknown error" + break; + + # Need to poll here for handling these cases: + # - If there is no PJSUA EXPECT scenario, we must keep polling the stdout, + # otherwise PJSUA process may stuck (due to stdout pipe buffer full?). + # - last PJSUA_EXPECT contains a pjsua command that needs time to + # finish, for example "v" (re-INVITE), the SIPp XML scenario may expect + # that re-INVITE transaction to be completed and without stdout poll + # PJSUA process may stuck. + # Ideally the poll should be done contiunously until SIPp process is + # terminated. + for ua_idx in range(len(ua)): + ua[ua_idx].expect(inc_const.STDOUT_REFRESH, raise_on_error = False) + + return ua_err_st + + +def sipp_err_to_str(err_code): + if err_code == 0: + return "All calls were successful" + elif err_code == 1: + return "At least one call failed" + elif err_code == 97: + return "exit on internal command. Calls may have been processed" + elif err_code == 99: + return "Normal exit without calls processed" + elif err_code == -1: + return "Fatal error (timeout)" + elif err_code == -2: + return "Fatal error binding a socket" + else: + return "Unknown error" + + +# Test body function +def TEST_FUNC(t): + + sipp_ret_code = 0 + ua_err_st = "" + + sipp = start_sipp() + if not sipp: + raise TestError("Failed starting SIPp") + + ua_err_st = exec_pjsua_expects(t, sipp) + + sipp_ret_code = wait_sipp(sipp) + + if ua_err_st != "": + raise TestError(ua_err_st) + + if sipp_ret_code: + rc = ctypes.c_byte(sipp_ret_code).value + raise TestError("SIPp returned error " + str(rc) + ": " + sipp_err_to_str(rc)) + + +# Here where it all comes together +test = TestParam(SIPP_SCEN_XML[:-4], + PJSUA_INST_PARAM, + TEST_FUNC) diff --git a/tests/pjsua/run.py b/tests/pjsua/run.py new file mode 100644 index 0000000..799b659 --- /dev/null +++ b/tests/pjsua/run.py @@ -0,0 +1,289 @@ +# $Id: run.py 4183 2012-06-28 09:16:03Z nanang $ +import sys +import imp +import re +import os +import subprocess +import random +import time +import getopt + +import inc_const as const +import inc_cfg as inc + +# Vars +G_EXE = "" # pjsua executable path +G_INUNIX = False # flags that test is running in Unix + + +# Usage string +usage = \ +""" +run.py - Automated test driver + +Usage: + run.py [options] MODULE CONFIG +Options: + --exe, -e pjsua executable path + --null-audio, -n use null audio +Sample: + run.py -n mod_run.py scripts-run/100_simple.py +""" + +# Parse arguments +try: + opts, args = getopt.getopt(sys.argv[1:], "hne:", ["help", "null-audio", "exe="]) +except getopt.GetoptError, err: + print str(err) + print usage + sys.exit(2) +for o, a in opts: + if o in ("-h", "--help"): + print usage + sys.exit() + elif o in ("-n", "--null-audio"): + inc.HAS_SND_DEV = 0 + elif o in ("-e", "--exe"): + G_EXE = a + else: + print "Unknown options" + sys.exit(2) + +if len(args) != 2: + print "Invalid arguments" + print usage + sys.exit(2) + +# Set global ARGS to be used by modules +inc.ARGS = args + +# Get the pjsua executable name +if G_EXE == "": + if sys.platform.find("win32")!=-1: + EXE_DIR = "../../pjsip-apps/bin/" + EXECUTABLES = [ "pjsua_vc6d.exe", + "pjsua_vc6.exe", + "pjsua-i386-Win32-vc8-Debug.exe", + "pjsua-i386-Win32-vc8-Debug-Dynamic.exe", + "pjsua-i386-Win32-vc8-Debug-Static.exe", + "pjsua-i386-Win32-vc8-Release.exe", + "pjsua-i386-Win32-vc8-Release-Dynamic.exe", + "pjsua-i386-Win32-vc8-Release-Static.exe" + ] + e_ts = 0 + for e in EXECUTABLES: + e = EXE_DIR + e + if os.access(e, os.F_OK): + st = os.stat(e) + if e_ts==0 or e_ts= 6: + self.trace("Timed-out!") + if raise_on_error: + raise inc.TestError(self.name + " " + title + ": Timeout expecting pattern: \"" + pattern + "\"") + else: + return None # timeout + # Search for expected text + if r.search(line) != None: + return line + + def sync_stdout(self): + self.trace("sync_stdout") + cmd = "echo 1" + str(random.randint(1000,9999)) + self.send(cmd) + self.expect(cmd) + + def wait(self): + self.trace("wait") + self.proc.communicate() + + def trace(self, s): + if self.trace_enabled: + now = time.time() + fmt = self.name + ": " + "================== " + s + " ==================" + " [at t=%(time)03d]" + print fmt % {'time':int(now - self.t0)} + +######################### +# Error handling +def handle_error(errmsg, t, close_processes = True): + print "====== Caught error: " + errmsg + " ======" + if (close_processes): + time.sleep(1) + for p in t.process: + # Protect against 'Broken pipe' exception + try: + p.send("q") + p.send("q") + except: + pass + is_err = False + try: + ret = p.expect(const.DESTROYED, False) + if not ret: + is_err = True + except: + is_err = True + if is_err: + if sys.hexversion >= 0x02060000: + p.proc.terminate() + else: + p.wait() + else: + p.wait() + print "Test completed with error: " + errmsg + sys.exit(1) + + +######################### +# MAIN + +# Import the test script +script = imp.load_source("script", inc.ARGS[0]) + +# Init random seed +random.seed() + +# Validate +if script.test == None: + print "Error: no test defined" + sys.exit(1) + +if script.test.skip: + print "Test " + script.test.title + " is skipped" + sys.exit(0) + +if len(script.test.inst_params) == 0: + print "Error: test doesn't contain pjsua run descriptions" + sys.exit(1) + +# Instantiate pjsuas +print "====== Running " + script.test.title + " ======" +print "Using " + G_EXE + " as pjsua executable" + +for inst_param in script.test.inst_params: + try: + # Create pjsua's Expect instance from the param + p = Expect(inst_param) + # Wait until registration completes + if inst_param.have_reg: + p.expect(inst_param.uri+".*registration success") + # Synchronize stdout + p.send("") + p.expect(const.PROMPT) + p.send("echo 1") + p.send("echo 1") + p.expect("echo 1") + # add running instance + script.test.process.append(p) + + except inc.TestError, e: + handle_error(e.desc, script.test) + +# Run the test function +if script.test.test_func != None: + try: + script.test.test_func(script.test) + except inc.TestError, e: + handle_error(e.desc, script.test) + +# Shutdown all instances +time.sleep(2) +for p in script.test.process: + # Unregister if we have_reg to make sure that next tests + # won't wail + if p.inst_param.have_reg: + p.send("ru") + p.expect(p.inst_param.uri+".*unregistration success") + p.send("q") + p.send("q") + time.sleep(0.5) + p.expect(const.DESTROYED, False) + p.wait() + +# Run the post test function +if script.test.post_func != None: + try: + script.test.post_func(script.test) + except inc.TestError, e: + handle_error(e.desc, script.test, False) + +# Done +print "Test " + script.test.title + " completed successfully" +sys.exit(0) + diff --git a/tests/pjsua/runall.py b/tests/pjsua/runall.py new file mode 100644 index 0000000..7aeabe0 --- /dev/null +++ b/tests/pjsua/runall.py @@ -0,0 +1,187 @@ +# $Id: runall.py 4183 2012-06-28 09:16:03Z nanang $ +import os +import sys +import time +import re +import shutil + +PYTHON = os.path.basename(sys.executable) + +# Usage: +# runall.py [test-to-resume] + + +# Initialize test list +tests = [] + +# Excluded tests (because they fail?) +excluded_tests = [ "svn", + "pyc", + "scripts-call/150_srtp_2_1", # SRTP optional 'cannot' call SRTP mandatory + "scripts-call/150_srtp_2_3.py", # temporarily disabled until #1267 done + "scripts-call/301_ice_public_a.py", # Unreliable, proxy returns 408 sometimes + "scripts-call/301_ice_public_b.py", # Doesn't work because OpenSER modifies SDP + "scripts-pres/200_publish.py", # Ok from cmdline, error from runall.py + "scripts-media-playrec/100_resample_lf_8_11.py", # related to clock-rate 11 kHz problem + "scripts-media-playrec/100_resample_lf_8_22.py", # related to clock-rate 22 kHz problem + "scripts-media-playrec/100_resample_lf_11" # related to clock-rate 11 kHz problem + ] + +# Add basic tests +for f in os.listdir("scripts-run"): + tests.append("mod_run.py scripts-run/" + f) + +# Add basic call tests +for f in os.listdir("scripts-call"): + tests.append("mod_call.py scripts-call/" + f) + +# Add presence tests +for f in os.listdir("scripts-pres"): + tests.append("mod_pres.py scripts-pres/" + f) + +# Add mod_sendto tests +for f in os.listdir("scripts-sendto"): + tests.append("mod_sendto.py scripts-sendto/" + f) + +# Add mod_media_playrec tests +for f in os.listdir("scripts-media-playrec"): + tests.append("mod_media_playrec.py scripts-media-playrec/" + f) + +# Add mod_pesq tests +for f in os.listdir("scripts-pesq"): + tests.append("mod_pesq.py scripts-pesq/" + f) + +# Add recvfrom tests +for f in os.listdir("scripts-recvfrom"): + tests.append("mod_recvfrom.py scripts-recvfrom/" + f) + +# Add sipp tests +for f in os.listdir("scripts-sipp"): + if f.endswith(".xml"): + tests.append("mod_sipp.py scripts-sipp/" + f) + +# Filter-out excluded tests +for pat in excluded_tests: + tests = [t for t in tests if t.find(pat)==-1] + + +resume_script="" +shell_cmd="" + +# Parse arguments +sys.argv.pop(0) +while len(sys.argv): + if sys.argv[0]=='/h' or sys.argv[0]=='-h' or sys.argv[0]=='--help' or sys.argv[0]=='/help': + sys.argv.pop(0) + print "Usage:" + print " runall.py [OPTIONS] [run.py-OPTIONS]" + print "OPTIONS:" + print " --list" + print " List the tests" + print " --list-xml" + print " List the tests as XML format suitable for ccdash" + print " --resume,-r RESUME" + print " RESUME is string/substring to specify where to resume tests." + print " If this argument is omited, tests will start from the beginning." + print " --shell,-s SHELL" + print " Run the tests with the specified SHELL cmd. This can also be" + print " used to run the test with ccdash. Example:" + print " --shell '/bin/sh -c'" + print " run.py-OPTIONS are applicable here" + sys.exit(0) + elif sys.argv[0] == '-r' or sys.argv[0] == '--resume': + if len(sys.argv) > 1: + resume_script=sys.argv[1] + sys.argv.pop(0) + sys.argv.pop(0) + else: + sys.argv.pop(0) + sys.stderr.write("Error: argument value required") + sys.exit(1) + elif sys.argv[0] == '--list': + sys.argv.pop(0) + for t in tests: + print t + sys.exit(0) + elif sys.argv[0] == '--list-xml': + sys.argv.pop(0) + for t in tests: + (mod,param) = t.split(None,2) + tname = mod[4:mod.find(".py")] + "_" + \ + param[param.find("/")+1:param.rfind(".")] + c = "" + if len(sys.argv): + c = " ".join(sys.argv) + " " + tcmd = PYTHON + ' run.py ' + c + t + print '\t\t' % (tname, tcmd) + sys.exit(0) + elif sys.argv[0] == '-s' or sys.argv[0] == '--shell': + if len(sys.argv) > 1: + shell_cmd = sys.argv[1] + sys.argv.pop(0) + sys.argv.pop(0) + else: + sys.argv.pop(0) + sys.stderr.write("Error: argument value required") + sys.exit(1) + else: + # should be run.py options + break + + +# Generate arguments for run.py +argv_st = " ".join(sys.argv) + " " + +# Init vars +fails_cnt = 0 +tests_cnt = 0 + +# Re-create "logs" directory +try: + shutil.rmtree("logs") +except: + print "Warning: failed in removing directory 'logs'" + +try: + os.mkdir("logs") +except: + print "Warning: failed in creating directory 'logs'" + +# Now run the tests +total_cnt = len(tests) +for t in tests: + if resume_script!="" and t.find(resume_script)==-1: + print "Skipping " + t +".." + total_cnt = total_cnt - 1 + continue + resume_script="" + cmdline = "python run.py " + argv_st + t + if shell_cmd: + cmdline = "%s '%s'" % (shell_cmd, cmdline) + t0 = time.time() + msg = "Running %d/%d: %s..." % (tests_cnt+1, total_cnt, cmdline) + sys.stdout.write(msg) + sys.stdout.flush() + ret = os.system(cmdline + " > output.log") + t1 = time.time() + if ret != 0: + dur = int(t1 - t0) + print " failed!! [" + str(dur) + "s]" + logname = re.search(".*\s+(.*)", t).group(1) + logname = re.sub("[\\\/]", "_", logname) + logname = re.sub("\.py$", ".log", logname) + logname = re.sub("\.xml$", ".log", logname) + logname = "logs/" + logname + shutil.move("output.log", logname) + print "Please see '" + logname + "' for the test log." + fails_cnt += 1 + else: + dur = int(t1 - t0) + print " ok [" + str(dur) + "s]" + tests_cnt += 1 + +if fails_cnt == 0: + print "All " + str(tests_cnt) + " tests completed successfully" +else: + print str(tests_cnt) + " tests completed, " + str(fails_cnt) + " test(s) failed" + diff --git a/tests/pjsua/scripts-call/100_simplecall.py b/tests/pjsua/scripts-call/100_simplecall.py new file mode 100644 index 0000000..bb26bc9 --- /dev/null +++ b/tests/pjsua/scripts-call/100_simplecall.py @@ -0,0 +1,12 @@ +# $Id: 100_simplecall.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +# Simple call +test_param = TestParam( + "Basic call", + [ + InstanceParam("callee", "--null-audio --max-calls=1"), + InstanceParam("caller", "--null-audio --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_0_1.py b/tests/pjsua/scripts-call/150_srtp_0_1.py new file mode 100644 index 0000000..fc84d6e --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_0_1.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_0_1.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +test_param= TestParam( + "Callee=no SRTP, caller=optional SRTP", + [ + InstanceParam("callee", "--null-audio --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_0_3.py b/tests/pjsua/scripts-call/150_srtp_0_3.py new file mode 100644 index 0000000..59a2259 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_0_3.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_0_3.py 3334 2010-10-05 16:32:04Z nanang $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=no SRTP, caller=optional (with duplicated offer) SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=0 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_1_0.py b/tests/pjsua/scripts-call/150_srtp_1_0.py new file mode 100644 index 0000000..4c44e12 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_1_0.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_1_0.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional SRTP, caller=no SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_1_1.py b/tests/pjsua/scripts-call/150_srtp_1_1.py new file mode 100644 index 0000000..9b78395 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_1_1.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_1_1.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional SRTP, caller=optional SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_1_2.py b/tests/pjsua/scripts-call/150_srtp_1_2.py new file mode 100644 index 0000000..8c2664e --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_1_2.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_1_2.py 2025 2008-06-15 19:43:43Z bennylp $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional SRTP, caller=mandatory SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_1_3.py b/tests/pjsua/scripts-call/150_srtp_1_3.py new file mode 100644 index 0000000..5d181a6 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_1_3.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_1_3.py 3334 2010-10-05 16:32:04Z nanang $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional SRTP, caller=optional (with duplicated offer) SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_2_1.py b/tests/pjsua/scripts-call/150_srtp_2_1.py new file mode 100644 index 0000000..ffd0b3c --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_2_1.py @@ -0,0 +1,12 @@ +# $Id: 150_srtp_2_1.py 2025 2008-06-15 19:43:43Z bennylp $ +# +from inc_cfg import * + +# Simple call +test_param = TestParam( + "Callee=mandatory SRTP, caller=optional SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_2_2.py b/tests/pjsua/scripts-call/150_srtp_2_2.py new file mode 100644 index 0000000..88401f8 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_2_2.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_2_2.py 2025 2008-06-15 19:43:43Z bennylp $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=mandatory SRTP, caller=mandatory SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_2_3.py b/tests/pjsua/scripts-call/150_srtp_2_3.py new file mode 100644 index 0000000..567f567 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_2_3.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_2_3.py 3334 2010-10-05 16:32:04Z nanang $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=mandatory SRTP, caller=optional (with duplicated offer) SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_3_0.py b/tests/pjsua/scripts-call/150_srtp_3_0.py new file mode 100644 index 0000000..af2741c --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_3_0.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_3_0.py 3334 2010-10-05 16:32:04Z nanang $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional (with duplicated offer) SRTP, caller=no SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=0 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_3_1.py b/tests/pjsua/scripts-call/150_srtp_3_1.py new file mode 100644 index 0000000..1a5c3ab --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_3_1.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_3_1.py 3334 2010-10-05 16:32:04Z nanang $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional (with duplicated offer) SRTP, caller=optional SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=1 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_3_2.py b/tests/pjsua/scripts-call/150_srtp_3_2.py new file mode 100644 index 0000000..7175ae6 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_3_2.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_3_2.py 3334 2010-10-05 16:32:04Z nanang $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional (with duplicated offer) SRTP, caller=mandatory SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=2 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/150_srtp_3_3.py b/tests/pjsua/scripts-call/150_srtp_3_3.py new file mode 100644 index 0000000..1ac50e0 --- /dev/null +++ b/tests/pjsua/scripts-call/150_srtp_3_3.py @@ -0,0 +1,11 @@ +# $Id: 150_srtp_3_3.py 3334 2010-10-05 16:32:04Z nanang $ +# +from inc_cfg import * + +test_param = TestParam( + "Callee=optional (with duplicated offer) SRTP, caller=optional (with duplicated offer) SRTP", + [ + InstanceParam("callee", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1"), + InstanceParam("caller", "--null-audio --use-srtp=3 --srtp-secure=0 --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/200_tcp.py b/tests/pjsua/scripts-call/200_tcp.py new file mode 100644 index 0000000..fafb665 --- /dev/null +++ b/tests/pjsua/scripts-call/200_tcp.py @@ -0,0 +1,12 @@ +# $Id: 200_tcp.py 2028 2008-06-16 13:04:44Z bennylp $ +# +from inc_cfg import * + +# TCP call +test_param = TestParam( + "TCP transport", + [ + InstanceParam("callee", "--null-audio --no-udp --max-calls=1", uri_param=";transport=tcp"), + InstanceParam("caller", "--null-audio --no-udp --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/300_ice_0_1.py b/tests/pjsua/scripts-call/300_ice_0_1.py new file mode 100644 index 0000000..c29055c --- /dev/null +++ b/tests/pjsua/scripts-call/300_ice_0_1.py @@ -0,0 +1,12 @@ +# $Id: 300_ice_0_1.py 2025 2008-06-15 19:43:43Z bennylp $ +# +from inc_cfg import * + +# ICE mismatch +test_param = TestParam( + "Callee=no ICE, caller=use ICE", + [ + InstanceParam("callee", "--null-audio --max-calls=1"), + InstanceParam("caller", "--null-audio --use-ice --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/300_ice_1_0.py b/tests/pjsua/scripts-call/300_ice_1_0.py new file mode 100644 index 0000000..1d920b3 --- /dev/null +++ b/tests/pjsua/scripts-call/300_ice_1_0.py @@ -0,0 +1,12 @@ +# $Id: 300_ice_1_0.py 2025 2008-06-15 19:43:43Z bennylp $ +# +from inc_cfg import * + +# ICE mismatch +test_param = TestParam( + "Callee=use ICE, caller=no ICE", + [ + InstanceParam("callee", "--null-audio --use-ice --max-calls=1"), + InstanceParam("caller", "--null-audio --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/300_ice_1_1.py b/tests/pjsua/scripts-call/300_ice_1_1.py new file mode 100644 index 0000000..faed5fb --- /dev/null +++ b/tests/pjsua/scripts-call/300_ice_1_1.py @@ -0,0 +1,12 @@ +# $Id: 300_ice_1_1.py 2084 2008-06-27 23:53:00Z bennylp $ +# +from inc_cfg import * + +# ICE mismatch +test_param = TestParam( + "Callee=use ICE, caller=use ICE", + [ + InstanceParam("callee", "--null-audio --use-ice --max-calls=1", enable_buffer=True), + InstanceParam("caller", "--null-audio --use-ice --max-calls=1", enable_buffer=True) + ] + ) diff --git a/tests/pjsua/scripts-call/301_ice_public_a.py b/tests/pjsua/scripts-call/301_ice_public_a.py new file mode 100644 index 0000000..3b63a18 --- /dev/null +++ b/tests/pjsua/scripts-call/301_ice_public_a.py @@ -0,0 +1,22 @@ +# $Id: 301_ice_public_a.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +# Note: +# - need --dis-codec to make INVITE packet less than typical MTU +uas_args = "--null-audio --id=\"\" --registrar=sip:sip.pjsip.org --username=test1 --password=test1 --realm=pjsip.org --proxy=\"sip:sip.pjsip.org;lr\" --rtp-port 0 --stun-srv stun.pjsip.org --use-ice --use-compact-form --max-calls 1 --dis-codec=i --dis-codec=s --dis-codec=g" + +uac_args = "--null-audio --id=\"\" --registrar=sip:sip.pjsip.org --username=test2 --password=test2 --realm=pjsip.org --proxy=\"sip:sip.pjsip.org;lr\" --rtp-port 0 --stun-srv stun.pjsip.org --use-ice --use-compact-form --max-calls 1 --dis-codec=i --dis-codec=s --dis-codec=g" + +test_param = TestParam( + "ICE via public internet", + [ + InstanceParam( "callee", uas_args, + uri="", + have_reg=True, have_publish=False), + InstanceParam( "caller", uac_args, + uri="", + have_reg=True, have_publish=False), + ] + ) + diff --git a/tests/pjsua/scripts-call/301_ice_public_b.py b/tests/pjsua/scripts-call/301_ice_public_b.py new file mode 100644 index 0000000..ba54a88 --- /dev/null +++ b/tests/pjsua/scripts-call/301_ice_public_b.py @@ -0,0 +1,25 @@ +# $Id: 301_ice_public_b.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +# This test: +# to make call with ICE but without STUN. + +# Note: +# - need --dis-codec to make INVITE packet less than typical MTU +uas_args = "--null-audio --id=\"\" --registrar=sip:sip.pjsip.org --username=test1 --password=test1 --realm=pjsip.org --proxy=\"sip:sip.pjsip.org;lr\" --rtp-port 0 --use-ice --use-compact-form --max-calls 1 --dis-codec=i --dis-codec=s --dis-codec=g --log-file callee.log" + +uac_args = "--null-audio --id=\"\" --registrar=sip:sip.pjsip.org --username=test2 --password=test2 --realm=pjsip.org --proxy=\"sip:sip.pjsip.org;lr\" --rtp-port 0 --use-ice --use-compact-form --max-calls 1 --dis-codec=i --dis-codec=s --dis-codec=g --log-file caller.log" + +test_param = TestParam( + "ICE via public internet with no STUN", + [ + InstanceParam( "callee", uas_args, + uri="", + have_reg=True, have_publish=False), + InstanceParam( "caller", uac_args, + uri="", + have_reg=True, have_publish=False), + ] + ) + diff --git a/tests/pjsua/scripts-call/305_ice_comp_1_2.py b/tests/pjsua/scripts-call/305_ice_comp_1_2.py new file mode 100644 index 0000000..d9717e6 --- /dev/null +++ b/tests/pjsua/scripts-call/305_ice_comp_1_2.py @@ -0,0 +1,12 @@ +# $Id: 305_ice_comp_1_2.py 2196 2008-08-07 09:55:52Z bennylp $ +# +from inc_cfg import * + +# Different number of ICE components +test_param = TestParam( + "Callee=use ICE, caller=use ICE", + [ + InstanceParam("callee", "--null-audio --use-ice --max-calls=1 --ice-no-rtcp", enable_buffer=True), + InstanceParam("caller", "--null-audio --use-ice --max-calls=1", enable_buffer=True) + ] + ) diff --git a/tests/pjsua/scripts-call/305_ice_comp_2_1.py b/tests/pjsua/scripts-call/305_ice_comp_2_1.py new file mode 100644 index 0000000..57bd548 --- /dev/null +++ b/tests/pjsua/scripts-call/305_ice_comp_2_1.py @@ -0,0 +1,12 @@ +# $Id: 305_ice_comp_2_1.py 2196 2008-08-07 09:55:52Z bennylp $ +# +from inc_cfg import * + +# Different number of ICE components +test_param = TestParam( + "Callee=use ICE, caller=use ICE", + [ + InstanceParam("callee", "--null-audio --use-ice --max-calls=1", enable_buffer=True), + InstanceParam("caller", "--null-audio --use-ice --max-calls=1 --ice-no-rtcp", enable_buffer=True) + ] + ) diff --git a/tests/pjsua/scripts-call/350_prack_a.py b/tests/pjsua/scripts-call/350_prack_a.py new file mode 100644 index 0000000..b018473 --- /dev/null +++ b/tests/pjsua/scripts-call/350_prack_a.py @@ -0,0 +1,12 @@ +# $Id: 350_prack_a.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +# TCP call +test_param = TestParam( + "Callee requires PRACK", + [ + InstanceParam("callee", "--null-audio --max-calls=1 --use-100rel"), + InstanceParam("caller", "--null-audio --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-call/350_prack_b.py b/tests/pjsua/scripts-call/350_prack_b.py new file mode 100644 index 0000000..f2b5673 --- /dev/null +++ b/tests/pjsua/scripts-call/350_prack_b.py @@ -0,0 +1,12 @@ +# $Id: 350_prack_b.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +# TCP call +test_param = TestParam( + "Caller requires PRACK", + [ + InstanceParam("callee", "--null-audio --max-calls=1"), + InstanceParam("caller", "--null-audio --max-calls=1 --use-100rel") + ] + ) diff --git a/tests/pjsua/scripts-call/400_tel_uri.py b/tests/pjsua/scripts-call/400_tel_uri.py new file mode 100644 index 0000000..114208f --- /dev/null +++ b/tests/pjsua/scripts-call/400_tel_uri.py @@ -0,0 +1,12 @@ +# $Id: 400_tel_uri.py 3323 2010-09-28 07:43:18Z bennylp $ +# +from inc_cfg import * + +# Simple call +test_param = TestParam( + "tel: URI in From", + [ + InstanceParam("callee", "--null-audio --max-calls=1 --id tel:+111"), + InstanceParam("caller", "--null-audio --max-calls=1") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_11_16.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_16.py new file mode 100644 index 0000000..40651d7 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_16.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_11_16.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 16 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 16000 --play-file wavs/input.11.wav --rec-file wavs/tmp.16.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_11_22.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_22.py new file mode 100644 index 0000000..23e6a9e --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_22.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_11_22.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 22 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 22050 --play-file wavs/input.11.wav --rec-file wavs/tmp.22.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_11_32.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_32.py new file mode 100644 index 0000000..0edccf8 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_32.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_11_32.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 32 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 32000 --play-file wavs/input.11.wav --rec-file wavs/tmp.32.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_11_44.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_44.py new file mode 100644 index 0000000..455eea9 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_44.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_11_44.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 44 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 44100 --play-file wavs/input.11.wav --rec-file wavs/tmp.44.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_11_48.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_48.py new file mode 100644 index 0000000..46c4d36 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_48.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_11_48.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 48 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 48000 --play-file wavs/input.11.wav --rec-file wavs/tmp.48.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_11_8.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_8.py new file mode 100644 index 0000000..cbef3e4 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_11_8.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_11_8.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 11 KHZ to 8 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 8000 --play-file wavs/input.11.wav --rec-file wavs/tmp.8.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_8_11.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_11.py new file mode 100644 index 0000000..c463203 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_11.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_8_11.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 11 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 11025 --play-file wavs/input.8.wav --rec-file wavs/tmp.11.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_8_16.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_16.py new file mode 100644 index 0000000..9fcb870 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_16.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_8_16.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 16 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 16000 --play-file wavs/input.8.wav --rec-file wavs/tmp.16.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_8_22.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_22.py new file mode 100644 index 0000000..37fa531 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_22.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_8_22.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 22 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 22050 --play-file wavs/input.8.wav --rec-file wavs/tmp.22.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_8_32.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_32.py new file mode 100644 index 0000000..dfeb4b4 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_32.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_8_32.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 32 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 32000 --play-file wavs/input.8.wav --rec-file wavs/tmp.32.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_8_44.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_44.py new file mode 100644 index 0000000..da5e570 --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_44.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_8_44.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 44 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 44100 --play-file wavs/input.8.wav --rec-file wavs/tmp.44.wav") + ] + ) diff --git a/tests/pjsua/scripts-media-playrec/100_resample_lf_8_48.py b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_48.py new file mode 100644 index 0000000..cb314da --- /dev/null +++ b/tests/pjsua/scripts-media-playrec/100_resample_lf_8_48.py @@ -0,0 +1,11 @@ +# $Id: 100_resample_lf_8_48.py 2052 2008-06-25 18:18:32Z nanang $ +# +from inc_cfg import * + +# simple test +test_param = TestParam( + "Resample (large filter) 8 KHZ to 48 KHZ", + [ + InstanceParam("endpt", "--null-audio --quality 10 --clock-rate 48000 --play-file wavs/input.8.wav --rec-file wavs/tmp.48.wav") + ] + ) diff --git a/tests/pjsua/scripts-pesq/100_defaults.py b/tests/pjsua/scripts-pesq/100_defaults.py new file mode 100644 index 0000000..51737ba --- /dev/null +++ b/tests/pjsua/scripts-pesq/100_defaults.py @@ -0,0 +1,19 @@ +# $Id: 100_defaults.py 3286 2010-08-18 14:30:15Z bennylp $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with default pjsua settings +test_param = TestParam( + "PESQ defaults pjsua settings", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --play-file wavs/input.16.wav --no-vad"), + InstanceParam("UA2", "--null-audio --max-calls=1 --rec-file wavs/tmp.16.wav --clock-rate 16000 --auto-answer 200") + ] + ) + +pesq_threshold = 3.8 diff --git a/tests/pjsua/scripts-pesq/101_defaults.py b/tests/pjsua/scripts-pesq/101_defaults.py new file mode 100644 index 0000000..97e208d --- /dev/null +++ b/tests/pjsua/scripts-pesq/101_defaults.py @@ -0,0 +1,18 @@ +# $Id: 101_defaults.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with default pjsua settings +test_param = TestParam( + "PESQ defaults pjsua settings (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --play-file wavs/input.16.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --rec-file wavs/tmp.16.wav --clock-rate 16000 --auto-answer 200") + ] + ) + + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = None diff --git a/tests/pjsua/scripts-pesq/200_codec_g711a.py b/tests/pjsua/scripts-pesq/200_codec_g711a.py new file mode 100644 index 0000000..7b73e37 --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_g711a.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_g711a.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with PCMA codec +test_param = TestParam( + "PESQ codec PCMA", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec pcma --clock-rate 8000 --play-file wavs/input.8.wav"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec pcma --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/200_codec_g711u.py b/tests/pjsua/scripts-pesq/200_codec_g711u.py new file mode 100644 index 0000000..acb0147 --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_g711u.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_g711u.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with PCMU codec +test_param = TestParam( + "PESQ codec PCMU", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec pcmu --clock-rate 8000 --play-file wavs/input.8.wav"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec pcmu --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/200_codec_g722.py b/tests/pjsua/scripts-pesq/200_codec_g722.py new file mode 100644 index 0000000..30b14b2 --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_g722.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_g722.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with G722 codec +test_param = TestParam( + "PESQ codec G722", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec g722 --clock-rate 16000 --play-file wavs/input.16.wav"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec g722 --clock-rate 16000 --rec-file wavs/tmp.16.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.7 diff --git a/tests/pjsua/scripts-pesq/200_codec_gsm.py b/tests/pjsua/scripts-pesq/200_codec_gsm.py new file mode 100644 index 0000000..2be167a --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_gsm.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_gsm.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with GSM codec +test_param = TestParam( + "PESQ codec GSM", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec gsm --clock-rate 8000 --play-file wavs/input.8.wav"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec gsm --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.0 diff --git a/tests/pjsua/scripts-pesq/200_codec_ilbc.py b/tests/pjsua/scripts-pesq/200_codec_ilbc.py new file mode 100644 index 0000000..aff193c --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_ilbc.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_ilbc.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with iLBC codec +test_param = TestParam( + "PESQ codec iLBC", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec ilbc --clock-rate 8000 --play-file wavs/input.8.wav"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec ilbc --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.0 diff --git a/tests/pjsua/scripts-pesq/200_codec_l16_16000.py b/tests/pjsua/scripts-pesq/200_codec_l16_16000.py new file mode 100644 index 0000000..dc202fa --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_l16_16000.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_l16_16000.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with L16/16000/1 codec +test_param = TestParam( + "PESQ codec L16/16000/1", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec L16/16000/1 --clock-rate 16000 --play-file wavs/input.16.wav"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec L16/16000/1 --clock-rate 16000 --rec-file wavs/tmp.16.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/200_codec_l16_16000_stereo.py b/tests/pjsua/scripts-pesq/200_codec_l16_16000_stereo.py new file mode 100644 index 0000000..4dbc132 --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_l16_16000_stereo.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_l16_16000_stereo.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with L16/16000/2 codec +test_param = TestParam( + "PESQ defaults pjsua settings", + [ + InstanceParam("UA1", ADD_PARAM + " --stereo --max-calls=1 --clock-rate 16000 --add-codec L16/16000/2 --play-file wavs/input.2.16.wav"), + InstanceParam("UA2", "--null-audio --stereo --max-calls=1 --clock-rate 16000 --add-codec L16/16000/2 --rec-file wavs/tmp.2.16.wav --auto-answer 200") + ] + ) + +pesq_threshold = None diff --git a/tests/pjsua/scripts-pesq/200_codec_l16_8000.py b/tests/pjsua/scripts-pesq/200_codec_l16_8000.py new file mode 100644 index 0000000..34a9bb2 --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_l16_8000.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_l16_8000.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with L16/8000/1 codec +test_param = TestParam( + "PESQ codec L16/8000/1", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec L16/8000/1 --clock-rate 8000 --play-file wavs/input.8.wav"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec L16/8000/1 --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/200_codec_l16_8000_stereo.py b/tests/pjsua/scripts-pesq/200_codec_l16_8000_stereo.py new file mode 100644 index 0000000..755050e --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_l16_8000_stereo.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_l16_8000_stereo.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with L16/8000/2 codec +test_param = TestParam( + "PESQ defaults pjsua settings", + [ + InstanceParam("UA1", ADD_PARAM + " --stereo --max-calls=1 --clock-rate 8000 --add-codec L16/8000/2 --play-file wavs/input.2.8.wav"), + InstanceParam("UA2", "--null-audio --stereo --max-calls=1 --clock-rate 8000 --add-codec L16/8000/2 --rec-file wavs/tmp.2.8.wav --auto-answer 200") + ] + ) + +pesq_threshold = None diff --git a/tests/pjsua/scripts-pesq/200_codec_speex_16000.py b/tests/pjsua/scripts-pesq/200_codec_speex_16000.py new file mode 100644 index 0000000..bdacba9 --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_speex_16000.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_speex_16000.py 3286 2010-08-18 14:30:15Z bennylp $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with Speex/16000 codec +test_param = TestParam( + "PESQ codec Speex WB", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --clock-rate 16000 --add-codec speex/16000 --play-file wavs/input.16.wav --no-vad"), + InstanceParam("UA2", "--null-audio --max-calls=1 --clock-rate 16000 --add-codec speex/16000 --rec-file wavs/tmp.16.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.8 diff --git a/tests/pjsua/scripts-pesq/200_codec_speex_8000.py b/tests/pjsua/scripts-pesq/200_codec_speex_8000.py new file mode 100644 index 0000000..9c7c7df --- /dev/null +++ b/tests/pjsua/scripts-pesq/200_codec_speex_8000.py @@ -0,0 +1,19 @@ +# $Id: 200_codec_speex_8000.py 3286 2010-08-18 14:30:15Z bennylp $ +# +from inc_cfg import * + +ADD_PARAM = "" + +if (HAS_SND_DEV == 0): + ADD_PARAM += "--null-audio" + +# Call with Speex/8000 codec +test_param = TestParam( + "PESQ codec Speex NB", + [ + InstanceParam("UA1", ADD_PARAM + " --max-calls=1 --add-codec speex/8000 --clock-rate 8000 --play-file wavs/input.8.wav --no-vad"), + InstanceParam("UA2", "--null-audio --max-calls=1 --add-codec speex/8000 --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +pesq_threshold = 3.65 diff --git a/tests/pjsua/scripts-pesq/201_codec_g711a.py b/tests/pjsua/scripts-pesq/201_codec_g711a.py new file mode 100644 index 0000000..7e7e744 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_g711a.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_g711a.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with PCMA codec +test_param = TestParam( + "PESQ codec PCMA (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec pcma --clock-rate 8000 --play-file wavs/input.8.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec pcma --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/201_codec_g711u.py b/tests/pjsua/scripts-pesq/201_codec_g711u.py new file mode 100644 index 0000000..77f9e22 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_g711u.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_g711u.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with PCMU codec +test_param = TestParam( + "PESQ codec PCMU (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec pcmu --clock-rate 8000 --play-file wavs/input.8.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec pcmu --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/201_codec_g722.py b/tests/pjsua/scripts-pesq/201_codec_g722.py new file mode 100644 index 0000000..ce959a0 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_g722.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_g722.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with G722 codec +test_param = TestParam( + "PESQ codec G722 (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec g722 --clock-rate 16000 --play-file wavs/input.16.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec g722 --clock-rate 16000 --rec-file wavs/tmp.16.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.7 diff --git a/tests/pjsua/scripts-pesq/201_codec_gsm.py b/tests/pjsua/scripts-pesq/201_codec_gsm.py new file mode 100644 index 0000000..44443b0 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_gsm.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_gsm.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with GSM codec +test_param = TestParam( + "PESQ codec GSM (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec gsm --clock-rate 8000 --play-file wavs/input.8.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec gsm --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.0 diff --git a/tests/pjsua/scripts-pesq/201_codec_ilbc.py b/tests/pjsua/scripts-pesq/201_codec_ilbc.py new file mode 100644 index 0000000..b04a8c2 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_ilbc.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_ilbc.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with iLBC codec +test_param = TestParam( + "PESQ codec iLBC (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec ilbc --clock-rate 8000 --play-file wavs/input.8.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec ilbc --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.0 diff --git a/tests/pjsua/scripts-pesq/201_codec_l16_16000.py b/tests/pjsua/scripts-pesq/201_codec_l16_16000.py new file mode 100644 index 0000000..efd7744 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_l16_16000.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_l16_16000.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +# Call with L16/16000/1 codec +test_param = TestParam( + "PESQ codec L16/16000/1 (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec L16/16000/1 --clock-rate 16000 --play-file wavs/input.16.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec L16/16000/1 --clock-rate 16000 --rec-file wavs/tmp.16.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/201_codec_l16_16000_stereo.py b/tests/pjsua/scripts-pesq/201_codec_l16_16000_stereo.py new file mode 100644 index 0000000..c312218 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_l16_16000_stereo.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_l16_16000_stereo.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +# Call with L16/16000/2 codec +test_param = TestParam( + "PESQ defaults pjsua settings", + [ + InstanceParam("UA1", "--stereo --max-calls=1 --clock-rate 16000 --add-codec L16/16000/2 --play-file wavs/input.2.16.wav --null-audio"), + InstanceParam("UA2", "--stereo --max-calls=1 --clock-rate 16000 --add-codec L16/16000/2 --rec-file wavs/tmp.2.16.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = None diff --git a/tests/pjsua/scripts-pesq/201_codec_l16_8000.py b/tests/pjsua/scripts-pesq/201_codec_l16_8000.py new file mode 100644 index 0000000..90e2de9 --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_l16_8000.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_l16_8000.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +# Call with L16/8000/1 codec +test_param = TestParam( + "PESQ codec L16/8000/1 (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec L16/8000/1 --clock-rate 8000 --play-file wavs/input.8.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec L16/8000/1 --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.5 diff --git a/tests/pjsua/scripts-pesq/201_codec_l16_8000_stereo.py b/tests/pjsua/scripts-pesq/201_codec_l16_8000_stereo.py new file mode 100644 index 0000000..434a4ea --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_l16_8000_stereo.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_l16_8000_stereo.py 2075 2008-06-27 16:18:13Z nanang $ +# +from inc_cfg import * + +# Call with L16/8000/2 codec +test_param = TestParam( + "PESQ defaults pjsua settings", + [ + InstanceParam("UA1", "--stereo --max-calls=1 --clock-rate 8000 --add-codec L16/8000/2 --play-file wavs/input.2.8.wav --null-audio"), + InstanceParam("UA2", "--stereo --max-calls=1 --clock-rate 8000 --add-codec L16/8000/2 --rec-file wavs/tmp.2.8.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = None diff --git a/tests/pjsua/scripts-pesq/201_codec_speex_16000.py b/tests/pjsua/scripts-pesq/201_codec_speex_16000.py new file mode 100644 index 0000000..92f3ccc --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_speex_16000.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_speex_16000.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with Speex/16000 codec +test_param = TestParam( + "PESQ codec Speex WB (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --clock-rate 16000 --add-codec speex/16000 --play-file wavs/input.16.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --clock-rate 16000 --add-codec speex/16000 --rec-file wavs/tmp.16.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.7 diff --git a/tests/pjsua/scripts-pesq/201_codec_speex_8000.py b/tests/pjsua/scripts-pesq/201_codec_speex_8000.py new file mode 100644 index 0000000..b48dcba --- /dev/null +++ b/tests/pjsua/scripts-pesq/201_codec_speex_8000.py @@ -0,0 +1,17 @@ +# $Id: 201_codec_speex_8000.py 2063 2008-06-26 18:52:16Z nanang $ +# +from inc_cfg import * + +# Call with Speex/8000 codec +test_param = TestParam( + "PESQ codec Speex NB (RX side uses snd dev)", + [ + InstanceParam("UA1", "--max-calls=1 --add-codec speex/8000 --clock-rate 8000 --play-file wavs/input.8.wav --null-audio"), + InstanceParam("UA2", "--max-calls=1 --add-codec speex/8000 --clock-rate 8000 --rec-file wavs/tmp.8.wav --auto-answer 200") + ] + ) + +if (HAS_SND_DEV == 0): + test_param.skip = True + +pesq_threshold = 3.0 diff --git a/tests/pjsua/scripts-pres/100_peertopeer.py b/tests/pjsua/scripts-pres/100_peertopeer.py new file mode 100644 index 0000000..a35f981 --- /dev/null +++ b/tests/pjsua/scripts-pres/100_peertopeer.py @@ -0,0 +1,12 @@ +# $Id: 100_peertopeer.py 2392 2008-12-22 18:54:58Z bennylp $ +# +from inc_cfg import * + +# Direct peer to peer presence +test_param = TestParam( + "Direct peer to peer presence", + [ + InstanceParam("client1", "--null-audio"), + InstanceParam("client2", "--null-audio") + ] + ) diff --git a/tests/pjsua/scripts-pres/200_publish.py b/tests/pjsua/scripts-pres/200_publish.py new file mode 100644 index 0000000..d06b190 --- /dev/null +++ b/tests/pjsua/scripts-pres/200_publish.py @@ -0,0 +1,35 @@ +# $Id: 200_publish.py 2028 2008-06-16 13:04:44Z bennylp $ +# +from inc_cfg import * + +# Basic registration +test_param = TestParam( + "Presence with PUBLISH", + [ + InstanceParam( "ua1", + "--null-audio"+ + " --id=\"\""+ + " --registrar=sip:sip.pjsip.org" + + " --username=test1" + + " --password=test1" + + " --realm=*" + + " --proxy=\"sip:sip.pjsip.org;lr\"" + + " --publish", + uri="", + have_reg=True, + have_publish=True), + InstanceParam( "ua2", + "--null-audio"+ + " --id=\"\""+ + " --registrar=sip:sip.pjsip.org" + + " --username=test2" + + " --password=test2" + + " --realm=*" + + " --proxy=\"sip:sip.pjsip.org;lr\"" + + " --publish", + uri="", + have_reg=True, + have_publish=True), + ] + ) + diff --git a/tests/pjsua/scripts-recvfrom/100_simple.py b/tests/pjsua/scripts-recvfrom/100_simple.py new file mode 100644 index 0000000..7f65ee1 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/100_simple.py @@ -0,0 +1,16 @@ +# $Id: 100_simple.py 3284 2010-08-18 07:38:48Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--auto-update-nat=0" + +req1 = sip.RecvfromTransaction("Registration", 200, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["Server: Snake Registrar", "Expires: 221", "Contact: sip:localhost"], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Simple registration test", + pjsua, [req1]) diff --git a/tests/pjsua/scripts-recvfrom/200_reg_good_enocredentiall.py b/tests/pjsua/scripts-recvfrom/200_reg_good_enocredentiall.py new file mode 100644 index 0000000..3df45db --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/200_reg_good_enocredentiall.py @@ -0,0 +1,15 @@ +# $Id: 200_reg_good_enocredentiall.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT" + +req1 = sip.RecvfromTransaction("", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1234\""], + expect="PJSIP_ENOCREDENTIAL" + ) + +recvfrom_cfg = sip.RecvfromCfg("Failed registration test", + pjsua, [req1]) diff --git a/tests/pjsua/scripts-recvfrom/201_reg_good_ok.py b/tests/pjsua/scripts-recvfrom/201_reg_good_ok.py new file mode 100644 index 0000000..c6f524a --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/201_reg_good_ok.py @@ -0,0 +1,23 @@ +# $Id: 201_reg_good_ok.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--username user --realm python --password passwd --auto-update-nat=0" + +req1 = sip.RecvfromTransaction("Initial registration", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1234\""], + expect="SIP/2.0 401" + ) + +req2 = sip.RecvfromTransaction("Registration retry with auth", 200, + include=["REGISTER sip", "Authorization:", + "realm=\"python\"", "username=\"user\"", + "nonce=\"1234\"", "response="], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Successful registration test", + pjsua, [req1, req2]) diff --git a/tests/pjsua/scripts-recvfrom/202_reg_good_ok_wildcard.py b/tests/pjsua/scripts-recvfrom/202_reg_good_ok_wildcard.py new file mode 100644 index 0000000..524d4cd --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/202_reg_good_ok_wildcard.py @@ -0,0 +1,23 @@ +# $Id: 202_reg_good_ok_wildcard.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--username user --realm \"*\" --password passwd --auto-update-nat=0" + +req1 = sip.RecvfromTransaction("Initial registration", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1234\""], + expect="SIP/2.0 401" + ) + +req2 = sip.RecvfromTransaction("Registration retry with auth", 200, + include=["REGISTER sip", "Authorization:", + "realm=\"python\"", "username=\"user\"", + "nonce=\"1234\"", "response="], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Successful registration with wildcard realm test", + pjsua, [req1, req2]) diff --git a/tests/pjsua/scripts-recvfrom/203_reg_good_empty_realm.py b/tests/pjsua/scripts-recvfrom/203_reg_good_empty_realm.py new file mode 100644 index 0000000..e936438 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/203_reg_good_empty_realm.py @@ -0,0 +1,31 @@ +# $Id: 203_reg_good_empty_realm.py 3150 2010-04-29 00:23:43Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=* --user=username --password=password " + \ + "--auto-update-nat=0" + +# 401 Response, missing realm value +req1 = sip.RecvfromTransaction("Initial request", 401, + include=["REGISTER sip"], + exclude=[], + resp_hdr=['WWW-Authenticate: Digest'] + ) + +# Client should retry, we giving it another 401 with empty realm +req2 = sip.RecvfromTransaction("REGISTER retry #1 of 2", 407, + include=["REGISTER sip"], + exclude=[], + resp_hdr=['Proxy-Authenticate: Digest realm=""'] + ) + +# Client should retry +req3 = sip.RecvfromTransaction("REGISTER retry #2 of 2", 200, + include=[], + exclude=[], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Registration with empty realm", + pjsua, [req1, req2, req3]) diff --git a/tests/pjsua/scripts-recvfrom/205_reg_good_no_realm.py b/tests/pjsua/scripts-recvfrom/205_reg_good_no_realm.py new file mode 100644 index 0000000..5343854 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/205_reg_good_no_realm.py @@ -0,0 +1,16 @@ +# $Id: 205_reg_good_no_realm.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=provider --user=username --password=password" + +req1 = sip.RecvfromTransaction("", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1234\""], + expect="PJSIP_ENOCREDENTIAL" + ) + +recvfrom_cfg = sip.RecvfromCfg("Failed registration because of realm test", + pjsua, [req1]) diff --git a/tests/pjsua/scripts-recvfrom/206_reg_good_efailedcredential.py b/tests/pjsua/scripts-recvfrom/206_reg_good_efailedcredential.py new file mode 100644 index 0000000..9cd5ecb --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/206_reg_good_efailedcredential.py @@ -0,0 +1,26 @@ +# $Id: 206_reg_good_efailedcredential.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Authentication failure test with same nonce + + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password" + +req1 = sip.RecvfromTransaction("Initial request", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1\""] + ) + +req2 = sip.RecvfromTransaction("REGISTER retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"1\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1\""], + expect="PJSIP_EFAILEDCREDENTIAL" + ) + + +recvfrom_cfg = sip.RecvfromCfg("Authentication failure with same nonce", + pjsua, [req1, req2]) diff --git a/tests/pjsua/scripts-recvfrom/208_reg_good_retry_nonce_ok.py b/tests/pjsua/scripts-recvfrom/208_reg_good_retry_nonce_ok.py new file mode 100644 index 0000000..ef862d0 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/208_reg_good_retry_nonce_ok.py @@ -0,0 +1,29 @@ +# $Id: 208_reg_good_retry_nonce_ok.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password " + \ + "--auto-update-nat=0" + +req1 = sip.RecvfromTransaction("Initial request", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1\""] + ) + +req2 = sip.RecvfromTransaction("REGISTER first retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"1\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"2\", stale=true"] + ) + + +req3 = sip.RecvfromTransaction("REGISTER retry with new nonce", 200, + include=["REGISTER sip", "Authorization", "nonce=\"2\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Authentication okay after retry with new nonce", + pjsua, [req1, req2, req3]) diff --git a/tests/pjsua/scripts-recvfrom/209a_reg_handle_423_ok.py b/tests/pjsua/scripts-recvfrom/209a_reg_handle_423_ok.py new file mode 100644 index 0000000..2b57342 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/209a_reg_handle_423_ok.py @@ -0,0 +1,31 @@ +# $Id: 209a_reg_handle_423_ok.py 3105 2010-02-23 11:03:07Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password " + \ + "--auto-update-nat=0" + +# 423 Response without Min-Expires header +req1 = sip.RecvfromTransaction("Initial request", 423, + include=["REGISTER sip"], + exclude=[], + resp_hdr=[] + ) + +# Client should retry with Expires header containing special value (pjsip specific) +req2 = sip.RecvfromTransaction("REGISTER retry after 423 response without Min-Expires header", 423, + include=["REGISTER sip", "Expires: 3601"], + exclude=[], + resp_hdr=["Min-Expires: 3612"] + ) + +# Client should retry with proper Expires header now +req3 = sip.RecvfromTransaction("REGISTER retry after proper 423", 200, + include=["Expires: 3612"], + exclude=[], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Reregistration after 423 response", + pjsua, [req1, req2, req3]) diff --git a/tests/pjsua/scripts-recvfrom/209b_reg_handle_423_bad_min_expires1.py b/tests/pjsua/scripts-recvfrom/209b_reg_handle_423_bad_min_expires1.py new file mode 100644 index 0000000..3c22109 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/209b_reg_handle_423_bad_min_expires1.py @@ -0,0 +1,20 @@ +# $Id: 209b_reg_handle_423_bad_min_expires1.py 3105 2010-02-23 11:03:07Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password " + \ + "--auto-update-nat=0 --reg-timeout 300" + +# 423 Response with Min-Expires header that is lower than what the client +# had requested +req1 = sip.RecvfromTransaction("Initial request", 423, + include=["REGISTER sip"], + exclude=[], + resp_hdr=["Min-Expires: 250"], + expect="invalid Min-Expires" + + ) + +recvfrom_cfg = sip.RecvfromCfg("Invalid 423 response to REGISTER", + pjsua, [req1]) diff --git a/tests/pjsua/scripts-recvfrom/209c_reg_handle_423_bad_min_expires2.py b/tests/pjsua/scripts-recvfrom/209c_reg_handle_423_bad_min_expires2.py new file mode 100644 index 0000000..68fda46 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/209c_reg_handle_423_bad_min_expires2.py @@ -0,0 +1,25 @@ +# $Id: 209c_reg_handle_423_bad_min_expires2.py 3105 2010-02-23 11:03:07Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password " + \ + "--auto-update-nat=0 --reg-timeout 300" + +# 423 without Min-Expires. PJSIP would retry with Expires: 3601 +req1 = sip.RecvfromTransaction("Initial request", 423, + include=["REGISTER sip"], + exclude=[], + resp_hdr=[] + ) + +# Another 423, still without Min-Expires +req2 = sip.RecvfromTransaction("Retry with guessed Expires header", 423, + include=["REGISTER sip", "Expires: 3601"], + exclude=[], + resp_hdr=[], + expect="without Min-Expires header is invalid" + ) + +recvfrom_cfg = sip.RecvfromCfg("Invalid 423 response to REGISTER", + pjsua, [req1, req2]) diff --git a/tests/pjsua/scripts-recvfrom/215_reg_good_multi_ok.py b/tests/pjsua/scripts-recvfrom/215_reg_good_multi_ok.py new file mode 100644 index 0000000..4b63a5e --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/215_reg_good_multi_ok.py @@ -0,0 +1,28 @@ +# $Id: 215_reg_good_multi_ok.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--username theuser1 --realm python1 --password passwd --next-cred " + \ + "--username theuser2 --realm python2 --password passwd " + \ + "--auto-update-nat=0" + +req1 = sip.RecvfromTransaction("Initial registration", 401, + include=["REGISTER sip"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python1\", nonce=\"1234\"", + "WWW-Authenticate: Digest realm=\"python2\", nonce=\"6789\""], + expect="SIP/2.0 401" + ) + +req2 = sip.RecvfromTransaction("Registration retry with auth", 200, + include=["REGISTER sip", + "Authorization:[\\s\\S]+Authorization:", # Must have 2 Auth hdrs + "realm=\"python1\"", "realm=\"python2\"", + "username=\"theuser1\"", "username=\"theuser2\"", + "nonce=\"1234\"", "nonce=\"6789\"", + "response="], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Multiple authentication challenges", + pjsua, [req1, req2]) diff --git a/tests/pjsua/scripts-recvfrom/220_reg_good_ims_ok.py b/tests/pjsua/scripts-recvfrom/220_reg_good_ims_ok.py new file mode 100644 index 0000000..4d1ff16 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/220_reg_good_ims_ok.py @@ -0,0 +1,26 @@ +# $Id: 220_reg_good_ims_ok.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--username user@ims-domain --realm python --password passwd --use-ims --auto-update-nat=0" + +req1 = sip.RecvfromTransaction("Initial registration", 401, + include=["REGISTER sip", "Authorization", + "username=\"user@ims-domain\"", + "realm=\"python\""], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1234\""], + expect="SIP/2.0 401" + ) + +req2 = sip.RecvfromTransaction("Registration retry with auth", 200, + include=["REGISTER sip", "Authorization:", + "realm=\"python\"", "username=\"user@ims-domain\"", + "nonce=\"1234\"", "response="], + # Must not have double Authorization header: + exclude=["Authorization:[\\s\\S]+Authorization:"], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Successful IMS registration test", + pjsua, [req1, req2]) diff --git a/tests/pjsua/scripts-recvfrom/230_reg_bad_fail_stale_true.py b/tests/pjsua/scripts-recvfrom/230_reg_bad_fail_stale_true.py new file mode 100644 index 0000000..cfd7d00 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/230_reg_bad_fail_stale_true.py @@ -0,0 +1,41 @@ +# $Id: 230_reg_bad_fail_stale_true.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# In this test we simulate broken server, where it always sends +# stale=true with all 401 responses. We should expect pjsip to +# retry the authentication until PJSIP_MAX_STALE_COUNT is +# exceeded. When pjsip retries the authentication, it should +# use the new nonce from server + + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password" + +req1 = sip.RecvfromTransaction("Initial request", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1\""] + ) + +req2 = sip.RecvfromTransaction("First retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"1\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"2\", stale=true"] + ) + +req3 = sip.RecvfromTransaction("Second retry retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"2\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"3\", stale=true"] + ) + +req4 = sip.RecvfromTransaction("Third retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"3\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"4\", stale=true"], + expect="PJSIP_EAUTHSTALECOUNT" + ) + +recvfrom_cfg = sip.RecvfromCfg("Failed registration retry (server rejects with stale=true) ", + pjsua, [req1, req2, req3, req4]) diff --git a/tests/pjsua/scripts-recvfrom/231_reg_bad_fail_stale_false_nonce_changed.py b/tests/pjsua/scripts-recvfrom/231_reg_bad_fail_stale_false_nonce_changed.py new file mode 100644 index 0000000..ed47d29 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/231_reg_bad_fail_stale_false_nonce_changed.py @@ -0,0 +1,41 @@ +# $Id: 231_reg_bad_fail_stale_false_nonce_changed.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# In this test we simulate broken server, where: +# - it wants to signal that NONCE has change +# - but it sets stale=false +# For this case pjsip will retry authentication until +# PJSIP_MAX_STALE_COUNT is exceeded. +# + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password" + +req1 = sip.RecvfromTransaction("Initial request", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1\""] + ) + +req2 = sip.RecvfromTransaction("First retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"1\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"2\", stale=true"] + ) + +req3 = sip.RecvfromTransaction("Second retry retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"2\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"3\", stale=true"] + ) + +req4 = sip.RecvfromTransaction("Third retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"3\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"4\", stale=true"], + expect="PJSIP_EAUTHSTALECOUNT" + ) + +recvfrom_cfg = sip.RecvfromCfg("Failed registration retry (server rejects with stale=true) ", + pjsua, [req1, req2, req3, req4]) diff --git a/tests/pjsua/scripts-recvfrom/234_reg_bad_stale_ok.py b/tests/pjsua/scripts-recvfrom/234_reg_bad_stale_ok.py new file mode 100644 index 0000000..e50da60 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/234_reg_bad_stale_ok.py @@ -0,0 +1,41 @@ +# $Id: 234_reg_bad_stale_ok.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# In this test we simulate broken server, where it wants to +# change the nonce, but it fails to set stale to true. In this +# case, we should expect pjsip to retry the authentication until +# PJSIP_MAX_STALE_COUNT is exceeded as it should have detected +# that that nonce has changed + + +pjsua = "--null-audio --id=sip:CLIENT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password " + \ + "--auto-update-nat=0" + +req1 = sip.RecvfromTransaction("Initial request", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1\""] + ) + +req2 = sip.RecvfromTransaction("First retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"1\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"2\""] + ) + +req3 = sip.RecvfromTransaction("Second retry retry", 401, + include=["REGISTER sip", "Authorization", "nonce=\"2\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"3\""] + ) + +req4 = sip.RecvfromTransaction("Third retry", 200, + include=["REGISTER sip", "Authorization", "nonce=\"3\""], + exclude=["Authorization:[\\s\\S]+Authorization:"], + expect="registration success" + ) + +recvfrom_cfg = sip.RecvfromCfg("Successful auth server changes nonce but with stale=false", + pjsua, [req1, req2, req3, req4]) diff --git a/tests/pjsua/scripts-recvfrom/235_reg_good_tel_uri_enocredential.py b/tests/pjsua/scripts-recvfrom/235_reg_good_tel_uri_enocredential.py new file mode 100644 index 0000000..c15a77b --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/235_reg_good_tel_uri_enocredential.py @@ -0,0 +1,15 @@ +# $Id: 235_reg_good_tel_uri_enocredential.py 3323 2010-09-28 07:43:18Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +pjsua = "--null-audio --id=tel:+12345 --registrar sip:127.0.0.1:$PORT" + +req1 = sip.RecvfromTransaction("", 401, + include=["REGISTER sip"], + exclude=["Authorization"], + resp_hdr=["WWW-Authenticate: Digest realm=\"python\", nonce=\"1234\""], + expect="PJSIP_ENOCREDENTIAL" + ) + +recvfrom_cfg = sip.RecvfromCfg("Failed registration with tel: URI test", + pjsua, [req1]) diff --git a/tests/pjsua/scripts-recvfrom/240_publish_scenarios.py b/tests/pjsua/scripts-recvfrom/240_publish_scenarios.py new file mode 100644 index 0000000..bd9a51d --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/240_publish_scenarios.py @@ -0,0 +1,51 @@ +# $Id: 240_publish_scenarios.py 2661 2009-04-28 22:19:49Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Several PUBLISH failure scenarios that should be handled automatically + + +pjsua = "--null-audio --id=sip:127.0.0.1:$PORT --registrar sip:127.0.0.1:$PORT " + \ + "--realm=python --user=username --password=password " + \ + "--auto-update-nat=0 --publish" +#pjsua = "--null-audio --local-port 0 --rtp-port 0" + +# Handle REGISTER first +req1 = sip.RecvfromTransaction("Initial REGISTER", 200, + include=["REGISTER sip"], + exclude=[], + resp_hdr=["Expires: 1800"] + ) + +# First PUBLISH, reply with 412 +req2 = sip.RecvfromTransaction("Initial PUBLISH, will be replied with 412", 412, + include=["PUBLISH sip"], + exclude=["Expires:"] + ) + +# Second PUBLISH +req3 = sip.RecvfromTransaction("Second PUBLISH, will be replied with 200", 200, + include=["PUBLISH sip"], + exclude=["Expires:"], + resp_hdr=["Expires: 60", "SIP-ETag: dx200xyz"] + ) + +# PUBLISH refresh, respond with 408 +req4 = sip.RecvfromTransaction("PUBLISH refresh, will be replied with 408", 408, + include=["PUBLISH sip", "SIP-If-Match: dx200xyz"], + exclude=["Expires:"], + resp_hdr=["Expires: 60", "SIP-ETag: dx200xyz"] + ) + +# After 5 minutes, pjsua should retry again +req5 = sip.RecvfromTransaction("PUBLISH retry", 200, + include=["PUBLISH sip"], + exclude=["Expires:", "SIP-If-Match:"], + resp_hdr=["Expires: 60", "SIP-ETag: abc"] + ) + + + +recvfrom_cfg = sip.RecvfromCfg("PUBLISH scenarios", + pjsua, [req1, req2, req3]) + diff --git a/tests/pjsua/scripts-recvfrom/300_timer_good.py b/tests/pjsua/scripts-recvfrom/300_timer_good.py new file mode 100644 index 0000000..4281141 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/300_timer_good.py @@ -0,0 +1,17 @@ +# $Id: 300_timer_good.py 3307 2010-09-08 05:38:49Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# INVITE session using session timer + +pjsua = "--null-audio sip:127.0.0.1:$PORT --use-timer 2 --timer-min-se 100 --timer-se 2000" + +req = sip.RecvfromTransaction("INVITE with session timer", 200, + include=["Session-Expires:\s*2000", "Min-SE:\s*100"], + exclude=[], + resp_hdr=["Session-Expires: 1000;refresher=uac"] + ) + +recvfrom_cfg = sip.RecvfromCfg("INVITE session using session timer", + pjsua, [req]) + diff --git a/tests/pjsua/scripts-recvfrom/301_timer_good_retry_after_422.py b/tests/pjsua/scripts-recvfrom/301_timer_good_retry_after_422.py new file mode 100644 index 0000000..3bd8a57 --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/301_timer_good_retry_after_422.py @@ -0,0 +1,30 @@ +# $Id: 301_timer_good_retry_after_422.py 3287 2010-08-18 14:30:17Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Session timers retry after 422 + + +pjsua = "--null-audio sip:127.0.0.1:$PORT --timer-min-se 100 --timer-se 1000" + +# First INVITE with timer rejected with 422 +req1 = sip.RecvfromTransaction("INVITE with SE too small", 422, + include=["Session-Expires:\s*1000"], + exclude=[], + resp_hdr=["Min-SE: 2000"] + ) + +# Wait for ACK +req2 = sip.RecvfromTransaction("Wait ACK", 0, include=["ACK sip"]) + +# New INVITE with SE >= Min-SE +req3 = sip.RecvfromTransaction("Retrying with acceptable SE", 200, + include=["Session-Expires:\s*2000", "Min-SE:\s*2000"], + exclude=[], + resp_hdr=["Session-Expires: 2000;refresher=uac"] + ) + + +recvfrom_cfg = sip.RecvfromCfg("Session timers retry after 422", + pjsua, [req1, req2, req3]) + diff --git a/tests/pjsua/scripts-recvfrom/400_inv_answered_with_less_media.py b/tests/pjsua/scripts-recvfrom/400_inv_answered_with_less_media.py new file mode 100644 index 0000000..2fd8c7f --- /dev/null +++ b/tests/pjsua/scripts-recvfrom/400_inv_answered_with_less_media.py @@ -0,0 +1,32 @@ +# $Id: 400_inv_answered_with_less_media.py 3716 2011-08-19 12:24:48Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Offer with 2 media lines answered with only 1 media line + +pjsua = "--null-audio sip:127.0.0.1:$PORT --id=sip:1000@localhost --extra-audio --use-srtp=0" + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +req = sip.RecvfromTransaction("Receiving 2 media lines, answer with 1 media line", 200, + include=["m=audio \d+ RTP/AVP", "m=audio \d+ RTP/AVP"], + exclude=[], + resp_hdr=["Content-type: application/sdp"], + resp_body=sdp, + ) + +recvfrom_cfg = sip.RecvfromCfg("Receiving answer with less media lines", + pjsua, [req]) + diff --git a/tests/pjsua/scripts-run/100_simple.py b/tests/pjsua/scripts-run/100_simple.py new file mode 100644 index 0000000..ed1b316 --- /dev/null +++ b/tests/pjsua/scripts-run/100_simple.py @@ -0,0 +1,13 @@ +# $Id: 100_simple.py 2028 2008-06-16 13:04:44Z bennylp $ +# +# Just about the simple pjsua command line parameter, which should +# never fail in any circumstances +from inc_cfg import * + +test_param = TestParam( + "Basic run", + [ + InstanceParam("pjsua", "--null-audio --rtp-port 0") + ] + ) + diff --git a/tests/pjsua/scripts-run/200_register.py b/tests/pjsua/scripts-run/200_register.py new file mode 100644 index 0000000..1ce0c26 --- /dev/null +++ b/tests/pjsua/scripts-run/200_register.py @@ -0,0 +1,20 @@ +# $Id: 200_register.py 2028 2008-06-16 13:04:44Z bennylp $ +# +from inc_cfg import * + +# Basic registration +test_param = TestParam( + "Basic registration", + [ + InstanceParam( "client", + "--null-audio"+ + " --id=\"\""+ + " --registrar=sip:sip.pjsip.org" + + " --username=test1" + + " --password=test1" + + " --realm=*", + uri="sip:test1@pjsip.org", + have_reg=True), + ] + ) + diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py new file mode 100644 index 0000000..f33a17d --- /dev/null +++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_1.py @@ -0,0 +1,52 @@ +# $Id: 001_torture_4475_3_1_1_1.py 2505 2009-03-12 11:25:11Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Torture message from RFC 4475 +# 3.1.1. Valid Messages +# 3.1.1.1. A Short Tortuous INVITE +complete_msg = \ +"""INVITE sip:vivekg@chair-dnrc.example.com;unknownparam SIP/2.0 +TO : + sip:vivekg@chair-dnrc.example.com ; tag = 1918181833n +from : "J Rosenberg \\\\\\"" + ; + tag = 98asjd8 +MaX-fOrWaRdS: 0068 +Call-ID: wsinv.ndaksdj@192.0.2.1 +Content-Length : 150 +cseq: 0009 + INVITE +Via : SIP / 2.0 + /UDP + 192.0.2.2;rport;branch=390skdjuw +s : +NewFangledHeader: newfangled value + continued newfangled value +UnknownHeaderWithUnusualValue: ;;,,;;,; +Content-Type: application/sdp +Route: + +v: SIP / 2.0 / TCP spindle.example.com ; + branch = z9hG4bK9ikj8 , + SIP / 2.0 / UDP 192.168.255.111 ; branch= + z9hG4bK30239 +m:"Quoted string \\"\\"" ; newparam = + newvalue ; + secondparam ; q = 0.33 + +v=0 +o=mhandley 29739 7272939 IN IP4 192.0.2.3 +s=- +c=IN IP4 192.0.2.4 +t=0 0 +m=audio 49217 RTP/AVP 0 12 +m=video 3227 RTP/AVP 31 +a=rtpmap:31 LPC +""" + + +sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.1", + "--null-audio --auto-answer 200", + "", 481, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py new file mode 100644 index 0000000..e5b08ef --- /dev/null +++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_2.py @@ -0,0 +1,25 @@ +# $Id: 001_torture_4475_3_1_1_2.py 2505 2009-03-12 11:25:11Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Torture message from RFC 4475 +# 3.1.1. Valid Messages +# 3.1.1.2. Wide Range of Valid Characters +complete_msg = \ +"""!interesting-Method0123456789_*+`.%indeed'~ sip:1_unusual.URI~(to-be!sure)&isn't+it$/crazy?,/;;*:&it+has=1,weird!*pas$wo~d_too.(doesn't-it)@example.com SIP/2.0 +Via: SIP/2.0/UDP host1.example.com;rport;branch=z9hG4bK-.!%66*_+`'~ +To: "BEL:\\\x07 NUL:\\\x00 DEL:\\\x7F" +From: token1~` token2'+_ token3*%!.- ;fromParam''~+*_!.-%="\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9";tag=_token~1'+`*%!-. +Call-ID: intmeth.word%ZK-!.*_+'@word`~)(><:\\/"][?}{ +CSeq: 139122385 !interesting-Method0123456789_*+`.%indeed'~ +Max-Forwards: 255 +extensionHeader-!.%*+_`'~: \xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB +Content-Length: 0 + +""" + + +sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.2", + "--null-audio --auto-answer 200", + "", 405, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py new file mode 100644 index 0000000..5e5848b --- /dev/null +++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_3.py @@ -0,0 +1,35 @@ +# $Id: 001_torture_4475_3_1_1_3.py 2505 2009-03-12 11:25:11Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Torture message from RFC 4475 +# 3.1.1. Valid Messages +# 3.1.1.3. Valid Use of the % Escaping Mechanism +complete_msg = \ +"""INVITE sip:sips%3Auser%40example.com@example.net SIP/2.0 +To: sip:%75se%72@example.com +From: ;tag=$FROM_TAG +Max-Forwards: 87 +i: esc01.239409asdfakjkn23onasd0-3234 +CSeq: 234234 INVITE +Via: SIP/2.0/UDP host5.example.net;rport;branch=z9hG4bKkdjuw +C: application/sdp +Contact: + +Content-Length: 150 + +v=0 +o=mhandley 29739 7272939 IN IP4 192.0.2.1 +s=- +c=IN IP4 192.0.2.1 +t=0 0 +m=audio 49217 RTP/AVP 0 12 +m=video 3227 RTP/AVP 31 +a=rtpmap:31 LPC +""" + + +sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.3", + "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py new file mode 100644 index 0000000..4381db3 --- /dev/null +++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_4.py @@ -0,0 +1,25 @@ +# $Id: 001_torture_4475_3_1_1_4.py 3712 2011-08-18 17:34:29Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Torture message from RFC 4475 +# 3.1.1. Valid Messages +# 3.1.1.4. Escaped Nulls in URIs +complete_msg = \ +"""REGISTER sip:example.com SIP/2.0 +To: sip:null-%00-null@example.com +From: sip:null-%00-null@example.com;tag=839923423 +Max-Forwards: 70 +Call-ID: escnull.39203ndfvkjdasfkq3w4otrq0adsfdfnavd +CSeq: 14398234 REGISTER +Via: SIP/2.0/UDP host5.example.com;rport;branch=z9hG4bKkdjuw +Contact: +Contact: +L:0 +""" + + +sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.4", + "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py new file mode 100644 index 0000000..236d034 --- /dev/null +++ b/tests/pjsua/scripts-sendto/001_torture_4475_3_1_1_5.py @@ -0,0 +1,25 @@ +# $Id: 001_torture_4475_3_1_1_5.py 2505 2009-03-12 11:25:11Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Torture message from RFC 4475 +# 3.1.1. Valid Messages +# 3.1.1.5. Use of % When It Is Not an Escape +complete_msg = \ +"""RE%47IST%45R sip:registrar.example.com SIP/2.0 +To: "%Z%45" +From: "%Z%45" ;tag=f232jadfj23 +Call-ID: esc02.asdfnqwo34rq23i34jrjasdcnl23nrlknsdf +Via: SIP/2.0/TCP host.example.com;rport;branch=z9hG4bK209%fzsnel234 +CSeq: 29344 RE%47IST%45R +Max-Forwards: 70 +Contact: +C%6Fntact: +Contact: +l: 0 +""" + +sendto_cfg = sip.SendtoCfg( "RFC 4475 3.1.1.5", + "--null-audio --auto-answer 200", + "", 405, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/100_simplecall.py b/tests/pjsua/scripts-sendto/100_simplecall.py new file mode 100644 index 0000000..000f501 --- /dev/null +++ b/tests/pjsua/scripts-sendto/100_simplecall.py @@ -0,0 +1,20 @@ +# $Id: 100_simplecall.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +sendto_cfg = sip.SendtoCfg( "simple call", "--null-audio --auto-answer 200", sdp, 200) + diff --git a/tests/pjsua/scripts-sendto/110_tel_uri.py b/tests/pjsua/scripts-sendto/110_tel_uri.py new file mode 100644 index 0000000..70164c9 --- /dev/null +++ b/tests/pjsua/scripts-sendto/110_tel_uri.py @@ -0,0 +1,46 @@ +# $Id: 110_tel_uri.py 2451 2009-02-13 10:13:08Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Handling of incoming tel: URI. +complete_msg = \ +"""INVITE tel:+2065551212 SIP/2.0 +Via: SIP/2.0/UDP $LOCAL_IP:$LOCAL_PORT;rport;x-route-tag="tgrp:cococisco1";branch=z9hG4bK61E05 +From: $FROM_TAG +To: +Date: Thu, 12 Feb 2009 18:32:33 GMT +Call-ID: 58F8F7D6-F86A11DD-8013D591-5694EF79 +Supported: 100rel,timer,resource-priority +Min-SE: 86400 +Cisco-Guid: 1492551325-4167700957-2148586897-1452601209 +User-Agent: Cisco-SIPGateway/IOS-12.x +Allow: INVITE, OPTIONS, BYE, CANCEL, ACK, PRACK, UPDATE, REFER, SUBSCRIBE, NOTIFY, INFO, REGISTER +CSeq: 101 INVITE +Max-Forwards: 70 +Timestamp: 1234463553 +Contact: +Contact: +Record-Route: +Expires: 180 +Allow-Events: telephone-event +Content-Type: application/sdp +Content-Disposition: session;handling=required +Content-Length: 265 + +v=0 +o=CiscoSystemsSIP-GW-UserAgent 1296 9529 IN IP4 X.X.X.X +s=SIP Call +c=IN IP4 $LOCAL_IP +t=0 0 +m=audio 18676 RTP/AVP 0 101 19 +c=IN IP4 $LOCAL_IP +a=rtpmap:0 PCMU/8000 +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-16 +a=rtpmap:19 CN/8000 +a=ptime:20 +""" + +sendto_cfg = sip.SendtoCfg( "tel: URI", "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_1.py b/tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_1.py new file mode 100644 index 0000000..57a73f9 --- /dev/null +++ b/tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_1.py @@ -0,0 +1,28 @@ +# $Id: 120_sdp_with_video_dynamic_1.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Video uses dynamic payload type +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +m=video 4000 RTP/AVP 100 +a=rtpmap:100 myvideo/80000 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=video 0 RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and video", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_2.py b/tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_2.py new file mode 100644 index 0000000..b5c8f5c --- /dev/null +++ b/tests/pjsua/scripts-sendto/120_sdp_with_video_dynamic_2.py @@ -0,0 +1,28 @@ +# $Id: 120_sdp_with_video_dynamic_2.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# In this case the video codec uses dynamic payload type +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=video 4000 RTP/AVP 100 +a=rtpmap:100 myvideo/96000 +m=audio 5000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=video 0 RTP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and video", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/121_sdp_with_video_static_1.py b/tests/pjsua/scripts-sendto/121_sdp_with_video_static_1.py new file mode 100644 index 0000000..c45f94c --- /dev/null +++ b/tests/pjsua/scripts-sendto/121_sdp_with_video_static_1.py @@ -0,0 +1,28 @@ +# $Id: 121_sdp_with_video_static_1.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Video uses static payload type which will cause failure +# when session.c looks-up the codec in codec manager +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +m=video 4000 RTP/AVP 54 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=video 0 RTP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and video", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/121_sdp_with_video_static_2.py b/tests/pjsua/scripts-sendto/121_sdp_with_video_static_2.py new file mode 100644 index 0000000..0058e1b --- /dev/null +++ b/tests/pjsua/scripts-sendto/121_sdp_with_video_static_2.py @@ -0,0 +1,28 @@ +# $Id: 121_sdp_with_video_static_2.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Video uses static payload type which will cause failure +# when session.c looks-up the codec in codec manager +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=video 4000 RTP/AVP 54 +m=audio 5000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=video 0 RTP/AVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and video", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_1.py b/tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_1.py new file mode 100644 index 0000000..e4fc6a7 --- /dev/null +++ b/tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_1.py @@ -0,0 +1,27 @@ +# $Id: 122_sdp_with_unknown_dynamic_1.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +m=xapplicationx 4000 RTP/AVP 100 +a=rtpmap:100 myapp/80000 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=xapplicationx 0 RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and unknown", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_2.py b/tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_2.py new file mode 100644 index 0000000..bbdc902 --- /dev/null +++ b/tests/pjsua/scripts-sendto/122_sdp_with_unknown_dynamic_2.py @@ -0,0 +1,27 @@ +# $Id: 122_sdp_with_unknown_dynamic_2.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=xapplicationx 4000 RTP/AVP 100 +a=rtpmap:100 myapp/80000 +m=audio 5000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=xapplicationx 0 RTP/AVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and unknown", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_1.py b/tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_1.py new file mode 100644 index 0000000..b21fc54 --- /dev/null +++ b/tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_1.py @@ -0,0 +1,27 @@ +# $Id: 123_sdp_with_unknown_static_1.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# The unknown media uses static payload type +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +m=xapplicationx 4000 RTP/AVP 54 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=xapplicationx 0 RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and unknown", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_2.py b/tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_2.py new file mode 100644 index 0000000..8e0e081 --- /dev/null +++ b/tests/pjsua/scripts-sendto/123_sdp_with_unknown_static_2.py @@ -0,0 +1,27 @@ +# $Id: 123_sdp_with_unknown_static_2.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# The unknown media uses static payload type +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=xapplicationx 4000 RTP/AVP 54 +m=audio 5000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=xapplicationx 0 RTP/AVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and unknown", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/124_sdp_with_unknown_static_unknown_transport.py b/tests/pjsua/scripts-sendto/124_sdp_with_unknown_static_unknown_transport.py new file mode 100644 index 0000000..c298503 --- /dev/null +++ b/tests/pjsua/scripts-sendto/124_sdp_with_unknown_static_unknown_transport.py @@ -0,0 +1,27 @@ +# $Id: 124_sdp_with_unknown_static_unknown_transport.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +m=xapplicationx 4000 XRTPX/XAVPX 54 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=xapplicationx 0 XRTPX/XAVPX " + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mixed audio and unknown and with unknown transport", + pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_0.py b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_0.py new file mode 100644 index 0000000..8f01152 --- /dev/null +++ b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_0.py @@ -0,0 +1,29 @@ +# $Id: 125_sdp_with_multi_audio_0.py 3711 2011-08-18 17:31:46Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Multiple good m=audio lines! The current algorithm in pjsua-lib will +# select the first audio (note that in 1.x it will select the last audio) +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +m=audio 4000 RTP/AVP 0 +m=audio 3000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=audio 0 RTP/AVP[\\s\\S]+m=audio 0 RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Mutiple good m=audio lines", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_1.py b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_1.py new file mode 100644 index 0000000..2331c3c --- /dev/null +++ b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_1.py @@ -0,0 +1,27 @@ +# $Id: 125_sdp_with_multi_audio_1.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Multiple m=audio, one of them is bad +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +m=audio 4000 UNKNOWN 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+m=audio 0 UNKNOWN" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Audio and bad audio", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_2.py b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_2.py new file mode 100644 index 0000000..17fd297 --- /dev/null +++ b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_2.py @@ -0,0 +1,27 @@ +# $Id: 125_sdp_with_multi_audio_2.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Multiple m=audio, one of them is bad +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 UNKNOWN 0 +m=audio 5000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio 0 UNKNOWN[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Audio and bad audio", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_3.py b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_3.py new file mode 100644 index 0000000..9731b0e --- /dev/null +++ b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_3.py @@ -0,0 +1,28 @@ +# $Id: 125_sdp_with_multi_audio_3.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Multiple m=audio, one of them has dynamic PT codec that we don't support +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 100 +a=rtpmap:100 someunknowncodec/8000 +m=audio 4000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio 0 RTP/AVP[\s\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Multiple audio lines", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_4.py b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_4.py new file mode 100644 index 0000000..e075449 --- /dev/null +++ b/tests/pjsua/scripts-sendto/125_sdp_with_multi_audio_4.py @@ -0,0 +1,27 @@ +# $Id: 125_sdp_with_multi_audio_4.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Multiple m=audio, one of them has static PT codec that we don't support +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 80 +m=audio 4000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio 0 RTP/AVP[\s\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Multiple audio lines", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/126_sdp_with_port_0_and_no_rtpmap_for_dynamic_pt.py b/tests/pjsua/scripts-sendto/126_sdp_with_port_0_and_no_rtpmap_for_dynamic_pt.py new file mode 100644 index 0000000..22e2b0f --- /dev/null +++ b/tests/pjsua/scripts-sendto/126_sdp_with_port_0_and_no_rtpmap_for_dynamic_pt.py @@ -0,0 +1,26 @@ +# $Id: 126_sdp_with_port_0_and_no_rtpmap_for_dynamic_pt.py 3011 2009-11-10 10:58:20Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=video 0 RTP/AVP 100 +m=audio 5000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=video 0 RTP/AVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("SDP media with port 0 and no rtpmap for dynamic PT", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_1.py b/tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_1.py new file mode 100644 index 0000000..8fd13c9 --- /dev/null +++ b/tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_1.py @@ -0,0 +1,28 @@ +# $Id: 140_sdp_with_direction_attr_in_session_1.py 3086 2010-02-03 14:43:25Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Offer contains "sendonly" attribute in the session. Answer should +# respond with appropriate direction in session or media +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +a=sendonly +m=audio 5000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "a=recvonly" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("SDP direction in session", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_2.py b/tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_2.py new file mode 100644 index 0000000..76db859 --- /dev/null +++ b/tests/pjsua/scripts-sendto/140_sdp_with_direction_attr_in_session_2.py @@ -0,0 +1,30 @@ +# $Id: 140_sdp_with_direction_attr_in_session_2.py 3086 2010-02-03 14:43:25Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Offer contains "inactive" attribute in the session, however the media +# also has "sendonly" attribute. Answer should appropriately respond +# direction attribute in media, instead of the one in session. +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +a=inactive +m=audio 5000 RTP/AVP 0 +a=sendonly +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "a=recvonly" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("SDP direction in session", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/150_err_extension.py b/tests/pjsua/scripts-sendto/150_err_extension.py new file mode 100644 index 0000000..d5ebe0b --- /dev/null +++ b/tests/pjsua/scripts-sendto/150_err_extension.py @@ -0,0 +1,27 @@ +# $Id: 150_err_extension.py 2066 2008-06-26 19:51:01Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "Require: xxx-my-extension\n" +include = ["Unsupported: xxx-my-extension"] +exclude = [] +sendto_cfg = sip.SendtoCfg("Bad extension", pjsua_args, sdp, 420, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + + diff --git a/tests/pjsua/scripts-sendto/151_err_sdp_video.py b/tests/pjsua/scripts-sendto/151_err_sdp_video.py new file mode 100644 index 0000000..7401964 --- /dev/null +++ b/tests/pjsua/scripts-sendto/151_err_sdp_video.py @@ -0,0 +1,23 @@ +# $Id: 151_err_sdp_video.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=video 4000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Video not acceptable", pjsua_args, sdp, 488, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/152_err_sdp_no_media.py b/tests/pjsua/scripts-sendto/152_err_sdp_no_media.py new file mode 100644 index 0000000..1148085 --- /dev/null +++ b/tests/pjsua/scripts-sendto/152_err_sdp_no_media.py @@ -0,0 +1,22 @@ +# $Id: 152_err_sdp_no_media.py 2066 2008-06-26 19:51:01Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg("No media in SDP", pjsua_args, sdp, 400, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/153_err_sdp_unsupported_codec.py b/tests/pjsua/scripts-sendto/153_err_sdp_unsupported_codec.py new file mode 100644 index 0000000..ec15495 --- /dev/null +++ b/tests/pjsua/scripts-sendto/153_err_sdp_unsupported_codec.py @@ -0,0 +1,24 @@ +# $Id: 153_err_sdp_unsupported_codec.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=video 4000 RTP/AVP 101 +a=rtpmap:101 my-proprietary-codec +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Unsupported codec", pjsua_args, sdp, 488, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/155_err_sdp_bad_syntax.py b/tests/pjsua/scripts-sendto/155_err_sdp_bad_syntax.py new file mode 100644 index 0000000..071217e --- /dev/null +++ b/tests/pjsua/scripts-sendto/155_err_sdp_bad_syntax.py @@ -0,0 +1,23 @@ +# $Id: 155_err_sdp_bad_syntax.py 2066 2008-06-26 19:51:01Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v= +o= +s= +c= +t= +a= +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = [ "Warning: " ] # better have Warning header +exclude = [] + +sendto_cfg = sip.SendtoCfg("Bad SDP syntax", pjsua_args, sdp, 400, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/156_err_sdp_bad_net_type.py b/tests/pjsua/scripts-sendto/156_err_sdp_bad_net_type.py new file mode 100644 index 0000000..07d4db2 --- /dev/null +++ b/tests/pjsua/scripts-sendto/156_err_sdp_bad_net_type.py @@ -0,0 +1,27 @@ +# $Id: 156_err_sdp_bad_net_type.py 2066 2008-06-26 19:51:01Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=AF IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = [ "Warning: " ] # better have Warning header +exclude = [] +sendto_cfg = sip.SendtoCfg("Bad SDP network type", pjsua_args, sdp, 400, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + + diff --git a/tests/pjsua/scripts-sendto/157_err_sdp_bad_addr_type.py b/tests/pjsua/scripts-sendto/157_err_sdp_bad_addr_type.py new file mode 100644 index 0000000..3cb404a --- /dev/null +++ b/tests/pjsua/scripts-sendto/157_err_sdp_bad_addr_type.py @@ -0,0 +1,27 @@ +# $Id: 157_err_sdp_bad_addr_type.py 2066 2008-06-26 19:51:01Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP7 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = [ "Warning: " ] # better have Warning header +exclude = [] +sendto_cfg = sip.SendtoCfg("Bad SDP address type", pjsua_args, sdp, 400, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + + diff --git a/tests/pjsua/scripts-sendto/158_err_sdp_bad_transport_type.py b/tests/pjsua/scripts-sendto/158_err_sdp_bad_transport_type.py new file mode 100644 index 0000000..915ba8a --- /dev/null +++ b/tests/pjsua/scripts-sendto/158_err_sdp_bad_transport_type.py @@ -0,0 +1,27 @@ +# $Id: 158_err_sdp_bad_transport_type.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/XAVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "" +include = [] +exclude = [] +sendto_cfg = sip.SendtoCfg("Unsupported transport type", pjsua_args, sdp, 488, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + + diff --git a/tests/pjsua/scripts-sendto/159_no_rport.py b/tests/pjsua/scripts-sendto/159_no_rport.py new file mode 100644 index 0000000..f7a7468 --- /dev/null +++ b/tests/pjsua/scripts-sendto/159_no_rport.py @@ -0,0 +1,38 @@ +# $Id: 159_no_rport.py 2442 2009-02-06 08:44:23Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Ticket http://trac.pjsip.org/repos/ticket/718 +# RTC doesn't put rport in Via, and it is report to have caused segfault. +complete_msg = \ +"""INVITE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP $LOCAL_IP:$LOCAL_PORT;branch=z9hG4bK74a60ee5 +From: ;tag=as2858a32c +To: +Contact: +Call-ID: 123@localhost +CSeq: 1 INVITE +Max-Forwards: 70 +Content-Type: application/sdp +Content-Length: 285 + +v=0 +o=root 4236 4236 IN IP4 192.168.1.11 +s=session +c=IN IP4 192.168.1.11 +t=0 0 +m=audio 14390 RTP/AVP 0 3 8 101 +a=rtpmap:0 PCMU/8000 +a=rtpmap:3 GSM/8000 +a=rtpmap:8 PCMA/8000 +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-16 +a=silenceSupp:off - - - - +a=ptime:20 +a=sendrecv +""" + + +sendto_cfg = sip.SendtoCfg( "RTC no rport", "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/159_no_rport_nit.py b/tests/pjsua/scripts-sendto/159_no_rport_nit.py new file mode 100644 index 0000000..073108e --- /dev/null +++ b/tests/pjsua/scripts-sendto/159_no_rport_nit.py @@ -0,0 +1,25 @@ +# $Id: 159_no_rport_nit.py 2442 2009-02-06 08:44:23Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Ticket http://trac.pjsip.org/repos/ticket/718 +# RTC doesn't put rport in Via, and it is reported to have caused segfault. +# +complete_msg = \ +"""MESSAGE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP localhost:$LOCAL_PORT;branch=z9hG4bK$BRANCH +From: ;tag=as2858a32c +To: +Call-ID: 123@localhost +CSeq: 1 MESSAGE +Max-Forwards: 70 +Content-Length: 11 +Content-Type: text/plain + +Hello world +""" + + +sendto_cfg = sip.SendtoCfg( "RTC no rport", "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/160_err_duplicate_replaces.py b/tests/pjsua/scripts-sendto/160_err_duplicate_replaces.py new file mode 100644 index 0000000..63da2e4 --- /dev/null +++ b/tests/pjsua/scripts-sendto/160_err_duplicate_replaces.py @@ -0,0 +1,23 @@ +# $Id: 160_err_duplicate_replaces.py 2066 2008-06-26 19:51:01Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "Replaces: abcd;from_tag=1\r\nReplaces: efgh;from_tag=2\r\n" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Duplicate replaces header", pjsua_args, sdp, 400, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/161_err_replaces_dlg_not_found.py b/tests/pjsua/scripts-sendto/161_err_replaces_dlg_not_found.py new file mode 100644 index 0000000..33d934c --- /dev/null +++ b/tests/pjsua/scripts-sendto/161_err_replaces_dlg_not_found.py @@ -0,0 +1,23 @@ +# $Id: 161_err_replaces_dlg_not_found.py 2066 2008-06-26 19:51:01Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "Replaces: abcd;from_tag=1\r\n" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Replaced dialog not found", pjsua_args, sdp, 481, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/170_timer_required.py b/tests/pjsua/scripts-sendto/170_timer_required.py new file mode 100644 index 0000000..9ac1708 --- /dev/null +++ b/tests/pjsua/scripts-sendto/170_timer_required.py @@ -0,0 +1,27 @@ +# $Id: 170_timer_required.py 3307 2010-09-08 05:38:49Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-timer 2 --timer-min-se 90 --timer-se 1800" +extra_headers = "Require: timer\nSupported: timer\nSession-Expires: 1800\n" +include = ["Session-Expires: .*;refresher=.*"] +exclude = [] +sendto_cfg = sip.SendtoCfg("Session Timer required", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + + diff --git a/tests/pjsua/scripts-sendto/171_timer_initiated_by_uas.py b/tests/pjsua/scripts-sendto/171_timer_initiated_by_uas.py new file mode 100644 index 0000000..4ce1a24 --- /dev/null +++ b/tests/pjsua/scripts-sendto/171_timer_initiated_by_uas.py @@ -0,0 +1,36 @@ +# $Id: 171_timer_initiated_by_uas.py 3307 2010-09-08 05:38:49Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +# RFC 4028 Section 9: +# If the incoming request contains a Supported header field with a +# value 'timer' but does not contain a Session-Expires header, it means +# that the UAS is indicating support for timers but is not requesting +# one. The UAS may request a session timer in the 2XX response by +# including a Session-Expires header field. The value MUST NOT be set +# to a duration lower than the value in the Min-SE header field in the +# request, if it is present. + +pjsua_args = "--null-audio --auto-answer 200 --use-timer 2 --timer-min-se 90 --timer-se 1800" +extra_headers = "Supported: timer\n" +include = ["Session-Expires: .*;refresher=.*"] +exclude = [] +sendto_cfg = sip.SendtoCfg("Session Timer initiated by UAS", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + + diff --git a/tests/pjsua/scripts-sendto/172_timer_supported_but_not_used.py b/tests/pjsua/scripts-sendto/172_timer_supported_but_not_used.py new file mode 100644 index 0000000..88a4d99 --- /dev/null +++ b/tests/pjsua/scripts-sendto/172_timer_supported_but_not_used.py @@ -0,0 +1,26 @@ +# $Id: 172_timer_supported_but_not_used.py 2858 2009-08-11 12:42:38Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200" +extra_headers = "Supported: timer\n" +include = [] +exclude = ["Session-Expires:"] +sendto_cfg = sip.SendtoCfg("Session Timer supported but not used", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/173_timer_offer_no_refresher.py b/tests/pjsua/scripts-sendto/173_timer_offer_no_refresher.py new file mode 100644 index 0000000..d6417cd --- /dev/null +++ b/tests/pjsua/scripts-sendto/173_timer_offer_no_refresher.py @@ -0,0 +1,26 @@ +# $Id: 173_timer_offer_no_refresher.py 2858 2009-08-11 12:42:38Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --timer-min-se 90" +extra_headers = "Supported: timer\nSession-Expires: 1800\n" +include = ["Session-Expires:.*;refresher=ua[cs]"] +exclude = [] +sendto_cfg = sip.SendtoCfg("Session Timer without specifying refresher", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/173_timer_offer_refresher_uac.py b/tests/pjsua/scripts-sendto/173_timer_offer_refresher_uac.py new file mode 100644 index 0000000..3629d4d --- /dev/null +++ b/tests/pjsua/scripts-sendto/173_timer_offer_refresher_uac.py @@ -0,0 +1,26 @@ +# $Id: 173_timer_offer_refresher_uac.py 2858 2009-08-11 12:42:38Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --timer-min-se 90" +extra_headers = "Supported: timer\nSession-Expires: 1800;refresher=uac\n" +include = ["Session-Expires:.*;refresher=ua[cs]"] +exclude = [] +sendto_cfg = sip.SendtoCfg("Session Timer offer refresher uac", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/173_timer_offer_refresher_uas.py b/tests/pjsua/scripts-sendto/173_timer_offer_refresher_uas.py new file mode 100644 index 0000000..96508af --- /dev/null +++ b/tests/pjsua/scripts-sendto/173_timer_offer_refresher_uas.py @@ -0,0 +1,26 @@ +# $Id: 173_timer_offer_refresher_uas.py 2858 2009-08-11 12:42:38Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --timer-min-se 90" +extra_headers = "Supported: timer\nSession-Expires: 1800;refresher=uas\n" +include = ["Session-Expires:.*;refresher=ua[cs]"] +exclude = [] +sendto_cfg = sip.SendtoCfg("Session Timer offer refresher uas", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/174_timer_se_too_small.py b/tests/pjsua/scripts-sendto/174_timer_se_too_small.py new file mode 100644 index 0000000..cde4e9a --- /dev/null +++ b/tests/pjsua/scripts-sendto/174_timer_se_too_small.py @@ -0,0 +1,26 @@ +# $Id: 174_timer_se_too_small.py 2858 2009-08-11 12:42:38Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --timer-min-se 2000 --timer-se 2000" +extra_headers = "Supported: timer\nSession-Expires: 1800\n" +include = ["Min-SE:\s*2000"] +exclude = [] +sendto_cfg = sip.SendtoCfg("Session Timer SE too small", pjsua_args, sdp, 422, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/200_ice_no_ice.py b/tests/pjsua/scripts-sendto/200_ice_no_ice.py new file mode 100644 index 0000000..9344896 --- /dev/null +++ b/tests/pjsua/scripts-sendto/200_ice_no_ice.py @@ -0,0 +1,26 @@ +# $Id: 200_ice_no_ice.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1" +include = [] +exclude = ["a=ice", "a=candidate"] + +sendto_cfg = sip.SendtoCfg( "caller has no ice, answer must not have ICE", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/200_ice_success_1.py b/tests/pjsua/scripts-sendto/200_ice_success_1.py new file mode 100644 index 0000000..0340795 --- /dev/null +++ b/tests/pjsua/scripts-sendto/200_ice_success_1.py @@ -0,0 +1,31 @@ +# $Id: 200_ice_success_1.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=ice-ufrag:1234 +a=ice-pwd:5678 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1" +include = ["a=ice-ufrag"] # must have ICE +exclude = ["a=candidate:[0-9a-zA-Z]+ 2 UDP", # must not answer with 2 components + "ice-mismatch" # must not mismatch + ] + +sendto_cfg = sip.SendtoCfg( "caller sends only one component", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/200_ice_success_2.py b/tests/pjsua/scripts-sendto/200_ice_success_2.py new file mode 100644 index 0000000..cc28f59 --- /dev/null +++ b/tests/pjsua/scripts-sendto/200_ice_success_2.py @@ -0,0 +1,36 @@ +# $Id: 200_ice_success_2.py 2084 2008-06-27 23:53:00Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtcp:4382 IN IP4 192.168.0.4 +a=ice-ufrag:1234 +a=ice-pwd:5678 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host +a=candidate:YY 2 UDP 1234 192.168.0.4 4382 typ host +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1" +include = ["a=ice-ufrag", # must have ICE + "a=candidate:[0-9a-zA-Z]+ 2 UDP" # must have RTCP component + ] +exclude = [ + "ice-mismatch" # must not mismatch + ] + +sendto_cfg = sip.SendtoCfg( "caller sends only one component", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude, + enable_buffer = True) + diff --git a/tests/pjsua/scripts-sendto/200_ice_success_3.py b/tests/pjsua/scripts-sendto/200_ice_success_3.py new file mode 100644 index 0000000..8fdadd6 --- /dev/null +++ b/tests/pjsua/scripts-sendto/200_ice_success_3.py @@ -0,0 +1,35 @@ +# $Id: 200_ice_success_3.py 2376 2008-12-11 17:25:50Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=ice-ufrag:1234 +a=ice-pwd:5678 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host +a=candidate:YY 2 UDP 1234 127.0.0.1 4001 typ host +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1" +include = ["a=ice-ufrag", # must have ICE + "a=candidate:[0-9a-zA-Z]+ 2 UDP" # must have RTCP component + ] +exclude = [ + "ice-mismatch" # must not mismatch + ] + +sendto_cfg = sip.SendtoCfg( "caller sends two components without a=rtcp line", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude, + enable_buffer = True) + diff --git a/tests/pjsua/scripts-sendto/200_ice_success_4.py b/tests/pjsua/scripts-sendto/200_ice_success_4.py new file mode 100644 index 0000000..8da6cad --- /dev/null +++ b/tests/pjsua/scripts-sendto/200_ice_success_4.py @@ -0,0 +1,35 @@ +# $Id: 200_ice_success_4.py 2376 2008-12-11 17:25:50Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtcp:4382 IN IP4 192.168.0.4 +a=ice-ufrag:1234 +a=ice-pwd:5678 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host +a=candidate:YY 2 UDP 1234 127.0.0.2 4002 typ host +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1 --ice-no-rtcp" +include = ["a=ice-ufrag"] # must have ICE +exclude = [ + "ice-mismatch", # must not mismatch + "a=candidate:[0-9a-zA-Z]+ 2 UDP" # must not have RTCP component + ] + +sendto_cfg = sip.SendtoCfg( "pjsua with --ice-no-rtcp ignores RTCP things in the SDP", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude, + enable_buffer = True) + diff --git a/tests/pjsua/scripts-sendto/201_ice_mismatch_1.py b/tests/pjsua/scripts-sendto/201_ice_mismatch_1.py new file mode 100644 index 0000000..c91d8d5 --- /dev/null +++ b/tests/pjsua/scripts-sendto/201_ice_mismatch_1.py @@ -0,0 +1,29 @@ +# $Id: 201_ice_mismatch_1.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=ice-ufrag:1234 +a=ice-pwd:5678 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=candidate:XX 1 UDP 1 1.1.1.1 2222 typ host +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1" +include = ["a=ice-mismatch"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller sends mismatched offer for comp 1", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/201_ice_mismatch_2.py b/tests/pjsua/scripts-sendto/201_ice_mismatch_2.py new file mode 100644 index 0000000..69faebe --- /dev/null +++ b/tests/pjsua/scripts-sendto/201_ice_mismatch_2.py @@ -0,0 +1,31 @@ +# $Id: 201_ice_mismatch_2.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtcp:4382 IN IP4 192.168.0.4 +a=ice-ufrag:1234 +a=ice-pwd:5678 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host +a=candidate:XX 2 UDP 1234 127.0.0.1 4000 typ host +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1" +include = ["a=ice-mismatch"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller sends mismatched offer for comp 2", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/201_ice_mismatch_3.py b/tests/pjsua/scripts-sendto/201_ice_mismatch_3.py new file mode 100644 index 0000000..d1ad9a9 --- /dev/null +++ b/tests/pjsua/scripts-sendto/201_ice_mismatch_3.py @@ -0,0 +1,30 @@ +# $Id: 201_ice_mismatch_3.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtcp:4382 IN IP4 192.168.0.4 +a=ice-ufrag:1234 +a=ice-pwd:5678 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=candidate:XX 1 UDP 1234 127.0.0.1 4000 typ host +""" + +args = "--null-audio --use-ice --auto-answer 200 --max-calls 1" +include = ["a=ice-mismatch"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller sends mismatched offer for comp 2", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/251_multipart_ok_simple.py b/tests/pjsua/scripts-sendto/251_multipart_ok_simple.py new file mode 100644 index 0000000..c98cd4c --- /dev/null +++ b/tests/pjsua/scripts-sendto/251_multipart_ok_simple.py @@ -0,0 +1,38 @@ +# $Id: 251_multipart_ok_simple.py 3243 2010-08-01 09:48:51Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +body = \ +""" +--12345 +Content-Type: application/sdp + +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 + +--12345 +Content-Type: text/plain + +Hi there this is definitely not SDP + +--12345-- +""" + +args = "--null-audio --auto-answer 200 --max-calls 1" +extra_headers = "Content-Type: multipart/mixed; boundary=12345" +include = ["v=0", "m=audio"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Valid multipart/mixed body containing SDP", + pjsua_args=args, sdp="", resp_code=200, + extra_headers=extra_headers, body=body, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/252_multipart_ok_clutter.py b/tests/pjsua/scripts-sendto/252_multipart_ok_clutter.py new file mode 100644 index 0000000..dc9a83b --- /dev/null +++ b/tests/pjsua/scripts-sendto/252_multipart_ok_clutter.py @@ -0,0 +1,47 @@ +# $Id: 252_multipart_ok_clutter.py 3243 2010-08-01 09:48:51Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +body = \ +""" +This is the preamble. It is to be ignored, though it +is a handy place for composition agents to include an +explanatory note to non-MIME conformant readers. + +--123:45 +Content-Type: text/plain + +The first part is definitely not SDP + +--123:45 + +This is implicitly typed plain US-ASCII text. +It does NOT end with a linebreak. +--123:45 +Content-Type: application/sdp + +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 + +--123:45-- +This is the epilogue. It is also to be ignored. +""" + +args = "--null-audio --auto-answer 200 --max-calls 1" +extra_headers = "Content-Type: multipart/mixed; boundary=\"123:45\"" +include = ["v=0", "m=audio"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Valid but cluttered multipart/mixed body containing SDP", + pjsua_args=args, sdp="", resp_code=200, + extra_headers=extra_headers, body=body, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/260_multipart_err_no_sdp.py b/tests/pjsua/scripts-sendto/260_multipart_err_no_sdp.py new file mode 100644 index 0000000..ed28ca2 --- /dev/null +++ b/tests/pjsua/scripts-sendto/260_multipart_err_no_sdp.py @@ -0,0 +1,38 @@ +# $Id: 260_multipart_err_no_sdp.py 3243 2010-08-01 09:48:51Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +body = \ +""" +--12345 +Content-Type: application/notsdp + +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=pjmedia +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 + +--12345 +Content-Type: text/plain + +Hi there this is definitely not SDP + +--12345-- +""" + +args = "--null-audio --auto-answer 200 --max-calls 1" +extra_headers = "Content-Type: multipart/mixed; boundary=12345" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Multipart/mixed body without SDP", + pjsua_args=args, sdp="", resp_code=400, + extra_headers=extra_headers, body=body, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/300_srtp_crypto_case_insensitive.py b/tests/pjsua/scripts-sendto/300_srtp_crypto_case_insensitive.py new file mode 100644 index 0000000..1f609fd --- /dev/null +++ b/tests/pjsua/scripts-sendto/300_srtp_crypto_case_insensitive.py @@ -0,0 +1,27 @@ +# $Id: 300_srtp_crypto_case_insensitive.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/SAVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AeS_Cm_128_HmAC_shA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:2 aEs_cM_128_HMaC_ShA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 2 --srtp-secure 0" +include = ["m=audio \d+ RTP/SAVP", "a=crypto"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller has used mixed case in crypto attr, callee must process that normally", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/300_srtp_duplicated_crypto_tag.py b/tests/pjsua/scripts-sendto/300_srtp_duplicated_crypto_tag.py new file mode 100644 index 0000000..29f62c5 --- /dev/null +++ b/tests/pjsua/scripts-sendto/300_srtp_duplicated_crypto_tag.py @@ -0,0 +1,27 @@ +# $Id: 300_srtp_duplicated_crypto_tag.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller has used invalid crypto tag, callee must not accept the call", + pjsua_args=args, sdp=sdp, resp_code=406, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/300_srtp_invalid_crypto_tag_non_numeric.py b/tests/pjsua/scripts-sendto/300_srtp_invalid_crypto_tag_non_numeric.py new file mode 100644 index 0000000..8c5d7cc --- /dev/null +++ b/tests/pjsua/scripts-sendto/300_srtp_invalid_crypto_tag_non_numeric.py @@ -0,0 +1,27 @@ +# $Id: 300_srtp_invalid_crypto_tag_non_numeric.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:x AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller has used invalid crypto tag (non-numeric), callee must not accept the call", + pjsua_args=args, sdp=sdp, resp_code=406, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/300_srtp_receive_crypto_tag_zero.py b/tests/pjsua/scripts-sendto/300_srtp_receive_crypto_tag_zero.py new file mode 100644 index 0000000..a305fac --- /dev/null +++ b/tests/pjsua/scripts-sendto/300_srtp_receive_crypto_tag_zero.py @@ -0,0 +1,26 @@ +# $Id: 300_srtp_receive_crypto_tag_zero.py 2765 2009-06-17 12:00:47Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:0 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller has used crypto tag zero, callee must accept the call", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_1.py b/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_1.py new file mode 100644 index 0000000..35e712b --- /dev/null +++ b/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_1.py @@ -0,0 +1,26 @@ +# $Id: 300_srtp_receive_no_key_1.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:0 AES_CM_128_HMAC_SHA1_80 +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller send crypto attr without key, callee must not accept the call", + pjsua_args=args, sdp=sdp, resp_code=406, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_2.py b/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_2.py new file mode 100644 index 0000000..51fff9f --- /dev/null +++ b/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_2.py @@ -0,0 +1,26 @@ +# $Id: 300_srtp_receive_no_key_2.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:0 AES_CM_128_HMAC_SHA1_80 inline +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller send crypto attr without key, callee must not accept the call", + pjsua_args=args, sdp=sdp, resp_code=406, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_3.py b/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_3.py new file mode 100644 index 0000000..fcf8968 --- /dev/null +++ b/tests/pjsua/scripts-sendto/300_srtp_receive_no_key_3.py @@ -0,0 +1,26 @@ +# $Id: 300_srtp_receive_no_key_3.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:0 AES_CM_128_HMAC_SHA1_80 inline: +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller send crypto attr without key, callee must not accept the call", + pjsua_args=args, sdp=sdp, resp_code=406, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/301_srtp0_recv_avp.py b/tests/pjsua/scripts-sendto/301_srtp0_recv_avp.py new file mode 100644 index 0000000..af68feb --- /dev/null +++ b/tests/pjsua/scripts-sendto/301_srtp0_recv_avp.py @@ -0,0 +1,28 @@ +# $Id: 301_srtp0_recv_avp.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 0 --srtp-secure 0" +include = [] +exclude = ["a=crypto"] + +sendto_cfg = sip.SendtoCfg( "Callee has SRTP disabled but receive RTP/AVP with crypto, should accept without crypto", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/301_srtp0_recv_savp.py b/tests/pjsua/scripts-sendto/301_srtp0_recv_savp.py new file mode 100644 index 0000000..1066746 --- /dev/null +++ b/tests/pjsua/scripts-sendto/301_srtp0_recv_savp.py @@ -0,0 +1,28 @@ +# $Id: 301_srtp0_recv_savp.py 3713 2011-08-18 18:11:08Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/SAVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 0 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Callee has SRTP disabled but receive RTP/SAVP, should reject the call", + pjsua_args=args, sdp=sdp, resp_code=488, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/310_srtp1_no_crypto.py b/tests/pjsua/scripts-sendto/310_srtp1_no_crypto.py new file mode 100644 index 0000000..044fd66 --- /dev/null +++ b/tests/pjsua/scripts-sendto/310_srtp1_no_crypto.py @@ -0,0 +1,26 @@ +# $Id: 310_srtp1_no_crypto.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = ["m=audio \d+ RTP/AVP"] +exclude = ["a=crypto"] + +sendto_cfg = sip.SendtoCfg( "caller has no crypto attr, answer must accept without crypto attr", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/311_srtp1_recv_avp.py b/tests/pjsua/scripts-sendto/311_srtp1_recv_avp.py new file mode 100644 index 0000000..964222c --- /dev/null +++ b/tests/pjsua/scripts-sendto/311_srtp1_recv_avp.py @@ -0,0 +1,28 @@ +# $Id: 311_srtp1_recv_avp.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = ["m=audio \d+ RTP/AVP", "a=crypto"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Callee has SRTP optional and receive RTP/AVP with crypto, should accept with RTP/AVP & crypto", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/312_srtp1_recv_savp.py b/tests/pjsua/scripts-sendto/312_srtp1_recv_savp.py new file mode 100644 index 0000000..4a0f294 --- /dev/null +++ b/tests/pjsua/scripts-sendto/312_srtp1_recv_savp.py @@ -0,0 +1,28 @@ +# $Id: 312_srtp1_recv_savp.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/SAVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = ["m=audio \d+ RTP/SAVP", "a=crypto"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Callee has SRTP optional receive RTP/SAVP, should answer RTP/SAVP too", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/313_srtp1_unsupported_crypto.py b/tests/pjsua/scripts-sendto/313_srtp1_unsupported_crypto.py new file mode 100644 index 0000000..da5a878 --- /dev/null +++ b/tests/pjsua/scripts-sendto/313_srtp1_unsupported_crypto.py @@ -0,0 +1,26 @@ +# $Id: 313_srtp1_unsupported_crypto.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 CRYPTO_X inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 1 --srtp-secure 0" +include = [] +exclude = ["a=crypto"] + +sendto_cfg = sip.SendtoCfg( "caller has used unsupported crypto, callee (SRTP optional) accept the call without crypto", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/320_srtp2_no_crypto.py b/tests/pjsua/scripts-sendto/320_srtp2_no_crypto.py new file mode 100644 index 0000000..6231964 --- /dev/null +++ b/tests/pjsua/scripts-sendto/320_srtp2_no_crypto.py @@ -0,0 +1,26 @@ +# $Id: 320_srtp2_no_crypto.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/SAVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 2 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller has no crypto attr on RTP/SAVP, callee must not accept the call", + pjsua_args=args, sdp=sdp, resp_code=406, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_1.py b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_1.py new file mode 100644 index 0000000..815b130 --- /dev/null +++ b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_1.py @@ -0,0 +1,28 @@ +# $Id: 320_srtp_with_unknown_media_1.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +m=xapplicationx 4000 RTP/AVP 100 +a=rtpmap:100 myapp/80000 +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-srtp 1 --srtp-secure 0" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+a=crypto[\\s\\S]+m=xapplicationx 0 RTP/AVP" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("SRTP audio and unknown media", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_2.py b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_2.py new file mode 100644 index 0000000..5980f20 --- /dev/null +++ b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_media_2.py @@ -0,0 +1,28 @@ +# $Id: 320_srtp_with_unknown_media_2.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=xapplicationx 4000 RTP/AVP 100 +a=rtpmap:100 myapp/80000 +m=audio 5000 RTP/AVP 0 +a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-srtp 1 --srtp-secure 0" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=xapplicationx 0 RTP/AVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+a=crypto" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Unknown media and SRTP audio", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_1.py b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_1.py new file mode 100644 index 0000000..c0cf60d --- /dev/null +++ b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_1.py @@ -0,0 +1,27 @@ +# $Id: 320_srtp_with_unknown_transport_1.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/AVP 0 +a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +m=audio 4000 UNKNOWN 0 +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-srtp 1 --srtp-secure 0" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+a=crypto[\\s\\S]+m=audio 0 UNKNOWN" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("SRTP audio and unknown media", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_2.py b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_2.py new file mode 100644 index 0000000..b079471 --- /dev/null +++ b/tests/pjsua/scripts-sendto/320_srtp_with_unknown_transport_2.py @@ -0,0 +1,27 @@ +# $Id: 320_srtp_with_unknown_transport_2.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 UNKNOWN 0 +m=audio 5000 RTP/AVP 0 +a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-srtp 1 --srtp-secure 0" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio 0 UNKNOWN[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP[\\s\\S]+a=crypto" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("SRTP audio and unknown media", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/321_srtp2_recv_avp.py b/tests/pjsua/scripts-sendto/321_srtp2_recv_avp.py new file mode 100644 index 0000000..12cd6e2 --- /dev/null +++ b/tests/pjsua/scripts-sendto/321_srtp2_recv_avp.py @@ -0,0 +1,28 @@ +# $Id: 321_srtp2_recv_avp.py 3713 2011-08-18 18:11:08Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 2 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Callee has SRTP mandatory and receive RTP/AVP with crypto, should reject the call", + pjsua_args=args, sdp=sdp, resp_code=488, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/322_srtp2_recv_savp.py b/tests/pjsua/scripts-sendto/322_srtp2_recv_savp.py new file mode 100644 index 0000000..1e841e8 --- /dev/null +++ b/tests/pjsua/scripts-sendto/322_srtp2_recv_savp.py @@ -0,0 +1,28 @@ +# $Id: 322_srtp2_recv_savp.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/SAVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:t0r0/apkukU7JjjfR0mY8GEimBq4OiPEm9eKSFOx +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 2 --srtp-secure 0" +include = ["m=audio \d+ RTP/SAVP", "a=crypto"] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "Callee has SRTP mandatory receive RTP/SAVP, should answer RTP/SAVP too", + pjsua_args=args, sdp=sdp, resp_code=200, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/323_srtp2_receive_too_long_key.py b/tests/pjsua/scripts-sendto/323_srtp2_receive_too_long_key.py new file mode 100644 index 0000000..7536577 --- /dev/null +++ b/tests/pjsua/scripts-sendto/323_srtp2_receive_too_long_key.py @@ -0,0 +1,25 @@ +# $Id: 323_srtp2_receive_too_long_key.py 3193 2010-06-03 02:27:41Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Too long key should be rejected +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/SAVP 0 +a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQWnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-srtp 2 --srtp-secure 0" +extra_headers = "" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg("SRTP receive too long key", pjsua_args, sdp, 406, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/323_srtp2_unsupported_crypto.py b/tests/pjsua/scripts-sendto/323_srtp2_unsupported_crypto.py new file mode 100644 index 0000000..bd322fe --- /dev/null +++ b/tests/pjsua/scripts-sendto/323_srtp2_unsupported_crypto.py @@ -0,0 +1,26 @@ +# $Id: 323_srtp2_unsupported_crypto.py 2036 2008-06-20 17:43:55Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=tester +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/SAVP 0 101 +a=rtpmap:0 PCMU/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +a=crypto:1 CRYPTO_X inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +""" + +args = "--null-audio --auto-answer 200 --max-calls 1 --use-srtp 2 --srtp-secure 0" +include = [] +exclude = [] + +sendto_cfg = sip.SendtoCfg( "caller has used unsupported crypto, callee (SRTP mandatory) must reject the call", + pjsua_args=args, sdp=sdp, resp_code=406, + resp_inc=include, resp_exc=exclude) diff --git a/tests/pjsua/scripts-sendto/330_srtp_prefer_rtp_savp.py b/tests/pjsua/scripts-sendto/330_srtp_prefer_rtp_savp.py new file mode 100644 index 0000000..ed79593 --- /dev/null +++ b/tests/pjsua/scripts-sendto/330_srtp_prefer_rtp_savp.py @@ -0,0 +1,30 @@ +# $Id: 330_srtp_prefer_rtp_savp.py 3251 2010-08-06 01:03:33Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# When SRTP is enabled in pjsua, it should prefer to use +# RTP/SAVP media line if there are multiple m=audio lines +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 4000 RTP/AVP 0 +a=rtpmap:0 pcmu/8000 +m=audio 4000 RTP/SAVP 0 +a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-srtp 1 --srtp-secure 0" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio 0 RTP/AVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/SAVP[\\s\\S]+a=crypto" + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Prefer RTP/SAVP", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/331_srtp_prefer_rtp_avp.py b/tests/pjsua/scripts-sendto/331_srtp_prefer_rtp_avp.py new file mode 100644 index 0000000..bd09465 --- /dev/null +++ b/tests/pjsua/scripts-sendto/331_srtp_prefer_rtp_avp.py @@ -0,0 +1,29 @@ +# $Id: 331_srtp_prefer_rtp_avp.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# When SRTP is NOT enabled in pjsua, it should prefer to use +# RTP/AVP media line if there are multiple m=audio lines +sdp = \ +""" +v=0 +o=- 0 0 IN IP4 127.0.0.1 +s=- +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 5000 RTP/SAVP 0 +a=crypto:1 aes_cm_128_hmac_sha1_80 inline:WnD7c1ksDGs+dIefCEo8omPg4uO8DYIinNGL5yxQ +m=audio 4000 RTP/AVP 0 +""" + +pjsua_args = "--null-audio --auto-answer 200 --use-srtp 0" +extra_headers = "" +include = ["Content-Type: application/sdp", # response must include SDP + "m=audio 0 RTP/SAVP[\\s\\S]+m=audio [1-9]+[0-9]* RTP/AVP" + ] +exclude = ["a=crypto"] + +sendto_cfg = sip.SendtoCfg("Prefer RTP/SAVP", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/360_non_sip_uri.py b/tests/pjsua/scripts-sendto/360_non_sip_uri.py new file mode 100644 index 0000000..d838669 --- /dev/null +++ b/tests/pjsua/scripts-sendto/360_non_sip_uri.py @@ -0,0 +1,27 @@ +# $Id: 360_non_sip_uri.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Some non-SIP URI's in Contact header +# +complete_msg = \ +"""INVITE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP 192.168.0.14:5060;rport;branch=z9hG4bKPj9db9 +Max-Forwards: 70 +From: ;tag=08cd5bfc2d8a4fddb1f5e59c6961d298 +To: +Call-ID: 3373d9eb32aa458db7e69c7ea51e0bd7 +CSeq: 0 INVITE +Contact: mailto:dontspam@pjsip.org +Contact: +Contact: http://www.pjsip.org/the%20path.cgi?pname=pvalue +Contact: +User-Agent: PJSUA v0.9.0-trunk/win32 +Content-Length: 0 +""" + + +sendto_cfg = sip.SendtoCfg( "Non SIP URI in Contact", + "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/361_non_sip_uri.py b/tests/pjsua/scripts-sendto/361_non_sip_uri.py new file mode 100644 index 0000000..4b2b59b --- /dev/null +++ b/tests/pjsua/scripts-sendto/361_non_sip_uri.py @@ -0,0 +1,26 @@ +# $Id: 361_non_sip_uri.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# No SIP URI in Contact header +# +complete_msg = \ +"""INVITE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP 192.168.0.14:5060;rport;branch=z9hG4bKPj9db9 +Max-Forwards: 70 +From: ;tag=08cd5bfc2d8a4fddb1f5e59c6961d298 +To: +Call-ID: 3373d9eb32aa458db7e69c7ea51e0bd7 +CSeq: 0 INVITE +Contact: mailto:dontspam@pjsip.org +Contact: +Contact: http://www.pjsip.org/the%20path.cgi?pname=pvalue +User-Agent: PJSUA v0.9.0-trunk/win32 +Content-Length: 0 +""" + + +sendto_cfg = sip.SendtoCfg( "No SIP URI in Contact", + "--null-audio --auto-answer 200", + "", 500, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/362_non_sip_uri.py b/tests/pjsua/scripts-sendto/362_non_sip_uri.py new file mode 100644 index 0000000..6065a23 --- /dev/null +++ b/tests/pjsua/scripts-sendto/362_non_sip_uri.py @@ -0,0 +1,27 @@ +# $Id: 362_non_sip_uri.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Some non-SIP URI's in Contact header +# +complete_msg = \ +"""INVITE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP 192.168.0.14:5060;rport;branch=z9hG4bKPj9db9 +Max-Forwards: 70 +From: ;tag=08cd5bfc2d8a4fddb1f5e59c6961d298 +To: +Call-ID: 3373d9eb32aa458db7e69c7ea51e0bd7 +CSeq: 0 INVITE +Contact: +Contact: mailto:dontspam@pjsip.org +Contact: +Contact: http://www.pjsip.org/the%20path.cgi?pname=pvalue +User-Agent: PJSUA v0.9.0-trunk/win32 +Content-Length: 0 +""" + + +sendto_cfg = sip.SendtoCfg( "Non SIP URI in Contact", + "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/363_non_sip_uri_subscribe.py b/tests/pjsua/scripts-sendto/363_non_sip_uri_subscribe.py new file mode 100644 index 0000000..8547829 --- /dev/null +++ b/tests/pjsua/scripts-sendto/363_non_sip_uri_subscribe.py @@ -0,0 +1,31 @@ +# $Id: 363_non_sip_uri_subscribe.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Some non-SIP URI's in Contact header +# +complete_msg = \ +"""SUBSCRIBE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP 192.168.0.14:5060;rport;branch=z9hG4bKPj9db9 +Max-Forwards: 70 +From: ;tag=08cd5bfc2d8a4fddb1f5e59c6961d298 +To: +Call-ID: 3373d9eb32aa458db7e69c7ea51e0bd7 +CSeq: 0 SUBSCRIBE +Contact: mailto:dontspam@pjsip.org +Contact: +Contact: http://www.pjsip.org/the%20path.cgi?pname=pvalue +Contact: +Event: presence +Expires: 600 +Accept: application/pidf+xml, application/xpidf+xml +Allow-Events: presence, refer +User-Agent: PJSUA v0.9.0-trunk/win32 +Content-Length: 0 +""" + + +sendto_cfg = sip.SendtoCfg( "Non SIP URI in Contact", + "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/364_non_sip_uri_subscribe.py b/tests/pjsua/scripts-sendto/364_non_sip_uri_subscribe.py new file mode 100644 index 0000000..598b8cb --- /dev/null +++ b/tests/pjsua/scripts-sendto/364_non_sip_uri_subscribe.py @@ -0,0 +1,30 @@ +# $Id: 364_non_sip_uri_subscribe.py 2392 2008-12-22 18:54:58Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Some non-SIP URI's in Contact header +# +complete_msg = \ +"""SUBSCRIBE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP 192.168.0.14:5060;rport;branch=z9hG4bKPj9db9 +Max-Forwards: 70 +From: ;tag=08cd5bfc2d8a4fddb1f5e59c6961d298 +To: +Call-ID: 3373d9eb32aa458db7e69c7ea51e0bd7 +CSeq: 0 SUBSCRIBE +Contact: mailto:dontspam@pjsip.org +Contact: +Contact: http://www.pjsip.org/the%20path.cgi?pname=pvalue +Event: presence +Expires: 600 +Accept: application/pidf+xml, application/xpidf+xml +Allow-Events: presence, refer +User-Agent: PJSUA v0.9.0-trunk/win32 +Content-Length: 0 +""" + + +sendto_cfg = sip.SendtoCfg( "Non SIP URI in Contact", + "--null-audio --auto-answer 200", + "", 400, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/400_fmtp_g7221_with_bitrate.py b/tests/pjsua/scripts-sendto/400_fmtp_g7221_with_bitrate.py new file mode 100644 index 0000000..c9a92da --- /dev/null +++ b/tests/pjsua/scripts-sendto/400_fmtp_g7221_with_bitrate.py @@ -0,0 +1,34 @@ +# $Id: 400_fmtp_g7221_with_bitrate.py 3664 2011-07-19 03:42:28Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Answer for codec G722.1 should contain fmtp bitrate + +sdp = \ +""" +v=0 +o=- 3428650655 3428650655 IN IP4 192.168.1.9 +s=pjmedia +c=IN IP4 192.168.1.9 +t=0 0 +a=X-nat:0 +m=audio 4000 RTP/AVP 99 100 101 +a=rtcp:4001 IN IP4 192.168.1.9 +a=rtpmap:99 G7221/16000 +a=fmtp:99 bitrate=24000 +a=rtpmap:100 G7221/16000 +a=fmtp:100 bitrate=32000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --add-codec G7221" +extra_headers = "" +include = ["fmtp:[\d]+ bitrate="] # response must include fmtp bitrate +exclude = [] + +sendto_cfg = sip.SendtoCfg("Answer should contain fmtp bitrate for codec G722.1", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_24000.py b/tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_24000.py new file mode 100644 index 0000000..760a797 --- /dev/null +++ b/tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_24000.py @@ -0,0 +1,35 @@ +# $Id: 401_fmtp_g7221_with_bitrate_24000.py 3664 2011-07-19 03:42:28Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Answer with codec G722.1 should choose the same bitrate +# which in this test is 24000 + +sdp = \ +""" +v=0 +o=- 3428650655 3428650655 IN IP4 192.168.1.9 +s=pjmedia +c=IN IP4 192.168.1.9 +t=0 0 +a=X-nat:0 +m=audio 4000 RTP/AVP 100 101 +a=rtcp:4001 IN IP4 192.168.1.9 +a=rtpmap:100 G7221/16000 +a=fmtp:100 bitrate=24000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --add-codec G7221" +extra_headers = "" +include = ["a=rtpmap:[\d]+ G7221/16000", # response must choose G722.1 + "fmtp:[\d]+ bitrate=24000" # response must choose the same bitrate + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Answer with G722.1 should choose bitrate 24000", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_32000.py b/tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_32000.py new file mode 100644 index 0000000..2a7aa32 --- /dev/null +++ b/tests/pjsua/scripts-sendto/401_fmtp_g7221_with_bitrate_32000.py @@ -0,0 +1,35 @@ +# $Id: 401_fmtp_g7221_with_bitrate_32000.py 3664 2011-07-19 03:42:28Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Answer with codec G722.1 should choose the same bitrate +# which in this test is 32000 + +sdp = \ +""" +v=0 +o=- 3428650655 3428650655 IN IP4 192.168.1.9 +s=pjmedia +c=IN IP4 192.168.1.9 +t=0 0 +a=X-nat:0 +m=audio 4000 RTP/AVP 100 101 +a=rtcp:4001 IN IP4 192.168.1.9 +a=rtpmap:100 G7221/16000 +a=fmtp:100 bitrate=32000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --add-codec G7221" +extra_headers = "" +include = ["a=rtpmap:[\d]+ G7221/16000", # response must choose G722.1 + "fmtp:[\d]+ bitrate=32000" # response must choose the same bitrate + ] +exclude = [] + +sendto_cfg = sip.SendtoCfg("Answer with G722.1 should choose bitrate 32000", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/410_fmtp_amrnb_offer_octet_align.py b/tests/pjsua/scripts-sendto/410_fmtp_amrnb_offer_octet_align.py new file mode 100644 index 0000000..9b386e3 --- /dev/null +++ b/tests/pjsua/scripts-sendto/410_fmtp_amrnb_offer_octet_align.py @@ -0,0 +1,32 @@ +# $Id: 410_fmtp_amrnb_offer_octet_align.py 3664 2011-07-19 03:42:28Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Answer for codec AMR should contain fmtp octet-align=1 + +sdp = \ +""" +v=0 +o=- 3428650655 3428650655 IN IP4 192.168.1.9 +s=pjmedia +c=IN IP4 192.168.1.9 +t=0 0 +a=X-nat:0 +m=audio 4000 RTP/AVP 99 101 +a=rtcp:4001 IN IP4 192.168.1.9 +a=rtpmap:99 AMR/8000 +a=fmtp:99 octet-align=1 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --add-codec AMR" +extra_headers = "" +include = ["octet-align=1"] # response must include 'octet-align=1' +exclude = [] + +sendto_cfg = sip.SendtoCfg("AMR negotiation should response with fmtp 'octet-align=1'", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/411_fmtp_amrnb_offer_band_eff.py b/tests/pjsua/scripts-sendto/411_fmtp_amrnb_offer_band_eff.py new file mode 100644 index 0000000..9eebff5 --- /dev/null +++ b/tests/pjsua/scripts-sendto/411_fmtp_amrnb_offer_band_eff.py @@ -0,0 +1,31 @@ +# $Id: 411_fmtp_amrnb_offer_band_eff.py 3664 2011-07-19 03:42:28Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Answer for codec AMR should not contain fmtp octet-align=1 + +sdp = \ +""" +v=0 +o=- 3428650655 3428650655 IN IP4 192.168.1.9 +s=pjmedia +c=IN IP4 192.168.1.9 +t=0 0 +a=X-nat:0 +m=audio 4000 RTP/AVP 99 101 +a=rtcp:4001 IN IP4 192.168.1.9 +a=rtpmap:99 AMR/8000 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --add-codec AMR" +extra_headers = "" +include = [""] +exclude = ["octet-align=1"] # response must not include fmtp 'octet-align=1' + +sendto_cfg = sip.SendtoCfg("AMR negotiation should not contain 'octet-align=1'", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/412_fmtp_amrnb_offer_band_eff2.py b/tests/pjsua/scripts-sendto/412_fmtp_amrnb_offer_band_eff2.py new file mode 100644 index 0000000..d602386 --- /dev/null +++ b/tests/pjsua/scripts-sendto/412_fmtp_amrnb_offer_band_eff2.py @@ -0,0 +1,32 @@ +# $Id: 412_fmtp_amrnb_offer_band_eff2.py 3664 2011-07-19 03:42:28Z nanang $ +import inc_sip as sip +import inc_sdp as sdp + +# Answer for codec AMR should not contain fmtp octet-align=1 + +sdp = \ +""" +v=0 +o=- 3428650655 3428650655 IN IP4 192.168.1.9 +s=pjmedia +c=IN IP4 192.168.1.9 +t=0 0 +a=X-nat:0 +m=audio 4000 RTP/AVP 99 101 +a=rtcp:4001 IN IP4 192.168.1.9 +a=rtpmap:99 AMR/8000 +a=fmtp:99 octet-align=0 +a=sendrecv +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +""" + +pjsua_args = "--null-audio --auto-answer 200 --add-codec AMR" +extra_headers = "" +include = [""] +exclude = ["octet-align=1"] # response must not include fmtp 'octet-align=1' + +sendto_cfg = sip.SendtoCfg("AMR negotiation should not contain 'octet-align=1'", pjsua_args, sdp, 200, + extra_headers=extra_headers, + resp_inc=include, resp_exc=exclude) + diff --git a/tests/pjsua/scripts-sendto/500_pres_subscribe_with_bad_event.py b/tests/pjsua/scripts-sendto/500_pres_subscribe_with_bad_event.py new file mode 100644 index 0000000..99e2aed --- /dev/null +++ b/tests/pjsua/scripts-sendto/500_pres_subscribe_with_bad_event.py @@ -0,0 +1,28 @@ +# $Id: 500_pres_subscribe_with_bad_event.py 2273 2008-09-11 10:25:51Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Ticket http://trac.pjsip.org/repos/ticket/623, based on +# http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/2008-September/004709.html: +# +# Assertion when receiving SUBSCRIBE with non-presence Event. +complete_msg = \ +"""SUBSCRIBE sip:localhost;transport=UDP SIP/2.0 +Call-ID: f20e8783e764cae325dba17be4b8fe19@10.0.2.15 +CSeq: 1 SUBSCRIBE +From: ;tag=1710895 +To: +Via: SIP/2.0/UDP localhost;rport;branch=z9hG4bKd88a.18c427d2.0 +Max-Forwards: 69 +Event: message-summary +Contact: +Allow: NOTIFY, SUBSCRIBE +Content-Length: 0 + +""" + + +sendto_cfg = sip.SendtoCfg( "Incoming SUBSCRIBE with non presence", + "--null-audio", + "", 489, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/999_asterisk_err.py b/tests/pjsua/scripts-sendto/999_asterisk_err.py new file mode 100644 index 0000000..18aaa06 --- /dev/null +++ b/tests/pjsua/scripts-sendto/999_asterisk_err.py @@ -0,0 +1,45 @@ +# $Id: 999_asterisk_err.py 2081 2008-06-27 21:59:15Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/2008-June/003426.html: +# +# Report in pjsip mailing list on 27/6/2008 that this message will +# cause pjsip to respond with 500 and then second request will cause +# segfault. +complete_msg = \ +"""INVITE sip:5001@192.168.1.200:5060;transport=UDP SIP/2.0 +Via: SIP/2.0/UDP 192.168.1.11:5060;branch=z9hG4bK74a60ee5;rport +From: \"A user\" ;tag=as2858a32c +To: +Contact: +Call-ID: 0bc7612c665e875a4a46411442b930a6@192.168.1.11 +CSeq: 102 INVITE +User-Agent: Asterisk PBX +Max-Forwards: 70 +Date: Fri, 27 Jun 2008 08:46:47 GMT +Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY +Supported: replaces +Content-Type: application/sdp +Content-Length: 285 + +v=0 +o=root 4236 4236 IN IP4 192.168.1.11 +s=session +c=IN IP4 192.168.1.11 +t=0 0 +m=audio 14390 RTP/AVP 0 3 8 101 +a=rtpmap:0 PCMU/8000 +a=rtpmap:3 GSM/8000 +a=rtpmap:8 PCMA/8000 +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-16 +a=silenceSupp:off - - - - +a=ptime:20 +a=sendrecv +""" + + +sendto_cfg = sip.SendtoCfg( "Asterisk 500", "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sendto/999_message_no_body.py b/tests/pjsua/scripts-sendto/999_message_no_body.py new file mode 100644 index 0000000..0663a6f --- /dev/null +++ b/tests/pjsua/scripts-sendto/999_message_no_body.py @@ -0,0 +1,24 @@ +# $Id: 999_message_no_body.py 2884 2009-08-17 08:29:47Z bennylp $ +import inc_sip as sip +import inc_sdp as sdp + +# Incoming MESSAGE without body is now accepted +# +complete_msg = \ +"""MESSAGE sip:localhost SIP/2.0 +Via: SIP/2.0/UDP 192.168.0.14:5060;rport;branch=z9hG4bKPj9db9 +Max-Forwards: 70 +From: ;tag=08cd5bfc2d8a4fddb1f5e59c6961d298 +To: +Call-ID: 3373d9eb32aa458db7e69c7ea51e0bd7 +CSeq: 23809 MESSAGE +Contact: +User-Agent: PJSUA v0.8.0-trunk/win32 +Content-Type: text/plain +Content-Length: 50 +""" + + +sendto_cfg = sip.SendtoCfg( "empty MESSAGE", "--null-audio --auto-answer 200", + "", 200, complete_msg=complete_msg) + diff --git a/tests/pjsua/scripts-sipp/strict-route.py b/tests/pjsua/scripts-sipp/strict-route.py new file mode 100644 index 0000000..fbf2b18 --- /dev/null +++ b/tests/pjsua/scripts-sipp/strict-route.py @@ -0,0 +1,9 @@ +# $Id: strict-route.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id=sip:pjsua@localhost --username=pjsua --realm=* $SIPP_URI"] + +PJSUA_EXPECTS = [[0, "ACK sip:proxy@.* SIP/2\.0", ""], + [0, const.STATE_CONFIRMED, "h"] + ] diff --git a/tests/pjsua/scripts-sipp/strict-route.xml b/tests/pjsua/scripts-sipp/strict-route.xml new file mode 100644 index 0000000..0ed6935 --- /dev/null +++ b/tests/pjsua/scripts-sipp/strict-route.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Record-route: + Content-Type: application/sdp + + v=0 + o=- 3442013205 3442013205 IN IP4 [local_ip] + s=pjsip + c=IN IP4 [local_ip] + t=0 0 + m=audio 4002 RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + Record-route: + Content-Type: application/sdp + + v=0 + o=- 3442013205 3442013205 IN IP4 [local_ip] + s=pjsip + c=IN IP4 [local_ip] + t=0 0 + m=audio 4002 RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/transfer-attended.py b/tests/pjsua/scripts-sipp/transfer-attended.py new file mode 100644 index 0000000..2eaf44b --- /dev/null +++ b/tests/pjsua/scripts-sipp/transfer-attended.py @@ -0,0 +1,52 @@ +# $Id: transfer-attended.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio", # UA0 + "--null-audio", # UA1 + "--null-audio" # UA2 + ] + +PJSUA_EXPECTS = [ + # A calls B + [0, "", "m"], + [0, "", "$PJSUA_URI[1]"], + [0, const.STATE_CALLING, ""], + [1, const.EVENT_INCOMING_CALL, "a"], + [1, "", "200"], + [0, const.STATE_CONFIRMED, ""], + [1, const.STATE_CONFIRMED, ""], + + # B holds A + [1, "", "H"], + [0, const.MEDIA_HOLD, ""], + [1, const.MEDIA_HOLD, ""], + + # B calls C + [1, "", "m"], + [1, "", "$PJSUA_URI[2]"], + [1, const.STATE_CALLING, ""], + [2, const.EVENT_INCOMING_CALL, "a"], + [2, "", "200"], + [1, const.STATE_CONFIRMED, ""], + [2, const.STATE_CONFIRMED, ""], + + # B holds C + [1, "", "]"], + [1, "", "H"], + [2, const.MEDIA_HOLD, ""], + [1, const.MEDIA_HOLD, ""], + [1, "", "]"], + + # B transfer A to C + [1, "", "X"], + [1, "", "1"], + [0, "Call .* is being transfered", ""], + [1, "Subscription state .* ACCEPTED", ""], + [0, const.STATE_CALLING, ""], + [2, "Call .* is being replaced", ""], + [1, "call transfered successfully", ""], + [0, const.MEDIA_ACTIVE, ""], + [2, const.MEDIA_ACTIVE, ""], + [1, const.STATE_DISCONNECTED, ""] + ] diff --git a/tests/pjsua/scripts-sipp/transfer-attended.xml b/tests/pjsua/scripts-sipp/transfer-attended.xml new file mode 100644 index 0000000..bd184d2 --- /dev/null +++ b/tests/pjsua/scripts-sipp/transfer-attended.xml @@ -0,0 +1,26 @@ + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + Max-Forwards: 70 + CSeq: 1 OPTIONS + Content-Length: 0 + + ]]> + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/transfer-unattended.py b/tests/pjsua/scripts-sipp/transfer-unattended.py new file mode 100644 index 0000000..14011e1 --- /dev/null +++ b/tests/pjsua/scripts-sipp/transfer-unattended.py @@ -0,0 +1,30 @@ +# $Id: transfer-unattended.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio", # UA0 + "--null-audio", # UA1 + "--null-audio" # UA2 + ] + +PJSUA_EXPECTS = [ + # A calls B + [0, "", "m"], + [0, "", "$PJSUA_URI[1]"], + [0, const.STATE_CALLING, ""], + [1, const.EVENT_INCOMING_CALL, "a"], + [1, "", "200"], + [0, const.STATE_CONFIRMED, ""], + [1, const.STATE_CONFIRMED, ""], + + # B transfer A to C + [1, "", "x"], + [1, "", "$PJSUA_URI[2]"], + [0, const.STATE_CALLING, ""], + [2, const.EVENT_INCOMING_CALL, "a"], + [2, "", "200"], + [0, const.MEDIA_ACTIVE, ""], + [2, const.MEDIA_ACTIVE, ""], + [1, "call transfered successfully", ""], + [1, const.STATE_DISCONNECTED, ""] + ] diff --git a/tests/pjsua/scripts-sipp/transfer-unattended.xml b/tests/pjsua/scripts-sipp/transfer-unattended.xml new file mode 100644 index 0000000..bd184d2 --- /dev/null +++ b/tests/pjsua/scripts-sipp/transfer-unattended.xml @@ -0,0 +1,26 @@ + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + Max-Forwards: 70 + CSeq: 1 OPTIONS + Content-Length: 0 + + ]]> + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-bad-ack.xml b/tests/pjsua/scripts-sipp/uac-bad-ack.xml new file mode 100644 index 0000000..d93e30c --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-bad-ack.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-inv-and-ack-without-sdp.xml b/tests/pjsua/scripts-sipp/uac-inv-and-ack-without-sdp.xml new file mode 100644 index 0000000..a61aba7 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-inv-and-ack-without-sdp.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + ]]> + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml b/tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml new file mode 100644 index 0000000..384be82 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-inv-multiple-require.xml @@ -0,0 +1,67 @@ + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Require: timer + Require: toto + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio [media_port] RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + + ]]> + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.py b/tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.py new file mode 100644 index 0000000..fd82347 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.py @@ -0,0 +1,7 @@ +# $Id: uac-inv-two-media-but-one-disabled-no-rtpmap.py 4177 2012-06-26 02:28:59Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --auto-answer=200"] + +PJSUA_EXPECTS = [[0, const.STATE_CONFIRMED, "v"]] diff --git a/tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.xml b/tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.xml new file mode 100644 index 0000000..0770fe9 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-inv-two-media-but-one-disabled-no-rtpmap.xml @@ -0,0 +1,97 @@ + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 3 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio 4000 RTP/AVP 0 + m=video 0 RTP/AVP 100 + + ]]> + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 3 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-inv-without-sdp.py b/tests/pjsua/scripts-sipp/uac-inv-without-sdp.py new file mode 100644 index 0000000..45f9467 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-inv-without-sdp.py @@ -0,0 +1,11 @@ +# $Id: uac-inv-without-sdp.py 4177 2012-06-26 02:28:59Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1"] + +PJSUA_EXPECTS = [[0, const.EVENT_INCOMING_CALL, "a"], + [0, "", "200"], + [0, const.MEDIA_ACTIVE, ""], + [0, const.STATE_CONFIRMED, "h"] + ] diff --git a/tests/pjsua/scripts-sipp/uac-inv-without-sdp.xml b/tests/pjsua/scripts-sipp/uac-inv-without-sdp.xml new file mode 100644 index 0000000..929c83a --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-inv-without-sdp.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + ]]> + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + +v=0 +o=BroadWorks 1378618 0 IN IP4 192.168.2.25 +s=- +c=IN IP4 192.168.2.25 +t=0 0 +m=audio 4020 RTP/AVP 0 101 +c=IN IP4 192.168.2.25 +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-15 +m=video 4022 RTP/AVP 97 +c=IN IP4 192.168.2.25 +b=TIAS:512000 +a=rtpmap:97 H264/90000 +a=fmtp:97 profile-level-id=42900b +a=orient:portrait +a=rtcp-fb:* nack pli + + ]]> + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-message-no-body.xml b/tests/pjsua/scripts-sipp/uac-message-no-body.xml new file mode 100644 index 0000000..1b7f072 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-message-no-body.xml @@ -0,0 +1,32 @@ + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 MESSAGE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Message without body + Content-Length: 0 + + ]]> + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-options.xml b/tests/pjsua/scripts-sipp/uac-options.xml new file mode 100644 index 0000000..7b14884 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-options.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 OPTIONS + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: [len] + + ]]> + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-reinvite-bad-via-branch.xml b/tests/pjsua/scripts-sipp/uac-reinvite-bad-via-branch.xml new file mode 100644 index 0000000..ed825c9 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-reinvite-bad-via-branch.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Tester 234 123 IN IP4 127.0.0.1 + s=Tester + c=IN IP4 127.0.0.1 + t=0 0 + m=audio 17424 RTP/AVP 0 101 + a=rtpmap:101 telephone-event/8000 + a=sendrecv + + ]]> + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Tester 234 124 IN IP4 127.0.0.1 + s=Tester + c=IN IP4 127.0.0.1 + t=0 0 + m=audio 17424 RTP/AVP 0 101 + a=rtpmap:101 telephone-event/8000 + + + ]]> + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 3 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-reinvite-port-0-bad-sdp.xml b/tests/pjsua/scripts-sipp/uac-reinvite-port-0-bad-sdp.xml new file mode 100644 index 0000000..d1cc04f --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-reinvite-port-0-bad-sdp.xml @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Tester 234 123 IN IP4 89.208.145.194 + s=Tester + c=IN IP4 89.208.145.194 + t=0 0 + m=audio 17424 RTP/AVP 111 0 18 101 + a=rtpmap:111 SPEEX/16000 + a=rtpmap:0 PCMU/8000 + a=rtpmap:18 G729/8000 + a=rtpmap:101 telephone-event/8000 + a=sendrecv + a=rtcp:17425 + m=video 11128 RTP/AVP 34 103 104 + a=rtpmap:34 H263/90000 + a=rtpmap:103 H263-1998/90000 + a=rtpmap:104 H264/90000 + a=sendrecv + a=rtcp:11129 + + ]]> + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Tester 234 124 IN IP4 89.208.145.194 + s=Tester + c=IN IP4 89.208.145.194 + t=0 0 + m=audio 17424 RTP/AVP 111 0 18 101 + a=rtpmap:111 SPEEX/16000 + a=rtpmap:0 PCMU/8000 + a=rtpmap:18 G729/8000 + a=rtpmap:101 telephone-event/8000 + a=sendrecv + a=rtcp:17425 + m=video 0 RTP/AVP 34 103 104 + a=sendrecv + + + ]]> + + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 2 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 3 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-subscribe.xml b/tests/pjsua/scripts-sipp/uac-subscribe.xml new file mode 100644 index 0000000..c42e951 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-subscribe.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 1 SUBSCRIBE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Event: presence + Expires: 600 + Accept: application/pidf+xml, application/xpidf+xml + Allow-Events: presence, refer + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + ;tag=[call_number] + To: sut + Call-ID: [call_id] + CSeq: 2 SUBSCRIBE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Event: presence + Expires: 0 + Accept: application/pidf+xml, application/xpidf+xml + Allow-Events: presence, refer + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uac-ticket-1148.py b/tests/pjsua/scripts-sipp/uac-ticket-1148.py new file mode 100644 index 0000000..414cb8c --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-ticket-1148.py @@ -0,0 +1,7 @@ +# $Id: uac-ticket-1148.py 4177 2012-06-26 02:28:59Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --auto-answer=200"] + +PJSUA_EXPECTS = [[0, const.STATE_CONFIRMED, "v"]] diff --git a/tests/pjsua/scripts-sipp/uac-ticket-1148.xml b/tests/pjsua/scripts-sipp/uac-ticket-1148.xml new file mode 100644 index 0000000..2a2ec8b --- /dev/null +++ b/tests/pjsua/scripts-sipp/uac-ticket-1148.xml @@ -0,0 +1,98 @@ + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 3 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] + s=- + c=IN IP[media_ip_type] [media_ip] + t=0 0 + m=audio 4000 RTP/AVP 0 + m=video 5000 RTP/AVP 100 + a=rtpmap:100 H261/90000 + + ]]> + + + + + + + + + + + ;tag=[call_number] + To: sut [peer_tag_param] + Call-ID: [call_id] + CSeq: 3 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Subject: Performance Test + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-422-then-200-bad-se.xml b/tests/pjsua/scripts-sipp/uas-422-then-200-bad-se.xml new file mode 100644 index 0000000..9f4df39 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-422-then-200-bad-se.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Min-SE: 5400 + Content-Length: 0 + + ]]> + + + + + + + + + + + + Supported: replaces + Session-Expires: 3600;refresher=uas + Require: timer + Content-Type: application/sdp + Content-Disposition: session;handling=required + Content-Length: [len] + + v=0 + o=Some-UserAgent 68 210 IN IP4 [local_ip] + s=SIP Call + c=IN IP4 [local_ip] + t=0 0 + m=audio 17294 RTP/AVP 0 101 + c=IN IP4 [local_ip] + a=rtpmap:0 PCMU/8000 + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-16 + a=ptime:20 + + ]]> + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts-support-update.xml b/tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts-support-update.xml new file mode 100644 index 0000000..8016272 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts-support-update.xml @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts.xml b/tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts.xml new file mode 100644 index 0000000..5ff1f99 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-180-multiple-fmts.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-answer-200-inv-without-sdp.xml b/tests/pjsua/scripts-sipp/uas-answer-200-inv-without-sdp.xml new file mode 100644 index 0000000..70a3b5f --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-200-inv-without-sdp.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts-support-update.xml b/tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts-support-update.xml new file mode 100644 index 0000000..8605381 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts-support-update.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts.xml b/tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts.xml new file mode 100644 index 0000000..9fee67b --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-200-multiple-fmts.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.py b/tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.py new file mode 100644 index 0000000..5bd516d --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.py @@ -0,0 +1,7 @@ +# $Id: uas-answer-200-reinvite-without-sdp.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 $SIPP_URI"] + +PJSUA_EXPECTS = [[0, const.STATE_CONFIRMED, "v"]] diff --git a/tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.xml b/tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.xml new file mode 100644 index 0000000..f51c421 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-200-reinvite-without-sdp.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.py b/tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.py new file mode 100644 index 0000000..adc562a --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.py @@ -0,0 +1,7 @@ +# $Id: uas-answer-200-update-without-sdp.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 $SIPP_URI"] + +PJSUA_EXPECTS = [[0, const.STATE_CONFIRMED, "U"]] diff --git a/tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.xml b/tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.xml new file mode 100644 index 0000000..e561db1 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-answer-200-update-without-sdp.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-auth.py b/tests/pjsua/scripts-sipp/uas-auth.py new file mode 100644 index 0000000..fbe422b --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-auth.py @@ -0,0 +1,7 @@ +# $Id: uas-auth.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id=sip:a@localhost --username=a --realm=* --registrar=$SIPP_URI"] + +PJSUA_EXPECTS = [] diff --git a/tests/pjsua/scripts-sipp/uas-auth.xml b/tests/pjsua/scripts-sipp/uas-auth.xml new file mode 100644 index 0000000..96be0b9 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-auth.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-cancel-no-final.py b/tests/pjsua/scripts-sipp/uas-cancel-no-final.py new file mode 100644 index 0000000..bf8f8d7 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-cancel-no-final.py @@ -0,0 +1,7 @@ +# $Id: uas-cancel-no-final.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 $SIPP_URI"] + +PJSUA_EXPECTS = [[0, const.STATE_EARLY, "h"]] diff --git a/tests/pjsua/scripts-sipp/uas-cancel-no-final.xml b/tests/pjsua/scripts-sipp/uas-cancel-no-final.xml new file mode 100644 index 0000000..e96f2a3 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-cancel-no-final.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-early-bye.xml b/tests/pjsua/scripts-sipp/uas-early-bye.xml new file mode 100644 index 0000000..216b8b4 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-early-bye.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 BYE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-forked-100rel.xml b/tests/pjsua/scripts-sipp/uas-forked-100rel.xml new file mode 100644 index 0000000..3a1ca22 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-forked-100rel.xml @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Require: 100rel + RSeq: 1000 + Content-Length: 0 + ]]> + + + + + + + + + + + + + + + + Require: 100rel + RSeq: 2000 + Content-Length: 0 + ]]> + + + + + + + + + + + + + + + + Require: 100rel + RSeq: 2001 + Content-Length: 0 + ]]> + + + + + + + + + + + + + + + + Require: 100rel + RSeq: 2004 + Content-Length: 0 + ]]> + + + + + + + + Require: 100rel + RSeq: 1001 + Content-Length: 0 + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-forked-200.xml b/tests/pjsua/scripts-sipp/uas-forked-200.xml new file mode 100644 index 0000000..a67f8ca --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-forked-200.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Type: application/sdp + + v=0 + o=- 3442013205 3442013205 IN IP4 192.168.0.13 + s=pjsip + c=IN IP4 192.168.0.13 + t=0 0 + m=audio 4002 RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + Content-Type: application/sdp + + v=0 + o=- 3442013205 3442013205 IN IP4 192.168.0.13 + s=pjsip + c=IN IP4 192.168.0.13 + t=0 0 + m=audio 4002 RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-inv-answered-with-srtp.xml b/tests/pjsua/scripts-sipp/uas-inv-answered-with-srtp.xml new file mode 100644 index 0000000..1f928e7 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-inv-answered-with-srtp.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Type: application/sdp + + v=0 + o=- 3441953879 3441953879 IN IP4 192.168.0.15 + s=pjmedia + c=IN IP4 192.168.0.15 + t=0 0 + m=audio 4004 RTP/SAVP 0 101 + a=rtpmap:0 PCMU/8000 + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-15 + a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:D4Mf5fIPqxwse/lLrVc2XhLk7NSL6JI0k0Jps4Br + + ]]> + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-inv_401_retry_after_100.xml b/tests/pjsua/scripts-sipp/uas-inv_401_retry_after_100.xml new file mode 100644 index 0000000..6debd13 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-inv_401_retry_after_100.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-mwi-0.py b/tests/pjsua/scripts-sipp/uas-mwi-0.py new file mode 100644 index 0000000..9c30a49 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-mwi-0.py @@ -0,0 +1,7 @@ +# $Id: uas-mwi-0.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id sip:pjsua@localhost:$SIPP_PORT --mwi"] + +PJSUA_EXPECTS = [] diff --git a/tests/pjsua/scripts-sipp/uas-mwi-0.xml b/tests/pjsua/scripts-sipp/uas-mwi-0.xml new file mode 100644 index 0000000..6697c17 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-mwi-0.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + Expires: 600 + ]]> + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: message-summary + Subscription-State: terminated;reason=goinghome + Content-Type: application/simple-message-summary + Content-Length: [len] + + Messages-Waiting: yes + Voice-Message: 4/8 (1/2) + + ]]> + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-mwi.py b/tests/pjsua/scripts-sipp/uas-mwi.py new file mode 100644 index 0000000..df2e577 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-mwi.py @@ -0,0 +1,7 @@ +# $Id: uas-mwi.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id sip:pjsua@localhost:$SIPP_PORT --mwi"] + +PJSUA_EXPECTS = [] diff --git a/tests/pjsua/scripts-sipp/uas-mwi.xml b/tests/pjsua/scripts-sipp/uas-mwi.xml new file mode 100644 index 0000000..ed81195 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-mwi.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + Expires: 600 + ]]> + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: message-summary + Subscription-State: active;expires=50 + Content-Type: application/simple-message-summary + Content-Length: [len] + + Messages-Waiting: yes + Voice-Message: 4/8 (1/2) + + ]]> + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 2 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: message-summary + Subscription-State: terminated;reason=noresource + Content-Type: application/simple-message-summary + Content-Length: [len] + + Messages-Waiting: yes + Voice-Message: 4/8 (1/2) + + ]]> + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-prack_fork.xml b/tests/pjsua/scripts-sipp/uas-prack_fork.xml new file mode 100644 index 0000000..ddae747 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-prack_fork.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + ]]> + + + + + + + + + + + + + + + Content-Type: application/sdp + + v=0 + o=- 3442013205 3442013205 IN IP4 192.168.0.13 + s=pjsip + c=IN IP4 192.168.0.13 + t=0 0 + m=audio 4002 RTP/AVP 0 + a=rtpmap:0 PCMU/8000 + ]]> + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-reinv-and-ack-same-branch-without-sdp.xml b/tests/pjsua/scripts-sipp/uas-reinv-and-ack-same-branch-without-sdp.xml new file mode 100644 index 0000000..cab4e53 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-reinv-and-ack-same-branch-without-sdp.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-reinv-and-ack-without-sdp.xml b/tests/pjsua/scripts-sipp/uas-reinv-and-ack-without-sdp.xml new file mode 100644 index 0000000..90e1cec --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-reinv-and-ack-without-sdp.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-reinv-glare.py b/tests/pjsua/scripts-sipp/uas-reinv-glare.py new file mode 100644 index 0000000..a6b2d25 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-reinv-glare.py @@ -0,0 +1,7 @@ +# $Id: uas-reinv-glare.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 $SIPP_URI"] + +PJSUA_EXPECTS = [[0, const.STATE_CONFIRMED, "U"]] diff --git a/tests/pjsua/scripts-sipp/uas-reinv-glare.xml b/tests/pjsua/scripts-sipp/uas-reinv-glare.xml new file mode 100644 index 0000000..60c65f7 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-reinv-glare.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=- 2 2 IN IP4 192.168.0.15 + s=pjmedia + c=IN IP4 192.168.0.15 + t=0 0 + m=audio 4004 RTP/AVP 0 + + ]]> + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-reinv-no-media.xml b/tests/pjsua/scripts-sipp/uas-reinv-no-media.xml new file mode 100644 index 0000000..1c16fdd --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-reinv-no-media.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=- 2 2 IN IP4 192.168.0.15 + s=pjmedia + c=IN IP4 192.168.0.15 + t=0 0 + m=audio 0 RTP/AVP 0 + + ]]> + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 INVITE + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Content-Length: 0 + + ]]> + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-late-notify.py b/tests/pjsua/scripts-sipp/uas-subscribe-late-notify.py new file mode 100644 index 0000000..3734132 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-late-notify.py @@ -0,0 +1,11 @@ +# $Id: uas-subscribe-late-notify.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id sip:pjsua@localhost --add-buddy $SIPP_URI"] + +PJSUA_EXPECTS = [[0, "", "s"], + [0, "Subscribe presence of:", "1"], + [0, "subscription state is ACTIVE", ""], + [0, "subscription state is TERMINATED", ""] + ] diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-late-notify.xml b/tests/pjsua/scripts-sipp/uas-subscribe-late-notify.xml new file mode 100644 index 0000000..7bf0664 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-late-notify.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + Expires: 60 + ]]> + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: active;expires=10 + Content-Type: application/pidf+xml + + + + + + open + + + closed + + active + + org.openmobilealliance:PoC-session + 1.0 + + + + ]]> + + + + + + + + + + + + Content-Length: 0 + Expires: 60 + ]]> + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 2 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: terminated;reason=timeout + Content-Length: 0 + ]]> + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.py b/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.py new file mode 100644 index 0000000..6316c81 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.py @@ -0,0 +1,11 @@ +# $Id: uas-subscribe-multipart-notify.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id sip:pjsua@localhost --add-buddy $SIPP_URI"] + +PJSUA_EXPECTS = [[0, "", "s"], + [0, "Subscribe presence of:", "1"], + [0, "status is Online", ""], + [0, "subscription state is TERMINATED", ""] + ] diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml b/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml new file mode 100644 index 0000000..e2e1f9b --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-multipart-notify.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + Expires: 60 + ]]> + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: active;expires=10 + Content-Type: multipart/mixed;boundary=abcd + + --abcd + Content-Type: text/plain + + Hi there, please don't read this part. + --abcd + Content-Type: application/pidf+xml + + + + + + open + + + + --abcd-- + ]]> + + + + + + + + + + + + + + + + Content-Length: 0 + ]]> + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.py b/tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.py new file mode 100644 index 0000000..ed64feb --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.py @@ -0,0 +1,10 @@ +# $Id: uas-subscribe-notify-terminate.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id sip:pjsua@localhost --add-buddy $SIPP_URI"] + +PJSUA_EXPECTS = [[0, "", "s"], + [0, "Subscribe presence of:", "1"], + [0, "subscription state is TERMINATED", ""] + ] diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.xml b/tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.xml new file mode 100644 index 0000000..1171a56 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-notify-terminate.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + Expires: 0 + ]]> + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: terminated;reason=timeout + Content-Type: application/pidf+xml + + + + + + open + + + closed + + active + + org.openmobilealliance:PoC-session + 1.0 + + + + ]]> + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.py b/tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.py new file mode 100644 index 0000000..549e98f --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.py @@ -0,0 +1,11 @@ +# $Id: uas-subscribe-refresh-481.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id sip:pjsua@localhost --add-buddy $SIPP_URI"] + +PJSUA_EXPECTS = [[0, "", "s"], + [0, "Subscribe presence of:", "1"], + [0, "status is Online", ""], + [0, "subscription state is TERMINATED", ""] + ] diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.xml b/tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.xml new file mode 100644 index 0000000..0cb2682 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-refresh-481.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + Expires: 60 + ]]> + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: active;expires=10 + Content-Type: application/pidf+xml + + + + + + open + + + + ]]> + + + + + + + + + + + + + + + + Content-Length: 0 + ]]> + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.py b/tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.py new file mode 100644 index 0000000..4a79d44 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.py @@ -0,0 +1,11 @@ +# $Id: uas-subscribe-terminated-retry.py 4188 2012-06-29 09:01:17Z nanang $ +# +import inc_const as const + +PJSUA = ["--null-audio --max-calls=1 --id sip:pjsua@localhost --add-buddy $SIPP_URI"] + +PJSUA_EXPECTS = [[0, "", "s"], + [0, "Subscribe presence of:", "1"], + [0, "Presence subscription .* is TERMINATED", ""], + [0, "Resubscribing .* in 5000 ms", ""] + ] diff --git a/tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.xml b/tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.xml new file mode 100644 index 0000000..4843cc3 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-subscribe-terminated-retry.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + Expires: 60 + ]]> + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 1 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: active;expires=50 + Content-Type: application/pidf+xml + + + + + + open + + + + ]]> + + + + + + + + + + + + + ;tag=[call_number] + To[$3] + Call-ID: [call_id] + Cseq: 3 NOTIFY + Contact: sip:sipp@[local_ip]:[local_port] + Max-Forwards: 70 + Event: presence + Subscription-State: terminated;reason=probation;retry-after=5 + Content-Length: 0 + ]]> + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-template.xml b/tests/pjsua/scripts-sipp/uas-template.xml new file mode 100644 index 0000000..d51f89c --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-template.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Content-Length: 0 + ]]> + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-timer-reinvite.xml b/tests/pjsua/scripts-sipp/uas-timer-reinvite.xml new file mode 100644 index 0000000..fe5169b --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-timer-reinvite.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Require: timer + Session-Expires: 90;refresher=uac + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Some-UserAgent 68 210 IN IP4 [local_ip] + s=SIP Call + c=IN IP4 [local_ip] + t=0 0 + m=audio 17294 RTP/AVP 0 101 + c=IN IP4 [local_ip] + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-16 + ]]> + + + + + + + + + + + Require: timer + Session-Expires: 90;refresher=uac + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Some-UserAgent 68 210 IN IP4 [local_ip] + s=SIP Call + c=IN IP4 [local_ip] + t=0 0 + m=audio 17294 RTP/AVP 0 101 + c=IN IP4 [local_ip] + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-16 + ]]> + + + + + + + + + + + + + + + + + + diff --git a/tests/pjsua/scripts-sipp/uas-timer-update.xml b/tests/pjsua/scripts-sipp/uas-timer-update.xml new file mode 100644 index 0000000..11a5973 --- /dev/null +++ b/tests/pjsua/scripts-sipp/uas-timer-update.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Allow: UPDATE, INVITE + Require: timer + Session-Expires: 90;refresher=uac + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Some-UserAgent 68 210 IN IP4 [local_ip] + s=SIP Call + c=IN IP4 [local_ip] + t=0 0 + m=audio 17294 RTP/AVP 0 101 + c=IN IP4 [local_ip] + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-16 + ]]> + + + + + + + + + + + Allow: INVITE + Require: timer + Session-Expires: 90;refresher=uac + Content-Length: 0 + ]]> + + + + + + + + Allow: INVITE + Require: timer + Session-Expires: 90;refresher=uac + Content-Type: application/sdp + Content-Length: [len] + + v=0 + o=Some-UserAgent 68 210 IN IP4 [local_ip] + s=SIP Call + c=IN IP4 [local_ip] + t=0 0 + m=audio 17294 RTP/AVP 0 101 + c=IN IP4 [local_ip] + a=rtpmap:101 telephone-event/8000 + a=fmtp:101 0-16 + ]]> + + + + + + + + + + + + + + + diff --git a/tests/pjsua/tools/Makefile b/tests/pjsua/tools/Makefile new file mode 100644 index 0000000..189eb00 --- /dev/null +++ b/tests/pjsua/tools/Makefile @@ -0,0 +1,21 @@ +#Modify this to point to the PJSIP location. +PJBASE=~/Desktop/project/pjproject + +include $(PJBASE)/build.mak + +CC = $(APP_CC) +LDFLAGS = $(APP_LDFLAGS) +LDLIBS = $(APP_LDLIBS) +CFLAGS = $(APP_CFLAGS) +CPPFLAGS= ${CFLAGS} + +# If your application is in a file named myapp.cpp or myapp.c +# # this is the line you will need to build the binary. +# all: myapp +# +cmp_wav: cmp_wav.c + $(CC) -o $@ $< $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) + +clean: + rm -f cmp_wav.o cmp_wav + diff --git a/tests/pjsua/tools/cmp_wav.c b/tests/pjsua/tools/cmp_wav.c new file mode 100644 index 0000000..e3c864c --- /dev/null +++ b/tests/pjsua/tools/cmp_wav.c @@ -0,0 +1,262 @@ +/* $Id: cmp_wav.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#define app_perror(a,b,c) printf("%s: %s (%d)", a, b, c) + + +/* For logging purpose. */ +#define THIS_FILE "cmp_wav.c" +#define BYTES_PER_FRAME 512 + +static const char *desc = +" FILE \n" +" \n" +" cmp_wav.c \n" +" \n" +" PURPOSE \n" +" \n" +" Compare two WAV files. \n" +" \n" +" USAGE \n" +" \n" +" cmp_wav ORIGINAL_WAV DEGRADED_WAV [TIME] [DETAIL] \n" +" \n" +" ORIGINAL_WAV The original WAV file as reference. \n" +" DEGRADED_WAV The degraded WAV file. \n" +" TIME Compare only some part of the files \n" +" (in ms, since the beginning). \n" +" Specify 0 (default) to compare the whole time. \n" +" DETAIL Show detail result, 1 or 0 (default=0, means no)\n" +" \n" +" Both files must have same clock rate and must contain \n" +" uncompressed (i.e. 16bit) PCM. \n"; + + +/* Sum of multiplication of corresponding samples in buf1 & buf2 */ +double sum_mult_sig(pj_int16_t *buf1, pj_int16_t *buf2, unsigned nsamples) +{ + double mag = 0; + + while (nsamples--) + mag += (double)*buf1++ * (double)*buf2++; + + return mag; +} + + +/* + * main() + */ +int main(int argc, char *argv[]) +{ + pj_caching_pool cp; + pjmedia_endpt *med_endpt; + pj_pool_t *pool; + pjmedia_port *file_ori_port; + pjmedia_port *file_deg_port; + pj_status_t status; + unsigned first_nsamples = 0; + unsigned samples_compared = 0; + + char buf1[BYTES_PER_FRAME]; + char buf2[BYTES_PER_FRAME]; + + double ref_mag = 0; + double deg_mag = 0; + double mix_mag = 0; + + int detail = 0; + int res_deg, res_mix, res_overall; + + if (argc < 3) { + puts("Error: original & degraded filename required"); + puts(desc); + return 1; + } + + /* Set log level. */ + pj_log_set_level(3); + + /* Must init PJLIB first: */ + status = pj_init(); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + /* Must create a pool factory before we can allocate any memory. */ + pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); + + /* + * Initialize media endpoint. + * This will implicitly initialize PJMEDIA too. + */ + status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + /* Create memory pool for our file player */ + pool = pj_pool_create( &cp.factory, /* pool factory */ + "wav", /* pool name. */ + 4000, /* init size */ + 4000, /* increment size */ + NULL /* callback on error */ + ); + + /* Create file media port from the original WAV file */ + status = pjmedia_wav_player_port_create( pool, /* memory pool */ + argv[1], /* file to play */ + 40, /* ptime. */ + PJMEDIA_FILE_NO_LOOP, /* flags */ + 0, /* default buffer */ + &file_ori_port/* returned port */ + ); + if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Unable to use WAV file", status); + return 1; + } + + /* Create file media port from the degraded WAV file */ + status = pjmedia_wav_player_port_create( pool, /* memory pool */ + argv[2], /* file to play */ + 40, /* ptime. */ + PJMEDIA_FILE_NO_LOOP, /* flags */ + 0, /* default buffer */ + &file_deg_port/* returned port */ + ); + if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Unable to use WAV file", status); + return 1; + } + + if (file_ori_port->info.clock_rate != file_deg_port->info.clock_rate) { + app_perror(THIS_FILE, "Clock rates must be same.", PJ_EINVAL); + return 1; + } + + if (argc > 3) + first_nsamples = atoi(argv[3]) * file_ori_port->info.clock_rate / 1000; + + if (argc > 4) + detail = atoi(argv[4]); + + while (1) { + pjmedia_frame f1, f2; + + f1.buf = buf1; + f1.size = BYTES_PER_FRAME; + f2.buf = buf2; + f2.size = BYTES_PER_FRAME; + + status = pjmedia_port_get_frame(file_ori_port, &f1); + if (status == PJ_EEOF) { + break; + } else if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Error occured while reading file", status); + break; + } + status = pjmedia_port_get_frame(file_deg_port, &f2); + if (status == PJ_EEOF) { + break; + } else if (status != PJ_SUCCESS) { + app_perror(THIS_FILE, "Error occured while reading file", status); + break; + } + + /* Calculate magnitudes */ + ref_mag += sum_mult_sig(f1.buf, f1.buf, BYTES_PER_FRAME >> 1); + deg_mag += sum_mult_sig(f2.buf, f2.buf, BYTES_PER_FRAME >> 1); + mix_mag += sum_mult_sig(f1.buf, f2.buf, BYTES_PER_FRAME >> 1); + + samples_compared += BYTES_PER_FRAME >> 1; + if (first_nsamples && samples_compared >= first_nsamples) + break; + } + + /* Degraded magnitude compared to reference magnitude + */ + res_deg = (int) (deg_mag / ref_mag * 100.0); + if (res_deg < 0) + res_deg = -1; + else if (res_deg >= 81) + res_deg = 9; + else + res_deg = pj_isqrt(res_deg); + + /* Mixed magnitude (don't know what this is actually :D) compared to + * reference magnitude + */ + res_mix = (int) (mix_mag / ref_mag * 100.0); + if (res_mix < 0) + res_mix = -1; + else if (res_mix >= 81) + res_mix = 9; + else + res_mix = pj_isqrt(res_mix); + + /* Overall score. + * If mixed score is -1, then overall score should be -1 as well. + * Apply no weighting (1:1) for now. + */ + if (res_mix == -1) + res_overall = -1; + else + res_overall = (res_mix*1 + res_deg*1) / 2; + + if (detail) { + printf("Reference = %.0f\n", ref_mag); + printf("Degraded = %.0f\n", deg_mag); + printf("Mixed = %.0f\n", mix_mag); + + printf("\n"); + + printf("Score 1 = %d\n", res_deg); + printf("Score 2 = %d\n", res_mix); + + printf("\n"); + } + + printf("Overall = %d\n", res_overall); + + /* Destroy file port */ + status = pjmedia_port_destroy( file_ori_port ); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + status = pjmedia_port_destroy( file_deg_port ); + PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); + + /* Release application pool */ + pj_pool_release( pool ); + + /* Destroy media endpoint. */ + pjmedia_endpt_destroy( med_endpt ); + + /* Destroy pool factory */ + pj_caching_pool_destroy( &cp ); + + /* Shutdown PJLIB */ + pj_shutdown(); + + + /* Done. */ + return 0; +} + diff --git a/tests/pjsua/wavs/.keep b/tests/pjsua/wavs/.keep new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3