#[cfg(test)]
use super::*;
use crate::{
mock::conclude_pvf_checking, paras_registrar, paras_registrar::mock::*,
traits::Registrar as RegistrarTrait,
};
use pezframe_support::{assert_noop, assert_ok};
use pezkuwi_primitives::SessionIndex;
use pezpallet_balances::Error as BalancesError;
use pezsp_runtime::traits::BadOrigin;
#[test]
fn end_to_end_scenario_works() {
new_test_ext().execute_with(|| {
let para_id = LOWEST_PUBLIC_ID;
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
assert!(!Teyrchains::is_parathread(para_id));
let validation_code = test_validation_code(32);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(32),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
assert!(Teyrchains::is_parathread(para_id));
assert!(!Teyrchains::is_teyrchain(para_id));
assert_ok!(mock::Registrar::make_teyrchain(para_id));
run_to_session(START_SESSION_INDEX + 4);
assert!(!Teyrchains::is_parathread(para_id));
assert!(Teyrchains::is_teyrchain(para_id));
assert_ok!(mock::Registrar::make_parathread(para_id));
run_to_session(START_SESSION_INDEX + 6);
assert!(Teyrchains::is_parathread(para_id));
assert!(!Teyrchains::is_teyrchain(para_id));
assert_ok!(mock::Registrar::deregister(RuntimeOrigin::root(), para_id,));
run_to_session(START_SESSION_INDEX + 8);
assert!(!Teyrchains::is_parathread(para_id));
assert!(!Teyrchains::is_teyrchain(para_id));
});
}
#[test]
fn register_works() {
new_test_ext().execute_with(|| {
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let para_id = LOWEST_PUBLIC_ID;
assert!(!Teyrchains::is_parathread(para_id));
let validation_code = test_validation_code(32);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_eq!(Balances::reserved_balance(&1), <Test as Config>::ParaDeposit::get());
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(32),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
assert!(Teyrchains::is_parathread(para_id));
let validation_code_deposit =
max_code_size() as BalanceOf<Test> * <Test as Config>::DataDepositPerByte::get();
let head_deposit = 32 * <Test as Config>::DataDepositPerByte::get();
assert_eq!(
Balances::reserved_balance(&1),
<Test as Config>::ParaDeposit::get() + head_deposit + validation_code_deposit
);
});
}
#[test]
fn schedule_code_upgrade_validates_code() {
new_test_ext().execute_with(|| {
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let para_id = LOWEST_PUBLIC_ID;
assert!(!Teyrchains::is_parathread(para_id));
let validation_code = test_validation_code(32);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_eq!(Balances::reserved_balance(&1), <Test as Config>::ParaDeposit::get());
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(32),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
assert!(Teyrchains::is_parathread(para_id));
let new_code = test_validation_code(0);
assert_noop!(
mock::Registrar::schedule_code_upgrade(
RuntimeOrigin::signed(1),
para_id,
new_code.clone(),
),
paras::Error::<Test>::InvalidCode
);
let new_code = test_validation_code(max_code_size() as usize + 1);
assert_noop!(
mock::Registrar::schedule_code_upgrade(
RuntimeOrigin::signed(1),
para_id,
new_code.clone(),
),
paras::Error::<Test>::InvalidCode
);
});
}
#[test]
fn register_handles_basic_errors() {
new_test_ext().execute_with(|| {
let para_id = LOWEST_PUBLIC_ID;
assert_noop!(
mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(max_head_size() as usize),
test_validation_code(max_code_size() as usize),
),
Error::<Test>::NotReserved
);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_noop!(
mock::Registrar::register(
RuntimeOrigin::signed(2),
para_id,
test_genesis_head(max_head_size() as usize),
test_validation_code(max_code_size() as usize),
),
Error::<Test>::NotOwner
);
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(max_head_size() as usize),
test_validation_code(max_code_size() as usize),
));
run_to_session(2);
assert_ok!(mock::Registrar::deregister(RuntimeOrigin::root(), para_id));
assert_noop!(
mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(max_head_size() as usize),
test_validation_code(max_code_size() as usize),
),
Error::<Test>::NotReserved
);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(2)));
assert_noop!(
mock::Registrar::register(
RuntimeOrigin::signed(2),
para_id + 1,
test_genesis_head((max_head_size() + 1) as usize),
test_validation_code(max_code_size() as usize),
),
Error::<Test>::HeadDataTooLarge
);
assert_noop!(
mock::Registrar::register(
RuntimeOrigin::signed(2),
para_id + 1,
test_genesis_head(max_head_size() as usize),
test_validation_code((max_code_size() + 1) as usize),
),
Error::<Test>::CodeTooLarge
);
assert_noop!(
mock::Registrar::reserve(RuntimeOrigin::signed(1337)),
BalancesError::<Test, _>::InsufficientBalance
);
});
}
#[test]
fn deregister_works() {
new_test_ext().execute_with(|| {
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let para_id = LOWEST_PUBLIC_ID;
assert!(!Teyrchains::is_parathread(para_id));
let validation_code = test_validation_code(32);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(32),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
assert!(Teyrchains::is_parathread(para_id));
assert_ok!(mock::Registrar::deregister(RuntimeOrigin::root(), para_id,));
run_to_session(START_SESSION_INDEX + 4);
assert!(paras::Pezpallet::<Test>::lifecycle(para_id).is_none());
assert_eq!(Balances::reserved_balance(&1), 0);
});
}
#[test]
fn deregister_handles_basic_errors() {
new_test_ext().execute_with(|| {
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let para_id = LOWEST_PUBLIC_ID;
assert!(!Teyrchains::is_parathread(para_id));
let validation_code = test_validation_code(32);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
test_genesis_head(32),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
assert!(Teyrchains::is_parathread(para_id));
assert_noop!(mock::Registrar::deregister(RuntimeOrigin::signed(2), para_id,), BadOrigin);
assert_ok!(mock::Registrar::make_teyrchain(para_id));
run_to_session(START_SESSION_INDEX + 4);
assert_noop!(
mock::Registrar::deregister(RuntimeOrigin::root(), para_id,),
Error::<Test>::NotParathread
);
});
}
#[test]
fn swap_works() {
new_test_ext().execute_with(|| {
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let para_1 = LOWEST_PUBLIC_ID;
let para_2 = LOWEST_PUBLIC_ID + 1;
let validation_code = test_validation_code(max_code_size() as usize);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_1,
test_genesis_head(max_head_size() as usize),
validation_code.clone(),
));
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(2)));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(2),
para_2,
test_genesis_head(max_head_size() as usize),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
run_to_session(START_SESSION_INDEX + 2);
assert_ok!(mock::Registrar::make_teyrchain(para_1));
let mut swap_data = SwapData::get();
swap_data.insert(para_1, 69);
swap_data.insert(para_2, 1337);
SwapData::set(swap_data);
run_to_session(START_SESSION_INDEX + 4);
assert!(Teyrchains::is_teyrchain(para_1));
assert!(!Teyrchains::is_parathread(para_1));
assert!(!Teyrchains::is_teyrchain(para_2));
assert!(Teyrchains::is_parathread(para_2));
assert_ok!(mock::Registrar::swap(para_origin(para_1), para_1, para_2,));
assert_ok!(mock::Registrar::swap(para_origin(para_2), para_2, para_1,));
System::assert_last_event(RuntimeEvent::Registrar(paras_registrar::Event::Swapped {
para_id: para_2,
other_id: para_1,
}));
run_to_session(START_SESSION_INDEX + 6);
assert!(!Teyrchains::is_teyrchain(para_1));
assert!(Teyrchains::is_parathread(para_1));
assert!(Teyrchains::is_teyrchain(para_2));
assert!(!Teyrchains::is_parathread(para_2));
assert_eq!(SwapData::get().get(¶_1).unwrap(), &1337);
assert_eq!(SwapData::get().get(¶_2).unwrap(), &69);
assert_ok!(mock::Registrar::swap(para_origin(para_1), para_1, para_2,));
assert_ok!(mock::Registrar::swap(para_origin(para_2), para_2, para_1,));
System::assert_last_event(RuntimeEvent::Registrar(paras_registrar::Event::Swapped {
para_id: para_2,
other_id: para_1,
}));
assert_eq!(SwapData::get().get(¶_1).unwrap(), &69);
assert_eq!(SwapData::get().get(¶_2).unwrap(), &1337);
let para_3 = LOWEST_PUBLIC_ID + 2;
let validation_code = test_validation_code(max_code_size() as usize);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(3)));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(3),
para_3,
test_genesis_head(max_head_size() as usize),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX + 6);
run_to_session(START_SESSION_INDEX + 8);
assert_ok!(mock::Registrar::make_teyrchain(para_3));
let mut swap_data = SwapData::get();
swap_data.insert(para_3, 777);
SwapData::set(swap_data);
run_to_session(START_SESSION_INDEX + 10);
assert!(Teyrchains::is_teyrchain(para_3));
assert!(!Teyrchains::is_parathread(para_3));
assert!(Teyrchains::is_teyrchain(para_1));
assert!(!Teyrchains::is_parathread(para_1));
assert_ok!(mock::Registrar::swap(para_origin(para_1), para_1, para_3,));
assert_ok!(mock::Registrar::swap(para_origin(para_3), para_3, para_1,));
System::assert_last_event(RuntimeEvent::Registrar(paras_registrar::Event::Swapped {
para_id: para_3,
other_id: para_1,
}));
assert_eq!(SwapData::get().get(¶_3).unwrap(), &69);
assert_eq!(SwapData::get().get(¶_1).unwrap(), &777);
});
}
#[test]
fn para_lock_works() {
new_test_ext().execute_with(|| {
run_to_block(1);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
let para_id = LOWEST_PUBLIC_ID;
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_id,
vec![1; 3].into(),
test_validation_code(32)
));
assert_noop!(mock::Registrar::add_lock(RuntimeOrigin::signed(2), para_id), BadOrigin);
mock::Registrar::on_new_head(para_id, &Default::default());
assert_noop!(
mock::Registrar::ensure_root_para_or_owner(RuntimeOrigin::signed(1), para_id),
Error::<Test>::ParaLocked,
);
assert_noop!(mock::Registrar::remove_lock(RuntimeOrigin::signed(1), para_id), BadOrigin);
assert_ok!(mock::Registrar::remove_lock(para_origin(para_id), para_id));
assert_ok!(mock::Registrar::ensure_root_para_or_owner(RuntimeOrigin::signed(1), para_id));
mock::Registrar::on_new_head(para_id, &Default::default());
assert_ok!(mock::Registrar::ensure_root_para_or_owner(RuntimeOrigin::signed(1), para_id));
});
}
#[test]
fn swap_handles_bad_states() {
new_test_ext().execute_with(|| {
const START_SESSION_INDEX: SessionIndex = 1;
run_to_session(START_SESSION_INDEX);
let para_1 = LOWEST_PUBLIC_ID;
let para_2 = LOWEST_PUBLIC_ID + 1;
assert!(!Teyrchains::is_parathread(para_1));
assert!(!Teyrchains::is_parathread(para_2));
assert_noop!(
mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2),
Error::<Test>::NotRegistered
);
let validation_code = test_validation_code(32);
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(1)));
assert_ok!(mock::Registrar::reserve(RuntimeOrigin::signed(2)));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(1),
para_1,
test_genesis_head(32),
validation_code.clone(),
));
assert_ok!(mock::Registrar::register(
RuntimeOrigin::signed(2),
para_2,
test_genesis_head(32),
validation_code.clone(),
));
conclude_pvf_checking::<Test>(&validation_code, VALIDATORS, START_SESSION_INDEX);
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
assert_noop!(
mock::Registrar::swap(RuntimeOrigin::root(), para_2, para_1),
Error::<Test>::CannotSwap
);
run_to_session(START_SESSION_INDEX + 2);
assert!(Teyrchains::is_parathread(para_1));
assert!(Teyrchains::is_parathread(para_2));
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
assert_noop!(
mock::Registrar::swap(RuntimeOrigin::root(), para_2, para_1),
Error::<Test>::CannotSwap
);
assert_ok!(mock::Registrar::make_teyrchain(para_1));
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
assert_noop!(
mock::Registrar::swap(RuntimeOrigin::root(), para_2, para_1),
Error::<Test>::CannotSwap
);
run_to_session(START_SESSION_INDEX + 3);
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
assert_noop!(
mock::Registrar::swap(RuntimeOrigin::root(), para_2, para_1),
Error::<Test>::CannotSwap
);
run_to_session(START_SESSION_INDEX + 4);
assert!(Teyrchains::is_teyrchain(para_1));
assert!(Teyrchains::is_parathread(para_2));
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_2, para_1));
assert!(System::events().iter().any(|r| matches!(
r.event,
RuntimeEvent::Registrar(paras_registrar::Event::Swapped { .. })
)));
run_to_session(START_SESSION_INDEX + 5);
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
assert_noop!(
mock::Registrar::swap(RuntimeOrigin::root(), para_2, para_1),
Error::<Test>::CannotSwap
);
run_to_session(START_SESSION_INDEX + 6);
assert!(Teyrchains::is_teyrchain(para_2));
assert!(Teyrchains::is_parathread(para_1));
assert!(System::events().iter().any(|r| matches!(
r.event,
RuntimeEvent::Registrar(paras_registrar::Event::Swapped { .. })
)));
assert_ok!(mock::Registrar::make_parathread(para_2));
run_to_session(START_SESSION_INDEX + 7);
assert_ok!(mock::Registrar::swap(RuntimeOrigin::root(), para_1, para_2));
assert_noop!(
mock::Registrar::swap(RuntimeOrigin::root(), para_2, para_1),
Error::<Test>::CannotSwap
);
run_to_session(START_SESSION_INDEX + 8);
assert!(Teyrchains::is_parathread(para_1));
assert!(Teyrchains::is_parathread(para_2));
});
}