/** * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "dusktest.h" #include "item/inventory.h" static void test_inventoryInit(void **state) { (void)state; inventorystack_t storage[5]; inventory_t inventory; inventoryInit(&inventory, storage, 5); // Should setup struct assert_non_null(inventory.storage); assert_int_equal(inventory.storageSize, 5); // Should zero the item ids. for(size_t i = 0; i < inventory.storageSize; i++) { assert_int_equal(inventory.storage[i].item, ITEM_ID_NULL); assert_int_equal(inventory.storage[i].quantity, 0); } // Should fail when given NULL inventory pointer expect_assert_failure(inventoryInit(NULL, storage, 5)); // Should fail when given NULL storage pointer expect_assert_failure(inventoryInit(&inventory, NULL, 5)); // Should fail when given zero storage size expect_assert_failure(inventoryInit(&inventory, storage, 0)); } static void test_inventoryItemExists(void **state) { (void)state; inventorystack_t storage[5]; inventory_t inventory; inventoryInit(&inventory, storage, 5); // Initially should not exist assert_false(inventoryItemExists(&inventory, ITEM_ID_POTION)); // Add item inventorySet(&inventory, ITEM_ID_POTION, 3); assert_true(inventoryItemExists(&inventory, ITEM_ID_POTION)); // Remove item inventorySet(&inventory, ITEM_ID_POTION, 0); assert_false(inventoryItemExists(&inventory, ITEM_ID_POTION)); // Should fail when given NULL inventory pointer expect_assert_failure(inventoryItemExists(NULL, ITEM_ID_POTION)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventoryItemExists(&inventory, ITEM_ID_POTION)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventoryItemExists(&inventory, ITEM_ID_POTION)); inventory.storageSize = 5; // Should fail when given ITEM_ID_NULL expect_assert_failure(inventoryItemExists(&inventory, ITEM_ID_NULL)); // Should fail if item has zero quantity somehow inventorySet(&inventory, ITEM_ID_POTION, 3); inventory.storage[0].quantity = 0; expect_assert_failure(inventoryItemExists(&inventory, ITEM_ID_POTION)); } static void test_inventorySet(void **state) { (void)state; inventorystack_t storage[5]; inventory_t inventory; inventoryInit(&inventory, storage, 5); // Set item quantity inventorySet(&inventory, ITEM_ID_POTION, 4); assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[0].quantity, 4); // Update item quantity inventorySet(&inventory, ITEM_ID_POTION, 2); assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[0].quantity, 2); // Remove item by setting quantity to 0 inventorySet(&inventory, ITEM_ID_POTION, 0); assert_int_equal(inventory.storage[0].item, ITEM_ID_NULL); // Setting multiple items should not cause issues inventorySet(&inventory, ITEM_ID_POTION, 1); inventorySet(&inventory, ITEM_ID_POTATO, 5); assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[0].quantity, 1); assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); assert_int_equal(inventory.storage[1].quantity, 5); assert_int_equal(inventory.storage[2].item, ITEM_ID_NULL); // Setting early item to 0 should shift others down inventorySet(&inventory, ITEM_ID_POTION, 0);// Item 0 removed assert_int_equal(inventory.storage[0].item, ITEM_ID_POTATO); assert_int_equal(inventory.storage[0].quantity, 5); assert_int_equal(inventory.storage[1].item, ITEM_ID_NULL); // Setting non-existing item should add it inventorySet(&inventory, ITEM_ID_POTION, 3); assert_int_equal(inventory.storage[1].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[1].quantity, 3); // Should fail when given NULL inventory pointer expect_assert_failure(inventorySet(NULL, ITEM_ID_POTION, 3)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventorySet(&inventory, ITEM_ID_POTION, 3)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventorySet(&inventory, ITEM_ID_POTION, 3)); inventory.storageSize = 5; // Should fail when given ITEM_ID_NULL expect_assert_failure(inventorySet(&inventory, ITEM_ID_NULL, 3)); } static void test_inventoryAdd(void **state) { (void)state; inventorystack_t storage[5]; inventory_t inventory; inventoryInit(&inventory, storage, 5); // Add item quantity inventoryAdd(&inventory, ITEM_ID_POTION, 4); assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[0].quantity, 4); // Add more to existing item inventoryAdd(&inventory, ITEM_ID_POTION, 3); assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[0].quantity, 7); // Adding item that would overflow should assert expect_assert_failure(inventoryAdd(&inventory, ITEM_ID_POTION, 250)); // Should fail when given NULL inventory pointer expect_assert_failure(inventoryAdd(NULL, ITEM_ID_POTION, 3)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventoryAdd(&inventory, ITEM_ID_POTION, 3)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventoryAdd(&inventory, ITEM_ID_POTION, 3)); inventory.storageSize = 5; // Should fail when given ITEM_ID_NULL expect_assert_failure(inventoryAdd(&inventory, ITEM_ID_NULL, 3)); } static void test_inventoryRemove(void **state) { (void)state; inventorystack_t storage[5]; inventory_t inventory; inventoryInit(&inventory, storage, 5); // Add item and then remove it inventorySet(&inventory, ITEM_ID_POTION, 5); inventoryRemove(&inventory, ITEM_ID_POTION); assert_int_equal(inventory.storage[0].item, ITEM_ID_NULL); // Removing non-existing item should do nothing inventoryRemove(&inventory, ITEM_ID_POTION); assert_int_equal(inventory.storage[0].item, ITEM_ID_NULL); // Should fail when given NULL inventory pointer expect_assert_failure(inventoryRemove(NULL, ITEM_ID_POTION)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventoryRemove(&inventory, ITEM_ID_POTION)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventoryRemove(&inventory, ITEM_ID_POTION)); inventory.storageSize = 5; // Should fail when given ITEM_ID_NULL expect_assert_failure(inventoryRemove(&inventory, ITEM_ID_NULL)); } static void test_inventoryGetCount(void **state) { (void)state; inventorystack_t storage[5]; inventory_t inventory; inventoryInit(&inventory, storage, 5); // Initially should be zero assert_int_equal(inventoryGetCount(&inventory, ITEM_ID_POTION), 0); // Add item and check count inventorySet(&inventory, ITEM_ID_POTION, 4); assert_int_equal(inventoryGetCount(&inventory, ITEM_ID_POTION), 4); // Update item quantity and check count inventorySet(&inventory, ITEM_ID_POTION, 2); assert_int_equal(inventoryGetCount(&inventory, ITEM_ID_POTION), 2); // Remove item and check count inventorySet(&inventory, ITEM_ID_POTION, 0); assert_int_equal(inventoryGetCount(&inventory, ITEM_ID_POTION), 0); // Should fail when given NULL inventory pointer expect_assert_failure(inventoryGetCount(NULL, ITEM_ID_POTION)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventoryGetCount(&inventory, ITEM_ID_POTION)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventoryGetCount(&inventory, ITEM_ID_POTION)); inventory.storageSize = 5; // Should fail when given ITEM_ID_NULL expect_assert_failure(inventoryGetCount(&inventory, ITEM_ID_NULL)); } static void test_inventoryIsFull(void **state) { (void)state; inventorystack_t storage[2]; inventory_t inventory; inventoryInit(&inventory, storage, 2); // Initially should not be full assert_false(inventoryIsFull(&inventory)); // Fill inventory inventorySet(&inventory, ITEM_ID_POTION, 1); inventorySet(&inventory, ITEM_ID_POTATO, 1); assert_true(inventoryIsFull(&inventory)); // Remove one item inventoryRemove(&inventory, ITEM_ID_POTION); assert_false(inventoryIsFull(&inventory)); // Add one item back inventorySet(&inventory, ITEM_ID_POTION, 1); assert_true(inventoryIsFull(&inventory)); // Should fail when given NULL inventory pointer expect_assert_failure(inventoryIsFull(NULL)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventoryIsFull(&inventory)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventoryIsFull(&inventory)); inventory.storageSize = 2; } static void test_inventoryItemFull(void **state) { (void)state; inventorystack_t storage[2]; inventory_t inventory; inventoryInit(&inventory, storage, 2); // Initially should not be full assert_false(inventoryItemFull(&inventory, ITEM_ID_POTION)); // Add some potions, but not too many. inventorySet(&inventory, ITEM_ID_POTION, 100); assert_false(inventoryItemFull(&inventory, ITEM_ID_POTION)); // Fill with potions inventorySet(&inventory, ITEM_ID_POTION, ITEM_STACK_QUANTITY_MAX); assert_true(inventoryItemFull(&inventory, ITEM_ID_POTION)); // Add potatoes, should not affect potions inventorySet(&inventory, ITEM_ID_POTATO, 50); assert_true(inventoryItemFull(&inventory, ITEM_ID_POTION)); assert_false(inventoryItemFull(&inventory, ITEM_ID_POTATO)); // Remove some potions inventorySet(&inventory, ITEM_ID_POTION, 200); assert_false(inventoryItemFull(&inventory, ITEM_ID_POTION)); // Fill with potatoes inventorySet(&inventory, ITEM_ID_POTATO, ITEM_STACK_QUANTITY_MAX); assert_false(inventoryItemFull(&inventory, ITEM_ID_POTION)); assert_true(inventoryItemFull(&inventory, ITEM_ID_POTATO)); // Should fail when given NULL inventory pointer expect_assert_failure(inventoryItemFull(NULL, ITEM_ID_POTION)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventoryItemFull(&inventory, ITEM_ID_POTION)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventoryItemFull(&inventory, ITEM_ID_POTION)); inventory.storageSize = 2; } static void test_inventorySort(void **state) { (void)state; inventorystack_t storage[5]; inventory_t inventory; inventoryInit(&inventory, storage, 5); // Add items out of order inventorySet(&inventory, ITEM_ID_POTATO, 3); inventorySet(&inventory, ITEM_ID_APPLE, 5); inventorySet(&inventory, ITEM_ID_POTION, 2); // Sort by ID inventorySort(&inventory, INVENTORY_SORT_BY_ID, false); // Check order assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); assert_int_equal(inventory.storage[2].item, ITEM_ID_APPLE); // Sort by ID reverse inventorySort(&inventory, INVENTORY_SORT_BY_ID, true); assert_int_equal(inventory.storage[0].item, ITEM_ID_APPLE); assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); assert_int_equal(inventory.storage[2].item, ITEM_ID_POTION); // Sort by type inventorySort(&inventory, INVENTORY_SORT_BY_ID, false); assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); assert_int_equal(inventory.storage[2].item, ITEM_ID_APPLE); // Sort by type reverse inventorySort(&inventory, INVENTORY_SORT_BY_ID, true); assert_int_equal(inventory.storage[0].item, ITEM_ID_APPLE); assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); assert_int_equal(inventory.storage[2].item, ITEM_ID_POTION); // Should fail when given NULL inventory pointer expect_assert_failure(inventorySort(NULL, INVENTORY_SORT_BY_ID, false)); // Should fail when given NULL storage pointer inventory.storage = NULL; expect_assert_failure(inventorySort(&inventory, INVENTORY_SORT_BY_ID, false)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; expect_assert_failure(inventorySort(&inventory, INVENTORY_SORT_BY_ID, false)); inventory.storageSize = 5; } int main(int argc, char** argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_inventoryInit), cmocka_unit_test(test_inventoryItemExists), cmocka_unit_test(test_inventorySet), cmocka_unit_test(test_inventoryAdd), cmocka_unit_test(test_inventoryRemove), cmocka_unit_test(test_inventoryGetCount), cmocka_unit_test(test_inventoryIsFull), cmocka_unit_test(test_inventoryItemFull), cmocka_unit_test(test_inventorySort), }; return cmocka_run_group_tests(tests, NULL, NULL); }