def __init__(self) -> None: self.isopen = True self.user_host = base.get_user_host() self.default_identity = self.user_host # Accumulators for verifying that close is working. self.num_read_loops = 0 self.done_task: asyncio.Future = asyncio.Future() # Set of SalInfo. self._salinfo_set: weakref.WeakSet[SalInfo] = weakref.WeakSet() self.origin = os.getpid() self.idl_dir = idl.get_idl_dir() qos_path = ddsconfig.get_qos_path() self.ackcmd_qos_set = QosSet(qos_path=qos_path, profile_name="AckcmdProfile") self.command_qos_set = QosSet(qos_path=qos_path, profile_name="CommandProfile") self.event_qos_set = QosSet(qos_path=qos_path, profile_name="EventProfile") self.telemetry_qos_set = QosSet(qos_path=qos_path, profile_name="TelemetryProfile") # Any of the three qos providers is fine for the participant qos. participant_qos = self.command_qos_set.qos_provider.get_participant_qos( ) self.participant = dds.DomainParticipant(qos=participant_qos)
def setUp(cls): cls.component = "Test" cls.data_dir = pathlib.Path(__file__).parent / "data" / "topic_names_sets" metadata = salobj.parse_idl( cls.component, idl.get_idl_dir() / "sal_revCoded_Test.idl" ) command_names = [] event_names = [] telemetry_names = [] for topic_metadata in metadata.topic_info.values(): sal_topic_name = topic_metadata.sal_name if sal_topic_name.startswith("command_"): command_names.append(sal_topic_name[8:]) elif sal_topic_name.startswith("logevent_"): event_names.append(sal_topic_name[9:]) elif sal_topic_name != "ackcmd": telemetry_names.append(sal_topic_name) cls.command_names = tuple(command_names) cls.event_names = tuple(event_names) cls.telemetry_names = tuple(telemetry_names) cls.all_names = dict( commands=cls.command_names, events=cls.event_names, telemetry=cls.telemetry_names, ) cls.categories = ("commands", "events", "telemetry")
def __init__(self, name): self.name = name self.xml_dir = get_env_dir("TS_XML_DIR", "ts_xml not setup") self.sal_work_dir = get_env_dir("SAL_WORK_DIR", "$SAL_WORK_DIR must be defined") idl_file_name = f"sal_revCoded_{self.name}.idl" self.idl_file_from_path = self.sal_work_dir / "idl-templates" / "validated" / "sal" / idl_file_name self.idl_file_to_path = idl.get_idl_dir() / idl_file_name
def get_component_metadata( components: typing.List[str], ) -> typing.Dict[str, typing.Any]: """Gather metadada information, needed to validate topics versions. Parameters ---------- components : `list` of `str` List of components name in the "Name:index" format. Returns ------- `dict` Component metadata. """ return dict([( component, salobj.parse_idl( component, idl.get_idl_dir() / f"sal_revCoded_{component.split(':')[0]}.idl", ), ) for component in components])
def test_test_idl(self) -> None: """Test a Test IDL file generated by the current version of ts_sal. This is to catch format changes relative to the local Simple IDL files. It is not as thorough as the tests for the local Simple IDL files because I don't want to make too many assumptions about minor details of the XML. """ idl_path = idl.get_idl_dir() / "sal_revCoded_Test.idl" metadata = salobj.parse_idl(name="Test", idl_path=idl_path) assert metadata.name == "Test" assert idl_path.samefile(metadata.idl_path) # Check that names match between info dict keys # and the name in the metadata. for sal_topic_name, topic_metadata in metadata.topic_info.items(): assert topic_metadata.sal_name == sal_topic_name for field_name, field_metadata in topic_metadata.field_info.items( ): assert field_metadata.name == field_name # Check that some of the expected topic names are present. some_expected_topic_names = ( "command_enable", "command_setArrays", "command_setScalars", "logevent_arrays", "logevent_scalars", "arrays", "scalars", ) assert set(some_expected_topic_names).issubset( set(metadata.topic_info.keys())) # Dict of field name: expected type name field_types = dict( salIndex="long", private_revCode="string", private_sndStamp="double", private_rcvStamp="double", private_seqNum="long", private_identity="string", private_origin="long", boolean0="boolean", byte0="octet", short0="short", int0="long", long0="long", longLong0="long long", string0="string", unsignedShort0="unsigned short", unsignedInt0="unsigned long", unsignedLong0="unsigned long", float0="float", double0="double", ) # Check some details of arrays topics, including data type, # array length and string length. for topic_name in ("arrays", "logevent_arrays", "command_setArrays"): with self.subTest(topic_name=topic_name): topic_metadata = metadata.topic_info[topic_name] for deprecated_field in ("char0", "octet0"): topic_metadata.field_info.pop(deprecated_field, None) expected_field_names = set(field_types.keys()) expected_field_names.remove("string0") # only in scalars assert set( topic_metadata.field_info.keys()) == expected_field_names for field_metadata in topic_metadata.field_info.values(): if field_metadata.name[-1] != "0": assert field_metadata.array_length is None else: assert field_metadata.array_length == 5 assert isinstance(field_metadata.description, str) assert field_metadata.type_name == field_types[ field_metadata.name] # Check some details of scalars topics, including data type, # array length and string length. for topic_name in ("scalars", "logevent_scalars", "command_setScalars"): with self.subTest(topic_name=topic_name): topic_metadata = metadata.topic_info[topic_name] for deprecated_field in ("char0", "octet0"): topic_metadata.field_info.pop(deprecated_field, None) expected_field_names = set(field_types.keys()) assert set( topic_metadata.field_info.keys()) == expected_field_names for field_metadata in topic_metadata.field_info.values(): assert field_metadata.array_length is None assert isinstance(field_metadata.description, str) assert field_metadata.type_name == field_types[ field_metadata.name]
def __init__(self, *, component, topic_names_list, queue_len=salobj.topics.DEFAULT_QUEUE_LEN): self.component = component self.topic_names_list = list(topic_names_list) self.queue_len = int(queue_len) topic_categories = ("commands", "events", "telemetry") # Construct a dict of topic category: all topic names, by reading the # IDL file. Topic names *omit* the command_ and logevent_ prefix. all_names_dict = {category: set() for category in topic_categories} idl_metadata = salobj.parse_idl( component, idl.get_idl_dir() / f"sal_revCoded_{component}.idl") for topic in idl_metadata.topic_info: if topic.startswith("command_"): all_names_dict["commands"].add(topic[8:]) elif topic.startswith("logevent_"): all_names_dict["events"].add(topic[9:]) elif topic == "ackcmd": pass else: all_names_dict["telemetry"].add(topic) # Examine the topic_names_list, recording which topics have been seen # and looking for invalid and duplicate names. ackcmd_added = False seen_names_dict = {category: set() for category in topic_categories} for i, topic_names in enumerate(self.topic_names_list): if topic_names.add_ackcmd: if ackcmd_added: raise ValueError( f"topic_names_list[{i}] invalid: ackcmd already added") ackcmd_added = True for category in topic_categories: all_names = all_names_dict[category] seen_names = seen_names_dict[category] specified_names = set(getattr(topic_names, category, [])) # Check that specified names are valid invalid_names = specified_names - all_names if invalid_names: raise ValueError( f"topic_names_list[{i}].{category} " f"has invalid names: {sorted(invalid_names)}") # Check for duplicates duplicate_names = seen_names & specified_names if duplicate_names: raise ValueError( f"topic_names_list[{i}].{category} " f"has names already specified: {sorted(duplicate_names)}" ) seen_names |= specified_names # Append a TopicNames to handle remaining topics, if needed. remaining_names = { category: all_names_dict[category] - seen_names_dict[category] for category in topic_categories } if not ackcmd_added or any( len(remaining_names[category]) > 0 for category in topic_categories): self.topic_names_list.append( TopicNames(add_ackcmd=not ackcmd_added, **remaining_names))
def test_get_idl_dir(self): expected_idl_dir = self.get_expected_data_dir() / "idl" assert idl.get_idl_dir() == expected_idl_dir