3333CONN_API_KEY = "connection"
3434REG_API_KEY = "registration"
3535
36+ RTP_RESOURCE_DATA_DIR = "test_data/controller"
37+ MXL_RESOURCE_DATA_DIR = "test_data/controller/mxl"
38+ MXL_TRANSPORT = "urn:x-nmos:transport:mxl"
39+ MXL_CONNECTION_API_VERSION = "v1.2"
40+
3641
3742class ControllerTest (GenericTest ):
3843 """
3944 Testing initial set up of new test suite for controller testing
4045 """
46+
4147 def __init__ (self , apis , registries , node , dns_server , auths , disable_auto = True , ** kwargs ):
4248 # Remove the Testing Facade spec_path as there are no corresponding GitHub repos for the Testing Facade API
4349 apis [TESTING_FACADE_API_KEY ].pop ("spec_path" , None )
@@ -52,7 +58,9 @@ def __init__(self, apis, registries, node, dns_server, auths, disable_auto=True,
5258 self .dns_server = dns_server
5359 self .mock_registry_base_url = ''
5460 self .mock_node_base_url = ''
55- self .test_data = self .load_resource_data ()
61+ self .rtp_test_data = self ._load_resource_templates (RTP_RESOURCE_DATA_DIR )
62+ self .rtp_test_data ['node' ]['id' ] = self .node .id
63+ self .mxl_test_data = self ._load_resource_templates (MXL_RESOURCE_DATA_DIR )
5664 self .senders = []
5765 self .sender_ip_addresses = {}
5866 self .receivers = []
@@ -137,26 +145,72 @@ def _format_device_metadata(self, label, description, id):
137145 """ Used to format answers based on device metadata """
138146 return label + ' (' + description + ', ' + id + ')'
139147
148+ def _sender_transport (self , sender ):
149+ return sender .get ("transport" , self .rtp_test_data ["sender" ]["transport" ])
150+
151+ def _receiver_transport (self , receiver ):
152+ return receiver .get ("transport" , self .rtp_test_data ["receiver" ]["transport" ])
153+
154+ def _uses_mxl_transport (self , transport ):
155+ return transport == MXL_TRANSPORT
156+
157+ def _connection_api_version_for_transport (self , transport ):
158+ if self ._uses_mxl_transport (transport ):
159+ return MXL_CONNECTION_API_VERSION
160+ return self .connection_api_version
161+
162+ def _device_controls (self , transport ):
163+ connection_api_version = self ._connection_api_version_for_transport (transport )
164+ return {
165+ "href" : self .mock_node_base_url + "x-nmos/connection/" + connection_api_version + "/" ,
166+ "type" : "urn:x-nmos:control:sr-ctrl/" + connection_api_version
167+ }
168+
169+ def _sender_uses_rtp_transport (self , sender ):
170+ return self ._sender_transport (sender ).startswith ("urn:x-nmos:transport:rtp" )
171+
172+ def _sender_uses_mxl_transport (self , sender ):
173+ return self ._uses_mxl_transport (self ._sender_transport (sender ))
174+
175+ def _receiver_uses_rtp_transport (self , receiver ):
176+ return self ._receiver_transport (receiver ).startswith ("urn:x-nmos:transport:rtp" )
177+
178+ def _receiver_uses_mxl_transport (self , receiver ):
179+ return self ._uses_mxl_transport (self ._receiver_transport (receiver ))
180+
181+ def _resource_templates_for_sender (self , sender ):
182+ if self ._sender_uses_mxl_transport (sender ):
183+ return self .mxl_test_data
184+ return self .rtp_test_data
185+
186+ def _resource_templates_for_receiver (self , receiver ):
187+ if self ._receiver_uses_mxl_transport (receiver ):
188+ return self .mxl_test_data
189+ return self .rtp_test_data
190+
140191 def _populate_registry (self , test ):
141192 """Populate registry and mock node with mock senders and receivers"""
142193 self .node .reset () # Ensure previously added senders and receivers are removed
143194 if self .primary_registry :
144195 self .primary_registry .common .reset () # Ensure any previously registered senders and receivers are removed
145196 sender_ip_final_octet = 159
197+ mxl_domain_id = str (uuid .uuid4 ())
146198
147199 # Register node
148200 self ._register_node (test , self .node .id , "AMWA Test Suite Node" , "AMWA Test Suite Node" )
149201
150202 # self.senders should be initialized in the set_up_tests() override of derived test
151203 # each mock sender defined as: {'label': <unique label>, 'description': '',
152- # 'registered': <is registered with mock Registry>}
204+ # 'registered': <is registered with mock Registry>,
205+ # 'transport': <optional; defaults to RTP template transport>}
153206 for sender in self .senders :
154207 sender ["id" ] = str (uuid .uuid4 ())
155208 sender ["device_id" ] = str (uuid .uuid4 ())
156209 sender ["flow_id" ] = str (uuid .uuid4 ())
157210 sender ["source_id" ] = str (uuid .uuid4 ())
158- sender ["manifest_href" ] = self .mock_node_base_url + "x-nmos/connection/" + self .connection_api_version \
159- + "/single/senders/" + sender ["id" ] + "/transportfile"
211+ if self ._sender_uses_rtp_transport (sender ):
212+ sender ["manifest_href" ] = self .mock_node_base_url + "x-nmos/connection/" \
213+ + self .connection_api_version + "/single/senders/" + sender ["id" ] + "/transportfile"
160214 sender ["version" ] = NMOSUtils .get_TAI_time ()
161215 sender ["display_answer" ] = self ._format_device_metadata (sender ['label' ], sender ['description' ],
162216 sender ['id' ])
@@ -165,22 +219,26 @@ def _populate_registry(self, test):
165219 time .sleep (0.1 )
166220 if sender ["registered" ]:
167221 self ._register_sender (test , sender )
168- # Add sender to mock node
169- sender_json = self ._create_sender_json (sender )
170- sender_ip_address = self .senders_ip_base + str (sender_ip_final_octet )
171- self .node .add_sender (sender_json , sender_ip_address , sender .get ("sdp_params" , {}))
172- self .sender_ip_addresses [sender ["id" ]] = sender_ip_address
173- sender_ip_final_octet += 1
222+ # Add RTP senders to mock node (IS-05 Connection API)
223+ if self ._sender_uses_rtp_transport (sender ):
224+ sender_json = self ._create_sender_json (sender )
225+ sender_ip_address = self .senders_ip_base + str (sender_ip_final_octet )
226+ self .node .add_sender (sender_json , sender_ip_address , sender .get ("sdp_params" , {}))
227+ self .sender_ip_addresses [sender ["id" ]] = sender_ip_address
228+ sender_ip_final_octet += 1
229+ elif self ._sender_uses_mxl_transport (sender ):
230+ self .node .add_mxl_sender (self ._create_sender_json (sender ), mxl_domain_id )
174231
175232 # self.receivers should be initialized in the set_up_tests() override of derived test
176233 # each mock receiver defined as: {'label': <unique label>, 'description': '',
177- # 'connectable': <has IS-05 connection API>, 'registered': <is registered with mock Registry>}
234+ # 'connectable': <has IS-05 connection API>, 'registered': <is registered with mock Registry>,
235+ # 'transport': <optional; defaults to RTP template transport>}
178236 for receiver in self .receivers :
179237 receiver ["id" ] = str (uuid .uuid4 ())
180238 receiver ["device_id" ] = str (uuid .uuid4 ())
181- receiver [ "controls_href" ] = self .mock_node_base_url + "x-nmos/connection/" \
182- + self . connection_api_version + "/"
183- receiver ["controls_type" ] = "urn:x-nmos:control:sr-ctrl/" + self . connection_api_version
239+ receiver_controls = self ._device_controls ( self . _receiver_transport ( receiver ))
240+ receiver [ "controls_href" ] = receiver_controls [ "href" ]
241+ receiver ["controls_type" ] = receiver_controls [ "type" ]
184242 receiver ["version" ] = NMOSUtils .get_TAI_time ()
185243 receiver ["display_answer" ] = self ._format_device_metadata (
186244 receiver ['label' ], receiver ['description' ], receiver ['id' ])
@@ -192,20 +250,20 @@ def _populate_registry(self, test):
192250 # Add receiver to mock node
193251 # Note: mock node is currently only a mock Connection API
194252 # so only add 'connectable' receivers
195- if receiver ["connectable" ]:
253+ if receiver ["connectable" ] and self . _receiver_uses_rtp_transport ( receiver ) :
196254 receiver_json = self ._create_receiver_json (receiver )
197255 self .node .add_receiver (receiver_json )
256+ elif receiver ["connectable" ] and self ._receiver_uses_mxl_transport (receiver ):
257+ self .node .add_mxl_receiver (self ._create_receiver_json (receiver ), mxl_domain_id )
198258
199- def load_resource_data (self ):
200- """Loads test data from files """
201- result_data = dict ()
259+ def _load_resource_templates (self , directory ):
260+ """Loads IS-04 resource templates from a controller test data directory. """
261+ templates = {}
202262 resources = ["node" , "device" , "source" , "flow" , "sender" , "receiver" ]
203263 for resource in resources :
204- with open ("test_data/controller/v1.3_{}.json" .format (resource )) as resource_data :
205- resource_json = json .load (resource_data )
206- result_data [resource ] = resource_json
207- result_data ['node' ]['id' ] = self .node .id
208- return result_data
264+ with open ("{}/v1.3_{}.json" .format (directory , resource )) as resource_data :
265+ templates [resource ] = json .load (resource_data )
266+ return templates
209267
210268 def post_resource (self , test , type , data = None , reg_url = None , codes = None , fail = Test .FAIL , headers = None ):
211269 """
@@ -214,7 +272,7 @@ def post_resource(self, test, type, data=None, reg_url=None, codes=None, fail=Te
214272 Otherwise, on success, returns values of the Location header and X-Paging-Timestamp debugging header.
215273 """
216274 if not data :
217- data = self .test_data [type ]
275+ data = self .rtp_test_data [type ]
218276
219277 if not reg_url :
220278 reg_url = self .mock_registry_base_url + 'x-nmos/registration/v1.3/'
@@ -258,15 +316,16 @@ def _register_node(self, test, node_id, label, description):
258316 """
259317 Perform POST requests on the Registration API to create node registration
260318 """
261- node_data = deepcopy (self .test_data ["node" ])
319+ node_data = deepcopy (self .rtp_test_data ["node" ])
262320 node_data ["id" ] = node_id
263321 node_data ["label" ] = label
264322 node_data ["description" ] = description
265323 node_data ["version" ] = NMOSUtils .get_TAI_time ()
266324 self .post_resource (test , "node" , node_data , codes = [201 ])
267325
268326 def _create_sender_json (self , sender ):
269- sender_data = deepcopy (self .test_data ["sender" ])
327+ templates = self ._resource_templates_for_sender (sender )
328+ sender_data = deepcopy (templates ["sender" ])
270329
271330 if "sdp_params" in sender :
272331 # Mapping sdp_params names to sender names
@@ -283,6 +342,7 @@ def _create_sender_json(self, sender):
283342 "device_id" ,
284343 "flow_id" ,
285344 "manifest_href" ,
345+ "transport" ,
286346 "version" ]
287347
288348 for property in overridden_properties :
@@ -298,23 +358,24 @@ def _register_sender(self, test, sender, codes=[201], fail=Test.FAIL):
298358 Use to create sender [code=201] or to update existing sender [code=200]
299359 """
300360 # use the test data as a template for creating new resources
361+ templates = self ._resource_templates_for_sender (sender )
301362
302363 # Register device
303- device_data = deepcopy (self . test_data ["device" ])
364+ device_data = deepcopy (templates ["device" ])
304365 device_data ["id" ] = sender ["device_id" ]
305366 device_data ["label" ] = "AMWA Test Device"
306367 device_data ["description" ] = "AMWA Test Device"
307368 device_data ["node_id" ] = self .node .id
308- device_data [ "controls" ][ 0 ][ "href" ] = self .mock_node_base_url + "x-nmos/connection/" \
309- + self . connection_api_version + "/"
310- device_data ["controls" ][0 ]["type" ] = "urn:x-nmos:control:sr-ctrl/" + self . connection_api_version
369+ sender_controls = self ._device_controls ( self . _sender_transport ( sender ))
370+ device_data [ "controls" ][ 0 ][ "href" ] = sender_controls [ "href" ]
371+ device_data ["controls" ][0 ]["type" ] = sender_controls [ "type" ]
311372 device_data ["senders" ] = [sender ["id" ]]
312373 device_data ["receivers" ] = []
313374 device_data ["version" ] = sender ["version" ]
314375 self .post_resource (test , "device" , device_data , codes = codes , fail = fail )
315376
316377 # Register source
317- source_data = deepcopy (self . test_data ["source" ])
378+ source_data = deepcopy (templates ["source" ])
318379 source_data ["id" ] = sender ["source_id" ]
319380 source_data ["label" ] = "AMWA Test Source"
320381 source_data ["description" ] = "AMWA Test Source"
@@ -323,7 +384,7 @@ def _register_sender(self, test, sender, codes=[201], fail=Test.FAIL):
323384 self .post_resource (test , "source" , source_data , codes = codes , fail = fail )
324385
325386 # Register flow
326- flow_data = deepcopy (self . test_data ["flow" ])
387+ flow_data = deepcopy (templates ["flow" ])
327388 flow_data ["id" ] = sender ["flow_id" ]
328389 flow_data ["label" ] = "AMWA Test Flow"
329390 flow_data ["description" ] = "AMWA Test Flow"
@@ -351,10 +412,10 @@ def delete_sender(self, test, sender):
351412 raise NMOSTestException (test .FAIL ("Registration API returned an unexpected response: {}" .format (r )))
352413
353414 def _create_receiver_json (self , receiver ):
354- # Register receiver
355- receiver_data = deepcopy (self . test_data ["receiver" ])
415+ templates = self . _resource_templates_for_receiver ( receiver )
416+ receiver_data = deepcopy (templates ["receiver" ])
356417
357- overriden_properties = ["id" , "label" , "description" , "device_id" , "version" , "caps" ]
418+ overriden_properties = ["id" , "label" , "description" , "device_id" , "transport" , " version" , "caps" ]
358419
359420 for property in overriden_properties :
360421 if property in receiver :
@@ -369,9 +430,10 @@ def _register_receiver(self, test, receiver, codes=[201], fail=Test.FAIL):
369430 Use to create receiver [code=201] or to update existing receiver [code=200]
370431 """
371432 # use the test data as a template for creating new resources
433+ templates = self ._resource_templates_for_receiver (receiver )
372434
373435 # Register device
374- device_data = deepcopy (self . test_data ["device" ])
436+ device_data = deepcopy (templates ["device" ])
375437 device_data ["id" ] = receiver ["device_id" ]
376438 device_data ["label" ] = "AMWA Test Device"
377439 device_data ["description" ] = "AMWA Test Device"
@@ -448,7 +510,9 @@ def pre_tests_message(self):
448510 """ )
449511
450512 try :
451- self .testing_facade_utils .invoke_testing_facade (question , [], test_type = "action" )
513+ metadata = {'test_class' : self .__class__ .__name__ }
514+ self .testing_facade_utils .invoke_testing_facade (
515+ question , [], test_type = "action" , metadata = metadata )
452516
453517 except TestingFacadeException :
454518 # pre_test_introducton timed out
0 commit comments