1da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org//
2da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org// Use of this source code is governed by a BSD-style license that can be
4da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org// found in the LICENSE file.
5da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org//
6da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org#include <sstream>
7da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org#include <string>
8da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org#include <vector>
9da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org#include "GLSLANG/ShaderLang.h"
10da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org#include "gtest/gtest.h"
11da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
12da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org#define SHADER(Src) #Src
13da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
14da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgclass ExpressionLimitTest : public testing::Test {
15da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgprotected:
16da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const int kMaxExpressionComplexity = 16;
17da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const int kMaxCallStackDepth = 16;
18da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* kExpressionTooComplex;
19da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* kCallStackTooDeep;
20da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* kHasRecursion;
21da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
22da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    virtual void SetUp()
23da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
24da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        memset(&resources, 0, sizeof(resources));
25da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
26da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ASSERT_TRUE(ShInitialize() != 0) << "Could not ShInitialize";
27da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
28da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateResources(&resources);
29da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
30da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
31da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    virtual void TearDown()
32da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
33da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ASSERT_TRUE(ShFinalize() != 0);
34da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
35da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
36da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Set up the per compile resources
37da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    void GenerateResources(ShBuiltInResources* resources)
38da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
39da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ShInitBuiltInResources(resources);
40da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
41da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxVertexAttribs = 8;
42da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxVertexUniformVectors = 128;
43da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxVaryingVectors = 8;
44da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxVertexTextureImageUnits = 0;
45da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxCombinedTextureImageUnits = 8;
46da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxTextureImageUnits = 8;
47da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxFragmentUniformVectors = 16;
48da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxDrawBuffers = 1;
49da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
50da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->OES_standard_derivatives = 0;
51da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->OES_EGL_image_external = 0;
52da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
53da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxExpressionComplexity = kMaxExpressionComplexity;
54da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        resources->MaxCallStackDepth = kMaxCallStackDepth;
55da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
56da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
57da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    void GenerateLongExpression(int length, std::stringstream* ss)
58da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
59da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        for (int ii = 0; ii < length; ++ii) {
60da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org          *ss << "+ vec4(" << ii << ")";
61da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
62da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
63da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
64da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    std::string GenerateShaderWithLongExpression(int length)
65da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
66da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        static const char* shaderStart = SHADER(
67da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            precision mediump float;
68da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            uniform vec4 u_color;
69da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            void main()
70da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            {
71da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org               gl_FragColor = u_color
72da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        );
73da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
74da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        std::stringstream ss;
75da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ss << shaderStart;
76da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateLongExpression(length, &ss);
77da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ss << "; }";
78da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
79da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        return ss.str();
80da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
81da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
82da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    std::string GenerateShaderWithUnusedLongExpression(int length)
83da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
84da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        static const char* shaderStart = SHADER(
85da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            precision mediump float;
86da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            uniform vec4 u_color;
87da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            void main()
88da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            {
89da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org               gl_FragColor = u_color;
90da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            }
91da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            vec4 someFunction() {
92da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org              return u_color
93da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        );
94da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
95da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        std::stringstream ss;
96da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
97da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ss << shaderStart;
98da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateLongExpression(length, &ss);
99da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ss << "; }";
100da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
101da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        return ss.str();
102da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
103da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
104da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    void GenerateDeepFunctionStack(int length, std::stringstream* ss)
105da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
106da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        static const char* shaderStart = SHADER(
107da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            precision mediump float;
108da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            uniform vec4 u_color;
109da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            vec4 function0()  {
110da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org              return u_color;
111da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            }
112da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        );
113da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
114da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        *ss << shaderStart;
115da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        for (int ii = 0; ii < length; ++ii) {
116da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org          *ss << "vec4 function" << (ii + 1) << "() {\n"
117da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org              << "  return function" << ii << "();\n"
118da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org              << "}\n";
119da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
120da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
121da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
122da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    std::string GenerateShaderWithDeepFunctionStack(int length)
123da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
124da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        std::stringstream ss;
125da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
126da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateDeepFunctionStack(length, &ss);
127da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
128da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ss << "void main() {\n"
129da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org           << "  gl_FragColor = function" << length << "();\n"
130da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org           << "}";
131da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
132da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        return ss.str();
133da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
134da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
135da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    std::string GenerateShaderWithUnusedDeepFunctionStack(int length)
136da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    {
137da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        std::stringstream ss;
138da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
139da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateDeepFunctionStack(length, &ss);
140da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
141da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        ss << "void main() {\n"
142da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org           << "  gl_FragColor = vec4(0,0,0,0);\n"
143da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org           << "}";
144da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
145da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
146da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        return ss.str();
147da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
148da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
149da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Compiles a shader and if there's an error checks for a specific
150da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // substring in the error log. This way we know the error is specific
151da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // to the issue we are testing.
152da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    bool CheckShaderCompilation(ShHandle compiler,
153da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                                const char* source,
154da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                                int compileOptions,
155da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                                const char* expected_error) {
156da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        bool success = ShCompile(compiler, &source, 1, compileOptions);
157da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        if (success) {
158da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            success = !expected_error;
159da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        } else {
160da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            size_t bufferLen = 0;
161da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &bufferLen);
162da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            char* buffer(new char [bufferLen]);
163da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            ShGetInfoLog(compiler, buffer);
164da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            std::string log(buffer, buffer + bufferLen);
165da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            delete [] buffer;
166da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            if (expected_error)
167da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                success = log.find(expected_error) != std::string::npos;
168da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
169da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            EXPECT_TRUE(success) << log << "\n----shader----\n" << source;
170da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
171da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        return success;
172da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    }
173da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
174da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShBuiltInResources resources;
175da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org};
176da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
177da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgconst char* ExpressionLimitTest::kExpressionTooComplex =
178da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    "Expression too complex";
179da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgconst char* ExpressionLimitTest::kCallStackTooDeep =
180da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    "call stack too deep";
181da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgconst char* ExpressionLimitTest::kHasRecursion =
182da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    "Function recursion detected";
183da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
184da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgTEST_F(ExpressionLimitTest, ExpressionComplexity)
185da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org{
186da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderSpec spec = SH_WEBGL_SPEC;
187da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderOutput output = SH_ESSL_OUTPUT;
188da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShHandle vertexCompiler = ShConstructCompiler(
189da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        SH_FRAGMENT_SHADER, spec, output, &resources);
190da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    int compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
191da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
192da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test expression under the limit passes.
193da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
194da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
195da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithLongExpression(
196da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxExpressionComplexity - 10).c_str(),
197da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, NULL));
198da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test expression over the limit fails.
199da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
200da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
201da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithLongExpression(
202da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxExpressionComplexity + 10).c_str(),
203da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kExpressionTooComplex));
204da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test expression over the limit without a limit does not fail.
205da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
206da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
207da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithLongExpression(
208da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxExpressionComplexity + 10).c_str(),
209da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, NULL));
210da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org}
211da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
212da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgTEST_F(ExpressionLimitTest, UnusedExpressionComplexity)
213da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org{
214da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderSpec spec = SH_WEBGL_SPEC;
215da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderOutput output = SH_ESSL_OUTPUT;
216da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShHandle vertexCompiler = ShConstructCompiler(
217da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        SH_FRAGMENT_SHADER, spec, output, &resources);
218da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    int compileOptions = SH_LIMIT_EXPRESSION_COMPLEXITY;
219da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
220da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test expression under the limit passes.
221da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
222da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
223da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithUnusedLongExpression(
224da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxExpressionComplexity - 10).c_str(),
225da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, NULL));
226da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test expression over the limit fails.
227da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
228da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
229da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithUnusedLongExpression(
230da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxExpressionComplexity + 10).c_str(),
231da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kExpressionTooComplex));
232da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test expression over the limit without a limit does not fail.
233da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
234da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
235da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithUnusedLongExpression(
236da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxExpressionComplexity + 10).c_str(),
237da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions & ~SH_LIMIT_EXPRESSION_COMPLEXITY, NULL));
238da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org}
239da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
240da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgTEST_F(ExpressionLimitTest, CallStackDepth)
241da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org{
242da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderSpec spec = SH_WEBGL_SPEC;
243da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderOutput output = SH_ESSL_OUTPUT;
244da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShHandle vertexCompiler = ShConstructCompiler(
245da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        SH_FRAGMENT_SHADER, spec, output, &resources);
246da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    int compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
247da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
248da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test call stack under the limit passes.
249da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
250da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
251da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithDeepFunctionStack(
252da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxCallStackDepth - 10).c_str(),
253da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, NULL));
254da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test call stack over the limit fails.
255da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
256da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
257da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithDeepFunctionStack(
258da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxCallStackDepth + 10).c_str(),
259da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kCallStackTooDeep));
260da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test call stack over the limit without limit does not fail.
261da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
262da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
263da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithDeepFunctionStack(
264da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxCallStackDepth + 10).c_str(),
265da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, NULL));
266da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org}
267da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
268da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgTEST_F(ExpressionLimitTest, UnusedCallStackDepth)
269da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org{
270da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderSpec spec = SH_WEBGL_SPEC;
271da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderOutput output = SH_ESSL_OUTPUT;
272da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShHandle vertexCompiler = ShConstructCompiler(
273da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        SH_FRAGMENT_SHADER, spec, output, &resources);
274da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    int compileOptions = SH_LIMIT_CALL_STACK_DEPTH;
275da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
276da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test call stack under the limit passes.
277da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
278da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
279da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithUnusedDeepFunctionStack(
280da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxCallStackDepth - 10).c_str(),
281da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, NULL));
282da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test call stack over the limit fails.
283da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
284da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
285da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithUnusedDeepFunctionStack(
286da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxCallStackDepth + 10).c_str(),
287da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kCallStackTooDeep));
288da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Test call stack over the limit without limit does not fail.
289da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
290da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler,
291da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        GenerateShaderWithUnusedDeepFunctionStack(
292da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            kMaxCallStackDepth + 10).c_str(),
293da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions & ~SH_LIMIT_CALL_STACK_DEPTH, NULL));
294da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org}
295da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
296da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.orgTEST_F(ExpressionLimitTest, Recursion)
297da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org{
298da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderSpec spec = SH_WEBGL_SPEC;
299da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShShaderOutput output = SH_ESSL_OUTPUT;
300da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    ShHandle vertexCompiler = ShConstructCompiler(
301da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        SH_FRAGMENT_SHADER, spec, output, &resources);
302da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    int compileOptions = 0;
303da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
304da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion0 = SHADER(
305da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
306da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
307da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc()  {
308da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return someFunc();
309da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
310da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
311da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
312da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = u_color * someFunc();
313da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
314da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
315da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
316da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion1 = SHADER(
317da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
318da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
319da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
320da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc();
321da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
322da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc1()  {
323da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return someFunc();
324da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
325da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
326da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc()  {
327da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return someFunc1();
328da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
329da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
330da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
331da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = u_color * someFunc();
332da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
333da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
334da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
335da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion2 = SHADER(
336da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
337da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
338da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc()  {
339da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            if (u_color.x > 0.5) {
340da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                return someFunc();
341da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            } else {
342da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                return vec4(1);
343da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            }
344da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
345da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
346da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
347da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = someFunc();
348da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
349da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
350da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
351da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion3 = SHADER(
352da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
353da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
354da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc()  {
355da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            if (u_color.x > 0.5) {
356da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                return vec4(1);
357da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            } else {
358da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org                return someFunc();
359da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            }
360da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
361da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
362da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
363da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = someFunc();
364da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
365da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
366da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
367da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion4 = SHADER(
368da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
369da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
370da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc()  {
371da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return (u_color.x > 0.5) ? vec4(1) : someFunc();
372da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
373da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
374da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
375da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = someFunc();
376da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
377da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
378da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
379da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion5 = SHADER(
380da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
381da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
382da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc()  {
383da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return (u_color.x > 0.5) ? someFunc() : vec4(1);
384da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
385da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
386da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
387da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = someFunc();
388da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
389da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
390da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
391da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion6 = SHADER(
392da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
393da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
394da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 someFunc()  {
395da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return someFunc();
396da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
397da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
398da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
399da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = u_color;
400da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
401da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
402da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
403da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithNoRecursion = SHADER(
404da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
405da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
406da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
407da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec3 rgb(int r, int g, int b) {
408da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return vec3(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0);
409da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
410da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
411da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        // these external calls used to incorrectly trigger
412da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        // recursion detection.
413da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec3 hairColor0 = rgb(151, 200, 234);
414da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec3 faceColor2 = rgb(183, 148, 133);
415da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
416da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
417da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = u_color + vec4(hairColor0 + faceColor2, 0);
418da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
419da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
420da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
421da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion7 = SHADER(
422da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
423da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
424da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
425da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 function2() {
426da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return u_color;
427da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
428da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
429da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 function1() {
430da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            vec4 a = function2();
431da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            vec4 b = function1();
432da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return a + b;
433da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
434da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
435da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
436da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = function1();
437da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
438da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
439da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
440da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    static const char* shaderWithRecursion8 = SHADER(
441da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        precision mediump float;
442da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        uniform vec4 u_color;
443da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
444da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 function1();
445da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
446da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 function3() {
447da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return function1();
448da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
449da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
450da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 function2() {
451da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return function3();
452da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
453da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
454da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vec4 function1() {
455da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            return function2();
456da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
457da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
458da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        void main() {
459da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org            gl_FragColor = function1();
460da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        }
461da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    );
462da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
463da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check simple recursions fails.
464da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
465da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion0,
466da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
467da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check simple recursions fails.
468da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
469da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion1,
470da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
471da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check if recursions fails.
472da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
473da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion2,
474da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
475da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check if recursions fails.
476da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
477da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion3,
478da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
479da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check ternary recursions fails.
480da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
481da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion4,
482da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
483da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check ternary recursions fails.
484da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
485da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion5,
486da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
487da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check unused recursions passes.
488da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
489da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion6,
490da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, NULL));
491da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
492da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion7,
493da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
494da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
495da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion8,
496da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, kHasRecursion));
497da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check unused recursions fails if limiting call stack
498da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // since we check all paths.
499da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
500da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithRecursion6,
501da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions | SH_LIMIT_CALL_STACK_DEPTH, kHasRecursion));
502da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
503da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check unused recursions passes.
504da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
505da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithNoRecursion,
506da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions, NULL));
507da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    // Check unused recursions passes if limiting call stack.
508da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org    EXPECT_TRUE(CheckShaderCompilation(
509da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        vertexCompiler, shaderWithNoRecursion,
510da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org        compileOptions | SH_LIMIT_CALL_STACK_DEPTH, NULL));
511da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org}
512da8ea022340eba4899339874eefd5407612717b1shannonwoods@chromium.org
513