mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-17 08:53:28 -05:00
fix: tell a local DNS outage from a gone host
This commit is contained in:
1 parent
cd4a9143f7
commit
08aa0beb22
2 files changed
+36
-6
No files matched your search
+18
-1
@@ -208,12 +208,29 @@ def _host_is_unresolvable(exc: BaseException) -> bool:
|
||||
if seen is None:
|
||||
break
|
||||
if isinstance(seen, socket.gaierror):
|
||||
return True
|
||||
# A resolver that answers nothing at all is the local network:
|
||||
# every profile would read as gone, and the sweep would report
|
||||
# nothing to review while it reviewed nothing.
|
||||
return seen.errno == socket.EAI_NONAME and _resolver_answers()
|
||||
nested = getattr(seen, "reason", None)
|
||||
seen = nested if isinstance(nested, BaseException) else seen.__cause__
|
||||
return False
|
||||
|
||||
|
||||
# A name every forge call depends on: if it does not resolve, the fault is
|
||||
# local and no host can be declared gone.
|
||||
RESOLVER_PROBE = "github.com"
|
||||
|
||||
|
||||
def _resolver_answers() -> bool:
|
||||
"""Whether name resolution works here at all. Replaced in tests."""
|
||||
try:
|
||||
socket.getaddrinfo(RESOLVER_PROBE, 443)
|
||||
except OSError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _fetch(url: str, accept_json: bool = False) -> bytes | None:
|
||||
"""Body of a GET, or None on 404.
|
||||
|
||||
|
||||
+18
-5
@@ -9,6 +9,7 @@ import sys
|
||||
import tempfile
|
||||
import socket
|
||||
import unittest
|
||||
from unittest import mock
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
@@ -291,14 +292,26 @@ class TestGoneUpstream(unittest.TestCase):
|
||||
self.assertEqual(self.calls, 1)
|
||||
|
||||
def test_unresolvable_host_is_gone_and_not_retried(self):
|
||||
self._serve(
|
||||
urllib.error.URLError(socket.gaierror(-2, "Name or service not known"))
|
||||
)
|
||||
with self.assertRaises(upstream.GoneError):
|
||||
upstream._fetch("https://host/x")
|
||||
self._serve(urllib.error.URLError(
|
||||
socket.gaierror(socket.EAI_NONAME, "Name or service not known")
|
||||
))
|
||||
with mock.patch.object(upstream, "_resolver_answers", return_value=True):
|
||||
with self.assertRaises(upstream.GoneError):
|
||||
upstream._fetch("https://host/x")
|
||||
self.assertEqual(self.calls, 1)
|
||||
self.assertEqual(self.slept, [])
|
||||
|
||||
def test_a_local_resolver_outage_is_not_gone(self):
|
||||
"""With DNS down here, every forge looked gone and profile_sync
|
||||
listed nothing to review, exiting 0."""
|
||||
for errno, resolver in ((socket.EAI_NONAME, False), (socket.EAI_AGAIN, True)):
|
||||
with self.subTest(errno=errno, resolver=resolver):
|
||||
self._serve(urllib.error.URLError(socket.gaierror(errno, "no")))
|
||||
with mock.patch.object(upstream, "_resolver_answers", return_value=resolver):
|
||||
with self.assertRaises(upstream.UpstreamError) as caught:
|
||||
upstream._fetch("https://host/x")
|
||||
self.assertNotIsInstance(caught.exception, upstream.GoneError)
|
||||
|
||||
def test_a_gone_error_is_still_an_upstream_error(self):
|
||||
self._serve(_http_error(451))
|
||||
with self.assertRaises(upstream.UpstreamError):
|
||||
|
||||
Reference in new issue
Block a user