From 44e80c569c2fe55347149cd796e0cc2140948d5d Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 13 Sep 2024 12:53:36 -0400 Subject: [PATCH] Update tests.rs --- steps/54/src/tests.rs | 292 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) diff --git a/steps/54/src/tests.rs b/steps/54/src/tests.rs index 2969c31c..fab1f489 100644 --- a/steps/54/src/tests.rs +++ b/steps/54/src/tests.rs @@ -29,6 +29,10 @@ construct_runtime! { } } +const DEFAULT_KITTY: Kitty = Kitty { dna: [0u8; 32], owner: 1, price: None }; +const ALICE: u64 = 1; +const BOB: u64 = 2; + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; @@ -85,3 +89,291 @@ fn create_kitty_emits_event() { System::assert_last_event(Event::::Created { owner: 1 }.into()); }) } + +#[test] +fn count_for_kitties_created_correctly() { + new_test_ext().execute_with(|| { + // Querying storage before anything is set will return `0`. + assert_eq!(CountForKitties::::get(), 0); + // You can `set` the value using an `u32`. + CountForKitties::::set(1337u32); + // You can `put` the value directly with a `u32`. + CountForKitties::::put(1337u32); + }) +} + +#[test] +fn mint_increments_count_for_kitty() { + new_test_ext().execute_with(|| { + // Querying storage before anything is set will return `0`. + assert_eq!(CountForKitties::::get(), 0); + // Call `mint` to create a new kitty. + assert_ok!(PalletKitties::mint(1, [1u8; 32])); + // Now the storage should be `1` + assert_eq!(CountForKitties::::get(), 1); + // Let's call it two more times... + assert_ok!(PalletKitties::mint(2, [2u8; 32])); + assert_ok!(PalletKitties::mint(3, [3u8; 32])); + // Now the storage should be `3` + assert_eq!(CountForKitties::::get(), 3); + }) +} + +#[test] +fn mint_errors_when_overflow() { + new_test_ext().execute_with(|| { + // Set the count to the largest value possible. + CountForKitties::::set(u32::MAX); + // `create_kitty` should not succeed because of safe math. + assert_noop!( + PalletKitties::create_kitty(RuntimeOrigin::signed(1)), + Error::::TooManyKitties + ); + }) +} + +#[test] +fn kitties_map_created_correctly() { + new_test_ext().execute_with(|| { + let zero_key = [0u8; 32]; + assert_eq!(Kitties::::contains_key(zero_key), false); + Kitties::::insert(zero_key, DEFAULT_KITTY); + assert_eq!(Kitties::::contains_key(zero_key), true); + }) +} + +#[test] +fn create_kitty_adds_to_map() { + new_test_ext().execute_with(|| { + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(1))); + assert_eq!(Kitties::::iter().count(), 1); + }) +} + +#[test] +fn cannot_mint_duplicate_kitty() { + new_test_ext().execute_with(|| { + assert_ok!(PalletKitties::mint(1, [0u8; 32])); + assert_noop!(PalletKitties::mint(2, [0u8; 32]), Error::::DuplicateKitty); + }) +} + +#[test] +fn kitty_struct_has_expected_traits() { + new_test_ext().execute_with(|| { + let kitty = DEFAULT_KITTY; + let bytes = kitty.encode(); + let _new_kitty = Kitty::::decode(&mut &bytes[..]).unwrap(); + assert!(Kitty::::max_encoded_len() > 0); + let _info = Kitty::::type_info(); + }) +} + +#[test] +fn mint_stores_owner_in_kitty() { + new_test_ext().execute_with(|| { + assert_ok!(PalletKitties::mint(1337, [42u8; 32])); + let kitty = Kitties::::get([42u8; 32]).unwrap(); + assert_eq!(kitty.owner, 1337); + assert_eq!(kitty.dna, [42u8; 32]); + }) +} + +#[test] +fn create_kitty_makes_unique_kitties() { + new_test_ext().execute_with(|| { + // Two calls to `create_kitty` should work. + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(1))); + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(2))); + // And should result in two kitties in our system. + assert_eq!(CountForKitties::::get(), 2); + assert_eq!(Kitties::::iter().count(), 2); + }) +} + +#[test] +fn kitties_owned_created_correctly() { + new_test_ext().execute_with(|| { + // Initially users have no kitties owned. + assert_eq!(KittiesOwned::::get(1).len(), 0); + // Let's create two kitties. + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(1))); + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(1))); + // Now they should have two kitties owned. + assert_eq!(KittiesOwned::::get(1).len(), 2); + }); +} + +#[test] +fn cannot_own_too_many_kitties() { + new_test_ext().execute_with(|| { + // If your max owned is different than 100, you will need to update this. + for _ in 0..100 { + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(1))); + } + assert_noop!( + PalletKitties::create_kitty(RuntimeOrigin::signed(1)), + Error::::TooManyOwned + ); + }); +} + +#[test] +fn transfer_emits_event() { + new_test_ext().execute_with(|| { + // We need to set block number to 1 to view events. + System::set_block_number(1); + // Create a kitty to transfer + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(ALICE))); + // Get the kitty id. + let kitty_id = Kitties::::iter_keys().collect::>()[0]; + assert_ok!(PalletKitties::transfer(RuntimeOrigin::signed(ALICE), BOB, kitty_id)); + System::assert_last_event( + Event::::Transferred { from: ALICE, to: BOB, kitty_id }.into(), + ); + }); +} + +#[test] +fn transfer_logic_works() { + new_test_ext().execute_with(|| { + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(ALICE))); + // Starting state looks good. + let kitty = &Kitties::::iter_values().collect::>()[0]; + let kitty_id = kitty.dna; + assert_eq!(kitty.owner, ALICE); + assert_eq!(KittiesOwned::::get(ALICE), vec![kitty_id]); + assert_eq!(KittiesOwned::::get(BOB), vec![]); + // Cannot transfer to yourself. + assert_noop!( + PalletKitties::transfer(RuntimeOrigin::signed(ALICE), ALICE, kitty_id), + Error::::TransferToSelf + ); + // Cannot transfer a non-existent kitty. + assert_noop!( + PalletKitties::transfer(RuntimeOrigin::signed(ALICE), BOB, [0u8; 32]), + Error::::NoKitty + ); + // Cannot transfer kitty you do not own. + assert_noop!( + PalletKitties::transfer(RuntimeOrigin::signed(BOB), ALICE, kitty_id), + Error::::NotOwner + ); + // Transfer should work when parameters are right. + assert_ok!(PalletKitties::transfer(RuntimeOrigin::signed(ALICE), BOB, kitty_id)); + // Storage is updated correctly. + assert_eq!(KittiesOwned::::get(ALICE), vec![]); + assert_eq!(KittiesOwned::::get(BOB), vec![kitty_id]); + let kitty = &Kitties::::iter_values().collect::>()[0]; + assert_eq!(kitty.owner, BOB); + }); +} + +#[test] +fn native_balance_associated_type_works() { + new_test_ext().execute_with(|| { + assert_ok!(<::NativeBalance as Mutate<_>>::mint_into(&ALICE, 1337)); + assert_eq!( + <::NativeBalance as Inspect<_>>::total_balance(&ALICE), + 1337 + ); + }); +} + +#[test] +fn balance_of_type_works() { + // Inside our tests, the `BalanceOf` type has a concrete type of `u64`. + let _example_balance: BalanceOf = 1337u64; +} + +#[test] +fn set_price_emits_event() { + new_test_ext().execute_with(|| { + // We need to set block number to 1 to view events. + System::set_block_number(1); + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(ALICE))); + let kitty_id = Kitties::::iter_keys().collect::>()[0]; + assert_ok!(PalletKitties::set_price(RuntimeOrigin::signed(ALICE), kitty_id, Some(1337))); + // Assert the last event by our blockchain is the `Created` event with the correct owner. + System::assert_last_event( + Event::::PriceSet { owner: ALICE, kitty_id, new_price: Some(1337) }.into(), + ); + }) +} + +#[test] +fn set_price_logic_works() { + new_test_ext().execute_with(|| { + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(ALICE))); + let kitty = &Kitties::::iter_values().collect::>()[0]; + assert_eq!(kitty.price, None); + let kitty_id = kitty.dna; + assert_ok!(PalletKitties::set_price(RuntimeOrigin::signed(ALICE), kitty_id, Some(1337))); + let kitty = Kitties::::get(kitty_id).unwrap(); + assert_eq!(kitty.price, Some(1337)); + }) +} + +#[test] +fn do_buy_kitty_emits_event() { + new_test_ext().execute_with(|| { + // We need to set block number to 1 to view events. + System::set_block_number(1); + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(ALICE))); + let kitty_id = Kitties::::iter_keys().collect::>()[0]; + assert_ok!(PalletKitties::set_price(RuntimeOrigin::signed(ALICE), kitty_id, Some(1337))); + assert_ok!(Balances::mint_into(&BOB, 100_000)); + assert_ok!(PalletKitties::buy_kitty(RuntimeOrigin::signed(BOB), kitty_id, 1337)); + // Assert the last event by our blockchain is the `Created` event with the correct owner. + System::assert_last_event( + Event::::Sold { buyer: BOB, kitty_id, price: 1337 }.into(), + ); + }) +} + +#[test] +fn do_buy_kitty_logic_works() { + new_test_ext().execute_with(|| { + assert_ok!(PalletKitties::create_kitty(RuntimeOrigin::signed(ALICE))); + let kitty = &Kitties::::iter_values().collect::>()[0]; + let kitty_id = kitty.dna; + assert_eq!(kitty.owner, ALICE); + assert_eq!(KittiesOwned::::get(ALICE), vec![kitty_id]); + // Cannot buy kitty which does not exist. + assert_noop!( + PalletKitties::buy_kitty(RuntimeOrigin::signed(BOB), [0u8; 32], 1337), + Error::::NoKitty + ); + // Cannot buy kitty which is not for sale. + assert_noop!( + PalletKitties::buy_kitty(RuntimeOrigin::signed(BOB), kitty_id, 1337), + Error::::NotForSale + ); + assert_ok!(PalletKitties::set_price(RuntimeOrigin::signed(ALICE), kitty_id, Some(1337))); + // Cannot buy kitty for a lower price. + assert_noop!( + PalletKitties::buy_kitty(RuntimeOrigin::signed(BOB), kitty_id, 1336), + Error::::MaxPriceTooLow + ); + // Cannot buy kitty if you don't have the funds. + assert_noop!( + PalletKitties::buy_kitty(RuntimeOrigin::signed(BOB), kitty_id, 1337), + frame::arithmetic::ArithmeticError::Underflow + ); + // Cannot buy kitty if it would kill your account (i.e. set your balance to 0). + assert_ok!(Balances::mint_into(&BOB, 1337)); + assert!( + PalletKitties::buy_kitty(RuntimeOrigin::signed(BOB), kitty_id, 1337).is_err(), + // TODO: assert_noop on DispatchError::Token(TokenError::NotExpendable) + ); + // When everything is right, it works. + assert_ok!(Balances::mint_into(&BOB, 100_000)); + assert_ok!(PalletKitties::buy_kitty(RuntimeOrigin::signed(BOB), kitty_id, 1337)); + // State is updated correctly. + assert_eq!(KittiesOwned::::get(BOB), vec![kitty_id]); + let kitty = Kitties::::get(kitty_id).unwrap(); + assert_eq!(kitty.owner, BOB); + // Price is reset to `None`. + assert_eq!(kitty.price, None); + }) +}