[asterisk-dev] [Code Review] 4438: add auto-dtmf mode for pjsip

Matt Jordan reviewboard at asterisk.org
Sun Mar 22 23:29:37 CDT 2015


-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviewboard.asterisk.org/r/4438/#review14764
-----------------------------------------------------------


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.

- Matt Jordan


On March 15, 2015, 2:48 a.m., yaron nahum wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://reviewboard.asterisk.org/r/4438/
> -----------------------------------------------------------
> 
> (Updated March 15, 2015, 2:48 a.m.)
> 
> 
> Review request for Asterisk Developers.
> 
> 
> Bugs: ASTERISK-24706
>     https://issues.asterisk.org/jira/browse/ASTERISK-24706
> 
> 
> Repository: Asterisk
> 
> 
> Description
> -------
> 
> add auto-dtmf mode for pjsip
> 
> 
> Diffs
> -----
> 
>   /trunk/res/res_pjsip_session.c 431537 
>   /trunk/res/res_pjsip_sdp_rtp.c 431537 
>   /trunk/res/res_pjsip/pjsip_configuration.c 431537 
>   /trunk/res/res_pjsip.c 431537 
>   /trunk/main/dsp.c 431537 
>   /trunk/include/asterisk/res_pjsip.h 431537 
>   /trunk/include/asterisk/dsp.h 431537 
>   /trunk/channels/chan_pjsip.c 431537 
> 
> Diff: https://reviewboard.asterisk.org/r/4438/diff/
> 
> 
> Testing
> -------
> 
> 
> Thanks,
> 
> yaron nahum
> 
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-dev/attachments/20150323/68017a6d/attachment-0001.html>


More information about the asterisk-dev mailing list