Skip to content
This repository has been archived by the owner on Aug 13, 2024. It is now read-only.

Commit

Permalink
WIP #60 done string hash
Browse files Browse the repository at this point in the history
  • Loading branch information
ninjabear committed Sep 22, 2016
1 parent 7310878 commit ca9557f
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 28 deletions.
80 changes: 54 additions & 26 deletions src/factotum/executor/task_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ pub enum State {
}

#[derive(Clone)]
pub struct Task<'a, T:'a> {
pub struct Task<T> {
pub name: String,
pub state: State,
pub children: Vec<&'a[Task<'a, T>]>,
pub children: Vec<String>,
pub task_spec: T,
pub run_result: Option<RunResult>
}

impl<'a, T> Task<'a, T> {
impl<T> Task<T> {
pub fn new<S: Into<String>>(name: S, task_spec: T) -> Self {
Task {
name: name.into(),
Expand All @@ -60,49 +60,77 @@ impl<'a, T> Task<'a, T> {
}
}

pub struct TaskList<'a, T: 'a> {
pub tasks: Vec<Vec<&'a[Task<'a, T>]>>
pub type TaskGroup<T> = Vec<Task<T>>;

pub struct TaskList<T> {
pub tasks: Vec<TaskGroup<T>>,
edges: HashMap<String,Vec<String>>
}

impl<'a, T> TaskList<'a, T> {
impl<T> TaskList<T> {

pub fn new() -> Self {
TaskList {
tasks: vec![]
tasks: vec![],
edges: HashMap::new()
}
}

pub fn add_group(&mut self, tasks:Vec<&'a[Task<T>]>) {
pub fn add_group(&mut self, tasks:TaskGroup<T>) -> Result<(), String> {
{
let new_edges:Vec<&str> = tasks.iter()
.map(|t| t.name.as_ref())
.collect();

for edge in new_edges {
if self.edges.contains_key(edge) {
return Err(format!("Task '{}' has been added already - task names must be unique", edge))
} else {
self.edges.insert(edge.to_string(), vec![]);
}
}
}

self.tasks.push(tasks);
return Ok(());
}

pub fn set_child(&mut self, child:&Task<T>, parent:&Task<T>) -> Result<(), &'static str> {
let mut seen:HashMap<_, _> = HashMap::new();
for task_grp in self.tasks.iter() {
for task in task_grp {
if task.name == child.name {
if let Some(parent) = seen.get(&parent.name) {
parent.children.push(task);
return Ok(())
} else {
return Err("Cannot add a child if the parent isn't in an earlier task group")
}
}
seen.insert(task.name.clone(), task);
}
pub fn set_child(&mut self, parent:&Task<T>, child:&Task<T>) -> Result<(), String> {
if self.get_task_by_name(&child.name).is_some() {
if let Some(children) = self.edges.get_mut(&parent.name) {
children.push(child.name.clone());
Ok(())
} else {
Err(format!("Parent task '{}' doesn't exist!", parent.name))
}
} else {
Err(format!("Child task '{}' doesn't exist!", &child.name))
}
Err("nop")
}

pub fn get_task_by_name(&self, name:&str) -> Option<&Task<T>> {
for task_group in self.tasks.iter() {
for task in task_group.iter() {
pub fn get_task_by_name(&mut self, name:&str) -> Option<&mut Task<T>> {
for task_group in self.tasks.iter_mut() {
for task in task_group.iter_mut() {
if task.name == name {
return Some(task)
}
}
}
None
}

pub fn get_descendants(&self, task_name:&str) -> Vec<String> {
let default = &vec![];
let deps:Vec<String> = self.edges.get(task_name).unwrap_or(default).iter().map(|x| x.clone()).collect();

let mut seen = vec![];

for dep in deps {
seen.push(dep.clone());
seen.extend(self.get_descendants(&dep));
}

return seen;
}


Expand Down
78 changes: 76 additions & 2 deletions src/factotum/executor/task_list/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,25 @@ fn task_new_defaults_good() {
assert!(task.run_result.is_some()==false)
}

#[test]
fn task_grp_dup_names_err() {
let mut task_group = TaskGroup::<String>::new();
task_group.push(Task::<String>::new("hello", "hello".to_string()));
task_group.push(Task::<String>::new("world", "world".to_string()));
let mut tl = TaskList::<String>::new();
let expected_good = tl.add_group(task_group);
assert!(expected_good.ok().is_some());


let mut task_group_err = TaskGroup::<String>::new();
task_group_err.push(Task::<String>::new("hello", "hello".to_string()));
let expected_bad = tl.add_group(task_group_err);
match expected_bad {
Ok(()) => panic!("Duplicate values added to tasklist"),
Err(msg) => assert_eq!("Task 'hello' has been added already - task names must be unique", msg)
}
}

#[test]
fn test_get_by_name() {
let mut tl = TaskList::<String>::new();
Expand All @@ -34,15 +53,70 @@ fn test_get_by_name() {
tl.add_group(vec![
Task::<String>::new("hello", "world".to_string()),
Task::<String>::new("yes", "world".to_string())
]);
]).ok().unwrap();

tl.add_group(vec![
Task::<String>::new("thing", "world".to_string()),
Task::<String>::new("yah", "world".to_string())
]);
]).ok().unwrap();

assert!(tl.get_task_by_name("hello").is_some());
assert!(tl.get_task_by_name("yes").is_some());
assert!(tl.get_task_by_name("thing").is_some());
assert!(tl.get_task_by_name("yah").is_some());
}

#[test]
fn set_child_no_parent_err() {
let mut tl = TaskList::<&str>::new();
tl.add_group(vec![
Task::<&str>::new("child", "world"),
]).ok().unwrap();
let r = tl.set_child(&Task::<&str>::new("parent", "world"), &Task::<&str>::new("child", "world"));
assert!(r.ok().is_some()==false);
}

#[test]
fn set_child_no_child_err() {
let mut tl = TaskList::<&str>::new();
tl.add_group(vec![
Task::<&str>::new("parent", "world"),
]).ok().unwrap();
let r = tl.set_child(&Task::<&str>::new("parent", "world"), &Task::<&str>::new("child", "world"));
assert!(r.ok().is_some()==false);
}

#[test]
fn set_child_good() {
let mut tl = TaskList::<&str>::new();
let tg = vec![
Task::<&str>::new("parent", "world"),
Task::<&str>::new("child", "world")
];
tl.add_group(tg).ok().unwrap();
let r = tl.set_child(&Task::<&str>::new("parent", "world"),
&Task::<&str>::new("child", "world"));
assert!(r.ok().is_some()==true);
}

#[test]
fn get_children() {
let mut tl = TaskList::<&str>::new();
let tg = vec![
Task::<&str>::new("parent", "world"),
Task::<&str>::new("child", "world"),
Task::<&str>::new("grandchild", "world"),
Task::<&str>::new("grandchild2", "world")
];
tl.add_group(tg).ok().unwrap();
tl.set_child(&Task::<&str>::new("parent", "world"),
&Task::<&str>::new("child", "world")).ok();
tl.set_child(&Task::<&str>::new("child", "world"),
&Task::<&str>::new("grandchild", "world")).ok();
tl.set_child(&Task::<&str>::new("child", "world"),
&Task::<&str>::new("grandchild2", "world")).ok();

assert_eq!(vec!["grandchild", "grandchild2"], tl.get_descendants("child"));
assert_eq!(vec!["child", "grandchild", "grandchild2"], tl.get_descendants("parent"));
assert_eq!(Vec::<String>::new(), tl.get_descendants(""))
}

0 comments on commit ca9557f

Please sign in to comment.