From 41e6284129a906bcf16dc6e66456cd4d36a044dc Mon Sep 17 00:00:00 2001 From: reuben olinsky Date: Thu, 24 Oct 2024 22:52:04 -0700 Subject: [PATCH] test: run completion tests using bash-completion 2.14.0 (#238) --- .github/workflows/ci.yaml | 11 +++++++ brush-shell/Cargo.toml | 4 +++ brush-shell/tests/completion_tests.rs | 44 ++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 40810f1e..bfa82041 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -164,6 +164,17 @@ jobs: ${BASH_PATH} --version echo "BASH_PATH=${BASH_PATH}">>$GITHUB_ENV + - name: "Download recent bash-completion sources for tests" + uses: actions/checkout@v4 + with: + repository: "scop/bash-completion" + ref: "2.14.0" + path: "bash-completion" + + - name: "Setup bash-completion" + run: | + echo "BASH_COMPLETION_PATH=${GITHUB_WORKSPACE}/bash-completion/bash_completion">>$GITHUB_ENV + - name: Test run: | set -euxo pipefail diff --git a/brush-shell/Cargo.toml b/brush-shell/Cargo.toml index abd64715..f4a44f7a 100644 --- a/brush-shell/Cargo.toml +++ b/brush-shell/Cargo.toml @@ -25,6 +25,10 @@ harness = false name = "brush-interactive-tests" path = "tests/interactive_tests.rs" +[[test]] +name = "brush-completion-tests" +path = "tests/completion_tests.rs" + [features] default = ["basic", "reedline"] basic = [] diff --git a/brush-shell/tests/completion_tests.rs b/brush-shell/tests/completion_tests.rs index 0e444765..bc779cdc 100644 --- a/brush-shell/tests/completion_tests.rs +++ b/brush-shell/tests/completion_tests.rs @@ -4,14 +4,14 @@ use anyhow::Result; use assert_fs::prelude::*; -use std::path::Path; +use std::path::PathBuf; struct TestShellWithBashCompletion { shell: brush_core::Shell, temp_dir: assert_fs::TempDir, } -const BASH_COMPLETION_SCRIPT: &str = "/usr/share/bash-completion/bash_completion"; +const DEFAULT_BASH_COMPLETION_SCRIPT: &str = "/usr/share/bash-completion/bash_completion"; impl TestShellWithBashCompletion { async fn new() -> Result { @@ -23,11 +23,12 @@ impl TestShellWithBashCompletion { ..Default::default() }; - let mut shell = brush_core::Shell::new(&create_options).await?; + let bash_completion_script_path = Self::find_bash_completion_script()?; + let mut shell = brush_core::Shell::new(&create_options).await?; let exec_params = shell.default_exec_params(); let source_result = shell - .source::(Path::new(BASH_COMPLETION_SCRIPT), &[], &exec_params) + .source::(bash_completion_script_path.as_path(), &[], &exec_params) .await?; if source_result.exit_code != 0 { @@ -39,6 +40,22 @@ impl TestShellWithBashCompletion { Ok(Self { shell, temp_dir }) } + fn find_bash_completion_script() -> Result { + // See if an environmental override was provided. + let script_path = std::env::var("BASH_COMPLETION_PATH") + .map(PathBuf::from) + .unwrap_or(PathBuf::from(DEFAULT_BASH_COMPLETION_SCRIPT)); + + if script_path.exists() { + Ok(script_path) + } else { + Err(anyhow::anyhow!( + "bash completion script not found: {}", + script_path.display() + )) + } + } + pub async fn complete(&mut self, line: &str, pos: usize) -> Result> { let completions = self.shell.get_completions(line, pos).await?; Ok(completions.candidates.into_iter().collect()) @@ -280,3 +297,22 @@ async fn complete_command_option() -> Result<()> { Ok(()) } + +/// Tests completion with some well-known programs that have been good manual test cases +/// for us in the past. +#[tokio::test] +async fn complete_path_args_to_well_known_programs() -> Result<()> { + let mut test_shell = TestShellWithBashCompletion::new().await?; + + // Create file and dir. + test_shell.temp_dir.child("item1").touch()?; + test_shell.temp_dir.child("item2").create_dir_all()?; + + // Complete. + let input = "tar tvf ./item"; + let results = test_shell.complete(input, input.len()).await?; + + assert_eq!(results, ["./item1", "./item2"]); + + Ok(()) +}