@@ -628,3 +628,49 @@ async def test_dns_resolver_manager_multiple_event_loops(
628
628
# Verify resolver cleanup
629
629
resolver1 .cancel .assert_called_once ()
630
630
resolver2 .cancel .assert_called_once ()
631
+
632
+
633
+ @pytest .mark .skipif (not getaddrinfo , reason = "aiodns >=3.2.0 required" )
634
+ async def test_dns_resolver_manager_weakref_garbage_collection () -> None :
635
+ """Test that release_resolver handles None resolver due to weakref garbage collection."""
636
+ manager = _DNSResolverManager ()
637
+
638
+ # Create a mock resolver that will be None when accessed
639
+ mock_resolver = Mock ()
640
+ mock_resolver .cancel = Mock ()
641
+
642
+ with patch ("aiodns.DNSResolver" , return_value = mock_resolver ):
643
+ # Create an AsyncResolver to get a resolver from the manager
644
+ resolver = AsyncResolver ()
645
+ loop = asyncio .get_running_loop ()
646
+
647
+ # Manually corrupt the data to simulate garbage collection
648
+ # by setting the resolver to None
649
+ manager ._loop_data [loop ] = (None , manager ._loop_data [loop ][1 ]) # type: ignore[assignment]
650
+
651
+ # This should not raise an AttributeError: 'NoneType' object has no attribute 'cancel'
652
+ await resolver .close ()
653
+
654
+ # Verify no exception was raised and the loop data was cleaned up properly
655
+ # Since we set resolver to None and there was one client, the entry should be removed
656
+ assert loop not in manager ._loop_data
657
+
658
+
659
+ @pytest .mark .skipif (not getaddrinfo , reason = "aiodns >=3.2.0 required" )
660
+ async def test_dns_resolver_manager_missing_loop_data () -> None :
661
+ """Test that release_resolver handles missing loop data gracefully."""
662
+ manager = _DNSResolverManager ()
663
+
664
+ with patch ("aiodns.DNSResolver" ):
665
+ # Create an AsyncResolver
666
+ resolver = AsyncResolver ()
667
+ loop = asyncio .get_running_loop ()
668
+
669
+ # Manually remove the loop data to simulate race condition
670
+ manager ._loop_data .clear ()
671
+
672
+ # This should not raise a KeyError
673
+ await resolver .close ()
674
+
675
+ # Verify no exception was raised
676
+ assert loop not in manager ._loop_data
0 commit comments