/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.0 Module
 * -------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Negative GL State API tests.
 *//*--------------------------------------------------------------------*/

#include "es31fNegativeStateApiTests.hpp"

#include "gluCallLogWrapper.hpp"
#include "gluContextInfo.hpp"
#include "gluShaderProgram.hpp"

#include "glwDefs.hpp"
#include "glwEnums.hpp"

#include "tcuStringTemplate.hpp"

#include "deMemory.h"

#include <string>
#include <map>

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace NegativeTestShared
{

using glu::CallLogWrapper;
using tcu::TestLog;
using namespace glw;

static const char *uniformTestVertSource = "${GLSL_VERSION_DECL}\n"
                                           "uniform mediump vec4 vUnif_vec4;\n"
                                           "in mediump vec4 attr;"
                                           "layout(shared) uniform Block { mediump vec4 blockVar; };\n"
                                           "void main (void)\n"
                                           "{\n"
                                           "    gl_Position = vUnif_vec4 + blockVar + attr;\n"
                                           "}\n\0";

static const char *uniformTestFragSource = "${GLSL_VERSION_DECL}\n"
                                           "uniform mediump ivec4 fUnif_ivec4;\n"
                                           "uniform mediump uvec4 fUnif_uvec4;\n"
                                           "layout(location = 0) out mediump vec4 fragColor;"
                                           "void main (void)\n"
                                           "{\n"
                                           "    fragColor = vec4(vec4(fUnif_ivec4) + vec4(fUnif_uvec4));\n"
                                           "}\n\0";

// Helper class that enables tests to be executed on GL4.5 context
// and removes code redundancy in each test that requires it.
class VAOHelper
{
public:
    VAOHelper(NegativeTestContext &ctx) : m_vao(0), m_ctx(ctx)
    {
        // tests need vao only for GL4.5 context
        if (glu::isContextTypeES(ctx.getRenderContext().getType()))
            return;

        m_ctx.glGenVertexArrays(1, &m_vao);
        m_ctx.glBindVertexArray(m_vao);
    }

    ~VAOHelper()
    {
        if (m_vao)
            m_ctx.glDeleteVertexArrays(1, &m_vao);
    }

private:
    GLuint m_vao;
    NegativeTestContext &m_ctx;
};

static std::string getVtxFragVersionSources(const std::string source, NegativeTestContext &ctx)
{
    const bool supportsES32 = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));

    std::map<std::string, std::string> args;

    args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) :
                                               getGLSLVersionDeclaration(glu::GLSL_VERSION_300_ES);

    return tcu::StringTemplate(source).specialize(args);
}

// Enabling & disabling states
void enable(NegativeTestContext &ctx)
{
    ctx.beginSection("GL_INVALID_ENUM is generated if cap is not one of the allowed values.");
    ctx.glEnable(-1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

static bool checkSupport(NegativeTestContext &ctx)
{
    return contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
           contextSupports(ctx.getRenderContext().getType(), glu::ApiType::core(4, 5));
}

// Enabling & disabling states
void enablei(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    ctx.beginSection("GL_INVALID_ENUM is generated if cap is not one of the allowed values.");
    ctx.glEnablei(-1, -1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated  if index is greater than or equal to the number of indexed "
                     "capabilities for cap.");
    ctx.glEnablei(GL_BLEND, -1);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void disable(NegativeTestContext &ctx)
{
    ctx.beginSection("GL_INVALID_ENUM is generated if cap is not one of the allowed values.");
    ctx.glDisable(-1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void disablei(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    ctx.beginSection("GL_INVALID_ENUM is generated if cap is not one of the allowed values.");
    ctx.glDisablei(-1, -1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated  if index is greater than or equal to the number of indexed "
                     "capabilities for cap.");
    ctx.glDisablei(GL_BLEND, -1);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

// Simple state queries
void get_booleanv(NegativeTestContext &ctx)
{
    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
    GLboolean params = GL_FALSE;
    ctx.glGetBooleanv(-1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_booleani_v(NegativeTestContext &ctx)
{
    GLboolean data                 = -1;
    GLint maxUniformBufferBindings = 0;

    ctx.beginSection("GL_INVALID_ENUM is generated if target is not indexed state queriable with these commands.");
    ctx.glGetBooleani_v(-1, 0, &data);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection(
        "GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
    ctx.glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetBooleani_v(GL_UNIFORM_BUFFER_BINDING, maxUniformBufferBindings, &data);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_floatv(NegativeTestContext &ctx)
{
    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
    GLfloat params = 0.0f;
    ctx.glGetFloatv(-1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_integerv(NegativeTestContext &ctx)
{
    GLint params = -1;
    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
    ctx.glGetIntegerv(-1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_integer64v(NegativeTestContext &ctx)
{
    GLint64 params = -1;
    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
    ctx.glGetInteger64v(-1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_integeri_v(NegativeTestContext &ctx)
{
    GLint data                           = -1;
    GLint maxUniformBufferBindings       = 0;
    GLint maxShaderStorageBufferBindings = 0;

    ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
    ctx.glGetIntegeri_v(-1, 0, &data);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection(
        "GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
    ctx.glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, maxUniformBufferBindings, &data);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection(
        "GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
    ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, maxShaderStorageBufferBindings, &data);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_integer64i_v(NegativeTestContext &ctx)
{
    GLint64 data                         = (GLint64)-1;
    GLint maxUniformBufferBindings       = 0;
    GLint maxShaderStorageBufferBindings = 0;

    ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
    ctx.glGetInteger64i_v(-1, 0, &data);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection(
        "GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
    ctx.glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetInteger64i_v(GL_UNIFORM_BUFFER_START, maxUniformBufferBindings, &data);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection(
        "GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
    ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetInteger64i_v(GL_SHADER_STORAGE_BUFFER_START, maxShaderStorageBufferBindings, &data);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.glGetInteger64i_v(GL_SHADER_STORAGE_BUFFER_SIZE, maxShaderStorageBufferBindings, &data);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_string(NegativeTestContext &ctx)
{
    ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
    ctx.glGetString(-1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_stringi(NegativeTestContext &ctx)
{
    GLint numExtensions = 0;

    ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
    ctx.glGetStringi(-1, 0);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is outside the valid range for indexed state name.");
    ctx.glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
    ctx.glGetStringi(GL_EXTENSIONS, numExtensions);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

// Enumerated state queries: Shaders

void get_attached_shaders(NegativeTestContext &ctx)
{
    GLuint shaders[1]   = {0};
    GLuint shaderObject = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLuint program      = ctx.glCreateProgram();
    GLsizei count[1]    = {0};

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetAttachedShaders(-1, 1, &count[0], &shaders[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetAttachedShaders(shaderObject, 1, &count[0], &shaders[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if maxCount is less than 0.");
    ctx.glGetAttachedShaders(program, -1, &count[0], &shaders[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glDeleteShader(shaderObject);
    ctx.glDeleteProgram(program);
}

void get_shaderiv(NegativeTestContext &ctx)
{
    GLboolean shaderCompilerSupported;
    GLuint shader  = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLuint program = ctx.glCreateProgram();
    GLint param[1] = {-1};

    ctx.glGetBooleanv(GL_SHADER_COMPILER, &shaderCompilerSupported);
    ctx.getLog() << TestLog::Message << "// GL_SHADER_COMPILER = " << (shaderCompilerSupported ? "GL_TRUE" : "GL_FALSE")
                 << TestLog::EndMessage;

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetShaderiv(shader, -1, &param[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
    ctx.glGetShaderiv(-1, GL_SHADER_TYPE, &param[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if shader does not refer to a shader object.");
    ctx.glGetShaderiv(program, GL_SHADER_TYPE, &param[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(program);
}

void get_shader_info_log(NegativeTestContext &ctx)
{
    GLuint shader     = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLuint program    = ctx.glCreateProgram();
    GLsizei length[1] = {-1};
    char infoLog[128] = {0};

    ctx.beginSection("GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
    ctx.glGetShaderInfoLog(-1, 128, &length[0], &infoLog[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if shader is not a shader object.");
    ctx.glGetShaderInfoLog(program, 128, &length[0], &infoLog[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if maxLength is less than 0.");
    ctx.glGetShaderInfoLog(shader, -1, &length[0], &infoLog[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(program);
}

void get_shader_precision_format(NegativeTestContext &ctx)
{
    GLboolean shaderCompilerSupported;
    GLint range[2];
    GLint precision[1];

    ctx.glGetBooleanv(GL_SHADER_COMPILER, &shaderCompilerSupported);
    ctx.getLog() << TestLog::Message << "// GL_SHADER_COMPILER = " << (shaderCompilerSupported ? "GL_TRUE" : "GL_FALSE")
                 << TestLog::EndMessage;

    deMemset(&range[0], 0xcd, sizeof(range));
    deMemset(&precision[0], 0xcd, sizeof(precision));

    ctx.beginSection("GL_INVALID_ENUM is generated if shaderType or precisionType is not an accepted value.");
    ctx.glGetShaderPrecisionFormat(-1, GL_MEDIUM_FLOAT, &range[0], &precision[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetShaderPrecisionFormat(GL_VERTEX_SHADER, -1, &range[0], &precision[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetShaderPrecisionFormat(-1, -1, &range[0], &precision[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_shader_source(NegativeTestContext &ctx)
{
    GLsizei length[1] = {0};
    char source[1]    = {0};
    GLuint program    = ctx.glCreateProgram();
    GLuint shader     = ctx.glCreateShader(GL_VERTEX_SHADER);

    ctx.beginSection("GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
    ctx.glGetShaderSource(-1, 1, &length[0], &source[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if shader is not a shader object.");
    ctx.glGetShaderSource(program, 1, &length[0], &source[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if bufSize is less than 0.");
    ctx.glGetShaderSource(shader, -1, &length[0], &source[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glDeleteProgram(program);
    ctx.glDeleteShader(shader);
}

// Enumerated state queries: Programs

void get_programiv(NegativeTestContext &ctx)
{
    GLuint program  = ctx.glCreateProgram();
    GLuint shader   = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLint params[1] = {0};

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetProgramiv(program, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetProgramiv(-1, GL_LINK_STATUS, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program does not refer to a program object.");
    ctx.glGetProgramiv(shader, GL_LINK_STATUS, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteProgram(program);
    ctx.glDeleteShader(shader);
}

void get_program_info_log(NegativeTestContext &ctx)
{
    GLuint program    = ctx.glCreateProgram();
    GLuint shader     = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLsizei length[1] = {0};
    char infoLog[1]   = {'x'};

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetProgramInfoLog(-1, 1, &length[0], &infoLog[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetProgramInfoLog(shader, 1, &length[0], &infoLog[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if maxLength is less than 0.");
    ctx.glGetProgramInfoLog(program, -1, &length[0], &infoLog[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glDeleteProgram(program);
    ctx.glDeleteShader(shader);
}

// Enumerated state queries: Shader variables

void get_tex_parameterfv(NegativeTestContext &ctx)
{
    GLfloat params[1] = {0};

    ctx.beginSection("GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
    ctx.glGetTexParameterfv(-1, GL_TEXTURE_MAG_FILTER, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameterfv(GL_TEXTURE_2D, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameterfv(-1, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_tex_parameteriv(NegativeTestContext &ctx)
{
    GLint params[1] = {0};

    ctx.beginSection("GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
    ctx.glGetTexParameteriv(-1, GL_TEXTURE_MAG_FILTER, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameteriv(GL_TEXTURE_2D, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameteriv(-1, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_tex_parameteriiv(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    GLint params[1] = {0};

    ctx.beginSection("GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
    ctx.glGetTexParameterIiv(-1, GL_TEXTURE_MAG_FILTER, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameterIiv(GL_TEXTURE_2D, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameterIiv(-1, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_tex_parameteriuiv(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    GLuint params[1] = {0};

    ctx.beginSection("GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
    ctx.glGetTexParameterIuiv(-1, GL_TEXTURE_MAG_FILTER, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameterIuiv(GL_TEXTURE_2D, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetTexParameterIuiv(-1, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_uniformfv(NegativeTestContext &ctx)
{
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLfloat params[4] = {0.f};
    GLuint shader;
    GLuint programEmpty;
    GLint unif;

    ctx.glUseProgram(program.getProgram());

    unif = ctx.glGetUniformLocation(program.getProgram(), "vUnif_vec4"); // vec4
    if (unif == -1)
        ctx.fail("Failed to retrieve uniform location");

    shader       = ctx.glCreateShader(GL_VERTEX_SHADER);
    programEmpty = ctx.glCreateProgram();

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetUniformfv(-1, unif, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetUniformfv(shader, unif, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program has not been successfully linked.");
    ctx.glGetUniformfv(programEmpty, unif, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable "
                     "location for the specified program object.");
    ctx.glGetUniformfv(program.getProgram(), -1, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(programEmpty);
}

void get_nuniformfv(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint unif        = ctx.glGetUniformLocation(program.getProgram(), "vUnif_vec4");
    GLfloat params[4] = {0.0f, 0.0f, 0.0f, 0.0f};
    GLuint shader;
    GLuint programEmpty;
    GLsizei bufferSize;

    ctx.glUseProgram(program.getProgram());

    if (unif == -1)
        ctx.fail("Failed to retrieve uniform location");

    shader       = ctx.glCreateShader(GL_VERTEX_SHADER);
    programEmpty = ctx.glCreateProgram();

    ctx.glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &bufferSize);

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetnUniformfv(-1, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetnUniformfv(shader, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program has not been successfully linked.");
    ctx.glGetnUniformfv(programEmpty, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable "
                     "location for the specified program object.");
    ctx.glGetnUniformfv(program.getProgram(), -1, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if the buffer size required to store the requested data is "
                     "greater than bufSize.");
    ctx.glGetnUniformfv(program.getProgram(), unif, 0, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(programEmpty);
}

void get_uniformiv(NegativeTestContext &ctx)
{
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint unif      = ctx.glGetUniformLocation(program.getProgram(), "fUnif_ivec4");
    GLint params[4] = {0, 0, 0, 0};
    GLuint shader;
    GLuint programEmpty;

    ctx.glUseProgram(program.getProgram());

    if (unif == -1)
        ctx.fail("Failed to retrieve uniform location");

    shader       = ctx.glCreateShader(GL_VERTEX_SHADER);
    programEmpty = ctx.glCreateProgram();

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetUniformiv(-1, unif, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetUniformiv(shader, unif, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program has not been successfully linked.");
    ctx.glGetUniformiv(programEmpty, unif, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable "
                     "location for the specified program object.");
    ctx.glGetUniformiv(program.getProgram(), -1, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(programEmpty);
}

void get_nuniformiv(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint unif      = ctx.glGetUniformLocation(program.getProgram(), "fUnif_ivec4");
    GLint params[4] = {0, 0, 0, 0};
    GLuint shader;
    GLuint programEmpty;
    GLsizei bufferSize;

    ctx.glUseProgram(program.getProgram());

    if (unif == -1)
        ctx.fail("Failed to retrieve uniform location");

    shader       = ctx.glCreateShader(GL_VERTEX_SHADER);
    programEmpty = ctx.glCreateProgram();

    ctx.glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &bufferSize);

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetnUniformiv(-1, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetnUniformiv(shader, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program has not been successfully linked.");
    ctx.glGetnUniformiv(programEmpty, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable "
                     "location for the specified program object.");
    ctx.glGetnUniformiv(program.getProgram(), -1, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if the buffer size required to store the requested data is "
                     "greater than bufSize.");
    ctx.glGetnUniformiv(program.getProgram(), unif, -1, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(programEmpty);
}

void get_uniformuiv(NegativeTestContext &ctx)
{
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint unif       = ctx.glGetUniformLocation(program.getProgram(), "fUnif_uvec4");
    GLuint params[4] = {0, 0, 0, 0};
    GLuint shader;
    GLuint programEmpty;

    ctx.glUseProgram(program.getProgram());

    if (unif == -1)
        ctx.fail("Failed to retrieve uniform location");

    shader       = ctx.glCreateShader(GL_VERTEX_SHADER);
    programEmpty = ctx.glCreateProgram();

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetUniformuiv(-1, unif, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetUniformuiv(shader, unif, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program has not been successfully linked.");
    ctx.glGetUniformuiv(programEmpty, unif, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable "
                     "location for the specified program object.");
    ctx.glGetUniformuiv(program.getProgram(), -1, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(programEmpty);
}

void get_nuniformuiv(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint unif       = ctx.glGetUniformLocation(program.getProgram(), "fUnif_ivec4");
    GLuint params[4] = {0, 0, 0, 0};
    GLuint shader;
    GLuint programEmpty;
    GLsizei bufferSize;

    ctx.glUseProgram(program.getProgram());

    if (unif == -1)
        ctx.fail("Failed to retrieve uniform location");

    shader       = ctx.glCreateShader(GL_VERTEX_SHADER);
    programEmpty = ctx.glCreateProgram();

    ctx.glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &bufferSize);

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetnUniformuiv(-1, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetnUniformuiv(shader, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program has not been successfully linked.");
    ctx.glGetnUniformuiv(programEmpty, unif, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable "
                     "location for the specified program object.");
    ctx.glGetnUniformuiv(program.getProgram(), -1, bufferSize, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if the buffer size required to store the requested data is "
                     "greater than bufSize.");
    ctx.glGetnUniformuiv(program.getProgram(), unif, -1, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteShader(shader);
    ctx.glDeleteProgram(programEmpty);
}

void get_active_uniform(NegativeTestContext &ctx)
{
    GLuint shader = ctx.glCreateShader(GL_VERTEX_SHADER);
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint numActiveUniforms = -1;

    ctx.glGetProgramiv(program.getProgram(), GL_ACTIVE_UNIFORMS, &numActiveUniforms);
    ctx.getLog() << TestLog::Message << "// GL_ACTIVE_UNIFORMS = " << numActiveUniforms << " (expected 4)."
                 << TestLog::EndMessage;

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetActiveUniform(-1, 0, 0, 0, 0, 0, 0);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetActiveUniform(shader, 0, 0, 0, 0, 0, 0);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to the number of active uniform "
                     "variables in program.");
    ctx.glUseProgram(program.getProgram());
    ctx.glGetActiveUniform(program.getProgram(), numActiveUniforms, 0, 0, 0, 0, 0);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if bufSize is less than 0.");
    ctx.glGetActiveUniform(program.getProgram(), 0, -1, 0, 0, 0, 0);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glUseProgram(0);
    ctx.glDeleteShader(shader);
}

void get_active_uniformsiv(NegativeTestContext &ctx)
{
    GLuint shader = ctx.glCreateShader(GL_VERTEX_SHADER);
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLuint unusedUniformIndex = 1;
    GLint unusedParamDst      = -1;
    GLint numActiveUniforms   = -1;

    ctx.glUseProgram(program.getProgram());

    ctx.glGetProgramiv(program.getProgram(), GL_ACTIVE_UNIFORMS, &numActiveUniforms);
    ctx.getLog() << TestLog::Message << "// GL_ACTIVE_UNIFORMS = " << numActiveUniforms << " (expected 4)."
                 << TestLog::EndMessage;

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetActiveUniformsiv(-1, 1, &unusedUniformIndex, GL_UNIFORM_TYPE, &unusedParamDst);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetActiveUniformsiv(shader, 1, &unusedUniformIndex, GL_UNIFORM_TYPE, &unusedParamDst);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if any value in uniformIndices is greater than or equal to the "
                     "value of GL_ACTIVE_UNIFORMS for program.");
    for (int excess = 0; excess <= 2; excess++)
    {
        std::vector<GLuint> invalidUniformIndices;
        invalidUniformIndices.push_back(1);
        invalidUniformIndices.push_back(numActiveUniforms - 1 + excess);
        invalidUniformIndices.push_back(1);

        std::vector<GLint> unusedParamsDst(invalidUniformIndices.size());
        ctx.glGetActiveUniformsiv(program.getProgram(), (GLsizei)invalidUniformIndices.size(),
                                  &invalidUniformIndices[0], GL_UNIFORM_TYPE, &unusedParamsDst[0]);
        ctx.expectError(excess == 0 ? GL_NO_ERROR : GL_INVALID_VALUE);
    }
    ctx.endSection();

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted token.");
    ctx.glGetActiveUniformsiv(program.getProgram(), 1, &unusedUniformIndex, -1, &unusedParamDst);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.glUseProgram(0);
    ctx.glDeleteShader(shader);
}

void get_active_uniform_blockiv(NegativeTestContext &ctx)
{
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLuint shader         = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLint params          = -1;
    GLint numActiveBlocks = -1;

    ctx.glGetProgramiv(program.getProgram(), GL_ACTIVE_UNIFORM_BLOCKS, &numActiveBlocks);
    ctx.getLog() << TestLog::Message << "// GL_ACTIVE_UNIFORM_BLOCKS = " << numActiveBlocks << " (expected 1)."
                 << TestLog::EndMessage;
    ctx.expectError(GL_NO_ERROR);

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not the name of either a program or shader object.");
    ctx.glGetActiveUniformBlockiv(-1, 0, GL_UNIFORM_BLOCK_BINDING, &params);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is the name of a shader object");
    ctx.glGetActiveUniformBlockiv(shader, 0, GL_UNIFORM_BLOCK_BINDING, &params);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if uniformBlockIndex is greater than or equal to the value of "
                     "GL_ACTIVE_UNIFORM_BLOCKS or is not the index of an active uniform block in program.");
    ctx.glUseProgram(program.getProgram());
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetActiveUniformBlockiv(program.getProgram(), numActiveBlocks, GL_UNIFORM_BLOCK_BINDING, &params);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not one of the accepted tokens.");
    ctx.glGetActiveUniformBlockiv(program.getProgram(), 0, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.glUseProgram(0);
}

void get_active_uniform_block_name(NegativeTestContext &ctx)
{
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLuint shader         = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLsizei length        = -1;
    GLint numActiveBlocks = -1;
    GLchar uniformBlockName[128];

    deMemset(&uniformBlockName[0], 0, sizeof(uniformBlockName));

    ctx.glGetProgramiv(program.getProgram(), GL_ACTIVE_UNIFORM_BLOCKS, &numActiveBlocks);
    ctx.getLog() << TestLog::Message << "// GL_ACTIVE_UNIFORM_BLOCKS = " << numActiveBlocks << " (expected 1)."
                 << TestLog::EndMessage;
    ctx.expectError(GL_NO_ERROR);

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is the name of a shader object.");
    ctx.glGetActiveUniformBlockName(shader, numActiveBlocks, GL_UNIFORM_BLOCK_BINDING, &length, &uniformBlockName[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not the name of either a program or shader object.");
    ctx.glGetActiveUniformBlockName(-1, numActiveBlocks, GL_UNIFORM_BLOCK_BINDING, &length, &uniformBlockName[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if uniformBlockIndex is greater than or equal to the value of "
                     "GL_ACTIVE_UNIFORM_BLOCKS or is not the index of an active uniform block in program.");
    ctx.glUseProgram(program.getProgram());
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetActiveUniformBlockName(program.getProgram(), numActiveBlocks, (int)sizeof(uniformBlockName), &length,
                                    &uniformBlockName[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glUseProgram(0);
}

void get_active_attrib(NegativeTestContext &ctx)
{
    GLuint shader = ctx.glCreateShader(GL_VERTEX_SHADER);
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint numActiveAttributes = -1;
    GLsizei length            = -1;
    GLint size                = -1;
    GLenum type               = -1;
    GLchar name[32];

    deMemset(&name[0], 0, sizeof(name));

    ctx.glGetProgramiv(program.getProgram(), GL_ACTIVE_ATTRIBUTES, &numActiveAttributes);
    ctx.getLog() << TestLog::Message << "// GL_ACTIVE_ATTRIBUTES = " << numActiveAttributes << " (expected 1)."
                 << TestLog::EndMessage;

    ctx.glUseProgram(program.getProgram());

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
    ctx.glGetActiveAttrib(-1, 0, 32, &length, &size, &type, &name[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is not a program object.");
    ctx.glGetActiveAttrib(shader, 0, 32, &length, &size, &type, &name[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_ACTIVE_ATTRIBUTES.");
    ctx.glGetActiveAttrib(program.getProgram(), numActiveAttributes, (int)sizeof(name), &length, &size, &type,
                          &name[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if bufSize is less than 0.");
    ctx.glGetActiveAttrib(program.getProgram(), 0, -1, &length, &size, &type, &name[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glUseProgram(0);
    ctx.glDeleteShader(shader);
}

void get_uniform_indices(NegativeTestContext &ctx)
{
    GLuint shader = ctx.glCreateShader(GL_VERTEX_SHADER);
    glu::ShaderProgram program(ctx.getRenderContext(),
                               glu::makeVtxFragSources(getVtxFragVersionSources(uniformTestVertSource, ctx),
                                                       getVtxFragVersionSources(uniformTestFragSource, ctx)));
    GLint numActiveBlocks     = -1;
    const GLchar *uniformName = "Block.blockVar";
    GLuint uniformIndices     = -1;
    GLuint invalid            = -1;

    ctx.glGetProgramiv(program.getProgram(), GL_ACTIVE_UNIFORM_BLOCKS, &numActiveBlocks);
    ctx.getLog() << TestLog::Message << "// GL_ACTIVE_UNIFORM_BLOCKS = " << numActiveBlocks << TestLog::EndMessage;
    ctx.expectError(GL_NO_ERROR);

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is a name of shader object.");
    ctx.glGetUniformIndices(shader, 1, &uniformName, &uniformIndices);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if program is not name of program or shader object.");
    ctx.glGetUniformIndices(invalid, 1, &uniformName, &uniformIndices);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glUseProgram(0);
    ctx.glDeleteShader(shader);
}

void get_vertex_attribfv(NegativeTestContext &ctx)
{
    GLfloat params = 0.0f;
    GLint maxVertexAttribs;
    VAOHelper vao(ctx);

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetVertexAttribfv(0, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
    ctx.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    ctx.glGetVertexAttribfv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_vertex_attribiv(NegativeTestContext &ctx)
{
    GLint params = -1;
    GLint maxVertexAttribs;
    VAOHelper vao(ctx);

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetVertexAttribiv(0, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
    ctx.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    ctx.glGetVertexAttribiv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_vertex_attribi_iv(NegativeTestContext &ctx)
{
    GLint params = -1;
    GLint maxVertexAttribs;
    VAOHelper vao(ctx);

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetVertexAttribIiv(0, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
    ctx.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    ctx.glGetVertexAttribIiv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_vertex_attribi_uiv(NegativeTestContext &ctx)
{
    GLuint params = (GLuint)-1;
    GLint maxVertexAttribs;
    VAOHelper vao(ctx);

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetVertexAttribIuiv(0, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
    ctx.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    ctx.glGetVertexAttribIuiv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_vertex_attrib_pointerv(NegativeTestContext &ctx)
{
    GLvoid *ptr[1] = {DE_NULL};
    GLint maxVertexAttribs;

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetVertexAttribPointerv(0, -1, &ptr[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
    ctx.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
    ctx.glGetVertexAttribPointerv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

void get_frag_data_location(NegativeTestContext &ctx)
{
    GLuint shader  = ctx.glCreateShader(GL_VERTEX_SHADER);
    GLuint program = ctx.glCreateProgram();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program is the name of a shader object.");
    ctx.glGetFragDataLocation(shader, "gl_FragColor");
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if program has not been linked.");
    ctx.glGetFragDataLocation(program, "gl_FragColor");
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteProgram(program);
    ctx.glDeleteShader(shader);
}

// Enumerated state queries: Buffers

void get_buffer_parameteriv(NegativeTestContext &ctx)
{
    GLint params = -1;
    GLuint buf;
    ctx.glGenBuffers(1, &buf);
    ctx.glBindBuffer(GL_ARRAY_BUFFER, buf);

    ctx.beginSection("GL_INVALID_ENUM is generated if target or value is not an accepted value.");
    ctx.glGetBufferParameteriv(-1, GL_BUFFER_SIZE, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetBufferParameteriv(GL_ARRAY_BUFFER, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetBufferParameteriv(-1, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
    ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
    ctx.glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &params);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteBuffers(1, &buf);
}

void get_buffer_parameteri64v(NegativeTestContext &ctx)
{
    GLint64 params = -1;
    GLuint buf;
    ctx.glGenBuffers(1, &buf);
    ctx.glBindBuffer(GL_ARRAY_BUFFER, buf);

    ctx.beginSection("GL_INVALID_ENUM is generated if target or value is not an accepted value.");
    ctx.glGetBufferParameteri64v(-1, GL_BUFFER_SIZE, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetBufferParameteri64v(GL_ARRAY_BUFFER, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetBufferParameteri64v(-1, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
    ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
    ctx.glGetBufferParameteri64v(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &params);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteBuffers(1, &buf);
}

void get_buffer_pointerv(NegativeTestContext &ctx)
{
    GLvoid *params = DE_NULL;
    GLuint buf;
    ctx.glGenBuffers(1, &buf);
    ctx.glBindBuffer(GL_ARRAY_BUFFER, buf);

    ctx.beginSection("GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
    ctx.glGetBufferPointerv(GL_ARRAY_BUFFER, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetBufferPointerv(-1, GL_BUFFER_MAP_POINTER, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
    ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
    ctx.glGetBufferPointerv(GL_ARRAY_BUFFER, GL_BUFFER_MAP_POINTER, &params);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteBuffers(1, &buf);
}

void get_framebuffer_attachment_parameteriv(NegativeTestContext &ctx)
{
    GLint params[1] = {-1};
    GLuint fbo;
    GLuint rbo[2];

    ctx.glGenFramebuffers(1, &fbo);
    ctx.glGenRenderbuffers(2, rbo);

    ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    ctx.glBindRenderbuffer(GL_RENDERBUFFER, rbo[0]);
    ctx.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 16, 16);
    ctx.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo[0]);
    ctx.glBindRenderbuffer(GL_RENDERBUFFER, rbo[1]);
    ctx.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 16, 16);
    ctx.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
    ctx.glCheckFramebufferStatus(GL_FRAMEBUFFER);
    ctx.expectError(GL_NO_ERROR);

    ctx.beginSection("GL_INVALID_ENUM is generated if target is not one of the accepted tokens.");
    ctx.glGetFramebufferAttachmentParameteriv(-1, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
                                              &params[0]); // TYPE is GL_RENDERBUFFER
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection(
        "GL_INVALID_ENUM is generated if pname is not valid for the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE.");
    ctx.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                              GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
                                              &params[0]); // TYPE is GL_RENDERBUFFER
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glBindFramebuffer(GL_FRAMEBUFFER, 0);

    ctx.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_BACK, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
                                              &params[0]); // TYPE is GL_FRAMEBUFFER_DEFAULT
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if attachment is GL_DEPTH_STENCIL_ATTACHMENT and different "
                     "objects are bound to the depth and stencil attachment points of target.");
    ctx.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
                     "GL_NONE and pname is not GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME.");
    ctx.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &params[0]); // TYPE is GL_NONE
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                              GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, &params[0]); // TYPE is GL_NONE
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION or GL_INVALID_ENUM is generated if attachment is not one of the accepted "
                     "values for the current binding of target.");
    ctx.glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_BACK, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
                                              &params[0]); // A FBO is bound so GL_BACK is invalid
    ctx.expectError(GL_INVALID_OPERATION, GL_INVALID_ENUM);
    ctx.glBindFramebuffer(GL_FRAMEBUFFER, 0);
    ctx.glGetFramebufferAttachmentParameteriv(
        GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
        &params[0]); // Default framebuffer is bound so GL_COLOR_ATTACHMENT0 is invalid
    ctx.expectError(GL_INVALID_OPERATION, GL_INVALID_ENUM);
    ctx.endSection();

    ctx.glDeleteFramebuffers(1, &fbo);
}

void get_renderbuffer_parameteriv(NegativeTestContext &ctx)
{
    GLint params[1] = {-1};
    GLuint rbo;
    ctx.glGenRenderbuffers(1, &rbo);
    ctx.glBindRenderbuffer(GL_RENDERBUFFER, rbo);

    ctx.beginSection("GL_INVALID_ENUM is generated if target is not GL_RENDERBUFFER.");
    ctx.glGetRenderbufferParameteriv(-1, GL_RENDERBUFFER_WIDTH, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not one of the accepted tokens.");
    ctx.glGetRenderbufferParameteriv(GL_RENDERBUFFER, -1, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION  is generated if the renderbuffer currently bound to target is zero.");
    ctx.glBindRenderbuffer(GL_RENDERBUFFER, 0);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &params[0]);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glDeleteRenderbuffers(1, &rbo);
    ctx.glBindRenderbuffer(GL_RENDERBUFFER, 0);
}

void get_internalformativ(NegativeTestContext &ctx)
{
    const bool isES = glu::isContextTypeES(ctx.getRenderContext().getType());
    GLint params[16];

    deMemset(&params[0], 0xcd, sizeof(params));

    ctx.beginSection("GL_INVALID_VALUE is generated if bufSize is negative.");
    ctx.glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, -1, &params[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not GL_SAMPLES or GL_NUM_SAMPLE_COUNTS.");
    ctx.glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, -1, 16, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_ENUM is generated if internalformat is not color-, depth-, or stencil-renderable.");

    if (isES)
    {
        if (!ctx.getContextInfo().isExtensionSupported("GL_EXT_render_snorm"))
        {
            ctx.glGetInternalformativ(GL_RENDERBUFFER, GL_RG8_SNORM, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
            ctx.expectError(GL_INVALID_ENUM);
        }

        ctx.glGetInternalformativ(GL_RENDERBUFFER, GL_COMPRESSED_RGB8_ETC2, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
        ctx.expectError(GL_INVALID_ENUM);
        ctx.endSection();
    }

    ctx.beginSection("GL_INVALID_ENUM is generated if target is not GL_RENDERBUFFER.");
    ctx.glGetInternalformativ(-1, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetInternalformativ(GL_FRAMEBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
    ctx.expectError(GL_INVALID_ENUM);

    if (isES && !ctx.getContextInfo().isExtensionSupported("GL_EXT_sparse_texture"))
    {
        ctx.glGetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
        ctx.expectError(GL_INVALID_ENUM);
    }

    ctx.endSection();
}

// Query object queries

void get_queryiv(NegativeTestContext &ctx)
{
    GLint params = -1;

    ctx.beginSection("GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
    ctx.glGetQueryiv(GL_ANY_SAMPLES_PASSED, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetQueryiv(-1, GL_CURRENT_QUERY, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glGetQueryiv(-1, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void get_query_objectuiv(NegativeTestContext &ctx)
{
    GLuint params = -1;
    GLuint id;
    ctx.glGenQueries(1, &id);

    ctx.beginSection("GL_INVALID_OPERATION is generated if id is not the name of a query object.");
    ctx.glGetQueryObjectuiv(-1, GL_QUERY_RESULT_AVAILABLE, &params);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.getLog() << TestLog::Message << "// Note: " << id
                 << " is not a query object yet, since it hasn't been used by glBeginQuery" << TestLog::EndMessage;
    ctx.glGetQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &params);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.endSection();

    ctx.glBeginQuery(GL_ANY_SAMPLES_PASSED, id);
    ctx.glEndQuery(GL_ANY_SAMPLES_PASSED);

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not an accepted value.");
    ctx.glGetQueryObjectuiv(id, -1, &params);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_OPERATION is generated if id is the name of a currently active query object.");
    ctx.glBeginQuery(GL_ANY_SAMPLES_PASSED, id);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &params);
    ctx.expectError(GL_INVALID_OPERATION);
    ctx.glEndQuery(GL_ANY_SAMPLES_PASSED);
    ctx.expectError(GL_NO_ERROR);
    ctx.endSection();

    ctx.glDeleteQueries(1, &id);
}

// Sync object queries

void get_synciv(NegativeTestContext &ctx)
{
    GLsizei length = -1;
    GLint values[32];
    GLsync sync;

    deMemset(&values[0], 0xcd, sizeof(values));

    ctx.beginSection("GL_INVALID_VALUE is generated if sync is not the name of a sync object.");
    ctx.glGetSynciv(0, GL_OBJECT_TYPE, 32, &length, &values[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_ENUM is generated if pname is not one of the accepted tokens.");
    sync = ctx.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetSynciv(sync, -1, 32, &length, &values[0]);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.glDeleteSync(sync);

    ctx.beginSection("GL_INVALID_VALUE is generated if bufSize is negative.");
    sync = ctx.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
    ctx.expectError(GL_NO_ERROR);
    ctx.glGetSynciv(sync, GL_OBJECT_TYPE, -1, &length, &values[0]);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();

    ctx.glDeleteSync(sync);
}

// Enumerated boolean state queries

void is_enabled(NegativeTestContext &ctx)
{
    ctx.beginSection("GL_INVALID_ENUM is generated if cap is not an accepted value.");
    ctx.glIsEnabled(-1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glIsEnabled(GL_TRIANGLES);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

void is_enabledi(NegativeTestContext &ctx)
{
    TCU_CHECK_AND_THROW(NotSupportedError, checkSupport(ctx), "This test requires a higher context version.");

    ctx.beginSection("GL_INVALID_ENUM is generated if cap is not an accepted value.");
    ctx.glIsEnabledi(-1, 1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glIsEnabledi(GL_TRIANGLES, 1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();

    ctx.beginSection("GL_INVALID_VALUE is generated if index is outside the valid range for the indexed state cap.");
    ctx.glIsEnabledi(GL_BLEND, -1);
    ctx.expectError(GL_INVALID_VALUE);
    ctx.endSection();
}

// Hints

void hint(NegativeTestContext &ctx)
{
    ctx.beginSection("GL_INVALID_ENUM is generated if either target or mode is not an accepted value.");
    ctx.glHint(GL_GENERATE_MIPMAP_HINT, -1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glHint(-1, GL_FASTEST);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.glHint(-1, -1);
    ctx.expectError(GL_INVALID_ENUM);
    ctx.endSection();
}

std::vector<FunctionContainer> getNegativeStateApiTestFunctions()
{
    const FunctionContainer funcs[] = {
        {enable, "enable", "Invalid glEnable() usage"},
        {disable, "disable", "Invalid glDisable() usage"},
        {get_booleanv, "get_booleanv", "Invalid glGetBooleanv() usage"},
        {get_floatv, "get_floatv", "Invalid glGetFloatv() usage"},
        {get_integerv, "get_integerv", "Invalid glGetIntegerv() usage"},
        {get_integer64v, "get_integer64v", "Invalid glGetInteger64v() usage"},
        {get_integeri_v, "get_integeri_v", "Invalid glGetIntegeri_v() usage"},
        {get_booleani_v, "get_booleani_v", "Invalid glGetBooleani_v() usage"},
        {get_integer64i_v, "get_integer64i_v", "Invalid glGetInteger64i_v() usage"},
        {get_string, "get_string", "Invalid glGetString() usage"},
        {get_stringi, "get_stringi", "Invalid glGetStringi() usage"},
        {get_attached_shaders, "get_attached_shaders", "Invalid glGetAttachedShaders() usage"},
        {get_shaderiv, "get_shaderiv", "Invalid glGetShaderiv() usage"},
        {get_shader_info_log, "get_shader_info_log", "Invalid glGetShaderInfoLog() usage"},
        {get_shader_precision_format, "get_shader_precision_format", "Invalid glGetShaderPrecisionFormat() usage"},
        {get_shader_source, "get_shader_source", "Invalid glGetShaderSource() usage"},
        {get_programiv, "get_programiv", "Invalid glGetProgramiv() usage"},
        {get_program_info_log, "get_program_info_log", "Invalid glGetProgramInfoLog() usage"},
        {get_tex_parameterfv, "get_tex_parameterfv", "Invalid glGetTexParameterfv() usage"},
        {get_tex_parameteriv, "get_tex_parameteriv", "Invalid glGetTexParameteriv() usage"},
        {get_uniformfv, "get_uniformfv", "Invalid glGetUniformfv() usage"},
        {get_uniformiv, "get_uniformiv", "Invalid glGetUniformiv() usage"},
        {get_uniformuiv, "get_uniformuiv", "Invalid glGetUniformuiv() usage"},
        {get_active_uniform, "get_active_uniform", "Invalid glGetActiveUniform() usage"},
        {get_active_uniformsiv, "get_active_uniformsiv", "Invalid glGetActiveUniformsiv() usage"},
        {get_active_uniform_blockiv, "get_active_uniform_blockiv", "Invalid glGetActiveUniformBlockiv() usage"},
        {get_active_uniform_block_name, "get_active_uniform_block_name", "Invalid glGetActiveUniformBlockName() usage"},
        {get_active_attrib, "get_active_attrib", "Invalid glGetActiveAttrib() usage"},
        {get_uniform_indices, "get_uniform_indices", "Invalid glGetUniformIndices() usage"},
        {get_vertex_attribfv, "get_vertex_attribfv", "Invalid glGetVertexAttribfv() usage"},
        {get_vertex_attribiv, "get_vertex_attribiv", "Invalid glGetVertexAttribiv() usage"},
        {get_vertex_attribi_iv, "get_vertex_attribi_iv", "Invalid glGetVertexAttribIiv() usage"},
        {get_vertex_attribi_uiv, "get_vertex_attribi_uiv", "Invalid glGetVertexAttribIuiv() usage"},
        {get_vertex_attrib_pointerv, "get_vertex_attrib_pointerv", "Invalid glGetVertexAttribPointerv() usage"},
        {get_frag_data_location, "get_frag_data_location", "Invalid glGetFragDataLocation() usage"},
        {get_buffer_parameteriv, "get_buffer_parameteriv", "Invalid glGetBufferParameteriv() usage"},
        {get_buffer_parameteri64v, "get_buffer_parameteri64v", "Invalid glGetBufferParameteri64v() usage"},
        {get_buffer_pointerv, "get_buffer_pointerv", "Invalid glGetBufferPointerv() usage"},
        {get_framebuffer_attachment_parameteriv, "get_framebuffer_attachment_parameteriv",
         "Invalid glGetFramebufferAttachmentParameteriv() usage"},
        {get_renderbuffer_parameteriv, "get_renderbuffer_parameteriv", "Invalid glGetRenderbufferParameteriv() usage"},
        {get_internalformativ, "get_internalformativ", "Invalid glGetInternalformativ() usage"},
        {get_queryiv, "get_queryiv", "Invalid glGetQueryiv() usage"},
        {get_query_objectuiv, "get_query_objectuiv", "Invalid glGetQueryObjectuiv() usage"},
        {get_synciv, "get_synciv", "Invalid glGetSynciv() usage"},
        {is_enabled, "is_enabled", "Invalid glIsEnabled() usage"},
        {hint, "hint", "Invalid glHint() usage"},
        {enablei, "enablei", "Invalid glEnablei() usage"},
        {disablei, "disablei", "Invalid glDisablei() usage"},
        {get_tex_parameteriiv, "get_tex_parameteriiv", "Invalid glGetTexParameterIiv() usage"},
        {get_tex_parameteriuiv, "get_tex_parameteriuiv", "Invalid glGetTexParameterIuiv() usage"},
        {get_nuniformfv, "get_nuniformfv", "Invalid glGetnUniformfv() usage"},
        {get_nuniformiv, "get_nuniformiv", "Invalid glGetnUniformiv() usage"},
        {get_nuniformuiv, "get_nuniformuiv", "Invalid glGetnUniformuiv() usage"},
        {is_enabledi, "is_enabledi", "Invalid glIsEnabledi() usage"},
    };

    return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
}

} // namespace NegativeTestShared
} // namespace Functional
} // namespace gles31
} // namespace deqp
