Skip to content

Cache flush bit test fails because ServiceInfo will use expired records from the cache #738

@bdraco

Description

@bdraco

    @pytest.mark.asyncio
    async def test_cache_flush_bit():
        """Test that the cache flush bit sets the TTL to one for matching records."""
        # instantiate a zeroconf instance
        aiozc = AsyncZeroconf(interfaces=['127.0.0.1'])
        zc = aiozc.zeroconf
    
        type_ = "_cacheflush._tcp.local."
        name = "knownname"
        registration_name = "%s.%s" % (name, type_)
        desc = {'path': '/~paulsm/'}
        server_name = "server-uu1.local."
        info = ServiceInfo(
            type_, registration_name, 80, 0, 0, desc, server_name, addresses=[socket.inet_aton("10.0.1.2")]
        )
        a_record = info.dns_addresses()[0]
        zc.cache.async_add_records([info.dns_pointer(), a_record, info.dns_text(), info.dns_service()])
    
        info.addresses = [socket.inet_aton("10.0.1.5"), socket.inet_aton("10.0.1.6")]
        new_records = info.dns_addresses()
        for new_record in new_records:
            assert new_record.unique is True
    
        original_a_record = zc.cache.async_get_unique(a_record)
        # Do the run within 1s to verify the original record is not going to be expired
        out = r.DNSOutgoing(const._FLAGS_QR_RESPONSE | const._FLAGS_AA, multicast=True)
        for answer in new_records:
            out.add_answer_at_time(answer, 0)
        for packet in out.packets():
            zc.record_manager.async_updates_from_response(r.DNSIncoming(packet))
        assert zc.cache.async_get_unique(a_record) is original_a_record
        assert original_a_record.ttl != 1
        for record in new_records:
            assert zc.cache.async_get_unique(record) is not None
    
        original_a_record.created = current_time_millis() - 1001
    
        # Do the run within 1s to verify the original record is not going to be expired
        out = r.DNSOutgoing(const._FLAGS_QR_RESPONSE | const._FLAGS_AA, multicast=True)
        for answer in new_records:
            out.add_answer_at_time(answer, 0)
        for packet in out.packets():
            zc.record_manager.async_updates_from_response(r.DNSIncoming(packet))
        assert original_a_record.ttl == 1
        for record in new_records:
            assert zc.cache.async_get_unique(record) is not None
    
        cached_records = [zc.cache.async_get_unique(record) for record in new_records]
        for record in cached_records:
            record.created = current_time_millis() - 1001
    
        fresh_address = socket.inet_aton("4.4.4.4")
        info.addresses = [fresh_address]
        # Do the run within 1s to verify the two new records get marked as expired
        out = r.DNSOutgoing(const._FLAGS_QR_RESPONSE | const._FLAGS_AA, multicast=True)
        for answer in info.dns_addresses():
            out.add_answer_at_time(answer, 0)
        for packet in out.packets():
            zc.record_manager.async_updates_from_response(r.DNSIncoming(packet))
        for record in cached_records:
            assert record.ttl == 1
    
        for entry in zc.cache.async_all_by_details(server_name, const._TYPE_A, const._CLASS_IN):
            if entry.address == fresh_address:
                assert entry.ttl > 1
            else:
                assert entry.ttl == 1
    
        # Wait for the ttl 1 records to expire
        await asyncio.sleep(1.01)
    
        loaded_info = r.ServiceInfo(type_, registration_name)
        loaded_info.load_from_cache(zc)
>       assert loaded_info.addresses == info.addresses
E       AssertionError: assert [b'\n\x00\x01...\x04\x04\x04'] == [b'\x04\x04\x04\x04']
E         At index 0 diff: b'\n\x00\x01\x02' != b'\x04\x04\x04\x04'
E         Left contains 3 more items, first extra item: b'\n\x00\x01\x05'
E         Full diff:
E         - [b'\x04\x04\x04\x04']
E         + [b'\n\x00\x01\x02', b'\n\x00\x01\x05', b'\n\x00\x01\x06', b'\x04\x04\x04\x04']

tests\test_handlers.py:915: AssertionError

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions