From a67b0812659d1481f4c5be77ce2cf448b0b37b8c Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Mon, 14 Jun 2021 22:49:07 -0300 Subject: Start rewriting in Rust --- src/git/tests.rs | 389 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 src/git/tests.rs (limited to 'src/git') diff --git a/src/git/tests.rs b/src/git/tests.rs new file mode 100644 index 0000000..ef6c763 --- /dev/null +++ b/src/git/tests.rs @@ -0,0 +1,389 @@ +// This file is part of GAnarchy - decentralized development hub +// Copyright (C) 2021 Soni L. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//! Unit tests for the git module. + +use super::*; + +use std::panic::AssertUnwindSafe; + +use assert_fs::assert::PathAssert; +use assert_fs::fixture::{TempDir, PathChild}; +use predicates; +use testserver::serve; + +const MAGIC_BRANCH: &'static str = "gan\ + 0000000000000000000000000000000000000000000000000000000000000000"; + +const MAGIC_COMMIT: &'static str = "9d7224353c34ad675ee5e43fb3115aaaf98832e9"; + +// Oh yes. +static REPO: &'static str = +r#####"! +branches.a/ 0 0 0 644 8 ` +! +config.t/ 0 0 0 644 66 ` +[core] + repositoryformatversion = 0 + filemode = true + bare = true +description.t/ 0 0 0 644 73 ` +Unnamed repository; edit this file 'description' to name the repository. + +HEAD.t/ 0 0 0 644 24 ` +ref: refs/heads/default +hooks.a/ 0 0 0 644 8 ` +! +info.a/ 0 0 0 644 428 ` +! +exclude.t/ 0 0 0 644 240 ` +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ +refs.t/ 0 0 0 644 60 ` +9d7224353c34ad675ee5e43fb3115aaaf98832e9 refs/heads/default +objects.a/ 0 0 0 644 916 ` +! +4b.a/ 0 0 0 644 192 ` +! +// 42 ` +825dc642cb6eb9a060e54bf8d69288fbee4904.b/ +/0 0 0 0 644 21 ` +eAErKUpNVTBgAAAKLAIB + +9d.a/ 0 0 0 644 398 ` +! +// 42 ` +7224353c34ad675ee5e43fb3115aaaf98832e9.b/ +/0 0 0 0 644 227 ` +eAGdjUsKwjAURR1nFW8DlpikIQURHRSngs7EQT6vNtIkJUZod2/BrkC4o3M5HJtC8AUYp5uSEUEY +xWpnpWDWSDSNppJiLUynnGyYUp1BFA0VRH9KnzJcU/TtxGCP0WEOKeIckjs+g/ZDZVM4wE4yXnMm +dw1sKaeULHRJFvxLJvdLTi+05QHtpMM4IKyAkFvv37BMR8D1O5+izrafYfxZFfkCj/1MqQ== + +info.a/ 0 0 0 644 70 ` +! +packs.t/ 0 0 0 644 1 ` + + +pack.a/ 0 0 0 644 8 ` +! +refs.a/ 0 0 0 644 246 ` +! +heads.a/ 0 0 0 644 110 ` +! +default.t/ 0 0 0 644 41 ` +9d7224353c34ad675ee5e43fb3115aaaf98832e9 + +tags.a/ 0 0 0 644 8 ` +! +"#####; + +/// Tests the low-level (raw) commands. +mod low_level { + use super::*; + + /// Tests that cmd_init works. + #[test] + fn test_cmd_git_init() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let git = Git::at_path(Initializer, repo.path()).unwrap(); + git.cmd_init(|args| { + // templates actually override the -b flag, but at least + // this tests that passing args to git init actually works. + // also note that the -b flag requires a fairly recent version + // of git but ah well. .-. + args.arg("-b").arg("hello"); + }).unwrap(); + // git init *always* creates HEAD, even for bare repos! + // we don't actually care about what HEAD contains tho. + repo.child("HEAD").assert(predicates::path::exists()); + } + + /// Tests that cmd_clone works. + #[test] + fn test_cmd_git_clone() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let git = Git::at_path(Initializer, repo.path()).unwrap(); + git.cmd_init(|_| {}).unwrap(); + // check that a HEAD exists + repo.child("HEAD").assert(predicates::path::exists()); + let clone = dir.child("ganarchy-fetch-0.git"); + // have to create a Git manually for this one. ah well. :( + let git_clone = Git { + path: clone.path().into(), + pending_branches: None, + sha256: false, + }; + git_clone.cmd_clone_from(repo.path(), |args| { + // also test if git clone args work. + args.arg("--shared"); + }).unwrap(); + // git clone should carry over the HEAD + let pred = predicates::path::eq_file(repo.child("HEAD").path()); + clone.child("HEAD").assert(pred); + } + + /// Tests that cmd works and that we can get output from it. + #[test] + fn test_cmd() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let git = Git::at_path(Initializer, repo.path()).unwrap(); + // we do need to init this because git attempts to cd to it. + git.cmd_init(|_| {}).unwrap(); + let output = git.cmd(|args| { + args.arg("check-ref-format"); + args.arg("--normalize"); + args.arg("//refs/heads/headache"); + }).unwrap(); + assert_eq!(output.stdout, b"refs/heads/headache\n"); + } +} + +/// Tests private operations. +mod privates { + use super::*; + + /// Tests that fork works. + #[test] + fn test_fork() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let clone = dir.child("ganarchy-fetch-0.git"); + // have to create a Git manually for this one. ah well. :( + let mut git_clone = Git { + path: clone.path().into(), + pending_branches: Some(Default::default()), + sha256: false, + }; + git.fork(&mut git_clone).unwrap(); + } + + /// Tests that delete works. + #[test] + fn test_delete() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let clone = dir.child("ganarchy-fetch-0.git"); + // have to create a Git manually for this one. ah well. :( + let mut git_clone = Git { + path: clone.path().into(), + pending_branches: Some(Default::default()), + sha256: false, + }; + git.fork(&mut git_clone).unwrap(); + git_clone.delete().unwrap(); + } + + // TODO rm_branch, replace, fetch_work, etc! + // (or we can rely on with_work_repos as an integration test) +} + +/// Tests public operations. +mod publics { + use super::*; + + /// Tests that ensure_exists works. + #[test] + fn test_ensure_exists() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + } + + /// Tests that with_work_repos works. + #[test] + fn test_with_work_repos() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD") + }).unwrap(); + git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + // This is basically check_history, but we skip cache repo check. + repo.cmd(|args| { + args.arg("merge-base"); + args.arg("--is-ancestor"); + args.arg(MAGIC_COMMIT); + args.arg(format!("refs/heads/{}", MAGIC_BRANCH)); + }) + }).unwrap(); + } + + /// Tests that fetch_source works. + #[test] + fn test_fetch_source() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD") + }).unwrap(); + } + + /// Tests that with_work_repos works properly on failure. + #[test] + fn test_with_work_repos_failure() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + let addr2 = format!("{}{}", &addr, "nonexistent"); + let res = git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD").unwrap(); + repo.fetch_source(&addr2, MAGIC_BRANCH, "HEAD") + }); + assert!(res.is_err()); + // it should not merge the successful one. + assert!(git.check_history(MAGIC_BRANCH, MAGIC_COMMIT).is_err()); + } + + /// Tests that panicking through with_work_repos leaves the disk "dirty". + /// Also tests that a future call to with_work_repos fails gracefully. + #[test] + fn test_with_work_repos_panic() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + let res = std::panic::catch_unwind(AssertUnwindSafe(|| { + // we DO NOT want to call unwrap() on ANY of these. + git.with_work_repos::<_, ()>(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD")?; + panic!() + }) + })); + // check that it panicked. + assert!(res.is_err()); + // now check that future calls return an error, without calling the + // closure. + let res: Result<(), _> = git.with_work_repos(1, |_| panic!()); + assert!(res.is_err()); + } + + /// Tests that check_branch is correct. + #[test] + fn test_check_branch() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + git.check_branch("default").unwrap(); + assert!(git.check_branch("HEAD").is_err()); + } + + /// Tests that check_history is correct. + #[test] + fn test_check_history() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD") + }).unwrap(); + git.check_history(MAGIC_BRANCH, MAGIC_COMMIT).unwrap(); + } + + /// Tests that get_counts is correct. (non-exhaustive) + #[test] + fn test_get_counts() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + let counts = git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD")?; + repo.get_counts(MAGIC_COMMIT, MAGIC_COMMIT) + }).unwrap(); + // Unfortunately we can only check MAGIC_COMMIT...MAGIC_COMMIT, + // so this is always gonna be (0, 0). + assert_eq!(counts, (0, 0)); + } + + /// Tests that get_hash is correct. + #[test] + fn test_get_hash() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + let hash = git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD")?; + repo.get_hash(MAGIC_BRANCH) + }).unwrap(); + let hashtoo = git.get_hash(MAGIC_BRANCH).unwrap(); + assert_eq!(hash, MAGIC_COMMIT); + assert_eq!(hash, hashtoo); + } + + /// Tests that get_message is correct. + #[test] + fn test_get_message() { + let dir = TempDir::new().unwrap(); + let repo = dir.child("ganarchy-cache.git"); + let mut git = Git::at_path(Initializer, repo.path()).unwrap(); + git.ensure_exists().unwrap(); + let server = serve(REPO); + let addr = format!("http://{}:{}/", testserver::IP, server.port()); + let msg = git.with_work_repos(1, |repos| { + let repo = &mut repos[0]; + repo.fetch_source(&addr, MAGIC_BRANCH, "HEAD")?; + repo.get_message(MAGIC_COMMIT) + }).unwrap(); + let msgtoo = git.get_message(MAGIC_COMMIT).unwrap(); + let expect = "[Project] Example Project\n\ + \n\ + This is an example GAnarchy project.\n"; + assert_eq!(msg, expect); + assert_eq!(msg, msgtoo); + } +} -- cgit 1.4.1