diff --git a/README.rst b/README.rst index c2171b5..6af7457 100644 --- a/README.rst +++ b/README.rst @@ -107,7 +107,7 @@ See the docs_ for the deats! .. _inbound ESL: https://freeswitch.org/confluence/display/FREESWITCH/mod_event_socket#mod_event_socket-Configuration .. _park-only: https://freeswitch.org/confluence/display/FREESWITCH/mod_dptools%3A+park -.. _here: https://github.com/friends-of-freeswitch/switchio/blob/master/conf/switchiodp.xml +.. _here: https://github.com/friends-of-freeswitch/switchio/blob/park_timeout/conf/ci-minimal/dialplan/switchydp.xml What's included? diff --git a/conf/ci-minimal/dialplan/switchydp.xml b/conf/ci-minimal/dialplan/switchydp.xml index aa1e486..4525e27 100644 --- a/conf/ci-minimal/dialplan/switchydp.xml +++ b/conf/ci-minimal/dialplan/switchydp.xml @@ -1,9 +1,10 @@ - + + diff --git a/conf/switchiodp.xml b/conf/switchiodp.xml deleted file mode 100644 index aa1e486..0000000 --- a/conf/switchiodp.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/setup.py b/setup.py index 1a4ea7d..2541a1b 100755 --- a/setup.py +++ b/setup.py @@ -33,9 +33,6 @@ ] }, install_requires=['click', 'colorlog'], - package_data={ - 'switchio': ['../conf/switchiodp.xml'] - }, extras_require={ 'metrics': ['pandas>=0.18'], 'hdf5': ['tables==3.2.1.1'], diff --git a/switchio/__init__.py b/switchio/__init__.py index 9d6d033..03cc095 100644 --- a/switchio/__init__.py +++ b/switchio/__init__.py @@ -39,4 +39,7 @@ 'Service', ] -PARK_DP = path.join(path.dirname(__file__), '../conf', 'switchiodp.xml') +PARK_DP = path.join( + path.dirname(__file__), + '../conf/ci-minimal/dialplan', 'switchiodp.xml' +) diff --git a/tests/conftest.py b/tests/conftest.py index deeed2c..c0d95af 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -177,6 +177,21 @@ def el(fshost): assert not el.is_alive() +@pytest.fixture +def ael(el): + """An event listener (el) with active event loop + Unsubscribe the listener from verbose updates. + """ + assert not el.connected() + # avoid latency caused by update events + el.unsubscribe("CALL_UPDATE") + el.connect() + el.start() + assert el.connected() + yield el + el.disconnect() + + @pytest.yield_fixture def client(fshost): """Deliver a core.Client connected to fshost diff --git a/tests/test_core.py b/tests/test_core.py index cb94c55..3e1f1d3 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -12,21 +12,6 @@ import asyncio -@pytest.fixture -def ael(el): - """An event listener (el) with active event loop - Unsubscribe the listener from verbose updates. - """ - assert not el.connected() - # avoid latency caused by update events - el.unsubscribe("CALL_UPDATE") - el.connect() - el.start() - assert el.connected() - yield el - el.disconnect() - - def bridge2dest_callback(sess): if sess['Call-Direction'] == 'inbound': sess.bridge(dest_url=sess['variable_sip_req_uri']) diff --git a/tests/test_coroutines.py b/tests/test_coroutines.py index 966e4b6..92630f9 100644 --- a/tests/test_coroutines.py +++ b/tests/test_coroutines.py @@ -88,3 +88,51 @@ async def timeout_on_hangup(self, sess): assert task.done() with pytest.raises(asyncio.TimeoutError): task.result() + + +@pytest.mark.parametrize('sleep', [2, 5]) +def test_simplest_flow(fssock, scenario, client, ael, sleep): + """Verify that a coroutine can satisfy SIPp's simplest call flow. + + Additionally, verify that when calls are not answered and left in the park + state they time out and are rejected after 3 seconds (according to the CI + dialplan). + """ + class MyApp: + @coroutine( + "CHANNEL_PARK", + subscribe=('PLAYBACK_STOP', 'PLAYBACK_START') + ) + async def answer_play_hangup(self, sess): + await asyncio.sleep(sleep) + await sess.answer() + # non-blocking + sess.playback( + 'en/us/callie/ivr/8000/ivr-founder_of_freesource.wav') + await sess.recv("PLAYBACK_START") + await sess.recv("CHANNEL_HANGUP") + # XXX: seems the playback isn't stopping on its own? - the + # hangup does it though... + # sess.breakmedia() + await sess.recv("PLAYBACK_STOP") + await sess.recv("CHANNEL_HANGUP_COMPLETE") + + client.connect() + client.listener = ael + # assigning a listener overrides it's call lookup var so restore it + client.listener.call_tracking_header = 'variable_call_uuid' + assert 'default' == client.load_app(MyApp, on_value="default") + + uac = scenario.prepare()[1] + uac.proxyaddr = None + uac.destaddr = fssock + uac.pause_duration = 6000 + + # make the call + if sleep > 3: + # XML dialplan's `park_timeout` should reject the call + with pytest.raises(RuntimeError): + uac() + else: + # call should be hung up by this UAC + uac()