fixtures.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. use super::curators;
  2. use super::mock::*;
  3. use crate::*;
  4. use frame_support::assert_ok;
  5. use frame_support::traits::Currency;
  6. // type aliases
  7. type AccountId = <Test as frame_system::Trait>::AccountId;
  8. type VideoId = <Test as Trait>::VideoId;
  9. // fixtures
  10. pub struct CreateChannelFixture {
  11. sender: AccountId,
  12. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  13. params: ChannelCreationParameters<Test>,
  14. }
  15. impl CreateChannelFixture {
  16. pub fn default() -> Self {
  17. Self {
  18. sender: DEFAULT_MEMBER_ACCOUNT_ID,
  19. actor: ContentActor::Member(DEFAULT_MEMBER_ID),
  20. params: ChannelCreationParameters::<Test> {
  21. assets: None,
  22. meta: None,
  23. reward_account: None,
  24. collaborators: BTreeSet::new(),
  25. },
  26. }
  27. }
  28. pub fn with_sender(self, sender: AccountId) -> Self {
  29. Self { sender, ..self }
  30. }
  31. pub fn with_actor(self, actor: ContentActor<CuratorGroupId, CuratorId, MemberId>) -> Self {
  32. Self { actor, ..self }
  33. }
  34. pub fn with_assets(self, assets: StorageAssets<Test>) -> Self {
  35. Self {
  36. params: ChannelCreationParameters::<Test> {
  37. assets: Some(assets),
  38. ..self.params
  39. },
  40. ..self
  41. }
  42. }
  43. pub fn with_collaborators(self, collaborators: BTreeSet<MemberId>) -> Self {
  44. Self {
  45. params: ChannelCreationParameters::<Test> {
  46. collaborators: collaborators,
  47. ..self.params
  48. },
  49. ..self
  50. }
  51. }
  52. pub fn with_reward_account(self, reward_account: AccountId) -> Self {
  53. Self {
  54. params: ChannelCreationParameters::<Test> {
  55. reward_account: Some(reward_account),
  56. ..self.params
  57. },
  58. ..self
  59. }
  60. }
  61. pub fn call_and_assert(&self, expected_result: DispatchResult) {
  62. let origin = Origin::signed(self.sender.clone());
  63. let balance_pre = Balances::usable_balance(self.sender);
  64. let channel_id = Content::next_channel_id();
  65. let channel_bag_id = Content::bag_id_for_channel(&channel_id);
  66. let beg_obj_id = storage::NextDataObjectId::<Test>::get();
  67. let actual_result =
  68. Content::create_channel(origin, self.actor.clone(), self.params.clone());
  69. let end_obj_id = storage::NextDataObjectId::<Test>::get();
  70. assert_eq!(actual_result, expected_result);
  71. let balance_post = Balances::usable_balance(self.sender);
  72. if actual_result.is_ok() {
  73. // ensure channel is on chain
  74. assert!(ChannelById::<Test>::contains_key(&channel_id));
  75. // channel counter increased
  76. assert_eq!(
  77. Content::next_channel_id(),
  78. channel_id.saturating_add(One::one())
  79. );
  80. // dynamic bag for channel is created
  81. assert_ok!(Storage::<Test>::ensure_bag_exists(&channel_bag_id));
  82. // event correctly deposited
  83. let owner = Content::actor_to_channel_owner(&self.actor).unwrap();
  84. assert_eq!(
  85. System::events().last().unwrap().event,
  86. MetaEvent::content(RawEvent::ChannelCreated(
  87. self.actor.clone(),
  88. channel_id,
  89. ChannelRecord {
  90. owner: owner,
  91. is_censored: false,
  92. reward_account: self.params.reward_account.clone(),
  93. collaborators: self.params.collaborators.clone(),
  94. num_videos: Zero::zero(),
  95. },
  96. self.params.clone(),
  97. ))
  98. );
  99. if let Some(assets) = self.params.assets.as_ref() {
  100. // balance accounting is correct
  101. let bag_deletion_prize = BalanceOf::<Test>::zero();
  102. let objects_deletion_prize =
  103. assets
  104. .object_creation_list
  105. .iter()
  106. .fold(BalanceOf::<Test>::zero(), |acc, _| {
  107. acc.saturating_add(
  108. <Test as storage::Trait>::DataObjectDeletionPrize::get(),
  109. )
  110. });
  111. assert_eq!(
  112. balance_pre.saturating_sub(balance_post),
  113. bag_deletion_prize.saturating_add(objects_deletion_prize),
  114. );
  115. assert!((beg_obj_id..end_obj_id).all(|id| {
  116. storage::DataObjectsById::<Test>::contains_key(&channel_bag_id, id)
  117. }));
  118. }
  119. } else {
  120. assert_eq!(balance_post, balance_pre);
  121. assert_eq!(beg_obj_id, end_obj_id);
  122. assert!(!storage::Bags::<Test>::contains_key(&channel_bag_id));
  123. assert!(!ChannelById::<Test>::contains_key(&channel_id));
  124. assert_eq!(NextChannelId::<Test>::get(), channel_id);
  125. }
  126. }
  127. }
  128. pub struct CreateVideoFixture {
  129. sender: AccountId,
  130. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  131. params: VideoCreationParameters<Test>,
  132. channel_id: ChannelId,
  133. }
  134. impl CreateVideoFixture {
  135. pub fn default() -> Self {
  136. Self {
  137. sender: DEFAULT_MEMBER_ACCOUNT_ID,
  138. actor: ContentActor::Member(DEFAULT_MEMBER_ACCOUNT_ID),
  139. params: VideoCreationParameters::<Test> {
  140. assets: None,
  141. meta: None,
  142. },
  143. channel_id: ChannelId::one(), // channel index starts at 1
  144. }
  145. }
  146. pub fn with_sender(self, sender: AccountId) -> Self {
  147. Self { sender, ..self }
  148. }
  149. pub fn with_channel_id(self, channel_id: ChannelId) -> Self {
  150. Self { channel_id, ..self }
  151. }
  152. pub fn with_actor(self, actor: ContentActor<CuratorGroupId, CuratorId, MemberId>) -> Self {
  153. Self { actor, ..self }
  154. }
  155. pub fn with_assets(self, assets: StorageAssets<Test>) -> Self {
  156. Self {
  157. params: VideoCreationParameters::<Test> {
  158. assets: Some(assets),
  159. ..self.params
  160. },
  161. ..self
  162. }
  163. }
  164. pub fn call_and_assert(&self, expected_result: DispatchResult) {
  165. let origin = Origin::signed(self.sender.clone());
  166. let balance_pre = Balances::usable_balance(self.sender);
  167. let channel_bag_id = Content::bag_id_for_channel(&self.channel_id);
  168. let video_id = Content::next_video_id();
  169. let beg_obj_id = storage::NextDataObjectId::<Test>::get();
  170. let actual_result = Content::create_video(
  171. origin,
  172. self.actor.clone(),
  173. self.channel_id,
  174. self.params.clone(),
  175. );
  176. let balance_post = Balances::usable_balance(self.sender);
  177. let end_obj_id = storage::NextDataObjectId::<Test>::get();
  178. assert_eq!(actual_result, expected_result);
  179. if actual_result.is_ok() {
  180. assert!(VideoById::<Test>::contains_key(&video_id));
  181. assert_eq!(
  182. Content::next_video_id(),
  183. video_id.saturating_add(One::one())
  184. );
  185. assert_eq!(
  186. System::events().last().unwrap().event,
  187. MetaEvent::content(RawEvent::VideoCreated(
  188. self.actor,
  189. self.channel_id,
  190. video_id,
  191. self.params.clone(),
  192. ))
  193. );
  194. if let Some(assets) = self.params.assets.as_ref() {
  195. // balance accounting is correct
  196. let bag_deletion_prize = BalanceOf::<Test>::zero();
  197. let objects_deletion_prize =
  198. assets
  199. .object_creation_list
  200. .iter()
  201. .fold(BalanceOf::<Test>::zero(), |acc, _| {
  202. acc.saturating_add(
  203. <Test as storage::Trait>::DataObjectDeletionPrize::get(),
  204. )
  205. });
  206. assert_eq!(
  207. balance_pre.saturating_sub(balance_post),
  208. bag_deletion_prize.saturating_add(objects_deletion_prize),
  209. );
  210. assert!((beg_obj_id..end_obj_id).all(|id| {
  211. storage::DataObjectsById::<Test>::contains_key(&channel_bag_id, id)
  212. }));
  213. }
  214. } else {
  215. assert!(!VideoById::<Test>::contains_key(&video_id));
  216. assert_eq!(Content::next_video_id(), video_id);
  217. if self.params.assets.is_some() {
  218. assert_eq!(balance_pre, balance_post,);
  219. assert!(!(beg_obj_id..end_obj_id).any(|id| {
  220. storage::DataObjectsById::<Test>::contains_key(&channel_bag_id, id)
  221. }));
  222. }
  223. }
  224. }
  225. }
  226. pub struct UpdateChannelFixture {
  227. sender: AccountId,
  228. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  229. channel_id: ChannelId,
  230. params: ChannelUpdateParameters<Test>,
  231. }
  232. impl UpdateChannelFixture {
  233. pub fn default() -> Self {
  234. Self {
  235. sender: DEFAULT_MEMBER_ACCOUNT_ID,
  236. actor: ContentActor::Member(DEFAULT_MEMBER_ACCOUNT_ID),
  237. channel_id: ChannelId::one(), // channel index starts at 1
  238. params: ChannelUpdateParameters::<Test> {
  239. assets_to_upload: None,
  240. new_meta: None,
  241. reward_account: None,
  242. assets_to_remove: BTreeSet::new(),
  243. collaborators: None,
  244. },
  245. }
  246. }
  247. pub fn with_sender(self, sender: AccountId) -> Self {
  248. Self { sender, ..self }
  249. }
  250. pub fn with_actor(self, actor: ContentActor<CuratorGroupId, CuratorId, MemberId>) -> Self {
  251. Self { actor, ..self }
  252. }
  253. pub fn with_channel_id(self, channel_id: ChannelId) -> Self {
  254. Self { channel_id, ..self }
  255. }
  256. pub fn with_assets_to_upload(self, assets: StorageAssets<Test>) -> Self {
  257. Self {
  258. params: ChannelUpdateParameters::<Test> {
  259. assets_to_upload: Some(assets),
  260. ..self.params
  261. },
  262. ..self
  263. }
  264. }
  265. pub fn with_assets_to_remove(self, assets: BTreeSet<DataObjectId<Test>>) -> Self {
  266. Self {
  267. params: ChannelUpdateParameters::<Test> {
  268. assets_to_remove: assets,
  269. ..self.params
  270. },
  271. ..self
  272. }
  273. }
  274. pub fn with_collaborators(self, collaborators: BTreeSet<MemberId>) -> Self {
  275. Self {
  276. params: ChannelUpdateParameters::<Test> {
  277. collaborators: Some(collaborators),
  278. ..self.params
  279. },
  280. ..self
  281. }
  282. }
  283. pub fn with_reward_account(self, reward_account: Option<Option<AccountId>>) -> Self {
  284. Self {
  285. params: ChannelUpdateParameters::<Test> {
  286. reward_account,
  287. ..self.params
  288. },
  289. ..self
  290. }
  291. }
  292. pub fn call_and_assert(&self, expected_result: DispatchResult) {
  293. let origin = Origin::signed(self.sender.clone());
  294. let balance_pre = Balances::usable_balance(self.sender);
  295. let channel_pre = Content::channel_by_id(&self.channel_id);
  296. let bag_id_for_channel = Content::bag_id_for_channel(&self.channel_id);
  297. let deletion_prize_deposited =
  298. self.params
  299. .assets_to_upload
  300. .as_ref()
  301. .map_or(BalanceOf::<Test>::zero(), |assets| {
  302. assets
  303. .object_creation_list
  304. .iter()
  305. .fold(BalanceOf::<Test>::zero(), |acc, _| {
  306. acc.saturating_add(
  307. <Test as storage::Trait>::DataObjectDeletionPrize::get(),
  308. )
  309. })
  310. });
  311. let deletion_prize_withdrawn = if !self.params.assets_to_remove.is_empty() {
  312. self.params
  313. .assets_to_remove
  314. .iter()
  315. .fold(BalanceOf::<Test>::zero(), |acc, id| {
  316. acc + storage::DataObjectsById::<Test>::get(&bag_id_for_channel, id)
  317. .deletion_prize
  318. })
  319. } else {
  320. BalanceOf::<Test>::zero()
  321. };
  322. let beg_obj_id = storage::NextDataObjectId::<Test>::get();
  323. let actual_result = Content::update_channel(
  324. origin,
  325. self.actor.clone(),
  326. self.channel_id,
  327. self.params.clone(),
  328. );
  329. let channel_post = Content::channel_by_id(&self.channel_id);
  330. let end_obj_id = storage::NextDataObjectId::<Test>::get();
  331. let balance_post = Balances::usable_balance(self.sender);
  332. assert_eq!(actual_result, expected_result);
  333. match actual_result {
  334. Ok(()) => {
  335. let owner = channel_post.owner.clone();
  336. assert_eq!(
  337. System::events().last().unwrap().event,
  338. MetaEvent::content(RawEvent::ChannelUpdated(
  339. self.actor.clone(),
  340. self.channel_id,
  341. ChannelRecord {
  342. owner: owner,
  343. is_censored: channel_pre.is_censored,
  344. reward_account: self
  345. .params
  346. .reward_account
  347. .clone()
  348. .unwrap_or(channel_pre.reward_account),
  349. collaborators: self
  350. .params
  351. .collaborators
  352. .clone()
  353. .unwrap_or(channel_pre.collaborators),
  354. num_videos: channel_pre.num_videos,
  355. },
  356. self.params.clone(),
  357. ))
  358. );
  359. assert_eq!(
  360. balance_post.saturating_sub(balance_pre),
  361. deletion_prize_withdrawn.saturating_sub(deletion_prize_deposited),
  362. );
  363. if self.params.assets_to_upload.is_some() {
  364. assert!((beg_obj_id..end_obj_id).all(|id| {
  365. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, id)
  366. }));
  367. }
  368. assert!(!self.params.assets_to_remove.iter().any(|id| {
  369. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, id)
  370. }));
  371. }
  372. Err(err) => {
  373. assert_eq!(channel_pre, channel_post);
  374. assert_eq!(balance_pre, balance_post);
  375. assert_eq!(beg_obj_id, end_obj_id);
  376. if err != storage::Error::<Test>::DataObjectDoesntExist.into() {
  377. assert!(self.params.assets_to_remove.iter().all(|id| {
  378. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, id)
  379. }))
  380. }
  381. }
  382. }
  383. }
  384. }
  385. pub struct UpdateVideoFixture {
  386. sender: AccountId,
  387. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  388. video_id: VideoId,
  389. params: VideoUpdateParameters<Test>,
  390. }
  391. impl UpdateVideoFixture {
  392. pub fn default() -> Self {
  393. Self {
  394. sender: DEFAULT_MEMBER_ACCOUNT_ID,
  395. actor: ContentActor::Member(DEFAULT_MEMBER_ID),
  396. video_id: VideoId::one(),
  397. params: VideoUpdateParameters::<Test> {
  398. assets_to_upload: None,
  399. assets_to_remove: BTreeSet::new(),
  400. new_meta: None,
  401. },
  402. }
  403. }
  404. pub fn with_sender(self, sender: AccountId) -> Self {
  405. Self { sender, ..self }
  406. }
  407. pub fn with_actor(self, actor: ContentActor<CuratorGroupId, CuratorId, MemberId>) -> Self {
  408. Self { actor, ..self }
  409. }
  410. pub fn with_video_id(self, video_id: VideoId) -> Self {
  411. Self { video_id, ..self }
  412. }
  413. pub fn with_assets_to_upload(self, assets: StorageAssets<Test>) -> Self {
  414. Self {
  415. params: VideoUpdateParameters::<Test> {
  416. assets_to_upload: Some(assets),
  417. ..self.params
  418. },
  419. ..self
  420. }
  421. }
  422. pub fn with_assets_to_remove(self, assets: BTreeSet<DataObjectId<Test>>) -> Self {
  423. Self {
  424. params: VideoUpdateParameters::<Test> {
  425. assets_to_remove: assets,
  426. ..self.params
  427. },
  428. ..self
  429. }
  430. }
  431. pub fn call_and_assert(&self, expected_result: DispatchResult) {
  432. let origin = Origin::signed(self.sender.clone());
  433. let balance_pre = Balances::usable_balance(self.sender);
  434. let video_pre = Content::video_by_id(&self.video_id);
  435. let bag_id_for_channel = Content::bag_id_for_channel(&video_pre.in_channel);
  436. let beg_obj_id = storage::NextDataObjectId::<Test>::get();
  437. let deletion_prize_deposited =
  438. self.params
  439. .assets_to_upload
  440. .as_ref()
  441. .map_or(BalanceOf::<Test>::zero(), |assets| {
  442. assets
  443. .object_creation_list
  444. .iter()
  445. .fold(BalanceOf::<Test>::zero(), |acc, _| {
  446. acc.saturating_add(
  447. <Test as storage::Trait>::DataObjectDeletionPrize::get(),
  448. )
  449. })
  450. });
  451. let deletion_prize_withdrawn = if !self.params.assets_to_remove.is_empty() {
  452. self.params
  453. .assets_to_remove
  454. .iter()
  455. .fold(BalanceOf::<Test>::zero(), |acc, obj_id| {
  456. acc + storage::DataObjectsById::<Test>::get(&bag_id_for_channel, obj_id)
  457. .deletion_prize
  458. })
  459. } else {
  460. BalanceOf::<Test>::zero()
  461. };
  462. let actual_result = Content::update_video(
  463. origin,
  464. self.actor.clone(),
  465. self.video_id,
  466. self.params.clone(),
  467. );
  468. let end_obj_id = storage::NextDataObjectId::<Test>::get();
  469. let balance_post = Balances::usable_balance(self.sender);
  470. let video_post = Content::video_by_id(&self.video_id);
  471. assert_eq!(actual_result, expected_result);
  472. match actual_result {
  473. Ok(()) => {
  474. assert_eq!(
  475. System::events().last().unwrap().event,
  476. MetaEvent::content(RawEvent::VideoUpdated(
  477. self.actor.clone(),
  478. self.video_id,
  479. self.params.clone()
  480. ))
  481. );
  482. assert_eq!(
  483. balance_post.saturating_sub(balance_pre),
  484. deletion_prize_withdrawn.saturating_sub(deletion_prize_deposited),
  485. );
  486. if self.params.assets_to_upload.is_some() {
  487. assert!((beg_obj_id..end_obj_id).all(|id| {
  488. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, id)
  489. }));
  490. }
  491. assert!(!self.params.assets_to_remove.iter().any(|obj_id| {
  492. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, obj_id)
  493. }));
  494. }
  495. Err(err) => {
  496. assert_eq!(video_pre, video_post);
  497. assert_eq!(balance_pre, balance_post);
  498. assert_eq!(beg_obj_id, end_obj_id);
  499. if err != storage::Error::<Test>::DataObjectDoesntExist.into() {
  500. assert!(self.params.assets_to_remove.iter().all(|id| {
  501. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, id)
  502. }));
  503. }
  504. }
  505. }
  506. }
  507. }
  508. pub struct DeleteChannelFixture {
  509. sender: AccountId,
  510. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  511. channel_id: ChannelId,
  512. num_objects_to_delete: u64,
  513. }
  514. impl DeleteChannelFixture {
  515. pub fn default() -> Self {
  516. Self {
  517. sender: DEFAULT_MEMBER_ACCOUNT_ID,
  518. actor: ContentActor::Member(DEFAULT_MEMBER_ID),
  519. channel_id: ChannelId::one(),
  520. num_objects_to_delete: DATA_OBJECTS_NUMBER as u64,
  521. }
  522. }
  523. pub fn with_sender(self, sender: AccountId) -> Self {
  524. Self { sender, ..self }
  525. }
  526. pub fn with_actor(self, actor: ContentActor<CuratorGroupId, CuratorId, MemberId>) -> Self {
  527. Self { actor, ..self }
  528. }
  529. pub fn with_num_objects_to_delete(self, num_objects_to_delete: u64) -> Self {
  530. Self {
  531. num_objects_to_delete,
  532. ..self
  533. }
  534. }
  535. pub fn with_channel_id(self, channel_id: ChannelId) -> Self {
  536. Self { channel_id, ..self }
  537. }
  538. pub fn call_and_assert(&self, expected_result: DispatchResult) {
  539. let origin = Origin::signed(self.sender.clone());
  540. let balance_pre = Balances::usable_balance(self.sender);
  541. let bag_id_for_channel = Content::bag_id_for_channel(&self.channel_id);
  542. let bag_deletion_prize = storage::Bags::<Test>::get(&bag_id_for_channel)
  543. .deletion_prize
  544. .unwrap_or(BalanceOf::<Test>::zero());
  545. let objects_deletion_prize =
  546. storage::DataObjectsById::<Test>::iter_prefix(&bag_id_for_channel)
  547. .fold(BalanceOf::<Test>::zero(), |acc, (_, obj)| {
  548. acc + obj.deletion_prize
  549. });
  550. let channel_objects_ids =
  551. storage::DataObjectsById::<Test>::iter_prefix(&bag_id_for_channel)
  552. .map(|(id, _)| id)
  553. .collect::<BTreeSet<_>>();
  554. let actual_result = Content::delete_channel(
  555. origin,
  556. self.actor.clone(),
  557. self.channel_id,
  558. self.num_objects_to_delete,
  559. );
  560. let balance_post = Balances::usable_balance(self.sender);
  561. assert_eq!(actual_result, expected_result);
  562. match actual_result {
  563. Ok(()) => {
  564. assert_eq!(
  565. System::events().last().unwrap().event,
  566. MetaEvent::content(RawEvent::ChannelDeleted(
  567. self.actor.clone(),
  568. self.channel_id,
  569. ))
  570. );
  571. let deletion_prize = bag_deletion_prize.saturating_add(objects_deletion_prize);
  572. assert_eq!(balance_post.saturating_sub(balance_pre), deletion_prize,);
  573. assert!(!<ChannelById<Test>>::contains_key(&self.channel_id));
  574. assert!(!channel_objects_ids.iter().any(|id| {
  575. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, id)
  576. }));
  577. assert!(!storage::Bags::<Test>::contains_key(&bag_id_for_channel));
  578. }
  579. Err(err) => {
  580. assert_eq!(balance_pre, balance_post);
  581. if err != Error::<Test>::ChannelDoesNotExist.into() {
  582. assert!(ChannelById::<Test>::contains_key(&self.channel_id));
  583. assert!(channel_objects_ids.iter().all(|id| {
  584. storage::DataObjectsById::<Test>::contains_key(&bag_id_for_channel, id)
  585. }));
  586. assert!(storage::Bags::<Test>::contains_key(&bag_id_for_channel));
  587. }
  588. }
  589. }
  590. }
  591. }
  592. pub struct DeleteVideoFixture {
  593. sender: AccountId,
  594. actor: ContentActor<CuratorGroupId, CuratorId, MemberId>,
  595. video_id: VideoId,
  596. assets_to_remove: BTreeSet<DataObjectId<Test>>,
  597. }
  598. impl DeleteVideoFixture {
  599. pub fn default() -> Self {
  600. Self {
  601. sender: DEFAULT_MEMBER_ACCOUNT_ID,
  602. actor: ContentActor::Member(DEFAULT_MEMBER_ID),
  603. video_id: VideoId::one(),
  604. assets_to_remove: BTreeSet::new(),
  605. }
  606. }
  607. pub fn with_sender(self, sender: AccountId) -> Self {
  608. Self { sender, ..self }
  609. }
  610. pub fn with_actor(self, actor: ContentActor<CuratorGroupId, CuratorId, MemberId>) -> Self {
  611. Self { actor, ..self }
  612. }
  613. pub fn with_assets_to_remove(self, assets_to_remove: BTreeSet<DataObjectId<Test>>) -> Self {
  614. Self {
  615. assets_to_remove,
  616. ..self
  617. }
  618. }
  619. pub fn with_video_id(self, video_id: VideoId) -> Self {
  620. Self { video_id, ..self }
  621. }
  622. pub fn call_and_assert(&self, expected_result: DispatchResult) {
  623. let origin = Origin::signed(self.sender.clone());
  624. let balance_pre = Balances::usable_balance(self.sender);
  625. let video_pre = <VideoById<Test>>::get(&self.video_id);
  626. let channel_bag_id = Content::bag_id_for_channel(&video_pre.in_channel);
  627. let deletion_prize =
  628. self.assets_to_remove
  629. .iter()
  630. .fold(BalanceOf::<Test>::zero(), |acc, obj_id| {
  631. acc + storage::DataObjectsById::<Test>::get(&channel_bag_id, obj_id)
  632. .deletion_prize
  633. });
  634. let actual_result = Content::delete_video(
  635. origin,
  636. self.actor.clone(),
  637. self.video_id,
  638. self.assets_to_remove.clone(),
  639. );
  640. let balance_post = Balances::usable_balance(self.sender);
  641. assert_eq!(actual_result, expected_result);
  642. match actual_result {
  643. Ok(()) => {
  644. assert_eq!(
  645. System::events().last().unwrap().event,
  646. MetaEvent::content(RawEvent::VideoDeleted(self.actor.clone(), self.video_id,))
  647. );
  648. assert_eq!(balance_post.saturating_sub(balance_pre), deletion_prize);
  649. assert!(!self.assets_to_remove.iter().any(|obj_id| {
  650. storage::DataObjectsById::<Test>::contains_key(&channel_bag_id, obj_id)
  651. }));
  652. assert!(!<VideoById<Test>>::contains_key(&self.video_id));
  653. }
  654. Err(err) => {
  655. assert_eq!(balance_pre, balance_post);
  656. if err == storage::Error::<Test>::DataObjectDoesntExist.into() {
  657. let video_post = <VideoById<Test>>::get(&self.video_id);
  658. assert_eq!(video_pre, video_post);
  659. assert!(VideoById::<Test>::contains_key(&self.video_id));
  660. } else if err == Error::<Test>::VideoDoesNotExist.into() {
  661. assert!(self.assets_to_remove.iter().all(|id| {
  662. storage::DataObjectsById::<Test>::contains_key(&channel_bag_id, id)
  663. }));
  664. } else {
  665. let video_post = <VideoById<Test>>::get(&self.video_id);
  666. assert_eq!(video_pre, video_post);
  667. assert!(VideoById::<Test>::contains_key(&self.video_id));
  668. assert!(self.assets_to_remove.iter().all(|id| {
  669. storage::DataObjectsById::<Test>::contains_key(&channel_bag_id, id)
  670. }));
  671. }
  672. }
  673. }
  674. }
  675. }
  676. // helper functions
  677. pub fn increase_account_balance_helper(account_id: u64, balance: u64) {
  678. let _ = Balances::deposit_creating(&account_id, balance);
  679. }
  680. pub fn slash_account_balance_helper(account_id: u64) {
  681. let _ = Balances::slash(&account_id, Balances::total_balance(&account_id));
  682. }
  683. pub fn create_data_object_candidates_helper(
  684. starting_ipfs_index: u8,
  685. number: u64,
  686. ) -> Vec<DataObjectCreationParameters> {
  687. let range = (starting_ipfs_index as u64)..((starting_ipfs_index as u64) + number);
  688. range
  689. .into_iter()
  690. .map(|_| DataObjectCreationParameters {
  691. size: DEFAULT_OBJECT_SIZE,
  692. ipfs_content_id: vec![1u8],
  693. })
  694. .collect()
  695. }
  696. pub fn create_data_objects_helper() -> Vec<DataObjectCreationParameters> {
  697. create_data_object_candidates_helper(1, DATA_OBJECTS_NUMBER)
  698. }
  699. pub fn create_initial_storage_buckets_helper() {
  700. // first set limits
  701. assert_eq!(
  702. Storage::<Test>::update_storage_buckets_voucher_max_limits(
  703. Origin::signed(STORAGE_WG_LEADER_ACCOUNT_ID),
  704. VOUCHER_OBJECTS_SIZE_LIMIT,
  705. VOUCHER_OBJECTS_NUMBER_LIMIT,
  706. ),
  707. Ok(())
  708. );
  709. // create bucket(s)
  710. assert_eq!(
  711. Storage::<Test>::create_storage_bucket(
  712. Origin::signed(STORAGE_WG_LEADER_ACCOUNT_ID),
  713. None,
  714. STORAGE_BUCKET_ACCEPTING_BAGS,
  715. STORAGE_BUCKET_OBJECTS_SIZE_LIMIT,
  716. STORAGE_BUCKET_OBJECTS_NUMBER_LIMIT,
  717. ),
  718. Ok(())
  719. );
  720. }
  721. pub fn create_default_member_owned_channel() {
  722. CreateChannelFixture::default()
  723. .with_sender(DEFAULT_MEMBER_ACCOUNT_ID)
  724. .with_actor(ContentActor::Member(DEFAULT_MEMBER_ID))
  725. .with_assets(StorageAssets::<Test> {
  726. expected_data_size_fee: Storage::<Test>::data_object_per_mega_byte_fee(),
  727. object_creation_list: create_data_objects_helper(),
  728. })
  729. .with_reward_account(DEFAULT_MEMBER_ACCOUNT_ID)
  730. .with_collaborators(vec![COLLABORATOR_MEMBER_ID].into_iter().collect())
  731. .call_and_assert(Ok(()));
  732. }
  733. pub fn create_default_curator_owned_channel() {
  734. let curator_group_id = curators::add_curator_to_new_group(DEFAULT_CURATOR_ID);
  735. CreateChannelFixture::default()
  736. .with_sender(DEFAULT_CURATOR_ACCOUNT_ID)
  737. .with_actor(ContentActor::Curator(curator_group_id, DEFAULT_CURATOR_ID))
  738. .with_assets(StorageAssets::<Test> {
  739. expected_data_size_fee: Storage::<Test>::data_object_per_mega_byte_fee(),
  740. object_creation_list: create_data_objects_helper(),
  741. })
  742. .with_reward_account(DEFAULT_CURATOR_ACCOUNT_ID)
  743. .with_collaborators(vec![COLLABORATOR_MEMBER_ID].into_iter().collect())
  744. .call_and_assert(Ok(()));
  745. }
  746. pub fn create_default_member_owned_channel_with_video() {
  747. create_default_member_owned_channel();
  748. CreateVideoFixture::default()
  749. .with_sender(DEFAULT_MEMBER_ACCOUNT_ID)
  750. .with_actor(ContentActor::Member(DEFAULT_MEMBER_ID))
  751. .with_assets(StorageAssets::<Test> {
  752. expected_data_size_fee: Storage::<Test>::data_object_per_mega_byte_fee(),
  753. object_creation_list: create_data_objects_helper(),
  754. })
  755. .with_channel_id(NextChannelId::<Test>::get() - 1)
  756. .call_and_assert(Ok(()));
  757. }
  758. pub fn create_default_curator_owned_channel_with_video() {
  759. create_default_curator_owned_channel();
  760. let curator_group_id = NextCuratorGroupId::<Test>::get() - 1;
  761. CreateVideoFixture::default()
  762. .with_sender(DEFAULT_CURATOR_ACCOUNT_ID)
  763. .with_actor(ContentActor::Curator(curator_group_id, DEFAULT_CURATOR_ID))
  764. .with_assets(StorageAssets::<Test> {
  765. expected_data_size_fee: Storage::<Test>::data_object_per_mega_byte_fee(),
  766. object_creation_list: create_data_objects_helper(),
  767. })
  768. .with_channel_id(NextChannelId::<Test>::get() - 1)
  769. .call_and_assert(Ok(()));
  770. }
  771. pub fn create_default_member_owned_channels_with_videos(n: u64) -> (u64, u64) {
  772. for _ in 0..n {
  773. create_default_member_owned_channel_with_video();
  774. }
  775. // assert that the specified channels have been created
  776. assert_eq!(VideoById::<Test>::iter().count() as u64, n);
  777. assert_eq!(ChannelById::<Test>::iter().count() as u64, n);
  778. let channels_migrations_per_block = <Test as Trait>::ChannelsMigrationsEachBlock::get();
  779. let videos_migrations_per_block = <Test as Trait>::VideosMigrationsEachBlock::get();
  780. // return the number of blocks required for migration
  781. let divide_with_ceiling =
  782. |x: u64, y: u64| (x / y) + ((x.checked_rem(y).unwrap_or_default() > 0u64) as u64);
  783. (
  784. divide_with_ceiling(n, channels_migrations_per_block),
  785. divide_with_ceiling(n, videos_migrations_per_block),
  786. )
  787. }