From 94a23a6839f3d4632c5abed1cb8846e4d295383e Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 17 Aug 2021 19:22:05 +0000 Subject: Proof of concept --- tests/no_repo.rs | 20 ------- tests/test.rs | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 20 deletions(-) delete mode 100644 tests/no_repo.rs create mode 100644 tests/test.rs (limited to 'tests') diff --git a/tests/no_repo.rs b/tests/no_repo.rs deleted file mode 100644 index 247426c..0000000 --- a/tests/no_repo.rs +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: EUPL-1.2 -// SPDX-FileCopyrightText: 2021 Alyssa Ross - -use std::process::Command; - -#[test] -fn no_repo() { - let output = Command::new(env!("CARGO_BIN_EXE_git-girf")) - .current_dir("/var/empty") - .env_clear() - .output() - .expect("spawn"); - - assert_eq!(output.status.code(), Some(128)); - assert_eq!( - output.stderr, - b"fatal: could not find repository from '.'\n" - ); - assert_eq!(output.stdout, b""); -} diff --git a/tests/test.rs b/tests/test.rs new file mode 100644 index 0000000..9edacff --- /dev/null +++ b/tests/test.rs @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: EUPL-1.2 +// SPDX-FileCopyrightText: 2021 Alyssa Ross + +use std::{ + env::var_os, + fs::create_dir, + io::{stderr, Write}, + process::Command, +}; + +use git2::{Commit, IntoCString, Oid, Reference, Signature, Time, Tree}; +use tempdir::TempDir; + +struct Repo<'a> { + inner: git2::Repository, + signature: Signature<'a>, +} + +impl Repo<'_> { + fn new(inner: git2::Repository) -> Self { + Self { + inner, + signature: Signature::new("git-girf test suite", "git-girf@test", &Time::new(0, 0)) + .unwrap(), + } + } + + fn commit(&self, files: &[(impl AsRef<[u8]>, impl AsRef<[u8]>)]) -> Oid { + let mut treebuilder = self.inner.treebuilder(None).unwrap(); + + for (path, data) in files { + let blob = self.inner.blob(data.as_ref()).unwrap(); + treebuilder.insert(path.as_ref(), blob, 0o100644).unwrap(); + } + + let tree_oid = treebuilder.write().unwrap(); + let tree = self.inner.find_tree(tree_oid).unwrap(); + let parent_oids = self + .inner + .head() + .into_iter() + .map(|head| head.target().unwrap()); + let parents: Vec<_> = parent_oids + .map(|oid| self.inner.find_commit(oid).unwrap()) + .collect(); + let borrowed_parents: Vec<_> = parents.iter().collect(); + dbg!(self.inner + .commit( + Some("HEAD"), + &self.signature, + &self.signature, + "A commit", + &tree, + &borrowed_parents, + ) + .unwrap()) + } +} + +#[test] +fn happy() { + let dir = TempDir::new("git-girf-tests").unwrap(); + + let path = var_os("PATH").unwrap_or_else(|| "/usr/bin:/bin".into()); + + let repo = Repo::new(git2::Repository::init(&dir).expect("opening repo")); + + // We're going to use `tail -n 1` as our filter command, meaning + // commits shouldn't be printed if they change the last line of + // any file. + + let mut expected = Vec::new(); + + repo.commit(&[("a", "a\na\n")]); + + // This creates a file, so shouldn't be printed. + repo.commit(&[("a", "a\na\n"), ("b", "b\nb\n")]); + + // This changes the first lines only, so should be printed. + expected.push(repo.commit(&[("a", "A\na\n"), ("b", "B\nb\n")])); + + // This changes the last line, so shouldn't be printed. + repo.commit(&[("a", "A\nA\n"), ("b", "b\nB\n")]); + + // This has lots of files, but it should be obvious that it + // doesn't have to be printed after the first file. We include it + // to test that short circuiting doesn't panic the diff thread. + repo.commit(&(b'a'..b'z').map(|c| ([c], [c, b'\n'])).collect::>()); + + let output = Command::new(env!("CARGO_BIN_EXE_git-girf")) + .args(&["tail", "-n", "1"]) + .current_dir(&dir) + .env_clear() + .env("PATH", path) + .output() + .expect("spawn"); + + let _ = stderr().write_all(&output.stderr); + + let len = expected.len(); + let mut expected_bytes = Vec::with_capacity(41 * expected.len()); + for oid in expected { + expected_bytes.extend_from_slice(oid.to_string().as_bytes()); + expected_bytes.push(b'\n'); + } + + assert!(output.stderr.is_empty()); + assert_eq!( + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&expected_bytes) + ); + assert!(output.status.success()); +} + +#[test] +fn no_repo() { + let output = Command::new(env!("CARGO_BIN_EXE_git-girf")) + .arg("cat") + .current_dir("/var/empty") + .env_clear() + .output() + .expect("spawn"); + + assert_eq!(output.status.code(), Some(128)); + assert_eq!( + output.stderr, + b"fatal: could not find repository from '.'\n" + ); + assert!(output.stdout.is_empty()); +} + +#[test] +fn no_args() { + let output = Command::new(env!("CARGO_BIN_EXE_git-girf")) + .current_dir("/var/empty") + .env_clear() + .output() + .expect("spawn"); + + assert_eq!(output.status.code(), Some(128)); + assert_eq!(output.stderr, b"fatal: no command given\n"); + assert!(output.stdout.is_empty()); +} + +#[test] +fn flag() { + let output = Command::new(env!("CARGO_BIN_EXE_git-girf")) + .arg("-Z") + .current_dir("/var/empty") + .env_clear() + .output() + .expect("spawn"); + + assert_eq!(output.status.code(), Some(128)); + assert_eq!(output.stderr, b"fatal: unrecognized argument: -Z\n"); + assert!(output.stdout.is_empty()); +} + +#[test] +fn filter_sigpipe() { + todo!(); +} + +#[test] +fn sigpipe() { + todo!(); +} -- cgit 1.4.1