mock.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. #![cfg(test)]
  2. use crate::*;
  3. use frame_support::dispatch::{DispatchError, DispatchResult};
  4. use frame_support::traits::{OnFinalize, OnInitialize};
  5. use frame_support::{impl_outer_event, impl_outer_origin, parameter_types};
  6. use sp_core::H256;
  7. use sp_runtime::{
  8. testing::Header,
  9. traits::{BlakeTwo256, IdentityLookup},
  10. ModuleId, Perbill,
  11. };
  12. use crate::ContentActorAuthenticator;
  13. use crate::Trait;
  14. use common::currency::GovernanceCurrency;
  15. pub type CuratorId = <Test as ContentActorAuthenticator>::CuratorId;
  16. pub type CuratorGroupId = <Test as ContentActorAuthenticator>::CuratorGroupId;
  17. pub type MemberId = <Test as MembershipTypes>::MemberId;
  18. pub type ChannelId = <Test as StorageOwnership>::ChannelId;
  19. /// Origins
  20. pub const LEAD_ORIGIN: u64 = 1;
  21. pub const FIRST_CURATOR_ORIGIN: u64 = 2;
  22. pub const SECOND_CURATOR_ORIGIN: u64 = 3;
  23. pub const FIRST_MEMBER_ORIGIN: u64 = 4;
  24. pub const SECOND_MEMBER_ORIGIN: u64 = 5;
  25. pub const UNKNOWN_ORIGIN: u64 = 7777;
  26. // Members range from MemberId 1 to 10
  27. pub const MEMBERS_COUNT: MemberId = 10;
  28. /// Runtime Id's
  29. pub const FIRST_CURATOR_ID: CuratorId = 1;
  30. pub const SECOND_CURATOR_ID: CuratorId = 2;
  31. pub const FIRST_CURATOR_GROUP_ID: CuratorGroupId = 1;
  32. // pub const SECOND_CURATOR_GROUP_ID: CuratorGroupId = 2;
  33. pub const FIRST_MEMBER_ID: MemberId = 1;
  34. pub const SECOND_MEMBER_ID: MemberId = 2;
  35. impl_outer_origin! {
  36. pub enum Origin for Test {}
  37. }
  38. mod content {
  39. pub use crate::Event;
  40. }
  41. mod storage_mod {
  42. pub use storage::Event;
  43. }
  44. mod membership_mod {
  45. pub use membership::Event;
  46. }
  47. impl_outer_event! {
  48. pub enum MetaEvent for Test {
  49. content<T>,
  50. frame_system<T>,
  51. balances<T>,
  52. membership_mod<T>,
  53. storage_mod<T>,
  54. }
  55. }
  56. #[derive(Clone, PartialEq, Eq, Debug)]
  57. pub struct Test;
  58. parameter_types! {
  59. pub const BlockHashCount: u64 = 250;
  60. pub const MaximumBlockWeight: u32 = 1024;
  61. pub const MaximumBlockLength: u32 = 2 * 1024;
  62. pub const AvailableBlockRatio: Perbill = Perbill::one();
  63. pub const MinimumPeriod: u64 = 5;
  64. }
  65. impl frame_system::Trait for Test {
  66. type BaseCallFilter = ();
  67. type Origin = Origin;
  68. type Call = ();
  69. type Index = u64;
  70. type BlockNumber = u64;
  71. type Hash = H256;
  72. type Hashing = BlakeTwo256;
  73. type AccountId = u64;
  74. type Lookup = IdentityLookup<Self::AccountId>;
  75. type Header = Header;
  76. type Event = MetaEvent;
  77. type BlockHashCount = BlockHashCount;
  78. type MaximumBlockWeight = MaximumBlockWeight;
  79. type DbWeight = ();
  80. type BlockExecutionWeight = ();
  81. type ExtrinsicBaseWeight = ();
  82. type MaximumExtrinsicWeight = ();
  83. type MaximumBlockLength = MaximumBlockLength;
  84. type AvailableBlockRatio = AvailableBlockRatio;
  85. type Version = ();
  86. type AccountData = balances::AccountData<u64>;
  87. type OnNewAccount = ();
  88. type OnKilledAccount = ();
  89. type PalletInfo = ();
  90. type SystemWeightInfo = ();
  91. }
  92. impl pallet_timestamp::Trait for Test {
  93. type Moment = u64;
  94. type OnTimestampSet = ();
  95. type MinimumPeriod = MinimumPeriod;
  96. type WeightInfo = ();
  97. }
  98. impl common::MembershipTypes for Test {
  99. type MemberId = u64;
  100. type ActorId = u64;
  101. }
  102. impl common::StorageOwnership for Test {
  103. type ChannelId = u64;
  104. type ContentId = u64;
  105. type DataObjectTypeId = u64;
  106. }
  107. parameter_types! {
  108. pub const ExistentialDeposit: u32 = 0;
  109. }
  110. impl balances::Trait for Test {
  111. type Balance = u64;
  112. type DustRemoval = ();
  113. type Event = MetaEvent;
  114. type ExistentialDeposit = ExistentialDeposit;
  115. type AccountStore = System;
  116. type WeightInfo = ();
  117. type MaxLocks = ();
  118. }
  119. impl GovernanceCurrency for Test {
  120. type Currency = balances::Module<Self>;
  121. }
  122. parameter_types! {
  123. pub const ScreenedMemberMaxInitialBalance: u64 = 5000;
  124. }
  125. impl membership::Trait for Test {
  126. type Event = MetaEvent;
  127. type PaidTermId = u64;
  128. type SubscriptionId = u64;
  129. type ScreenedMemberMaxInitialBalance = ();
  130. }
  131. impl ContentActorAuthenticator for Test {
  132. type CuratorId = u64;
  133. type CuratorGroupId = u64;
  134. fn is_lead(account_id: &Self::AccountId) -> bool {
  135. let lead_account_id = ensure_signed(Origin::signed(LEAD_ORIGIN)).unwrap();
  136. *account_id == lead_account_id
  137. }
  138. fn is_curator(curator_id: &Self::CuratorId, account_id: &Self::AccountId) -> bool {
  139. let first_curator_account_id = ensure_signed(Origin::signed(FIRST_CURATOR_ORIGIN)).unwrap();
  140. let second_curator_account_id =
  141. ensure_signed(Origin::signed(SECOND_CURATOR_ORIGIN)).unwrap();
  142. (first_curator_account_id == *account_id && FIRST_CURATOR_ID == *curator_id)
  143. || (second_curator_account_id == *account_id && SECOND_CURATOR_ID == *curator_id)
  144. }
  145. fn is_member(member_id: &Self::MemberId, account_id: &Self::AccountId) -> bool {
  146. let unknown_member_account_id = ensure_signed(Origin::signed(UNKNOWN_ORIGIN)).unwrap();
  147. *member_id < MEMBERS_COUNT && unknown_member_account_id != *account_id
  148. }
  149. fn is_valid_curator_id(curator_id: &Self::CuratorId) -> bool {
  150. *curator_id == FIRST_CURATOR_ID || *curator_id == SECOND_CURATOR_ID
  151. }
  152. }
  153. parameter_types! {
  154. pub const MaxNumberOfDataObjectsPerBag: u64 = 4;
  155. pub const MaxDistributionBucketFamilyNumber: u64 = 4;
  156. pub const MaxDistributionBucketNumberPerFamily: u64 = 10;
  157. pub const DataObjectDeletionPrize: u64 = 10;
  158. pub const StorageModuleId: ModuleId = ModuleId(*b"mstorage"); // module storage
  159. pub const BlacklistSizeLimit: u64 = 1;
  160. pub const MaxNumberOfPendingInvitationsPerDistributionBucket: u64 = 1;
  161. pub const StorageBucketsPerBagValueConstraint: storage::StorageBucketsPerBagValueConstraint =
  162. storage::StorageBucketsPerBagValueConstraint {min: 3, max_min_diff: 7};
  163. pub const InitialStorageBucketsNumberForDynamicBag: u64 = 3;
  164. pub const MaxRandomIterationNumber: u64 = 3;
  165. pub const DefaultMemberDynamicBagNumberOfStorageBuckets: u64 = 3;
  166. pub const DefaultChannelDynamicBagNumberOfStorageBuckets: u64 = 4;
  167. pub const DistributionBucketsPerBagValueConstraint: storage::DistributionBucketsPerBagValueConstraint =
  168. storage::StorageBucketsPerBagValueConstraint {min: 3, max_min_diff: 7};
  169. pub const MaxDataObjectSize: u64 = 400;
  170. }
  171. pub const STORAGE_WG_LEADER_ACCOUNT_ID: u64 = 100001;
  172. pub const DEFAULT_STORAGE_PROVIDER_ACCOUNT_ID: u64 = 100002;
  173. pub const DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID: u64 = 100003;
  174. pub const DISTRIBUTION_WG_LEADER_ACCOUNT_ID: u64 = 100004;
  175. pub const DEFAULT_STORAGE_PROVIDER_ID: u64 = 10;
  176. pub const ANOTHER_STORAGE_PROVIDER_ID: u64 = 11;
  177. pub const DEFAULT_DISTRIBUTION_PROVIDER_ID: u64 = 12;
  178. pub const ANOTHER_DISTRIBUTION_PROVIDER_ID: u64 = 13;
  179. impl storage::Trait for Test {
  180. type Event = MetaEvent;
  181. type DataObjectId = u64;
  182. type StorageBucketId = u64;
  183. type DistributionBucketId = u64;
  184. type DistributionBucketFamilyId = u64;
  185. type DistributionBucketOperatorId = u64;
  186. type ChannelId = u64;
  187. type DataObjectDeletionPrize = DataObjectDeletionPrize;
  188. type BlacklistSizeLimit = BlacklistSizeLimit;
  189. type ModuleId = StorageModuleId;
  190. type MemberOriginValidator = ();
  191. type StorageBucketsPerBagValueConstraint = StorageBucketsPerBagValueConstraint;
  192. type DefaultMemberDynamicBagNumberOfStorageBuckets =
  193. DefaultMemberDynamicBagNumberOfStorageBuckets;
  194. type DefaultChannelDynamicBagNumberOfStorageBuckets =
  195. DefaultChannelDynamicBagNumberOfStorageBuckets;
  196. type Randomness = CollectiveFlip;
  197. type MaxRandomIterationNumber = MaxRandomIterationNumber;
  198. type MaxDistributionBucketFamilyNumber = MaxDistributionBucketFamilyNumber;
  199. type MaxDistributionBucketNumberPerFamily = MaxDistributionBucketNumberPerFamily;
  200. type DistributionBucketsPerBagValueConstraint = DistributionBucketsPerBagValueConstraint;
  201. type MaxNumberOfPendingInvitationsPerDistributionBucket =
  202. MaxNumberOfPendingInvitationsPerDistributionBucket;
  203. type ContentId = u64;
  204. type MaxDataObjectSize = MaxDataObjectSize;
  205. fn ensure_storage_working_group_leader_origin(origin: Self::Origin) -> DispatchResult {
  206. let account_id = ensure_signed(origin)?;
  207. if account_id != STORAGE_WG_LEADER_ACCOUNT_ID {
  208. Err(DispatchError::BadOrigin)
  209. } else {
  210. Ok(())
  211. }
  212. }
  213. fn ensure_storage_worker_origin(origin: Self::Origin, _: u64) -> DispatchResult {
  214. let account_id = ensure_signed(origin)?;
  215. if account_id != DEFAULT_STORAGE_PROVIDER_ACCOUNT_ID {
  216. Err(DispatchError::BadOrigin)
  217. } else {
  218. Ok(())
  219. }
  220. }
  221. fn ensure_storage_worker_exists(worker_id: &u64) -> DispatchResult {
  222. let allowed_storage_providers =
  223. vec![DEFAULT_STORAGE_PROVIDER_ID, ANOTHER_STORAGE_PROVIDER_ID];
  224. if !allowed_storage_providers.contains(worker_id) {
  225. Err(DispatchError::Other("Invalid worker"))
  226. } else {
  227. Ok(())
  228. }
  229. }
  230. fn ensure_distribution_working_group_leader_origin(origin: Self::Origin) -> DispatchResult {
  231. let account_id = ensure_signed(origin)?;
  232. if account_id != DISTRIBUTION_WG_LEADER_ACCOUNT_ID {
  233. Err(DispatchError::BadOrigin)
  234. } else {
  235. Ok(())
  236. }
  237. }
  238. fn ensure_distribution_worker_origin(origin: Self::Origin, _: u64) -> DispatchResult {
  239. let account_id = ensure_signed(origin)?;
  240. if account_id != DEFAULT_DISTRIBUTION_PROVIDER_ACCOUNT_ID {
  241. Err(DispatchError::BadOrigin)
  242. } else {
  243. Ok(())
  244. }
  245. }
  246. fn ensure_distribution_worker_exists(worker_id: &u64) -> DispatchResult {
  247. let allowed_providers = vec![
  248. DEFAULT_DISTRIBUTION_PROVIDER_ID,
  249. ANOTHER_DISTRIBUTION_PROVIDER_ID,
  250. ];
  251. if !allowed_providers.contains(worker_id) {
  252. Err(DispatchError::Other("Invalid worker"))
  253. } else {
  254. Ok(())
  255. }
  256. }
  257. }
  258. pub const DEFAULT_MEMBER_ID: u64 = 100;
  259. pub const DEFAULT_MEMBER_ACCOUNT_ID: u64 = 101;
  260. impl common::origin::ActorOriginValidator<Origin, u64, u64> for () {
  261. fn ensure_actor_origin(origin: Origin, member_id: u64) -> Result<u64, &'static str> {
  262. let signed_account_id = frame_system::ensure_signed(origin)?;
  263. if signed_account_id == DEFAULT_MEMBER_ACCOUNT_ID && member_id == DEFAULT_MEMBER_ID {
  264. Ok(signed_account_id)
  265. } else {
  266. Err(DispatchError::BadOrigin.into())
  267. }
  268. }
  269. }
  270. // Anyone can upload and delete without restriction
  271. parameter_types! {
  272. pub const MaxNumberOfCuratorsPerGroup: u32 = 10;
  273. pub const ChannelOwnershipPaymentEscrowId: [u8; 8] = *b"12345678";
  274. }
  275. impl Trait for Test {
  276. /// The overarching event type.
  277. type Event = MetaEvent;
  278. /// Channel Transfer Payments Escrow Account seed for ModuleId to compute deterministic AccountId
  279. type ChannelOwnershipPaymentEscrowId = ChannelOwnershipPaymentEscrowId;
  280. /// Type of identifier for Videos
  281. type VideoId = u64;
  282. /// Type of identifier for Video Categories
  283. type VideoCategoryId = u64;
  284. /// Type of identifier for Channel Categories
  285. type ChannelCategoryId = u64;
  286. /// Type of identifier for Playlists
  287. type PlaylistId = u64;
  288. /// Type of identifier for Persons
  289. type PersonId = u64;
  290. /// Type of identifier for Channels
  291. type SeriesId = u64;
  292. /// Type of identifier for Channel transfer requests
  293. type ChannelOwnershipTransferRequestId = u64;
  294. /// The maximum number of curators per group constraint
  295. type MaxNumberOfCuratorsPerGroup = MaxNumberOfCuratorsPerGroup;
  296. /// The data object used in storage
  297. type DataObjectStorage = storage::Module<Self>;
  298. }
  299. pub type System = frame_system::Module<Test>;
  300. pub type Content = Module<Test>;
  301. // #[derive (Default)]
  302. pub struct ExtBuilder {
  303. next_channel_category_id: u64,
  304. next_channel_id: u64,
  305. next_video_category_id: u64,
  306. next_video_id: u64,
  307. next_playlist_id: u64,
  308. next_person_id: u64,
  309. next_series_id: u64,
  310. next_channel_transfer_request_id: u64,
  311. next_curator_group_id: u64,
  312. }
  313. impl Default for ExtBuilder {
  314. fn default() -> Self {
  315. Self {
  316. next_channel_category_id: 1,
  317. next_channel_id: 1,
  318. next_video_category_id: 1,
  319. next_video_id: 1,
  320. next_playlist_id: 1,
  321. next_person_id: 1,
  322. next_series_id: 1,
  323. next_channel_transfer_request_id: 1,
  324. next_curator_group_id: 1,
  325. }
  326. }
  327. }
  328. impl ExtBuilder {
  329. pub fn build(self) -> sp_io::TestExternalities {
  330. let mut t = frame_system::GenesisConfig::default()
  331. .build_storage::<Test>()
  332. .unwrap();
  333. GenesisConfig::<Test> {
  334. next_channel_category_id: self.next_channel_category_id,
  335. next_channel_id: self.next_channel_id,
  336. next_video_category_id: self.next_video_category_id,
  337. next_video_id: self.next_video_id,
  338. next_playlist_id: self.next_playlist_id,
  339. next_person_id: self.next_person_id,
  340. next_series_id: self.next_series_id,
  341. next_channel_transfer_request_id: self.next_channel_transfer_request_id,
  342. next_curator_group_id: self.next_curator_group_id,
  343. }
  344. .assimilate_storage(&mut t)
  345. .unwrap();
  346. t.into()
  347. }
  348. }
  349. pub fn with_default_mock_builder<R, F: FnOnce() -> R>(f: F) -> R {
  350. ExtBuilder::default().build().execute_with(|| f())
  351. }
  352. // Recommendation from Parity on testing on_finalize
  353. // https://substrate.dev/docs/en/next/development/module/tests
  354. pub fn run_to_block(n: u64) {
  355. while System::block_number() < n {
  356. <System as OnFinalize<u64>>::on_finalize(System::block_number());
  357. System::set_block_number(System::block_number() + 1);
  358. <System as OnInitialize<u64>>::on_initialize(System::block_number());
  359. }
  360. }
  361. pub type CollectiveFlip = randomness_collective_flip::Module<Test>;
  362. pub fn create_channel_mock(
  363. sender: u64,
  364. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  365. params: ChannelCreationParameters<Test>,
  366. result: DispatchResult,
  367. ) {
  368. let channel_id = Content::next_channel_id();
  369. assert_eq!(
  370. Content::create_channel(Origin::signed(sender), actor.clone(), params.clone()),
  371. result.clone(),
  372. );
  373. if result.is_ok() {
  374. let owner = Content::actor_to_channel_owner(&actor).unwrap();
  375. assert_eq!(
  376. System::events().last().unwrap().event,
  377. MetaEvent::content(RawEvent::ChannelCreated(
  378. actor.clone(),
  379. channel_id,
  380. ChannelRecord {
  381. owner: owner,
  382. is_censored: false,
  383. reward_account: params.reward_account,
  384. deletion_prize_source_account_id: sender,
  385. num_videos: 0,
  386. },
  387. params.clone(),
  388. ))
  389. );
  390. }
  391. }
  392. pub fn update_channel_mock(
  393. sender: u64,
  394. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  395. channel_id: ChannelId,
  396. params: ChannelUpdateParameters<Test>,
  397. result: DispatchResult,
  398. ) {
  399. let channel_pre = ChannelById::<Test>::get(channel_id.clone());
  400. assert_eq!(
  401. Content::update_channel(
  402. Origin::signed(sender),
  403. actor.clone(),
  404. channel_id.clone(),
  405. params.clone(),
  406. ),
  407. result.clone(),
  408. );
  409. if result.is_ok() {
  410. assert_eq!(
  411. System::events().last().unwrap().event,
  412. MetaEvent::content(RawEvent::ChannelUpdated(
  413. actor.clone(),
  414. channel_id,
  415. ChannelRecord {
  416. owner: channel_pre.owner.clone(),
  417. is_censored: channel_pre.is_censored,
  418. reward_account: channel_pre.reward_account.clone(),
  419. deletion_prize_source_account_id: sender,
  420. num_videos: channel_pre.num_videos,
  421. },
  422. params.clone(),
  423. ))
  424. );
  425. }
  426. }
  427. pub fn delete_channel_mock(
  428. sender: u64,
  429. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  430. channel_id: ChannelId,
  431. objects_num: u64,
  432. result: DispatchResult,
  433. ) {
  434. assert_eq!(
  435. Content::delete_channel(
  436. Origin::signed(sender),
  437. actor.clone(),
  438. channel_id.clone(),
  439. objects_num,
  440. ),
  441. result.clone(),
  442. );
  443. if result.is_ok() {
  444. assert_eq!(
  445. System::events().last().unwrap().event,
  446. MetaEvent::content(RawEvent::ChannelDeleted(actor.clone(), channel_id))
  447. )
  448. }
  449. }
  450. pub fn create_video_mock(
  451. sender: u64,
  452. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  453. channel_id: ChannelId,
  454. params: VideoCreationParameters<Test>,
  455. result: DispatchResult,
  456. ) {
  457. let video_id = Content::next_video_id();
  458. let num_videos_pre = Content::channel_by_id(channel_id).num_videos;
  459. assert_eq!(
  460. Content::create_video(
  461. Origin::signed(sender),
  462. actor.clone(),
  463. channel_id.clone(),
  464. params.clone()
  465. ),
  466. result.clone(),
  467. );
  468. if result.is_ok() {
  469. assert_eq!(
  470. System::events().last().unwrap().event,
  471. MetaEvent::content(RawEvent::VideoCreated(
  472. actor.clone(),
  473. channel_id,
  474. video_id,
  475. params.clone(),
  476. ))
  477. );
  478. assert_eq!(
  479. num_videos_pre + 1,
  480. Content::channel_by_id(channel_id).num_videos,
  481. );
  482. }
  483. }
  484. pub fn update_video_mock(
  485. sender: u64,
  486. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  487. video_id: <Test as Trait>::VideoId,
  488. params: VideoUpdateParameters<Test>,
  489. result: DispatchResult,
  490. ) {
  491. // let channel_id = Content::video_by_id(video_id.clone()).in_channel;
  492. // let num_videos_pre = Content::channel_by_id(channel_id).num_videos;
  493. assert_eq!(
  494. Content::update_video(
  495. Origin::signed(sender),
  496. actor.clone(),
  497. video_id.clone(),
  498. params.clone(),
  499. ),
  500. result.clone(),
  501. );
  502. if result.is_ok() {
  503. assert_eq!(
  504. System::events().last().unwrap().event,
  505. MetaEvent::content(RawEvent::VideoUpdated(
  506. actor.clone(),
  507. video_id,
  508. params.clone(),
  509. ))
  510. );
  511. }
  512. }