mock.rs 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. #![cfg(test)]
  2. use crate::InputValidationLengthConstraint;
  3. use crate::*;
  4. use core::iter::FromIterator;
  5. use frame_support::traits::{OnFinalize, OnInitialize};
  6. pub use frame_support::{
  7. assert_err, assert_ok, impl_outer_event, impl_outer_origin, parameter_types,
  8. };
  9. use sp_core::H256;
  10. use sp_runtime::{
  11. testing::Header,
  12. traits::{BlakeTwo256, IdentityLookup},
  13. Perbill,
  14. };
  15. use std::cell::RefCell;
  16. /// Runtime Types
  17. pub type ClassId = <Runtime as Trait>::ClassId;
  18. pub type EntityId = <Runtime as Trait>::EntityId;
  19. pub type Nonce = <Runtime as Trait>::Nonce;
  20. pub type Hashed = <Runtime as frame_system::Trait>::Hash;
  21. pub type TestCuratorId = CuratorId<Runtime>;
  22. pub type CuratorGroupId = <Runtime as Trait>::CuratorGroupId;
  23. pub type MemberId = <Runtime as common::Trait>::MemberId;
  24. /// Origins
  25. pub const LEAD_ORIGIN: u64 = 1;
  26. pub const FIRST_CURATOR_ORIGIN: u64 = 2;
  27. pub const SECOND_CURATOR_ORIGIN: u64 = 3;
  28. pub const FIRST_MEMBER_ORIGIN: u64 = 4;
  29. pub const SECOND_MEMBER_ORIGIN: u64 = 5;
  30. pub const UNKNOWN_ORIGIN: u64 = 7777;
  31. /// Runtime Id's
  32. pub const FIRST_CURATOR_ID: TestCuratorId = 1;
  33. pub const SECOND_CURATOR_ID: TestCuratorId = 2;
  34. pub const FIRST_CURATOR_GROUP_ID: CuratorGroupId = 1;
  35. pub const SECOND_CURATOR_GROUP_ID: CuratorGroupId = 2;
  36. pub const FIRST_MEMBER_ID: MemberId = 1;
  37. pub const SECOND_MEMBER_ID: MemberId = 2;
  38. pub const FIRST_CLASS_ID: ClassId = 1;
  39. pub const SECOND_CLASS_ID: ClassId = 2;
  40. pub const FIRST_ENTITY_ID: EntityId = 1;
  41. pub const SECOND_ENTITY_ID: EntityId = 2;
  42. pub const THIRD_ENTITY_ID: EntityId = 3;
  43. pub const UNKNOWN_CLASS_ID: ClassId = 111;
  44. pub const UNKNOWN_ENTITY_ID: EntityId = 222;
  45. pub const UNKNOWN_PROPERTY_ID: PropertyId = 333;
  46. pub const UNKNOWN_SCHEMA_ID: SchemaId = 444;
  47. pub const UNKNOWN_CURATOR_GROUP_ID: CuratorGroupId = 555;
  48. pub const UNKNOWN_CURATOR_ID: CuratorGroupId = 555;
  49. pub const UNKNOWN_MEMBER_ID: CuratorGroupId = 777;
  50. pub const FIRST_SCHEMA_ID: SchemaId = 0;
  51. pub const SECOND_SCHEMA_ID: SchemaId = 1;
  52. pub const FIRST_PROPERTY_ID: SchemaId = 0;
  53. pub const SECOND_PROPERTY_ID: SchemaId = 1;
  54. impl_outer_origin! {
  55. pub enum Origin for Runtime {}
  56. }
  57. // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
  58. #[derive(Clone, Default, PartialEq, Eq, Debug)]
  59. pub struct Runtime;
  60. parameter_types! {
  61. pub const BlockHashCount: u64 = 250;
  62. pub const MaximumBlockWeight: u32 = 1024;
  63. pub const MaximumBlockLength: u32 = 2 * 1024;
  64. pub const AvailableBlockRatio: Perbill = Perbill::one();
  65. pub const MinimumPeriod: u64 = 5;
  66. }
  67. thread_local! {
  68. static PROPERTY_NAME_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  69. static PROPERTY_DESCRIPTION_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  70. static CLASS_NAME_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  71. static CLASS_DESCRIPTION_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  72. static MAX_NUMBER_OF_CLASSES: RefCell<MaxNumber> = RefCell::new(0);
  73. static MAX_NUMBER_OF_MAINTAINERS_PER_CLASS: RefCell<MaxNumber> = RefCell::new(0);
  74. static MAX_NUMBER_OF_SCHEMAS_PER_CLASS: RefCell<MaxNumber> = RefCell::new(0);
  75. static MAX_NUMBER_OF_PROPERTIES_PER_CLASS: RefCell<MaxNumber> = RefCell::new(0);
  76. static MAX_NUMBER_OF_ENTITIES_PER_CLASS: RefCell<EntityId> = RefCell::new(0);
  77. static MAX_NUMBER_OF_CURATORS_PER_GROUP: RefCell<MaxNumber> = RefCell::new(0);
  78. static MAX_NUMBER_OF_OPERATIONS_DURING_ATOMIC_BATCHING: RefCell<MaxNumber> = RefCell::new(0);
  79. static VEC_MAX_LENGTH_CONSTRAINT: RefCell<VecMaxLength> = RefCell::new(0);
  80. static TEXT_MAX_LENGTH_CONSTRAINT: RefCell<TextMaxLength> = RefCell::new(0);
  81. static HASHED_TEXT_MAX_LENGTH_CONSTRAINT: RefCell<HashedTextMaxLength> = RefCell::new(Some(0));
  82. static INDIVIDUAL_ENTITIES_CREATION_LIMIT: RefCell<EntityId> = RefCell::new(0);
  83. }
  84. pub struct PropertyNameLengthConstraint;
  85. impl Get<InputValidationLengthConstraint> for PropertyNameLengthConstraint {
  86. fn get() -> InputValidationLengthConstraint {
  87. PROPERTY_NAME_CONSTRAINT.with(|v| *v.borrow())
  88. }
  89. }
  90. pub struct PropertyDescriptionLengthConstraint;
  91. impl Get<InputValidationLengthConstraint> for PropertyDescriptionLengthConstraint {
  92. fn get() -> InputValidationLengthConstraint {
  93. PROPERTY_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow())
  94. }
  95. }
  96. pub struct ClassNameLengthConstraint;
  97. impl Get<InputValidationLengthConstraint> for ClassNameLengthConstraint {
  98. fn get() -> InputValidationLengthConstraint {
  99. CLASS_NAME_CONSTRAINT.with(|v| *v.borrow())
  100. }
  101. }
  102. pub struct ClassDescriptionLengthConstraint;
  103. impl Get<InputValidationLengthConstraint> for ClassDescriptionLengthConstraint {
  104. fn get() -> InputValidationLengthConstraint {
  105. CLASS_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow())
  106. }
  107. }
  108. pub struct MaxNumberOfClasses;
  109. impl Get<MaxNumber> for MaxNumberOfClasses {
  110. fn get() -> MaxNumber {
  111. MAX_NUMBER_OF_CLASSES.with(|v| *v.borrow())
  112. }
  113. }
  114. pub struct MaxNumberOfMaintainersPerClass;
  115. impl Get<MaxNumber> for MaxNumberOfMaintainersPerClass {
  116. fn get() -> MaxNumber {
  117. MAX_NUMBER_OF_MAINTAINERS_PER_CLASS.with(|v| *v.borrow())
  118. }
  119. }
  120. pub struct MaxNumberOfCuratorsPerGroup;
  121. impl Get<MaxNumber> for MaxNumberOfCuratorsPerGroup {
  122. fn get() -> MaxNumber {
  123. MAX_NUMBER_OF_CURATORS_PER_GROUP.with(|v| *v.borrow())
  124. }
  125. }
  126. pub struct MaxNumberOfSchemasPerClass;
  127. impl Get<MaxNumber> for MaxNumberOfSchemasPerClass {
  128. fn get() -> MaxNumber {
  129. MAX_NUMBER_OF_SCHEMAS_PER_CLASS.with(|v| *v.borrow())
  130. }
  131. }
  132. pub struct MaxNumberOfPropertiesPerSchema;
  133. impl Get<MaxNumber> for MaxNumberOfPropertiesPerSchema {
  134. fn get() -> MaxNumber {
  135. MAX_NUMBER_OF_PROPERTIES_PER_CLASS.with(|v| *v.borrow())
  136. }
  137. }
  138. pub struct MaxNumberOfOperationsDuringAtomicBatching;
  139. impl Get<MaxNumber> for MaxNumberOfOperationsDuringAtomicBatching {
  140. fn get() -> MaxNumber {
  141. MAX_NUMBER_OF_OPERATIONS_DURING_ATOMIC_BATCHING.with(|v| *v.borrow())
  142. }
  143. }
  144. pub struct VecMaxLengthConstraint;
  145. impl Get<VecMaxLength> for VecMaxLengthConstraint {
  146. fn get() -> VecMaxLength {
  147. VEC_MAX_LENGTH_CONSTRAINT.with(|v| *v.borrow())
  148. }
  149. }
  150. pub struct TextMaxLengthConstraint;
  151. impl Get<TextMaxLength> for TextMaxLengthConstraint {
  152. fn get() -> TextMaxLength {
  153. TEXT_MAX_LENGTH_CONSTRAINT.with(|v| *v.borrow())
  154. }
  155. }
  156. pub struct HashedTextMaxLengthConstraint;
  157. impl Get<HashedTextMaxLength> for HashedTextMaxLengthConstraint {
  158. fn get() -> HashedTextMaxLength {
  159. HASHED_TEXT_MAX_LENGTH_CONSTRAINT.with(|v| *v.borrow())
  160. }
  161. }
  162. pub struct MaxNumberOfEntitiesPerClass;
  163. impl Get<EntityId> for MaxNumberOfEntitiesPerClass {
  164. fn get() -> EntityId {
  165. MAX_NUMBER_OF_ENTITIES_PER_CLASS.with(|v| *v.borrow())
  166. }
  167. }
  168. pub struct IndividualEntitiesCreationLimit;
  169. impl Get<EntityId> for IndividualEntitiesCreationLimit {
  170. fn get() -> EntityId {
  171. INDIVIDUAL_ENTITIES_CREATION_LIMIT.with(|v| *v.borrow())
  172. }
  173. }
  174. impl frame_system::Trait for Runtime {
  175. type BaseCallFilter = ();
  176. type Origin = Origin;
  177. type Call = ();
  178. type Index = u64;
  179. type BlockNumber = u64;
  180. type Hash = H256;
  181. type Hashing = BlakeTwo256;
  182. type AccountId = u64;
  183. type Lookup = IdentityLookup<Self::AccountId>;
  184. type Header = Header;
  185. type Event = TestEvent;
  186. type BlockHashCount = BlockHashCount;
  187. type MaximumBlockWeight = MaximumBlockWeight;
  188. type DbWeight = ();
  189. type BlockExecutionWeight = ();
  190. type ExtrinsicBaseWeight = ();
  191. type MaximumExtrinsicWeight = ();
  192. type MaximumBlockLength = MaximumBlockLength;
  193. type AvailableBlockRatio = AvailableBlockRatio;
  194. type Version = ();
  195. type PalletInfo = ();
  196. type AccountData = ();
  197. type OnNewAccount = ();
  198. type OnKilledAccount = ();
  199. type SystemWeightInfo = ();
  200. }
  201. mod test_events {
  202. pub use crate::Event;
  203. }
  204. impl_outer_event! {
  205. pub enum TestEvent for Runtime {
  206. test_events<T>,
  207. frame_system<T>,
  208. }
  209. }
  210. impl Trait for Runtime {
  211. type Event = TestEvent;
  212. type Nonce = u64;
  213. type ClassId = u64;
  214. type EntityId = u64;
  215. type CuratorGroupId = u64;
  216. type PropertyNameLengthConstraint = PropertyNameLengthConstraint;
  217. type PropertyDescriptionLengthConstraint = PropertyDescriptionLengthConstraint;
  218. type ClassNameLengthConstraint = ClassNameLengthConstraint;
  219. type ClassDescriptionLengthConstraint = ClassDescriptionLengthConstraint;
  220. type MaxNumberOfClasses = MaxNumberOfClasses;
  221. type MaxNumberOfMaintainersPerClass = MaxNumberOfMaintainersPerClass;
  222. type MaxNumberOfCuratorsPerGroup = MaxNumberOfCuratorsPerGroup;
  223. type MaxNumberOfSchemasPerClass = MaxNumberOfSchemasPerClass;
  224. type MaxNumberOfPropertiesPerSchema = MaxNumberOfPropertiesPerSchema;
  225. type MaxNumberOfOperationsDuringAtomicBatching = MaxNumberOfOperationsDuringAtomicBatching;
  226. type VecMaxLengthConstraint = VecMaxLengthConstraint;
  227. type TextMaxLengthConstraint = TextMaxLengthConstraint;
  228. type HashedTextMaxLengthConstraint = HashedTextMaxLengthConstraint;
  229. type MaxNumberOfEntitiesPerClass = MaxNumberOfEntitiesPerClass;
  230. type IndividualEntitiesCreationLimit = IndividualEntitiesCreationLimit;
  231. type WorkingGroup = ();
  232. type MemberOriginValidator = ();
  233. }
  234. impl common::working_group::WorkingGroupAuthenticator<Runtime> for () {
  235. fn ensure_worker_origin(
  236. _origin: <Runtime as frame_system::Trait>::Origin,
  237. _worker_id: &<Runtime as common::Trait>::ActorId,
  238. ) -> DispatchResult {
  239. unimplemented!()
  240. }
  241. fn ensure_leader_origin(_origin: <Runtime as frame_system::Trait>::Origin) -> DispatchResult {
  242. unimplemented!()
  243. }
  244. fn get_leader_member_id() -> Option<<Runtime as common::Trait>::MemberId> {
  245. unimplemented!()
  246. }
  247. fn is_leader_account_id(account_id: &<Runtime as frame_system::Trait>::AccountId) -> bool {
  248. let lead_account_id = ensure_signed(Origin::signed(LEAD_ORIGIN)).unwrap();
  249. *account_id == lead_account_id
  250. }
  251. fn is_worker_account_id(
  252. account_id: &<Runtime as frame_system::Trait>::AccountId,
  253. worker_id: &<Runtime as common::Trait>::ActorId,
  254. ) -> bool {
  255. let first_curator_account_id = ensure_signed(Origin::signed(FIRST_CURATOR_ORIGIN)).unwrap();
  256. let second_curator_account_id =
  257. ensure_signed(Origin::signed(SECOND_CURATOR_ORIGIN)).unwrap();
  258. (first_curator_account_id == *account_id && FIRST_CURATOR_ID == *worker_id)
  259. || (second_curator_account_id == *account_id && SECOND_CURATOR_ID == *worker_id)
  260. }
  261. }
  262. impl common::Trait for Runtime {
  263. type MemberId = u64;
  264. type ActorId = u64;
  265. }
  266. impl common::origin::MemberOriginValidator<Origin, u64, u64> for () {
  267. fn ensure_member_controller_account_origin(
  268. _origin: Origin,
  269. _member_id: u64,
  270. ) -> Result<u64, DispatchError> {
  271. unimplemented!()
  272. }
  273. fn is_member_controller_account(member_id: &u64, account_id: &u64) -> bool {
  274. let unknown_member_account_id = ensure_signed(Origin::signed(UNKNOWN_ORIGIN)).unwrap();
  275. *member_id < MaxNumberOfEntitiesPerClass::get() && unknown_member_account_id != *account_id
  276. }
  277. }
  278. pub struct ExtBuilder {
  279. property_name_constraint: InputValidationLengthConstraint,
  280. property_description_constraint: InputValidationLengthConstraint,
  281. class_name_constraint: InputValidationLengthConstraint,
  282. class_description_constraint: InputValidationLengthConstraint,
  283. max_number_of_classes: MaxNumber,
  284. max_number_of_maintainers_per_class: MaxNumber,
  285. max_number_of_schemas_per_class: MaxNumber,
  286. max_number_of_properties_per_class: MaxNumber,
  287. max_number_of_entities_per_class: EntityId,
  288. max_number_of_curators_per_group: MaxNumber,
  289. max_number_of_operations_during_atomic_batching: MaxNumber,
  290. vec_max_length_constraint: VecMaxLength,
  291. text_max_length_constraint: TextMaxLength,
  292. hashed_text_max_length_constraint: HashedTextMaxLength,
  293. individual_entities_creation_limit: EntityId,
  294. }
  295. impl Default for ExtBuilder {
  296. fn default() -> Self {
  297. Self {
  298. property_name_constraint: InputValidationLengthConstraint::new(1, 49),
  299. property_description_constraint: InputValidationLengthConstraint::new(1, 500),
  300. class_name_constraint: InputValidationLengthConstraint::new(1, 49),
  301. class_description_constraint: InputValidationLengthConstraint::new(1, 500),
  302. max_number_of_classes: 100,
  303. max_number_of_maintainers_per_class: 10,
  304. max_number_of_schemas_per_class: 20,
  305. max_number_of_properties_per_class: 40,
  306. max_number_of_entities_per_class: 400,
  307. max_number_of_curators_per_group: 50,
  308. max_number_of_operations_during_atomic_batching: 500,
  309. vec_max_length_constraint: 200,
  310. text_max_length_constraint: 5000,
  311. hashed_text_max_length_constraint: Some(25000),
  312. individual_entities_creation_limit: 50,
  313. }
  314. }
  315. }
  316. impl ExtBuilder {
  317. pub fn set_associated_consts(&self) {
  318. PROPERTY_NAME_CONSTRAINT.with(|v| *v.borrow_mut() = self.property_name_constraint);
  319. PROPERTY_DESCRIPTION_CONSTRAINT
  320. .with(|v| *v.borrow_mut() = self.property_description_constraint);
  321. CLASS_NAME_CONSTRAINT.with(|v| *v.borrow_mut() = self.class_name_constraint);
  322. CLASS_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow_mut() = self.class_description_constraint);
  323. MAX_NUMBER_OF_CLASSES.with(|v| *v.borrow_mut() = self.max_number_of_classes);
  324. MAX_NUMBER_OF_MAINTAINERS_PER_CLASS
  325. .with(|v| *v.borrow_mut() = self.max_number_of_maintainers_per_class);
  326. MAX_NUMBER_OF_SCHEMAS_PER_CLASS
  327. .with(|v| *v.borrow_mut() = self.max_number_of_schemas_per_class);
  328. MAX_NUMBER_OF_PROPERTIES_PER_CLASS
  329. .with(|v| *v.borrow_mut() = self.max_number_of_properties_per_class);
  330. MAX_NUMBER_OF_ENTITIES_PER_CLASS
  331. .with(|v| *v.borrow_mut() = self.max_number_of_entities_per_class);
  332. MAX_NUMBER_OF_CURATORS_PER_GROUP
  333. .with(|v| *v.borrow_mut() = self.max_number_of_curators_per_group);
  334. MAX_NUMBER_OF_OPERATIONS_DURING_ATOMIC_BATCHING
  335. .with(|v| *v.borrow_mut() = self.max_number_of_operations_during_atomic_batching);
  336. VEC_MAX_LENGTH_CONSTRAINT.with(|v| *v.borrow_mut() = self.vec_max_length_constraint);
  337. TEXT_MAX_LENGTH_CONSTRAINT.with(|v| *v.borrow_mut() = self.text_max_length_constraint);
  338. HASHED_TEXT_MAX_LENGTH_CONSTRAINT
  339. .with(|v| *v.borrow_mut() = self.hashed_text_max_length_constraint);
  340. INDIVIDUAL_ENTITIES_CREATION_LIMIT
  341. .with(|v| *v.borrow_mut() = self.individual_entities_creation_limit);
  342. }
  343. pub fn build(self, config: GenesisConfig<Runtime>) -> sp_io::TestExternalities {
  344. self.set_associated_consts();
  345. let mut t = frame_system::GenesisConfig::default()
  346. .build_storage::<Runtime>()
  347. .unwrap();
  348. config.assimilate_storage(&mut t).unwrap();
  349. t.into()
  350. }
  351. }
  352. // This function basically just builds a genesis storage key/value store according to
  353. // our desired mockup.
  354. fn default_content_directory_genesis_config() -> GenesisConfig<Runtime> {
  355. GenesisConfig {
  356. class_by_id: vec![],
  357. entity_by_id: vec![],
  358. curator_group_by_id: vec![],
  359. next_class_id: 1,
  360. next_entity_id: 1,
  361. next_curator_group_id: 1,
  362. }
  363. }
  364. pub fn with_test_externalities<R, F: FnOnce() -> R>(f: F) -> R {
  365. let default_genesis_config = default_content_directory_genesis_config();
  366. /*
  367. Events are not emitted on block 0.
  368. So any dispatchable calls made during genesis block formation will have no events emitted.
  369. https://substrate.dev/recipes/2-appetizers/4-events.html
  370. */
  371. let func = || {
  372. run_to_block(1);
  373. f()
  374. };
  375. ExtBuilder::default()
  376. .build(default_genesis_config)
  377. .execute_with(func)
  378. }
  379. pub fn generate_text(len: usize) -> Vec<u8> {
  380. vec![b'x'; len]
  381. }
  382. impl<ClassId: Default + BaseArithmetic + Clone + Copy> Property<ClassId> {
  383. pub fn required(mut self) -> Self {
  384. self.required = true;
  385. self
  386. }
  387. pub fn unique(mut self) -> Self {
  388. self.unique = true;
  389. self
  390. }
  391. }
  392. // Events
  393. type RawTestEvent = RawEvent<
  394. CuratorGroupId,
  395. TestCuratorId,
  396. ClassId,
  397. EntityId,
  398. EntityController<MemberId>,
  399. EntityCreationVoucher<Runtime>,
  400. bool,
  401. Actor<CuratorGroupId, TestCuratorId, MemberId>,
  402. Nonce,
  403. Option<ReferenceCounterSideEffects<Runtime>>,
  404. Option<(EntityId, EntityReferenceCounterSideEffect)>,
  405. u32,
  406. ClassPermissions<CuratorGroupId>,
  407. Property<ClassId>,
  408. InputPropertyValue<Runtime>,
  409. InputValue<Runtime>,
  410. OperationType<Runtime>,
  411. >;
  412. pub fn get_test_event(raw_event: RawTestEvent) -> TestEvent {
  413. TestEvent::test_events(raw_event)
  414. }
  415. pub fn assert_event(tested_event: TestEvent, number_of_events_after_call: usize) {
  416. // Ensure runtime events length is equal to expected number of events after call
  417. assert_eq!(System::events().len(), number_of_events_after_call);
  418. // Ensure last emitted event is equal to expected one
  419. assert_eq!(System::events().iter().last().unwrap().event, tested_event);
  420. }
  421. pub fn assert_failure(
  422. call_result: DispatchResult,
  423. expected_error: Error<Runtime>,
  424. number_of_events_before_call: usize,
  425. ) {
  426. // Ensure call result is equal to expected error
  427. assert_err!(call_result, expected_error);
  428. // Ensure no other events emitted after call
  429. assert_eq!(System::events().len(), number_of_events_before_call);
  430. }
  431. // Curator groups
  432. pub fn next_curator_group_id() -> CuratorGroupId {
  433. TestModule::next_curator_group_id()
  434. }
  435. pub fn add_curator_group(lead_origin: u64) -> DispatchResult {
  436. TestModule::add_curator_group(Origin::signed(lead_origin))
  437. }
  438. pub fn remove_curator_group(lead_origin: u64, curator_group_id: CuratorGroupId) -> DispatchResult {
  439. TestModule::remove_curator_group(Origin::signed(lead_origin), curator_group_id)
  440. }
  441. pub fn add_curator_to_group(
  442. lead_origin: u64,
  443. curator_group_id: CuratorGroupId,
  444. curator_id: TestCuratorId,
  445. ) -> DispatchResult {
  446. TestModule::add_curator_to_group(Origin::signed(lead_origin), curator_group_id, curator_id)
  447. }
  448. pub fn remove_curator_from_group(
  449. lead_origin: u64,
  450. curator_group_id: CuratorGroupId,
  451. curator_id: TestCuratorId,
  452. ) -> DispatchResult {
  453. TestModule::remove_curator_from_group(Origin::signed(lead_origin), curator_group_id, curator_id)
  454. }
  455. pub fn set_curator_group_status(
  456. lead_origin: u64,
  457. curator_group_id: CuratorGroupId,
  458. is_active: bool,
  459. ) -> DispatchResult {
  460. TestModule::set_curator_group_status(Origin::signed(lead_origin), curator_group_id, is_active)
  461. }
  462. pub fn curator_group_by_id(curator_group_id: CuratorGroupId) -> CuratorGroup<TestCuratorId> {
  463. TestModule::curator_group_by_id(curator_group_id)
  464. }
  465. pub fn curator_group_exists(curator_group_id: CuratorGroupId) -> bool {
  466. CuratorGroupById::<Runtime>::contains_key(curator_group_id)
  467. }
  468. // Classes
  469. pub enum ClassType {
  470. Valid,
  471. NameTooLong,
  472. NameTooShort,
  473. DescriptionTooLong,
  474. DescriptionTooShort,
  475. InvalidMaximumEntitiesCount,
  476. InvalidDefaultVoucherUpperBound,
  477. DefaultVoucherUpperBoundExceedsMaximumEntitiesCount,
  478. MaintainersLimitReached,
  479. CuratorGroupDoesNotExist,
  480. }
  481. pub fn get_class_for(class_type: ClassType) -> Class<EntityId, ClassId, CuratorGroupId> {
  482. let mut class = create_class_with_default_permissions();
  483. match class_type {
  484. ClassType::Valid => (),
  485. ClassType::NameTooShort => {
  486. class.set_name(generate_text(
  487. ClassNameLengthConstraint::get().min() as usize - 1,
  488. ));
  489. }
  490. ClassType::NameTooLong => {
  491. class.set_name(generate_text(
  492. ClassNameLengthConstraint::get().max() as usize + 1,
  493. ));
  494. }
  495. ClassType::DescriptionTooLong => {
  496. class.set_description(generate_text(
  497. ClassDescriptionLengthConstraint::get().max() as usize + 1,
  498. ));
  499. }
  500. ClassType::DescriptionTooShort => {
  501. class.set_description(generate_text(
  502. ClassDescriptionLengthConstraint::get().min() as usize - 1,
  503. ));
  504. }
  505. ClassType::InvalidMaximumEntitiesCount => {
  506. class.set_maximum_entities_count(MaxNumberOfEntitiesPerClass::get() + 1);
  507. }
  508. ClassType::InvalidDefaultVoucherUpperBound => {
  509. class.set_default_entity_creation_voucher_upper_bound(
  510. IndividualEntitiesCreationLimit::get() + 1,
  511. );
  512. }
  513. ClassType::DefaultVoucherUpperBoundExceedsMaximumEntitiesCount => {
  514. class.set_maximum_entities_count(5);
  515. class.set_maximum_entities_count(3);
  516. }
  517. ClassType::MaintainersLimitReached => {
  518. let mut maintainers = BTreeSet::new();
  519. for curator_group_id in 1..=(MaxNumberOfMaintainersPerClass::get() + 1) {
  520. maintainers.insert(curator_group_id as CuratorGroupId);
  521. }
  522. class.get_permissions_mut().set_maintainers(maintainers);
  523. }
  524. ClassType::CuratorGroupDoesNotExist => {
  525. let maintainers = BTreeSet::from_iter(vec![UNKNOWN_CURATOR_GROUP_ID].into_iter());
  526. class.get_permissions_mut().set_maintainers(maintainers);
  527. }
  528. };
  529. class
  530. }
  531. pub fn create_simple_class(lead_origin: u64, class_type: ClassType) -> DispatchResult {
  532. let class = get_class_for(class_type);
  533. TestModule::create_class(
  534. Origin::signed(lead_origin),
  535. class.get_name().to_owned(),
  536. class.get_description().to_owned(),
  537. class.get_permissions_ref().to_owned(),
  538. class.get_maximum_entities_count(),
  539. class.get_default_entity_creation_voucher_upper_bound(),
  540. )
  541. }
  542. pub fn create_class_with_default_permissions() -> Class<EntityId, ClassId, CuratorGroupId> {
  543. Class::new(
  544. ClassPermissions::default(),
  545. generate_text(ClassNameLengthConstraint::get().max() as usize),
  546. generate_text(ClassDescriptionLengthConstraint::get().max() as usize),
  547. MaxNumberOfEntitiesPerClass::get(),
  548. IndividualEntitiesCreationLimit::get(),
  549. )
  550. }
  551. pub fn add_maintainer_to_class(
  552. lead_origin: u64,
  553. class_id: ClassId,
  554. curator_group_id: CuratorGroupId,
  555. ) -> DispatchResult {
  556. TestModule::add_maintainer_to_class(Origin::signed(lead_origin), class_id, curator_group_id)
  557. }
  558. pub fn remove_maintainer_from_class(
  559. lead_origin: u64,
  560. class_id: ClassId,
  561. curator_group_id: CuratorGroupId,
  562. ) -> DispatchResult {
  563. TestModule::remove_maintainer_from_class(
  564. Origin::signed(lead_origin),
  565. class_id,
  566. curator_group_id,
  567. )
  568. }
  569. pub fn update_class_permissions(
  570. lead_origin: u64,
  571. class_id: ClassId,
  572. updated_any_member: Option<bool>,
  573. updated_entity_creation_blocked: Option<bool>,
  574. updated_all_entity_property_values_locked: Option<bool>,
  575. updated_maintainers: Option<BTreeSet<CuratorGroupId>>,
  576. ) -> DispatchResult {
  577. TestModule::update_class_permissions(
  578. Origin::signed(lead_origin),
  579. class_id,
  580. updated_any_member,
  581. updated_entity_creation_blocked,
  582. updated_all_entity_property_values_locked,
  583. updated_maintainers,
  584. )
  585. }
  586. pub fn add_class_schema(
  587. lead_origin: u64,
  588. class_id: ClassId,
  589. existing_properties: BTreeSet<PropertyId>,
  590. new_properties: Vec<Property<ClassId>>,
  591. ) -> DispatchResult {
  592. TestModule::add_class_schema(
  593. Origin::signed(lead_origin),
  594. class_id,
  595. existing_properties,
  596. new_properties,
  597. )
  598. }
  599. pub fn update_class_schema_status(
  600. lead_origin: u64,
  601. class_id: ClassId,
  602. schema_id: SchemaId,
  603. status: bool,
  604. ) -> DispatchResult {
  605. TestModule::update_class_schema_status(Origin::signed(lead_origin), class_id, schema_id, status)
  606. }
  607. pub fn next_class_id() -> ClassId {
  608. TestModule::next_class_id()
  609. }
  610. pub fn class_by_id(class_id: ClassId) -> Class<EntityId, ClassId, CuratorGroupId> {
  611. TestModule::class_by_id(class_id)
  612. }
  613. pub fn class_exists(class_id: ClassId) -> bool {
  614. ClassById::<Runtime>::contains_key(class_id)
  615. }
  616. // Vouchers
  617. pub fn update_entity_creation_voucher(
  618. lead_origin: u64,
  619. class_id: ClassId,
  620. controller: EntityController<MemberId>,
  621. maximum_entities_count: EntityId,
  622. ) -> DispatchResult {
  623. TestModule::update_entity_creation_voucher(
  624. Origin::signed(lead_origin),
  625. class_id,
  626. controller,
  627. maximum_entities_count,
  628. )
  629. }
  630. pub fn entity_creation_vouchers(
  631. class_id: ClassId,
  632. entity_controller: &EntityController<MemberId>,
  633. ) -> EntityCreationVoucher<Runtime> {
  634. TestModule::entity_creation_vouchers(class_id, entity_controller)
  635. }
  636. pub fn entity_creation_voucher_exists(
  637. class_id: ClassId,
  638. entity_controller: &EntityController<MemberId>,
  639. ) -> bool {
  640. EntityCreationVouchers::<Runtime>::contains_key(class_id, entity_controller)
  641. }
  642. // Entities
  643. pub fn entity_exists(entity_id: EntityId) -> bool {
  644. EntityById::<Runtime>::contains_key(entity_id)
  645. }
  646. pub fn entity_by_id(entity_id: EntityId) -> Entity<ClassId, MemberId, Hashed, EntityId, Nonce> {
  647. TestModule::entity_by_id(entity_id)
  648. }
  649. pub fn next_entity_id() -> EntityId {
  650. TestModule::next_entity_id()
  651. }
  652. pub fn create_entity(
  653. origin: u64,
  654. class_id: ClassId,
  655. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  656. ) -> DispatchResult {
  657. TestModule::create_entity(Origin::signed(origin), class_id, actor)
  658. }
  659. pub fn remove_entity(
  660. origin: u64,
  661. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  662. entity_id: EntityId,
  663. ) -> DispatchResult {
  664. TestModule::remove_entity(Origin::signed(origin), actor, entity_id)
  665. }
  666. pub fn update_entity_permissions(
  667. lead_origin: u64,
  668. entity_id: EntityId,
  669. updated_frozen: Option<bool>,
  670. updated_referenceable: Option<bool>,
  671. ) -> DispatchResult {
  672. TestModule::update_entity_permissions(
  673. Origin::signed(lead_origin),
  674. entity_id,
  675. updated_frozen,
  676. updated_referenceable,
  677. )
  678. }
  679. pub fn add_schema_support_to_entity(
  680. origin: u64,
  681. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  682. entity_id: EntityId,
  683. schema_id: SchemaId,
  684. new_property_values: BTreeMap<PropertyId, InputPropertyValue<Runtime>>,
  685. ) -> DispatchResult {
  686. TestModule::add_schema_support_to_entity(
  687. Origin::signed(origin),
  688. actor,
  689. entity_id,
  690. schema_id,
  691. new_property_values,
  692. )
  693. }
  694. pub fn update_entity_property_values(
  695. origin: u64,
  696. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  697. entity_id: EntityId,
  698. new_property_values: BTreeMap<PropertyId, InputPropertyValue<Runtime>>,
  699. ) -> DispatchResult {
  700. TestModule::update_entity_property_values(
  701. Origin::signed(origin),
  702. actor,
  703. entity_id,
  704. new_property_values,
  705. )
  706. }
  707. pub fn clear_entity_property_vector(
  708. origin: u64,
  709. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  710. entity_id: EntityId,
  711. in_class_schema_property_id: PropertyId,
  712. ) -> DispatchResult {
  713. TestModule::clear_entity_property_vector(
  714. Origin::signed(origin),
  715. actor,
  716. entity_id,
  717. in_class_schema_property_id,
  718. )
  719. }
  720. pub fn insert_at_entity_property_vector(
  721. origin: u64,
  722. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  723. entity_id: EntityId,
  724. in_class_schema_property_id: PropertyId,
  725. index_in_property_vector: VecMaxLength,
  726. property_value: InputValue<Runtime>,
  727. nonce: Nonce,
  728. ) -> DispatchResult {
  729. TestModule::insert_at_entity_property_vector(
  730. Origin::signed(origin),
  731. actor,
  732. entity_id,
  733. in_class_schema_property_id,
  734. index_in_property_vector,
  735. property_value,
  736. nonce,
  737. )
  738. }
  739. pub fn remove_at_entity_property_vector(
  740. origin: u64,
  741. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  742. entity_id: EntityId,
  743. in_class_schema_property_id: PropertyId,
  744. index_in_property_vector: VecMaxLength,
  745. nonce: Nonce,
  746. ) -> DispatchResult {
  747. TestModule::remove_at_entity_property_vector(
  748. Origin::signed(origin),
  749. actor,
  750. entity_id,
  751. in_class_schema_property_id,
  752. index_in_property_vector,
  753. nonce,
  754. )
  755. }
  756. pub fn transfer_entity_ownership(
  757. origin: u64,
  758. entity_id: EntityId,
  759. new_controller: EntityController<MemberId>,
  760. new_property_value_references_with_same_owner_flag_set: BTreeMap<
  761. PropertyId,
  762. InputPropertyValue<Runtime>,
  763. >,
  764. ) -> DispatchResult {
  765. TestModule::transfer_entity_ownership(
  766. Origin::signed(origin),
  767. entity_id,
  768. new_controller,
  769. new_property_value_references_with_same_owner_flag_set,
  770. )
  771. }
  772. // Transaction
  773. pub fn transaction(
  774. origin: u64,
  775. actor: Actor<CuratorGroupId, TestCuratorId, MemberId>,
  776. operations: Vec<OperationType<Runtime>>,
  777. ) -> DispatchResult {
  778. TestModule::transaction(Origin::signed(origin), actor, operations)
  779. }
  780. pub enum InvalidPropertyType {
  781. NameTooLong,
  782. NameTooShort,
  783. DescriptionTooLong,
  784. DescriptionTooShort,
  785. TextIsTooLong,
  786. TextHashIsTooLong,
  787. VecIsTooLong,
  788. }
  789. impl Property<ClassId> {
  790. pub fn default_with_name(name_len: usize) -> Self {
  791. let name = generate_text(name_len);
  792. let description = generate_text(PropertyDescriptionLengthConstraint::get().min() as usize);
  793. Self {
  794. name,
  795. description,
  796. ..Property::<ClassId>::default()
  797. }
  798. }
  799. pub fn with_name_and_type(
  800. name_len: usize,
  801. property_type: PropertyType<ClassId>,
  802. required: bool,
  803. unique: bool,
  804. ) -> Self {
  805. let name = generate_text(name_len);
  806. let description = generate_text(PropertyDescriptionLengthConstraint::get().min() as usize);
  807. Self {
  808. name,
  809. description,
  810. property_type,
  811. required,
  812. unique,
  813. ..Property::<ClassId>::default()
  814. }
  815. }
  816. pub fn invalid(invalid_property_type: InvalidPropertyType) -> Property<ClassId> {
  817. let mut default_property = Property::<ClassId>::default_with_name(
  818. PropertyNameLengthConstraint::get().min() as usize,
  819. );
  820. match invalid_property_type {
  821. InvalidPropertyType::NameTooLong => {
  822. default_property.name =
  823. generate_text(PropertyNameLengthConstraint::get().max() as usize + 1);
  824. }
  825. InvalidPropertyType::NameTooShort => {
  826. default_property.name =
  827. generate_text(PropertyNameLengthConstraint::get().min() as usize - 1);
  828. }
  829. InvalidPropertyType::DescriptionTooLong => {
  830. default_property.description =
  831. generate_text(PropertyDescriptionLengthConstraint::get().max() as usize + 1);
  832. }
  833. InvalidPropertyType::DescriptionTooShort => {
  834. default_property.description =
  835. generate_text(PropertyDescriptionLengthConstraint::get().min() as usize - 1);
  836. }
  837. InvalidPropertyType::TextIsTooLong => {
  838. default_property.property_type =
  839. PropertyType::<ClassId>::single_text(TextMaxLengthConstraint::get() + 1);
  840. }
  841. InvalidPropertyType::TextHashIsTooLong => {
  842. if let Some(hashed_text_max_len) = HashedTextMaxLengthConstraint::get() {
  843. default_property.property_type =
  844. PropertyType::<ClassId>::single_text_hash(Some(hashed_text_max_len + 1));
  845. }
  846. }
  847. InvalidPropertyType::VecIsTooLong => {
  848. default_property.property_type = PropertyType::<ClassId>::vec_reference(
  849. FIRST_CLASS_ID,
  850. true,
  851. VecMaxLengthConstraint::get() + 1,
  852. );
  853. }
  854. };
  855. default_property
  856. }
  857. }
  858. impl PropertyType<ClassId> {
  859. pub fn vec_reference(
  860. class_id: ClassId,
  861. same_controller: bool,
  862. max_length: VecMaxLength,
  863. ) -> PropertyType<ClassId> {
  864. let vec_type = Type::<ClassId>::Reference(class_id, same_controller);
  865. let vec_reference = VecPropertyType::<ClassId>::new(vec_type, max_length);
  866. PropertyType::<ClassId>::Vector(vec_reference)
  867. }
  868. pub fn vec_text(
  869. text_max_len: TextMaxLength,
  870. vec_max_length: VecMaxLength,
  871. ) -> PropertyType<ClassId> {
  872. let vec_type = Type::<ClassId>::Text(text_max_len);
  873. let vec_text = VecPropertyType::<ClassId>::new(vec_type, vec_max_length);
  874. PropertyType::<ClassId>::Vector(vec_text)
  875. }
  876. pub fn single_text(text_max_len: TextMaxLength) -> PropertyType<ClassId> {
  877. let text_type = Type::<ClassId>::Text(text_max_len);
  878. PropertyType::<ClassId>::Single(text_type)
  879. }
  880. pub fn single_text_hash(text_hash_max_len: HashedTextMaxLength) -> PropertyType<ClassId> {
  881. let text_type = Type::<ClassId>::Hash(text_hash_max_len);
  882. PropertyType::<ClassId>::Single(text_type)
  883. }
  884. pub fn vec_text_hash(
  885. text_hash_max_len: HashedTextMaxLength,
  886. vec_max_length: VecMaxLength,
  887. ) -> PropertyType<ClassId> {
  888. let vec_type = Type::<ClassId>::Hash(text_hash_max_len);
  889. let vec_text_hash = VecPropertyType::<ClassId>::new(vec_type, vec_max_length);
  890. PropertyType::<ClassId>::Vector(vec_text_hash)
  891. }
  892. }
  893. impl<T: Trait> InputPropertyValue<T> {
  894. pub fn vec_reference(entity_ids: Vec<EntityId>) -> InputPropertyValue<Runtime> {
  895. let vec_value = VecInputValue::<Runtime>::Reference(entity_ids);
  896. InputPropertyValue::<Runtime>::Vector(vec_value)
  897. }
  898. pub fn vec_text(texts: Vec<Vec<u8>>) -> InputPropertyValue<Runtime> {
  899. let vec_value = VecInputValue::<Runtime>::Text(texts);
  900. InputPropertyValue::<Runtime>::Vector(vec_value)
  901. }
  902. pub fn vec_text_to_hash(texts: Vec<Vec<u8>>) -> InputPropertyValue<Runtime> {
  903. let vec_value = VecInputValue::<Runtime>::TextToHash(texts);
  904. InputPropertyValue::<Runtime>::Vector(vec_value)
  905. }
  906. pub fn single_text(text_len: TextMaxLength) -> InputPropertyValue<Runtime> {
  907. let text_value = InputValue::<Runtime>::Text(generate_text(text_len as usize));
  908. InputPropertyValue::<Runtime>::Single(text_value)
  909. }
  910. pub fn single_text_to_hash(text_len: TextMaxLength) -> InputPropertyValue<Runtime> {
  911. let text_value = InputValue::<Runtime>::TextToHash(generate_text(text_len as usize));
  912. InputPropertyValue::<Runtime>::Single(text_value)
  913. }
  914. }
  915. impl From<InboundReferenceCounter> for EntityReferenceCounterSideEffect {
  916. fn from(inbound_rc: InboundReferenceCounter) -> Self {
  917. Self {
  918. total: inbound_rc.total as i32,
  919. same_owner: inbound_rc.same_owner as i32,
  920. }
  921. }
  922. }
  923. impl EntityReferenceCounterSideEffect {
  924. pub fn new(total: i32, same_owner: i32) -> Self {
  925. Self { total, same_owner }
  926. }
  927. }
  928. impl PropertyLockingPolicy {
  929. pub fn new(is_locked_from_maintainer: bool, is_locked_from_controller: bool) -> Self {
  930. Self {
  931. is_locked_from_maintainer,
  932. is_locked_from_controller,
  933. }
  934. }
  935. }
  936. // Assign back to type variables so we can make dispatched calls of these modules later.
  937. pub type System = frame_system::Module<Runtime>;
  938. pub type TestModule = Module<Runtime>;
  939. // Recommendation from Parity on testing on_finalize
  940. // https://substrate.dev/docs/en/next/development/module/tests
  941. pub fn run_to_block(n: u64) {
  942. while System::block_number() < n {
  943. <System as OnFinalize<u64>>::on_finalize(System::block_number());
  944. <TestModule as OnFinalize<u64>>::on_finalize(System::block_number());
  945. System::set_block_number(System::block_number() + 1);
  946. <System as OnInitialize<u64>>::on_initialize(System::block_number());
  947. <TestModule as OnInitialize<u64>>::on_initialize(System::block_number());
  948. }
  949. }