From dc91a40f5d8b48d30c05b5847887598198891328 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Fri, 11 Sep 2026 18:39:49 +0200 Subject: [PATCH] test: cover testHeaderCoexistence --- tests/testHeaderCoexistence.cpp | 154 ++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 tests/testHeaderCoexistence.cpp diff --git a/tests/testHeaderCoexistence.cpp b/tests/testHeaderCoexistence.cpp new file mode 100644 index 0000000..ac98c00 --- /dev/null +++ b/tests/testHeaderCoexistence.cpp @@ -0,0 +1,154 @@ +// Every public header pulled into ONE translation unit. +// +// This exists because it already failed for real: two modules independently +// declared vf::DamageSource (an enum in Survival.h, a struct in Damage.h) and +// nothing caught it, because no single translation unit ever included both. +// The combined binary linked and then died with SIGSEGV instead of a compiler +// error. A duplicate type, a duplicate free function or a conflicting +// declaration between any two modules now fails this file at compile time. +// +// Do not split this file and do not include headers selectively - the whole +// point is that all of them meet here. + +#include "vf/Advancement.h" +#include "vf/Anvil.h" +#include "vf/Behavior.h" +#include "vf/BiomeGen.h" +#include "vf/Block.h" +#include "vf/BlockTick.h" +#include "vf/Boss.h" +#include "vf/Brewing.h" +#include "vf/Brush.h" +#include "vf/Chunk.h" +#include "vf/ChunkCache.h" +#include "vf/ChunkPipeline.h" +#include "vf/ChunkSync.h" +#include "vf/Circuit.h" +#include "vf/Climate.h" +#include "vf/Codec.h" +#include "vf/Command.h" +#include "vf/Container.h" +#include "vf/ContainerMenu.h" +#include "vf/Crafting.h" +#include "vf/Damage.h" +#include "vf/DataPack.h" +#include "vf/Dimension.h" +#include "vf/Dispenser.h" +#include "vf/EditHistory.h" +#include "vf/Effect.h" +#include "vf/Enchant.h" +#include "vf/EndGen.h" +#include "vf/Entity.h" +#include "vf/Equipment.h" +#include "vf/Explosion.h" +#include "vf/Farming.h" +#include "vf/Fluid.h" +#include "vf/Frustum.h" +#include "vf/Gossip.h" +#include "vf/Hopper.h" +#include "vf/Inventory.h" +#include "vf/Item.h" +#include "vf/ItemStack.h" +#include "vf/JobSystem.h" +#include "vf/Json.h" +#include "vf/LightEngine.h" +#include "vf/Lighting.h" +#include "vf/LitMesh.h" +#include "vf/Loot.h" +#include "vf/LootTables.h" +#include "vf/Math.h" +#include "vf/Mesh.h" +#include "vf/Minecart.h" +#include "vf/Mob.h" +#include "vf/Nbt.h" +#include "vf/NetServer.h" +#include "vf/NetSession.h" +#include "vf/NetherGen.h" +#include "vf/Noise.h" +#include "vf/NoiseAdv.h" +#include "vf/Pathfind.h" +#include "vf/Physics.h" +#include "vf/Piston.h" +#include "vf/PlayerData.h" +#include "vf/Portal.h" +#include "vf/PotionCatalog.h" +#include "vf/Protocol.h" +#include "vf/Raid.h" +#include "vf/Rail.h" +#include "vf/RandomTick.h" +#include "vf/Raycast.h" +#include "vf/Region.h" +#include "vf/RegionCompact.h" +#include "vf/SaveIntegrity.h" +#include "vf/SaveMigration.h" +#include "vf/SaveV3.h" +#include "vf/Schematic.h" +#include "vf/Scoreboard.h" +#include "vf/Selection.h" +#include "vf/Serialize.h" +#include "vf/SlotAction.h" +#include "vf/Spawning.h" +#include "vf/Streaming.h" +#include "vf/StructureGen.h" +#include "vf/Structures.h" +#include "vf/Survival.h" +#include "vf/Terrain.h" +#include "vf/TilePalette.h" +#include "vf/TileTexture.h" +#include "vf/TimeOfDay.h" +#include "vf/Trade.h" +#include "vf/Transport.h" +#include "vf/Villager.h" +#include "vf/Weather.h" +#include "vf/World.h" +#include "vf/WorldBackup.h" +#include "vf/WorldGen.h" +#include "vf/WorldSim.h" + +#include "testHarness.h" + +#include +#include +#include +#include +#include + +using namespace vf; + +namespace { + +// Walk up from the working directory until the source tree is found, so the +// binary can be launched from the repository root (what `make test` does) or +// from one level below it. +std::filesystem::path findRepoRoot() { + std::filesystem::path here = std::filesystem::current_path(); + for (int step = 0; step < 4; ++step) { + if (std::filesystem::is_directory(here / "core" / "include" / "vf") && + std::filesystem::is_regular_file(here / "tests" / "testHeaderCoexistence.cpp")) { + return here; + } + if (!here.has_parent_path() || here.parent_path() == here) break; + here = here.parent_path(); + } + return {}; +} + +} // namespace + +// The guard above is only worth as much as its include list. A module added +// without a line here would quietly stop being checked, which is exactly how +// the first collision slipped through. This test reads the directory and this +// file's own source and fails when the two disagree. +VF_TEST(everyPublicHeaderIsListedInTheCoexistenceGuard) { + std::filesystem::path root = findRepoRoot(); + CHECK(!root.empty()); + if (root.empty()) return; + + std::set onDisk; + for (const auto& entry : std::filesystem::directory_iterator(root / "core" / "include" / "vf")) { + if (entry.is_regular_file() && entry.path().extension() == ".h") { + onDisk.insert(entry.path().filename().string()); + } + } + CHECK(onDisk.size() > 60u); +