Skip to content

Commit

Permalink
Add some more methods to Filesystem, make first test
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperCuber committed Jan 30, 2021
1 parent 30ada38 commit 544ed52
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 82 deletions.
6 changes: 2 additions & 4 deletions src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use anyhow::{Context, Result};
use crossterm::style::Colorize;
use handlebars::Handlebars;

use std::fs;

use crate::args::Options;
use crate::config::Variables;
use crate::difference;
Expand Down Expand Up @@ -476,7 +474,7 @@ pub(crate) fn perform_template_deploy(
variables: &Variables,
) -> Result<()> {
let file_contents =
fs::read_to_string(&template.source).context("read template source file")?;
fs.read_to_string(&template.source).context("read template source file")?;
let file_contents = template.apply_actions(file_contents);
let rendered = handlebars
.render_template(&file_contents, variables)
Expand All @@ -491,7 +489,7 @@ pub(crate) fn perform_template_deploy(
&None,
)
.context("create parent for cache file")?;
fs::write(&template.cache, rendered).context("write rendered template to cache")?;
fs.write(&template.cache, rendered).context("write rendered template to cache")?;

// Target
fs.copy_file(
Expand Down
102 changes: 97 additions & 5 deletions src/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,27 @@ pub fn plan_deploy(state: FileState) -> Vec<Action> {

#[cfg(test)]
mod test {
use crate::config::{SymbolicTarget, TemplateTarget};
use crate::file_state::{SymlinkDescription, TemplateDescription};
use crate::{
config::{SymbolicTarget, TemplateTarget},
filesystem::SymlinkComparison,
};
use crate::{
file_state::{SymlinkDescription, TemplateDescription},
filesystem::TemplateComparison,
};

use std::collections::BTreeSet;
use std::{
collections::BTreeSet,
path::{Path, PathBuf},
};

use super::*;

use mockall::predicate::*;

#[test]
fn initial_deploy() {
// File state
let a = SymlinkDescription {
source: "a_in".into(),
target: SymbolicTarget {
Expand Down Expand Up @@ -276,15 +288,95 @@ mod test {
existing_templates: BTreeSet::new(),
};

// Plan
let actions = plan_deploy(file_state);
assert_eq!(
actions,
[Action::CreateSymlink(a), Action::CreateTemplate(b)]
);

// Setup
let mut fs = crate::filesystem::MockFilesystem::new();
fs.expect_remove_file().times(1).returning(|_p| Ok(()));
let mut seq = mockall::Sequence::new();

let options = Options::default();
let handlebars = handlebars::Handlebars::new();
let variables = Default::default();

fn path_eq(expected: &str) -> impl Fn(&Path) -> bool {
let expected = PathBuf::from(expected);
move |actual| actual == expected
}

actions[0].run(&mut fs, &Options::default(), todo!(), todo!()).unwrap();
// Action 1
fs.expect_compare_symlink()
.times(1)
.with(function(path_eq("a_in")), function(path_eq("a_out")))
.in_sequence(&mut seq)
.returning(|_, _| Ok(SymlinkComparison::OnlySourceExists));
fs.expect_create_dir_all()
.times(1)
.with(function(path_eq("")), eq(None)) // parent of a_out
.in_sequence(&mut seq)
.returning(|_, _| Ok(()));
fs.expect_make_symlink()
.times(1)
.with(
function(path_eq("a_out")),
function(path_eq("a_in")),
eq(None),
)
.in_sequence(&mut seq)
.returning(|_, _, _| Ok(()));

actions[0]
.run(&mut fs, &options, &handlebars, &variables)
.unwrap();

fs.checkpoint();

// Action 2
fs.expect_compare_template()
.times(1)
.with(
function(path_eq("b_out")),
function(path_eq("cache/b_cache")),
)
.in_sequence(&mut seq)
.returning(|_, _| Ok(TemplateComparison::BothMissing));
fs.expect_create_dir_all()
.times(1)
.with(function(path_eq("")), eq(None)) // parent of b_out
.in_sequence(&mut seq)
.returning(|_, _| Ok(()));
fs.expect_read_to_string()
.times(1)
.with(function(path_eq("b_in")))
.in_sequence(&mut seq)
.returning(|_| Ok("".into()));
fs.expect_create_dir_all()
.times(1)
.with(function(path_eq("cache")), eq(None))
.in_sequence(&mut seq)
.returning(|_, _| Ok(()));
fs.expect_write()
.times(1)
.with(function(path_eq("cache/b_cache")), eq(String::from("")))
.in_sequence(&mut seq)
.returning(|_, _| Ok(()));
fs.expect_copy_file()
.times(1)
.with(function(path_eq("cache/b_cache")), function(path_eq("b_out")), eq(None))
.in_sequence(&mut seq)
.returning(|_, _, _| Ok(()));
fs.expect_copy_permissions()
.times(1)
.with(function(path_eq("b_in")), function(path_eq("b_out")), eq(None))
.in_sequence(&mut seq)
.returning(|_, _, _| Ok(()));

actions[1]
.run(&mut fs, &options, &handlebars, &variables)
.unwrap();
}
}
72 changes: 0 additions & 72 deletions src/file_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,75 +238,3 @@ impl FileState {
.collect()
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_file_state_symlinks_only() {
let mut existing_symlinks = BTreeMap::new();
existing_symlinks.insert("file1s".into(), "file1t".into()); // Same
existing_symlinks.insert("file2s".into(), "file2t".into()); // Deleted
existing_symlinks.insert("file3s".into(), "file3t".into()); // Target change

let mut desired_symlinks = BTreeMap::new();
desired_symlinks.insert("file1s".into(), "file1t".into()); // Same
desired_symlinks.insert("file3s".into(), "file0t".into()); // Target change
desired_symlinks.insert("file5s".into(), "file5t".into()); // New

let state = FileState::new(
desired_symlinks,
Default::default(),
existing_symlinks,
Default::default(),
"cache",
);

assert_eq!(
state.deleted_files(),
(
vec![
SymlinkDescription {
source: "file2s".into(),
target: "file2t".into(),
},
SymlinkDescription {
source: "file3s".into(),
target: "file3t".into(),
}
],
Vec::new()
),
"deleted files correct"
);
assert_eq!(
state.new_files(),
(
vec![
SymlinkDescription {
source: "file3s".into(),
target: "file0t".into(),
},
SymlinkDescription {
source: "file5s".into(),
target: "file5t".into(),
},
],
Vec::new()
),
"new files correct"
);
assert_eq!(
state.old_files(),
(
vec![SymlinkDescription {
source: "file1s".into(),
target: "file1t".into(),
}],
Vec::new()
),
"old files correct"
);
}
}
15 changes: 14 additions & 1 deletion src/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ pub trait Filesystem {
/// Removes a file or folder, elevating privileges if needed
fn remove_file(&mut self, path: &Path) -> Result<()>;

/// Read contents of file into a string
fn read_to_string(&mut self, path: &Path) -> Result<String>;

/// Write string to file, without elevating privileges
fn write(&mut self, path: &Path, content: String) -> Result<()>;

/// Delete parents of target file if they're empty
fn delete_parents(&mut self, path: &Path) -> Result<()>;

Expand Down Expand Up @@ -183,6 +189,14 @@ impl Filesystem for RealFilesystem {
}
}

fn read_to_string(&mut self, path: &Path) -> Result<String> {
fs::read_to_string(path).context("read from file")
}

fn write(&mut self, path: &Path, content: String) -> Result<()> {
fs::write(path, content).context("write to file")
}

fn delete_parents(&mut self, path: &Path) -> Result<()> {
let mut path = path.parent().context("get parent")?;
while path.is_dir()
Expand Down Expand Up @@ -636,7 +650,6 @@ mod filesystem_impl {
pub fn platform_dunce(path: &Path) -> PathBuf {
path.into()
}

}

pub use self::filesystem_impl::*;

0 comments on commit 544ed52

Please sign in to comment.