pub mod common;
use anyhow::{Context, Result};
use indexmap::indexset;
use garden::string;
#[test]
fn config_default() {
let config = garden::model::Configuration::new();
assert!(matches!(config.shell.as_str(), "bash" | "sh" | "zsh"));
assert_eq!(0, config.verbose);
assert_eq!("", config.root.get_expr());
}
#[test]
fn core() -> Result<()> {
let string = string!(
r#"
garden:
root: /usr
"#
);
let app_context = common::garden_context_from_string(&string)?;
let config = app_context.get_root_config();
assert_eq!(std::path::PathBuf::from("/usr"), config.root_path);
Ok(())
}
#[test]
fn variables() -> Result<()> {
let string = string!(
r#"
garden:
root: ~/src
variables:
foo: foo_value
bar: ${foo}
"#
);
let app_context = common::garden_context_from_string(&string)?;
let config = app_context.get_root_config();
assert_eq!(5, config.variables.len());
assert!(config.variables.contains_key("GARDEN_ROOT"));
assert!(config.variables.contains_key("GARDEN_CMD_QUIET"));
assert!(config.variables.contains_key("GARDEN_CMD_VERBOSE"));
assert!(config.variables.contains_key("foo"));
assert!(config.variables.contains_key("bar"));
let root_var = config.variables.get("GARDEN_ROOT").context("GARDEN_ROOT")?;
assert_eq!("/home/test/src", root_var.get_expr());
assert_eq!(
Some("/home/test/src".to_string()),
root_var.get_value().cloned()
);
let foo_var = config.variables.get("foo").context("foo")?;
assert_eq!("foo_value", foo_var.get_expr());
assert_eq!(None, foo_var.get_value());
let bar_var = config.variables.get("bar").context("bar")?;
assert_eq!("${foo}", bar_var.get_expr());
assert_eq!(None, bar_var.get_value());
Ok(())
}
#[test]
fn commands() -> Result<()> {
let string = string!(
r#"
commands:
test_cmd: echo cmd
test_cmd_vec:
- echo first
- echo second
"#
);
let app_context = common::garden_context_from_string(&string)?;
let config = app_context.get_root_config();
assert_eq!(2, config.commands.len());
assert!(config.commands.contains_key("test_cmd"));
assert_eq!(
1,
config
.commands
.get("test_cmd")
.context("test_cmd command")?
.len()
);
assert_eq!(
"echo cmd",
config
.commands
.get("test_cmd")
.context("test_cmd command")?
.first()
.context("test_cmd[0]")?
.get_expr()
);
let test_cmd_vec_opt = config.commands.get("test_cmd_vec");
assert!(test_cmd_vec_opt.is_some());
let test_cmd_vec = test_cmd_vec_opt.context("test_cmd_vec")?;
assert_eq!(2, test_cmd_vec.len());
assert_eq!("echo first", test_cmd_vec[0].get_expr());
assert_eq!("echo second", test_cmd_vec[1].get_expr());
Ok(())
}
#[test]
fn templates() -> Result<()> {
let string = string!(
r#"
templates:
template1:
variables:
foo: bar
environment:
ENV=: ${foo}env
THEPATH:
- ${foo}
- ${ENV}
template2:
extend: template1
variables:
baz: zax
zee: ${foo}
template3:
extend: [template1, template2]
variables:
foo: boo
"#
);
let app_context = common::garden_context_from_string(&string)?;
let config = app_context.get_root_config();
assert_eq!(3, config.templates.len());
let template1 = config.templates.get("template1").unwrap();
assert_eq!("template1", template1.get_name());
assert_eq!(1, template1.tree.variables.len());
let foo_var = template1.tree.variables.get("foo").context("foo")?;
assert_eq!("bar", foo_var.get_expr());
assert_eq!(2, template1.tree.environment.len());
assert_eq!("ENV=", template1.tree.environment[0].get_name());
assert_eq!(1, template1.tree.environment[0].len());
assert_eq!("${foo}env", template1.tree.environment[0].get(0).get_expr());
assert_eq!("THEPATH", template1.tree.environment[1].get_name());
assert_eq!(2, template1.tree.environment[1].len());
assert_eq!("${foo}", template1.tree.environment[1].get(0).get_expr());
assert_eq!("${ENV}", template1.tree.environment[1].get(1).get_expr());
let template2 = config.templates.get("template2").unwrap();
assert_eq!("template2", template2.get_name());
assert_eq!(indexset! {string!("template1")}, template2.extend);
assert_eq!(3, template2.tree.variables.len());
let baz_var = template2.tree.variables.get("baz").context("baz")?;
assert_eq!("zax", baz_var.get_expr());
let zee_var = template2.tree.variables.get("zee").context("zee")?;
assert_eq!("${foo}", zee_var.get_expr());
let foo_var = template2.tree.variables.get("foo").context("foo")?;
assert_eq!("bar", foo_var.get_expr());
let template3 = config.templates.get("template3").unwrap();
assert_eq!("template3", template3.get_name());
assert_eq!(
indexset! {string!("template1"), string!("template2")},
template3.extend
);
assert_eq!(3, template3.tree.variables.len());
let foo_var = template3.tree.variables.get("foo").context("foo")?;
assert_eq!("boo", foo_var.get_expr());
Ok(())
}
#[test]
fn groups() -> Result<()> {
let app_context = common::garden_context()?;
let config = app_context.get_root_config();
assert!(config.groups.len() >= 2);
assert!(config.groups.contains_key("cola"));
assert_eq!(
"cola",
config
.groups
.get("cola")
.context("missing cola group")?
.get_name()
);
assert_eq!(
indexset! {
string!("git"),
string!("cola"),
string!("python/qtpy")
},
config.groups["cola"].members
);
let test_group = config.groups.get("test").context("missing text group")?;
assert_eq!("test", test_group.get_name());
assert_eq!(
indexset! {
string!("a"),
string!("b"),
string!("c")
},
test_group.members
);
Ok(())
}
#[test]
fn trees() -> Result<()> {
let app_context = common::garden_context()?;
let config = app_context.get_root_config();
assert!(config.trees.len() >= 6);
let tree0 = &config.trees[0];
assert!(tree0.environment.is_empty());
assert_eq!(3, tree0.commands.len());
assert_eq!("git", tree0.get_name());
assert_eq!("git", tree0.get_path().get_expr()); assert_eq!(indexset! {string!("makefile")}, tree0.templates);
assert_eq!(1, tree0.remotes.len());
let origin_var = tree0.remotes.get("origin").context("origin")?;
assert_eq!("https://github.com/git/git", origin_var.get_expr());
assert_eq!(3, tree0.variables.len());
let tree_name_var = tree0.variables.get("TREE_NAME").context("TREE_NAME")?;
assert_eq!("git", tree_name_var.get_expr());
assert_eq!("git", tree_name_var.get_value().unwrap());
let tree_path_var = tree0.variables.get("TREE_PATH").context("TREE_PATH")?;
assert_eq!("/home/test/src/git", tree_path_var.get_expr());
assert_eq!("/home/test/src/git", tree_path_var.get_value().unwrap());
let prefix_var = tree0.variables.get("prefix").context("prefix")?;
assert_eq!("~/.local", prefix_var.get_expr());
assert_eq!(2, tree0.gitconfig.len());
let user_name_var = tree0.gitconfig.get("user.name").context("user.name")?;
assert_eq!(
"A U Thor",
user_name_var.first().context("user.name expr")?.get_expr()
);
assert_eq!(
None,
user_name_var
.first()
.context("None for user.name value")?
.get_value()
);
let user_email_var = tree0.gitconfig.get("user.email").context("user.email")?;
assert_eq!(
"author@example.com",
user_email_var
.first()
.context("user.email expr")?
.get_expr()
);
assert_eq!(
None,
user_email_var
.first()
.context("user.email value")?
.get_value()
);
let tree1 = &config.trees[1];
assert!(tree1.gitconfig.is_empty());
assert_eq!("cola", tree1.get_name());
assert_eq!("git-cola", tree1.get_path().get_expr());
assert_eq!(
indexset! {string!("makefile"), string!("python")},
tree1.templates
);
assert_eq!(2, tree1.remotes.len());
let origin_var = tree1.remotes.get("origin").context("origin")?;
assert_eq!(
"https://github.com/git-cola/git-cola",
origin_var.get_expr()
);
let remote_var = tree1.remotes.get("davvid").context("davvid")?;
assert_eq!("git@github.com:davvid/git-cola.git", remote_var.get_expr());
assert_eq!(3, tree1.environment.len());
assert_eq!("PYTHONPATH", tree1.environment[0].get_name());
assert_eq!(1, tree1.environment[0].len());
assert_eq!("${TREE_PATH}", tree1.environment[0].get(0).get_expr());
assert_eq!("PATH", tree1.environment[1].get_name());
assert_eq!(2, tree1.environment[1].len());
assert_eq!("${prefix}/bin", tree1.environment[1].get(0).get_expr());
assert_eq!("${TREE_PATH}/bin", tree1.environment[1].get(1).get_expr());
assert_eq!("PYTHONPATH", tree1.environment[2].get_name());
assert_eq!(1, tree1.environment[2].len());
assert_eq!(
"${GARDEN_ROOT}/python/send2trash",
tree1.environment[2].get(0).get_expr()
);
assert_eq!(3, tree1.commands.len());
assert!(tree1.commands.contains_key("build"));
assert!(tree1.commands.contains_key("install"));
assert!(tree1.commands.contains_key("test"));
let test_cmd = tree1.commands.get("test").context("test")?;
assert_eq!(2, test_cmd.len());
assert_eq!("git status --short", test_cmd[0].get_expr());
assert_eq!("make tox", test_cmd[1].get_expr());
let tree3 = &config.trees[4];
assert_eq!("annex/data", tree3.get_name());
assert_eq!(1, tree3.gitconfig.len());
let annex_ignore_var = tree3
.gitconfig
.get("remote.origin.annex-ignore")
.context("annex-ignore")?;
assert_eq!(
"true",
annex_ignore_var
.first()
.context("remote.origin.annex-ignore expr")?
.get_expr()
);
assert_eq!(2, tree3.remotes.len());
let origin_var = tree3.remotes.get("origin").context("origin")?;
assert_eq!("git@example.com:git-annex/data.git", origin_var.get_expr());
let remote_var = tree3.remotes.get("local").context("local")?;
assert_eq!("${GARDEN_ROOT}/annex/local", remote_var.get_expr());
let tree4 = &config.trees[5];
assert_eq!("annex/local", tree4.get_name());
assert_eq!(1, tree4.gitconfig.len());
let annex_ignore_var = tree4
.gitconfig
.get("remote.origin.annex-ignore")
.context("annex-ignore")?;
assert_eq!(
"true",
annex_ignore_var
.first()
.context("annex-ignore expr")?
.get_expr()
);
assert_eq!(2, tree4.remotes.len());
let origin_var = tree4.remotes.get("origin").context("origin")?;
assert_eq!("git@example.com:git-annex/data.git", origin_var.get_expr());
let remote_var = tree4.remotes.get("local").context("local")?;
assert_eq!("${GARDEN_ROOT}/annex/local", remote_var.get_expr());
Ok(())
}
#[test]
fn gardens() -> Result<()> {
let app_context = common::garden_context()?;
let config = app_context.get_root_config();
test_gardens(config)
}
#[test]
fn gardens_json() -> Result<()> {
let string = string!(
r#"
{
"gardens": {
"cola": {
"groups": "cola",
"variables": {
"prefix": "~/apps/git-cola/current"
},
"environment": {
"GIT_COLA_TRACE=": "full",
"PATH+": "${prefix}/bin"
},
"commands": {
"summary": [
"git branch",
"git status --short"
]
}
},
"git": {
"groups": "cola",
"trees": "gitk",
"gitconfig": {
"user.name": "A U Thor",
"user.email": "author@example.com"
}
}
}
}
"#
);
let app_context = common::garden_context_from_string(&string)?;
let config = app_context.get_root_config();
test_gardens(config)
}
fn test_gardens(config: &garden::model::Configuration) -> Result<()> {
assert!(config.gardens.len() >= 2);
assert_eq!("cola", config.gardens[0].get_name());
assert!(config.gardens[0].trees.is_empty());
assert!(config.gardens[0].gitconfig.is_empty());
assert_eq!(1, config.gardens[0].groups.len());
assert_eq!("cola", config.gardens[0].groups[0]);
assert_eq!(1, config.gardens[0].commands.len());
let summary_cmd_opt = config.gardens[0].commands.get("summary");
assert!(summary_cmd_opt.is_some());
let summary_cmd = summary_cmd_opt.context("summary")?;
assert_eq!(2, summary_cmd.len());
assert_eq!("git branch", summary_cmd[0].get_expr());
assert_eq!("git status --short", summary_cmd[1].get_expr());
let prefix_var = config.gardens[0]
.variables
.get("prefix")
.context("prefix")?;
assert_eq!("~/apps/git-cola/current", prefix_var.get_expr());
assert_eq!(2, config.gardens[0].environment.len());
assert_eq!(
"GIT_COLA_TRACE=",
config.gardens[0].environment[0].get_name()
);
assert_eq!(1, config.gardens[0].environment[0].len());
assert_eq!("full", config.gardens[0].environment[0].get(0).get_expr());
assert_eq!("PATH+", config.gardens[0].environment[1].get_name());
assert_eq!(1, config.gardens[0].environment[1].len());
assert_eq!(
"${prefix}/bin",
config.gardens[0].environment[1].get(0).get_expr()
);
assert_eq!("git", config.gardens[1].get_name());
assert!(config.gardens[1].environment.is_empty());
assert!(config.gardens[1].variables.is_empty());
assert!(config.gardens[1].commands.is_empty());
assert_eq!(indexset! {string!("cola")}, config.gardens[1].groups);
assert_eq!(indexset! {string!("gitk")}, config.gardens[1].trees);
assert_eq!(config.gardens[1].gitconfig.len(), 2);
let user_name_var = config.gardens[1]
.gitconfig
.get("user.name")
.context("user.name")?;
assert_eq!(
"A U Thor",
user_name_var.first().context("user.name expr")?.get_expr()
);
let user_email_var = config.gardens[1]
.gitconfig
.get("user.email")
.context("user.email")?;
assert_eq!(
"author@example.com",
user_email_var
.first()
.context("user.email expr")?
.get_expr()
);
Ok(())
}
#[test]
fn tree_path() -> Result<()> {
let app_context = common::garden_context()?;
let config = app_context.get_root_config();
assert!(config.trees.len() >= 4);
assert_eq!("/home/test/src/git", config.trees[0].path_as_ref().unwrap());
assert_eq!(
"/home/test/src/git-cola",
config.trees[1].path_as_ref().unwrap()
);
assert_eq!(
"/home/test/src/python/qtpy",
config.trees[2].path_as_ref().unwrap()
);
Ok(())
}
#[test]
fn test_template_url() -> Result<()> {
let app_context = common::garden_context()?;
let config = app_context.get_root_config();
assert!(config.trees.len() > 3);
let tree = &config.trees[3];
assert_eq!("tmp", tree.get_name());
assert_eq!(1, tree.remotes.len());
let origin_var = tree.remotes.get("origin").context("origin")?;
assert_eq!("${local}/${TREE_NAME}", origin_var.get_expr());
Ok(())
}
#[test]
fn read_grafts() -> Result<()> {
let app = garden::model::ApplicationContext::from_path_string("tests/data/garden.yaml")?;
let config = app.get_root_config();
assert_eq!(3, config.grafts.len());
assert_eq!("graft", config.grafts[0].get_name());
let graft_id = config.grafts[0].get_id();
assert!(graft_id.is_some());
let graft_node_id: usize = graft_id.unwrap().into();
assert_eq!(2usize, graft_node_id);
assert_eq!("graft-no-root", config.grafts[1].get_name());
let graft_id = config.grafts[1].get_id();
assert!(graft_id.is_some());
assert_eq!("libs", config.grafts[2].get_name());
let graft_id = config.grafts[2].get_id();
assert!(graft_id.is_some());
let graft_node_id: usize = graft_id.unwrap().into();
assert_eq!(6usize, graft_node_id);
Ok(())
}