From c68feee2cad7ea082c91fe662c57cfe68e3cced3 Mon Sep 17 00:00:00 2001 From: Achraf Maghous Date: Sun, 16 Feb 2025 11:03:18 +0100 Subject: [PATCH 1/4] chore: fixing unit test case sensitivity Handling filesystem specific case sensitivity, by creating temporary files and checking if they point towards same file using their inodes. This fixes #992 Signed-off-by: Achraf Maghous --- tests/artifact/test_local_artifact.py | 37 +++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/tests/artifact/test_local_artifact.py b/tests/artifact/test_local_artifact.py index 0f0bbd270..01885d8b0 100644 --- a/tests/artifact/test_local_artifact.py +++ b/tests/artifact/test_local_artifact.py @@ -1,9 +1,10 @@ -# Copyright (c) 2024 - 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2024 - 2025, Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. """Test the local artifact utilities.""" import os +import tempfile from pathlib import Path import pytest @@ -18,6 +19,18 @@ from macaron.errors import LocalArtifactFinderError +def is_case_sensitive_filesystem() -> bool: + """Check if current filesystem is case-sensitive.""" + with tempfile.NamedTemporaryFile(prefix="Tmp") as tmp: + base = tmp.name + lower = base.lower() + upper = base.upper() + + return not (os.path.exists(lower) or os.path.exists(upper)) or ( + os.path.exists(lower) and os.path.exists(upper) and os.stat(lower).st_ino != os.stat(upper).st_ino + ) + + @pytest.mark.parametrize( ("purl_str", "expectation"), [ @@ -205,13 +218,21 @@ def test_get_local_artifact_paths_succeeded_pypi(tmp_path: Path) -> None: python_venv_path = f"{tmp_path_str}/.venv/lib/python3.11/site-packages" # We are also testing if the patterns match case-insensitively. - pypi_artifact_paths = [ - f"{python_venv_path}/macaron", - f"{python_venv_path}/macaron-0.13.0.dist-info", - f"{python_venv_path}/Macaron-0.13.0.dist-info", - f"{python_venv_path}/macaron-0.13.0.data", - f"{python_venv_path}/Macaron-0.13.0.data", - ] + + if not is_case_sensitive_filesystem(): + pypi_artifact_paths = [ + f"{python_venv_path}/macaron", + f"{python_venv_path}/macaron-0.13.0.dist-info", + f"{python_venv_path}/macaron-0.13.0.data", + ] + else: + pypi_artifact_paths = [ + f"{python_venv_path}/macaron", + f"{python_venv_path}/macaron-0.13.0.dist-info", + f"{python_venv_path}/Macaron-0.13.0.dist-info", + f"{python_venv_path}/macaron-0.13.0.data", + f"{python_venv_path}/Macaron-0.13.0.data", + ] os.makedirs(python_venv_path) From 6a3a1320af0b0ca0251be26719755631a2f0369a Mon Sep 17 00:00:00 2001 From: Achraf Maghous Date: Mon, 17 Feb 2025 13:30:11 +0100 Subject: [PATCH 2/4] chore: refactoring is_case_sensitive_filesystem using tmp_path Using tmp_path made the use of st_ino obselete, now we create paths using touch method Signed-off-by: Achraf Maghous --- tests/artifact/test_local_artifact.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tests/artifact/test_local_artifact.py b/tests/artifact/test_local_artifact.py index 01885d8b0..260a1c566 100644 --- a/tests/artifact/test_local_artifact.py +++ b/tests/artifact/test_local_artifact.py @@ -4,7 +4,6 @@ """Test the local artifact utilities.""" import os -import tempfile from pathlib import Path import pytest @@ -21,14 +20,21 @@ def is_case_sensitive_filesystem() -> bool: """Check if current filesystem is case-sensitive.""" - with tempfile.NamedTemporaryFile(prefix="Tmp") as tmp: - base = tmp.name - lower = base.lower() - upper = base.upper() - - return not (os.path.exists(lower) or os.path.exists(upper)) or ( - os.path.exists(lower) and os.path.exists(upper) and os.stat(lower).st_ino != os.stat(upper).st_ino - ) + tmp_path = Path(".") + + # using "/" overloaded operator as __truediv__ in Path class to build a lower and upper path + lower = tmp_path / "a" + upper = tmp_path / "A" + + try: + lower.touch() + upper.touch() + return not upper.exists() + finally: + if lower.exists(): + lower.unlink() + if upper.exists(): + upper.unlink() @pytest.mark.parametrize( From 0814d218177660259b6844a8046ef27518d4708c Mon Sep 17 00:00:00 2001 From: Achraf Maghous Date: Tue, 18 Feb 2025 11:31:39 +0100 Subject: [PATCH 3/4] chore: checking filesystem case sensitivity without helper function Fixed checking case sensitivity using tmp_path, without needing to clean up created temporary files by using the existing tmp_path function argument already provided in test_get_local_artifact_paths_succeeded_pypi Signed-off-by: Achraf Maghous --- tests/artifact/test_local_artifact.py | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/tests/artifact/test_local_artifact.py b/tests/artifact/test_local_artifact.py index 260a1c566..279caf084 100644 --- a/tests/artifact/test_local_artifact.py +++ b/tests/artifact/test_local_artifact.py @@ -18,25 +18,6 @@ from macaron.errors import LocalArtifactFinderError -def is_case_sensitive_filesystem() -> bool: - """Check if current filesystem is case-sensitive.""" - tmp_path = Path(".") - - # using "/" overloaded operator as __truediv__ in Path class to build a lower and upper path - lower = tmp_path / "a" - upper = tmp_path / "A" - - try: - lower.touch() - upper.touch() - return not upper.exists() - finally: - if lower.exists(): - lower.unlink() - if upper.exists(): - upper.unlink() - - @pytest.mark.parametrize( ("purl_str", "expectation"), [ @@ -224,8 +205,11 @@ def test_get_local_artifact_paths_succeeded_pypi(tmp_path: Path) -> None: python_venv_path = f"{tmp_path_str}/.venv/lib/python3.11/site-packages" # We are also testing if the patterns match case-insensitively. + lower = tmp_path / "a" + upper = tmp_path / "A" - if not is_case_sensitive_filesystem(): + is_fs_case_sensitive: bool = lower.exists() and not upper.exists() + if not is_fs_case_sensitive: pypi_artifact_paths = [ f"{python_venv_path}/macaron", f"{python_venv_path}/macaron-0.13.0.dist-info", From 6b1d34e75be83ae824e137869301706655ad9087 Mon Sep 17 00:00:00 2001 From: Achraf Maghous Date: Wed, 19 Feb 2025 10:53:45 +0100 Subject: [PATCH 4/4] chore: opting for standalone function to check filesystem case sensitivity Using tempfile builtin package in order to check case sensitivity by observing the behavior of when creating lower and upper directory Signed-off-by: Achraf Maghous --- tests/artifact/test_local_artifact.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/artifact/test_local_artifact.py b/tests/artifact/test_local_artifact.py index 279caf084..1468bef42 100644 --- a/tests/artifact/test_local_artifact.py +++ b/tests/artifact/test_local_artifact.py @@ -4,6 +4,7 @@ """Test the local artifact utilities.""" import os +import tempfile from pathlib import Path import pytest @@ -18,6 +19,23 @@ from macaron.errors import LocalArtifactFinderError +def is_case_sensitive_filesystem() -> bool: + """Check if the filesystem is case-sensitive.""" + with tempfile.TemporaryDirectory() as temp_dir: + lower = os.path.join(temp_dir, "a") + upper = os.path.join(temp_dir, "A") + + os.mkdir(lower) + + try: + os.mkdir(upper) + # if upper is not treated the same as lower -> case sensitive + return True + except FileExistsError: + # upper is treated the same as lower -> case insensitive + return False + + @pytest.mark.parametrize( ("purl_str", "expectation"), [ @@ -205,11 +223,7 @@ def test_get_local_artifact_paths_succeeded_pypi(tmp_path: Path) -> None: python_venv_path = f"{tmp_path_str}/.venv/lib/python3.11/site-packages" # We are also testing if the patterns match case-insensitively. - lower = tmp_path / "a" - upper = tmp_path / "A" - - is_fs_case_sensitive: bool = lower.exists() and not upper.exists() - if not is_fs_case_sensitive: + if not is_case_sensitive_filesystem(): pypi_artifact_paths = [ f"{python_venv_path}/macaron", f"{python_venv_path}/macaron-0.13.0.dist-info",