mod test_utils;
use assert_cmd::{cargo_bin_cmd, Command};
use std::fs::read_to_string;
use std::path::PathBuf;
use tempfile::TempDir;
use test_utils::{dir_url, test_data};
use url::Url;
struct RepoPaths {
root_path: PathBuf,
metadata_base_url: Url,
targets_base_url: Url,
metadata_outdir: TempDir,
targets_outdir: TempDir,
}
impl RepoPaths {
fn new() -> Self {
let base = test_data().join("tuf-reference-impl");
RepoPaths {
root_path: base.join("metadata").join("1.root.json"),
metadata_base_url: dir_url(base.join("metadata")),
targets_base_url: dir_url(base.join("targets")),
metadata_outdir: TempDir::new().unwrap(),
targets_outdir: TempDir::new().unwrap(),
}
}
}
enum FileType {
Metadata,
Target,
}
fn assert_target_match(indir: &TempDir, filename: &str) {
assert_reference_file_match(indir, filename, FileType::Target)
}
fn assert_metadata_match(indir: &TempDir, filename: &str) {
assert_reference_file_match(indir, filename, FileType::Metadata)
}
fn assert_reference_file_match(indir: &TempDir, filename: &str, filetype: FileType) {
let got = read_to_string(indir.path().join(filename)).unwrap();
let ref_dir = match filetype {
FileType::Metadata => "metadata",
FileType::Target => "targets",
};
let reference = read_to_string(
test_utils::test_data()
.join("tuf-reference-impl")
.join(ref_dir)
.join(filename),
)
.unwrap();
assert_eq!(got, reference, "{} contents do not match.", filename);
}
fn assert_all_metadata(metadata_dir: &TempDir) {
for f in &[
"snapshot.json",
"targets.json",
"timestamp.json",
"1.root.json",
"role1.json",
"role2.json",
] {
assert_metadata_match(metadata_dir, f)
}
}
fn clone_base_command<'a>(cmd: &'a mut Command, repo_paths: &RepoPaths) -> &'a mut Command {
cmd.args([
"clone",
"--root",
repo_paths.root_path.to_str().unwrap(),
"--metadata-url",
repo_paths.metadata_base_url.as_str(),
"--metadata-dir",
repo_paths.metadata_outdir.path().to_str().unwrap(),
])
}
#[test]
fn clone_metadata() {
let repo_paths = RepoPaths::new();
let mut cmd = cargo_bin_cmd!("tuftool");
clone_base_command(&mut cmd, &repo_paths)
.args(["--metadata-only"])
.assert()
.success();
assert_all_metadata(&repo_paths.metadata_outdir)
}
#[test]
fn clone_metadata_target_args_failure() {
let repo_paths = RepoPaths::new();
let mut cmd = cargo_bin_cmd!("tuftool");
clone_base_command(&mut cmd, &repo_paths)
.args(["--metadata-only", "--target-names", "foo"])
.assert()
.failure();
clone_base_command(&mut cmd, &repo_paths)
.args([
"--metadata-only",
"--targets-url",
repo_paths.targets_base_url.as_str(),
])
.assert()
.failure();
clone_base_command(&mut cmd, &repo_paths)
.args([
"--metadata-only",
"--targets-dir",
repo_paths.targets_outdir.path().to_str().unwrap(),
])
.assert()
.failure();
clone_base_command(&mut cmd, &repo_paths)
.args([
"--metadata-only",
"--targets-url",
repo_paths.targets_base_url.as_str(),
"--targets-dir",
repo_paths.targets_outdir.path().to_str().unwrap(),
"--target-names",
"foo",
])
.assert()
.failure();
}
#[test]
fn clone_subset_targets() {
let target_name = "file1.txt";
let repo_paths = RepoPaths::new();
let mut cmd = cargo_bin_cmd!("tuftool");
clone_base_command(&mut cmd, &repo_paths)
.args([
"--targets-url",
repo_paths.targets_base_url.as_str(),
"--targets-dir",
repo_paths.targets_outdir.path().to_str().unwrap(),
"--target-names",
target_name,
])
.assert()
.success();
assert_all_metadata(&repo_paths.metadata_outdir);
assert_target_match(&repo_paths.targets_outdir, target_name);
assert_eq!(
repo_paths.targets_outdir.path().read_dir().unwrap().count(),
1
);
}
#[test]
fn clone_full_repo() {
let repo_paths = RepoPaths::new();
let mut cmd = cargo_bin_cmd!("tuftool");
clone_base_command(&mut cmd, &repo_paths)
.args([
"--targets-url",
repo_paths.targets_base_url.as_str(),
"--targets-dir",
repo_paths.targets_outdir.path().to_str().unwrap(),
])
.assert()
.success();
assert_all_metadata(&repo_paths.metadata_outdir);
for f in &["file1.txt", "file2.txt", "file3.txt"] {
assert_target_match(&repo_paths.targets_outdir, f)
}
}