summary refs log tree commit diff
path: root/tests/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test.rs')
-rw-r--r--tests/test.rs167
1 files changed, 167 insertions, 0 deletions
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 <hi@alyssa.is>
+
+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::<Vec<_>>());
+
+    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!();
+}