Skip to content

Commit

Permalink
fix: check child run before before adding migration to list
Browse files Browse the repository at this point in the history
Signed-off-by: Saurav Sharma <[email protected]>
  • Loading branch information
iamsauravsharma committed Mar 18, 2024
1 parent 6aed227 commit aa60890
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 41 deletions.
4 changes: 0 additions & 4 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ pub enum Error {
/// Error for failed to create migrations plan
#[error("failed to create migrations plan")]
FailedToCreateMigrationPlan,
/// Error raised when order cannot be determine properly for replace and run
/// before
#[error("replace and run before migration order cannot be determined properly")]
ReplaceRunBeforeMisMatch,
/// Parent is not applied
#[error("children is applied before parent")]
ParentIsNotApplied,
Expand Down
40 changes: 9 additions & 31 deletions src/migrator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,36 +501,6 @@ where
}
}

// Hashmap which contains all children generated from run before list
let mut run_before_children = HashMap::<_, Vec<_>>::new();
// in first loop add initial parent and child from parent due to run before
for (child, parents) in &parents_due_to_run_before {
for &parent in parents {
// since run before children is hash map we can have only one child occurrence
run_before_children.entry(parent).or_default().push(child);
}
}
// in second loop through recursive add all descendants
for (child, parents) in &parents_due_to_run_before {
for parent in parents {
populate_recursive(&mut run_before_children, parent, child);
}
}

// check for inconsistent order of migration for replace and run before
for (parent_migration, children_vec) in &run_before_children {
for &child in children_vec {
let root = get_root(&parent_due_to_replaces, child);
if !children_vec.contains(&root) {
if let Some(replace_children_vec) = replace_children.get(root) {
if !replace_children_vec.contains(parent_migration) {
return Err(Error::ReplaceRunBeforeMisMatch);
}
}
}
}
}

let mut migration_list = Vec::new();

// Create migration list until migration list length is equal to hash set
Expand Down Expand Up @@ -559,7 +529,15 @@ where
child
.parents()
.iter()
.all(|child_parent| migration_list.contains(&child_parent))
.all(|child_parent| migration_list.contains(&child_parent));
parents_due_to_run_before
.get(child)
.unwrap_or(&vec![])
.iter()
.all(|run_before_migration| {
migration_list.contains(run_before_migration)
|| children.contains(run_before_migration)
})
})
});
if all_required_added {
Expand Down
59 changes: 53 additions & 6 deletions src/migrator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ async fn replaces_multiple_times() {
}

#[tokio::test]
async fn replaces_run_before_mismatch_1() {
async fn replace_run_before_cond_1() {
struct A;
migration!(A, "a", vec_box!(), vec_box!(), vec_box!());
struct B;
Expand All @@ -226,11 +226,11 @@ async fn replaces_run_before_mismatch_1() {
migration!(D, "d", vec_box!(), vec_box!(), vec_box!(B));
let mut migrator = CustomMigrator::default();
let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D)).await;
assert!(plan.is_err());
assert!(plan.is_ok(), "{:?}", plan.err());
}

#[tokio::test]
async fn replaces_run_before_mismatch_2() {
async fn replaces_run_before_cond_2() {
struct A;
migration!(A, "a", vec_box!(), vec_box!(), vec_box!());
struct B;
Expand All @@ -243,11 +243,11 @@ async fn replaces_run_before_mismatch_2() {
migration!(E, "e", vec_box!(), vec_box!(), vec_box!(C));
let mut migrator = CustomMigrator::default();
let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D, E)).await;
assert!(plan.is_err());
assert!(plan.is_ok(), "{:?}", plan.err());
}

#[tokio::test]
async fn replaces_run_before_ok_1() {
async fn replaces_run_before_cond_3() {
struct A;
migration!(A, "a", vec_box!(), vec_box!(), vec_box!());
struct B;
Expand All @@ -264,7 +264,7 @@ async fn replaces_run_before_ok_1() {
}

#[tokio::test]
async fn replaces_run_before_ok_2() {
async fn replaces_run_before_cond_4() {
struct A;
migration!(A, "a", vec_box!(), vec_box!(), vec_box!());
struct B;
Expand All @@ -280,6 +280,53 @@ async fn replaces_run_before_ok_2() {
assert!(plan.is_ok(), "{:?}", plan.err());
}

#[tokio::test]
async fn replaces_run_before_cond_5() {
struct A;
migration!(A, "a", vec_box!(), vec_box!(), vec_box!());
struct B;
migration!(B, "b", vec_box!(A), vec_box!(), vec_box!());
struct C;
migration!(C, "c", vec_box!(), vec_box!(B), vec_box!());
struct D;
migration!(D, "d", vec_box!(), vec_box!(C), vec_box!(C));
let mut migrator = CustomMigrator::default();
let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D)).await;
assert!(plan.is_err());
}

#[tokio::test]
async fn replaces_run_before_cond_6() {
struct A;
migration!(A, "a", vec_box!(), vec_box!(), vec_box!());
struct B;
migration!(B, "b", vec_box!(A), vec_box!(), vec_box!());
struct C;
migration!(C, "c", vec_box!(), vec_box!(B), vec_box!());
struct D;
migration!(D, "d", vec_box!(), vec_box!(C, E), vec_box!());
struct E;
migration!(E, "e", vec_box!(), vec_box!(D), vec_box!(C));
let mut migrator = CustomMigrator::default();
let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D, E)).await;
assert!(plan.is_err());
}

#[tokio::test]
async fn replaces_run_before_cond_7() {
struct A;
migration!(A, "a", vec_box!(), vec_box!(), vec_box!());
struct B;
migration!(B, "b", vec_box!(A), vec_box!(), vec_box!());
struct C;
migration!(C, "c", vec_box!(), vec_box!(B), vec_box!(D));
struct D;
migration!(D, "d", vec_box!(), vec_box!(C), vec_box!());
let mut migrator = CustomMigrator::default();
let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D)).await;
assert!(plan.is_err());
}

#[tokio::test]
async fn loop_error() {
struct A;
Expand Down

0 comments on commit aa60890

Please sign in to comment.