Skip to content

Commit

Permalink
#5977: Add unit test checking that reloadDecls re-parses the file
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Jun 24, 2022
1 parent 38ed7f2 commit df14b27
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 12 deletions.
3 changes: 3 additions & 0 deletions include/ideclmanager.h
Expand Up @@ -49,6 +49,9 @@ class IDeclaration

// The type of this declaration
virtual Type getDeclType() const = 0;

// The raw syntax block (without the outer curly braces) used to construct this decl
virtual const DeclarationBlockSyntax& getBlockSyntax() const = 0;
};

using NamedDeclarations = std::map<std::string, IDeclaration::Ptr>;
Expand Down
11 changes: 8 additions & 3 deletions plugins/sound/SoundShader.cpp
Expand Up @@ -22,7 +22,7 @@ struct SoundShader::ParsedContents

SoundShader::SoundShader(const decl::DeclarationBlockSyntax& block)
: _name(block.name),
_blockContents(block.contents),
_declBlock(block),
_fileInfo(block.fileInfo),
_modName(block.getModName())
{ }
Expand All @@ -37,7 +37,7 @@ void SoundShader::parseDefinition() const
_contents.reset(new ParsedContents);

// Get a new tokeniser and parse the block
parser::BasicDefTokeniser<std::string> tok(_blockContents);
parser::BasicDefTokeniser<std::string> tok(_declBlock.contents);

while (tok.hasMoreTokens())
{
Expand Down Expand Up @@ -97,7 +97,12 @@ std::string SoundShader::getShaderFilePath() const

std::string SoundShader::getDefinition() const
{
return _blockContents;
return _declBlock.contents;
}

const decl::DeclarationBlockSyntax& SoundShader::getBlockSyntax() const
{
return _declBlock;
}

} // namespace sound
8 changes: 5 additions & 3 deletions plugins/sound/SoundShader.h
Expand Up @@ -9,14 +9,14 @@ namespace sound
{

/// Representation of a single sound shader.
class SoundShader :
class SoundShader final :
public ISoundShader
{
// Name of the shader
std::string _name;

// The raw unparsed definition block
std::string _blockContents;
decl::DeclarationBlockSyntax _declBlock;

// Information we have parsed on demand
struct ParsedContents;
Expand All @@ -36,7 +36,7 @@ class SoundShader :

SoundShader(const decl::DeclarationBlockSyntax& block);

virtual ~SoundShader();
~SoundShader();

// ISoundShader implementation
SoundRadii getRadii() const override;
Expand All @@ -47,6 +47,8 @@ class SoundShader :
const std::string& getDisplayFolder() const override;
std::string getShaderFilePath() const override;
std::string getDefinition() const override;

const decl::DeclarationBlockSyntax& getBlockSyntax() const override;
};

}
7 changes: 5 additions & 2 deletions radiantcore/decl/DeclarationManager.cpp
Expand Up @@ -124,7 +124,10 @@ void DeclarationManager::onParserFinished(Type parserType, std::map<Type, NamedD
{
auto& map = _declarationsByType.try_emplace(pair.first, Declarations()).first->second.decls;

map.merge(pair.second);
for (auto& parsedDecl : pair.second)
{
InsertDeclaration(map, std::move(parsedDecl.second));
}
}
}

Expand All @@ -139,7 +142,7 @@ void DeclarationManager::onParserFinished(Type parserType, std::map<Type, NamedD
// We might have received a parser in the meantime
handleUnrecognisedBlocks();

// Invoke the declsReloaded singal for this type
// Invoke the declsReloaded signal for this type
signal_DeclsReloaded(parserType).emit();
}

Expand Down
76 changes: 72 additions & 4 deletions test/DeclManager.cpp
@@ -1,6 +1,7 @@
#include "RadiantTest.h"

#include "ideclmanager.h"
#include "testutil/TemporaryFile.h"

namespace test
{
Expand All @@ -13,11 +14,13 @@ class TestDeclaration :
private:
decl::Type _type;
std::string _name;
decl::DeclarationBlockSyntax _block;

public:
TestDeclaration(decl::Type type, const std::string& name) :
TestDeclaration(decl::Type type, const decl::DeclarationBlockSyntax& block) :
_type(type),
_name(name)
_block(block),
_name(block.name)
{}

const std::string& getDeclName() const override
Expand All @@ -29,6 +32,11 @@ class TestDeclaration :
{
return _type;
}

const decl::DeclarationBlockSyntax& getBlockSyntax() const override
{
return _block;
}
};

class TestDeclarationParser :
Expand All @@ -52,7 +60,7 @@ class TestDeclarationParser :
std::this_thread::sleep_for(20ms);
}

return std::make_shared<TestDeclaration>(getDeclType(), block.name);
return std::make_shared<TestDeclaration>(getDeclType(), block);
}
};

Expand All @@ -69,7 +77,7 @@ class TestDeclaration2Parser :
// Create a new declaration instance from the given block
decl::IDeclaration::Ptr parseFromBlock(const decl::DeclarationBlockSyntax& block) override
{
return std::make_shared<TestDeclaration>(getDeclType(), block.name);
return std::make_shared<TestDeclaration>(getDeclType(), block);
}
};

Expand Down Expand Up @@ -273,4 +281,64 @@ TEST_F(DeclManagerTest, FindDeclaration)
EXPECT_FALSE(GlobalDeclarationManager().findDeclaration(decl::Type::Material, "decl/nonexistent"));
}

TEST_F(DeclManagerTest, ReloadDeclarationWithChangedFile)
{
TemporaryFile tempFile(_context.getTestProjectPath() + "testdecls/temp_file.decl");
tempFile.setContents(R"(
decl/temporary/11
{
diffusemap textures/temporary/11
}
decl/temporary/12
{
diffusemap textures/temporary/12
}
)");

GlobalDeclarationManager().registerDeclType("testdecl", std::make_shared<TestDeclarationParser>());
GlobalDeclarationManager().registerDeclFolder(decl::Type::Material, "testdecls", ".decl");

auto temp12 = GlobalDeclarationManager().findDeclaration(decl::Type::Material, "decl/temporary/12");
EXPECT_TRUE(temp12) << "Couldn't find the declaration decl/temporary/12";

auto temp11 = GlobalDeclarationManager().findDeclaration(decl::Type::Material, "decl/temporary/11");
EXPECT_TRUE(temp11) << "Couldn't find the declaration decl/temporary/11";

EXPECT_FALSE(GlobalDeclarationManager().findDeclaration(decl::Type::Material, "decl/temporary/13"))
<< "decl/temporary/13 should not be present";

EXPECT_NE(temp12->getBlockSyntax().contents.find("diffusemap textures/temporary/12"), std::string::npos) <<
"Didn't find the expected contents in the decl block";

// Change the file, change temp12, remove temp11 and add temp13 instead
tempFile.setContents(R"(
decl/temporary/12
{
diffusemap textures/changed_temporary/12
}
decl/temporary/13
{
diffusemap textures/temporary/13
}
)");

// Check the change sin temp12
temp12 = GlobalDeclarationManager().findDeclaration(decl::Type::Material, "decl/temporary/12");
EXPECT_TRUE(temp12) << "Couldn't find the declaration decl/temporary/12";

EXPECT_NE(temp12->getBlockSyntax().contents.find("diffusemap textures/changed_temporary/12"), std::string::npos) <<
"Couldn't find the changed contents in the decl block";

EXPECT_TRUE(GlobalDeclarationManager().findDeclaration(decl::Type::Material, "decl/temporary/13"))
<< "decl/temporary/13 should be present now";
EXPECT_FALSE(GlobalDeclarationManager().findDeclaration(decl::Type::Material, "decl/temporary/11"))
<< "decl/temporary/11 should be gone now";
}

}
37 changes: 37 additions & 0 deletions test/testutil/TemporaryFile.h
@@ -0,0 +1,37 @@
#pragma once

#include <string>
#include <fstream>
#include "os/file.h"

namespace test
{

// File object removing itself when going out of scope
class TemporaryFile
{
private:
std::string _path;

public:
TemporaryFile(const std::string& path, const std::string& contents = "") :
_path(path)
{
setContents(contents);
}

void setContents(const std::string& contents)
{
std::ofstream stream(_path, std::ofstream::out);
stream << contents;
stream.flush();
stream.close();
}

~TemporaryFile()
{
fs::remove(_path);
}
};

}
1 change: 1 addition & 0 deletions tools/msvc/Tests/Tests.vcxproj
Expand Up @@ -75,6 +75,7 @@
<ClInclude Include="..\..\..\test\testutil\CommandFailureHelper.h" />
<ClInclude Include="..\..\..\test\testutil\MapOperationMonitor.h" />
<ClInclude Include="..\..\..\test\testutil\RenderUtils.h" />
<ClInclude Include="..\..\..\test\testutil\TemporaryFile.h" />
<ClInclude Include="..\..\..\test\testutil\TestBufferObjectProvider.h" />
<ClInclude Include="..\..\..\test\testutil\FileSelectionHelper.h" />
<ClInclude Include="..\..\..\test\testutil\TestObjectRenderer.h" />
Expand Down
3 changes: 3 additions & 0 deletions tools/msvc/Tests/Tests.vcxproj.filters
Expand Up @@ -107,6 +107,9 @@
<ClInclude Include="..\..\..\test\testutil\RenderUtils.h">
<Filter>testutil</Filter>
</ClInclude>
<ClInclude Include="..\..\..\test\testutil\TemporaryFile.h">
<Filter>testutil</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="algorithm">
Expand Down

0 comments on commit df14b27

Please sign in to comment.