summaryrefslogtreecommitdiffstats
path: root/tests/BlockTypeRegistry
diff options
context:
space:
mode:
Diffstat (limited to 'tests/BlockTypeRegistry')
-rw-r--r--tests/BlockTypeRegistry/BlockTypePaletteTest.cpp122
-rw-r--r--tests/BlockTypeRegistry/CMakeLists.txt31
-rw-r--r--tests/BlockTypeRegistry/PalettedBlockAreaTest.cpp434
3 files changed, 586 insertions, 1 deletions
diff --git a/tests/BlockTypeRegistry/BlockTypePaletteTest.cpp b/tests/BlockTypeRegistry/BlockTypePaletteTest.cpp
new file mode 100644
index 000000000..ef79d8927
--- /dev/null
+++ b/tests/BlockTypeRegistry/BlockTypePaletteTest.cpp
@@ -0,0 +1,122 @@
+#include "Globals.h"
+#include "../TestHelpers.h"
+#include "BlockTypePalette.h"
+
+
+
+
+
+/** Tests the BlockTypePalette's basic APIs - creation, addition, querying. */
+static void testBasic()
+{
+ LOGD("Testing the basic BlockTypePalette's APIs...");
+
+ // Check inserting different block type names:
+ BlockTypePalette pal;
+ TEST_EQUAL(pal.index("testblock", BlockState()), 0); // Insert the first entry
+ TEST_EQUAL(pal.index("testblock", BlockState()), 0); // Check that it's not inserted again
+ TEST_EQUAL(pal.maybeIndex("testblock", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
+ TEST_EQUAL(pal.maybeIndex("nonexistent", BlockState()).second, false);
+
+ TEST_EQUAL(pal.index("another", BlockState()), 1); // Insert the second entry
+ TEST_EQUAL(pal.index("another", BlockState()), 1); // Check that it's not inserted twice
+ TEST_EQUAL(pal.maybeIndex("another", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
+ TEST_EQUAL(pal.maybeIndex("testblock", BlockState()), (std::make_pair<UInt32, bool>(0, true))); // The first one stayed
+
+ // Check same block type name, different BlockState:
+ BlockState bs1;
+ BlockState bs2("key1", "value1");
+ BlockState bs3({{"key1", "value1"}, {"key2", "value2"}});
+ BlockState bs2Copy(bs2);
+ TEST_EQUAL(pal.index("multistate", bs1), 2);
+ TEST_EQUAL(pal.index("multistate", bs2), 3);
+ TEST_EQUAL(pal.index("multistate", bs3), 4);
+ TEST_EQUAL(pal.index("multistate", bs2Copy), 3); // Different BlockState instance, but same content
+ TEST_EQUAL(pal.count(), 5);
+
+ // Check the entry() API:
+ TEST_EQUAL(pal.entry(0), (std::make_pair<AString, BlockState>("testblock", BlockState())));
+ TEST_EQUAL(pal.entry(1), (std::make_pair<AString, BlockState>("another", BlockState())));
+ TEST_EQUAL(pal.entry(2), (std::make_pair<AString, BlockState>("multistate", BlockState(bs1)))); // make_pair requires a copy of the state
+ TEST_EQUAL(pal.entry(3), (std::make_pair<AString, BlockState>("multistate", BlockState(bs2))));
+ TEST_EQUAL(pal.entry(4), (std::make_pair<AString, BlockState>("multistate", BlockState(bs3))));
+}
+
+
+
+
+
+/** Tests creating the transform map between two palettes. */
+static void testTransform()
+{
+ LOGD("Testing the createTransformMap API...");
+
+ // Create two palettes with some overlap:
+ BlockTypePalette pal1, pal2;
+ pal1.index("block1", BlockState());
+ pal1.index("block2", BlockState());
+ pal1.index("block3", BlockState());
+ pal1.index("block4", BlockState());
+ pal1.index("block5", BlockState("key1", "value1"));
+ pal2.index("block0", BlockState());
+ pal2.index("block2", BlockState()); // overlap
+ pal2.index("block3", BlockState()); // overlap
+ pal2.index("block4", BlockState("key1", "value1"));
+ pal2.index("block5", BlockState("key1", "value1")); // overlap
+ pal2.index("block6", BlockState("key1", "value1"));
+
+ // Check the transform map:
+ auto trans = pal1.createTransformMap(pal2);
+ TEST_EQUAL(pal1.maybeIndex("block1", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
+ TEST_EQUAL(pal1.maybeIndex("block2", BlockState()), (std::make_pair<UInt32, bool>(1, true)));
+ TEST_EQUAL(pal1.maybeIndex("block3", BlockState()), (std::make_pair<UInt32, bool>(2, true)));
+ TEST_EQUAL(pal1.maybeIndex("block4", BlockState()), (std::make_pair<UInt32, bool>(3, true)));
+ TEST_EQUAL(pal1.maybeIndex("block5", BlockState("key1", "value1")), (std::make_pair<UInt32, bool>(4, true)));
+ TEST_EQUAL(pal1.maybeIndex("block0", BlockState()), (std::make_pair<UInt32, bool>(5, true)));
+ TEST_EQUAL(pal1.maybeIndex("block4", BlockState("key1", "value1")), (std::make_pair<UInt32, bool>(6, true)));
+ TEST_EQUAL(pal1.maybeIndex("block6", BlockState("key1", "value1")), (std::make_pair<UInt32, bool>(7, true)));
+ TEST_EQUAL(trans.size(), 6);
+ TEST_EQUAL(trans[0], 5);
+ TEST_EQUAL(trans[1], 1);
+ TEST_EQUAL(trans[2], 2);
+ TEST_EQUAL(trans[3], 6);
+ TEST_EQUAL(trans[4], 4);
+ TEST_EQUAL(trans[5], 7);
+}
+
+
+
+
+
+int main()
+{
+ LOGD("BlockTypePaletteTest started");
+
+ try
+ {
+ testBasic();
+ testTransform();
+ }
+ catch (const TestException & exc)
+ {
+ LOGERROR("BlockTypePaletteTest has failed, an exception was thrown: %s", exc.mMessage.c_str());
+ return 1;
+ }
+ catch (const std::exception & exc)
+ {
+ LOGERROR("BlockTypePaletteTest has failed, an exception was thrown: %s", exc.what());
+ return 1;
+ }
+ catch (...)
+ {
+ LOGERROR("BlockTypePaletteTest has failed, an unhandled exception was thrown.");
+ return 1;
+ }
+
+ LOGD("BlockTypePaletteTest finished");
+ return 0;
+}
+
+
+
+
diff --git a/tests/BlockTypeRegistry/CMakeLists.txt b/tests/BlockTypeRegistry/CMakeLists.txt
index c95c503dd..379158d5c 100644
--- a/tests/BlockTypeRegistry/CMakeLists.txt
+++ b/tests/BlockTypeRegistry/CMakeLists.txt
@@ -21,6 +21,16 @@ add_executable(BlockStateTest
)
target_link_libraries(BlockStateTest fmt::fmt)
+add_executable(BlockTypePaletteTest
+ BlockTypePaletteTest.cpp
+ ../TestHelpers.h
+ ${CMAKE_SOURCE_DIR}/src/BlockState.cpp
+ ${CMAKE_SOURCE_DIR}/src/BlockTypePalette.cpp
+ ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
+ ${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp
+)
+target_link_libraries(BlockTypePaletteTest fmt::fmt)
+
# BlockTypeRegistryTest: Verify that the BlockTypeRegistry class works as intended:
add_executable(BlockTypeRegistryTest
BlockTypeRegistryTest.cpp
@@ -31,6 +41,21 @@ add_executable(BlockTypeRegistryTest
)
target_link_libraries(BlockTypeRegistryTest fmt::fmt)
+# PalettedBlockAreaTest: Verify that the PalettedBlockArea class works as intended:
+add_executable(PalettedBlockAreaTest
+ PalettedBlockAreaTest.cpp
+ ../TestHelpers.h
+ ${CMAKE_SOURCE_DIR}/src/BlockState.cpp
+ ${CMAKE_SOURCE_DIR}/src/BlockTypeRegistry.cpp
+ ${CMAKE_SOURCE_DIR}/src/BlockTypePalette.cpp
+ ${CMAKE_SOURCE_DIR}/src/Cuboid.cpp
+ ${CMAKE_SOURCE_DIR}/src/PalettedBlockArea.cpp
+ ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
+ ${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp
+)
+target_link_libraries(PalettedBlockAreaTest fmt::fmt)
+
+
@@ -38,8 +63,10 @@ target_link_libraries(BlockTypeRegistryTest fmt::fmt)
# Define individual tests:
-add_test(NAME BlockStateTest COMMAND BlockStateTest)
+add_test(NAME BlockStateTest COMMAND BlockStateTest)
add_test(NAME BlockTypeRegistryTest COMMAND BlockTypeRegistryTest)
+add_test(NAME BlockTypePaletteTest COMMAND BlockTypePaletteTest)
+add_test(NAME PalettedBlockAreaTest COMMAND PalettedBlockAreaTest)
@@ -49,5 +76,7 @@ add_test(NAME BlockTypeRegistryTest COMMAND BlockTypeRegistryTest)
set_target_properties(
BlockStateTest
BlockTypeRegistryTest
+ BlockTypePaletteTest
+ PalettedBlockAreaTest
PROPERTIES FOLDER Tests/BlockTypeRegistry
)
diff --git a/tests/BlockTypeRegistry/PalettedBlockAreaTest.cpp b/tests/BlockTypeRegistry/PalettedBlockAreaTest.cpp
new file mode 100644
index 000000000..0fc7c9452
--- /dev/null
+++ b/tests/BlockTypeRegistry/PalettedBlockAreaTest.cpp
@@ -0,0 +1,434 @@
+#include "Globals.h"
+#include <tuple>
+#include "PalettedBlockArea.h"
+#include "../TestHelpers.h"
+
+
+
+
+
+/** Tests creating a PBA. */
+static void testCreation()
+{
+ LOG("Testing PBA creation...");
+
+ // Check failures:
+ TEST_ASSERTS(PalettedBlockArea::createFilled({-2, 3, 4}, "block", BlockState())); // Negative coords
+ TEST_THROWS(PalettedBlockArea::createFilled({4096, 4096, 4096}, "block", BlockState()), std::runtime_error); // Size too large for UInt32
+
+ // Check that a created area really is filled:
+ auto pba = PalettedBlockArea::createFilled({2, 3, 4}, "block", BlockState());
+ TEST_EQUAL(pba.size(), Vector3i(2, 3, 4));
+ TEST_EQUAL(pba.whole(), cCuboid({0, 0, 0}, {2, 3, 4}));
+ TEST_EQUAL(pba.palette().count(), 1);
+ TEST_EQUAL(pba.maybePaletteIndex("block", BlockState()), (std::make_pair<UInt32, bool>(0, true)));
+ TEST_EQUAL(pba.maybePaletteIndex("nonexistentBlock", BlockState()).second, false);
+ for (int x = 0; x < 2; ++x)
+ {
+ for (int y = 0; y < 3; ++y)
+ {
+ for (int z = 0; z < 4; ++z)
+ {
+ TEST_EQUAL(pba.blockPaletteIndex({x, y, z}), 0);
+ }
+ }
+ }
+}
+
+
+
+
+
+/** Tests setting and getting blocks. */
+static void testSetting()
+{
+ LOG("Testing PBA's set and get APIs...");
+ auto pba = PalettedBlockArea::createFilled({2, 3, 4}, "block1", BlockState());
+ pba.setBlock({0, 0, 0}, "block2", BlockState());
+ pba.setBlock({1, 0, 0}, "block2", BlockState("key1", "value1"));
+ TEST_ASSERTS(pba.setBlock({2, 0, 0}, "block2", BlockState())); // Invalid coords
+ pba.setBlock({0, 1, 0}, 1);
+ TEST_ASSERTS(pba.setBlock({1, 1, 0}, 100)); // Invalid palette index
+
+ // Check that the blocks have been set:
+ TEST_EQUAL(pba.palette().count(), 3);
+ TEST_EQUAL(pba.block({0, 0, 0}), (std::make_pair<AString, BlockState>("block2", BlockState())));
+ TEST_EQUAL(pba.block({1, 0, 0}), (std::make_pair<AString, BlockState>("block2", BlockState("key1", "value1"))));
+ TEST_ASSERTS(pba.block({2, 0, 0})); // Invalid coords
+ TEST_EQUAL(pba.block({0, 1, 0}), (std::make_pair<AString, BlockState>("block2", BlockState())));
+ TEST_EQUAL(pba.block({1, 1, 0}), (std::make_pair<AString, BlockState>("block1", BlockState()))); // Didn't overwrite with invalid palette index
+ TEST_EQUAL(pba.blockPaletteIndex({0, 0, 0}), 1);
+ TEST_EQUAL(pba.blockPaletteIndex({1, 0, 0}), 2);
+ TEST_ASSERTS(pba.blockPaletteIndex({2, 0, 0})); // Invalid coords
+ TEST_EQUAL(pba.blockPaletteIndex({0, 1, 0}), 1);
+ TEST_EQUAL(pba.blockPaletteIndex({1, 1, 0}), 0); // Didn't overwrite with invalid palette index
+
+ // Test filling:
+ LOG("Testing PBA's fill API...");
+ pba.fill("block3", BlockState("key1", "value1"));
+ TEST_EQUAL(pba.palette().count(), 1);
+ TEST_EQUAL(pba.paletteEntry(0), (std::make_pair<AString, BlockState>("block3", BlockState("key1", "value1"))));
+ for (int x = 0; x < 2; ++x)
+ {
+ for (int y = 0; y < 2; ++y)
+ {
+ for (int z = 0; z < 2; ++z)
+ {
+ TEST_EQUAL(pba.blockPaletteIndex({x, y, z}), 0);
+ }
+ }
+ }
+}
+
+
+
+
+
+/** Creates pbaA and pbaB that are pre-filled with known content.
+The PBAs are then used for paste()-testing.
+Used to be a function, but clang-3.5 didn't like it ("error: debug information for auto is not yet supported"). */
+#define PREPARE_PASTING_PBAS \
+ auto pbaA = PalettedBlockArea::createFilled({5, 5, 5}, "blockA", BlockState()); \
+ for (int x = 0; x < 5; ++x) \
+ { \
+ for (int y = 0; y < 5; ++y) \
+ { \
+ for (int z = 0; z < 5; ++z) \
+ { \
+ pbaA.setBlock({x, y, z}, Printf("A-%d-%d-%d", x, y, z), BlockState()); \
+ } \
+ } \
+ } \
+ auto pbaB = PalettedBlockArea::createFilled({6, 6, 6}, "blockB", BlockState()); \
+ for (int x = 0; x < 6; ++x) \
+ { \
+ for (int y = 0; y < 6; ++y) \
+ { \
+ for (int z = 0; z < 6; ++z) \
+ { \
+ pbaB.setBlock({x, y, z}, Printf("B-%d-%d-%d", x, y, z), BlockState()); \
+ } \
+ } \
+ } \
+ do { } while (false)
+
+
+
+
+
+// This is the data for the original PBA, before the paste() operations.
+// It is included here so that when adding new paste() tests we can simply copy it
+// into the test function and modify for the test.
+/*
+static const AString expected[5][5][5] =
+{
+ {
+ {"A-0-0-0", "A-1-0-0", "A-2-0-0", "A-3-0-0", "A-4-0-0"},
+ {"A-0-1-0", "A-1-1-0", "A-2-1-0", "A-3-1-0", "A-4-1-0"},
+ {"A-0-2-0", "A-1-2-0", "A-2-2-0", "A-3-2-0", "A-4-2-0"},
+ {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"},
+ {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"},
+ },
+ {
+ {"A-0-0-1", "A-1-0-1", "A-2-0-1", "A-3-0-1", "A-4-0-1"},
+ {"A-0-1-1", "A-1-1-1", "A-2-1-1", "A-3-1-1", "A-4-1-1"},
+ {"A-0-2-1", "A-1-2-1", "A-2-2-1", "A-3-2-1", "A-4-2-1"},
+ {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"},
+ {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"},
+ },
+ {
+ {"A-0-0-2", "A-1-0-2", "A-2-0-2", "A-3-0-2", "A-4-0-2"},
+ {"A-0-1-2", "A-1-1-2", "A-2-1-2", "A-3-1-2", "A-4-1-2"},
+ {"A-0-2-2", "A-1-2-2", "A-2-2-2", "A-3-2-2", "A-4-2-2"},
+ {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"},
+ {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"},
+ },
+ {
+ {"A-0-0-3", "A-1-0-3", "A-2-0-3", "A-3-0-3", "A-4-0-3"},
+ {"A-0-1-3", "A-1-1-3", "A-2-1-3", "A-3-1-3", "A-4-1-3"},
+ {"A-0-2-3", "A-1-2-3", "A-2-2-3", "A-3-2-3", "A-4-2-3"},
+ {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"},
+ {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"},
+ },
+ {
+ {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"},
+ {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"},
+ {"A-0-2-4", "A-1-2-4", "A-2-2-4", "A-3-2-4", "A-4-2-4"},
+ {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"},
+ {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"},
+ },
+};
+*/
+
+
+
+
+
+/** Tests the "paste()" operation with the pasted region being completely inside the destination PBA. */
+static void testPastingCompletelyInside()
+{
+ LOG("Testing the paste() API with destination completely inside (with cropping)...");
+ PREPARE_PASTING_PBAS;
+ pbaA.paste(pbaB, cCuboid({1, 1, 1}, {4, 4, 4}), {1, 0, 0}); // Paste the 3x3x3 inside area from pbaB to pbaA, starting at {1, 0, 0}
+ static const AString expected[5][5][5] =
+ {
+ {
+ {"A-0-0-0", "B-1-1-1", "B-2-1-1", "B-3-1-1", "A-4-0-0"},
+ {"A-0-1-0", "B-1-2-1", "B-2-2-1", "B-3-2-1", "A-4-1-0"},
+ {"A-0-2-0", "B-1-3-1", "B-2-3-1", "B-3-3-1", "A-4-2-0"},
+ {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"},
+ {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"},
+ },
+ {
+ {"A-0-0-1", "B-1-1-2", "B-2-1-2", "B-3-1-2", "A-4-0-1"},
+ {"A-0-1-1", "B-1-2-2", "B-2-2-2", "B-3-2-2", "A-4-1-1"},
+ {"A-0-2-1", "B-1-3-2", "B-2-3-2", "B-3-3-2", "A-4-2-1"},
+ {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"},
+ {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"},
+ },
+ {
+ {"A-0-0-2", "B-1-1-3", "B-2-1-3", "B-3-1-3", "A-4-0-2"},
+ {"A-0-1-2", "B-1-2-3", "B-2-2-3", "B-3-2-3", "A-4-1-2"},
+ {"A-0-2-2", "B-1-3-3", "B-2-3-3", "B-3-3-3", "A-4-2-2"},
+ {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"},
+ {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"},
+ },
+ {
+ {"A-0-0-3", "A-1-0-3", "A-2-0-3", "A-3-0-3", "A-4-0-3"},
+ {"A-0-1-3", "A-1-1-3", "A-2-1-3", "A-3-1-3", "A-4-1-3"},
+ {"A-0-2-3", "A-1-2-3", "A-2-2-3", "A-3-2-3", "A-4-2-3"},
+ {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"},
+ {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"},
+ },
+ {
+ {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"},
+ {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"},
+ {"A-0-2-4", "A-1-2-4", "A-2-2-4", "A-3-2-4", "A-4-2-4"},
+ {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"},
+ {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"},
+ },
+ };
+ for (int x = 0; x < 5; ++x)
+ {
+ for (int y = 0; y < 5; ++y)
+ {
+ for (int z = 0; z < 5; ++z)
+ {
+ auto got = pbaA.block({x, y, z}).first;
+ TEST_EQUAL_MSG(
+ pbaA.block({x, y, z}).first,
+ expected[z][y][x],
+ Printf("{%d, %d, %d}, exp %s, got %s", x, y, z, expected[z][y][x].c_str(), pbaA.block({x, y, z}).first.c_str()).c_str()
+ );
+ }
+ }
+ }
+}
+
+
+
+
+
+/** Tests the "paste()" operation with the pasted region overflowing the destination PBA into the positive coords. */
+static void testPastingPositiveOverflow()
+{
+ LOG("Testing the paste() API with positive overflow...");
+ PREPARE_PASTING_PBAS;
+ pbaA.paste(pbaB, Vector3i{3, 2, 1}); // Paste the entire pbaB to pbaA, starting at {3, 2, 1}
+ static const AString expected[5][5][5] =
+ {
+ {
+ {"A-0-0-0", "A-1-0-0", "A-2-0-0", "A-3-0-0", "A-4-0-0"},
+ {"A-0-1-0", "A-1-1-0", "A-2-1-0", "A-3-1-0", "A-4-1-0"},
+ {"A-0-2-0", "A-1-2-0", "A-2-2-0", "A-3-2-0", "A-4-2-0"},
+ {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"},
+ {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"},
+ },
+ {
+ {"A-0-0-1", "A-1-0-1", "A-2-0-1", "A-3-0-1", "A-4-0-1"},
+ {"A-0-1-1", "A-1-1-1", "A-2-1-1", "A-3-1-1", "A-4-1-1"},
+ {"A-0-2-1", "A-1-2-1", "A-2-2-1", "B-0-0-0", "B-1-0-0"},
+ {"A-0-3-1", "A-1-3-1", "A-2-3-1", "B-0-1-0", "B-1-1-0"},
+ {"A-0-4-1", "A-1-4-1", "A-2-4-1", "B-0-2-0", "B-1-2-0"},
+ },
+ {
+ {"A-0-0-2", "A-1-0-2", "A-2-0-2", "A-3-0-2", "A-4-0-2"},
+ {"A-0-1-2", "A-1-1-2", "A-2-1-2", "A-3-1-2", "A-4-1-2"},
+ {"A-0-2-2", "A-1-2-2", "A-2-2-2", "B-0-0-1", "B-1-0-1"},
+ {"A-0-3-2", "A-1-3-2", "A-2-3-2", "B-0-1-1", "B-1-1-1"},
+ {"A-0-4-2", "A-1-4-2", "A-2-4-2", "B-0-2-1", "B-1-2-1"},
+ },
+ {
+ {"A-0-0-3", "A-1-0-3", "A-2-0-3", "A-3-0-3", "A-4-0-3"},
+ {"A-0-1-3", "A-1-1-3", "A-2-1-3", "A-3-1-3", "A-4-1-3"},
+ {"A-0-2-3", "A-1-2-3", "A-2-2-3", "B-0-0-2", "B-1-0-2"},
+ {"A-0-3-3", "A-1-3-3", "A-2-3-3", "B-0-1-2", "B-1-1-2"},
+ {"A-0-4-3", "A-1-4-3", "A-2-4-3", "B-0-2-2", "B-1-2-2"},
+ },
+ {
+ {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"},
+ {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"},
+ {"A-0-2-4", "A-1-2-4", "A-2-2-4", "B-0-0-3", "B-1-0-3"},
+ {"A-0-3-4", "A-1-3-4", "A-2-3-4", "B-0-1-3", "B-1-1-3"},
+ {"A-0-4-4", "A-1-4-4", "A-2-4-4", "B-0-2-3", "B-1-2-3"},
+ },
+ };
+ for (int x = 0; x < 5; ++x)
+ {
+ for (int y = 0; y < 5; ++y)
+ {
+ for (int z = 0; z < 5; ++z)
+ {
+ auto got = pbaA.block({x, y, z}).first;
+ TEST_EQUAL_MSG(
+ pbaA.block({x, y, z}).first,
+ expected[z][y][x],
+ Printf("{%d, %d, %d}, exp %s, got %s", x, y, z, expected[z][y][x].c_str(), pbaA.block({x, y, z}).first.c_str()).c_str()
+ );
+ }
+ }
+ }
+}
+
+
+
+
+
+/** Tests the "paste()" operation with the pasted region overflowing the destination PBA into the negative coords. */
+static void testPastingNegativeOverflow()
+{
+ LOG("Testing the paste() API with negative overflow...");
+ PREPARE_PASTING_PBAS;
+ pbaA.paste(pbaB, Vector3i{-4, -3, -2}); // Paste the entire pbaB to pbaA, starting at {-4, -3, -2}
+ static const AString expected[5][5][5] =
+ {
+ {
+ {"B-4-3-2", "B-5-3-2", "A-2-0-0", "A-3-0-0", "A-4-0-0"},
+ {"B-4-4-2", "B-5-4-2", "A-2-1-0", "A-3-1-0", "A-4-1-0"},
+ {"B-4-5-2", "B-5-5-2", "A-2-2-0", "A-3-2-0", "A-4-2-0"},
+ {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"},
+ {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"},
+ },
+ {
+ {"B-4-3-3", "B-5-3-3", "A-2-0-1", "A-3-0-1", "A-4-0-1"},
+ {"B-4-4-3", "B-5-4-3", "A-2-1-1", "A-3-1-1", "A-4-1-1"},
+ {"B-4-5-3", "B-5-5-3", "A-2-2-1", "A-3-2-1", "A-4-2-1"},
+ {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"},
+ {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"},
+ },
+ {
+ {"B-4-3-4", "B-5-3-4", "A-2-0-2", "A-3-0-2", "A-4-0-2"},
+ {"B-4-4-4", "B-5-4-4", "A-2-1-2", "A-3-1-2", "A-4-1-2"},
+ {"B-4-5-4", "B-5-5-4", "A-2-2-2", "A-3-2-2", "A-4-2-2"},
+ {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"},
+ {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"},
+ },
+ {
+ {"B-4-3-5", "B-5-3-5", "A-2-0-3", "A-3-0-3", "A-4-0-3"},
+ {"B-4-4-5", "B-5-4-5", "A-2-1-3", "A-3-1-3", "A-4-1-3"},
+ {"B-4-5-5", "B-5-5-5", "A-2-2-3", "A-3-2-3", "A-4-2-3"},
+ {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"},
+ {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"},
+ },
+ {
+ {"A-0-0-4", "A-1-0-4", "A-2-0-4", "A-3-0-4", "A-4-0-4"},
+ {"A-0-1-4", "A-1-1-4", "A-2-1-4", "A-3-1-4", "A-4-1-4"},
+ {"A-0-2-4", "A-1-2-4", "A-2-2-4", "A-3-2-4", "A-4-2-4"},
+ {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"},
+ {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"},
+ },
+ };
+ for (int x = 0; x < 5; ++x)
+ {
+ for (int y = 0; y < 5; ++y)
+ {
+ for (int z = 0; z < 5; ++z)
+ {
+ auto got = pbaA.block({x, y, z}).first;
+ TEST_EQUAL_MSG(
+ pbaA.block({x, y, z}).first,
+ expected[z][y][x],
+ Printf("{%d, %d, %d}, exp %s, got %s", x, y, z, expected[z][y][x].c_str(), pbaA.block({x, y, z}).first.c_str()).c_str()
+ );
+ }
+ }
+ }
+}
+
+
+
+
+
+/** Tests the "paste()" operation with the pasted region overflowing the destination PBA into mixed positive and negative coords. */
+static void testPastingMixedOverflow()
+{
+ LOG("Testing the paste() API with mixed positive and negative overflow...");
+ PREPARE_PASTING_PBAS;
+ pbaA.paste(pbaB, Vector3i{-4, -3, 2}); // Paste the entire pbaB to pbaA, starting at {-4, -3, 2}
+ static const AString expected[5][5][5] =
+ {
+ {
+ {"A-0-0-0", "A-1-0-0", "A-2-0-0", "A-3-0-0", "A-4-0-0"},
+ {"A-0-1-0", "A-1-1-0", "A-2-1-0", "A-3-1-0", "A-4-1-0"},
+ {"A-0-2-0", "A-1-2-0", "A-2-2-0", "A-3-2-0", "A-4-2-0"},
+ {"A-0-3-0", "A-1-3-0", "A-2-3-0", "A-3-3-0", "A-4-3-0"},
+ {"A-0-4-0", "A-1-4-0", "A-2-4-0", "A-3-4-0", "A-4-4-0"},
+ },
+ {
+ {"A-0-0-1", "A-1-0-1", "A-2-0-1", "A-3-0-1", "A-4-0-1"},
+ {"A-0-1-1", "A-1-1-1", "A-2-1-1", "A-3-1-1", "A-4-1-1"},
+ {"A-0-2-1", "A-1-2-1", "A-2-2-1", "A-3-2-1", "A-4-2-1"},
+ {"A-0-3-1", "A-1-3-1", "A-2-3-1", "A-3-3-1", "A-4-3-1"},
+ {"A-0-4-1", "A-1-4-1", "A-2-4-1", "A-3-4-1", "A-4-4-1"},
+ },
+ {
+ {"B-4-3-0", "B-5-3-0", "A-2-0-2", "A-3-0-2", "A-4-0-2"},
+ {"B-4-4-0", "B-5-4-0", "A-2-1-2", "A-3-1-2", "A-4-1-2"},
+ {"B-4-5-0", "B-5-5-0", "A-2-2-2", "A-3-2-2", "A-4-2-2"},
+ {"A-0-3-2", "A-1-3-2", "A-2-3-2", "A-3-3-2", "A-4-3-2"},
+ {"A-0-4-2", "A-1-4-2", "A-2-4-2", "A-3-4-2", "A-4-4-2"},
+ },
+ {
+ {"B-4-3-1", "B-5-3-1", "A-2-0-3", "A-3-0-3", "A-4-0-3"},
+ {"B-4-4-1", "B-5-4-1", "A-2-1-3", "A-3-1-3", "A-4-1-3"},
+ {"B-4-5-1", "B-5-5-1", "A-2-2-3", "A-3-2-3", "A-4-2-3"},
+ {"A-0-3-3", "A-1-3-3", "A-2-3-3", "A-3-3-3", "A-4-3-3"},
+ {"A-0-4-3", "A-1-4-3", "A-2-4-3", "A-3-4-3", "A-4-4-3"},
+ },
+ {
+ {"B-4-3-2", "B-5-3-2", "A-2-0-4", "A-3-0-4", "A-4-0-4"},
+ {"B-4-4-2", "B-5-4-2", "A-2-1-4", "A-3-1-4", "A-4-1-4"},
+ {"B-4-5-2", "B-5-5-2", "A-2-2-4", "A-3-2-4", "A-4-2-4"},
+ {"A-0-3-4", "A-1-3-4", "A-2-3-4", "A-3-3-4", "A-4-3-4"},
+ {"A-0-4-4", "A-1-4-4", "A-2-4-4", "A-3-4-4", "A-4-4-4"},
+ },
+ };
+ for (int x = 0; x < 5; ++x)
+ {
+ for (int y = 0; y < 5; ++y)
+ {
+ for (int z = 0; z < 5; ++z)
+ {
+ auto got = pbaA.block({x, y, z}).first;
+ TEST_EQUAL_MSG(
+ pbaA.block({x, y, z}).first,
+ expected[z][y][x],
+ Printf("{%d, %d, %d}, exp %s, got %s", x, y, z, expected[z][y][x].c_str(), pbaA.block({x, y, z}).first.c_str()).c_str()
+ );
+ }
+ }
+ }
+}
+
+
+
+
+
+IMPLEMENT_TEST_MAIN("PalettedBlockArea",
+ testCreation();
+ testSetting();
+ testPastingCompletelyInside();
+ testPastingPositiveOverflow();
+ testPastingNegativeOverflow();
+ testPastingMixedOverflow();
+)