Skip to content

Commit

Permalink
Add some simple unittests for shapeless recipes
Browse files Browse the repository at this point in the history
Note: devtest also has craft unittests (see devtest/mods/unittests/crafting.lua),
      but those aren't run at load-time.
  • Loading branch information
Desour committed Apr 14, 2023
1 parent ae7271b commit 50e91b8
Show file tree
Hide file tree
Showing 2 changed files with 276 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/unittest/CMakeLists.txt
Expand Up @@ -8,6 +8,7 @@ set (UNITTEST_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/test_collision.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_compression.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_connection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_craft.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_filepath.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_inventory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_irrptr.cpp
Expand Down
275 changes: 275 additions & 0 deletions src/unittest/test_craft.cpp
@@ -0,0 +1,275 @@
/*
Minetest
Copyright (C) 2023 DS
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "test.h"

#include "craftdef.h"

class TestCraft : public TestBase
{
public:
TestCraft() { TestManager::registerTestModule(this); }
const char *getName() { return "TestCraft"; }

void runTests(IGameDef *gamedef);

static std::string getDumpedCraftResult(CraftInput input, IGameDef *gamedef);
static void registerItemWithGroups(const std::string &itemname,
const std::vector<std::string> &groups, IGameDef *gamedef);

void testShapeless(IGameDef *gamedef);
};

static TestCraft g_test_instance;

void TestCraft::runTests(IGameDef *gamedef)
{
TEST(testShapeless, gamedef);
}

std::string TestCraft::getDumpedCraftResult(CraftInput input, IGameDef *gamedef)
{
// (input is passed by value, because getCraftResult needs a non-const ref
// for decrementing input)

IWritableCraftDefManager *cdef = (IWritableCraftDefManager *)gamedef->getCraftDefManager();

CraftOutput output{};
std::vector<ItemStack> output_replacements;

cdef->getCraftResult(input, output, output_replacements, false, gamedef);

return output.dump();
}

void TestCraft::registerItemWithGroups(const std::string &itemname,
const std::vector<std::string> &groups, IGameDef *gamedef)
{
IWritableItemDefManager *idef = (IWritableItemDefManager *)gamedef->getItemDefManager();

if (idef->isKnown(itemname)) {
// already registered. check that the groups match
const ItemDefinition &itemdef = idef->get(itemname);

SANITY_CHECK(itemdef.groups.size() == groups.size());
for (const auto &g : groups) {
auto it = itemdef.groups.find(g);
SANITY_CHECK(it != itemdef.groups.end());
SANITY_CHECK(it->second == 1);
}

} else {
// register it
ItemDefinition itemdef{};

itemdef.type = ITEM_CRAFT;
itemdef.name = itemname;
itemdef.description = itemname;
for (const auto &g : groups)
itemdef.groups[g] = 1;
idef->registerItem(itemdef);
}
}

void TestCraft::testShapeless(IGameDef *gamedef)
{
IWritableItemDefManager *idef = (IWritableItemDefManager *)gamedef->getItemDefManager();
IWritableCraftDefManager *cdef = (IWritableCraftDefManager *)gamedef->getCraftDefManager();

auto to_item = [&](const std::string &itemstring) -> ItemStack {
ItemStack item;
item.deSerialize(itemstring, idef);
return item;
};

cdef->clear();

idef->registerAlias("crafttest:a1", "crafttest:i1");
registerItemWithGroups("crafttest:i1", {}, gamedef);
registerItemWithGroups("crafttest:i2", {}, gamedef);
registerItemWithGroups("crafttest:i3", {}, gamedef);
registerItemWithGroups("crafttest:i4", {}, gamedef);
registerItemWithGroups("crafttest:g1g2", {"crafttest_g1", "crafttest_g2"}, gamedef);

cdef->registerCraft(new CraftDefinitionShapeless(
"crafttest:i1",
{
"crafttest:i1",
"crafttest:a1",
},
CraftReplacements{}
), gamedef);

cdef->registerCraft(new CraftDefinitionShapeless(
"crafttest:i2",
{
"crafttest:i2",
"crafttest:i1",
"crafttest:i2",
"crafttest:i1",
"crafttest:i2",
"crafttest:i1",
"crafttest:i2",
"crafttest:i1",
"crafttest:i2",
"crafttest:i1",
"crafttest:i2",
"crafttest:i1",
},
CraftReplacements{}
), gamedef);

cdef->registerCraft(new CraftDefinitionShapeless(
"crafttest:i3",
{
"crafttest:i2",
"crafttest:i1",
"crafttest:i2",
"group:crafttest_g1",
},
CraftReplacements{}
), gamedef);

cdef->registerCraft(new CraftDefinitionShapeless(
"crafttest:i4",
{
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g2",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
"group:crafttest_g1",
},
CraftReplacements{}
), gamedef);

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 3,
{
to_item("crafttest:i1"),
to_item("crafttest:i1"),
}), gamedef),
"(item=\"crafttest:i1\", time=0)");

cdef->initHashes(gamedef);

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 3,
{
to_item("crafttest:i1"),
to_item("crafttest:i1"),
}), gamedef),
"(item=\"crafttest:i1\", time=0)");

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 3,
{
to_item("crafttest:i1"),
to_item(""),
to_item("crafttest:i1"),
}), gamedef),
"(item=\"crafttest:i1\", time=0)");

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 4,
{
to_item("crafttest:i1"),
to_item("crafttest:i1"),
}), gamedef),
"(item=\"crafttest:i1\", time=0)");

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 3,
{
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
}), gamedef),
"(item=\"crafttest:i2\", time=0)");

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 4,
{
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i1"),
}), gamedef),
"(item=\"crafttest:i2\", time=0)");

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 3,
{
to_item("crafttest:i2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:g1g2"),
}), gamedef),
"(item=\"crafttest:i3\", time=0)");

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 3,
{
to_item("crafttest:g1g2"),
to_item("crafttest:i1"),
to_item("crafttest:i2"),
to_item("crafttest:i2"),
}), gamedef),
"(item=\"crafttest:i3\", time=0)");

UASSERTEQ(std::string, getDumpedCraftResult(CraftInput(CRAFT_METHOD_NORMAL, 3,
{
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
to_item("crafttest:g1g2"),
}), gamedef),
"(item=\"crafttest:i4\", time=0)");
}

0 comments on commit 50e91b8

Please sign in to comment.