From c9873817d5c069d6420473d0ace0c0cf84855855 Mon Sep 17 00:00:00 2001 From: Nik Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Wed, 19 Mar 2025 21:31:18 +0000 Subject: [PATCH] test: create helper macros for tests --- helix-vcs/src/git/blame.rs | 90 ++++++++++++++++++++++++++++++++------ helix-vcs/src/git/test.rs | 26 ++++++----- 2 files changed, 92 insertions(+), 24 deletions(-) diff --git a/helix-vcs/src/git/blame.rs b/helix-vcs/src/git/blame.rs index 0ee4deed..340cea96 100644 --- a/helix-vcs/src/git/blame.rs +++ b/helix-vcs/src/git/blame.rs @@ -4,7 +4,7 @@ use std::{collections::HashMap, path::Path}; use super::{get_repo_dir, open_repo}; -#[derive(Clone, PartialEq, PartialOrd, Ord, Eq)] +#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Debug)] pub struct BlameInformation { pub commit_hash: Option<String>, pub author_name: Option<String>, @@ -133,7 +133,7 @@ pub fn blame_line( // // So when our cursor is on the 10th added line or earlier, blame_line will be 0. This means // the blame will be incorrect. But that's fine, because when the cursor_line is on some hunk, - // we can show to the user nothing at all + // we can show to the user nothing at all. This is detected in the editor let blame_line = line.saturating_sub(added_lines_count) + removed_lines_count; let repo_dir = get_repo_dir(file)?; @@ -193,29 +193,93 @@ pub fn blame_line( #[cfg(test)] mod test { + use std::fs::File; + + use crate::git::test::{create_commit_with_message, empty_git_repo}; + use super::*; - #[test] - pub fn inline_blame_parser() { - let bob = BlameInformation { + macro_rules! assert_blamed_lines { + ($repo:ident, $file:ident @ $($commit_msg:literal => $($line:literal $expected:literal),+);+ $(;)?) => {{ + use std::fs::OpenOptions; + use std::io::Write; + + let write_file = |content: &str| { + let mut f = OpenOptions::new() + .write(true) + .truncate(true) + .open(&$file) + .unwrap(); + f.write_all(content.as_bytes()).unwrap(); + }; + + let commit = |msg| create_commit_with_message($repo.path(), true, msg); + + $( + let file_content = concat!($($line, "\n"),*); + write_file(file_content); + commit(stringify!($commit_msg)); + + let mut line_number = 0; + + $( + line_number += 1; + let blame_result = blame_line(&$file, line_number, 0, 0).unwrap().commit_message; + assert_eq!( + blame_result, + Some(concat!(stringify!($expected), "\n").to_owned()), + "Blame mismatch at line {}: expected '{}', got {:?}", + line_number, + stringify!($expected), + blame_result + ); + )* + )* + }}; + } + + fn bob() -> BlameInformation { + BlameInformation { commit_hash: Some("f14ab1cf".to_owned()), author_name: Some("Bob TheBuilder".to_owned()), author_email: Some("bob@bob.com".to_owned()), commit_date: Some("2028-01-10".to_owned()), commit_message: Some("feat!: extend house".to_owned()), commit_body: Some("BREAKING CHANGE: Removed door".to_owned()), - }; + } + } + #[test] + pub fn blame_lin() { + let repo = empty_git_repo(); + let file = repo.path().join("file.txt"); + File::create(&file).unwrap(); + + assert_blamed_lines! { + repo, file @ + 1 => + "fn main() {" 1, + "" 1, + "}" 1; + 2 => + "fn main() {" 1, + " lol" 2, + "}" 1; + }; + } + + #[test] + pub fn inline_blame_format_parser() { let default_values = "{author}, {date} • {message} • {commit}"; assert_eq!( - bob.parse_format(default_values), + bob().parse_format(default_values), "Bob TheBuilder, 2028-01-10 • feat!: extend house • f14ab1cf".to_owned() ); assert_eq!( BlameInformation { author_name: None, - ..bob.clone() + ..bob() } .parse_format(default_values), "2028-01-10 • feat!: extend house • f14ab1cf".to_owned() @@ -223,7 +287,7 @@ mod test { assert_eq!( BlameInformation { commit_date: None, - ..bob.clone() + ..bob() } .parse_format(default_values), "Bob TheBuilder • feat!: extend house • f14ab1cf".to_owned() @@ -232,7 +296,7 @@ mod test { BlameInformation { commit_message: None, author_email: None, - ..bob.clone() + ..bob() } .parse_format(default_values), "Bob TheBuilder, 2028-01-10 • f14ab1cf".to_owned() @@ -240,7 +304,7 @@ mod test { assert_eq!( BlameInformation { commit_hash: None, - ..bob.clone() + ..bob() } .parse_format(default_values), "Bob TheBuilder, 2028-01-10 • feat!: extend house".to_owned() @@ -249,7 +313,7 @@ mod test { BlameInformation { commit_date: None, author_name: None, - ..bob.clone() + ..bob() } .parse_format(default_values), "feat!: extend house • f14ab1cf".to_owned() @@ -258,7 +322,7 @@ mod test { BlameInformation { author_name: None, commit_message: None, - ..bob.clone() + ..bob() } .parse_format(default_values), "2028-01-10 • f14ab1cf".to_owned() diff --git a/helix-vcs/src/git/test.rs b/helix-vcs/src/git/test.rs index 164040f5..c758c80b 100644 --- a/helix-vcs/src/git/test.rs +++ b/helix-vcs/src/git/test.rs @@ -4,11 +4,11 @@ use tempfile::TempDir; use crate::git; -fn exec_git_cmd(args: &str, git_dir: &Path) { +pub fn exec_git_cmd(args: &[&str], git_dir: &Path) { let res = Command::new("git") .arg("-C") .arg(git_dir) // execute the git command in this directory - .args(args.split_whitespace()) + .args(args) .env_remove("GIT_DIR") .env_remove("GIT_ASKPASS") .env_remove("SSH_ASKPASS") @@ -25,26 +25,30 @@ fn exec_git_cmd(args: &str, git_dir: &Path) { .env("GIT_CONFIG_KEY_1", "init.defaultBranch") .env("GIT_CONFIG_VALUE_1", "main") .output() - .unwrap_or_else(|_| panic!("`git {args}` failed")); + .unwrap_or_else(|_| panic!("`git {args:?}` failed")); if !res.status.success() { println!("{}", String::from_utf8_lossy(&res.stdout)); eprintln!("{}", String::from_utf8_lossy(&res.stderr)); - panic!("`git {args}` failed (see output above)") + panic!("`git {args:?}` failed (see output above)") } } -fn create_commit(repo: &Path, add_modified: bool) { +pub fn create_commit(repo: &Path, add_modified: bool) { + create_commit_with_message(repo, add_modified, "commit") +} + +pub fn create_commit_with_message(repo: &Path, add_modified: bool, message: &str) { if add_modified { - exec_git_cmd("add -A", repo); + exec_git_cmd(&["add", "-A"], repo); } - exec_git_cmd("commit -m message", repo); + exec_git_cmd(&["commit", "-m", message], repo); } -fn empty_git_repo() -> TempDir { +pub fn empty_git_repo() -> TempDir { let tmp = tempfile::tempdir().expect("create temp dir for git testing"); - exec_git_cmd("init", tmp.path()); - exec_git_cmd("config user.email test@helix.org", tmp.path()); - exec_git_cmd("config user.name helix-test", tmp.path()); + exec_git_cmd(&["init"], tmp.path()); + exec_git_cmd(&["config", "user.email", "test@helix.org"], tmp.path()); + exec_git_cmd(&["config", "user.name", "helix-test"], tmp.path()); tmp }