test: extend coverage of testSchematic

This commit is contained in:
dualfroz committed 2026-09-12 22:15:01 +02:00
1 parent be77c57de3
commit dcba0c8da0
1 file changed
+179
+179
View File
@@ -315,3 +315,182 @@ VF_TEST(aTruncatedBufferIsRejectedAtEveryCutPoint) {
Schematic::capture(source, Selection::box({0, 0, 0}, {4, 4, 4}), "cut", "f", 1u).encode();
CHECK(bytes.size() > 40u);
Schematic loaded;
for (std::size_t keep : {std::size_t(0), std::size_t(3), std::size_t(11), bytes.size() - 5u,
bytes.size() - 1u}) {
ByteBuffer cut(bytes.begin(), bytes.begin() + static_cast<std::ptrdiff_t>(keep));
SchematicError error = Schematic::decode(cut.data(), cut.size(), loaded);
CHECK(error == SchematicError::Truncated);
}
// A body length claiming more bytes than the buffer holds is truncation too.
ByteBuffer lying = bytes;
writeU32(lying, 8, readU32(lying, 8) + 64u);
CHECK(Schematic::decode(lying.data(), lying.size(), loaded) == SchematicError::Truncated);
}
VF_TEST(aFlippedByteInTheBodyIsCaughtByTheChecksum) {
World source = terrainWorld(5, 5);
ByteBuffer bytes =
Schematic::capture(source, Selection::box({0, 0, 0}, {4, 4, 4}), "bit", "f", 1u).encode();
Schematic loaded;
for (std::size_t offset : {bodyOffset, bodyOffset + 20u, bytes.size() - 6u}) {
ByteBuffer damaged = bytes;
damaged[offset] = static_cast<uint8_t>(damaged[offset] ^ 0x40u);
CHECK(Schematic::decode(damaged.data(), damaged.size(), loaded) ==
SchematicError::BadChecksum);
}
ByteBuffer wrongChecksum = bytes;
writeU32(wrongChecksum, wrongChecksum.size() - 4u, 0xdeadbeefu);
CHECK(Schematic::decode(wrongChecksum.data(), wrongChecksum.size(), loaded) ==
SchematicError::BadChecksum);
}
VF_TEST(dimensionsThatDoNotMatchThePayloadAreRejected) {
World source = terrainWorld(5, 5);
ByteBuffer bytes =
Schematic::capture(source, Selection::box({0, 0, 0}, {4, 4, 4}), "dim", "f", 1u).encode();
Schematic control;
CHECK(Schematic::decode(bytes.data(), bytes.size(), control) == SchematicError::None);
CHECK(control.header().dims == Vec3i(5, 5, 5));
ByteBuffer widened = bytes;
patchBody(widened, 3u, 6u);
Schematic loaded;
CHECK(Schematic::decode(widened.data(), widened.size(), loaded) ==
SchematicError::DimensionMismatch);
ByteBuffer negative = bytes;
negative[bodyOffset] = 0xffu;
refreshChecksum(negative);
CHECK(Schematic::decode(negative.data(), negative.size(), loaded) ==
SchematicError::DimensionMismatch);
}
VF_TEST(aPaletteThatDoesNotDescribeRealBlocksIsRejected) {
World source = terrainWorld(5, 5);
ByteBuffer bytes =
Schematic::capture(source, Selection::box({0, 0, 0}, {4, 4, 4}), "pal", "f", 1u).encode();
Schematic loaded;
ByteBuffer unknownBlock = bytes;
patchBody(unknownBlock, paletteOffsetInBody, 250u);
CHECK(Schematic::decode(unknownBlock.data(), unknownBlock.size(), loaded) ==
SchematicError::BadPalette);
ByteBuffer emptyPalette = bytes;
patchBody(emptyPalette, 25u, 0u);
CHECK(Schematic::decode(emptyPalette.data(), emptyPalette.size(), loaded) ==
SchematicError::BadPalette);
}
VF_TEST(pasteModesDecideWhichExistingBlocksSurvive) {
ClipboardBuffer stamp({3, 1, 3}, {0, 0, 0});
for (int z = 0; z < 3; ++z)
for (int x = 0; x < 3; ++x) stamp.put(x, 0, z, Block::Planks);
Schematic schematic = Schematic::fromBuffer(stamp, "floor", "foksiu", 2u);
World overwrite;
for (int z = 0; z < 3; ++z)
for (int x = 0; x < 3; ++x) overwrite.setBlock(x, 0, z, Block::Stone);
CHECK_EQ(schematic.pasteInto(overwrite, {0, 0, 0}, ClipboardBuffer::PasteMode::Overwrite), 9u);
CHECK(overwrite.blockAt(1, 0, 1) == Block::Planks);
World intoAir;
for (int z = 0; z < 3; ++z)
for (int x = 0; x < 3; ++x) intoAir.setBlock(x, 0, z, Block::Stone);
CHECK_EQ(schematic.pasteInto(intoAir, {0, 0, 0}, ClipboardBuffer::PasteMode::IntoAirOnly), 0u);
CHECK(intoAir.blockAt(1, 0, 1) == Block::Stone);
CHECK_EQ(schematic.pasteInto(intoAir, {0, 1, 0}, ClipboardBuffer::PasteMode::IntoAirOnly), 9u);
CHECK(intoAir.blockAt(1, 1, 1) == Block::Planks);
World replaceOnly;
replaceOnly.setBlock(0, 0, 0, Block::Stone);
replaceOnly.setBlock(2, 0, 2, Block::Stone);
CHECK_EQ(schematic.pasteInto(replaceOnly, {0, 0, 0},
ClipboardBuffer::PasteMode::ReplaceExisting),
2u);
CHECK(replaceOnly.blockAt(0, 0, 0) == Block::Planks);
CHECK(replaceOnly.blockAt(1, 0, 1) == Block::Air);
}
VF_TEST(theAnchorDecidesWhereAPastedSchematicLands) {
ClipboardBuffer stamp({3, 3, 3}, {1, 1, 1});
for (int y = 0; y < 3; ++y)
for (int z = 0; z < 3; ++z)
for (int x = 0; x < 3; ++x) stamp.put(x, y, z, Block::Sandstone);
Schematic schematic = Schematic::fromBuffer(stamp, "cube", "foksiu", 4u);
World world;
schematic.pasteInto(world, {50, 50, 50}, ClipboardBuffer::PasteMode::Overwrite);
CHECK(world.blockAt(50, 50, 50) == Block::Sandstone);
CHECK(world.blockAt(49, 49, 49) == Block::Sandstone);
CHECK(world.blockAt(51, 51, 51) == Block::Sandstone);
CHECK(world.blockAt(52, 50, 50) == Block::Air);
CHECK(world.blockAt(48, 50, 50) == Block::Air);
}
VF_TEST(pastingThroughTheHistoryIsOneUndoableBatch) {
World world = terrainWorld(6, 6);
Selection region = Selection::box({0, 0, 0}, {5, 4, 5});
Schematic saved = Schematic::capture(world, region, "copy", "foksiu", 1u);
EditHistory history(1u << 20);
std::size_t before = 0;
for (int y = 0; y <= 4; ++y)
for (int z = 0; z <= 5; ++z)
for (int x = 0; x <= 5; ++x)
if (!isAir(world.blockAt(x, y, z))) ++before;
std::size_t written = saved.pasteInto(world, history, {20, 0, 20},
ClipboardBuffer::PasteMode::Overwrite, 5u);
CHECK(written > 0u);
CHECK_EQ(history.stats().batchCount, 1u);
CHECK(world.blockAt(20, 0, 20) == world.blockAt(0, 0, 0));
CHECK(history.undo(world));
for (int y = 0; y <= 4; ++y)
for (int z = 0; z <= 5; ++z)
for (int x = 0; x <= 5; ++x) CHECK(isAir(world.blockAt(20 + x, y, 20 + z)));
std::size_t after = 0;
for (int y = 0; y <= 4; ++y)
for (int z = 0; z <= 5; ++z)
for (int x = 0; x <= 5; ++x)
if (!isAir(world.blockAt(x, y, z))) ++after;
CHECK_EQ(after, before);
}
VF_TEST(anEmptySchematicSurvivesTheRoundTrip) {
Schematic nothing = Schematic::fromBuffer(ClipboardBuffer{}, "void", "foksiu", 9u);
CHECK(nothing.header().dims == Vec3i(0, 0, 0));
ByteBuffer bytes = nothing.encode();
Schematic loaded;
CHECK(Schematic::decode(bytes.data(), bytes.size(), loaded) == SchematicError::None);
CHECK(loaded.buffer().empty());
CHECK(loaded.header().name == std::string("void"));
World world;
CHECK_EQ(loaded.pasteInto(world, {0, 0, 0}, ClipboardBuffer::PasteMode::Overwrite), 0u);
CHECK_EQ(world.chunkCount(), 0u);
}
VF_TEST(reEncodingADecodedSchematicProducesTheSameBytes) {
World source = terrainWorld(7, 7);
Schematic saved = Schematic::capture(source, Selection::sphere({3, 3, 3}, 3), "stable",
"foksiu", 42u);
ByteBuffer first = saved.encode();
Schematic loaded;
CHECK(Schematic::decode(first.data(), first.size(), loaded) == SchematicError::None);
ByteBuffer second = loaded.encode();
CHECK(first == second);
CHECK(std::string(Schematic::errorText(SchematicError::None)) == std::string("ok"));
CHECK(std::string(Schematic::errorText(SchematicError::BadPalette)) !=
std::string(Schematic::errorText(SchematicError::BadChecksum)));
}