From 28efc73112f747f4d77a84872236823d93b25683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20M=C3=BCller?= Date: Wed, 4 Nov 2026 20:03:37 +0100 Subject: [PATCH] tests: let name resolution fail immediately in test_gui_start_with_bad_server On the Windows runners, each lookup of the non-existent host WRONG-dcor-dev.mpl.mpg.de took about 37 s. DCOR-Aid resolves it 31 times during startup and shutdown, so the test took 20 minutes there (45 s on Linux), which looked like a hanging test suite. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG | 2 ++ tests/common.py | 23 +++++++++++++++++++++++ tests/test_gui.py | 23 ++++++++++++----------- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 33fc7e9..f62400d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -69,6 +69,8 @@ automatically created test user - tests: clear persistent upload jobs before and after each GUI test, so that new main windows do not upload jobs of previous tests again + - tests: let name resolution fail immediately in + `test_gui_start_with_bad_server` (took 20 minutes on Windows) 1.1.3 - enh: use `HTTPAdapter` with `urlib3`'s `Retry` to handle connection issues - enh: use `requests.Session` when caching is disabled diff --git a/tests/common.py b/tests/common.py index 2bede64..c6ebbc0 100644 --- a/tests/common.py +++ b/tests/common.py @@ -1,10 +1,13 @@ +import contextlib import datetime import functools import json import os import pathlib import shutil +import socket import tempfile +from unittest import mock import uuid import warnings @@ -25,6 +28,26 @@ tpath = pathlib.Path(__file__).parent / "data" / "text_file.txt" +@contextlib.contextmanager +def fail_name_resolution(host_part): + """Let name resolution of hosts containing `host_part` fail immediately + + On the Windows GitHub Actions runners, resolving the non-existent host + "WRONG-dcor-dev.mpl.mpg.de" took about half a minute per lookup, which + made `test_gui_start_with_bad_server` take 20 minutes. + """ + getaddrinfo = socket.getaddrinfo + + def getaddrinfo_fail(host, *args, **kwargs): + if host_part in str(host).lower(): + raise socket.gaierror(socket.EAI_NONAME, + "Name or service not known") + return getaddrinfo(host, *args, **kwargs) + + with mock.patch("socket.getaddrinfo", side_effect=getaddrinfo_fail): + yield + + def get_api(): api = CKANAPI(server=SERVER, api_key=get_api_key(), ssl_verify=True) return api diff --git a/tests/test_gui.py b/tests/test_gui.py index 560a24b..804dbb7 100644 --- a/tests/test_gui.py +++ b/tests/test_gui.py @@ -192,17 +192,18 @@ def test_gui_start_with_bad_server(qtbot): settings = QtCore.QSettings() settings.setValue("auth/server", "WRONG-dcor-dev.mpl.mpg.de") try: - mw = DCORAid() - qtbot.addWidget(mw) - QtWidgets.QApplication.setActiveWindow(mw) - QtWidgets.QApplication.processEvents( - QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 200) - # just make sure that DCOR-Aid thinks it is offline - assert not mw.ui.panel_upload.isEnabled() - assert not mw.ui.panel_download.isEnabled() - mw.close() - QtWidgets.QApplication.processEvents( - QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 200) + with common.fail_name_resolution("wrong-dcor-dev"): + mw = DCORAid() + qtbot.addWidget(mw) + QtWidgets.QApplication.setActiveWindow(mw) + QtWidgets.QApplication.processEvents( + QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 200) + # just make sure that DCOR-Aid thinks it is offline + assert not mw.ui.panel_upload.isEnabled() + assert not mw.ui.panel_download.isEnabled() + mw.close() + QtWidgets.QApplication.processEvents( + QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 200) finally: # reset to testing defaults settings.setValue("auth/server", common.SERVER)