vtcode-core 0.177.1

Core library for VT Code - a Rust-based terminal coding agent
Documentation
use super::*;

#[tokio::test]
async fn literal_backend_leading_dash_paths_and_empty_matches() {
    let workspace = tempfile::Builder::new().prefix("-literal-").tempdir_in(".").unwrap();
    let path = Path::new(workspace.path().file_name().unwrap()).join("-guide.md");
    std::fs::write(&path, "- [Sessions](#sessions)\nplain\n").unwrap();
    let found = search_literal_bounded("- [Sessions](#sessions)", &path, &[], 5).await.unwrap();
    assert_eq!(found.candidates.len(), 1);
    assert_eq!(found.candidates[0].line, 1);
    assert_eq!(found.candidates[0].matched_text, "- [Sessions](#sessions)");
    let empty = search_literal_bounded("absent", &path, &[], 5).await.unwrap();
    assert!(empty.candidates.is_empty());
    assert!(!empty.truncated);
    let error = search_literal_bounded("plain", &workspace.path().join("missing"), &[], 5)
        .await
        .unwrap_err();
    assert!(error.to_string().contains("ripgrep literal search failed"));
}

#[cfg(unix)]
#[tokio::test]
async fn literal_backend_terminates_controlled_children_on_cancel_error_and_truncation() {
    use std::process::Command;

    for mode in ["cancel", "malformed", "truncated"] {
        let workspace = tempfile::tempdir().unwrap();
        let pid_path = workspace.path().join("pid");
        let script = match mode {
            "cancel" => "echo $$ > \"$1\"; exec sleep 30",
            "malformed" => "echo $$ > \"$1\"; printf 'invalid json\\n'; exec sleep 30",
            _ => {
                "echo $$ > \"$1\"; printf '%s\\n' '{\"type\":\"match\",\"data\":{\"path\":{\"text\":\"x.md\"},\"lines\":{\"text\":\"abc\"},\"submatches\":[{\"start\":0,\"end\":3,\"match\":{\"text\":\"abc\"}}]}}'; exec sleep 30"
            }
        };
        let mut command = TokioCommand::new("sh");
        command
            .args(["-c", script, "literal-test"])
            .arg(&pid_path)
            .stdout(Stdio::piped())
            .stderr(Stdio::null());
        let task = tokio::spawn(run_literal_child(command, "abc", 1));
        let pid = tokio::time::timeout(Duration::from_secs(3), async {
            loop {
                if let Ok(pid) = tokio::fs::read_to_string(&pid_path).await
                    && !pid.trim().is_empty()
                {
                    break pid.trim().to_string();
                }
                tokio::time::sleep(Duration::from_millis(10)).await;
            }
        })
        .await
        .unwrap();
        if mode == "cancel" {
            task.abort();
            assert!(task.await.unwrap_err().is_cancelled());
        } else {
            let result = tokio::time::timeout(Duration::from_secs(3), task).await.unwrap().unwrap();
            if mode == "malformed" {
                assert!(result.unwrap_err().to_string().contains("failed to parse ripgrep"));
            } else {
                let result = result.unwrap();
                assert!(result.truncated);
                assert_eq!(result.candidates.len(), 1);
            }
        }
        tokio::time::timeout(Duration::from_secs(3), async {
            while Command::new("kill")
                .args(["-0", &pid])
                .stdout(Stdio::null())
                .stderr(Stdio::null())
                .status()
                .unwrap()
                .success()
            {
                tokio::time::sleep(Duration::from_millis(10)).await;
            }
        })
        .await
        .expect("the owned search child must terminate");
    }
}