def test_close_publisher_contained_entities(implicit_pub):
    p = utils.create_participant()
    topic1 = dds.StringTopicType.Topic(p, "test topic1")
    topic2 = dds.StringTopicType.Topic(p, "test topic2")
    topic30 = dds.StringTopicType.Topic(p, "test topic3")

    pub1 = None
    pub2 = dds.Publisher(p)
    if not implicit_pub:
        pub1 = dds.Publisher(p)
    else:
        pub1 = p.implicit_publisher

    writer10 = dds.StringTopicType.DataWriter(pub1, topic1)
    writer11 = dds.StringTopicType.DataWriter(pub1, topic1)
    writer20 = dds.StringTopicType.DataWriter(pub1, topic2)
    writer30 = dds.StringTopicType.DataWriter(pub1, topic30)
    writer31 = dds.StringTopicType.DataWriter(pub2, topic30)

    pub1.close()

    assert pub1.closed
    assert not pub2.closed

    assert writer10.closed
    assert writer11.closed
    assert writer20.closed
    assert writer30.closed
    assert not writer31.closed
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    # Participant properties give access to the builtin readers
    participant.participant_reader.bind_listener(
        BuiltinParticipantListener(),
        dds.StatusMask.data_available())

    participant.subscription_reader.bind_listener(
        BuiltinSubscriptionListener(),
        dds.StatusMask.data_available())


    msg_type = dds.QosProvider('msg.xml').type('builtin_topics_lib', 'msg')
    topic = dds.DynamicData.Topic(participant, 'Example msg', msg_type)
    writer = dds.DynamicData.DataWriter(dds.Publisher(participant), topic)
    instance = dds.DynamicData(msg_type)

    # write samples in a loop, incrementing the 'x' field
    count = 0
    while (sample_count == 0) or (count < sample_count):
        time.sleep(1)
        instance['x'] = count
        writer.write(instance, dds.InstanceHandle())
        count += 1
    assert count == 5
Beispiel #3
0
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    # Participant properties give access to the builtin readers
    participant.participant_reader.bind_listener(
        BuiltinParticipantListener(), dds.StatusMask.DATA_AVAILABLE
    )

    participant.subscription_reader.bind_listener(
        BuiltinSubscriptionListener(), dds.StatusMask.DATA_AVAILABLE
    )

    participant.enable()

    msg_type = dds.QosProvider("msg.xml").type("builtin_topics_lib", "msg")
    topic = dds.DynamicData.Topic(participant, "Example msg", msg_type)
    writer = dds.DynamicData.DataWriter(dds.Publisher(participant), topic)
    instance = dds.DynamicData(msg_type)

    # write samples in a loop, incrementing the 'x' field
    count = 0
    while (sample_count == 0) or (count < sample_count):
        time.sleep(1)
        instance["x"] = count
        writer.write(instance, dds.InstanceHandle())
        count += 1
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    wssc_type = dds.QosProvider("waitset_cond.xml").type("wssc_lib", "Foo")
    topic = dds.DynamicData.Topic(participant, "Example Foo", wssc_type)
    writer = dds.DynamicData.DataWriter(dds.Publisher(participant), topic)

    sample = dds.DynamicData(wssc_type)

    count = 0
    while (sample_count == 0) or (count < sample_count):
        print("Writing Foo, count = {}".format(count))
        sample["x"] = count
        writer.write(sample)

        count += 1
        time.sleep(1)
Beispiel #5
0
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    cft_type = dds.QosProvider("cft.xml").type("cft_lib", "cft")
    topic = dds.DynamicData.Topic(participant, "Example cft", cft_type)

    writer_qos = dds.QosProvider.default.datawriter_qos
    writer = dds.DynamicData.DataWriter(dds.Publisher(participant), topic, writer_qos)

    sample = dds.DynamicData(cft_type)

    count = 0
    while (sample_count == 0) or (count < sample_count):
        print("Writing cft, count={}".format(count))
        sample["count"] = count
        sample["name"] = "ODD" if count % 2 == 1 else "EVEN"
        writer.write(sample)
        time.sleep(1)
        count += 1
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    # We can register the custom filter on the writer side
    participant.register_contentfilter(ccf.CustomFilterType(), "CustomFilter")

    ccf_type = dds.QosProvider("ccf.xml").type("ccf_lib", "Foo")
    topic = dds.DynamicData.Topic(participant, "Example ccf", ccf_type)

    writer = dds.DynamicData.DataWriter(dds.Publisher(participant), topic)

    instance = dds.DynamicData(ccf_type)

    count = 0
    while (sample_count == 0) or (count < sample_count):
        print("Writing ccf, count={}".format(count))
        instance["x"] = count
        writer.write(instance)
        time.sleep(1)
        count += 1
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    wsqc_type = dds.QosProvider("waitset_query_cond.xml").type(
        "wsqc_lib", "waitset_query_cond"
    )
    topic = dds.DynamicData.Topic(participant, "Example waitset_query_cond", wsqc_type)
    writer = dds.DynamicData.DataWriter(dds.Publisher(participant), topic)

    instance = dds.DynamicData(wsqc_type)

    count = 0
    while (sample_count == 0) or (count < sample_count):
        print("Writing waitset_query_cond, count = {}".format(count))
        instance["x"] = count
        instance["name"] = "ODD" if count % 2 == 1 else "EVEN"

        writer.write(instance)
        count += 1
        time.sleep(1)
Beispiel #8
0
    def __init__(self, domain_id, sample_type):
        self.participant = create_participant(domain_id)

        reader_qos = self.participant.implicit_subscriber.default_datareader_qos
        reader_qos << dds.Durability.transient_local
        reader_qos << dds.Reliability.reliable()
        reader_qos << dds.History.keep_all

        writer_qos = self.participant.implicit_publisher.default_datawriter_qos
        writer_qos << dds.Durability.transient_local
        writer_qos << dds.Reliability.reliable()
        writer_qos << dds.History.keep_all
        if sample_type == "StringTopicType":
            self.topic = dds.StringTopicType.Topic(self.participant,
                                                   "StringTopicType")
            self.reader = dds.StringTopicType.DataReader(
                self.participant, self.topic, reader_qos)
            self.writer = dds.StringTopicType.DataWriter(
                self.participant, self.topic, writer_qos)
        elif sample_type == "KeyedStringTopicType":
            self.topic = dds.KeyedStringTopicType.Topic(
                self.participant, "KeyedStringTopicType")
            self.reader = dds.KeyedStringTopicType.DataReader(
                self.participant, self.topic, reader_qos)
            self.writer = dds.KeyedStringTopicType.DataWriter(
                self.participant, self.topic, writer_qos)
        elif sample_type == "PerformanceTest":
            provider = dds.QosProvider(
                str(pathlib.Path(__file__).parent.absolute()) +
                "/../xml/PerfTest.xml")
            provider_type = provider.type("PerformanceTest")
            self.topic = dds.DynamicData.Topic(self.participant,
                                               "PerformanceTest",
                                               provider_type)
            self.reader = dds.DynamicData.DataReader(
                dds.Subscriber(self.participant), self.topic, reader_qos)
            self.writer = dds.DynamicData.DataWriter(
                dds.Publisher(self.participant), self.topic, writer_qos)
        else:
            raise Exception(sample_type + " not supported in test system")
Beispiel #9
0
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    cft_type = dds.QosProvider("cft.xml").type("cft_lib", "cft")
    topic = dds.DynamicData.Topic(participant, "Example cft", cft_type)

    writer_qos = dds.QosProvider.default.datawriter_qos
    writer = dds.DynamicData.DataWriter(dds.Publisher(participant), topic,
                                        writer_qos)

    instance = dds.DynamicData(cft_type)
    handle = dds.InstanceHandle.nil()

    # Output "ones" digit of count as 'x' field
    count = 0
    while (sample_count == 0) or (count < sample_count):
        instance["count"] = count
        instance["x"] = count % 10
        print("Writing cft, count={}\tx={}".format(instance["count"],
                                                   instance["x"]))
        writer.write(instance, handle)
        time.sleep(1)
        count += 1
Beispiel #10
0
def publisher_main(domain_id, sample_count):
    participant = dds.DomainParticipant(domain_id)

    publisher_qos = dds.QosProvider.default.publisher_qos
    publisher = dds.Publisher(participant, publisher_qos)

    coherent_type = dds.QosProvider("coherent.xml").type(
        "coherent_lib", "coherent")
    topic = dds.DynamicData.Topic(participant, "Example coherent",
                                  coherent_type)
    datawriter_qos = dds.QosProvider.default.datawriter_qos
    writer = dds.DynamicData.DataWriter(publisher, topic, datawriter_qos)

    sample = dds.DynamicData(coherent_type)
    sample["id"] = 0
    handle = writer.register_instance(sample)

    num_samples = 7
    count = 0
    while (sample_count == 0) or (count < sample_count):
        # Use a context manager to scope the coherent set writes
        with dds.CoherentSet(publisher):
            print("Begin Coherent Changes")

            for i in xrange(num_samples):
                time.sleep(1)
                sample["field"] = chr(ord("a") + i)
                sample["value"] = random.randint(0, 10)
                print("Updating instance, {}->{}".format(
                    sample["field"], sample["value"]))
                writer.write(sample, handle)
                count += 1

            print("End Coherent Changes")

    writer.unregister_instance(handle)
    def __init__(self, domain_id, use_dynamic_data, use_qos_object,
                 use_custom_topic, use_replier_cft, use_pub_sub_args,
                 use_callback_funcs, use_simple_replier):
        qos = dds.DomainParticipantQos()
        qos.database.shutdown_cleanup_period = dds.Duration.from_milliseconds(
            100)
        self._participant = dds.DomainParticipant(domain_id, qos)
        if use_dynamic_data:
            self._type = get_keyed_string_dynamic_type()
            self.create_data_fnc = create_dynamic_rr_data
            self.parse_data_fnc = parse_dynamic_rr_data
            self.copy_sample_fnc = copy_dynamic_sample
            create_topic_func = create_dynamic_topic
        else:
            self._type = type_cls = dds.KeyedStringTopicType
            self.create_data_fnc = create_rr_data
            self.parse_data_fnc = parse_rr_data
            self.copy_sample_fnc = copy_sample
            create_topic_func = create_topic

        service_name = 'Test'

        if use_qos_object:
            request_writer_qos = request.Requester.default_writer_qos
            request_reader_qos = request.Replier.default_reader_qos
            reply_writer_qos = request.Replier.default_writer_qos
            reply_reader_qos = request.Requester.default_reader_qos
        else:
            request_writer_qos = request_reader_qos = reply_writer_qos = reply_reader_qos = None

        if use_custom_topic:
            # Test with custom Topic object
            request_topic = create_topic_func(self._participant, 'TestRequest')
            # Test with custom string Topic name
            reply_topic = 'TestReply'
        else:
            request_topic = reply_topic = None

        if use_replier_cft:
            replier_filter = dds.Filter("NOT (key MATCH 'filtered')")
            request_reader_topic = create_topic_func(
                self._participant,
                'TestRequest') if request_topic is None else request_topic
            if isinstance(self._type, dds.DynamicType):
                request_reader_topic = dds.DynamicData.ContentFilteredTopic(
                    request_reader_topic, 'request_cft', replier_filter)
            else:
                request_reader_topic = dds.KeyedStringTopicType.ContentFilteredTopic(
                    request_reader_topic, 'request_cft', replier_filter)
        else:
            request_reader_topic = request_topic

        if use_pub_sub_args:
            publisher = dds.Publisher(self._participant)
            subscriber = dds.Subscriber(self._participant)
        else:
            publisher = subscriber = None

        self._cb = use_callback_funcs
        self._request_queue = queue.Queue()
        self._reply_queue = queue.Queue()
        if use_callback_funcs:

            def replier_callback(replier):
                for sample in (s for s in replier.take_requests()
                               if s.info.valid):
                    self._request_queue.put(self.copy_sample_fnc(sample))

            def requester_callback(requester):
                for sample in (s for s in requester.take_replies()
                               if s.info.valid):
                    self._reply_queue.put(self.copy_sample_fnc(sample))
        else:
            replier_callback = requester_callback = None

        self._requester = request.Requester(self._type, self._type,
                                            self._participant, service_name,
                                            request_topic, reply_topic,
                                            request_writer_qos,
                                            reply_reader_qos, publisher,
                                            subscriber, requester_callback)

        self._simple = use_simple_replier
        if use_simple_replier:

            def simple_replier_callback(request):
                key, value = self.parse_data_fnc(request)
                reply = self.create_data_fnc(key, value + ' reply')
                return reply

            self._replier = request.SimpleReplier(
                self._type, self._type, self._participant,
                simple_replier_callback, service_name, request_reader_topic,
                reply_topic, reply_writer_qos, request_reader_qos, publisher,
                subscriber)
        else:
            self._replier = request.Replier(self._type, self._type,
                                            self._participant, service_name,
                                            request_reader_topic, reply_topic,
                                            reply_writer_qos,
                                            request_reader_qos, publisher,
                                            subscriber, replier_callback)
def run_example(domain_id, sample_count, sensor_id):

    # A DomainParticipant allows an application to begin communicating in
    # a DDS domain. Typically there is one DomainParticipant per application.
    # DomainParticipant QoS is configured in USER_QOS_PROFILES.xml
    participant = dds.DomainParticipant(domain_id)

    # A Topic has a name and a datatype. Create a Topic named
    # "ChocolateTemperature" with type Temperature
    provider = dds.QosProvider(FILE)
    temperature_type = provider.type("Temperature")
    lot_status_kind_type = provider.type("LotStatusKind")

    topic = dds.DynamicData.Topic(
        participant, "ChocolateTemperature", temperature_type
    )

    # Exercise #2.1: Add a new Topic
    lot_state_type = provider.type("ChocolateLotState")
    lot_state_topic = dds.DynamicData.Topic(
        participant, "ChocolateLotState", lot_state_type
    )

    # A Publisher allows an application to create one or more DataWriters
    # Publisher QoS is configured in USER_QOS_PROFILES.xml
    publisher = dds.Publisher(participant)

    # This DataWriter writes data on Topic "ChocolateTemperature"
    # DataWriter QoS is configured in USER_QOS_PROFILES.xml
    writer = dds.DynamicData.DataWriter(publisher, topic)

    # Create data sample for writing
    temperature_sample = dds.DynamicData(temperature_type)

    # Exercise #2.2: Add new DataWriter and data sample
    lot_state_writer = dds.DynamicData.DataWriter(publisher, lot_state_topic)
    lot_state_sample = dds.DynamicData(lot_state_type)

    i = 0
    try:
        while sample_count is None or i < sample_count:
            # Modify the data to be written here
            temperature_sample["sensor_id"] = sensor_id
            # Generate a number x where 30 <= x <= 32
            temperature_sample["degrees"] = random.randint(30, 32)

            # Exercise #2.3: Write data with new ChocolateLotState DataWriter
            # Note: We're adding a writer but no reader, this exercise can be
            # viewed using rtiddsspy
            lot_state_sample["lot_id"] = i % 100
            lot_state_sample["lot_status"] = lot_status_kind_type[
                "PROCESSING"
            ].ordinal
            lot_state_writer.write(lot_state_sample)

            print(f"Writing ChocolateTemperature, count {i}")
            writer.write(temperature_sample)

            # Exercise 1.1: Change this to sleep 100 ms in between writing
            # temperatures
            time.sleep(4)

            i += 1

    except KeyboardInterrupt:
        pass
def run_example(domain_id, sensor_id):
    # A DomainParticipant allows an application to begin communicating in
    # a DDS domain. Typically there is one DomainParticipant per application.
    # DomainParticipant QoS is configured in USER_QOS_PROFILES.xml
    participant = dds.DomainParticipant(domain_id)

    # A Topic has a name and a datatype. Create Topics.
    # Topic names are constants defined in the XML file.
    temperature_topic = dds.DynamicData.Topic(participant,
                                              CHOCOLATE_TEMPERATURE_TOPIC,
                                              TEMPERATURE_TYPE)
    lot_state_topic = dds.DynamicData.Topic(participant,
                                            CHOCOLATE_LOT_STATE_TOPIC,
                                            CHOCOLATE_LOT_TYPE)

    # A Publisher allows an application to create one or more DataWriters
    # Publisher QoS is configured in USER_QOS_PROFILES.xml
    publisher = dds.Publisher(participant)

    # Create DataWriters of Topics "ChocolateTemperature" & "ChocolateLotState"
    # DataWriter QoS is configured in USER_QOS_PROFILES.xml
    temperature_writer = dds.DynamicData.DataWriter(publisher,
                                                    temperature_topic)
    lot_state_writer = dds.DynamicData.DataWriter(publisher, lot_state_topic)

    # A Subscriber allows an application to create one or more DataReaders
    # Subscriber QoS is configured in USER_QOS_PROFILES.xml
    subscriber = dds.Subscriber(participant)

    # Create DataReader of Topic "ChocolateLotState".
    # DataReader QoS is configured in USER_QOS_PROFILES.xml
    lot_state_reader = dds.DynamicData.DataReader(subscriber, lot_state_topic)

    # Obtain the DataReader's Status Condition
    status_condition = dds.StatusCondition(lot_state_reader)
    # Enable the 'data available' status.
    status_condition.enabled_statuses = dds.StatusMask.data_available()

    # Associate a handler with the status condition. This will run when the
    # condition is triggered, in the context of the dispatch call (see below)
    def handler(_):
        nonlocal lot_state_reader
        nonlocal lot_state_writer
        process_lot(lot_state_reader, lot_state_writer)

    # Create a WaitSet and attach the StatusCondition
    status_condition.set_handler(handler)

    waitset = dds.WaitSet()
    waitset += status_condition

    # Create a thread to periodically publish the temperature
    print(f"ChocolateTemperature Sensor with ID: {sensor_id} starting")
    temperature_thread = threading.Thread(target=publish_temperature,
                                          args=(temperature_writer, sensor_id))
    temperature_thread.start()
    try:
        while True:
            # Wait for ChocolateLotState
            print("Waiting for lot")
            waitset.dispatch(dds.Duration(10))  # Wait up to 10s for update
    except KeyboardInterrupt:
        pass

    temperature_thread.join()
Beispiel #14
0
def run_example(domain_id, lots_to_process, sensor_id):

    # A DomainParticipant allows an application to begin communicating in
    # a DDS domain. Typically there is one DomainParticipant per application.
    # DomainParticipant QoS is configured in USER_QOS_PROFILES.xml
    participant = dds.DomainParticipant(domain_id)

    # A Topic has a name and a datatype. Create a Topic with type
    # ChocolateLotState.  Topic name is a constant defined in the XML file.
    topic = dds.DynamicData.Topic(participant, CHOCOLATE_LOT_STATE_TOPIC,
                                  CHOCOLATE_LOT_TYPE)

    # Exercise #4.1: Add a Topic for Temperature to this application
    temperature_topic = dds.DynamicData.Topic(participant,
                                              CHOCOLATE_TEMPERATURE_TOPIC,
                                              provider.type("Temperature"))

    # A Publisher allows an application to create one or more DataWriters
    # Publisher QoS is configured in USER_QOS_PROFILES.xml
    publisher = dds.Publisher(participant)

    # This DataWriter writes data on Topic "ChocolateLotState"
    # DataWriter QoS is configured in USER_QOS_PROFILES.xml
    writer = dds.DynamicData.DataWriter(publisher, topic)

    # A Subscriber allows an application to create one or more DataReaders
    # Subscriber QoS is configured in USER_QOS_PROFILES.xml
    subscriber = dds.Subscriber(participant)

    # Create DataReader of Topic "ChocolateLotState".
    # DataReader QoS is configured in USER_QOS_PROFILES.xml
    reader = dds.DynamicData.DataReader(subscriber, topic)

    # Exercise #4.2: Add a DataReader for Temperature to this application
    temperature_reader = dds.DynamicData.DataReader(subscriber,
                                                    temperature_topic)

    # Obtain the DataReader's Status Condition
    status_condition = dds.StatusCondition(reader)
    # Enable the 'data available' status.
    status_condition.enabled_statuses = dds.StatusMask.data_available()

    # Associate a handler with the status condition. This will run when the
    # condition is triggered, in the context of the dispatch call (see below)
    lots_processed = 0

    def handler(_):
        nonlocal lots_processed
        nonlocal reader
        lots_processed += monitor_lot_state(reader)

    status_condition.set_handler(handler)

    temperature_status_condition = dds.StatusCondition(reader)

    temperature_status_condition.enabled_statuses = (
        dds.StatusMask.data_available())

    def temperature_handler(_):
        nonlocal temperature_reader
        monitor_lot_state(temperature_reader)

    temperature_status_condition.set_handler(temperature_handler)

    # Create a WaitSet and attach the StatusCondition
    waitset = dds.WaitSet()
    waitset += status_condition

    # Exercise #4.3: Add the new DataReader's StatusCondition to the Waitset
    waitset += temperature_status_condition

    # Create a thread to periodically publish the temperature
    start_lot_thread = threading.Thread(target=publish_start_lot,
                                        args=(writer, lots_to_process))
    start_lot_thread.start()
    try:
        while lots_to_process is None or lots_processed < lots_to_process:
            # Dispatch will call the handlers associated to the WaitSet conditions
            # when they activate
            waitset.dispatch(dds.Duration(4))  # Wait for up to 4s each time
    except KeyboardInterrupt:
        pass

    start_lot_thread.join()
def test_close_participant_contained_entities(implicit_pub, test_retain):
    p1 = utils.create_participant()
    p2 = utils.create_participant()
    topic1 = dds.StringTopicType.Topic(p1, "test_topic1")
    topic2 = dds.StringTopicType.Topic(p1, "test topic2")
    topic30 = dds.StringTopicType.Topic(p1, "test topic3")
    topic31 = dds.StringTopicType.Topic(p2, "test topic3")
    cft10 = dds.StringTopicType.ContentFilteredTopic(topic1, "cft10",
                                                     dds.Filter("value = '1'"))
    cft11 = dds.StringTopicType.ContentFilteredTopic(topic1, "cft11",
                                                     dds.Filter("value = '1'"))
    cft20 = dds.StringTopicType.ContentFilteredTopic(topic31, "cft20",
                                                     dds.Filter("value = '1'"))

    pub1 = None
    pub2 = None
    sub1 = None
    sub2 = None

    if not implicit_pub:
        pub1 = dds.Publisher(p1)
        pub2 = dds.Publisher(p2)
        sub1 = dds.Subscriber(p1)
        sub2 = dds.Subscriber(p2)
    else:
        pub1 = p1.implicit_publisher
        pub2 = p2.implicit_publisher
        sub1 = p1.implicit_subscriber
        sub2 = p2.implicit_subscriber

    writer10 = dds.StringTopicType.DataWriter(pub1, topic1)
    writer11 = dds.StringTopicType.DataWriter(pub1, topic1)
    writer20 = dds.StringTopicType.DataWriter(pub1, topic2)
    writer30 = dds.StringTopicType.DataWriter(pub1, topic30)
    writer31 = dds.StringTopicType.DataWriter(pub2, topic31)

    reader10 = dds.StringTopicType.DataReader(sub1, topic1)
    reader11 = dds.StringTopicType.DataReader(sub1, topic2)
    reader20 = dds.StringTopicType.DataReader(sub1, cft10)
    reader30 = dds.StringTopicType.DataReader(sub1, topic30)
    reader31 = dds.StringTopicType.DataReader(sub2, topic31)
    reader32 = dds.StringTopicType.DataReader(sub2, cft20)

    flow_controller10 = dds.FlowController(p1, "fc10")
    flow_controller11 = dds.FlowController(p1, "fc11")
    flow_controller12 = dds.FlowController(p1, "fc12")
    flow_controller20 = dds.FlowController(p2, "fc20")

    tq1 = dds.TopicQuery(
        reader10,
        dds.TopicQuerySelection(dds.Filter("value = '1' or value = '3'")))
    tq2 = dds.TopicQuery(
        reader31,
        dds.TopicQuerySelection(dds.Filter("value = '4' or value = '6'")))

    if test_retain:
        pub1.retain()
        reader11.retain()
        writer11.retain()
        topic2.retain()
        cft11.retain()
        flow_controller12.retain()
        tq1.retain()

    flow_controller12.close()
    p1.close()

    assert p1.closed

    assert pub1.closed
    assert sub1.closed
    assert not pub2.closed
    assert not sub2.closed

    assert topic1.closed
    assert topic2.closed
    assert topic30.closed
    assert not topic31.closed

    assert cft10.closed
    assert cft11.closed
    assert not cft20.closed

    assert writer10.closed
    assert writer11.closed
    assert writer20.closed
    assert writer30.closed
    assert not writer31.closed

    assert reader10.closed
    assert reader11.closed
    assert reader20.closed
    assert reader30.closed
    assert not reader31.closed

    assert flow_controller10.closed
    assert flow_controller11.closed
    assert flow_controller12.closed
    assert not flow_controller20.closed

    assert tq1.closed
    assert not tq2.closed