test: cover testSchematic
This commit is contained in:
1 parent
0f6bb179c7
commit
be77c57de3
1 file changed
+156
@@ -159,3 +159,159 @@ VF_TEST(rotatingFourTimesByNinetyDegreesReturnsTheOriginal) {
|
|||||||
twoQuarters.rotate(Rotation::Cw90);
|
twoQuarters.rotate(Rotation::Cw90);
|
||||||
CHECK(half.buffer().sameContent(twoQuarters.buffer()));
|
CHECK(half.buffer().sameContent(twoQuarters.buffer()));
|
||||||
|
|
||||||
|
Schematic backAgain = original;
|
||||||
|
backAgain.rotate(Rotation::Cw90);
|
||||||
|
backAgain.rotate(Rotation::Cw270);
|
||||||
|
CHECK(backAgain.buffer().sameContent(original.buffer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(aQuarterTurnSwapsTheHorizontalDimensionsAndMovesTheMarker) {
|
||||||
|
ClipboardBuffer buffer({4, 1, 2}, {0, 0, 0});
|
||||||
|
for (int z = 0; z < 2; ++z)
|
||||||
|
for (int x = 0; x < 4; ++x) buffer.put(x, 0, z, Block::Stone);
|
||||||
|
buffer.put(0, 0, 0, Block::Glowstone);
|
||||||
|
|
||||||
|
ClipboardBuffer turned = buffer.rotatedY(Rotation::Cw90);
|
||||||
|
CHECK(turned.dims() == Vec3i(2, 1, 4));
|
||||||
|
CHECK_EQ(turned.filledCount(), 8u);
|
||||||
|
// (0,0,0) maps to (dimZ - 1, 0, 0) under a clockwise quarter turn.
|
||||||
|
CHECK(turned.at(1, 0, 0) == Block::Glowstone);
|
||||||
|
CHECK(turned.at(0, 0, 0) == Block::Stone);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(mirroringTwiceOnTheSameAxisReturnsTheOriginal) {
|
||||||
|
ClipboardBuffer buffer({3, 2, 4}, {1, 0, 2});
|
||||||
|
for (int y = 0; y < 2; ++y)
|
||||||
|
for (int z = 0; z < 4; ++z)
|
||||||
|
for (int x = 0; x < 3; ++x) buffer.put(x, y, z, Block::Planks);
|
||||||
|
buffer.put(0, 0, 0, Block::Chest);
|
||||||
|
|
||||||
|
ClipboardBuffer flipped = buffer.mirrored(MirrorAxis::X);
|
||||||
|
CHECK(flipped.at(2, 0, 0) == Block::Chest);
|
||||||
|
CHECK(flipped.at(0, 0, 0) == Block::Planks);
|
||||||
|
CHECK(flipped.anchor() == Vec3i(1, 0, 2));
|
||||||
|
|
||||||
|
CHECK(flipped.mirrored(MirrorAxis::X).sameContent(buffer));
|
||||||
|
CHECK(buffer.mirrored(MirrorAxis::Y).mirrored(MirrorAxis::Y).sameContent(buffer));
|
||||||
|
CHECK(buffer.mirrored(MirrorAxis::Z).mirrored(MirrorAxis::Z).sameContent(buffer));
|
||||||
|
|
||||||
|
ClipboardBuffer alongZ = buffer.mirrored(MirrorAxis::Z);
|
||||||
|
CHECK(alongZ.at(0, 0, 3) == Block::Chest);
|
||||||
|
CHECK(alongZ.anchor() == Vec3i(1, 0, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(trimmingDropsEmptyMarginsAndKeepsTheAnchorOnTheSameBlock) {
|
||||||
|
ClipboardBuffer padded({8, 8, 8}, {5, 5, 5});
|
||||||
|
for (int y = 4; y <= 5; ++y)
|
||||||
|
for (int z = 4; z <= 6; ++z)
|
||||||
|
for (int x = 5; x <= 6; ++x) padded.put(x, y, z, Block::Bricks);
|
||||||
|
|
||||||
|
ClipboardBuffer tight = padded.trimmed();
|
||||||
|
CHECK(tight.dims() == Vec3i(2, 2, 3));
|
||||||
|
CHECK_EQ(tight.filledCount(), 12u);
|
||||||
|
CHECK(tight.anchor() == Vec3i(0, 1, 1));
|
||||||
|
CHECK(tight.at(0, 0, 0) == Block::Bricks);
|
||||||
|
|
||||||
|
World empty;
|
||||||
|
Schematic schematic = Schematic::fromBuffer(padded, "pad", "foksiu", 3u);
|
||||||
|
schematic.trim();
|
||||||
|
CHECK(schematic.header().dims == Vec3i(2, 2, 3));
|
||||||
|
CHECK_EQ(schematic.pasteInto(empty, {0, 0, 0}, ClipboardBuffer::PasteMode::Overwrite), 12u);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(versionOneDataIsMigratedToVersionTwoWhenLoaded) {
|
||||||
|
World source = terrainWorld(6, 6);
|
||||||
|
Schematic saved = Schematic::capture(source, Selection::box({0, 0, 0}, {5, 4, 5}), "legacy",
|
||||||
|
"foksiu", 777u);
|
||||||
|
|
||||||
|
ByteBuffer oldBytes = saved.encode(SchematicVersion::V1);
|
||||||
|
ByteBuffer newBytes = saved.encode(SchematicVersion::V2);
|
||||||
|
CHECK(oldBytes.size() < newBytes.size());
|
||||||
|
|
||||||
|
SchematicError error = SchematicError::BadMagic;
|
||||||
|
Schematic loaded = decodedCopy(oldBytes, error);
|
||||||
|
CHECK(error == SchematicError::None);
|
||||||
|
CHECK(loaded.migratedFromV1());
|
||||||
|
CHECK(loaded.header().version == SchematicVersion::V2);
|
||||||
|
CHECK(loaded.header().name.empty());
|
||||||
|
CHECK(loaded.header().author.empty());
|
||||||
|
CHECK_EQ(loaded.header().tick, 0u);
|
||||||
|
CHECK(loaded.buffer().sameContent(saved.buffer()));
|
||||||
|
|
||||||
|
// Re-saving the migrated schematic yields a v2 buffer that carries metadata.
|
||||||
|
loaded.setName("legacy");
|
||||||
|
loaded.setAuthor("foksiu");
|
||||||
|
loaded.setTick(777u);
|
||||||
|
SchematicError second = SchematicError::BadMagic;
|
||||||
|
Schematic again = decodedCopy(loaded.encode(), second);
|
||||||
|
CHECK(second == SchematicError::None);
|
||||||
|
CHECK(!again.migratedFromV1());
|
||||||
|
CHECK(again.header().name == std::string("legacy"));
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(theVoidMaskKeepsHolesInVersionTwoAndIsLostInVersionOne) {
|
||||||
|
World stoneBlock;
|
||||||
|
for (int y = 0; y < 9; ++y)
|
||||||
|
for (int z = 0; z < 9; ++z)
|
||||||
|
for (int x = 0; x < 9; ++x) stoneBlock.setBlock(x, y, z, Block::Stone);
|
||||||
|
|
||||||
|
Selection ball = Selection::sphere({4, 4, 4}, 4);
|
||||||
|
Schematic saved = Schematic::capture(stoneBlock, ball, "ball", "foksiu", 5u);
|
||||||
|
CHECK(saved.header().hasVoidMask);
|
||||||
|
CHECK(saved.buffer().filledCount() < saved.buffer().volume());
|
||||||
|
|
||||||
|
SchematicError error = SchematicError::BadMagic;
|
||||||
|
Schematic loaded = decodedCopy(saved.encode(), error);
|
||||||
|
CHECK(error == SchematicError::None);
|
||||||
|
CHECK(loaded.header().hasVoidMask);
|
||||||
|
CHECK_EQ(loaded.buffer().filledCount(), saved.buffer().filledCount());
|
||||||
|
CHECK(!loaded.buffer().filledAt(0, 0, 0));
|
||||||
|
|
||||||
|
SchematicError legacyError = SchematicError::BadMagic;
|
||||||
|
Schematic legacy = decodedCopy(saved.encode(SchematicVersion::V1), legacyError);
|
||||||
|
CHECK(legacyError == SchematicError::None);
|
||||||
|
CHECK(!legacy.header().hasVoidMask);
|
||||||
|
CHECK_EQ(legacy.buffer().filledCount(), legacy.buffer().volume());
|
||||||
|
CHECK(legacy.buffer().at(0, 0, 0) == Block::Air);
|
||||||
|
|
||||||
|
World target;
|
||||||
|
loaded.pasteInto(target, {0, 0, 0}, ClipboardBuffer::PasteMode::Overwrite);
|
||||||
|
CHECK(target.blockAt(4, 4, 4) == Block::Stone);
|
||||||
|
CHECK(target.blockAt(0, 0, 0) == Block::Air);
|
||||||
|
CHECK(target.blockAt(8, 8, 8) == Block::Air);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(aBufferWithTheWrongMagicNumberIsRejected) {
|
||||||
|
World source = terrainWorld(3, 3);
|
||||||
|
ByteBuffer bytes =
|
||||||
|
Schematic::capture(source, Selection::box({0, 0, 0}, {2, 2, 2}), "m", "f", 1u).encode();
|
||||||
|
bytes[0] = 0x00;
|
||||||
|
|
||||||
|
Schematic loaded;
|
||||||
|
CHECK(Schematic::decode(bytes.data(), bytes.size(), loaded) == SchematicError::BadMagic);
|
||||||
|
|
||||||
|
ByteBuffer garbage = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||||
|
CHECK(Schematic::decode(garbage.data(), garbage.size(), loaded) == SchematicError::BadMagic);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(anUnknownFormatVersionIsRejected) {
|
||||||
|
World source = terrainWorld(3, 3);
|
||||||
|
ByteBuffer bytes =
|
||||||
|
Schematic::capture(source, Selection::box({0, 0, 0}, {2, 2, 2}), "v", "f", 1u).encode();
|
||||||
|
writeU32(bytes, 4, 7u);
|
||||||
|
|
||||||
|
Schematic loaded;
|
||||||
|
CHECK(Schematic::decode(bytes.data(), bytes.size(), loaded) ==
|
||||||
|
SchematicError::UnsupportedVersion);
|
||||||
|
|
||||||
|
writeU32(bytes, 4, 0u);
|
||||||
|
CHECK(Schematic::decode(bytes.data(), bytes.size(), loaded) ==
|
||||||
|
SchematicError::UnsupportedVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(aTruncatedBufferIsRejectedAtEveryCutPoint) {
|
||||||
|
World source = terrainWorld(5, 5);
|
||||||
|
ByteBuffer bytes =
|
||||||
|
Schematic::capture(source, Selection::box({0, 0, 0}, {4, 4, 4}), "cut", "f", 1u).encode();
|
||||||
|
CHECK(bytes.size() > 40u);
|
||||||
|
|
||||||
Reference in new issue
Block a user