<html>
<body>
<div style="font-family: Verdana, Arial, Helvetica, Sans-Serif;">
<table bgcolor="#f9f3c9" width="100%" cellpadding="8" style="border: 1px #c9c399 solid;">
<tr>
<td>
This is an automatically generated e-mail. To reply, visit:
<a href="https://reviewboard.asterisk.org/r/4438/">https://reviewboard.asterisk.org/r/4438/</a>
</td>
</tr>
</table>
<br />
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">On testing:
To start, you will probably want to read up on the Asterisk Test Suite on the Asterisk wiki. In particular, the following pages have good information on getting started:
* Installation: https://wiki.asterisk.org/wiki/display/AST/Installing+the+Asterisk+Test+Suite
Some of the options listed on that page are not strictly necessary - PJSUA and its Python bindings can be particularly tricky, and ASTTest is only needed for lua tests (which are very few). The most important bits to get install are Python twisted and StarPY.
* Running: https://wiki.asterisk.org/wiki/display/AST/Running+the+Asterisk+Test+Suite
Since the Asterisk Test Suite can take a _very_ long time to run (4+ hours on the build agents), you typically want to only run a subset of the tests, using either the '-t' option or '-g' option.
Test development has evolved quite a lot over time. runtests.py walks through the 'tests.yaml' and 'test-config.yaml' files it finds in its subdirectories, building tests that it can execute. When it finds a test, it looks for one of two things:
(1) A runtest file. If it finds this, it executes it in a separate process. That runtest file can be anything - a shell script, python script, etc.
(2) If it doesn't find a runtest file, it looks to the 'test-config.yaml' file to tell it which Python modules should be loaded and executed.
The wiki documents both approaches:
(1) How to write a Python test - https://wiki.asterisk.org/wiki/display/AST/Writing+a+Python+Test
This follows the first approach. Most older tests were written in this fashion. Some new tests are still written in this way, particularly when what they test is sufficiently complex or different from other tests in the Testsuite.
(2) Using the pluggable framework - https://wiki.asterisk.org/wiki/display/AST/Pluggable+Component+Framework
This is the preferred way to write a test, as it makes use of common components in the Testsuite to "build" a test.
Your patch is a bit interesting, as we want to test really two different things:
(1) If a PJSIP endpoint with 'auto' receives an inbound inband DTMF, we switch to inband and successfully receive the digit
(2) If a PJSIP endpoint with 'auto' receives an inbound RTP DTMF, we switch to RTP and successfully receive the digit
Given that, I'd write the test as follows:
(1) Define a new test in tests/channels/pjsip/dtmf_auto
- Add a test-config.yaml
- Update the tests/channels/pjsip/tests.yaml to reference the new test location
- Create a configs/ast1/ folder
- Add an extensions.conf. The goal should be to have Asterisk place a PJSIP call to itself, using two different configurations of endpoints - one set for inband DTMF, another set for RFC 4733 DTMF. A PJSIP endpoint configured with 'auto' DTMF will receive the two calls, and Read() the digits in. The dialplan could look something like this:
[default]
exten => senddtmf,1,NoOp()
same => n,SendDTMF(1)
same => n,Hangup()
exten => _[dtmf].,1,NoOp()
same => n,Dial(PJSIP/receiver)
same => n,Hangup()
exten => receiver,1,NoOp()
same => n,Read(var)
same => n,Hangup()
- Add a pjsip.conf. You'll want three endpoints, all configured with contacts that match the local Asterisk instances. rmudgett just had a review that used a similar technique here - https://reviewboard.asterisk.org/r/4518 - the idea is that we have three PJSIP endpoints that happen to have the same contact as Asterisk's transport, but we use the from_user to determine who is who in the various requests.
[dtmf_inband]
type=endpoint
dtmf_mode=inband
[dtmf_rfc]
type=endpoint
dtmf_mode=rfc4733
[receiver]
type=endpoint
dtmf_mode=auto
(2) In your test-config.yaml, you'll need to pick a test object. A test object does a lot of stuff:
- It starts some number of Asterisk instances, connects AMI to them, and generally orchestrates the test
- It provides 'extension points' that other Python modules can connect to. These other modules can verify CDR records, check for AMI events, start new calls, etc.
In your case, since we'll need to make two calls (using Local channels) and then check some AMI events to make sure the DTMF was read, we can use the SimpleTestCase test object. There's a lot of tests that use this test object - being rather 'simple', it is good when you only have a single instance of Asterisk you want to manipulate, and you just need to make some Local channels that 'do stuff' in Asterisk. Your configuration would look something like this:
test-modules:
test-object:
config-section: test-object-config
typename: 'test_case.SimpleTestCase'
test-object-config:
spawn-after-hangup: True # Spawn the next 'iteration' when the previous hangs up
test-iterations:
-
channel: 'PJSIP/dtmf_inband'
context: 'default'
exten: 'senddtmf'
priority: '1'
-
channel: 'PJSIP/dtmf_rfc'
context: 'default'
exten: 'senddtmf'
priority: '1'
(3) At this point, it'd be a good idea to run the test and see what happens. The Testsuite will make logs in the logs directory, which will tell you what is happening in the test as it executes (I usually 'tail' it to watch the progress). You can bump up the debug of the Python logger in the logger.conf in the root directory. If the test fails (which is likely, since we haven't given it much to determine why it should succeed), you'll get the full test logs (including Asterisk logs) copied to that same directory.
(4) Once you have the channels actually running and dialling, you should listen for AMI events to make sure that the PJSIP/receiver channel is actually reading the DTMF '1' received from the inband/RFC mechanisms. You can do this by defining an AMI event listener pluggable module:
test-modules:
test-object:
config-section: test-object-config
typename: 'test_case.SimpleTestCase'
modules:
-
config-section: ami-config
typename: 'ami.AMIEventModule'
ami-config:
-
type: 'headermatch'
conditions:
match:
Event: 'DTMFEnd'
Channel: 'PJSIP/receiver-.*'
requirements:
match:
Digit: '1'
count: '2'
This will look for two DTMFEnd events on the PJSIP/receiver channels and - if gets both - will pass the test.
All of this is a bit much to take in initially, but once you get going, writing tests is actually quite easy. Luckily, there are a lot of examples of tests that do similar things - take a look in the Testsuite for tests that use the SimpleTestCase object and the AMIEventModule for examples. There is also sample documentation on the YAML structure for both in the sample-yaml subdirectory.
If you have any questions, please don't hesitate to contact folks on the asterisk-dev mailing list or in #asterisk-dev.</pre>
<br />
<p>- Matt Jordan</p>
<br />
<p>On March 15th, 2015, 2:48 a.m. CDT, yaron nahum wrote:</p>
<table bgcolor="#fefadf" width="100%" cellspacing="0" cellpadding="8" style="background-image: url('https://reviewboard.asterisk.org/static/rb/images/review_request_box_top_bg.ab6f3b1072c9.png'); background-position: left top; background-repeat: repeat-x; border: 1px black solid;">
<tr>
<td>
<div>Review request for Asterisk Developers.</div>
<div>By yaron nahum.</div>
<p style="color: grey;"><i>Updated March 15, 2015, 2:48 a.m.</i></p>
<div style="margin-top: 1.5em;">
<b style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Bugs: </b>
<a href="https://issues.asterisk.org/jira/browse/ASTERISK-24706">ASTERISK-24706</a>
</div>
<div style="margin-top: 1.5em;">
<b style="color: #575012; font-size: 10pt;">Repository: </b>
Asterisk
</div>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Description </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
<tr>
<td>
<pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">add auto-dtmf mode for pjsip</pre>
</td>
</tr>
</table>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Diffs</b> </h1>
<ul style="margin-left: 3em; padding-left: 0;">
<li>/trunk/res/res_pjsip_session.c <span style="color: grey">(431537)</span></li>
<li>/trunk/res/res_pjsip_sdp_rtp.c <span style="color: grey">(431537)</span></li>
<li>/trunk/res/res_pjsip/pjsip_configuration.c <span style="color: grey">(431537)</span></li>
<li>/trunk/res/res_pjsip.c <span style="color: grey">(431537)</span></li>
<li>/trunk/main/dsp.c <span style="color: grey">(431537)</span></li>
<li>/trunk/include/asterisk/res_pjsip.h <span style="color: grey">(431537)</span></li>
<li>/trunk/include/asterisk/dsp.h <span style="color: grey">(431537)</span></li>
<li>/trunk/channels/chan_pjsip.c <span style="color: grey">(431537)</span></li>
</ul>
<p><a href="https://reviewboard.asterisk.org/r/4438/diff/" style="margin-left: 3em;">View Diff</a></p>
</td>
</tr>
</table>
</div>
</body>
</html>