From 3baba0c81cbf1878336e3dbb684f2dcbf82a150c Mon Sep 17 00:00:00 2001 From: Jathavedhan M Date: Mon, 11 May 2026 17:02:59 +0530 Subject: [PATCH] fix: move multiprocessing_start_method_fork fixture to shared conftest On Python 3.14, the default multiprocessing start method changed from fork to forkserver (python/cpython#132898), which requires all Process arguments to be picklable. The unprivileged_client Kubernetes client object contains thread locks and closures that cannot be pickled, causing _pickle.PicklingError in test_successful_concurrent_uploads. Move the multiprocessing_start_method_fork fixture from tests/chaos/conftest.py to tests/conftest.py so it can be reused across test directories, and apply it to the affected upload test. Changes: - Move fixture to tests/conftest.py (shared across all test dirs) - Remove duplicate from tests/chaos/conftest.py - Add @pytest.mark.usefixtures("multiprocessing_start_method_fork") to test_successful_concurrent_uploads in test_upload.py - Existing chaos consumers (test_standard, test_snapshot, test_migration) resolve the fixture from the parent conftest Signed-off-by: Jathavedhan M --- tests/chaos/conftest.py | 11 ----------- tests/conftest.py | 17 +++++++++++++++++ tests/storage/cdi_upload/test_upload.py | 1 + 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/tests/chaos/conftest.py b/tests/chaos/conftest.py index 5a2da68652..bc75e0c95c 100644 --- a/tests/chaos/conftest.py +++ b/tests/chaos/conftest.py @@ -406,14 +406,3 @@ def deleted_pod_by_name_prefix(admin_client, cnv_pod_deletion_test_matrix__class namespace=pod_deletion_config["namespace_name"], pod_prefix=pod_deletion_config["pod_prefix"], ) - - -@pytest.fixture(scope="module") -def multiprocessing_start_method_fork(): - # Use fork context to avoid pickling issues with nested functions - # https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Process - # https://github.com/python/cpython/issues/132898 - original_start_method = multiprocessing.get_start_method() - multiprocessing.set_start_method("fork", force=True) - yield - multiprocessing.set_start_method(original_start_method, force=True) diff --git a/tests/conftest.py b/tests/conftest.py index a15cdf1155..82e9e9eafd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,6 +4,7 @@ import copy import logging +import multiprocessing import os import os.path import re @@ -227,6 +228,22 @@ AUDIT_LOG_PATTERN = re.compile(r"audit-(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2}\.\d{3})\.log") +@pytest.fixture(scope="module") +def multiprocessing_start_method_fork(): + """Temporarily set multiprocessing start method to ``fork``. + + Side effects: + Changes the process-global multiprocessing start method to ``fork`` + for the module lifetime, then restores the previous method on teardown. + """ + # https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Process + # https://github.com/python/cpython/issues/132898 + original_start_method = multiprocessing.get_start_method() + multiprocessing.set_start_method("fork", force=True) + yield + multiprocessing.set_start_method(original_start_method, force=True) + + @pytest.fixture(scope="session") def junitxml_polarion(record_testsuite_property): """ diff --git a/tests/storage/cdi_upload/test_upload.py b/tests/storage/cdi_upload/test_upload.py index f1a1e5f8b4..74d856201c 100644 --- a/tests/storage/cdi_upload/test_upload.py +++ b/tests/storage/cdi_upload/test_upload.py @@ -284,6 +284,7 @@ def _upload_image(dv_name, namespace, storage_class, local_name, client): @pytest.mark.sno @pytest.mark.s390x @pytest.mark.polarion("CNV-2015") +@pytest.mark.usefixtures("multiprocessing_start_method_fork") @pytest.mark.parametrize( "upload_file_path", [