diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e190a3a4b..8966d5944 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,6 +97,7 @@ jobs: sudo apt-get install -y libssl-dev libacl1-dev libxxhash-dev liblz4-dev libzstd-dev sudo apt-get install -y libfuse-dev fuse || true # Required for Python llfuse module sudo apt-get install -y libfuse3-dev fuse3 || true # Required for Python pyfuse3 module + sudo apt-get install -y bash zsh fish # for shell completion tests - name: Install Python requirements run: | diff --git a/src/borg/testsuite/shell_completions_test.py b/src/borg/testsuite/shell_completions_test.py new file mode 100644 index 000000000..3f3842c55 --- /dev/null +++ b/src/borg/testsuite/shell_completions_test.py @@ -0,0 +1,55 @@ +import os +import subprocess +import pytest + +SHELL_COMPLETIONS_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts", "shell_completions") + + +def test_bash_completion_is_valid(): + """Test that the bash completion file is valid bash syntax.""" + bash_completion_file = os.path.join(SHELL_COMPLETIONS_DIR, "bash", "borg") + assert os.path.isfile(bash_completion_file) + + # Check if bash is available + try: + subprocess.run(["bash", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) + except (subprocess.SubprocessError, FileNotFoundError): + pytest.skip("bash not available") + + # Test if the bash completion file can be sourced without errors + result = subprocess.run(["bash", "-n", bash_completion_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + assert result.returncode == 0, f"Bash completion file has syntax errors: {result.stderr.decode()}" + + +def test_fish_completion_is_valid(): + """Test that the fish completion file is valid fish syntax.""" + fish_completion_file = os.path.join(SHELL_COMPLETIONS_DIR, "fish", "borg.fish") + assert os.path.isfile(fish_completion_file) + + # Check if fish is available + try: + subprocess.run(["fish", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) + except (subprocess.SubprocessError, FileNotFoundError): + pytest.skip("fish not available") + + # Test if the fish completion file can be sourced without errors + result = subprocess.run( + ["fish", "-c", f"source {fish_completion_file}"], stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + assert result.returncode == 0, f"Fish completion file has syntax errors: {result.stderr.decode()}" + + +def test_zsh_completion_is_valid(): + """Test that the zsh completion file is valid zsh syntax.""" + zsh_completion_file = os.path.join(SHELL_COMPLETIONS_DIR, "zsh", "_borg") + assert os.path.isfile(zsh_completion_file) + + # Check if zsh is available + try: + subprocess.run(["zsh", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) + except (subprocess.SubprocessError, FileNotFoundError): + pytest.skip("zsh not available") + + # Test if the zsh completion file can be sourced without errors + result = subprocess.run(["zsh", "-n", zsh_completion_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + assert result.returncode == 0, f"Zsh completion file has syntax errors: {result.stderr.decode()}"