blob: 64980d7fa28a6f38a78196503a4aa7b6fc9f70e7 [file] [log] [blame]
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// MalformedShader_test.cpp:
// Tests that malformed shaders fail compilation.
//
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "GLSLANG/ShaderLang.h"
#include "compiler/translator/TranslatorESSL.h"
class MalformedShaderTest : public testing::Test
{
public:
MalformedShaderTest() : mExtraCompileOptions(0) {}
protected:
virtual void SetUp()
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_GLES3_SPEC);
ASSERT_TRUE(mTranslator->Init(resources));
}
virtual void TearDown()
{
delete mTranslator;
}
// Return true when compilation succeeds
bool compile(const std::string& shaderString)
{
const char *shaderStrings[] = { shaderString.c_str() };
bool compilationSuccess =
mTranslator->compile(shaderStrings, 1, SH_INTERMEDIATE_TREE | mExtraCompileOptions);
TInfoSink &infoSink = mTranslator->getInfoSink();
mInfoLog = infoSink.info.c_str();
return compilationSuccess;
}
bool hasWarning() const
{
return mInfoLog.find("WARNING: ") != std::string::npos;
}
protected:
std::string mInfoLog;
TranslatorESSL *mTranslator;
int mExtraCompileOptions;
};
class MalformedVertexShaderTest : public MalformedShaderTest
{
public:
MalformedVertexShaderTest() {}
protected:
void SetUp() override
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
mTranslator = new TranslatorESSL(GL_VERTEX_SHADER, SH_GLES3_SPEC);
ASSERT_TRUE(mTranslator->Init(resources));
}
};
class MalformedWebGL2ShaderTest : public MalformedShaderTest
{
public:
MalformedWebGL2ShaderTest() {}
protected:
void SetUp() override
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_WEBGL2_SPEC);
ASSERT_TRUE(mTranslator->Init(resources));
}
};
class MalformedWebGL1ShaderTest : public MalformedShaderTest
{
public:
MalformedWebGL1ShaderTest() {}
protected:
void SetUp() override
{
ShBuiltInResources resources;
ShInitBuiltInResources(&resources);
mTranslator = new TranslatorESSL(GL_FRAGMENT_SHADER, SH_WEBGL_SPEC);
ASSERT_TRUE(mTranslator->Init(resources));
}
};
class UnrollForLoopsTest : public MalformedShaderTest
{
public:
UnrollForLoopsTest() { mExtraCompileOptions = SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; }
};
// This is a test for a bug that used to exist in ANGLE:
// Calling a function with all parameters missing should not succeed.
TEST_F(MalformedShaderTest, FunctionParameterMismatch)
{
const std::string &shaderString =
"precision mediump float;\n"
"float fun(float a) {\n"
" return a * 2.0;\n"
"}\n"
"void main() {\n"
" float ff = fun();\n"
" gl_FragColor = vec4(ff);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Functions can't be redeclared as variables in the same scope (ESSL 1.00 section 4.2.7)
TEST_F(MalformedShaderTest, RedeclaringFunctionAsVariable)
{
const std::string &shaderString =
"precision mediump float;\n"
"float fun(float a) {\n"
" return a * 2.0;\n"
"}\n"
"float fun;\n"
"void main() {\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Functions can't be redeclared as structs in the same scope (ESSL 1.00 section 4.2.7)
TEST_F(MalformedShaderTest, RedeclaringFunctionAsStruct)
{
const std::string &shaderString =
"precision mediump float;\n"
"float fun(float a) {\n"
" return a * 2.0;\n"
"}\n"
"struct fun { float a; };\n"
"void main() {\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Functions can't be redeclared with different qualifiers (ESSL 1.00 section 6.1.0)
TEST_F(MalformedShaderTest, RedeclaringFunctionWithDifferentQualifiers)
{
const std::string &shaderString =
"precision mediump float;\n"
"float fun(out float a);\n"
"float fun(float a) {\n"
" return a * 2.0;\n"
"}\n"
"void main() {\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7)
TEST_F(MalformedShaderTest, CompareStructsContainingArrays)
{
const std::string &shaderString =
"precision mediump float;\n"
"struct s { float a[3]; };\n"
"void main() {\n"
" s a;\n"
" s b;\n"
" bool c = (a == b);\n"
" gl_FragColor = vec4(c ? 1.0 : 0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Assignment and equality are undefined for structures containing arrays (ESSL 1.00 section 5.7)
TEST_F(MalformedShaderTest, AssignStructsContainingArrays)
{
const std::string &shaderString =
"precision mediump float;\n"
"struct s { float a[3]; };\n"
"void main() {\n"
" s a;\n"
" s b;\n"
" b.a[0] = 0.0;\n"
" a = b;\n"
" gl_FragColor = vec4(a.a[0]);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Assignment and equality are undefined for structures containing samplers (ESSL 1.00 sections 5.7 and 5.9)
TEST_F(MalformedShaderTest, CompareStructsContainingSamplers)
{
const std::string &shaderString =
"precision mediump float;\n"
"struct s { sampler2D foo; };\n"
"uniform s a;\n"
"uniform s b;\n"
"void main() {\n"
" bool c = (a == b);\n"
" gl_FragColor = vec4(c ? 1.0 : 0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Samplers are not allowed as l-values (ESSL 3.00 section 4.1.7), our interpretation is that this
// extends to structs containing samplers. ESSL 1.00 spec is clearer about this.
TEST_F(MalformedShaderTest, AssignStructsContainingSamplers)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"struct s { sampler2D foo; };\n"
"uniform s a;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" s b;\n"
" b = a;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// This is a regression test for a particular bug that was in ANGLE.
// It also verifies that ESSL3 functionality doesn't leak to ESSL1.
TEST_F(MalformedShaderTest, ArrayWithNoSizeInInitializerList)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main() {\n"
" float a[2], b[];\n"
" gl_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Const variables need an initializer.
TEST_F(MalformedShaderTest, ConstVarNotInitialized)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" const float a;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Const variables need an initializer. In ESSL1 const structs containing
// arrays are not allowed at all since it's impossible to initialize them.
// Even though this test is for ESSL3 the only thing that's critical for
// ESSL1 is the non-initialization check that's used for both language versions.
// Whether ESSL1 compilation generates the most helpful error messages is a
// secondary concern.
TEST_F(MalformedShaderTest, ConstStructNotInitialized)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"struct S {\n"
" float a[3];\n"
"};\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" const S b;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Const variables need an initializer. In ESSL1 const arrays are not allowed
// at all since it's impossible to initialize them.
// Even though this test is for ESSL3 the only thing that's critical for
// ESSL1 is the non-initialization check that's used for both language versions.
// Whether ESSL1 compilation generates the most helpful error messages is a
// secondary concern.
TEST_F(MalformedShaderTest, ConstArrayNotInitialized)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" const float a[3];\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3)
TEST_F(MalformedShaderTest, BlockLayoutQualifierOnRegularUniform)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"layout(packed) uniform mat2 x;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Block layout qualifiers can't be used on non-block uniforms (ESSL 3.00 section 4.3.8.3)
TEST_F(MalformedShaderTest, BlockLayoutQualifierOnUniformWithEmptyDecl)
{
// Yes, the comma in the declaration below is not a typo.
// Empty declarations are allowed in GLSL.
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"layout(packed) uniform mat2, x;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9)
TEST_F(MalformedShaderTest, ArraysOfArrays1)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" float[5] a[3];\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Arrays of arrays are not allowed (ESSL 3.00 section 4.1.9)
TEST_F(MalformedShaderTest, ArraysOfArrays2)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" float[2] a, b[3];\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Implicitly sized arrays need to be initialized (ESSL 3.00 section 4.1.9)
TEST_F(MalformedShaderTest, UninitializedImplicitArraySize)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" float[] a;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// An operator can only form a constant expression if all the operands are constant expressions
// - even operands of ternary operator that are never evaluated. (ESSL 3.00 section 4.3.3)
TEST_F(MalformedShaderTest, TernaryOperatorNotConstantExpression)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform bool u;\n"
"void main() {\n"
" const bool a = true ? true : u;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Ternary operator can't operate on arrays (ESSL 3.00 section 5.7)
TEST_F(MalformedShaderTest, TernaryOperatorOnArrays)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" float[1] a = float[1](0.0);\n"
" float[1] b = float[1](1.0);\n"
" float[1] c = true ? a : b;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Ternary operator can't operate on structs (ESSL 3.00 section 5.7)
TEST_F(MalformedShaderTest, TernaryOperatorOnStructs)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"struct S { float foo; };\n"
"void main() {\n"
" S a = S(0.0);\n"
" S b = S(1.0);\n"
" S c = true ? a : b;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Array length() returns a constant signed integral expression (ESSL 3.00 section 4.1.9)
// Assigning it to unsigned should result in an error.
TEST_F(MalformedShaderTest, AssignArrayLengthToUnsigned)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" int[1] arr;\n"
" uint l = arr.length();\n"
" my_FragColor = vec4(float(l));\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
// Initializing with a varying should be an error.
TEST_F(MalformedShaderTest, AssignVaryingToGlobal)
{
const std::string &shaderString =
"precision mediump float;\n"
"varying float a;\n"
"float b = a * 2.0;\n"
"void main() {\n"
" gl_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
// Initializing with an uniform should be an error.
TEST_F(MalformedShaderTest, AssignUniformToGlobalESSL3)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform float a;\n"
"float b = a * 2.0;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
// Initializing with an uniform should generate a warning
// (we don't generate an error on ESSL 1.00 because of legacy compatibility)
TEST_F(MalformedShaderTest, AssignUniformToGlobalESSL1)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform float a;\n"
"float b = a * 2.0;\n"
"void main() {\n"
" gl_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
if (!hasWarning())
{
FAIL() << "Shader compilation succeeded without warnings, expecting warning " << mInfoLog;
}
}
else
{
FAIL() << "Shader compilation failed, expecting success with warning " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
// Initializing with an user-defined function call should be an error.
TEST_F(MalformedShaderTest, AssignFunctionCallToGlobal)
{
const std::string &shaderString =
"precision mediump float;\n"
"float foo() { return 1.0; }\n"
"float b = foo();\n"
"void main() {\n"
" gl_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
// Initializing with an assignment to another global should be an error.
TEST_F(MalformedShaderTest, AssignAssignmentToGlobal)
{
const std::string &shaderString =
"precision mediump float;\n"
"float c = 1.0;\n"
"float b = (c = 0.0);\n"
"void main() {\n"
" gl_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
// Initializing with incrementing another global should be an error.
TEST_F(MalformedShaderTest, AssignIncrementToGlobal)
{
const std::string &shaderString =
"precision mediump float;\n"
"float c = 1.0;\n"
"float b = (c++);\n"
"void main() {\n"
" gl_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 1.00 section 4.3)
// Initializing with a texture lookup function call should be an error.
TEST_F(MalformedShaderTest, AssignTexture2DToGlobal)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform mediump sampler2D s;\n"
"float b = texture2D(s, vec2(0.5, 0.5)).x;\n"
"void main() {\n"
" gl_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
// Initializing with a non-constant global should be an error.
TEST_F(MalformedShaderTest, AssignNonConstGlobalToGlobal)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"float a = 1.0;\n"
"float b = a * 2.0;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(b);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Global variable initializers need to be constant expressions (ESSL 3.00 section 4.3)
// Initializing with a constant global should be fine.
TEST_F(MalformedShaderTest, AssignConstGlobalToGlobal)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"const float a = 1.0;\n"
"float b = a * 2.0;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(b);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Statically assigning to both gl_FragData and gl_FragColor is forbidden (ESSL 1.00 section 7.2)
TEST_F(MalformedShaderTest, WriteBothFragDataAndFragColor)
{
const std::string &shaderString =
"precision mediump float;\n"
"void foo() {\n"
" gl_FragData[0].a++;\n"
"}\n"
"void main() {\n"
" gl_FragColor.x += 0.0;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Version directive must be on the first line (ESSL 3.00 section 3.3)
TEST_F(MalformedShaderTest, VersionOnSecondLine)
{
const std::string &shaderString =
"\n"
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Layout qualifier can only appear in global scope (ESSL 3.00 section 4.3.8)
TEST_F(MalformedShaderTest, LayoutQualifierInCondition)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform vec4 u;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" int i = 0;\n"
" for (int j = 0; layout(location = 0) bool b = false; ++j) {\n"
" ++i;\n"
" }\n"
" my_FragColor = u;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Layout qualifier can only appear where specified (ESSL 3.00 section 4.3.8)
TEST_F(MalformedShaderTest, LayoutQualifierInFunctionReturnType)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform vec4 u;\n"
"out vec4 my_FragColor;\n"
"layout(location = 0) vec4 foo() {\n"
" return u;\n"
"}\n"
"void main() {\n"
" my_FragColor = foo();\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// If there is more than one output, the location must be specified for all outputs.
// (ESSL 3.00.04 section 4.3.8.2)
TEST_F(MalformedShaderTest, TwoOutputsNoLayoutQualifiers)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform vec4 u;\n"
"out vec4 my_FragColor;\n"
"out vec4 my_SecondaryFragColor;\n"
"void main() {\n"
" my_FragColor = vec4(1.0);\n"
" my_SecondaryFragColor = vec4(0.5);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// (ESSL 3.00.04 section 4.3.8.2)
TEST_F(MalformedShaderTest, TwoOutputsFirstLayoutQualifier)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform vec4 u;\n"
"layout(location = 0) out vec4 my_FragColor;\n"
"out vec4 my_SecondaryFragColor;\n"
"void main() {\n"
" my_FragColor = vec4(1.0);\n"
" my_SecondaryFragColor = vec4(0.5);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// (ESSL 3.00.04 section 4.3.8.2)
TEST_F(MalformedShaderTest, TwoOutputsSecondLayoutQualifier)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform vec4 u;\n"
"out vec4 my_FragColor;\n"
"layout(location = 0) out vec4 my_SecondaryFragColor;\n"
"void main() {\n"
" my_FragColor = vec4(1.0);\n"
" my_SecondaryFragColor = vec4(0.5);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Uniforms can be arrays (ESSL 3.00 section 4.3.5)
TEST_F(MalformedShaderTest, UniformArray)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform vec4[2] u;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = u[0];\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Fragment shader input variables cannot be arrays of structs (ESSL 3.00 section 4.3.4)
TEST_F(MalformedShaderTest, FragmentInputArrayOfStructs)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"struct S {\n"
" vec4 foo;\n"
"};\n"
"in S i[2];\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = i[0].foo;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4)
// This test is testing the case where the array brackets are after the variable name, so
// the arrayness isn't known when the type and qualifiers are initially parsed.
TEST_F(MalformedVertexShaderTest, VertexShaderInputArray)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"in vec4 i[2];\n"
"void main() {\n"
" gl_Position = i[0];\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Vertex shader inputs can't be arrays (ESSL 3.00 section 4.3.4)
// This test is testing the case where the array brackets are after the type.
TEST_F(MalformedVertexShaderTest, VertexShaderInputArrayType)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"in vec4[2] i;\n"
"void main() {\n"
" gl_Position = i[0];\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Fragment shader inputs can't contain booleans (ESSL 3.00 section 4.3.4)
TEST_F(MalformedShaderTest, FragmentShaderInputStructWithBool)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"struct S {\n"
" bool foo;\n"
"};\n"
"in S s;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Fragment shader inputs without a flat qualifier can't contain integers (ESSL 3.00 section 4.3.4)
TEST_F(MalformedShaderTest, FragmentShaderInputStructWithInt)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"struct S {\n"
" int foo;\n"
"};\n"
"in S s;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Selecting a field of a vector that's the result of dynamic indexing a constant array should work.
TEST_F(MalformedShaderTest, ShaderSelectingFieldOfVectorIndexedFromArray)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform int i;\n"
"void main() {\n"
" float f = vec2[1](vec2(0.0, 0.1))[i].x;\n"
" my_FragColor = vec4(f);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Passing an array into a function and then passing a value from that array into another function
// should work. This is a regression test for a bug where the mangled name of a TType was not
// properly updated when determining the type resulting from array indexing.
TEST_F(MalformedShaderTest, ArrayValueFromFunctionParameterAsParameter)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform float u;\n"
"float foo(float f) {\n"
" return f * 2.0;\n"
"}\n"
"float bar(float[2] f) {\n"
" return foo(f[0]);\n"
"}\n"
"void main()\n"
"{\n"
" float arr[2];\n"
" arr[0] = u;\n"
" gl_FragColor = vec4(bar(arr));\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that out-of-range integer literal generates an error in ESSL 3.00.
TEST_F(MalformedShaderTest, OutOfRangeIntegerLiteral)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"precision highp int;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" my_FragColor = vec4(0x100000000);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that vector field selection from a value taken from an array constructor is accepted as a
// constant expression.
TEST_F(MalformedShaderTest, FieldSelectionFromVectorArrayConstructorIsConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" const float f = vec2[1](vec2(0.0, 1.0))[0].x;\n"
" my_FragColor = vec4(f);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that structure field selection from a value taken from an array constructor is accepted as a
// constant expression.
TEST_F(MalformedShaderTest, FieldSelectionFromStructArrayConstructorIsConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"struct S { float member; };\n"
"void main()\n"
"{\n"
" const float f = S[1](S(0.0))[0].member;\n"
" my_FragColor = vec4(f);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that a reference to a const array is accepted as a constant expression.
TEST_F(MalformedShaderTest, ArraySymbolIsConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" const float[2] arr = float[2](0.0, 1.0);\n"
" const float f = arr[0];\n"
" my_FragColor = vec4(f);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that using an array constructor in a parameter to a built-in function is accepted as a
// constant expression.
TEST_F(MalformedShaderTest, BuiltInFunctionAppliedToArrayConstructorIsConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" const float f = sin(float[2](0.0, 1.0)[0]);\n"
" my_FragColor = vec4(f);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that using an array constructor in a parameter to a built-in function is accepted as a
// constant expression.
TEST_F(MalformedShaderTest, BuiltInFunctionWithMultipleParametersAppliedToArrayConstructorIsConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" const float f = pow(1.0, float[2](0.0, 1.0)[0]);\n"
" my_FragColor = vec4(f);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that using an array constructor in a parameter to a constructor is accepted as a constant
// expression.
TEST_F(MalformedShaderTest, ConstructorWithMultipleParametersAppliedToArrayConstructorIsConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" const vec2 f = vec2(1.0, float[2](0.0, 1.0)[0]);\n"
" my_FragColor = vec4(f.x);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that using an array constructor in an operand of the ternary selection operator is accepted
// as a constant expression.
TEST_F(MalformedShaderTest, TernaryOperatorAppliedToArrayConstructorIsConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" const float f = true ? float[2](0.0, 1.0)[0] : 1.0;\n"
" my_FragColor = vec4(f);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that a ternary operator with one unevaluated non-constant operand is not a constant
// expression.
TEST_F(MalformedShaderTest, TernaryOperatorNonConstantOperand)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform float u;\n"
"void main()\n"
"{\n"
" const float f = true ? 1.0 : u;\n"
" gl_FragColor = vec4(f);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that a sampler can't be used in constructor argument list
TEST_F(MalformedShaderTest, SamplerInConstructorArguments)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform sampler2D s;\n"
"void main()\n"
"{\n"
" vec2 v = vec2(0.0, s);\n"
" gl_FragColor = vec4(v, 0.0, 0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that void can't be used in constructor argument list
TEST_F(MalformedShaderTest, VoidInConstructorArguments)
{
const std::string &shaderString =
"precision mediump float;\n"
"void foo() {}\n"
"void main()\n"
"{\n"
" vec2 v = vec2(0.0, foo());\n"
" gl_FragColor = vec4(v, 0.0, 0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that a shader passing a struct into a constructor of array of structs with 1 element works.
TEST_F(MalformedShaderTest, SingleStructArrayConstructor)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform float u;\n"
"struct S { float member; };\n"
"void main()\n"
"{\n"
" S[1] sarr = S[1](S(u));\n"
" my_FragColor = vec4(sarr[0].member);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Test that a shader with empty constructor parameter list is not accepted.
TEST_F(MalformedShaderTest, EmptyArrayConstructor)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform float u;\n"
"const float[] f = f[]();\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that indexing fragment outputs with a non-constant expression is forbidden, even if ANGLE
// is able to constant fold the index expression. ESSL 3.00 section 4.3.6.
TEST_F(MalformedShaderTest, DynamicallyIndexedFragmentOutput)
{
const std::string &shaderString =
"#version 300 es"
"precision mediump float;\n"
"uniform int a;\n"
"out vec4[2] my_FragData;\n"
"void main()\n"
"{\n"
" my_FragData[true ? 0 : a] = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that indexing an interface block array with a non-constant expression is forbidden, even if
// ANGLE is able to constant fold the index expression. ESSL 3.00 section 4.3.7.
TEST_F(MalformedShaderTest, DynamicallyIndexedInterfaceBlock)
{
const std::string &shaderString =
"#version 300 es"
"precision mediump float;\n"
"uniform int a;\n"
"uniform B\n"
"{\n"
" vec4 f;\n"
"}\n"
"blocks[2];\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" my_FragColor = blocks[true ? 0 : a].f;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that a shader that uses a struct definition in place of a struct constructor does not
// compile. See GLSL ES 1.00 section 5.4.3.
TEST_F(MalformedShaderTest, StructConstructorWithStructDefinition)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" struct s { float f; } (0.0);\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that indexing gl_FragData with a non-constant expression is forbidden in WebGL 2.0, even
// when ANGLE is able to constant fold the index.
// WebGL 2.0 spec section 'GLSL ES 1.00 Fragment Shader Output'
TEST_F(MalformedWebGL2ShaderTest, IndexFragDataWithNonConstant)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" for (int i = 0; i < 2; ++i) {\n"
" gl_FragData[true ? 0 : i] = vec4(0.0);\n"
" }\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that a non-constant texture offset is not accepted for textureOffset.
// ESSL 3.00 section 8.8
TEST_F(MalformedShaderTest, TextureOffsetNonConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform vec3 u_texCoord;\n"
"uniform mediump sampler3D u_sampler;\n"
"uniform int x;\n"
"void main()\n"
"{\n"
" my_FragColor = textureOffset(u_sampler, u_texCoord, ivec3(x, 3, -8));\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that a non-constant texture offset is not accepted for textureProjOffset with bias.
// ESSL 3.00 section 8.8
TEST_F(MalformedShaderTest, TextureProjOffsetNonConst)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform vec4 u_texCoord;\n"
"uniform mediump sampler3D u_sampler;\n"
"uniform int x;\n"
"void main()\n"
"{\n"
" my_FragColor = textureProjOffset(u_sampler, u_texCoord, ivec3(x, 3, -8), 0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that an out-of-range texture offset is not accepted.
// GLES 3.0.4 section 3.8.10 specifies that out-of-range offset has undefined behavior.
TEST_F(MalformedShaderTest, TextureLodOffsetOutOfRange)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"uniform vec3 u_texCoord;\n"
"uniform mediump sampler3D u_sampler;\n"
"void main()\n"
"{\n"
" my_FragColor = textureLodOffset(u_sampler, u_texCoord, 0.0, ivec3(0, 0, 8));\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that default precision qualifier for uint is not accepted.
// ESSL 3.00.4 section 4.5.4: Only allowed for float, int and sampler types.
TEST_F(MalformedShaderTest, DefaultPrecisionUint)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"precision mediump uint;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that sampler3D needs to be precision qualified.
// ESSL 3.00.4 section 4.5.4: New ESSL 3.00 sampler types don't have predefined precision.
TEST_F(MalformedShaderTest, NoPrecisionSampler3D)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"uniform sampler3D s;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Test that using a non-constant expression in a for loop initializer is forbidden in WebGL 1.0,
// even when ANGLE is able to constant fold the initializer.
// ESSL 1.00 Appendix A.
TEST_F(MalformedWebGL1ShaderTest, NonConstantLoopIndex)
{
const std::string &shaderString =
"precision mediump float;\n"
"uniform int u;\n"
"void main()\n"
"{\n"
" for (int i = (true ? 1 : u); i < 5; ++i) {\n"
" gl_FragColor = vec4(0.0);\n"
" }\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Regression test for an old crash bug in ANGLE.
// ForLoopUnroll used to crash when it encountered a while loop.
TEST_F(UnrollForLoopsTest, WhileLoop)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" while (true) {\n"
" gl_FragColor = vec4(0.0);\n"
" break;\n"
" }\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Regression test for an old crash bug in ANGLE.
// ForLoopUnroll used to crash when it encountered a loop that didn't fit the ESSL 1.00
// Appendix A limitations.
TEST_F(UnrollForLoopsTest, UnlimitedForLoop)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" for (;true;) {\n"
" gl_FragColor = vec4(0.0);\n"
" break;\n"
" }\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Check that indices that are not integers are rejected.
// The check should be done even if ESSL 1.00 Appendix A limitations are not applied.
TEST_F(MalformedShaderTest, NonIntegerIndex)
{
const std::string &shaderString =
"precision mediump float;\n"
"void main()\n"
"{\n"
" float f[3];\n"
" const float i = 2.0;\n"
" gl_FragColor = vec4(f[i]);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// ESSL1 shaders with a duplicate function prototype should be rejected.
// ESSL 1.00.17 section 4.2.7.
TEST_F(MalformedShaderTest, DuplicatePrototypeESSL1)
{
const std::string &shaderString =
"precision mediump float;\n"
"void foo();\n"
"void foo();\n"
"void foo() {}\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// ESSL3 shaders with a duplicate function prototype should be allowed.
// ESSL 3.00.4 section 4.2.3.
TEST_F(MalformedShaderTest, DuplicatePrototypeESSL3)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void foo();\n"
"void foo();\n"
"void foo() {}\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Shaders with a local function prototype should be rejected.
// ESSL 3.00.4 section 4.2.4.
TEST_F(MalformedShaderTest, LocalFunctionPrototype)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" void foo();\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// ESSL 3.00 fragment shaders can not use #pragma STDGL invariant(all).
// ESSL 3.00.4 section 4.6.1. Does not apply to other versions of ESSL.
TEST_F(MalformedShaderTest, ESSL300FragmentInvariantAll)
{
const std::string &shaderString =
"#version 300 es\n"
"#pragma STDGL invariant(all)\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Built-in functions can be overloaded in ESSL 1.00.
TEST_F(MalformedShaderTest, ESSL100BuiltInFunctionOverload)
{
const std::string &shaderString =
"precision mediump float;\n"
"int sin(int x)\n"
"{\n"
" return int(sin(float(x)));\n"
"}\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(sin(1));"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Built-in functions can not be overloaded in ESSL 3.00.
TEST_F(MalformedShaderTest, ESSL300BuiltInFunctionOverload)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"int sin(int x)\n"
"{\n"
" return int(sin(float(x)));\n"
"}\n"
"void main()\n"
"{\n"
" my_FragColor = vec4(sin(1));"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Multiplying a 4x2 matrix with a 4x2 matrix should not work.
TEST_F(MalformedShaderTest, CompoundMultiplyMatrixIdenticalNonSquareDimensions)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" mat4x2 foo;\n"
" foo *= mat4x2(4.0);\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Multiplying a matrix with 2 columns and 4 rows with a 2x2 matrix should work.
TEST_F(MalformedShaderTest, CompoundMultiplyMatrixValidNonSquareDimensions)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 my_FragColor;\n"
"void main()\n"
"{\n"
" mat2x4 foo;\n"
" foo *= mat2x2(4.0);\n"
" my_FragColor = vec4(0.0);\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Covers a bug where we would set the incorrect result size on an out-of-bounds vector swizzle.
TEST_F(MalformedShaderTest, OutOfBoundsVectorSwizzle)
{
const std::string &shaderString =
"void main() {\n"
" vec2(0).qq;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Covers a bug where strange preprocessor defines could trigger asserts.
TEST_F(MalformedShaderTest, DefineWithSemicolon)
{
const std::string &shaderString =
"#define Def; highp\n"
"uniform Def vec2 a;\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Covers a bug in our parsing of malformed shift preprocessor expressions.
TEST_F(MalformedShaderTest, LineDirectiveUndefinedShift)
{
const std::string &shaderString = "#line x << y";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Covers a bug in our parsing of malformed shift preprocessor expressions.
TEST_F(MalformedShaderTest, LineDirectiveNegativeShift)
{
const std::string &shaderString = "#line x << -1";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}