Skip to content

Commit

Permalink
Add test scenarios for task failure and cancellation
Browse files Browse the repository at this point in the history
  • Loading branch information
imstar15 committed Jul 19, 2023
1 parent bbff5fb commit 7c05ccf
Showing 1 changed file with 170 additions and 1 deletion.
171 changes: 170 additions & 1 deletion pallets/automation-time/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,6 @@ fn schedule_transfer_with_dynamic_dispatch() {
let account_id = AccountId32::new(ALICE);
let provided_id = vec![1, 2];
let task_id = AutomationTime::generate_task_id(account_id.clone(), provided_id.clone());
let task_hash_input = TaskHashInput::new(account_id.clone(), vec![1, 2]);

fund_account(&account_id, 900_000_000, 2, Some(0));

Expand Down Expand Up @@ -363,6 +362,176 @@ fn schedule_transfer_with_dynamic_dispatch() {
})
}

// The TaskCompleted event is emitted only when the task is successfully completed.
#[test]
fn will_emit_task_completed_event_when_task_completed() {
new_test_ext(START_BLOCK_TIME).execute_with(|| {
let frequency = 3_600;
let account_id = AccountId32::new(ALICE);
let provided_id = vec![1, 2];
let task_id = AutomationTime::generate_task_id(account_id.clone(), provided_id.clone());

fund_account(&account_id, 900_000_000, 2, Some(0));

let call: <Test as frame_system::Config>::RuntimeCall =
frame_system::Call::remark_with_event { remark: vec![0] }.into();

// Schedule a task to be executed at SCHEDULED_TIME and SCHEDULED_TIME + frequency.
let next_execution_time = SCHEDULED_TIME + frequency;
assert_ok!(AutomationTime::schedule_dynamic_dispatch_task(
RuntimeOrigin::signed(account_id.clone()),
vec![1, 2],
ScheduleParam::Fixed { execution_times: vec![SCHEDULED_TIME, next_execution_time] },
Box::new(call),
));

Timestamp::set_timestamp(SCHEDULED_TIME * 1_000);
LastTimeSlot::<Test>::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME));
System::reset_events();

// First execution
AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000));
let my_events = events();

let event = my_events.into_iter().find(|e| {
matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))
});

if event.is_some() {
panic!("TaskCompleted event should not be emitted when task is not completed");
}

// Second execution
Timestamp::set_timestamp(next_execution_time * 1_000);
System::reset_events();
AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000));
let my_events = events();

my_events
.into_iter()
.find(|e| matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. })))
.expect("TaskCompleted event should not be emitted when task is completed");
})
}

// The TaskCompleted event will not be emitted when the task is canceled.
fn will_not_emit_task_completed_event_when_task_canceled() {
new_test_ext(START_BLOCK_TIME).execute_with(|| {
let frequency = 3_600;
let account_id = AccountId32::new(ALICE);
let provided_id = vec![1, 2];
let task_id = AutomationTime::generate_task_id(account_id.clone(), provided_id.clone());

fund_account(&account_id, 900_000_000, 2, Some(0));

let call: <Test as frame_system::Config>::RuntimeCall =
frame_system::Call::remark_with_event { remark: vec![0] }.into();

// Schedule a task to be executed at SCHEDULED_TIME and SCHEDULED_TIME + frequency.
let next_execution_time = SCHEDULED_TIME + frequency;
assert_ok!(AutomationTime::schedule_dynamic_dispatch_task(
RuntimeOrigin::signed(account_id.clone()),
vec![1, 2],
ScheduleParam::Fixed { execution_times: vec![SCHEDULED_TIME, next_execution_time] },
Box::new(call),
));

// First execution
Timestamp::set_timestamp(SCHEDULED_TIME * 1_000);
LastTimeSlot::<Test>::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME));
System::reset_events();

AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000));
let my_events = events();

let event = my_events.into_iter().find(|e| {
matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))
});

if event.is_some() {
panic!("TaskCompleted event should not be emitted when task is not completed");
}

assert_ok!(AutomationTime::cancel_task(RuntimeOrigin::signed(account_id), task_id));

// Second execution
Timestamp::set_timestamp(next_execution_time * 1_000);
System::reset_events();
AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000));
let my_events = events();

// The TaskCompleted event will not be emitted when the task is canceled
let event = my_events.into_iter().find(|e| {
matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))
});
if event.is_some() {
panic!("The TaskCompleted event will not be emitted when the task is canceled");
}
})
}

// When a task fails, the TaskCompleted event will still be emitted.
#[test]
fn will_emit_task_completed_event_when_task_failed() {
new_test_ext(START_BLOCK_TIME).execute_with(|| {
let frequency = 3_600;
let account_id = AccountId32::new(ALICE);
let provided_id = vec![1, 2];
let task_id = AutomationTime::generate_task_id(account_id.clone(), provided_id.clone());

fund_account(&account_id, 900_000_000, 2, Some(0));
let current_funds = Balances::free_balance(AccountId32::new(ALICE));

// Because the execution of the transfer task twice requires a total amount is larger than current balance, the second task will fail.
let call: <Test as frame_system::Config>::RuntimeCall =
pallet_balances::Call::transfer { dest: AccountId32::new(BOB), value: current_funds / 2 + 1 }
.into();

// Schedule a task to be executed at SCHEDULED_TIME and SCHEDULED_TIME + frequency.
let next_execution_time = SCHEDULED_TIME + frequency;
assert_ok!(AutomationTime::schedule_dynamic_dispatch_task(
RuntimeOrigin::signed(account_id.clone()),
vec![1, 2],
ScheduleParam::Fixed { execution_times: vec![SCHEDULED_TIME, next_execution_time] },
Box::new(call),
));

// First execution
Timestamp::set_timestamp(SCHEDULED_TIME * 1_000);
LastTimeSlot::<Test>::put((LAST_BLOCK_TIME, LAST_BLOCK_TIME));
System::reset_events();

AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000));
let my_events = events();

let event = my_events.into_iter().find(|e| {
matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))
});

if event.is_some() {
panic!("TaskCompleted event should not be emitted when task is not completed");
}

// Second execution
Timestamp::set_timestamp(next_execution_time * 1_000);
System::reset_events();
AutomationTime::trigger_tasks(Weight::from_ref_time(900_000_000));
let my_events = events();

// The DynamicDispatchResult event with error should be emitted when task failed.
let event = my_events.clone().into_iter().find(|e| {
matches!(e, RuntimeEvent::AutomationTime(crate::Event::DynamicDispatchResult { result, .. }) if result.is_err())
})
.expect("The DynamicDispatchResult event with error should be emitted when task failed");

// When a task fails, the TaskCompleted event will still be emitted.
let event = my_events.into_iter().find(|e| {
matches!(e, RuntimeEvent::AutomationTime(crate::Event::TaskCompleted { .. }))
})
.expect("When a task fails, the TaskCompleted event will still be emitted");
})
}

#[test]
fn calculate_auto_compound_action_schedule_fee_amount_works() {
new_test_ext(START_BLOCK_TIME).execute_with(|| {
Expand Down

0 comments on commit 7c05ccf

Please sign in to comment.