Skip to content
Snippets Groups Projects
tests.rs 9.08 KiB
Newer Older
  • Learn to ignore specific revisions
  • Ermal Kaleci's avatar
    Ermal Kaleci committed
    #![cfg(test)]
    
    
    use crate::{
    
    	mock::{new_test_ext, AccountId, ModuleOracle, OracleCall, Origin, Test, Timestamp},
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    use codec::Encode;
    
    use frame_support::{
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    	assert_noop, assert_ok, dispatch,
    	traits::{ChangeMembers, OnFinalize},
    
    	unsigned::ValidateUnsigned,
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    };
    use sp_runtime::{
    
    	testing::{TestSignature, UintAuthorityId},
    
    	transaction_validity::{InvalidTransaction, TransactionSource, TransactionValidityError},
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    	RuntimeAppPublic,
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    fn feed_values_from_session_key(
    	id: UintAuthorityId,
    	index: u32,
    	nonce: u32,
    	values: Vec<(u32, u32)>,
    ) -> Result<dispatch::DispatchResult, TransactionValidityError> {
    
    	let now = <frame_system::Module<Test>>::block_number();
    	let sig = id.sign(&(nonce, now, &values).encode()).unwrap();
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    
    
    	<ModuleOracle as ValidateUnsigned>::validate_unsigned(
    		TransactionSource::External,
    
    		&OracleCall::feed_values(values.clone(), index, now, sig.clone()),
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    	)?;
    
    
    	Ok(ModuleOracle::feed_values(Origin::none(), values, index, now, sig))
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    }
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    fn feed_values(
    
    	from: AccountId,
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    	index: u32,
    	nonce: u32,
    	values: Vec<(u32, u32)>,
    ) -> Result<dispatch::DispatchResult, TransactionValidityError> {
    	let id = ModuleOracle::session_keys(from).unwrap();
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    	feed_values_from_session_key(id, index, nonce, values)
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    #[test]
    fn should_feed_values() {
    	new_test_ext().execute_with(|| {
    
    		let account_id: AccountId = 1;
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_ok!(feed_values(account_id, 0, 0, vec![(50, 1000), (51, 900), (52, 800)]));
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    
    		assert_eq!(
    
    			ModuleOracle::raw_values(&account_id, &50),
    			Some(TimestampedValue {
    				value: 1000,
    				timestamp: 12345,
    			})
    		);
    
    		assert_eq!(
    			ModuleOracle::raw_values(&account_id, &51),
    			Some(TimestampedValue {
    				value: 900,
    				timestamp: 12345,
    			})
    		);
    
    		assert_eq!(
    			ModuleOracle::raw_values(&account_id, &52),
    			Some(TimestampedValue {
    				value: 800,
    				timestamp: 12345,
    			})
    		);
    	});
    }
    
    #[test]
    fn should_feed_values_from_root() {
    	new_test_ext().execute_with(|| {
    		let account_id: AccountId = 1;
    
    		assert_ok!(ModuleOracle::feed_values(
    
    			Origin::root(),
    
    			vec![(50, 1000), (51, 900), (52, 800)],
    			0,
    
    			TestSignature(0, vec![])
    		));
    
    		assert_eq!(
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    			ModuleOracle::raw_values(&account_id, &50),
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    			Some(TimestampedValue {
    				value: 1000,
    				timestamp: 12345,
    			})
    		);
    
    		assert_eq!(
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    			ModuleOracle::raw_values(&account_id, &51),
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    			Some(TimestampedValue {
    				value: 900,
    				timestamp: 12345,
    			})
    		);
    
    		assert_eq!(
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    			ModuleOracle::raw_values(&account_id, &52),
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    			Some(TimestampedValue {
    				value: 800,
    				timestamp: 12345,
    			})
    		);
    	});
    }
    
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    #[test]
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    fn should_update_is_updated() {
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	new_test_ext().execute_with(|| {
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		let key: u32 = 50;
    		assert_eq!(ModuleOracle::is_updated(key), false);
    		assert_ok!(feed_values(1, 0, 0, vec![(key, 1000)]));
    		assert_ok!(feed_values(2, 1, 0, vec![(key, 1000)]));
    		assert_ok!(feed_values(3, 2, 0, vec![(key, 1000)]));
    		assert_eq!(ModuleOracle::is_updated(key), false);
    		assert_eq!(
    			ModuleOracle::get(&key).unwrap(),
    			TimestampedValue {
    				value: 1000,
    				timestamp: 12345
    			}
    		);
    		assert_eq!(ModuleOracle::is_updated(key), true);
    		ModuleOracle::on_finalize(1);
    		assert_ok!(feed_values(1, 0, 1, vec![(key, 1000)]));
    		assert_eq!(ModuleOracle::is_updated(key), false);
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	});
    }
    
    #[test]
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    fn should_validate_index() {
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	new_test_ext().execute_with(|| {
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_noop!(
    			feed_values(1, 1, 0, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_noop!(
    			feed_values(2, 0, 0, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    	});
    }
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    #[test]
    fn should_validate_nonce() {
    	new_test_ext().execute_with(|| {
    		assert_noop!(
    			feed_values(1, 0, 1, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_ok!(feed_values(1, 0, 0, vec![(50, 1000)]));
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_eq!(ModuleOracle::nonces(&1), 1);
    		ModuleOracle::on_finalize(1);
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_noop!(
    			feed_values(1, 0, 0, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    
    		assert_ok!(feed_values(1, 0, 1, vec![(50, 1000)]));
    
    		assert_eq!(ModuleOracle::nonces(&1), 2);
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	});
    }
    
    #[test]
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    fn should_read_raw_values() {
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	new_test_ext().execute_with(|| {
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		let key: u32 = 50;
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		let raw_values = ModuleOracle::read_raw_values(&key);
    		assert_eq!(raw_values, vec![]);
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_ok!(feed_values(1, 0, 0, vec![(key, 1000)]));
    		assert_ok!(feed_values(2, 1, 0, vec![(key, 1200)]));
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		let raw_values = ModuleOracle::read_raw_values(&key);
    		assert_eq!(
    			raw_values,
    			vec![
    				TimestampedValue {
    					value: 1000,
    					timestamp: 12345,
    				},
    				TimestampedValue {
    					value: 1200,
    					timestamp: 12345,
    				},
    			]
    		);
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	});
    }
    
    #[test]
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    fn should_combined_data() {
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	new_test_ext().execute_with(|| {
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		let key: u32 = 50;
    
    		assert_ok!(feed_values(1, 0, 0, vec![(key, 1300)]));
    		assert_ok!(feed_values(2, 1, 0, vec![(key, 1000)]));
    		assert_ok!(feed_values(3, 2, 0, vec![(key, 1200)]));
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    		let expected = Some(TimestampedValue {
    			value: 1200,
    			timestamp: 12345,
    		});
    
    		assert_eq!(ModuleOracle::get(&key), expected);
    
    		Timestamp::set_timestamp(23456);
    
    		assert_eq!(ModuleOracle::get(&key), expected);
    	});
    }
    
    #[test]
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    fn should_return_none_for_non_exist_key() {
    
    	new_test_ext().execute_with(|| {
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_eq!(ModuleOracle::get(&50), None);
    
    	});
    }
    
    #[test]
    fn multiple_calls_should_fail() {
    	new_test_ext().execute_with(|| {
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_ok!(feed_values(1, 0, 0, vec![(50, 1300)]));
    
    		assert_noop!(
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    			feed_values(1, 0, 1, vec![(50, 1300)]),
    			TransactionValidityError::Invalid(InvalidTransaction::Stale)
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    
    		ModuleOracle::on_finalize(1);
    
    		assert_ok!(feed_values(1, 0, 1, vec![(50, 1300)]));
    
    
    #[test]
    fn get_all_values_should_work() {
    	new_test_ext().execute_with(|| {
    		let eur: u32 = 1;
    		let jpy: u32 = 2;
    
    		assert_eq!(ModuleOracle::get_all_values(), vec![]);
    
    		// feed eur & jpy
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_ok!(feed_values(1, 0, 0, vec![(eur, 1300)]));
    		assert_ok!(feed_values(2, 1, 0, vec![(eur, 1000)]));
    		assert_ok!(feed_values(3, 2, 0, vec![(jpy, 9000)]));
    
    
    		// not enough eur & jpy prices
    		assert_eq!(ModuleOracle::get(&eur), None);
    		assert_eq!(ModuleOracle::get(&jpy), None);
    		assert_eq!(ModuleOracle::get_all_values(), vec![]);
    
    		// finalize block
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		ModuleOracle::on_finalize(1);
    
    
    		// feed eur & jpy
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_ok!(feed_values(3, 2, 1, vec![(eur, 1200)]));
    		assert_ok!(feed_values(1, 0, 1, vec![(jpy, 8000)]));
    
    
    		// enough eur prices
    		let eur_price = Some(TimestampedValue {
    			value: 1200,
    			timestamp: 12345,
    		});
    		assert_eq!(ModuleOracle::get(&eur), eur_price);
    
    		// not enough jpy prices
    		assert_eq!(ModuleOracle::get(&jpy), None);
    
    		assert_eq!(ModuleOracle::get_all_values(), vec![(eur, eur_price)]);
    
    		// feed jpy
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    		assert_ok!(feed_values(2, 1, 1, vec![(jpy, 7000)]));
    
    
    		// enough jpy prices
    		let jpy_price = Some(TimestampedValue {
    			value: 8000,
    			timestamp: 12345,
    		});
    		assert_eq!(ModuleOracle::get(&jpy), jpy_price);
    
    		assert_eq!(ModuleOracle::get_all_values(), vec![(eur, eur_price), (jpy, jpy_price)]);
    	});
    }
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    
    #[test]
    fn bad_index() {
    	new_test_ext().execute_with(|| {
    		assert_noop!(
    			feed_values(1, 255, 0, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    	});
    }
    
    #[test]
    fn change_member_should_work() {
    	new_test_ext().execute_with(|| {
    
    		<ModuleOracle as ChangeMembers<AccountId>>::change_members_sorted(&[4], &[1], &[2, 3, 4]);
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    
    		assert_noop!(
    			feed_values_from_session_key(10.into(), 0, 0, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    
    		assert_ok!(feed_values(2, 0, 0, vec![(50, 1000)]));
    
    		assert_noop!(
    			feed_values_from_session_key(40.into(), 2, 0, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    
    		assert_eq!(ModuleOracle::session_keys(&4), None);
    
    		assert_ok!(ModuleOracle::set_session_key(Origin::signed(4), 40.into()));
    
    		assert_ok!(feed_values(4, 2, 0, vec![(50, 1000)]));
    	});
    }
    
    #[test]
    fn should_clear_is_updated_on_change_member() {
    	new_test_ext().execute_with(|| {
    		assert_ok!(feed_values(1, 0, 0, vec![(50, 1000)]));
    		assert_ok!(feed_values(2, 1, 0, vec![(50, 1000)]));
    		assert_ok!(feed_values(3, 2, 0, vec![(50, 1000)]));
    
    		assert_eq!(
    			ModuleOracle::get(&50).unwrap(),
    			TimestampedValue {
    				value: 1000,
    				timestamp: 12345
    			}
    		);
    		assert_eq!(ModuleOracle::is_updated(50), true);
    
    		ModuleOracle::change_members_sorted(&[4], &[1], &[2, 3, 4]);
    
    		assert_eq!(ModuleOracle::is_updated(50), false);
    	});
    }
    
    #[test]
    fn should_clear_data_for_removed_members() {
    	new_test_ext().execute_with(|| {
    		assert_ok!(feed_values(1, 0, 0, vec![(50, 1000)]));
    		assert_ok!(feed_values(2, 1, 0, vec![(50, 1000)]));
    
    		ModuleOracle::change_members_sorted(&[4], &[1], &[2, 3, 4]);
    
    		assert_eq!(ModuleOracle::raw_values(&1, 50), None);
    		assert_eq!(ModuleOracle::session_keys(&1), None);
    		assert_eq!(ModuleOracle::nonces(&1), 0);
    	});
    }
    
    #[test]
    fn change_session_key() {
    	new_test_ext().execute_with(|| {
    		assert_ok!(ModuleOracle::set_session_key(Origin::signed(1), 11.into()));
    
    		assert_noop!(
    			feed_values_from_session_key(10.into(), 0, 0, vec![(50, 1000)]),
    			TransactionValidityError::Invalid(InvalidTransaction::BadProof)
    		);
    
    		assert_ok!(feed_values_from_session_key(11.into(), 0, 0, vec![(50, 1000)]));
    	});
    }