mock.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. #![cfg(test)]
  2. use crate::*;
  3. use crate::InputValidationLengthConstraint;
  4. use primitives::H256;
  5. use runtime_primitives::{
  6. testing::Header,
  7. traits::{BlakeTwo256, IdentityLookup},
  8. Perbill,
  9. };
  10. use srml_support::{assert_err, assert_ok, impl_outer_origin, parameter_types};
  11. use std::cell::RefCell;
  12. pub const MEMBER_ONE_WITH_CREDENTIAL_ZERO: u64 = 100;
  13. pub const MEMBER_TWO_WITH_CREDENTIAL_ZERO: u64 = 101;
  14. pub const MEMBER_ONE_WITH_CREDENTIAL_ONE: u64 = 102;
  15. pub const MEMBER_TWO_WITH_CREDENTIAL_ONE: u64 = 103;
  16. pub const UNKNOWN_CLASS_ID: <Runtime as Trait>::ClassId = 111;
  17. pub const UNKNOWN_ENTITY_ID: <Runtime as Trait>::EntityId = 222;
  18. pub const UNKNOWN_PROP_ID: PropertyId = 333;
  19. pub const UNKNOWN_SCHEMA_ID: SchemaId = 444;
  20. pub const SCHEMA_ID_0: SchemaId = 0;
  21. pub const SCHEMA_ID_1: SchemaId = 1;
  22. pub const ZERO_NONCE: <Runtime as Trait>::Nonce = 0;
  23. pub const FIRST_NONCE: <Runtime as Trait>::Nonce = 1;
  24. pub const SECOND_NONCE: <Runtime as Trait>::Nonce = 2;
  25. pub const VALID_PROPERTY_VEC_INDEX: VecMaxLength = 0;
  26. pub const INVALID_PROPERTY_VEC_INDEX: VecMaxLength = 5;
  27. pub const PROP_ID_BOOL: PropertyId = 0;
  28. pub const PROP_ID_REFERENCE_VEC: PropertyId = 1;
  29. pub const PROP_ID_U32: PropertyId = 1;
  30. pub const PROP_ID_REFERENCE: PropertyId = 2;
  31. pub const PROP_ID_U32_VEC: PropertyId = 3;
  32. pub const PROP_ID_U32_VEC_MAX_LEN: PropertyId = 20;
  33. pub const PRINCIPAL_GROUP_MEMBERS: [[u64; 2]; 2] = [
  34. [
  35. MEMBER_ONE_WITH_CREDENTIAL_ZERO,
  36. MEMBER_TWO_WITH_CREDENTIAL_ZERO,
  37. ],
  38. [
  39. MEMBER_ONE_WITH_CREDENTIAL_ONE,
  40. MEMBER_TWO_WITH_CREDENTIAL_ONE,
  41. ],
  42. ];
  43. pub const CLASS_PERMISSIONS_CREATOR1: u64 = 200;
  44. pub const CLASS_PERMISSIONS_CREATOR2: u64 = 300;
  45. pub const UNAUTHORIZED_CLASS_PERMISSIONS_CREATOR: u64 = 50;
  46. const CLASS_PERMISSIONS_CREATORS: [u64; 2] =
  47. [CLASS_PERMISSIONS_CREATOR1, CLASS_PERMISSIONS_CREATOR2];
  48. impl_outer_origin! {
  49. pub enum Origin for Runtime {}
  50. }
  51. // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
  52. #[derive(Clone, Default, PartialEq, Eq, Debug)]
  53. pub struct Runtime;
  54. parameter_types! {
  55. pub const BlockHashCount: u64 = 250;
  56. pub const MaximumBlockWeight: u32 = 1024;
  57. pub const MaximumBlockLength: u32 = 2 * 1024;
  58. pub const AvailableBlockRatio: Perbill = Perbill::one();
  59. pub const MinimumPeriod: u64 = 5;
  60. }
  61. impl system::Trait for Runtime {
  62. type Origin = Origin;
  63. type Index = u64;
  64. type BlockNumber = u64;
  65. type Call = ();
  66. type Hash = H256;
  67. type Hashing = BlakeTwo256;
  68. type AccountId = u64;
  69. type Lookup = IdentityLookup<Self::AccountId>;
  70. type Header = Header;
  71. type Event = ();
  72. type BlockHashCount = BlockHashCount;
  73. type MaximumBlockWeight = MaximumBlockWeight;
  74. type MaximumBlockLength = MaximumBlockLength;
  75. type AvailableBlockRatio = AvailableBlockRatio;
  76. type Version = ();
  77. }
  78. impl timestamp::Trait for Runtime {
  79. type Moment = u64;
  80. type OnTimestampSet = ();
  81. type MinimumPeriod = MinimumPeriod;
  82. }
  83. thread_local! {
  84. static PROPERTY_NAME_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  85. static PROPERTY_DESCRIPTION_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  86. static CLASS_NAME_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  87. static CLASS_DESCRIPTION_CONSTRAINT: RefCell<InputValidationLengthConstraint> = RefCell::new(InputValidationLengthConstraint::default());
  88. }
  89. pub struct PropertyNameConstraint;
  90. impl Get<InputValidationLengthConstraint> for PropertyNameConstraint {
  91. fn get() -> InputValidationLengthConstraint {
  92. PROPERTY_NAME_CONSTRAINT.with(|v| *v.borrow())
  93. }
  94. }
  95. pub struct PropertyDescriptionConstraint;
  96. impl Get<InputValidationLengthConstraint> for PropertyDescriptionConstraint {
  97. fn get() -> InputValidationLengthConstraint {
  98. PROPERTY_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow())
  99. }
  100. }
  101. pub struct ClassNameConstraint;
  102. impl Get<InputValidationLengthConstraint> for ClassNameConstraint {
  103. fn get() -> InputValidationLengthConstraint {
  104. CLASS_NAME_CONSTRAINT.with(|v| *v.borrow())
  105. }
  106. }
  107. pub struct ClassDescriptionConstraint;
  108. impl Get<InputValidationLengthConstraint> for ClassDescriptionConstraint {
  109. fn get() -> InputValidationLengthConstraint {
  110. CLASS_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow())
  111. }
  112. }
  113. impl Trait for Runtime {
  114. type Credential = u64;
  115. type Nonce = u64;
  116. type ClassId = u64;
  117. type EntityId = u64;
  118. type CredentialChecker = MockCredentialChecker;
  119. type CreateClassPermissionsChecker = MockCreateClassPermissionsChecker;
  120. type PropertyNameConstraint = PropertyNameConstraint;
  121. type PropertyDescriptionConstraint = PropertyDescriptionConstraint;
  122. type ClassNameConstraint = ClassNameConstraint;
  123. type ClassDescriptionConstraint = ClassDescriptionConstraint;
  124. }
  125. impl ActorAuthenticator for Runtime {
  126. type ActorId = u64;
  127. type GroupId = u64;
  128. fn authenticate_authority(account_id: Self::AccountId) -> bool {
  129. true
  130. }
  131. fn authenticate_actor_in_group(
  132. account_id: Self::AccountId,
  133. actor_id: Self::ActorId,
  134. group_id: Self::GroupId,
  135. ) -> bool {
  136. true
  137. }
  138. }
  139. pub struct MockCredentialChecker {}
  140. impl CredentialChecker<Runtime> for MockCredentialChecker {
  141. fn account_has_credential(
  142. account_id: &<Runtime as system::Trait>::AccountId,
  143. credential_id: <Runtime as Trait>::Credential,
  144. ) -> bool {
  145. if (credential_id as usize) < PRINCIPAL_GROUP_MEMBERS.len() {
  146. PRINCIPAL_GROUP_MEMBERS[credential_id as usize]
  147. .iter()
  148. .any(|id| *id == *account_id)
  149. } else {
  150. false
  151. }
  152. }
  153. }
  154. pub struct MockCreateClassPermissionsChecker {}
  155. impl CreateClassPermissionsChecker<Runtime> for MockCreateClassPermissionsChecker {
  156. fn account_can_create_class_permissions(
  157. account_id: &<Runtime as system::Trait>::AccountId,
  158. ) -> bool {
  159. CLASS_PERMISSIONS_CREATORS
  160. .iter()
  161. .any(|id| *id == *account_id)
  162. }
  163. }
  164. pub struct ExtBuilder {
  165. property_name_constraint: InputValidationLengthConstraint,
  166. property_description_constraint: InputValidationLengthConstraint,
  167. class_name_constraint: InputValidationLengthConstraint,
  168. class_description_constraint: InputValidationLengthConstraint,
  169. }
  170. impl Default for ExtBuilder {
  171. fn default() -> Self {
  172. Self {
  173. property_name_constraint: InputValidationLengthConstraint::new(1, 49),
  174. property_description_constraint: InputValidationLengthConstraint::new(0, 500),
  175. class_name_constraint: InputValidationLengthConstraint::new(1, 49),
  176. class_description_constraint: InputValidationLengthConstraint::new(0, 500),
  177. }
  178. }
  179. }
  180. impl ExtBuilder {
  181. pub fn post_title_max_length(
  182. mut self,
  183. property_name_constraint: InputValidationLengthConstraint,
  184. ) -> Self {
  185. self.property_name_constraint = property_name_constraint;
  186. self
  187. }
  188. pub fn post_body_max_length(
  189. mut self,
  190. property_description_constraint: InputValidationLengthConstraint,
  191. ) -> Self {
  192. self.property_description_constraint = property_description_constraint;
  193. self
  194. }
  195. pub fn reply_max_length(
  196. mut self,
  197. class_name_constraint: InputValidationLengthConstraint,
  198. ) -> Self {
  199. self.class_name_constraint = class_name_constraint;
  200. self
  201. }
  202. pub fn posts_max_number(
  203. mut self,
  204. class_description_constraint: InputValidationLengthConstraint,
  205. ) -> Self {
  206. self.class_description_constraint = class_description_constraint;
  207. self
  208. }
  209. pub fn set_associated_consts(&self) {
  210. PROPERTY_NAME_CONSTRAINT.with(|v| *v.borrow_mut() = self.property_name_constraint);
  211. PROPERTY_DESCRIPTION_CONSTRAINT
  212. .with(|v| *v.borrow_mut() = self.property_description_constraint);
  213. CLASS_NAME_CONSTRAINT.with(|v| *v.borrow_mut() = self.class_name_constraint);
  214. CLASS_DESCRIPTION_CONSTRAINT.with(|v| *v.borrow_mut() = self.class_description_constraint);
  215. }
  216. pub fn build(self, config: GenesisConfig<Runtime>) -> runtime_io::TestExternalities {
  217. self.set_associated_consts();
  218. let mut t = system::GenesisConfig::default()
  219. .build_storage::<Runtime>()
  220. .unwrap();
  221. config.assimilate_storage(&mut t).unwrap();
  222. t.into()
  223. }
  224. }
  225. // This function basically just builds a genesis storage key/value store according to
  226. // our desired mockup.
  227. fn default_content_directory_genesis_config() -> GenesisConfig<Runtime> {
  228. GenesisConfig {
  229. class_by_id: vec![],
  230. entity_by_id: vec![],
  231. next_class_id: 1,
  232. next_entity_id: 1,
  233. }
  234. }
  235. pub fn with_test_externalities<R, F: FnOnce() -> R>(f: F) -> R {
  236. let default_genesis_config = default_content_directory_genesis_config();
  237. ExtBuilder::default()
  238. .build(default_genesis_config)
  239. .execute_with(f)
  240. }
  241. impl <T: Trait> Property<T> {
  242. pub fn required(mut self) -> Self {
  243. self.required = true;
  244. self
  245. }
  246. }
  247. pub fn assert_class_props(class_id: <Runtime as Trait>::ClassId, expected_props: Vec<Property<Runtime>>) {
  248. let class = TestModule::class_by_id(class_id);
  249. assert_eq!(class.properties, expected_props);
  250. }
  251. pub fn assert_class_schemas(class_id: <Runtime as Trait>::ClassId, expected_schema_prop_ids: Vec<Vec<PropertyId>>) {
  252. let class = TestModule::class_by_id(class_id);
  253. let schemas: Vec<_> = expected_schema_prop_ids
  254. .iter()
  255. .map(|prop_ids| Schema::new(prop_ids.to_owned()))
  256. .collect();
  257. assert_eq!(class.schemas, schemas);
  258. }
  259. pub fn assert_entity_not_found(result: dispatch::Result) {
  260. assert_err!(result, ERROR_ENTITY_NOT_FOUND);
  261. }
  262. pub fn simple_test_schema() -> Vec<Property<Runtime>> {
  263. vec![Property {
  264. prop_type: PropertyType::Int64,
  265. required: false,
  266. name: b"field1".to_vec(),
  267. description: b"Description field1".to_vec(),
  268. }]
  269. }
  270. pub fn simple_test_entity_property_values<T: Trait>() -> BTreeMap<PropertyId, PropertyValue<T>> {
  271. let mut property_values = BTreeMap::new();
  272. property_values.insert(0, PropertyValue::Int64(1337));
  273. property_values
  274. }
  275. pub fn create_simple_class(permissions: ClassPermissionsType<Runtime>) -> <Runtime as Trait>::ClassId {
  276. let class_id = TestModule::next_class_id();
  277. assert_ok!(TestModule::create_class(
  278. Origin::signed(CLASS_PERMISSIONS_CREATOR1),
  279. b"class_name_1".to_vec(),
  280. b"class_description_1".to_vec(),
  281. permissions
  282. ));
  283. class_id
  284. }
  285. pub fn create_simple_class_with_default_permissions() -> <Runtime as Trait>::ClassId {
  286. create_simple_class(Default::default())
  287. }
  288. pub fn class_minimal() -> ClassPermissionsType<Runtime> {
  289. ClassPermissions {
  290. // remove special permissions for entity maintainers
  291. entity_permissions: EntityPermissions {
  292. maintainer_has_all_permissions: false,
  293. ..Default::default()
  294. },
  295. ..Default::default()
  296. }
  297. }
  298. pub fn class_minimal_with_admins(
  299. admins: Vec<<Runtime as Trait>::Credential>,
  300. ) -> ClassPermissionsType<Runtime> {
  301. ClassPermissions {
  302. admins: admins.into(),
  303. ..class_minimal()
  304. }
  305. }
  306. pub fn next_entity_id() -> <Runtime as Trait>::EntityId {
  307. TestModule::next_entity_id()
  308. }
  309. pub fn create_entity_of_class(class_id: <Runtime as Trait>::ClassId) -> <Runtime as Trait>::EntityId {
  310. let entity_id = TestModule::next_entity_id();
  311. assert_eq!(TestModule::perform_entity_creation(class_id,), entity_id);
  312. entity_id
  313. }
  314. pub fn create_entity_with_schema_support() -> <Runtime as Trait>::EntityId {
  315. let (_, schema_id, entity_id) = create_class_with_schema_and_entity();
  316. let mut property_values = BTreeMap::new();
  317. property_values.insert(PROP_ID_BOOL, PropertyValue::Bool(true));
  318. property_values.insert(
  319. PROP_ID_U32_VEC,
  320. PropertyValue::Uint32Vec(vec![123, 234, 44], <Runtime as Trait>::Nonce::default()),
  321. );
  322. assert_ok!(TestModule::add_entity_schema_support(
  323. entity_id,
  324. schema_id,
  325. property_values
  326. ));
  327. entity_id
  328. }
  329. pub fn create_class_with_schema() -> (<Runtime as Trait>::ClassId, SchemaId) {
  330. let class_id = create_simple_class_with_default_permissions();
  331. let schema_id = TestModule::append_class_schema(
  332. class_id,
  333. vec![],
  334. vec![
  335. good_prop_bool().required(),
  336. good_prop_u32(),
  337. new_reference_class_prop(class_id),
  338. good_prop_u32_vec(),
  339. ],
  340. )
  341. .expect("This should not happen");
  342. (class_id, schema_id)
  343. }
  344. pub fn create_class_with_schema_and_entity() -> (<Runtime as Trait>::ClassId, SchemaId, <Runtime as Trait>::EntityId) {
  345. let (class_id, schema_id) = create_class_with_schema();
  346. let entity_id = create_entity_of_class(class_id);
  347. (class_id, schema_id, entity_id)
  348. }
  349. pub fn good_prop_bool() -> Property<Runtime> {
  350. Property {
  351. prop_type: PropertyType::Bool,
  352. required: false,
  353. name: b"Name of a bool property".to_vec(),
  354. description: b"Description of a bool property".to_vec(),
  355. }
  356. }
  357. pub fn good_prop_u32() -> Property<Runtime> {
  358. Property {
  359. prop_type: PropertyType::Uint32,
  360. required: false,
  361. name: b"Name of a u32 property".to_vec(),
  362. description: b"Description of a u32 property".to_vec(),
  363. }
  364. }
  365. pub fn good_prop_u32_vec() -> Property<Runtime> {
  366. Property {
  367. prop_type: PropertyType::Uint32Vec(PROP_ID_U32_VEC_MAX_LEN),
  368. required: false,
  369. name: b"Name of a u32 vec property".to_vec(),
  370. description: b"Description of a u32 vec property".to_vec(),
  371. }
  372. }
  373. pub fn good_prop_text() -> Property<Runtime> {
  374. Property {
  375. prop_type: PropertyType::Text(20),
  376. required: false,
  377. name: b"Name of a text property".to_vec(),
  378. description: b"Description of a text property".to_vec(),
  379. }
  380. }
  381. pub fn new_reference_class_prop(class_id: <Runtime as Trait>::ClassId) -> Property<Runtime> {
  382. Property {
  383. prop_type: PropertyType::Reference(class_id),
  384. required: false,
  385. name: b"Name of a internal property".to_vec(),
  386. description: b"Description of a internal property".to_vec(),
  387. }
  388. }
  389. pub fn new_reference_class_prop_vec(class_id: <Runtime as Trait>::ClassId) -> Property<Runtime> {
  390. Property {
  391. prop_type: PropertyType::ReferenceVec(PROP_ID_U32_VEC_MAX_LEN, class_id),
  392. required: false,
  393. name: b"Name of a internal property".to_vec(),
  394. description: b"Description of a internal property".to_vec(),
  395. }
  396. }
  397. pub fn good_class_name() -> Vec<u8> {
  398. b"Name of a class".to_vec()
  399. }
  400. pub fn good_class_description() -> Vec<u8> {
  401. b"Description of a class".to_vec()
  402. }
  403. pub fn good_props() -> Vec<Property<Runtime>> {
  404. vec![good_prop_bool(), good_prop_u32()]
  405. }
  406. pub fn good_prop_ids() -> Vec<PropertyId> {
  407. vec![0, 1]
  408. }
  409. pub fn bool_prop_value<T: Trait>() -> BTreeMap<PropertyId, PropertyValue<T>> {
  410. let mut property_values = BTreeMap::new();
  411. property_values.insert(0, PropertyValue::Bool(true));
  412. property_values
  413. }
  414. pub fn prop_value<T: Trait>(
  415. index: PropertyId,
  416. value: PropertyValue<T>,
  417. ) -> BTreeMap<PropertyId, PropertyValue<T>> {
  418. let mut property_values = BTreeMap::new();
  419. property_values.insert(index, value);
  420. property_values
  421. }
  422. // pub type System = system::Module;
  423. /// Export module on a test runtime
  424. pub type TestModule = Module<Runtime>;