Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(tests): Use command-specific test modules #394

Merged
merged 3 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
432 changes: 21 additions & 411 deletions crates/core/tests/integration.rs

Large diffs are not rendered by default.

245 changes: 245 additions & 0 deletions crates/core/tests/integration/backup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
use std::{
path::{Path, PathBuf},
str::FromStr,
};

use anyhow::Result;
use insta::Settings;
use pretty_assertions::assert_eq;
use rstest::rstest;

use rustic_core::{
repofile::{PackId, SnapshotFile},
BackupOptions, CommandInput, ParentOptions, PathList, SnapshotGroupCriterion, SnapshotOptions,
StringList,
};

use super::{
assert_with_win, insta_node_redaction, insta_snapshotfile_redaction, set_up_repo,
tar_gz_testdata, RepoOpen, TestSource,
};

#[rstest]
fn test_backup_with_tar_gz_passes(
tar_gz_testdata: Result<TestSource>,
set_up_repo: Result<RepoOpen>,
insta_snapshotfile_redaction: Settings,
insta_node_redaction: Settings,
) -> Result<()> {
// uncomment for logging output
// SimpleLogger::init(log::LevelFilter::Debug, Config::default())?;

// Fixtures
let (source, repo) = (tar_gz_testdata?, set_up_repo?.to_indexed_ids()?);

let paths = &source.path_list();

// we use as_path to not depend on the actual tempdir
let opts = BackupOptions::default().as_path(PathBuf::from_str("test")?);

// first backup
let first_snapshot = repo.backup(&opts, paths, SnapshotFile::default())?;

// We can also bind to scope ( https://docs.rs/insta/latest/insta/struct.Settings.html#method.bind_to_scope )
// But I think that can get messy with a lot of tests, also checking which settings are currently applied
// will be probably harder
insta_snapshotfile_redaction.bind(|| {
assert_with_win("backup-tar-summary-first", &first_snapshot);
});

assert_eq!(first_snapshot.parent, None);

// tree of first backup
// re-read index
let repo = repo.to_indexed_ids()?;
let tree = repo.node_from_path(first_snapshot.tree, Path::new("test/0/tests"))?;
let tree: rustic_core::repofile::Tree = repo.get_tree(&tree.subtree.expect("Sub tree"))?;

insta_node_redaction.bind(|| {
assert_with_win("backup-tar-tree", tree);
});

// get all snapshots and check them
let all_snapshots = repo.get_all_snapshots()?;
assert_eq!(vec![first_snapshot.clone()], all_snapshots);
// save list of pack files
let packs1: Vec<PackId> = repo.list()?.collect();

// re-read index
let repo = repo.to_indexed_ids()?;
// second backup
let second_snapshot = repo.backup(&opts, paths, SnapshotFile::default())?;

insta_snapshotfile_redaction.bind(|| {
assert_with_win("backup-tar-summary-second", &second_snapshot);
});

assert_eq!(second_snapshot.parent, Some(first_snapshot.id));
assert_eq!(first_snapshot.tree, second_snapshot.tree);

// pack files should be unchanged
let packs2: Vec<_> = repo.list()?.collect();
assert_eq!(packs1, packs2);

// re-read index
let repo = repo.to_indexed_ids()?;
// third backup with tags and explicitly given parent
let snap = SnapshotOptions::default()
.tags([StringList::from_str("a,b")?])
.to_snapshot()?;
let opts = opts.parent_opts(ParentOptions::default().parent(second_snapshot.id.to_string()));
let third_snapshot = repo.backup(&opts, paths, snap)?;

insta_snapshotfile_redaction.bind(|| {
assert_with_win("backup-tar-summary-third", &third_snapshot);
});
assert_eq!(third_snapshot.parent, Some(second_snapshot.id));
assert_eq!(third_snapshot.tree, second_snapshot.tree);

// get all snapshots and check them
let mut all_snapshots = repo.get_all_snapshots()?;
all_snapshots.sort_unstable();
assert_eq!(
vec![first_snapshot, second_snapshot, third_snapshot],
all_snapshots
);

// pack files should be unchanged
let packs2: Vec<_> = repo.list()?.collect();
assert_eq!(packs1, packs2);
let packs3: Vec<_> = repo.list()?.collect();
assert_eq!(packs1, packs3);

// Check if snapshots can be retrieved
let mut ids: Vec<_> = all_snapshots.iter().map(|sn| sn.id.to_string()).collect();
let snaps = repo.get_snapshots(&ids)?;
assert_eq!(snaps, all_snapshots);

// reverse order
all_snapshots.reverse();
ids.reverse();
let snaps = repo.update_snapshots(snaps, &ids)?;
assert_eq!(snaps, all_snapshots);

// get snapshot group
let group_by = SnapshotGroupCriterion::new().tags(true);
let mut groups = repo.get_snapshot_group(&[], group_by, |_| true)?;

// sort groups to get unique result
groups.iter_mut().for_each(|(_, snaps)| snaps.sort());
groups.sort_by_key(|(group, _)| group.tags.clone());

insta_snapshotfile_redaction.bind(|| {
assert_with_win("backup-tar-groups", &groups);
});

// filter snapshots by tag
let filter = |snap: &SnapshotFile| snap.tags.contains("a");
let snaps = repo.get_matching_snapshots(filter)?;
insta_snapshotfile_redaction.bind(|| {
assert_with_win("backup-tar-matching-snaps", &snaps);
});

Ok(())
}

#[rstest]
fn test_backup_dry_run_with_tar_gz_passes(
tar_gz_testdata: Result<TestSource>,
set_up_repo: Result<RepoOpen>,
insta_snapshotfile_redaction: Settings,
insta_node_redaction: Settings,
) -> Result<()> {
// Fixtures
let (source, repo) = (tar_gz_testdata?, set_up_repo?.to_indexed_ids()?);

let paths = &source.path_list();

// we use as_path to not depend on the actual tempdir
let opts = BackupOptions::default()
.as_path(PathBuf::from_str("test")?)
.dry_run(true);

// dry-run backup
let snap_dry_run = repo.backup(&opts, paths, SnapshotFile::default())?;

insta_snapshotfile_redaction.bind(|| {
assert_with_win("dryrun-tar-summary-first", &snap_dry_run);
});

// check that repo is still empty
let snaps = repo.get_all_snapshots()?;
assert_eq!(snaps.len(), 0);
assert_eq!(repo.list::<PackId>()?.count(), 0);
assert_eq!(repo.list::<PackId>()?.count(), 0);

// first real backup
let opts = opts.dry_run(false);
let first_snapshot = repo.backup(&opts, paths, SnapshotFile::default())?;
assert_eq!(snap_dry_run.tree, first_snapshot.tree);
let packs: Vec<_> = repo.list::<PackId>()?.collect();

// tree of first backup
// re-read index
let repo = repo.to_indexed_ids()?;
let tree = repo.node_from_path(first_snapshot.tree, Path::new("test/0/tests"))?;
let tree = repo.get_tree(&tree.subtree.expect("Sub tree"))?;

insta_node_redaction.bind(|| {
assert_with_win("dryrun-tar-tree", tree);
});

// re-read index
let repo = repo.to_indexed_ids()?;
// second dry-run backup
let opts = opts.dry_run(true);
let snap_dry_run = repo.backup(&opts, paths, SnapshotFile::default())?;

insta_snapshotfile_redaction.bind(|| {
assert_with_win("dryrun-tar-summary-second", &snap_dry_run);
});

// check that no data has been added
let snaps = repo.get_all_snapshots()?;
assert_eq!(snaps, vec![first_snapshot]);
let packs_dry_run: Vec<PackId> = repo.list()?.collect();
assert_eq!(packs_dry_run, packs);

// re-read index
let repo = repo.to_indexed_ids()?;
// second real backup
let opts = opts.dry_run(false);
let second_snapshot = repo.backup(&opts, paths, SnapshotFile::default())?;
assert_eq!(snap_dry_run.tree, second_snapshot.tree);
Ok(())
}

#[rstest]
fn test_backup_stdin_command(
set_up_repo: Result<RepoOpen>,
insta_snapshotfile_redaction: Settings,
) -> Result<()> {
// Fixtures
let repo = set_up_repo?.to_indexed_ids()?;
let paths = PathList::from_string("-")?;

let cmd: CommandInput = "echo test".parse()?;
let opts = BackupOptions::default()
.stdin_filename("test")
.stdin_command(cmd);
// backup data from cmd
let snapshot = repo.backup(&opts, &paths, SnapshotFile::default())?;
insta_snapshotfile_redaction.bind(|| {
assert_with_win("stdin-command-summary", &snapshot);
});

// re-read index
let repo = repo.to_indexed()?;

// check content
let node = repo.node_from_snapshot_path("latest:test", |_| true)?;
let mut content = Vec::new();
repo.dump(&node, &mut content)?;
assert_eq!(content, b"test\n");
Ok(())
}
61 changes: 61 additions & 0 deletions crates/core/tests/integration/find.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::{
path::{Path, PathBuf},
str::FromStr,
};

use anyhow::Result;
use globset::Glob;
use rstest::rstest;

use rustic_core::{
repofile::{Node, SnapshotFile},
BackupOptions, FindMatches, FindNode,
};

use super::{assert_with_win, set_up_repo, tar_gz_testdata, RepoOpen, TestSource};

#[rstest]
fn test_find(tar_gz_testdata: Result<TestSource>, set_up_repo: Result<RepoOpen>) -> Result<()> {
// Fixtures
let (source, repo) = (tar_gz_testdata?, set_up_repo?.to_indexed_ids()?);
let paths = &source.path_list();

// we use as_path to not depend on the actual tempdir
let opts = BackupOptions::default().as_path(PathBuf::from_str("test")?);
// backup test-data
let snapshot = repo.backup(&opts, paths, SnapshotFile::default())?;

// re-read index
let repo = repo.to_indexed_ids()?;

// test non-existing path
let not_found = repo.find_nodes_from_path(vec![snapshot.tree], Path::new("not_existing"))?;
assert_with_win("find-nodes-not-found", not_found);
// test non-existing match
let glob = Glob::new("not_existing")?.compile_matcher();
let not_found =
repo.find_matching_nodes(vec![snapshot.tree], &|path, _| glob.is_match(path))?;
assert_with_win("find-matching-nodes-not-found", not_found);

// test existing path
let FindNode { matches, .. } =
repo.find_nodes_from_path(vec![snapshot.tree], Path::new("test/0/tests/testfile"))?;
assert_with_win("find-nodes-existing", matches);
// test existing match
let glob = Glob::new("testfile")?.compile_matcher();
let match_func = |path: &Path, _: &Node| {
glob.is_match(path) || path.file_name().is_some_and(|f| glob.is_match(f))
};
let FindMatches { paths, matches, .. } =
repo.find_matching_nodes(vec![snapshot.tree], &match_func)?;
assert_with_win("find-matching-existing", (paths, matches));
// test existing match
let glob = Glob::new("testfile*")?.compile_matcher();
let match_func = |path: &Path, _: &Node| {
glob.is_match(path) || path.file_name().is_some_and(|f| glob.is_match(f))
};
let FindMatches { paths, matches, .. } =
repo.find_matching_nodes(vec![snapshot.tree], &match_func)?;
assert_with_win("find-matching-wildcard-existing", (paths, matches));
Ok(())
}
52 changes: 52 additions & 0 deletions crates/core/tests/integration/ls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::{collections::BTreeMap, ffi::OsStr};
use std::{path::PathBuf, str::FromStr};

use anyhow::Result;
use insta::Settings;
use rstest::rstest;

use rustic_core::{
repofile::{Metadata, Node, SnapshotFile},
BackupOptions, LsOptions, RusticResult,
};

use super::{
assert_with_win, insta_node_redaction, set_up_repo, tar_gz_testdata, RepoOpen, TestSource,
};

#[rstest]
fn test_ls(
tar_gz_testdata: Result<TestSource>,
set_up_repo: Result<RepoOpen>,
insta_node_redaction: Settings,
) -> Result<()> {
// Fixtures
let (source, repo) = (tar_gz_testdata?, set_up_repo?.to_indexed_ids()?);
let paths = &source.path_list();

// we use as_path to not depend on the actual tempdir
let opts = BackupOptions::default().as_path(PathBuf::from_str("test")?);
// backup test-data
let snapshot = repo.backup(&opts, paths, SnapshotFile::default())?;

// test non-existing entries
let mut node = Node::new_node(
OsStr::new(""),
rustic_core::repofile::NodeType::Dir,
Metadata::default(),
);
node.subtree = Some(snapshot.tree);

// re-read index
let repo = repo.to_indexed_ids()?;

let entries: BTreeMap<_, _> = repo
.ls(&node, &LsOptions::default())?
.collect::<RusticResult<_>>()?;

insta_node_redaction.bind(|| {
assert_with_win("ls", &entries);
});

Ok(())
}
Loading
Loading