Files
voculinux/tests/test_cross_distro_compatibility.py
T
Jatin K MalikandGitHub 04eada775b feat: Phase 5 & 6 - Complete cross-distro compatibility fixes (#168)
Phase 5: Fix remaining hardcoded GI_TYPELIB_PATH values
- install.sh: Use dynamic GI_TYPELIB_DETECTED in package verification (line 1208)
- install.sh: Use dynamic path in desktop entry Exec line (line 1651)
- CI workflow: Use pkg-config for dynamic GI_TYPELIB_PATH detection (line 151)

Phase 6: Testing & validation improvements
- Add comprehensive test_cross_distro_compatibility.py test suite
- Tests verify no hardcoded paths, dynamic detection works, wrapper scripts correct
- Update DISTRO_COMPATIBILITY.md with implementation status and technical details

Fixes #157 (remaining issues)
Related to #48 (Snap packaging)
2026-02-09 21:07:25 -08:00

196 lines
8.2 KiB
Python

"""
Test cross-distro compatibility features.
This module tests the cross-distribution compatibility features including:
- Dynamic GI_TYPELIB_PATH detection
- Wrapper script generation with correct paths
- Desktop entry configuration
"""
import os
from pathlib import Path
import pytest
def get_repo_root() -> Path:
"""Get the repository root directory."""
# Start from current file and traverse up to find repo root
current = Path(__file__).resolve()
for parent in [current] + list(current.parents):
# Check for common repo indicators
if (parent / ".git").exists() or (parent / "install.sh").exists():
return parent
# Also check if we're in a 'vocalinux' subdirectory (CI structure)
if parent.name == "vocalinux" and (parent.parent / "vocalinux" / "install.sh").exists():
return parent.parent / "vocalinux"
# Fallback: use parent of tests directory
return current.parent.parent.parent
REPO_ROOT = get_repo_root()
class TestCrossDistroCompatibility:
"""Test cross-distro compatibility features."""
@pytest.fixture
def install_sh_content(self):
"""Fixture to load install.sh content."""
install_sh_path = REPO_ROOT / "install.sh"
if not install_sh_path.exists():
pytest.skip(f"install.sh not found at {install_sh_path}")
return install_sh_path.read_text()
@pytest.fixture
def workflow_content(self):
"""Fixture to load workflow content."""
workflow_path = REPO_ROOT / ".github" / "workflows" / "unified-pipeline.yml"
if not workflow_path.exists():
pytest.skip(f"Workflow file not found at {workflow_path}")
return workflow_path.read_text()
def test_detect_typelib_path_function_exists(self, install_sh_content):
"""Test that detect_typelib_path function exists in install.sh."""
assert (
"detect_typelib_path()" in install_sh_content
), "detect_typelib_path function should exist"
assert (
"pkg-config --variable=typelibdir" in install_sh_content
), "Should use pkg-config for detection"
def test_no_hardcoded_gi_typelib_path_in_verification(self, install_sh_content):
"""Test that package verification uses dynamic GI_TYPELIB_PATH."""
# The verification function should use the detected path, not hardcoded
assert (
"verify_package_installed()" in install_sh_content
), "verify_package_installed function should exist"
# Check that it uses GI_TYPELIB_DETECTED variable
verify_section = install_sh_content[
install_sh_content.find("verify_package_installed()") : install_sh_content.find(
"verify_package_installed()"
)
+ 500
]
assert (
"GI_TYPELIB_DETECTED" in verify_section or '"$GI_TYPELIB_DETECTED"' in verify_section
), "verify_package_installed should use GI_TYPELIB_DETECTED variable"
def test_wrapper_script_uses_detected_path(self, install_sh_content):
"""Test that wrapper scripts use the detected GI_TYPELIB_PATH."""
# Check that wrapper script creation uses GI_TYPELIB_DETECTED
assert (
"export GI_TYPELIB_PATH=$GI_TYPELIB_DETECTED" in install_sh_content
), "Wrapper script should export GI_TYPELIB_PATH with detected value"
def test_desktop_entry_uses_detected_path(self, install_sh_content):
"""Test that desktop entry uses detected GI_TYPELIB_PATH."""
# The sed command for desktop entry should use the detected path
assert (
"GI_TYPELIB_PATH=$GI_TYPELIB_DETECTED" in install_sh_content
or "GI_TYPELIB_PATH=\${GI_TYPELIB_DETECTED}" in install_sh_content
), "Desktop entry sed command should use GI_TYPELIB_DETECTED"
# Should NOT have hardcoded /usr/lib/girepository-1.0 in desktop entry section
desktop_start = install_sh_content.find("install_desktop_entry()")
if desktop_start == -1:
pytest.skip("install_desktop_entry function not found")
desktop_section = install_sh_content[desktop_start : desktop_start + 1000]
if "sed -i" in desktop_section and "vocalinux.desktop" in desktop_section:
assert (
"/usr/lib/girepository-1.0"
not in desktop_section.split("sed -i")[1].split("vocalinux.desktop")[0]
), "Desktop entry should not hardcode /usr/lib/girepository-1.0 path"
def test_detect_typelib_path_with_pkgconfig(self, install_sh_content):
"""Test that detect_typelib_path uses pkg-config when available."""
# Extract the detect_typelib_path function
func_start = install_sh_content.find("detect_typelib_path() {")
if func_start == -1:
pytest.skip("detect_typelib_path function not found")
func_end = install_sh_content.find("}", func_start)
func_content = install_sh_content[func_start:func_end]
# Should check for pkg-config first
assert "pkg-config" in func_content, "Should check for pkg-config"
assert "gobject-introspection-1.0" in func_content, "Should query gobject-introspection-1.0"
def test_detect_typelib_path_fallback_paths(self, install_sh_content):
"""Test that detect_typelib_path has fallback paths for various distros."""
# Should have fallback paths for different distros
expected_paths = [
"/usr/lib/x86_64-linux-gnu/girepository-1.0", # Ubuntu/Debian x86_64
"/usr/lib/aarch64-linux-gnu/girepository-1.0", # ARM64
"/usr/lib64/girepository-1.0", # Fedora/RHEL
"/usr/lib/girepository-1.0", # Arch and fallback
]
for path in expected_paths:
assert path in install_sh_content, f"Should have fallback path: {path}"
def test_ci_workflow_uses_dynamic_detection(self, workflow_content):
"""Test that CI workflow uses dynamic GI_TYPELIB_PATH detection."""
# Should use pkg-config or dynamic detection
assert (
"pkg-config --variable=typelibdir" in workflow_content
), "CI workflow should use pkg-config for GI_TYPELIB_PATH"
class TestResourceManagerCrossDistro:
"""Test ResourceManager cross-distro path handling."""
def test_resource_manager_has_xdg_support(self):
"""Test that ResourceManager supports XDG directories."""
from vocalinux.utils.resource_manager import ResourceManager
rm = ResourceManager()
resources_dir = rm.resources_dir
# Should be a valid path string
assert isinstance(resources_dir, str), "resources_dir should be a string"
assert len(resources_dir) > 0, "resources_dir should not be empty"
class TestRecognitionManagerCrossDistro:
"""Test RecognitionManager cross-distro model path handling."""
def test_system_model_paths_exists(self):
"""Test that system model paths configuration exists."""
from vocalinux.speech_recognition.recognition_manager import SYSTEM_MODELS_DIRS
# Should be a list of paths
assert isinstance(SYSTEM_MODELS_DIRS, list), "SYSTEM_MODELS_DIRS should be a list"
assert len(SYSTEM_MODELS_DIRS) > 0, "SYSTEM_MODELS_DIRS should not be empty"
# Should include XDG paths
has_xdg = any("/share/" in path for path in SYSTEM_MODELS_DIRS)
assert has_xdg, "SYSTEM_MODELS_DIRS should include XDG paths"
class TestDocumentation:
"""Test that documentation is accurate."""
def test_distro_compatibility_documentation_exists(self):
"""Test that DISTRO_COMPATIBILITY.md exists and is accurate."""
docs_path = REPO_ROOT / "docs" / "DISTRO_COMPATIBILITY.md"
if not docs_path.exists():
pytest.skip(f"DISTRO_COMPATIBILITY.md not found at {docs_path}")
content = docs_path.read_text()
# Should mention the dynamic path detection
assert (
"pkg-config" in content or "detect_typelib_path" in content
), "Should document dynamic path detection"
# Should mention supported distros
expected_distros = ["Ubuntu", "Debian", "Fedora", "Arch", "openSUSE"]
for distro in expected_distros:
assert distro in content, f"Should mention {distro} support"
if __name__ == "__main__":
pytest.main([__file__, "-v"])