From 8a6253a43a43084275b31ef05e674e4987b05a84 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrangé" Date: Tue, 17 Dec 2024 15:59:23 +0000 Subject: tests/functional: remove many unused imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Identified using 'pylint --disable=all --enable=W0611' Reviewed-by: Thomas Huth Signed-off-by: Daniel P. Berrangé Message-ID: <20241217155953.3950506-3-berrange@redhat.com> Signed-off-by: Thomas Huth --- tests/functional/qemu_test/asset.py | 1 - 1 file changed, 1 deletion(-) (limited to 'tests/functional/qemu_test/asset.py') diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index f126cd5863..559af0351f 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -9,7 +9,6 @@ import hashlib import logging import os import stat -import subprocess import sys import unittest import urllib.request -- cgit 1.4.1 From c27f452d61a4741605da2e03c0e6c756dd249f25 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrangé" Date: Tue, 17 Dec 2024 15:59:24 +0000 Subject: tests/functional: resolve str(Asset) to cache file path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow an Asset object to be used in place of a filename but making its string representation resolve to the cache file path. Signed-off-by: Daniel P. Berrangé Reviewed-by: Richard Henderson Message-ID: <20241217155953.3950506-4-berrange@redhat.com> Signed-off-by: Thomas Huth --- tests/functional/qemu_test/asset.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests/functional/qemu_test/asset.py') diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index 559af0351f..c5d3e73c4b 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -39,6 +39,9 @@ class Asset: return "Asset: url=%s hash=%s cache=%s" % ( self.url, self.hash, self.cache_file) + def __str__(self): + return str(self.cache_file) + def _check(self, cache_file): if self.hash is None: return True -- cgit 1.4.1 From 6ff217c2d1c231f727c1be356da4a71cdfdd7ec5 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrangé" Date: Tue, 17 Dec 2024 15:59:51 +0000 Subject: tests/functional: skip tests if assets are not available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If downloading of assets has been disabled, then skip running a test if the assets it has registered are not already downloaded. Reviewed-by: Thomas Huth Signed-off-by: Daniel P. Berrangé Message-ID: <20241217155953.3950506-31-berrange@redhat.com> Signed-off-by: Thomas Huth --- tests/functional/qemu_test/asset.py | 8 +++++++- tests/functional/qemu_test/testcase.py | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'tests/functional/qemu_test/asset.py') diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index c5d3e73c4b..39832b2587 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -65,6 +65,12 @@ class Asset: def valid(self): return self.cache_file.exists() and self._check(self.cache_file) + def fetchable(self): + return not os.environ.get("QEMU_TEST_NO_DOWNLOAD", False) + + def available(self): + return self.valid() or self.fetchable() + def _wait_for_other_download(self, tmp_cache_file): # Another thread already seems to download the asset, so wait until # it is done, while also checking the size to see whether it is stuck @@ -103,7 +109,7 @@ class Asset: self.cache_file, self.url) return str(self.cache_file) - if os.environ.get("QEMU_TEST_NO_DOWNLOAD", False): + if not self.fetchable(): raise Exception("Asset cache is invalid and downloads disabled") self.log.info("Downloading %s to %s...", self.url, self.cache_file) diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py index aa6c9c0d64..869f3949fe 100644 --- a/tests/functional/qemu_test/testcase.py +++ b/tests/functional/qemu_test/testcase.py @@ -184,6 +184,14 @@ class QemuBaseTest(unittest.TestCase): def log_file(self, *args): return str(Path(self.outputdir, *args)) + def assets_available(self): + for name, asset in vars(self.__class__).items(): + if name.startswith("ASSET_") and type(asset) == Asset: + if not asset.available(): + self.log.debug(f"Asset {asset.url} not available") + return False + return True + def setUp(self, bin_prefix): self.assertIsNotNone(self.qemu_bin, 'QEMU_TEST_QEMU_BINARY must be set') self.arch = self.qemu_bin.split('-')[-1] @@ -209,6 +217,9 @@ class QemuBaseTest(unittest.TestCase): self.machinelog.setLevel(logging.DEBUG) self.machinelog.addHandler(self._log_fh) + if not self.assets_available(): + self.skipTest('One or more assets is not available') + def tearDown(self): if "QEMU_TEST_KEEP_SCRATCH" not in os.environ: shutil.rmtree(self.workdir) -- cgit 1.4.1 From 674a750b51df188d6baf55f1f1f8fc6f57fcf6cf Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrangé" Date: Tue, 17 Dec 2024 15:59:52 +0000 Subject: tests/functional: ignore errors when caching assets, except for 404 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We see periodic errors caching assets due to a combination of transient networking and server problems. With the previous patch to skip running a test when it has missing assets, we can now treat most cache download errors as non-fatal. Only HTTP 404 is retained as fatal, since it is a strong indicator of a fully broken test rather than a transient error. Reviewed-by: Thomas Huth Signed-off-by: Daniel P. Berrangé Message-ID: <20241217155953.3950506-32-berrange@redhat.com> Signed-off-by: Thomas Huth --- tests/functional/qemu_test/asset.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'tests/functional/qemu_test/asset.py') diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index 39832b2587..f0730695f0 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -15,6 +15,7 @@ import urllib.request from time import sleep from pathlib import Path from shutil import copyfileobj +from urllib.error import HTTPError # Instances of this class must be declared as class level variables @@ -170,7 +171,18 @@ class Asset: for name, asset in vars(test.__class__).items(): if name.startswith("ASSET_") and type(asset) == Asset: log.info("Attempting to cache '%s'" % asset) - asset.fetch() + try: + asset.fetch() + except HTTPError as e: + # Treat 404 as fatal, since it is highly likely to + # indicate a broken test rather than a transient + # server or networking problem + if e.code == 404: + raise + + log.debug(f"HTTP error {e.code} from {asset.url} " + + "skipping asset precache") + log.removeHandler(handler) def precache_suite(suite): -- cgit 1.4.1