use grovewright_core::codec::{DecodeError, Reader, Writer}; use grovewright_core::inventory::{ Inventory, ItemId, Stack, INVENTORY_SLOTS, ITEM_STONE, STACK_LIMIT, }; const OTHER: ItemId = ItemId(2); const CAPACITY: u32 = STACK_LIMIT * INVENTORY_SLOTS as u32; #[test] fn a_new_inventory_is_empty() { let inventory = Inventory::new(); assert_eq!(inventory.slots().len(), INVENTORY_SLOTS); assert!(inventory.slots().iter().all(Option::is_none)); assert_eq!(inventory.count(ITEM_STONE), 0); assert_eq!(inventory.free_space(ITEM_STONE), CAPACITY); assert_eq!(Inventory::default(), inventory); } #[test] fn add_tops_up_a_stack_before_using_an_empty_slot() { let mut inventory = Inventory::new(); assert_eq!(inventory.add(ITEM_STONE, 90), 0); assert_eq!(inventory.add(OTHER, 5), 0); assert_eq!(inventory.add(ITEM_STONE, 20), 0); let stone = |count| { Some(Stack { item: ITEM_STONE, count, }) }; assert_eq!(inventory.slots()[0], stone(99)); assert_eq!( inventory.slots()[1], Some(Stack { item: OTHER, count: 5 }) ); assert_eq!(inventory.slots()[2], stone(11)); assert_eq!(inventory.count(ITEM_STONE), 110); assert_eq!(inventory.count(OTHER), 5); } #[test] fn add_reports_what_does_not_fit() { let mut inventory = Inventory::new(); assert_eq!(inventory.add(ITEM_STONE, CAPACITY + 7), 7); assert_eq!(inventory.count(ITEM_STONE), CAPACITY); assert_eq!(inventory.free_space(ITEM_STONE), 0); assert_eq!(inventory.free_space(OTHER), 0); assert_eq!(inventory.add(OTHER, 1), 1); } #[test] fn free_space_counts_empty_slots_and_matching_stacks() { let mut inventory = Inventory::new(); inventory.add(ITEM_STONE, 10); inventory.add(OTHER, 1); assert_eq!( inventory.free_space(ITEM_STONE), CAPACITY - STACK_LIMIT - 10 ); assert_eq!(inventory.free_space(OTHER), CAPACITY - STACK_LIMIT - 1); } #[test] fn remove_takes_exactly_the_requested_amount() { let mut inventory = Inventory::new(); inventory.add(ITEM_STONE, 150); assert!(inventory.remove(ITEM_STONE, 60)); assert_eq!(inventory.count(ITEM_STONE), 90); assert_eq!( inventory.slots()[0], Some(Stack { item: ITEM_STONE, count: 90 }) ); assert_eq!(inventory.slots()[1], None); } #[test] fn remove_changes_nothing_when_too_few_are_present() { let mut inventory = Inventory::new(); inventory.add(ITEM_STONE, 10); let before = inventory.clone(); assert!(!inventory.remove(ITEM_STONE, 11)); assert!(!inventory.remove(OTHER, 1)); assert_eq!(inventory, before); } #[test] #[should_panic(expected = "item id zero is reserved")] fn the_reserved_item_id_cannot_be_added() { Inventory::new().add(ItemId(0), 1); } #[test] fn an_inventory_survives_encoding() { let mut inventory = Inventory::new(); inventory.add(ITEM_STONE, 120); inventory.add(OTHER, 3); let mut w = Writer::new(); inventory.encode(&mut w); let bytes = w.into_bytes(); let mut r = Reader::new(&bytes); assert_eq!(Inventory::decode(&mut r), Ok(inventory)); assert_eq!(r.finish(), Ok(())); } #[test] fn decoding_rejects_impossible_stack_counts() { for count in [0, STACK_LIMIT + 1] { let mut w = Writer::new(); w.u16(ITEM_STONE.0); w.u32(count); let bytes = w.into_bytes(); assert_eq!( Inventory::decode(&mut Reader::new(&bytes)), Err(DecodeError::InvalidValue("stack count")), "count {count}" ); } }