Commit 10fcd9be by Olli Etuaho Committed by Commit Bot

Add a helper class for compiler string matching tests

The MatchOutputCodeTest class makes it easier to implement tests that do string matching on compiler output. Inheriting test classes set the compiler settings, tests then call compile() with the shader string and can call foundInCode() to check if the output code contains a given string. Various compiler unit tests that already did string matching are refactored to make use of this new helper class. Some tests now use SH_GLES3_SPEC instead of SH_GLES2_SPEC - this should not have a significant impact on test coverage. Some compileTestShader function variants that are now unused can be removed from the code. BUG=angleproject:1430 TEST=angle_unittests Change-Id: I1fd3529d5a1c6ab192f95ace800cf162604e68e7 Reviewed-on: https://chromium-review.googlesource.com/357800Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent bbf1c102
......@@ -16,35 +16,15 @@ namespace
{
// Test for the SH_EMULATE_BUILT_IN_FUNCTIONS flag.
class EmulateBuiltInFunctionsTest : public testing::Test
class EmulateBuiltInFunctionsTest : public MatchOutputCodeTest
{
public:
EmulateBuiltInFunctionsTest() {}
protected:
void compile(const std::string &shaderString)
EmulateBuiltInFunctionsTest()
: MatchOutputCodeTest(GL_VERTEX_SHADER,
SH_EMULATE_BUILT_IN_FUNCTIONS,
SH_GLSL_COMPATIBILITY_OUTPUT)
{
std::string infoLog;
bool compilationSuccess = compileTestShader(GL_VERTEX_SHADER,
SH_GLES2_SPEC,
SH_GLSL_COMPATIBILITY_OUTPUT,
shaderString,
SH_EMULATE_BUILT_IN_FUNCTIONS,
&mGLSLCode,
&infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation into GLSL failed " << infoLog;
}
}
bool foundInCode(const char *stringToFind)
{
return mGLSLCode.find(stringToFind) != std::string::npos;
}
private:
std::string mGLSLCode;
};
TEST_F(EmulateBuiltInFunctionsTest, DotEmulated)
......
......@@ -12,82 +12,23 @@
#include "GLSLANG/ShaderLang.h"
#include "tests/test_utils/compiler_test.h"
class DebugShaderPrecisionTest : public testing::Test
class DebugShaderPrecisionTest : public MatchOutputCodeTest
{
public:
DebugShaderPrecisionTest() {}
protected:
void compile(const std::string& shaderString)
{
std::string infoLog;
bool compilationSuccess = compileWithSettings(SH_ESSL_OUTPUT, shaderString, &mESSLCode, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation into ESSL failed " << infoLog;
}
compilationSuccess = compileWithSettings(SH_GLSL_COMPATIBILITY_OUTPUT, shaderString, &mGLSLCode, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation into GLSL failed " << infoLog;
}
}
bool foundInESSLCode(const char* stringToFind)
{
return mESSLCode.find(stringToFind) != std::string::npos;
}
bool foundInGLSLCode(const char* stringToFind)
{
return mGLSLCode.find(stringToFind) != std::string::npos;
}
bool foundInCode(const char* stringToFind)
{
return foundInESSLCode(stringToFind) && foundInGLSLCode(stringToFind);
}
bool notFoundInCode(const char* stringToFind)
{
return !foundInESSLCode(stringToFind) && !foundInGLSLCode(stringToFind);
}
private:
bool compileWithSettings(ShShaderOutput output, const std::string &shaderString,
std::string *translatedCode, std::string *infoLog)
DebugShaderPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT)
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
resources.WEBGL_debug_shader_precision = 1;
return compileTestShader(GL_FRAGMENT_SHADER, SH_GLES3_SPEC, output, shaderString,
&resources, translatedCode, infoLog);
addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
getResources()->WEBGL_debug_shader_precision = 1;
}
std::string mESSLCode;
std::string mGLSLCode;
};
class NoDebugShaderPrecisionTest : public testing::Test
class NoDebugShaderPrecisionTest : public MatchOutputCodeTest
{
public:
NoDebugShaderPrecisionTest() {}
protected:
bool compile(const std::string& shaderString)
NoDebugShaderPrecisionTest()
: MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_GLSL_COMPATIBILITY_OUTPUT)
{
return compileTestShader(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT,
shaderString, &mCode, nullptr);
}
bool foundInCode(const char* stringToFind)
{
return mCode.find(stringToFind) != std::string::npos;
}
private:
std::string mCode;
};
TEST_F(DebugShaderPrecisionTest, RoundingFunctionsDefined)
......@@ -178,7 +119,7 @@ TEST_F(NoDebugShaderPrecisionTest, HelpersWrittenOnlyWithExtension)
"void main() {\n"
" gl_FragColor = vec4(u);\n"
"}\n";
ASSERT_TRUE(compile(shaderString));
compile(shaderString);
ASSERT_FALSE(foundInCode("angle_frm"));
}
......@@ -191,7 +132,7 @@ TEST_F(NoDebugShaderPrecisionTest, PragmaHasEffectsOnlyWithExtension)
"void main() {\n"
" gl_FragColor = vec4(u);\n"
"}\n";
ASSERT_TRUE(compile(shaderString));
compile(shaderString);
ASSERT_FALSE(foundInCode("angle_frm"));
}
......
......@@ -12,30 +12,13 @@
#include "GLSLANG/ShaderLang.h"
#include "tests/test_utils/compiler_test.h"
class GLSLCompatibilityOutputTest : public testing::Test
class GLSLCompatibilityOutputTest : public MatchOutputCodeTest
{
public:
GLSLCompatibilityOutputTest() {}
protected:
void compile(const std::string &shaderString)
GLSLCompatibilityOutputTest()
: MatchOutputCodeTest(GL_VERTEX_SHADER, SH_VARIABLES, SH_GLSL_COMPATIBILITY_OUTPUT)
{
int compilationFlags = SH_VARIABLES;
std::string infoLog;
bool compilationSuccess =
compileTestShader(GL_VERTEX_SHADER, SH_GLES2_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT,
shaderString, compilationFlags, &mTranslatedSource, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation failed " << infoLog;
}
}
bool find(const char *name) const { return mTranslatedSource.find(name) != std::string::npos; }
private:
std::string mTranslatedSource;
};
// Verify gl_Position is written when compiling in compatibility mode
......@@ -46,5 +29,5 @@ TEST_F(GLSLCompatibilityOutputTest, GLPositionWrittenTest)
"void main() {\n"
"}";
compile(shaderString);
EXPECT_TRUE(find("gl_Position"));
EXPECT_TRUE(foundInCode("gl_Position"));
}
\ No newline at end of file
......@@ -12,36 +12,16 @@
#include "GLSLANG/ShaderLang.h"
#include "tests/test_utils/compiler_test.h"
class NVDrawBuffersTest : public testing::Test
class NVDrawBuffersTest : public MatchOutputCodeTest
{
public:
NVDrawBuffersTest() {}
protected:
void compile(const std::string &shaderString)
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
resources.MaxDrawBuffers = 8;
resources.EXT_draw_buffers = 1;
resources.NV_draw_buffers = 1;
std::string infoLog;
bool compilationSuccess = compileTestShader(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_ESSL_OUTPUT,
shaderString, &resources, &mGLSLCode, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation into ESSL failed " << infoLog;
}
}
bool foundInCode(const char *stringToFind)
NVDrawBuffersTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT)
{
return mGLSLCode.find(stringToFind) != std::string::npos;
ShBuiltInResources *resources = getResources();
resources->MaxDrawBuffers = 8;
resources->EXT_draw_buffers = 1;
resources->NV_draw_buffers = 1;
}
private:
std::string mGLSLCode;
};
TEST_F(NVDrawBuffersTest, NVDrawBuffers)
......
......@@ -15,31 +15,10 @@
namespace
{
class PackUnpackTest : public testing::Test
class PackUnpackTest : public MatchOutputCodeTest
{
public:
PackUnpackTest() {}
protected:
void compile(const std::string& shaderString)
{
std::string infoLog;
bool compilationSuccess = compileTestShader(GL_FRAGMENT_SHADER, SH_GLES3_SPEC,
SH_GLSL_410_CORE_OUTPUT,
shaderString, &mGLSLCode, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation into GLSL 4.1 failed " << infoLog;
}
}
bool foundInGLSLCode(const char* stringToFind)
{
return mGLSLCode.find(stringToFind) != std::string::npos;
}
private:
std::string mGLSLCode;
PackUnpackTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_GLSL_410_CORE_OUTPUT) {}
};
//Check if PackSnorm2x16 Emulation for GLSL 4.1 compile correctly.
......@@ -55,7 +34,7 @@ TEST_F(PackUnpackTest, PackSnorm2x16Emulation)
" fragColor = vec4(0.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInGLSLCode("uint webgl_packSnorm2x16_emu(vec2 v)"));
ASSERT_TRUE(foundInCode("uint webgl_packSnorm2x16_emu(vec2 v)"));
}
//Check if UnpackSnorm2x16 Emulation for GLSL 4.1 compile correctly.
......@@ -71,7 +50,7 @@ TEST_F(PackUnpackTest, UnpackSnorm2x16Emulation)
" fragColor = vec4(0.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInGLSLCode("vec2 webgl_unpackSnorm2x16_emu(uint u)"));
ASSERT_TRUE(foundInCode("vec2 webgl_unpackSnorm2x16_emu(uint u)"));
}
//Check if PackHalf2x16 Emulation for GLSL 4.1 compile correctly.
......@@ -87,7 +66,7 @@ TEST_F(PackUnpackTest, PackHalf2x16Emulation)
" fragColor = vec4(0.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInGLSLCode("uint webgl_packHalf2x16_emu(vec2 v)"));
ASSERT_TRUE(foundInCode("uint webgl_packHalf2x16_emu(vec2 v)"));
}
//Check if UnpackHalf2x16 Emulation for GLSL 4.1 compile correctly.
......@@ -103,7 +82,7 @@ TEST_F(PackUnpackTest, UnpackHalf2x16Emulation)
" fragColor = vec4(0.0);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInGLSLCode("vec2 webgl_unpackHalf2x16_emu(uint u)"));
ASSERT_TRUE(foundInCode("vec2 webgl_unpackHalf2x16_emu(uint u)"));
}
} // namespace
......@@ -15,47 +15,17 @@
namespace
{
class PruneUnusedFunctionsTest : public testing::Test
class PruneUnusedFunctionsTest : public MatchOutputCodeTest
{
public:
PruneUnusedFunctionsTest() {}
PruneUnusedFunctionsTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT) {}
protected:
void compile(const std::string &shaderString, bool prune)
{
int compilationFlags = SH_VARIABLES | (prune ? 0 : SH_DONT_PRUNE_UNUSED_FUNCTIONS);
std::string infoLog;
bool compilationSuccess = compileTestShader(GL_FRAGMENT_SHADER, SH_GLES3_SPEC, SH_ESSL_OUTPUT,
shaderString, compilationFlags, &mTranslatedSource, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation failed " << infoLog;
}
}
bool kept(const char *functionName, int nOccurences) const
{
size_t currentPos = 0;
while (nOccurences-- > 0)
{
auto position = mTranslatedSource.find(functionName, currentPos);
if (position == std::string::npos)
{
return false;
}
currentPos = position + 1;
}
return mTranslatedSource.find(functionName, currentPos) == std::string::npos;
MatchOutputCodeTest::compile(shaderString, compilationFlags);
}
bool removed(const char* functionName) const
{
return mTranslatedSource.find(functionName) == std::string::npos;
}
private:
std::string mTranslatedSource;
};
// Check that unused function and prototypes are removed iff the options is set
......@@ -71,12 +41,12 @@ TEST_F(PruneUnusedFunctionsTest, UnusedFunctionAndProto)
" return a;\n"
"}\n";
compile(shaderString, true);
EXPECT_TRUE(removed("unused("));
EXPECT_TRUE(kept("main(", 1));
EXPECT_TRUE(notFoundInCode("unused("));
EXPECT_TRUE(foundInCode("main(", 1));
compile(shaderString, false);
EXPECT_TRUE(kept("unused(", 2));
EXPECT_TRUE(kept("main(", 1));
EXPECT_TRUE(foundInCode("unused(", 2));
EXPECT_TRUE(foundInCode("main(", 1));
}
// Check that unimplemented prototypes are removed iff the options is set
......@@ -89,12 +59,12 @@ TEST_F(PruneUnusedFunctionsTest, UnimplementedPrototype)
" gl_FragColor = vec4(1.0);\n"
"}\n";
compile(shaderString, true);
EXPECT_TRUE(removed("unused("));
EXPECT_TRUE(kept("main(", 1));
EXPECT_TRUE(notFoundInCode("unused("));
EXPECT_TRUE(foundInCode("main(", 1));
compile(shaderString, false);
EXPECT_TRUE(kept("unused(", 1));
EXPECT_TRUE(kept("main(", 1));
EXPECT_TRUE(foundInCode("unused(", 1));
EXPECT_TRUE(foundInCode("main(", 1));
}
// Check that used functions are not prunued (duh)
......@@ -110,12 +80,12 @@ TEST_F(PruneUnusedFunctionsTest, UsedFunction)
" return a;\n"
"}\n";
compile(shaderString, true);
EXPECT_TRUE(kept("used(", 3));
EXPECT_TRUE(kept("main(", 1));
EXPECT_TRUE(foundInCode("used(", 3));
EXPECT_TRUE(foundInCode("main(", 1));
compile(shaderString, false);
EXPECT_TRUE(kept("used(", 3));
EXPECT_TRUE(kept("main(", 1));
EXPECT_TRUE(foundInCode("used(", 3));
EXPECT_TRUE(foundInCode("main(", 1));
}
}
......@@ -12,29 +12,10 @@
#include "GLSLANG/ShaderLang.h"
#include "tests/test_utils/compiler_test.h"
class RecordConstantPrecisionTest : public testing::Test
class RecordConstantPrecisionTest : public MatchOutputCodeTest
{
public:
RecordConstantPrecisionTest() {}
protected:
void compile(const std::string &shaderString)
{
std::string infoLog;
bool compilationSuccess = compileTestShader(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_ESSL_OUTPUT,
shaderString, &mTranslatedCode, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation into ESSL failed " << infoLog;
}
}
bool foundInCode(const char *stringToFind)
{
return mTranslatedCode.find(stringToFind) != std::string::npos;
}
private:
std::string mTranslatedCode;
RecordConstantPrecisionTest() : MatchOutputCodeTest(GL_FRAGMENT_SHADER, 0, SH_ESSL_OUTPUT) {}
};
// The constant cannot be folded if its precision is higher than the other operands, since it
......
......@@ -6,9 +6,12 @@
// compiler_test.cpp:
// utilities for compiler unit tests.
#include "tests/test_utils/compiler_test.h"
#include "angle_gl.h"
#include "compiler/translator/Compiler.h"
bool compileTestShader(sh::GLenum type,
bool compileTestShader(GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
......@@ -36,18 +39,7 @@ bool compileTestShader(sh::GLenum type,
return compilationSuccess;
}
bool compileTestShader(sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
ShBuiltInResources *resources,
std::string *translatedCode,
std::string *infoLog)
{
return compileTestShader(type, spec, output, shaderString, resources, 0, translatedCode, infoLog);
}
bool compileTestShader(sh::GLenum type,
bool compileTestShader(GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
......@@ -60,12 +52,113 @@ bool compileTestShader(sh::GLenum type,
return compileTestShader(type, spec, output, shaderString, &resources, compileOptions, translatedCode, infoLog);
}
bool compileTestShader(sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
std::string *translatedCode,
std::string *infoLog)
MatchOutputCodeTest::MatchOutputCodeTest(GLenum shaderType,
int defaultCompileOptions,
ShShaderOutput outputType)
: mShaderType(shaderType), mDefaultCompileOptions(defaultCompileOptions)
{
ShInitBuiltInResources(&mResources);
mOutputCode[outputType] = std::string();
}
void MatchOutputCodeTest::addOutputType(const ShShaderOutput outputType)
{
mOutputCode[outputType] = std::string();
}
ShBuiltInResources *MatchOutputCodeTest::getResources()
{
return compileTestShader(type, spec, output, shaderString, 0, translatedCode, infoLog);
return &mResources;
}
void MatchOutputCodeTest::compile(const std::string &shaderString)
{
compile(shaderString, mDefaultCompileOptions);
}
void MatchOutputCodeTest::compile(const std::string &shaderString, const int compileOptions)
{
std::string infoLog;
for (auto &code : mOutputCode)
{
bool compilationSuccess =
compileWithSettings(code.first, shaderString, compileOptions, &code.second, &infoLog);
if (!compilationSuccess)
{
FAIL() << "Shader compilation failed:\n" << infoLog;
}
}
}
bool MatchOutputCodeTest::compileWithSettings(ShShaderOutput output,
const std::string &shaderString,
const int compileOptions,
std::string *translatedCode,
std::string *infoLog)
{
return compileTestShader(mShaderType, SH_GLES3_SPEC, output, shaderString, &mResources,
compileOptions, translatedCode, infoLog);
}
bool MatchOutputCodeTest::foundInCode(ShShaderOutput output, const char *stringToFind) const
{
const auto code = mOutputCode.find(output);
EXPECT_NE(mOutputCode.end(), code);
return code->second.find(stringToFind) != std::string::npos;
}
bool MatchOutputCodeTest::foundInCode(ShShaderOutput output,
const char *stringToFind,
const int expectedOccurrences) const
{
const auto code = mOutputCode.find(output);
EXPECT_NE(mOutputCode.end(), code);
size_t currentPos = 0;
int occurencesLeft = expectedOccurrences;
while (occurencesLeft-- > 0)
{
auto position = code->second.find(stringToFind, currentPos);
if (position == std::string::npos)
{
return false;
}
currentPos = position + 1;
}
return code->second.find(stringToFind, currentPos) == std::string::npos;
}
bool MatchOutputCodeTest::foundInCode(const char *stringToFind) const
{
for (auto &code : mOutputCode)
{
if (!foundInCode(code.first, stringToFind))
{
return false;
}
}
return true;
}
bool MatchOutputCodeTest::foundInCode(const char *stringToFind, const int expectedOccurrences) const
{
for (auto &code : mOutputCode)
{
if (!foundInCode(code.first, stringToFind, expectedOccurrences))
{
return false;
}
}
return true;
}
bool MatchOutputCodeTest::notFoundInCode(const char *stringToFind) const
{
for (auto &code : mOutputCode)
{
if (foundInCode(code.first, stringToFind))
{
return false;
}
}
return true;
}
......@@ -9,9 +9,13 @@
#ifndef TESTS_TEST_UTILS_COMPILER_TEST_H_
#define TESTS_TEST_UTILS_COMPILER_TEST_H_
#include <map>
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "GLSLANG/ShaderLang.h"
bool compileTestShader(sh::GLenum type,
bool compileTestShader(GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
......@@ -20,15 +24,7 @@ bool compileTestShader(sh::GLenum type,
std::string *translatedCode,
std::string *infoLog);
bool compileTestShader(sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
ShBuiltInResources *resources,
std::string *translatedCode,
std::string *infoLog);
bool compileTestShader(sh::GLenum type,
bool compileTestShader(GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
......@@ -36,11 +32,57 @@ bool compileTestShader(sh::GLenum type,
std::string *translatedCode,
std::string *infoLog);
bool compileTestShader(sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const std::string &shaderString,
std::string *translatedCode,
std::string *infoLog);
class MatchOutputCodeTest : public testing::Test
{
protected:
MatchOutputCodeTest(GLenum shaderType, int defaultCompileOptions, ShShaderOutput outputType);
void addOutputType(const ShShaderOutput outputType);
ShBuiltInResources *getResources();
// Compile functions clear any results from earlier calls to them.
void compile(const std::string &shaderString);
void compile(const std::string &shaderString, const int compileOptions);
bool foundInESSLCode(const char *stringToFind) const
{
return foundInCode(SH_ESSL_OUTPUT, stringToFind);
}
bool foundInGLSLCode(const char *stringToFind) const
{
return foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, stringToFind);
}
bool foundInCode(ShShaderOutput output, const char *stringToFind) const;
// Test that the string occurs for exactly expectedOccurrences times
bool foundInCode(ShShaderOutput output,
const char *stringToFind,
const int expectedOccurrences) const;
// Test that the string is found in all outputs
bool foundInCode(const char *stringToFind) const;
// Test that the string occurs for exactly expectedOccurrences times in all outputs
bool foundInCode(const char *stringToFind, const int expectedOccurrences) const;
// Test that the string is found in none of the outputs
bool notFoundInCode(const char *stringToFind) const;
private:
bool compileWithSettings(ShShaderOutput output,
const std::string &shaderString,
int compileOptions,
std::string *translatedCode,
std::string *infoLog);
GLenum mShaderType;
int mDefaultCompileOptions;
ShBuiltInResources mResources;
std::map<ShShaderOutput, std::string> mOutputCode;
};
#endif // TESTS_TEST_UTILS_COMPILER_TEST_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment