Advertisement
Guest User

rls tests lists/nominal/presence/

a guest
Jul 29th, 2014
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 75.10 KB | None | 0 0
  1. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/tests.yaml
  2. ===================================================================
  3. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/tests.yaml (revision 0)
  4. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/tests.yaml (revision 0)
  5. @@ -0,0 +1,3 @@
  6. +tests:
  7. + - dir: 'presence'
  8. + - dir: 'mwi'
  9.  
  10. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/tests.yaml
  11. ___________________________________________________________________
  12. Added: svn:keywords
  13. + Author Date Id Revision
  14. Added: svn:eol-style
  15. + native
  16. Added: svn:mime-type
  17. + text/plain
  18.  
  19. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/notify.py
  20. ===================================================================
  21. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/notify.py (revision 0)
  22. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/notify.py (revision 0)
  23. @@ -0,0 +1,60 @@
  24. +#/usr/bin/env python
  25. +
  26. +import sys
  27. +import logging
  28. +
  29. +sys.path.append('lib/python')
  30. +sys.path.append('tests/channels/pjsip/subscriptions/rls')
  31. +
  32. +from pcap import VOIPListener
  33. +from rls_integrity import RLSValidator
  34. +
  35. +LOGGER = logging.getLogger(__name__)
  36. +
  37. +LIST_NAME = 'pres_list'
  38. +RESOURCES = {
  39. + 'alice': {
  40. + 'type': 'PIDF',
  41. + 'state': 'active'
  42. + },
  43. + 'bob': {
  44. + 'type': 'PIDF',
  45. + 'state': 'active'
  46. + }
  47. + }
  48. +
  49. +
  50. +class IntegrityCheck(VOIPListener):
  51. + def __init__(self, module_config, test_object):
  52. + """Create listener and add AMI observer/callbacks."""
  53. + VOIPListener.__init__(self, module_config, test_object)
  54. + self.add_callback('SIP', self.multipart_handler)
  55. + self.test_object = test_object
  56. + self.token = test_object.create_fail_token("Haven't handled all "
  57. + "expected NOTIFY packets.")
  58. +
  59. + def multipart_handler(self, packet):
  60. + """Checks multipart packets to see if NOTIFY messages have
  61. + anticipated data.
  62. + """
  63. + if 'NOTIFY' not in packet.request_line:
  64. + return
  65. +
  66. + if packet.body.packet_type != 'Multipart':
  67. + return
  68. +
  69. + validator = RLSValidator(test_object=self.test_object,
  70. + packet=packet,
  71. + version=0,
  72. + full_state=True,
  73. + list_name=LIST_NAME,
  74. + resources=RESOURCES)
  75. + validator.check_integrity()
  76. +
  77. + # If we actually make it to here, the test passes. Yay!
  78. + self.test_object.set_passed(True)
  79. + self.test_object.remove_fail_token(self.token)
  80. +
  81. + self.remove_callbacks('SIP')
  82. +
  83. + self.test_object.stop_reactor()
  84.  
  85. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/notify.py
  86. ___________________________________________________________________
  87. Added: svn:eol-style
  88. + native
  89. Added: svn:executable
  90. + *
  91. Added: svn:mime-type
  92. + text/plain
  93. Added: svn:keywords
  94. + Author Date Id Revision
  95.  
  96. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/test-config.yaml
  97. ===================================================================
  98. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/test-config.yaml (revision 0)
  99. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/test-config.yaml (revision 0)
  100. @@ -0,0 +1,58 @@
  101. +testinfo:
  102. + summary: 'Baseline test to ensure subscription establishment and RLMI document correctness.'
  103. + description: |
  104. + 'This test uses SIPp to establish a subscription to a resource list.
  105. + The resource list is a presence list that contains two elements,
  106. + alice@default and bob@default. Once the subscription is established, a
  107. + PCAP listner is used to ensure that the NOTIFY body sent by Asterisk is
  108. + what is expected. It checks the following:
  109. + * That the multipart body contains three parts
  110. + * That the multipart body consists of one RLMI document and two
  111. + PIDF documents
  112. + * That the RLMI document has the proper integrity
  113. + * There is only a single list element
  114. + * The version number is 0
  115. + * There are two resource elements
  116. + * The two resource elements have an instance element with a
  117. + cid attribute corresponding to the Content-ID of the two
  118. + multipart body parts
  119. + * Each resource element has the expected name element present
  120. + * The PIDF documents have proper integrity
  121. + * The reported states are correct for each part
  122. + * The Content-ID header matches the corresponding cid attribute
  123. + from the instance element in the RLMI document.'
  124. +
  125. +properties:
  126. + minversion: '13.0.0'
  127. + dependencies:
  128. + - python: 'twisted'
  129. + - python: 'starpy'
  130. + - python: 'yappcap'
  131. + - python: 'pyxb'
  132. + - asterisk: 'res_pjsip'
  133. + - asterisk: 'res_pjsip_pubsub'
  134. + tags:
  135. + - rls
  136. + - pjsip
  137. +
  138. +test-modules:
  139. + add-test-to-search-path: 'True'
  140. + test-object:
  141. + config-section: 'test-case-config'
  142. + typename: 'sipp.SIPpTestCase'
  143. + modules:
  144. + -
  145. + config-section: 'pcap-config'
  146. + typename: 'notify.IntegrityCheck'
  147. +
  148. +test-case-config:
  149. + test-iterations:
  150. + -
  151. + scenarios:
  152. + - { 'key-args': {'scenario': 'list_subscribe.xml', '-i': '127.0.0.1', '-p': '5061', '-s': 'pres_list'} }
  153. +
  154. +pcap-config:
  155. + bpf-filter: 'udp port 5061'
  156. + register-observer: True
  157. + debug-packets: True
  158. + device: 'lo'
  159.  
  160. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/test-config.yaml
  161. ___________________________________________________________________
  162. Added: svn:mime-type
  163. + text/plain
  164. Added: svn:keywords
  165. + Author Date Id Revision
  166. Added: svn:eol-style
  167. + native
  168.  
  169. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/pjsip.conf
  170. ===================================================================
  171. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/pjsip.conf (revision 0)
  172. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/pjsip.conf (revision 0)
  173. @@ -0,0 +1,21 @@
  174. +[pres_list]
  175. +type = resource_list
  176. +event = presence
  177. +list_item = alice
  178. +list_item = bob
  179. +
  180. +[sipp]
  181. +type=aor
  182. +max_contacts=1
  183. +contact=sip:sipp@127.0.0.1:5061
  184. +
  185. +[sipp]
  186. +type = endpoint
  187. +context = default
  188. +aors=sipp
  189. +transport=local
  190. +
  191. +[local]
  192. +type=transport
  193. +protocol=udp
  194. +bind=0.0.0.0:5060
  195.  
  196. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/pjsip.conf
  197. ___________________________________________________________________
  198. Added: svn:keywords
  199. + Author Date Id Revision
  200. Added: svn:eol-style
  201. + native
  202. Added: svn:mime-type
  203. + text/plain
  204.  
  205. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/extensions.conf
  206. ===================================================================
  207. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/extensions.conf (revision 0)
  208. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/extensions.conf (revision 0)
  209. @@ -0,0 +1,3 @@
  210. +[default]
  211. +exten => alice,hint,Custom:alice
  212. +exten => bob,hint,Custom:bob
  213.  
  214. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/initial_notify/configs/ast1/extensions.conf
  215. ___________________________________________________________________
  216. Added: svn:mime-type
  217. + text/plain
  218. Added: svn:keywords
  219. + Author Date Id Revision
  220. Added: svn:eol-style
  221. + native
  222.  
  223. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/test-config.yaml
  224. ===================================================================
  225. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/test-config.yaml (revision 0)
  226. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/test-config.yaml (revision 0)
  227. @@ -0,0 +1,45 @@
  228. +testinfo:
  229. + summary: 'Test to ensure that the full_state=yes option is honored in pjsip.conf'
  230. + description: |
  231. + 'This test uses SIPp to establish a subscription to a resource list.
  232. + The resource list is a presence list that contains two elements,
  233. + alice@default and bob@default. Once established, the test sends a state
  234. + change for the alice@default resource. A PCAP listener is used to
  235. + ensure that the NOTIFY bodies sent by Asterisk are valid. Each of the
  236. + two bodies should convey full resource state of the list. The version
  237. + number of the list should increment for each NOTIFY body.'
  238. +
  239. +properties:
  240. + minversion: '13.0.0'
  241. + dependencies:
  242. + - python: 'twisted'
  243. + - python: 'starpy'
  244. + - python: 'yappcap'
  245. + - python: 'pyxb'
  246. + - asterisk: 'res_pjsip'
  247. + - asterisk: 'res_pjsip_pubsub'
  248. + tags:
  249. + - rls
  250. + - pjsip
  251. +
  252. +test-modules:
  253. + add-test-to-search-path: 'True'
  254. + test-object:
  255. + config-section: 'test-case-config'
  256. + typename: 'sipp.SIPpTestCase'
  257. + modules:
  258. + -
  259. + config-section: 'pcap-config'
  260. + typename: 'full_state.IntegrityCheck'
  261. +
  262. +test-case-config:
  263. + test-iterations:
  264. + -
  265. + scenarios:
  266. + - { 'key-args': {'scenario': 'list_subscribe.xml', '-i': '127.0.0.1', '-p': '5061', '-s': 'pres_list'} }
  267. +
  268. +pcap-config:
  269. + bpf-filter: 'udp port 5061'
  270. + register-observer: True
  271. + debug-packets: True
  272. + device: 'lo'
  273.  
  274. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/test-config.yaml
  275. ___________________________________________________________________
  276. Added: svn:eol-style
  277. + native
  278. Added: svn:mime-type
  279. + text/plain
  280. Added: svn:keywords
  281. + Author Date Id Revision
  282.  
  283. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/extensions.conf
  284. ===================================================================
  285. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/extensions.conf (revision 0)
  286. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/extensions.conf (revision 0)
  287. @@ -0,0 +1,3 @@
  288. +[default]
  289. +exten => alice,hint,Custom:alice
  290. +exten => bob,hint,Custom:bob
  291.  
  292. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/extensions.conf
  293. ___________________________________________________________________
  294. Added: svn:eol-style
  295. + native
  296. Added: svn:mime-type
  297. + text/plain
  298. Added: svn:keywords
  299. + Author Date Id Revision
  300.  
  301. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/pjsip.conf
  302. ===================================================================
  303. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/pjsip.conf (revision 0)
  304. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/pjsip.conf (revision 0)
  305. @@ -0,0 +1,22 @@
  306. +[pres_list]
  307. +type = resource_list
  308. +event = presence
  309. +list_item = alice
  310. +list_item = bob
  311. +full_state = yes
  312. +
  313. +[sipp]
  314. +type=aor
  315. +max_contacts=1
  316. +contact=sip:sipp@127.0.0.1:5061
  317. +
  318. +[sipp]
  319. +type = endpoint
  320. +context = default
  321. +aors=sipp
  322. +transport=local
  323. +
  324. +[local]
  325. +type=transport
  326. +protocol=udp
  327. +bind=0.0.0.0:5060
  328.  
  329. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/configs/ast1/pjsip.conf
  330. ___________________________________________________________________
  331. Added: svn:mime-type
  332. + text/plain
  333. Added: svn:keywords
  334. + Author Date Id Revision
  335. Added: svn:eol-style
  336. + native
  337.  
  338. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/full_state.py
  339. ===================================================================
  340. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/full_state.py (revision 0)
  341. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/full_state.py (revision 0)
  342. @@ -0,0 +1,84 @@
  343. +#/usr/bin/env python
  344. +
  345. +import sys
  346. +import logging
  347. +
  348. +sys.path.append('lib/python')
  349. +sys.path.append('tests/channels/pjsip/subscriptions/rls')
  350. +
  351. +from pcap import VOIPListener
  352. +from rls_integrity import RLSValidator
  353. +
  354. +LOGGER = logging.getLogger(__name__)
  355. +
  356. +LIST_NAME = 'pres_list'
  357. +RESOURCES = {
  358. + 'alice': {
  359. + 'type': 'PIDF',
  360. + 'state': 'active'
  361. + },
  362. + 'bob': {
  363. + 'type': 'PIDF',
  364. + 'state': 'active'
  365. + }
  366. +}
  367. +
  368. +
  369. +class IntegrityCheck(VOIPListener):
  370. + def __init__(self, module_config, test_object):
  371. + """Create listener and add AMI observer/callbacks."""
  372. + VOIPListener.__init__(self, module_config, test_object)
  373. + self.test_object = test_object
  374. + self.token = test_object.create_fail_token("Haven't handled all "
  375. + "expected NOTIFY packets.")
  376. + self.version = 0
  377. + self.ami = None
  378. + self.test_object.register_ami_observer(self.ami_connect)
  379. + self.test_object.register_scenario_started_observer(
  380. + self.scenario_started)
  381. + self.add_callback('SIP', self.multipart_handler)
  382. +
  383. + def multipart_handler(self, packet):
  384. + """Checks multipart packets to see if NOTIFY messages have
  385. + anticipated data.
  386. + """
  387. + if 'NOTIFY' not in packet.request_line:
  388. + return
  389. +
  390. + if packet.body.packet_type != 'Multipart':
  391. + return
  392. +
  393. + if self.version > 1:
  394. + return
  395. +
  396. + validator = RLSValidator(test_object=self.test_object,
  397. + packet=packet,
  398. + version=self.version,
  399. + full_state=True,
  400. + list_name=LIST_NAME,
  401. + resources=RESOURCES)
  402. + validator.check_integrity()
  403. + self.version += 1
  404. +
  405. + if self.version > 1:
  406. + # We expect two NOTIFYs only. If we get them, things passed!
  407. + self.test_object.set_passed(True)
  408. + self.test_object.remove_fail_token(self.token)
  409. + self.test_object.stop_reactor()
  410. +
  411. + def ami_connect(self, ami):
  412. + """Callback when AMI connects. Sets test AMI instance."""
  413. + self.ami = ami
  414. +
  415. + def scenario_started(self, scenario):
  416. + """Callback when SIPp scenario has started.
  417. +
  418. + Once the scenario has started, we change the device state
  419. + of Alice. The result should be that Asterisk sends a NOTIFY.
  420. + """
  421. + message = {
  422. + 'Action': 'SetVar',
  423. + 'Variable': 'DEVICE_STATE(Custom:alice)',
  424. + 'Value': 'INUSE'
  425. + }
  426. + self.ami.sendMessage(message)
  427.  
  428. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/full_state.py
  429. ___________________________________________________________________
  430. Added: svn:eol-style
  431. + native
  432. Added: svn:executable
  433. + *
  434. Added: svn:mime-type
  435. + text/plain
  436. Added: svn:keywords
  437. + Author Date Id Revision
  438.  
  439. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/sipp/list_subscribe.xml
  440. ===================================================================
  441. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/sipp/list_subscribe.xml (revision 0)
  442. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/sipp/list_subscribe.xml (revision 0)
  443. @@ -0,0 +1,84 @@
  444. +<?xml version="1.0" encoding="ISO-8859-1" ?>
  445. +<!DOCTYPE scenario SYSTEM "sipp.dtd">
  446. +
  447. +<scenario name="Basic Sipstone UAC">
  448. + <send retrans="500">
  449. + <![CDATA[
  450. +
  451. + SUBSCRIBE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
  452. + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
  453. + From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
  454. + To: sut <sip:[service]@[remote_ip]:[remote_port]>
  455. + Call-ID: [call_id]
  456. + CSeq: 1 SUBSCRIBE
  457. + Contact: sip:sipp@[local_ip]:[local_port]
  458. + Max-Forwards: 70
  459. + Subject: Performance Test
  460. + Event: presence
  461. + Supported: eventlist
  462. + Accept: application/rlmi+xml
  463. + Accept: application/pidf+xml
  464. + Accept: multipart/related
  465. + Expires: 3600
  466. + Content-Length: 0
  467. +
  468. + ]]>
  469. + </send>
  470. +
  471. + <recv response="100"
  472. + optional="true">
  473. + </recv>
  474. +
  475. + <recv response="200" rtd="true">
  476. + <action>
  477. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  478. + </action>
  479. + </recv>
  480. +
  481. + <recv request="NOTIFY" crlf="true">
  482. + <action>
  483. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  484. + </action>
  485. + </recv>
  486. +
  487. + <Reference variables="1" />
  488. +
  489. + <send>
  490. + <![CDATA[
  491. +
  492. + SIP/2.0 200 OK
  493. + [last_Via:]
  494. + [last_From:]
  495. + [last_To:]
  496. + [last_Call-ID:]
  497. + [last_CSeq:]
  498. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  499. + Content-Length: 0
  500. +
  501. + ]]>
  502. + </send>
  503. +
  504. + <recv request="NOTIFY" crlf="true">
  505. + <action>
  506. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  507. + </action>
  508. + </recv>
  509. +
  510. + <Reference variables="1" />
  511. +
  512. + <send>
  513. + <![CDATA[
  514. +
  515. + SIP/2.0 200 OK
  516. + [last_Via:]
  517. + [last_From:]
  518. + [last_To:]
  519. + [last_Call-ID:]
  520. + [last_CSeq:]
  521. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  522. + Content-Length: 0
  523. +
  524. + ]]>
  525. + </send>
  526. +
  527. +</scenario>
  528.  
  529. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/full_state/sipp/list_subscribe.xml
  530. ___________________________________________________________________
  531. Added: svn:mime-type
  532. + text/plain
  533. Added: svn:keywords
  534. + Author Date Id Revision
  535. Added: svn:eol-style
  536. + native
  537.  
  538. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/sipp/list_subscribe.xml
  539. ===================================================================
  540. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/sipp/list_subscribe.xml (revision 0)
  541. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/sipp/list_subscribe.xml (revision 0)
  542. @@ -0,0 +1,38 @@
  543. +<?xml version="1.0" encoding="ISO-8859-1" ?>
  544. +<!DOCTYPE scenario SYSTEM "sipp.dtd">
  545. +
  546. +<scenario name="Basic Sipstone UAC">
  547. + <send retrans="500">
  548. + <![CDATA[
  549. +
  550. + SUBSCRIBE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
  551. + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
  552. + From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
  553. + To: sut <sip:[service]@[remote_ip]:[remote_port]>
  554. + Call-ID: [call_id]
  555. + CSeq: 1 SUBSCRIBE
  556. + Contact: sip:sipp@[local_ip]:[local_port]
  557. + Max-Forwards: 70
  558. + Subject: Performance Test
  559. + Event: presence
  560. + Supported: eventlist
  561. + Accept: application/rlmi+xml
  562. + Accept: application/pidf+xml
  563. + Accept: multipart/related
  564. + Content-Length: 0
  565. +
  566. + ]]>
  567. + </send>
  568. +
  569. + <recv response="100"
  570. + optional="true">
  571. + </recv>
  572. +
  573. + <recv response="200" rtd="true">
  574. + <action>
  575. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  576. + </action>
  577. + </recv>
  578. +
  579. + <Reference variables="1" />
  580. +</scenario>
  581.  
  582. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/sipp/list_subscribe.xml
  583. ___________________________________________________________________
  584. Added: svn:mime-type
  585. + text/plain
  586. Added: svn:keywords
  587. + Author Date Id Revision
  588. Added: svn:eol-style
  589. + native
  590.  
  591. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/test-config.yaml
  592. ===================================================================
  593. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/test-config.yaml (revision 0)
  594. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/test-config.yaml (revision 0)
  595. @@ -0,0 +1,31 @@
  596. +testinfo:
  597. + summary: 'This test ensures that a list subscription can be established.'
  598. + description: |
  599. + 'This test uses a SIPp scenario to subscribe to a presence list. The
  600. + SIPp script ensures that Asterisk returns a 200 OK and that a
  601. + "Require: eventlist" header is present.'
  602. +
  603. +properties:
  604. + minversion: '13.0.0'
  605. + dependencies:
  606. + - python: 'twisted'
  607. + - python: 'starpy'
  608. + - asterisk: 'res_pjsip'
  609. + - asterisk: 'res_pjsip_pubsub'
  610. + - sipp:
  611. + version: 'v3.0'
  612. + tags:
  613. + - rls
  614. + - pjsip
  615. +
  616. +test-modules:
  617. + add-test-to-search-path: 'True'
  618. + test-object:
  619. + config-section: 'test-case-config'
  620. + typename: 'sipp.SIPpTestCase'
  621. +
  622. +test-case-config:
  623. + test-iterations:
  624. + -
  625. + scenarios:
  626. + - { 'key-args': {'scenario': 'list_subscribe.xml', '-i': '127.0.0.1', '-p': '5061', '-s': 'pres_list'} }
  627.  
  628. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/test-config.yaml
  629. ___________________________________________________________________
  630. Added: svn:eol-style
  631. + native
  632. Added: svn:mime-type
  633. + text/plain
  634. Added: svn:keywords
  635. + Author Date Id Revision
  636.  
  637. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/extensions.conf
  638. ===================================================================
  639. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/extensions.conf (revision 0)
  640. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/extensions.conf (revision 0)
  641. @@ -0,0 +1,3 @@
  642. +[default]
  643. +exten => alice,hint,Custom:alice
  644. +exten => bob,hint,Custom:bob
  645.  
  646. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/extensions.conf
  647. ___________________________________________________________________
  648. Added: svn:mime-type
  649. + text/plain
  650. Added: svn:keywords
  651. + Author Date Id Revision
  652. Added: svn:eol-style
  653. + native
  654.  
  655. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/pjsip.conf
  656. ===================================================================
  657. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/pjsip.conf (revision 0)
  658. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/pjsip.conf (revision 0)
  659. @@ -0,0 +1,21 @@
  660. +[pres_list]
  661. +type = resource_list
  662. +event = presence
  663. +list_item = alice
  664. +list_item = bob
  665. +
  666. +[sipp]
  667. +type=aor
  668. +max_contacts=1
  669. +contact=sip:sipp@127.0.0.1:5061
  670. +
  671. +[sipp]
  672. +type = endpoint
  673. +context = default
  674. +aors=sipp
  675. +transport=local
  676. +
  677. +[local]
  678. +type=transport
  679. +protocol=udp
  680. +bind=0.0.0.0:5060
  681.  
  682. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/subscription_establishment/configs/ast1/pjsip.conf
  683. ___________________________________________________________________
  684. Added: svn:eol-style
  685. + native
  686. Added: svn:mime-type
  687. + text/plain
  688. Added: svn:keywords
  689. + Author Date Id Revision
  690.  
  691. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/extensions.conf
  692. ===================================================================
  693. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/extensions.conf (revision 0)
  694. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/extensions.conf (revision 0)
  695. @@ -0,0 +1,4 @@
  696. +[default]
  697. +exten => alice,hint,Custom:alice
  698. +exten => bob,hint,Custom:bob
  699. +
  700.  
  701. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/extensions.conf
  702. ___________________________________________________________________
  703. Added: svn:mime-type
  704. + text/plain
  705. Added: svn:keywords
  706. + Author Date Id Revision
  707. Added: svn:eol-style
  708. + native
  709.  
  710. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/pjsip.conf
  711. ===================================================================
  712. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/pjsip.conf (revision 0)
  713. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/pjsip.conf (revision 0)
  714. @@ -0,0 +1,22 @@
  715. +[pres_list]
  716. +type = resource_list
  717. +event = presence
  718. +list_item = alice
  719. +list_item = bob
  720. +full_state = yes
  721. +
  722. +[sipp]
  723. +type=aor
  724. +max_contacts=1
  725. +contact=sip:sipp@127.0.0.1:5061
  726. +
  727. +[sipp]
  728. +type = endpoint
  729. +context = default
  730. +aors=sipp
  731. +transport=local
  732. +
  733. +[local]
  734. +type=transport
  735. +protocol=udp
  736. +bind=0.0.0.0:5060
  737.  
  738. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/configs/ast1/pjsip.conf
  739. ___________________________________________________________________
  740. Added: svn:mime-type
  741. + text/plain
  742. Added: svn:keywords
  743. + Author Date Id Revision
  744. Added: svn:eol-style
  745. + native
  746.  
  747. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/sipp/resubscribe.xml
  748. ===================================================================
  749. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/sipp/resubscribe.xml (revision 0)
  750. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/sipp/resubscribe.xml (revision 0)
  751. @@ -0,0 +1,112 @@
  752. +<?xml version="1.0" encoding="ISO-8859-1" ?>
  753. +<!DOCTYPE scenario SYSTEM "sipp.dtd">
  754. +
  755. +<scenario name="Basic Sipstone UAC">
  756. + <send retrans="500">
  757. + <![CDATA[
  758. +
  759. + SUBSCRIBE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
  760. + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
  761. + From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
  762. + To: sut <sip:[service]@[remote_ip]:[remote_port]>
  763. + Call-ID: [call_id]
  764. + CSeq: 1 SUBSCRIBE
  765. + Contact: sip:sipp@[local_ip]:[local_port]
  766. + Max-Forwards: 70
  767. + Subject: Performance Test
  768. + Event: presence
  769. + Supported: eventlist
  770. + Accept: application/rlmi+xml
  771. + Accept: application/pidf+xml
  772. + Accept: multipart/related
  773. + Expires: 3600
  774. + Content-Length: 0
  775. +
  776. + ]]>
  777. + </send>
  778. +
  779. + <recv response="100"
  780. + optional="true">
  781. + </recv>
  782. +
  783. + <recv response="200" rtd="true">
  784. + <action>
  785. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  786. + </action>
  787. + </recv>
  788. +
  789. + <!-- Initial NOTIFY upon subscribing -->
  790. + <recv request="NOTIFY" crlf="true">
  791. + <action>
  792. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  793. + </action>
  794. + </recv>
  795. +
  796. + <send>
  797. + <![CDATA[
  798. +
  799. + SIP/2.0 200 OK
  800. + [last_Via:]
  801. + [last_From:]
  802. + [last_To:]
  803. + [last_Call-ID:]
  804. + [last_CSeq:]
  805. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  806. + Content-Length: 0
  807. +
  808. + ]]>
  809. + </send>
  810. +
  811. + <send retrans="500">
  812. + <![CDATA[
  813. +
  814. + SUBSCRIBE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
  815. + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
  816. + From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
  817. + To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
  818. + Call-ID: [call_id]
  819. + CSeq: [cseq] SUBSCRIBE
  820. + Contact: sip:sipp@[local_ip]:[local_port]
  821. + Max-Forwards: 70
  822. + Subject: Performance Test
  823. + Event: presence
  824. + Supported: eventlist
  825. + Accept: application/rlmi+xml
  826. + Accept: application/pidf+xml
  827. + Accept: multipart/related
  828. + Expires: 3600
  829. + Content-Length: 0
  830. +
  831. + ]]>
  832. + </send>
  833. +
  834. + <!-- NOTIFY upon resubscription -->
  835. + <recv request="NOTIFY" crlf="true">
  836. + <action>
  837. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  838. + </action>
  839. + </recv>
  840. +
  841. + <recv response="200" crlf="true">
  842. + <action>
  843. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  844. + </action>
  845. + </recv>
  846. +
  847. + <Reference variables="1" />
  848. +
  849. + <send>
  850. + <![CDATA[
  851. +
  852. + SIP/2.0 200 OK
  853. + [last_Via:]
  854. + [last_From:]
  855. + [last_To:]
  856. + [last_Call-ID:]
  857. + [last_CSeq:]
  858. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  859. + Content-Length: 0
  860. +
  861. + ]]>
  862. + </send>
  863. +
  864.  
  865. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/sipp/resubscribe.xml
  866. ___________________________________________________________________
  867. Added: svn:mime-type
  868. + text/plain
  869. Added: svn:keywords
  870. + Author Date Id Revision
  871. Added: svn:eol-style
  872. + native
  873.  
  874. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/resubscribe.py
  875. ===================================================================
  876. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/resubscribe.py (revision 0)
  877. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/resubscribe.py (revision 0)
  878. @@ -0,0 +1,65 @@
  879. +#/usr/bin/env python
  880. +
  881. +import sys
  882. +import logging
  883. +
  884. +sys.path.append('lib/python')
  885. +sys.path.append('tests/channels/pjsip/subscriptions/rls')
  886. +
  887. +from pcap import VOIPListener
  888. +from rls_integrity import RLSValidator
  889. +
  890. +LOGGER = logging.getLogger(__name__)
  891. +
  892. +LIST_NAME = 'pres_list'
  893. +RESOURCES = {
  894. + 'alice': {
  895. + 'type': 'PIDF',
  896. + 'state': 'active'
  897. + },
  898. + 'bob': {
  899. + 'type': 'PIDF',
  900. + 'state': 'active'
  901. + }
  902. +}
  903. +
  904. +
  905. +class IntegrityCheck(VOIPListener):
  906. + def __init__(self, module_config, test_object):
  907. + """Create listener and add AMI observer/callbacks."""
  908. + VOIPListener.__init__(self, module_config, test_object)
  909. + self.test_object = test_object
  910. + self.token = test_object.create_fail_token("Haven't handled all "
  911. + "expected NOTIFY packets.")
  912. + self.version = 0
  913. + self.ami = None
  914. + self.add_callback('SIP', self.multipart_handler)
  915. +
  916. + def multipart_handler(self, packet):
  917. + """Checks multipart packets to see if NOTIFY messages have
  918. + anticipated data.
  919. + """
  920. + if 'NOTIFY' not in packet.request_line:
  921. + return
  922. +
  923. + if packet.body.packet_type != 'Multipart':
  924. + return
  925. +
  926. + if self.version > 1:
  927. + # This should be impossible, but check for it anyway
  928. + return
  929. +
  930. + validator = RLSValidator(test_object=self.test_object,
  931. + packet=packet,
  932. + version=self.version,
  933. + full_state=True,
  934. + list_name=LIST_NAME,
  935. + resources=RESOURCES)
  936. + validator.check_integrity()
  937. + self.version += 1
  938. +
  939. + if self.version > 1:
  940. + # We expect two NOTIFYs only. If we get them, things passed!
  941. + self.test_object.set_passed(True)
  942. + self.test_object.remove_fail_token(self.token)
  943. + self.test_object.stop_reactor()
  944.  
  945. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/resubscribe.py
  946. ___________________________________________________________________
  947. Added: svn:executable
  948. + *
  949. Added: svn:mime-type
  950. + text/plain
  951. Added: svn:keywords
  952. + Author Date Id Revision
  953. Added: svn:eol-style
  954. + native
  955.  
  956. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/test-config.yaml
  957. ===================================================================
  958. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/test-config.yaml (revision 0)
  959. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/test-config.yaml (revision 0)
  960. @@ -0,0 +1,46 @@
  961. +testinfo:
  962. + summary: 'Test to ensure that full state is sent on resubscription'
  963. + description: |
  964. + 'This test uses SIPp to establish a subscription to a resource list.
  965. + The resource list is a presence list that contains two elements,
  966. + alice@default and bob@default. Once the subscription is established,
  967. + the scenario resubscribes to the list. A PCAP listener is used to
  968. + ensure that the NOTIFY bodies sent by Asterisk are valid. Each of the
  969. + two bodies should convey full resource state of the list, even though
  970. + the list is configured to receive partial state notifications. The
  971. + version number of the list should increment for each NOTIFY body.'
  972. +
  973. +properties:
  974. + minversion: '13.0.0'
  975. + dependencies:
  976. + - python: 'twisted'
  977. + - python: 'starpy'
  978. + - python: 'yappcap'
  979. + - python: 'pyxb'
  980. + - asterisk: 'res_pjsip'
  981. + - asterisk: 'res_pjsip_pubsub'
  982. + tags:
  983. + - rls
  984. + - pjsip
  985. +
  986. +test-modules:
  987. + add-test-to-search-path: 'True'
  988. + test-object:
  989. + config-section: 'test-case-config'
  990. + typename: 'sipp.SIPpTestCase'
  991. + modules:
  992. + -
  993. + config-section: 'pcap-config'
  994. + typename: 'resubscribe.IntegrityCheck'
  995. +
  996. +test-case-config:
  997. + test-iterations:
  998. + -
  999. + scenarios:
  1000. + - { 'key-args': {'scenario': 'resubscribe.xml', '-i': '127.0.0.1', '-p': '5061', '-s': 'pres_list'} }
  1001. +
  1002. +pcap-config:
  1003. + bpf-filter: 'udp port 5061'
  1004. + register-observer: True
  1005. + debug-packets: True
  1006. + device: 'lo'
  1007.  
  1008. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/resubscribe_full_state/test-config.yaml
  1009. ___________________________________________________________________
  1010. Added: svn:eol-style
  1011. + native
  1012. Added: svn:mime-type
  1013. + text/plain
  1014. Added: svn:keywords
  1015. + Author Date Id Revision
  1016.  
  1017. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/pjsip.conf
  1018. ===================================================================
  1019. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/pjsip.conf (revision 0)
  1020. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/pjsip.conf (revision 0)
  1021. @@ -0,0 +1,22 @@
  1022. +[pres_list]
  1023. +type = resource_list
  1024. +event = presence
  1025. +list_item = alice
  1026. +list_item = bob
  1027. +full_state = yes
  1028. +
  1029. +[sipp]
  1030. +type=aor
  1031. +max_contacts=1
  1032. +contact=sip:sipp@127.0.0.1:5061
  1033. +
  1034. +[sipp]
  1035. +type = endpoint
  1036. +context = default
  1037. +aors=sipp
  1038. +transport=local
  1039. +
  1040. +[local]
  1041. +type=transport
  1042. +protocol=udp
  1043. +bind=0.0.0.0:5060
  1044.  
  1045. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/pjsip.conf
  1046. ___________________________________________________________________
  1047. Added: svn:mime-type
  1048. + text/plain
  1049. Added: svn:keywords
  1050. + Author Date Id Revision
  1051. Added: svn:eol-style
  1052. + native
  1053.  
  1054. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/extensions.conf
  1055. ===================================================================
  1056. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/extensions.conf (revision 0)
  1057. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/extensions.conf (revision 0)
  1058. @@ -0,0 +1,4 @@
  1059. +[default]
  1060. +exten => alice,hint,Custom:alice
  1061. +exten => bob,hint,Custom:bob
  1062. +
  1063.  
  1064. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/configs/ast1/extensions.conf
  1065. ___________________________________________________________________
  1066. Added: svn:mime-type
  1067. + text/plain
  1068. Added: svn:keywords
  1069. + Author Date Id Revision
  1070. Added: svn:eol-style
  1071. + native
  1072.  
  1073. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/sipp/termination.xml
  1074. ===================================================================
  1075. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/sipp/termination.xml (revision 0)
  1076. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/sipp/termination.xml (revision 0)
  1077. @@ -0,0 +1,118 @@
  1078. +<?xml version="1.0" encoding="ISO-8859-1" ?>
  1079. +<!DOCTYPE scenario SYSTEM "sipp.dtd">
  1080. +
  1081. +<scenario name="Basic Sipstone UAC">
  1082. + <send retrans="500">
  1083. + <![CDATA[
  1084. +
  1085. + SUBSCRIBE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
  1086. + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
  1087. + From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
  1088. + To: sut <sip:[service]@[remote_ip]:[remote_port]>
  1089. + Call-ID: [call_id]
  1090. + CSeq: 1 SUBSCRIBE
  1091. + Contact: sip:sipp@[local_ip]:[local_port]
  1092. + Max-Forwards: 70
  1093. + Subject: Performance Test
  1094. + Event: presence
  1095. + Supported: eventlist
  1096. + Accept: application/rlmi+xml
  1097. + Accept: application/pidf+xml
  1098. + Accept: multipart/related
  1099. + Expires: 3600
  1100. + Content-Length: 0
  1101. +
  1102. + ]]>
  1103. + </send>
  1104. +
  1105. + <recv response="100"
  1106. + optional="true">
  1107. + </recv>
  1108. +
  1109. + <recv response="200" rtd="true">
  1110. + <action>
  1111. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1112. + </action>
  1113. + </recv>
  1114. +
  1115. + <!-- Initial NOTIFY upon subscribing -->
  1116. + <recv request="NOTIFY" crlf="true">
  1117. + <action>
  1118. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1119. + </action>
  1120. + </recv>
  1121. +
  1122. + <send>
  1123. + <![CDATA[
  1124. +
  1125. + SIP/2.0 200 OK
  1126. + [last_Via:]
  1127. + [last_From:]
  1128. + [last_To:]
  1129. + [last_Call-ID:]
  1130. + [last_CSeq:]
  1131. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  1132. + Content-Length: 0
  1133. +
  1134. + ]]>
  1135. + </send>
  1136. +
  1137. + <send retrans="500" start_txn="howdy">
  1138. + <![CDATA[
  1139. +
  1140. + SUBSCRIBE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
  1141. + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
  1142. + From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
  1143. + To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
  1144. + Call-ID: [call_id]
  1145. + CSeq: [cseq] SUBSCRIBE
  1146. + Contact: sip:sipp@[local_ip]:[local_port]
  1147. + Max-Forwards: 70
  1148. + Subject: Performance Test
  1149. + Event: presence
  1150. + Supported: eventlist
  1151. + Accept: application/rlmi+xml
  1152. + Accept: application/pidf+xml
  1153. + Accept: multipart/related
  1154. + Expires: 0
  1155. + Content-Length: 0
  1156. +
  1157. + ]]>
  1158. + </send>
  1159. +
  1160. + <!-- NOTIFY upon termination -->
  1161. + <recv request="NOTIFY" crlf="true">
  1162. + <action>
  1163. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1164. + </action>
  1165. + </recv>
  1166. +
  1167. + <recv response="200" rtd="true">
  1168. + <action>
  1169. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1170. + </action>
  1171. + </recv>
  1172. +
  1173. + <send>
  1174. + <![CDATA[
  1175. +
  1176. + SIP/2.0 200 OK
  1177. + [last_Via:]
  1178. + [last_From:]
  1179. + [last_To:]
  1180. + [last_Call-ID:]
  1181. + [last_CSeq:]
  1182. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  1183. + Content-Length: 0
  1184. +
  1185. + ]]>
  1186. + </send>
  1187. +
  1188. + <recv response="200" crlf="true" response_txn="howdy">
  1189. + <action>
  1190. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1191. + </action>
  1192. + </recv>
  1193. +
  1194. + <Reference variables="1" />
  1195. +
  1196.  
  1197. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/sipp/termination.xml
  1198. ___________________________________________________________________
  1199. Added: svn:mime-type
  1200. + text/plain
  1201. Added: svn:keywords
  1202. + Author Date Id Revision
  1203. Added: svn:eol-style
  1204. + native
  1205.  
  1206. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/termination.py
  1207. ===================================================================
  1208. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/termination.py (revision 0)
  1209. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/termination.py (revision 0)
  1210. @@ -0,0 +1,77 @@
  1211. +#/usr/bin/env python
  1212. +
  1213. +import sys
  1214. +import logging
  1215. +
  1216. +sys.path.append('lib/python')
  1217. +sys.path.append('tests/channels/pjsip/subscriptions/rls')
  1218. +
  1219. +from pcap import VOIPListener
  1220. +from rls_integrity import RLSValidator
  1221. +
  1222. +LOGGER = logging.getLogger(__name__)
  1223. +
  1224. +LIST_NAME = 'pres_list'
  1225. +RESOURCES = [
  1226. + {
  1227. + 'alice': {
  1228. + 'type': 'PIDF',
  1229. + 'state': 'active'
  1230. + },
  1231. + 'bob': {
  1232. + 'type': 'PIDF',
  1233. + 'state': 'active'
  1234. + }
  1235. + },
  1236. + {
  1237. + 'alice': {
  1238. + 'type': 'PIDF',
  1239. + 'state': 'terminated'
  1240. + },
  1241. + 'bob': {
  1242. + 'type': 'PIDF',
  1243. + 'state': 'terminated'
  1244. + }
  1245. + }
  1246. +]
  1247. +
  1248. +
  1249. +class IntegrityCheck(VOIPListener):
  1250. +
  1251. + def __init__(self, module_config, test_object):
  1252. + """Create listener and add AMI observer/callbacks."""
  1253. + VOIPListener.__init__(self, module_config, test_object)
  1254. + self.test_object = test_object
  1255. + self.token = test_object.create_fail_token("Haven't handled all "
  1256. + "expected NOTIFY packets.")
  1257. + self.version = 0
  1258. + self.ami = None
  1259. + self.add_callback('SIP', self.multipart_handler)
  1260. +
  1261. + def multipart_handler(self, packet):
  1262. + """Checks multipart packets to see if NOTIFY messages have
  1263. + anticipated data.
  1264. + """
  1265. + if 'NOTIFY' not in packet.request_line:
  1266. + return
  1267. +
  1268. + if packet.body.packet_type != 'Multipart':
  1269. + return
  1270. +
  1271. + if self.version > 1:
  1272. + return
  1273. +
  1274. + validator = RLSValidator(test_object=self.test_object,
  1275. + packet=packet,
  1276. + version=self.version,
  1277. + full_state=True,
  1278. + list_name=LIST_NAME,
  1279. + resources=RESOURCES[self.version])
  1280. + validator.check_integrity()
  1281. + self.version += 1
  1282. +
  1283. + if self.version > 1:
  1284. + # We expect two NOTIFYs only. If we get them, things passed!
  1285. + self.test_object.set_passed(True)
  1286. + self.test_object.remove_fail_token(self.token)
  1287. + self.test_object.stop_reactor()
  1288.  
  1289. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/termination.py
  1290. ___________________________________________________________________
  1291. Added: svn:mime-type
  1292. + text/plain
  1293. Added: svn:keywords
  1294. + Author Date Id Revision
  1295. Added: svn:eol-style
  1296. + native
  1297. Added: svn:executable
  1298. + *
  1299.  
  1300. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/test-config.yaml
  1301. ===================================================================
  1302. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/test-config.yaml (revision 0)
  1303. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/test-config.yaml (revision 0)
  1304. @@ -0,0 +1,47 @@
  1305. +testinfo:
  1306. + summary: 'Test to ensure that full state is sent on resubscription'
  1307. + description: |
  1308. + 'This test uses SIPp to establish a subscription to a resource list.
  1309. + The resource list is a presence list that contains two elements,
  1310. + alice@default and bob@default. Once the subscription is established,
  1311. + the scenario terminates its subscription to the list. A PCAP listener
  1312. + is used to ensure that the NOTIFY bodies sent by Asterisk are valid.
  1313. + Each of the two bodies should convey full resource state of the list,
  1314. + even though the list is configured to receive partial state
  1315. + notifications. The version number of the list should increment for
  1316. + each NOTIFY body.'
  1317. +
  1318. +properties:
  1319. + minversion: '13.0.0'
  1320. + dependencies:
  1321. + - python: 'twisted'
  1322. + - python: 'starpy'
  1323. + - python: 'yappcap'
  1324. + - python: 'pyxb'
  1325. + - asterisk: 'res_pjsip'
  1326. + - asterisk: 'res_pjsip_pubsub'
  1327. + tags:
  1328. + - rls
  1329. + - pjsip
  1330. +
  1331. +test-modules:
  1332. + add-test-to-search-path: 'True'
  1333. + test-object:
  1334. + config-section: 'test-case-config'
  1335. + typename: 'sipp.SIPpTestCase'
  1336. + modules:
  1337. + -
  1338. + config-section: 'pcap-config'
  1339. + typename: 'termination.IntegrityCheck'
  1340. +
  1341. +test-case-config:
  1342. + test-iterations:
  1343. + -
  1344. + scenarios:
  1345. + - { 'key-args': {'scenario': 'termination.xml', '-i': '127.0.0.1', '-p': '5061', '-s': 'pres_list'} }
  1346. +
  1347. +pcap-config:
  1348. + bpf-filter: 'udp port 5061'
  1349. + register-observer: True
  1350. + debug-packets: True
  1351. + device: 'lo'
  1352.  
  1353. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/termination_full_state/test-config.yaml
  1354. ___________________________________________________________________
  1355. Added: svn:eol-style
  1356. + native
  1357. Added: svn:mime-type
  1358. + text/plain
  1359. Added: svn:keywords
  1360. + Author Date Id Revision
  1361.  
  1362. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/pjsip.conf
  1363. ===================================================================
  1364. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/pjsip.conf (revision 0)
  1365. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/pjsip.conf (revision 0)
  1366. @@ -0,0 +1,22 @@
  1367. +[pres_list]
  1368. +type = resource_list
  1369. +event = presence
  1370. +list_item = alice
  1371. +list_item = bob
  1372. +full_state = no
  1373. +
  1374. +[sipp]
  1375. +type=aor
  1376. +max_contacts=1
  1377. +contact=sip:sipp@127.0.0.1:5061
  1378. +
  1379. +[sipp]
  1380. +type = endpoint
  1381. +context = default
  1382. +aors=sipp
  1383. +transport=local
  1384. +
  1385. +[local]
  1386. +type=transport
  1387. +protocol=udp
  1388. +bind=0.0.0.0:5060
  1389.  
  1390. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/pjsip.conf
  1391. ___________________________________________________________________
  1392. Added: svn:mime-type
  1393. + text/plain
  1394. Added: svn:keywords
  1395. + Author Date Id Revision
  1396. Added: svn:eol-style
  1397. + native
  1398.  
  1399. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/extensions.conf
  1400. ===================================================================
  1401. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/extensions.conf (revision 0)
  1402. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/extensions.conf (revision 0)
  1403. @@ -0,0 +1,3 @@
  1404. +[default]
  1405. +exten => alice,hint,Custom:alice
  1406. +exten => bob,hint,Custom:bob
  1407.  
  1408. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/configs/ast1/extensions.conf
  1409. ___________________________________________________________________
  1410. Added: svn:eol-style
  1411. + native
  1412. Added: svn:mime-type
  1413. + text/plain
  1414. Added: svn:keywords
  1415. + Author Date Id Revision
  1416.  
  1417. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/sipp/list_subscribe.xml
  1418. ===================================================================
  1419. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/sipp/list_subscribe.xml (revision 0)
  1420. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/sipp/list_subscribe.xml (revision 0)
  1421. @@ -0,0 +1,84 @@
  1422. +<?xml version="1.0" encoding="ISO-8859-1" ?>
  1423. +<!DOCTYPE scenario SYSTEM "sipp.dtd">
  1424. +
  1425. +<scenario name="Basic Sipstone UAC">
  1426. + <send retrans="500">
  1427. + <![CDATA[
  1428. +
  1429. + SUBSCRIBE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
  1430. + Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
  1431. + From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
  1432. + To: sut <sip:[service]@[remote_ip]:[remote_port]>
  1433. + Call-ID: [call_id]
  1434. + CSeq: 1 SUBSCRIBE
  1435. + Contact: sip:sipp@[local_ip]:[local_port]
  1436. + Max-Forwards: 70
  1437. + Subject: Performance Test
  1438. + Event: presence
  1439. + Supported: eventlist
  1440. + Accept: application/rlmi+xml
  1441. + Accept: application/pidf+xml
  1442. + Accept: multipart/related
  1443. + Expires: 3600
  1444. + Content-Length: 0
  1445. +
  1446. + ]]>
  1447. + </send>
  1448. +
  1449. + <recv response="100"
  1450. + optional="true">
  1451. + </recv>
  1452. +
  1453. + <recv response="200" rtd="true">
  1454. + <action>
  1455. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1456. + </action>
  1457. + </recv>
  1458. +
  1459. + <recv request="NOTIFY" crlf="true">
  1460. + <action>
  1461. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1462. + </action>
  1463. + </recv>
  1464. +
  1465. + <Reference variables="1" />
  1466. +
  1467. + <send>
  1468. + <![CDATA[
  1469. +
  1470. + SIP/2.0 200 OK
  1471. + [last_Via:]
  1472. + [last_From:]
  1473. + [last_To:]
  1474. + [last_Call-ID:]
  1475. + [last_CSeq:]
  1476. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  1477. + Content-Length: 0
  1478. +
  1479. + ]]>
  1480. + </send>
  1481. +
  1482. + <recv request="NOTIFY" crlf="true">
  1483. + <action>
  1484. + <ereg regexp="eventlist" search_in="hdr" header="Require:" check_it="true" assign_to="1" />
  1485. + </action>
  1486. + </recv>
  1487. +
  1488. + <Reference variables="1" />
  1489. +
  1490. + <send>
  1491. + <![CDATA[
  1492. +
  1493. + SIP/2.0 200 OK
  1494. + [last_Via:]
  1495. + [last_From:]
  1496. + [last_To:]
  1497. + [last_Call-ID:]
  1498. + [last_CSeq:]
  1499. + Contact: <sip:[local_ip]:[local_port];transport=[transport]>
  1500. + Content-Length: 0
  1501. +
  1502. + ]]>
  1503. + </send>
  1504. +
  1505. +</scenario>
  1506.  
  1507. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/sipp/list_subscribe.xml
  1508. ___________________________________________________________________
  1509. Added: svn:mime-type
  1510. + text/plain
  1511. Added: svn:keywords
  1512. + Author Date Id Revision
  1513. Added: svn:eol-style
  1514. + native
  1515.  
  1516. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/test-config.yaml
  1517. ===================================================================
  1518. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/test-config.yaml (revision 0)
  1519. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/test-config.yaml (revision 0)
  1520. @@ -0,0 +1,46 @@
  1521. +testinfo:
  1522. + summary: 'Test to ensure that the full_state=no option is honored in pjsip.conf'
  1523. + description: |
  1524. + 'This test uses SIPp to establish a subscription to a resource list.
  1525. + The resource list is a presence list that contains two elements,
  1526. + alice@default and bob@default. Once established, the test sends a state
  1527. + change for the alice@default resource. A PCAP listener is used to
  1528. + ensure that the NOTIFY bodies sent by Asterisk are valid. The initial
  1529. + NOTIFY request should convey full state, and the second NOTIFY request
  1530. + should convey partial state. The version number of the list should increment
  1531. + for each NOTIFY body.'
  1532. +
  1533. +properties:
  1534. + minversion: '13.0.0'
  1535. + dependencies:
  1536. + - python: 'twisted'
  1537. + - python: 'starpy'
  1538. + - python: 'yappcap'
  1539. + - python: 'pyxb'
  1540. + - asterisk: 'res_pjsip'
  1541. + - asterisk: 'res_pjsip_pubsub'
  1542. + tags:
  1543. + - rls
  1544. + - pjsip
  1545. +
  1546. +test-modules:
  1547. + add-test-to-search-path: 'True'
  1548. + test-object:
  1549. + config-section: 'test-case-config'
  1550. + typename: 'sipp.SIPpTestCase'
  1551. + modules:
  1552. + -
  1553. + config-section: 'pcap-config'
  1554. + typename: 'partial_state.IntegrityCheck'
  1555. +
  1556. +test-case-config:
  1557. + test-iterations:
  1558. + -
  1559. + scenarios:
  1560. + - { 'key-args': {'scenario': 'list_subscribe.xml', '-i': '127.0.0.1', '-p': '5061', '-s': 'pres_list'} }
  1561. +
  1562. +pcap-config:
  1563. + bpf-filter: 'udp port 5061'
  1564. + register-observer: True
  1565. + debug-packets: True
  1566. + device: 'lo'
  1567.  
  1568. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/test-config.yaml
  1569. ___________________________________________________________________
  1570. Added: svn:mime-type
  1571. + text/plain
  1572. Added: svn:keywords
  1573. + Author Date Id Revision
  1574. Added: svn:eol-style
  1575. + native
  1576.  
  1577. Index: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/partial_state.py
  1578. ===================================================================
  1579. --- tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/partial_state.py (revision 0)
  1580. +++ tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/partial_state.py (revision 0)
  1581. @@ -0,0 +1,97 @@
  1582. +#/usr/bin/env python
  1583. +
  1584. +import sys
  1585. +import logging
  1586. +
  1587. +sys.path.append('lib/python')
  1588. +sys.path.append('tests/channels/pjsip/subscriptions/rls')
  1589. +
  1590. +from pcap import VOIPListener
  1591. +from rls_integrity import RLSValidator
  1592. +
  1593. +LOGGER = logging.getLogger(__name__)
  1594. +
  1595. +LIST_NAME = 'pres_list'
  1596. +
  1597. +RESOURCES = [
  1598. + # First NOTIFY will have all resources present
  1599. + {
  1600. + 'alice': {
  1601. + 'type': 'PIDF',
  1602. + 'state': 'active'
  1603. + },
  1604. + 'bob': {
  1605. + 'type': 'PIDF',
  1606. + 'state': 'active'
  1607. + }
  1608. + },
  1609. + # Second NOTIFY will only have the changed resource present
  1610. + {
  1611. + 'alice': {
  1612. + 'type': 'PIDF',
  1613. + 'state': 'active'
  1614. + }
  1615. + }
  1616. +]
  1617. +
  1618. +
  1619. +class IntegrityCheck(VOIPListener):
  1620. + def __init__(self, module_config, test_object):
  1621. + """Create listener and add AMI observer/callbacks."""
  1622. + VOIPListener.__init__(self, module_config, test_object)
  1623. + self.test_object = test_object
  1624. + self.token = test_object.create_fail_token("Haven't handled all "
  1625. + "expected NOTIFY packets.")
  1626. + self.version = 0
  1627. + self.ami = None
  1628. + self.test_object.register_ami_observer(self.ami_connect)
  1629. + self.test_object.register_scenario_started_observer(
  1630. + self.scenario_started)
  1631. + self.add_callback('SIP', self.multipart_handler)
  1632. +
  1633. + def multipart_handler(self, packet):
  1634. + """Checks multipart packets to see if NOTIFY messages have
  1635. + anticipated data.
  1636. + """
  1637. + if 'NOTIFY' not in packet.request_line:
  1638. + return
  1639. +
  1640. + if packet.body.packet_type != 'Multipart':
  1641. + return
  1642. +
  1643. + if self.version > 1:
  1644. + return
  1645. +
  1646. + full_state = True if self.version == 0 else False
  1647. +
  1648. + validator = RLSValidator(test_object=self.test_object,
  1649. + packet=packet,
  1650. + version=self.version,
  1651. + full_state=full_state,
  1652. + list_name=LIST_NAME,
  1653. + resources=RESOURCES[self.version])
  1654. + validator.check_integrity()
  1655. + self.version += 1
  1656. +
  1657. + if self.version > 1:
  1658. + # We expect two NOTIFYs only. If we get them, things passed!
  1659. + self.test_object.set_passed(True)
  1660. + self.test_object.remove_fail_token(self.token)
  1661. + self.test_object.stop_reactor()
  1662. +
  1663. + def ami_connect(self, ami):
  1664. + """Callback when AMI connects. Sets test AMI instance."""
  1665. + self.ami = ami
  1666. +
  1667. + def scenario_started(self, scenario):
  1668. + """Callback when SIPp scenario has started.
  1669. +
  1670. + Once the scenario has started, we change the device state
  1671. + of Alice. The result should be that Asterisk sends a NOTIFY.
  1672. + """
  1673. + message = {
  1674. + 'Action': 'SetVar',
  1675. + 'Variable': 'DEVICE_STATE(Custom:alice)',
  1676. + 'Value': 'INUSE'
  1677. + }
  1678. + self.ami.sendMessage(message)
  1679.  
  1680. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/nominal/presence/partial_state/partial_state.py
  1681. ___________________________________________________________________
  1682. Added: svn:mime-type
  1683. + text/plain
  1684. Added: svn:keywords
  1685. + Author Date Id Revision
  1686. Added: svn:eol-style
  1687. + native
  1688. Added: svn:executable
  1689. + *
  1690.  
  1691. Index: tests/channels/pjsip/subscriptions/rls/lists/tests.yaml
  1692. ===================================================================
  1693. --- tests/channels/pjsip/subscriptions/rls/lists/tests.yaml (revision 0)
  1694. +++ tests/channels/pjsip/subscriptions/rls/lists/tests.yaml (revision 0)
  1695. @@ -0,0 +1,3 @@
  1696. +tests:
  1697. + - dir: 'nominal'
  1698. + - dir: 'off-nominal'
  1699.  
  1700. Property changes on: tests/channels/pjsip/subscriptions/rls/lists/tests.yaml
  1701. ___________________________________________________________________
  1702. Added: svn:mime-type
  1703. + text/plain
  1704. Added: svn:keywords
  1705. + Author Date Id Revision
  1706. Added: svn:eol-style
  1707. + native
  1708.  
  1709. Index: tests/channels/pjsip/subscriptions/rls/tests.yaml
  1710. ===================================================================
  1711. --- tests/channels/pjsip/subscriptions/rls/tests.yaml (revision 0)
  1712. +++ tests/channels/pjsip/subscriptions/rls/tests.yaml (revision 0)
  1713. @@ -0,0 +1,2 @@
  1714. +tests:
  1715. + - dir: 'lists'
  1716.  
  1717. Property changes on: tests/channels/pjsip/subscriptions/rls/tests.yaml
  1718. ___________________________________________________________________
  1719. Added: svn:mime-type
  1720. + text/plain
  1721. Added: svn:keywords
  1722. + Author Date Id Revision
  1723. Added: svn:eol-style
  1724. + native
  1725.  
  1726. Index: tests/channels/pjsip/subscriptions/rls/rls_integrity.py
  1727. ===================================================================
  1728. --- tests/channels/pjsip/subscriptions/rls/rls_integrity.py (revision 0)
  1729. +++ tests/channels/pjsip/subscriptions/rls/rls_integrity.py (revision 0)
  1730. @@ -0,0 +1,232 @@
  1731. +#/usr/bin/env python
  1732. +
  1733. +import logging
  1734. +import xml.etree.ElementTree as ET
  1735. +
  1736. +LOGGER = logging.getLogger(__name__)
  1737. +
  1738. +
  1739. +def count_parts(parts, packet_type):
  1740. + """Count the number of parts of a particular type in a multipart body"""
  1741. + return sum([1 for x in parts if x.body.packet_type == packet_type])
  1742. +
  1743. +
  1744. +class RLSValidator(object):
  1745. + """General class that validates a multipart RLS NOTIFY body"""
  1746. + def __init__(self, test_object, packet, version, full_state, list_name,
  1747. + resources):
  1748. + """Initializer
  1749. +
  1750. + Keyword Arguments:
  1751. + test_object The test object for the running test.
  1752. + packet The Multipart NOTIFY body in full.
  1753. + version The expected RLMI version attribute. Expressed as an integer.
  1754. + full_state The expected RLMI fullState attribute. Expressed as a
  1755. + boolean.
  1756. + list_name The expected RLMI name element value.
  1757. + packet_type The type of body parts to expect other than RLMI.
  1758. + resources A dictionary of the resource names and their expected state.
  1759. + """
  1760. + super(RLSValidator, self).__init__()
  1761. + self.test_object = test_object
  1762. + self.packet = packet
  1763. + self.version = version
  1764. + self.full_state = full_state
  1765. + self.list_name = list_name
  1766. + self.resources = resources
  1767. + self.rlmi_cids = {}
  1768. + self.resource_cids = {}
  1769. +
  1770. + def check_integrity(self):
  1771. + """Validates a multipart RLS body
  1772. +
  1773. + If the multipart body does not pass validation, then the test will
  1774. + fail. If this method returns at all, it means that the body passed
  1775. + validation.
  1776. + """
  1777. +
  1778. + # Number of resources plus an RLMI part
  1779. + if len(self.packet.body.parts) != len(self.resources) + 1:
  1780. + self.fail_test("Unexpected number of parts (%d) in multipart body"
  1781. + % len(self.packet.body.parts))
  1782. +
  1783. + rlmi_parts = count_parts(self.packet.body.parts, 'RLMI')
  1784. + resource_parts = len(self.packet.body.parts) - 1
  1785. +
  1786. + if rlmi_parts != 1:
  1787. + self.fail_test("Unexpected number of RLMI parts (%d) in multipart"
  1788. + "body" % rlmi_parts)
  1789. +
  1790. + if resource_parts != len(self.resources):
  1791. + self.fail_test("Unexpected number of parts (%d) in multipart"
  1792. + "body" % resource_parts)
  1793. +
  1794. + for part in self.packet.body.parts:
  1795. + if part.body.packet_type == 'RLMI':
  1796. + self.validate_rlmi(part.body.list_elem, self.resources, self.list_name)
  1797. + elif part.body.packet_type == 'PIDF':
  1798. + self.validate_pidf(part.body, self.resources)
  1799. + elif part.body.packet_type == 'Multipart':
  1800. + self.validate_multipart(part, self.resources)
  1801. +
  1802. + if len(self.rlmi_cids) != len(self.resource_cids):
  1803. + self.fail_test("Gathered mismatching number of Content IDs. RLMI"
  1804. + "document has %d. Should have %d" %
  1805. + (len(self.rlmi_cids), len(self.resource_cids)))
  1806. +
  1807. + for uri, cid in self.rlmi_cids.iteritems():
  1808. + if uri not in self.resource_cids:
  1809. + self.fail_test("URI not found in %s documents" %
  1810. + (uri))
  1811. + if self.resource_cids.get(uri) != cid:
  1812. + self.fail_test("Mismatching Content ID for URI %s. RLMI"
  1813. + "document has %s. Document has %s" %
  1814. + (uri, cid, self.resource_cids.get(uri)))
  1815. +
  1816. + def validate_rlmi(self, list_elem, resources, list_name):
  1817. + """Validate an RLMI document
  1818. +
  1819. + This method checks the integrity of the list element and calls
  1820. + into a helper method to check the integrity of each resource
  1821. + element in the list.
  1822. +
  1823. + Keyword Arguments:
  1824. + list_elem The XML <list> element in the RLMI body, as parsed by pyxb
  1825. + resources The expected resources dictionary relevant to this RLMI body
  1826. + """
  1827. + if list_elem.version != self.version:
  1828. + self.fail_test("Unexpected RLMI version %d" % list_elem.version)
  1829. +
  1830. + if list_elem.fullState != self.full_state:
  1831. + self.fail_test("Unexpected fullState value %s" %
  1832. + str(list_elem.fullState))
  1833. +
  1834. + if len(list_elem.name) != 1:
  1835. + self.fail_test("Unexpected number of names (%d) in RLMI list" %
  1836. + len(list_elem.name))
  1837. +
  1838. + if len(list_elem.resource) != len(resources):
  1839. + self.fail_test("Unexpected number of resources (%d) in RLMI list" %
  1840. + len(list_elem.resource))
  1841. +
  1842. + if list_elem.name[0].value() != list_name:
  1843. + self.fail_test("Unexpected list name: %s" %
  1844. + list_elem.name[0].value())
  1845. +
  1846. + for resource in list_elem.resource:
  1847. + self.validate_rlmi_resource(resource, resources)
  1848. +
  1849. + def validate_rlmi_resource(self, rlmi_resource, resources):
  1850. + """Validate an RLMI resource
  1851. +
  1852. + This method checks the integrity of a resource XML element within an
  1853. + RLMI list.
  1854. +
  1855. + Keyword Arguments:
  1856. + rlmi_resource The XML <resource> element in the RLMI <list>, as parsed
  1857. + by pyxb
  1858. + resources The expected resources dictionary relevant to this RLMI
  1859. + resource
  1860. + """
  1861. + if not rlmi_resource.uri:
  1862. + self.fail_test("Resource is missing a URI")
  1863. +
  1864. + if len(rlmi_resource.name) != 1:
  1865. + self.fail_test("Unexpected number of names (%d) in resource" %
  1866. + len(rlmi_resource.name))
  1867. +
  1868. + if len(rlmi_resource.instance) != 1:
  1869. + self.fail_test("Unexpeced number of instances (%d) in resource" %
  1870. + len(rlmi_resource.instance))
  1871. +
  1872. + name = rlmi_resource.name[0].value()
  1873. + if name not in resources:
  1874. + self.fail_test("Unexpected resource name %s" % name)
  1875. +
  1876. + instance = rlmi_resource.instance[0]
  1877. + if not instance.state:
  1878. + self.fail_test("Resource instance has no state")
  1879. + if not instance.id:
  1880. + self.fail_test("Resource instance has no id")
  1881. + if not instance.cid:
  1882. + self.fail_test("Resource instance has no cid")
  1883. +
  1884. + if instance.state != resources[name]['state']:
  1885. + self.fail_test("Unexpected instance state %s" % instance.state)
  1886. +
  1887. + self.rlmi_cids[rlmi_resource.uri] = rlmi_resource.instance[0].cid
  1888. +
  1889. + def validate_pidf(self, pidf_part, resources):
  1890. + """Validates the integrity of a PIDF body
  1891. +
  1892. + This uses XML ElementTree to parse the PIDF body and ensures basic
  1893. + structural elements (as they relate to RLS) are present.
  1894. +
  1895. + Keyword Arguments:
  1896. + pidf_part The PIDF part from a multipart body.
  1897. + resources The expected resources dictionary relevant to this PIDF body
  1898. + """
  1899. +
  1900. + if not pidf_part.content_id:
  1901. + self.fail_test("PIDF part does not have a Content-ID")
  1902. +
  1903. + try:
  1904. + root = ET.fromstring(pidf_part.xml)
  1905. + except Exception as ex:
  1906. + self.fail_test("Exception when parsing PIDF XML: %s" % ex)
  1907. +
  1908. + entity = root.get('entity')
  1909. + if not entity:
  1910. + self.fail_test("PIDF document root has no entity")
  1911. +
  1912. + stripped_entity = entity.strip('<>')
  1913. + self.resource_cids[stripped_entity] = pidf_part.content_id
  1914. +
  1915. + def validate_multipart(self, multi_part, resources):
  1916. + """Validates the integrity of a Multipart body
  1917. +
  1918. + This filters down through parts within the multipart body
  1919. + in order to recursively evaluate each element contained
  1920. + within.
  1921. +
  1922. + Keyword Arguments:
  1923. + multi_part The Multipart part from a multipart body.
  1924. + resources The expected resources dictionary relevant for this
  1925. + multipart body. May be the full list specified by the test
  1926. + or a deeper node.
  1927. + """
  1928. + if not multi_part.content_id:
  1929. + self.fail_test("Multipart does not have a Content-ID")
  1930. +
  1931. + for part in multi_part.body.parts:
  1932. + if part.body.packet_type == 'RLMI':
  1933. + name = part.body.list_elem.name[0].value()
  1934. + uri = part.body.list_elem.uri
  1935. +
  1936. + self.resource_cids[uri] = multi_part.content_id
  1937. +
  1938. + next_resources = resources.get(name)
  1939. + if not next_resources:
  1940. + self.fail_test("Missing '%s'" % name)
  1941. + return
  1942. +
  1943. + if next_resources['type'] != 'Multipart':
  1944. + self.fail_test("Packet Type is wrong -- processing multipart, "
  1945. + "but expected type is %s" % next_resources['type'])
  1946. + return
  1947. +
  1948. + next_resources = next_resources['sublist']
  1949. +
  1950. + for part in multi_part.body.parts:
  1951. + if part.body.packet_type == 'RLMI':
  1952. + self.validate_rlmi(part.body.list_elem, next_resources, name)
  1953. + elif part.body.packet_type == 'PIDF':
  1954. + self.validate_pidf(part.body, next_resources)
  1955. + elif part.body.packet_type == 'Multipart':
  1956. + self.validate_multipart(part.body, next_resources)
  1957. +
  1958. + def fail_test(self, message):
  1959. + """Fail the test and stop the reactor"""
  1960. + LOGGER.error(message)
  1961. + self.test_object.set_passed(False)
  1962. + self.test_object.stop_reactor()
  1963.  
  1964. Property changes on: tests/channels/pjsip/subscriptions/rls/rls_integrity.py
  1965. ___________________________________________________________________
  1966. Added: svn:executable
  1967. + *
  1968. Added: svn:mime-type
  1969. + text/plain
  1970. Added: svn:keywords
  1971. + Author Date Id Revision
  1972. Added: svn:eol-style
  1973. + native
  1974.  
  1975. Index: tests/channels/pjsip/subscriptions/tests.yaml
  1976. ===================================================================
  1977. --- tests/channels/pjsip/subscriptions/tests.yaml (revision 5316)
  1978. +++ tests/channels/pjsip/subscriptions/tests.yaml (working copy)
  1979. @@ -6,3 +6,4 @@
  1980. - test: 'unknown_event_package'
  1981. - test: 'unallowed'
  1982. - test: 'below_min_expiry'
  1983. + - dir: 'rls'
  1984. Index: lib/python/asterisk/pcap.py
  1985. ===================================================================
  1986. --- lib/python/asterisk/pcap.py (revision 5316)
  1987. +++ lib/python/asterisk/pcap.py (working copy)
  1988. @@ -25,6 +25,8 @@
  1989. except:
  1990. PCAP_AVAILABLE = False
  1991.  
  1992. +import rlmi
  1993. +
  1994. LOGGER = logging.getLogger(__name__)
  1995.  
  1996. class PcapListener(object):
  1997. @@ -57,7 +59,7 @@
  1998. # Let exceptions propagate - if we can't create the pcap, this should
  1999. # throw the exception to the pluggable module creation routines
  2000. test_object.create_pcap_listener(
  2001. - device=None,
  2002. + device=device,
  2003. bpf_filter=bpf_filter,
  2004. dumpfile=filename)
  2005.  
  2006. @@ -201,6 +203,87 @@
  2007. self.rtcp_port = self.rtp_port + 1
  2008.  
  2009.  
  2010. +class PIDFPacket(Packet):
  2011. + '''A PIDF presence body. Owned by SIPPacket or a MultipartPacket.'''
  2012. +
  2013. + def __init__(self, ascii_packet, raw_packet, content_id):
  2014. + Packet.__init__(self, packet_type="PIDF", raw_packet=raw_packet)
  2015. + self.xml = ascii_packet.strip()
  2016. + self.content_id = content_id
  2017. +
  2018. +
  2019. +class RLMIPacket(Packet):
  2020. + '''An RLMI body. Owned either by a SIPPacket or a MultipartPacket.'''
  2021. +
  2022. + def __init__(self, ascii_packet, raw_packet):
  2023. + Packet.__init__(self, packet_type="RLMI", raw_packet=raw_packet)
  2024. + self.list_elem = rlmi.CreateFromDocument(ascii_packet.strip())
  2025. +
  2026. +
  2027. +class MultipartPart:
  2028. + def __init__(self, part, raw_packet):
  2029. + self.headers = {}
  2030. +
  2031. + last_pos = part.find('\r\n\r\n')
  2032. + headers = part[:last_pos].split('\r\n')
  2033. + body = part[last_pos:]
  2034. +
  2035. + for header in headers:
  2036. + colon_pos = header.find(':')
  2037. + self.headers[header[:colon_pos]] = header[colon_pos + 1:].strip()
  2038. +
  2039. + content_type = self.headers.get('Content-Type')
  2040. + self.content_id = self.headers.get('Content-ID').strip('<>')
  2041. +
  2042. + self.body = BodyFactory.create_body(content_type, body.strip(),
  2043. + raw_packet, self.content_id)
  2044. +
  2045. +
  2046. +class MultipartPacket(Packet):
  2047. + '''A multipart body. Owned either by a SIPPacket or a Multipartpacket.'''
  2048. +
  2049. + def __init__(self, content_type, ascii_packet, raw_packet):
  2050. + Packet.__init__(self, packet_type="Multipart", raw_packet=raw_packet)
  2051. + self.boundary = None
  2052. + self.parts = []
  2053. +
  2054. + for part in content_type.split(';'):
  2055. + param, equal, value = part.partition('=')
  2056. + if param == 'boundary':
  2057. + self.boundary = '--%s' % value.strip('"')
  2058. +
  2059. + if not self.boundary:
  2060. + raise Exception
  2061. +
  2062. + parts = ascii_packet.split(self.boundary)
  2063. +
  2064. + # Start with the second part since the initial boundary has no content
  2065. + # before it.
  2066. + for part in parts[1:]:
  2067. + stripped = part.strip('\r\n ')
  2068. + # The final boundary in a multipart body is --boundary--
  2069. + if stripped == '--':
  2070. + break
  2071. + self.parts.append(MultipartPart(stripped, raw_packet))
  2072. +
  2073. +
  2074. +class BodyFactory(object):
  2075. + @staticmethod
  2076. + def create_body(content_type, ascii_packet, raw_packet, content_id=None):
  2077. + body_type, _, _ = content_type.partition(';')
  2078. + if (body_type == 'application/sdp'):
  2079. + return SDPPacket(ascii_packet, raw_packet)
  2080. + elif (body_type == 'multipart/related'):
  2081. + return MultipartPacket(content_type, ascii_packet, raw_packet)
  2082. + elif (body_type == 'application/rlmi+xml'):
  2083. + return RLMIPacket(ascii_packet, raw_packet)
  2084. + elif (body_type == 'application/pidf+xml'):
  2085. + return PIDFPacket(ascii_packet, raw_packet, content_id)
  2086. + else:
  2087. + return Packet(body_type, raw_packet)
  2088. + pass
  2089. +
  2090. +
  2091. class SIPPacket(Packet):
  2092. ''' A SIP packet '''
  2093.  
  2094. @@ -213,7 +296,7 @@
  2095. '''
  2096. Packet.__init__(self, packet_type='SIP', raw_packet=raw_packet)
  2097.  
  2098. - self.sdp_packet = None
  2099. + self.body = None
  2100. self.headers = {}
  2101. self.request_line = ''
  2102. self.ascii_packet = ascii_packet
  2103. @@ -232,8 +315,11 @@
  2104. colon_pos = header.find(':')
  2105. self.headers[header[:colon_pos]] = header[colon_pos + 1:].strip()
  2106. if int(self.headers.get('Content-Length')) > 0:
  2107. - self.sdp_packet = SDPPacket(ascii_packet=remainder_packet,
  2108. - raw_packet=raw_packet)
  2109. + content_type = self.headers.get('Content-Type',
  2110. + 'application/sdp').strip()
  2111. + self.body = BodyFactory.create_body(content_type,
  2112. + ascii_packet=remainder_packet,
  2113. + raw_packet=raw_packet)
  2114.  
  2115.  
  2116. class SIPPacketFactory():
  2117. @@ -270,9 +356,10 @@
  2118. # RTP port and RTCP port; then set that information for this particular
  2119. # stream in the factory manager so that the factories for RTP can
  2120. # interpret packets correctly
  2121. - if ret_packet != None and ret_packet.sdp_packet != None and \
  2122. - ret_packet.sdp_packet.rtp_port != 0 and \
  2123. - ret_packet.sdp_packet.rtcp_port != 0:
  2124. + if ret_packet and ret_packet.body and \
  2125. + ret_packet.body.packet_type == 'SDP' and \
  2126. + ret_packet.sdp_packet.rtp_port != 0 and \
  2127. + ret_packet.sdp_packet.rtcp_port != 0:
  2128. self._factory_manager.add_global_data(ret_packet.ip_layer.header.source,
  2129. {'rtp': ret_packet.sdp_packet.rtp_port,
  2130. 'rtcp': ret_packet.sdp_packet.rtcp_port})
  2131. @@ -451,3 +538,6 @@
  2132. if packet_type not in self._callbacks:
  2133. self._callbacks[packet_type] = []
  2134. self._callbacks[packet_type].append(callback)
  2135. +
  2136. + def remove_callbacks(self, packet_type):
  2137. + del self._callbacks[packet_type]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement