Skip to content

Commit

Permalink
#5336: Construct a unit test scenario to check whether the CSG merge …
Browse files Browse the repository at this point in the history
…algorithm joins brushes of different entities
  • Loading branch information
codereader committed Sep 27, 2020
1 parent 65179d4 commit 4e06dd6
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
33 changes: 33 additions & 0 deletions test/CSG.cpp
@@ -1,9 +1,42 @@
#include "RadiantTest.h"

#include "imap.h"
#include "ibrush.h"
#include "entitylib.h"
#include "algorithm/Scene.h"

// Issue #5336: Crash when using CSG Merge on brushes that are entities
TEST_F(RadiantTest, CSGMergeWithFuncStatic)
{
loadMap("csg_merge_with_func_static.map");

// Locate the first worldspawn brush
scene::INodePtr firstBrush = test::algorithm::getNthChild(GlobalMapModule().getWorldspawn(), 0);
ASSERT_TRUE(firstBrush);

// Locate the func_static in the map
EntityNodeFindByClassnameWalker walker("func_static");
GlobalSceneGraph().root()->traverse(walker);

auto entityNode = walker.getEntityNode();
ASSERT_TRUE(entityNode);
ASSERT_TRUE(entityNode->hasChildNodes());

// Select both of them, the order is important
Node_setSelected(firstBrush, true);
Node_setSelected(entityNode, true);

// CSG merge
GlobalCommandSystem().executeCommand("CSGMerge");

// No merge should have happened since the brushes
// are not part of the same entity
// So assume the scene didn't change
ASSERT_TRUE(test::algorithm::getNthChild(GlobalMapModule().getWorldspawn(), 0) == firstBrush);

EntityNodeFindByClassnameWalker walker2("func_static");
GlobalSceneGraph().root()->traverse(walker2);

ASSERT_TRUE(walker.getEntityNode());
ASSERT_TRUE(walker.getEntityNode()->hasChildNodes());
}
31 changes: 31 additions & 0 deletions test/algorithm/Scene.h
@@ -0,0 +1,31 @@
#pragma once

#include <cstddef>
#include "inode.h"
#include "ientity.h"

namespace test::algorithm
{

// Returns the n-th child of the given parent node
inline scene::INodePtr getNthChild(const scene::INodePtr& parent, std::size_t index)
{
std::size_t n = 0;
scene::INodePtr candidate;

parent->foreachNode([&](const scene::INodePtr& node)
{
if (n == index)
{
candidate = node;
return false;
}

++n;
return true;
});

return candidate;
}

}
1 change: 1 addition & 0 deletions tools/msvc/Tests/Tests.vcxproj
Expand Up @@ -55,6 +55,7 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\test\algorithm\Scene.h" />
<ClInclude Include="..\..\..\test\HeadlessOpenGLContext.h" />
<ClInclude Include="..\..\..\test\RadiantTest.h" />
<ClInclude Include="..\..\..\test\TestContext.h" />
Expand Down
24 changes: 24 additions & 0 deletions tools/msvc/Tests/Tests.vcxproj.filters
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\..\..\test\CSG.cpp" />
<ClCompile Include="..\..\..\test\HeadlessOpenGLContext.cpp" />
<ClCompile Include="..\..\..\test\test.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\test\HeadlessOpenGLContext.h" />
<ClInclude Include="..\..\..\test\RadiantTest.h" />
<ClInclude Include="..\..\..\test\TestContext.h" />
<ClInclude Include="..\..\..\test\algorithm\Scene.h">
<Filter>algorithm</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Filter Include="algorithm">
<UniqueIdentifier>{519b0a02-8afc-4b67-9fa3-aeed09412562}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

0 comments on commit 4e06dd6

Please sign in to comment.