/*-------------------------------------------------------------------------
 * 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 "es3fNegativeStateApiTests.hpp"
#include "es3fApiCase.hpp"
#include "gluShaderProgram.hpp"
#include "gluContextInfo.hpp"
#include "deMemory.h"

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

using namespace glw; // GL types

namespace deqp
{
namespace gles3
{
namespace Functional
{

using tcu::TestLog;

static const char* uniformTestVertSource	=	"#version 300 es\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	=	"#version 300 es\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";

NegativeStateApiTests::NegativeStateApiTests (Context& context)
	: TestCaseGroup(context, "state", "Negative GL State API Cases")
{
}

NegativeStateApiTests::~NegativeStateApiTests (void)
{
}

void NegativeStateApiTests::init (void)
{
	// Enabling & disabling states

	ES3F_ADD_API_CASE(enable, "Invalid glEnable() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if cap is not one of the allowed values.");
			glEnable(-1);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(disable, "Invalid glDisable() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if cap is not one of the allowed values.");
			glDisable(-1);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});

	// Simple state queries

	ES3F_ADD_API_CASE(get_booleanv, "Invalid glGetBooleanv() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
			GLboolean params = GL_FALSE;
			glGetBooleanv(-1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_floatv, "Invalid glGetFloatv() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
			GLfloat params = 0.0f;
			glGetFloatv(-1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_integerv, "Invalid glGetIntegerv() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
			GLint params = -1;
			glGetIntegerv(-1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_integer64v, "Invalid glGetInteger64v() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not one of the allowed values.");
			GLint64 params = -1;
			glGetInteger64v(-1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_integeri_v, "Invalid glGetIntegeri_v() usage",
		{
			GLint data = -1;
			GLint maxUniformBufferBindings;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if name is not an accepted value.");
			glGetIntegeri_v(-1, 0, &data);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
			glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
			expectError(GL_NO_ERROR);
			glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, maxUniformBufferBindings, &data);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_integer64i_v, "Invalid glGetInteger64i_v() usage",
		{
			GLint64 data = (GLint64)-1;;
			GLint maxUniformBufferBindings;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if name is not an accepted value.");
			glGetInteger64i_v(-1, 0, &data);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
			glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
			expectError(GL_NO_ERROR);
			glGetInteger64i_v(GL_UNIFORM_BUFFER_START, maxUniformBufferBindings, &data);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_string, "Invalid glGetString() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if name is not an accepted value.");
			glGetString(-1);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_stringi, "Invalid glGetStringi() usage",
		{
			GLint numExtensions;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if name is not an accepted value.");
			glGetStringi(-1, 0);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is outside the valid range for indexed state name.");
			glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
			glGetStringi(GL_EXTENSIONS, numExtensions);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});

	// Enumerated state queries: Shaders

	ES3F_ADD_API_CASE(get_attached_shaders, "Invalid glGetAttachedShaders() usage",
		{
			GLuint shaders[1];
			GLuint shaderObject = glCreateShader(GL_VERTEX_SHADER);
			GLuint program		= glCreateProgram();
			GLsizei count[1];

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetAttachedShaders(-1, 1, &count[0], &shaders[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetAttachedShaders(shaderObject, 1, &count[0], &shaders[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if maxCount is less than 0.");
			glGetAttachedShaders(program, -1, &count[0], &shaders[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			glDeleteShader(shaderObject);
			glDeleteProgram(program);
		});
	ES3F_ADD_API_CASE(get_shaderiv, "Invalid glGetShaderiv() usage",
		{
			GLboolean shaderCompilerSupported;
			glGetBooleanv(GL_SHADER_COMPILER, &shaderCompilerSupported);
			m_log << TestLog::Message << "// GL_SHADER_COMPILER = " << (shaderCompilerSupported ? "GL_TRUE" : "GL_FALSE") << TestLog::EndMessage;

			GLuint shader	= glCreateShader(GL_VERTEX_SHADER);
			GLuint program	= glCreateProgram();
			GLint param[1]	= { -1 };

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetShaderiv(shader, -1, &param[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
			glGetShaderiv(-1, GL_SHADER_TYPE, &param[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader does not refer to a shader object.");
			glGetShaderiv(program, GL_SHADER_TYPE, &param[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteShader(shader);
			glDeleteProgram(program);
		});
	ES3F_ADD_API_CASE(get_shader_info_log, "Invalid glGetShaderInfoLog() usage",
		{
			GLuint shader		= glCreateShader(GL_VERTEX_SHADER);
			GLuint program		= glCreateProgram();
			GLsizei length[1]	= { 0 };
			char infoLog[128]	= { 0 };

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
			glGetShaderInfoLog(-1, 128, &length[0], &infoLog[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object.");
			glGetShaderInfoLog(program, 128, &length[0], &infoLog[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if maxLength is less than 0.");
			glGetShaderInfoLog(shader, -1, &length[0], &infoLog[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			glDeleteShader(shader);
			glDeleteProgram(program);
		});
	ES3F_ADD_API_CASE(get_shader_precision_format, "Invalid glGetShaderPrecisionFormat() usage",
		{
			GLboolean shaderCompilerSupported;
			glGetBooleanv(GL_SHADER_COMPILER, &shaderCompilerSupported);
			m_log << TestLog::Message << "// GL_SHADER_COMPILER = " << (shaderCompilerSupported ? "GL_TRUE" : "GL_FALSE") << TestLog::EndMessage;

			GLint range[2];
			GLint precision[1];

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

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if shaderType or precisionType is not an accepted value.");
			glGetShaderPrecisionFormat (-1, GL_MEDIUM_FLOAT, &range[0], &precision[0]);
			expectError(GL_INVALID_ENUM);
			glGetShaderPrecisionFormat (GL_VERTEX_SHADER, -1, &range[0], &precision[0]);
			expectError(GL_INVALID_ENUM);
			glGetShaderPrecisionFormat (-1, -1, &range[0], &precision[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_shader_source, "Invalid glGetShaderSource() usage",
		{
			GLsizei length[1]	= { 0 };
			char source[1]		= { 0 };
			GLuint program	= glCreateProgram();
			GLuint shader	= glCreateShader(GL_VERTEX_SHADER);

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL.");
			glGetShaderSource(-1, 1, &length[0], &source[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object.");
			glGetShaderSource(program, 1, &length[0], &source[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if bufSize is less than 0.");
			glGetShaderSource(shader, -1, &length[0], &source[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

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

	// Enumerated state queries: Programs

	ES3F_ADD_API_CASE(get_programiv, "Invalid glGetProgramiv() usage",
		{
			GLuint program	= glCreateProgram();
			GLuint shader	= glCreateShader(GL_VERTEX_SHADER);
			GLint params[1]	= { -1 };

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetProgramiv(program, -1, &params[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetProgramiv(-1, GL_LINK_STATUS, &params[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program does not refer to a program object.");
			glGetProgramiv(shader, GL_LINK_STATUS, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteProgram(program);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(get_program_info_log, "Invalid glGetProgramInfoLog() usage",
		{
			GLuint program		= glCreateProgram();
			GLuint shader		= glCreateShader(GL_VERTEX_SHADER);
			GLsizei length[1]	= { 0 };
			char infoLog[1]		= { 0 };

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetProgramInfoLog (-1, 1, &length[0], &infoLog[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetProgramInfoLog (shader, 1, &length[0], &infoLog[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if maxLength is less than 0.");
			glGetProgramInfoLog (program, -1, &length[0], &infoLog[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

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

	// Enumerated state queries: Shader variables

	ES3F_ADD_API_CASE(get_tex_parameterfv, "Invalid glGetTexParameterfv() usage",
		{
			GLfloat params[1] = { 0.0f };

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
			glGetTexParameterfv (-1, GL_TEXTURE_MAG_FILTER, &params[0]);
			expectError(GL_INVALID_ENUM);
			glGetTexParameterfv (GL_TEXTURE_2D, -1, &params[0]);
			expectError(GL_INVALID_ENUM);
			glGetTexParameterfv (-1, -1, &params[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_tex_parameteriv, "Invalid glGetTexParameteriv() usage",
		{
			GLint params[1] = { 0 };

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
			glGetTexParameteriv (-1, GL_TEXTURE_MAG_FILTER, &params[0]);
			expectError(GL_INVALID_ENUM);
			glGetTexParameteriv (GL_TEXTURE_2D, -1, &params[0]);
			expectError(GL_INVALID_ENUM);
			glGetTexParameteriv (-1, -1, &params[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_uniformfv, "Invalid glGetUniformfv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			glUseProgram(program.getProgram());

			GLint unif = glGetUniformLocation(program.getProgram(), "vUnif_vec4");	// vec4
			if (unif == -1)
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");

			GLuint shader		= glCreateShader(GL_VERTEX_SHADER);
			GLuint programEmpty = glCreateProgram();
			GLfloat params[4]	= { 0.0f };

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetUniformfv (-1, unif, &params[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetUniformfv (shader, unif, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been successfully linked.");
			glGetUniformfv (programEmpty, unif, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable location for the specified program object.");
			glGetUniformfv (program.getProgram(), -1, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteShader(shader);
			glDeleteProgram(programEmpty);
		});
	ES3F_ADD_API_CASE(get_uniformiv, "Invalid glGetUniformiv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			glUseProgram(program.getProgram());

			GLint unif = glGetUniformLocation(program.getProgram(), "fUnif_ivec4");	// ivec4
			if (unif == -1)
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");

			GLuint shader		= glCreateShader(GL_VERTEX_SHADER);
			GLuint programEmpty = glCreateProgram();
			GLint params[4]		= { 0 };

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetUniformiv (-1, unif, &params[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetUniformiv (shader, unif, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been successfully linked.");
			glGetUniformiv (programEmpty, unif, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable location for the specified program object.");
			glGetUniformiv (program.getProgram(), -1, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteShader(shader);
			glDeleteProgram(programEmpty);
		});
	ES3F_ADD_API_CASE(get_uniformuiv, "Invalid glGetUniformuiv() usage",
		{
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			glUseProgram(program.getProgram());

			GLint unif = glGetUniformLocation(program.getProgram(), "fUnif_uvec4");	// uvec4
			if (unif == -1)
				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location");

			GLuint shader		= glCreateShader(GL_VERTEX_SHADER);
			GLuint programEmpty = glCreateProgram();
			GLuint params[4]	= { 0 };

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetUniformuiv (-1, unif, &params[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetUniformuiv (shader, unif, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been successfully linked.");
			glGetUniformuiv (programEmpty, unif, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if location does not correspond to a valid uniform variable location for the specified program object.");
			glGetUniformuiv (program.getProgram(), -1, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteShader(shader);
			glDeleteProgram(programEmpty);
		});
	ES3F_ADD_API_CASE(get_active_uniform, "Invalid glGetActiveUniform() usage",
		{
			GLuint				shader				= glCreateShader(GL_VERTEX_SHADER);
			glu::ShaderProgram	program				(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			GLint				numActiveUniforms	= -1;

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

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetActiveUniform(-1, 0, 0, 0, 0, 0, 0);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetActiveUniform(shader, 0, 0, 0, 0, 0, 0);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to the number of active uniform variables in program.");
			glUseProgram(program.getProgram());
			glGetActiveUniform(program.getProgram(), numActiveUniforms, 0, 0, 0, 0, 0);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if bufSize is less than 0.");
			glGetActiveUniform(program.getProgram(), 0, -1, 0, 0, 0, 0);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			glUseProgram(0);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(get_active_uniformsiv, "Invalid glGetActiveUniformsiv() usage",
		{
			GLuint					shader				= glCreateShader(GL_VERTEX_SHADER);
			glu::ShaderProgram		program				(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			GLuint					dummyUniformIndex	= 1;
			GLint					dummyParamDst		= -1;
			GLint					numActiveUniforms	= -1;

			glUseProgram(program.getProgram());

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

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetActiveUniformsiv(-1, 1, &dummyUniformIndex, GL_UNIFORM_TYPE, &dummyParamDst);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetActiveUniformsiv(shader, 1, &dummyUniformIndex, GL_UNIFORM_TYPE, &dummyParamDst);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "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> dummyParamsDst(invalidUniformIndices.size());
				glGetActiveUniformsiv(program.getProgram(), (GLsizei)invalidUniformIndices.size(), &invalidUniformIndices[0], GL_UNIFORM_TYPE, &dummyParamsDst[0]);
				expectError(excess == 0 ? GL_NO_ERROR : GL_INVALID_VALUE);
			}
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted token.");
			glGetActiveUniformsiv(program.getProgram(), 1, &dummyUniformIndex, -1, &dummyParamDst);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glUseProgram(0);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(get_active_uniform_blockiv, "Invalid glGetActiveUniformBlockiv() usage",
		{
			glu::ShaderProgram	program			(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			GLint				params			= -1;
			GLint				numActiveBlocks	= -1;

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

			m_log << TestLog::Section("", "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.");
			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);
			glGetActiveUniformBlockiv(program.getProgram(), numActiveBlocks, GL_UNIFORM_BLOCK_BINDING, &params);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not one of the accepted tokens.");
			glGetActiveUniformBlockiv(program.getProgram(), 0, -1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(get_active_uniform_block_name, "Invalid glGetActiveUniformBlockName() usage",
		{
			glu::ShaderProgram	program			(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			GLsizei				length			= -1;
			GLint				numActiveBlocks	= -1;
			GLchar				uniformBlockName[128];

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

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

			m_log << TestLog::Section("", "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.");
			glUseProgram(program.getProgram());
			expectError(GL_NO_ERROR);
			glGetActiveUniformBlockName(program.getProgram(), numActiveBlocks, (int)sizeof(uniformBlockName), &length, &uniformBlockName[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			glUseProgram(0);
		});
	ES3F_ADD_API_CASE(get_active_attrib, "Invalid glGetActiveAttrib() usage",
		{
			GLuint				shader				= glCreateShader(GL_VERTEX_SHADER);
			glu::ShaderProgram	program				(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			GLint				numActiveAttributes	= -1;

			GLsizei				length				= -1;
			GLint				size				= -1;
			GLenum				type				= -1;
			GLchar				name[32];

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

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

			glUseProgram(program.getProgram());

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL.");
			glGetActiveAttrib(-1, 0, 32, &length, &size, &type, &name[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object.");
			glGetActiveAttrib(shader, 0, 32, &length, &size, &type, &name[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_ACTIVE_ATTRIBUTES.");
			glGetActiveAttrib(program.getProgram(), numActiveAttributes, (int)sizeof(name), &length, &size, &type, &name[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if bufSize is less than 0.");
			glGetActiveAttrib(program.getProgram(), 0, -1, &length, &size, &type, &name[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			glUseProgram(0);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(get_uniform_indices, "Invalid glGetUniformIndices() usage",
		{
			GLuint shader			= glCreateShader(GL_VERTEX_SHADER);
			glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource));
			GLint numActiveBlocks = -1;
			const GLchar* uniformName =  "Block.blockVar";
			GLuint uniformIndices = -1;

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

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is a name of shader object.");
			glGetUniformIndices(shader, 1, &uniformName, &uniformIndices);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not name of program or shader object.");
			GLuint invalid = -1;
			glGetUniformIndices(invalid, 1, &uniformName, &uniformIndices);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			glUseProgram(0);
			glDeleteShader(shader);
		});
	ES3F_ADD_API_CASE(get_vertex_attribfv, "Invalid glGetVertexAttribfv() usage",
		{
			GLfloat params = 0.0f;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetVertexAttribfv(0, -1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
			GLint maxVertexAttribs;
			glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
			glGetVertexAttribfv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_vertex_attribiv, "Invalid glGetVertexAttribiv() usage",
		{
			GLint params = -1;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetVertexAttribiv(0, -1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
			GLint maxVertexAttribs;
			glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
			glGetVertexAttribiv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_vertex_attribi_iv, "Invalid glGetVertexAttribIiv() usage",
		{
			GLint params = -1;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetVertexAttribIiv(0, -1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
			GLint maxVertexAttribs;
			glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
			glGetVertexAttribIiv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_vertex_attribi_uiv, "Invalid glGetVertexAttribIuiv() usage",
		{
			GLuint params = (GLuint)-1;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetVertexAttribIuiv(0, -1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
			GLint maxVertexAttribs;
			glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
			glGetVertexAttribIuiv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &params);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_vertex_attrib_pointerv, "Invalid glGetVertexAttribPointerv() usage",
		{
			GLvoid* ptr[1] = { DE_NULL };

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetVertexAttribPointerv(0, -1, &ptr[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
			GLint maxVertexAttribs;
			glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
			glGetVertexAttribPointerv(maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr[0]);
			expectError(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_frag_data_location, "Invalid glGetFragDataLocation() usage",
		{
			GLuint shader	= glCreateShader(GL_VERTEX_SHADER);
			GLuint program	= glCreateProgram();

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is the name of a shader object.");
			glGetFragDataLocation(shader, "gl_FragColor");
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been linked.");
			glGetFragDataLocation(program, "gl_FragColor");
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

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

	// Enumerated state queries: Buffers

	ES3F_ADD_API_CASE(get_buffer_parameteriv, "Invalid glGetBufferParameteriv() usage",
		{
			GLint params = -1;
			GLuint buf;
			glGenBuffers(1, &buf);
			glBindBuffer(GL_ARRAY_BUFFER, buf);

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target or value is not an accepted value.");
			glGetBufferParameteriv(-1, GL_BUFFER_SIZE, &params);
			expectError(GL_INVALID_ENUM);
			glGetBufferParameteriv(GL_ARRAY_BUFFER, -1, &params);
			expectError(GL_INVALID_ENUM);
			glGetBufferParameteriv(-1, -1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
			glBindBuffer(GL_ARRAY_BUFFER, 0);
			glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &params);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteBuffers(1, &buf);
		});
	ES3F_ADD_API_CASE(get_buffer_parameteri64v, "Invalid glGetBufferParameteri64v() usage",
		{
			GLint64 params = -1;
			GLuint buf;
			glGenBuffers(1, &buf);
			glBindBuffer(GL_ARRAY_BUFFER, buf);

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target or value is not an accepted value.");
			glGetBufferParameteri64v(-1, GL_BUFFER_SIZE, &params);
			expectError(GL_INVALID_ENUM);
			glGetBufferParameteri64v(GL_ARRAY_BUFFER , -1, &params);
			expectError(GL_INVALID_ENUM);
			glGetBufferParameteri64v(-1, -1, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
			glBindBuffer(GL_ARRAY_BUFFER, 0);
			glGetBufferParameteri64v(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &params);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteBuffers(1, &buf);
		});
	ES3F_ADD_API_CASE(get_buffer_pointerv, "Invalid glGetBufferPointerv() usage",
		{
			GLvoid* params = DE_NULL;
			GLuint buf;
			glGenBuffers(1, &buf);
			glBindBuffer(GL_ARRAY_BUFFER, buf);

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
			glGetBufferPointerv(GL_ARRAY_BUFFER, -1, &params);
			expectError(GL_INVALID_ENUM);
			glGetBufferPointerv(-1, GL_BUFFER_MAP_POINTER, &params);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
			glBindBuffer(GL_ARRAY_BUFFER, 0);
			glGetBufferPointerv(GL_ARRAY_BUFFER, GL_BUFFER_MAP_POINTER, &params);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			glDeleteBuffers(1, &buf);
		});
	ES3F_ADD_API_CASE(get_framebuffer_attachment_parameteriv, "Invalid glGetFramebufferAttachmentParameteriv() usage",
		{
			GLint params[1] = { -1 };
			GLuint fbo;
			GLuint rbo[2];

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

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

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not one of the accepted tokens.");
			glGetFramebufferAttachmentParameteriv(-1, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &params[0]);					// TYPE is GL_RENDERBUFFER
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not valid for the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE.");
			glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &params[0]);	// TYPE is GL_RENDERBUFFER
			expectError(GL_INVALID_ENUM);
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
			glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_BACK, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &params[0]);					// TYPE is GL_FRAMEBUFFER_DEFAULT
			expectError(GL_INVALID_ENUM);
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "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.");
			glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &params[0]);
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "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.");
			glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &params[0]);		// TYPE is GL_NONE
			expectError(GL_NO_ERROR);
			glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, &params[0]);	// TYPE is GL_NONE
			expectError(GL_INVALID_OPERATION);
			m_log << TestLog::EndSection;

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

			glDeleteFramebuffers(1, &fbo);
		});
	ES3F_ADD_API_CASE(get_renderbuffer_parameteriv, "Invalid glGetRenderbufferParameteriv() usage",
		{
			GLint params[1] = { -1 };
			GLuint rbo;
			glGenRenderbuffers(1, &rbo);
			glBindRenderbuffer(GL_RENDERBUFFER, rbo);

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_RENDERBUFFER.");
			glGetRenderbufferParameteriv(-1, GL_RENDERBUFFER_WIDTH, &params[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not one of the accepted tokens.");
			glGetRenderbufferParameteriv(GL_RENDERBUFFER, -1, &params[0]);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			glDeleteRenderbuffers(1, &rbo);
			glBindRenderbuffer(GL_RENDERBUFFER, 0);
		});
	ES3F_ADD_API_CASE(get_internalformativ, "Invalid glGetInternalformativ() usage",
		{
			GLint params[16];

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

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if bufSize is negative.");
			glGetInternalformativ	(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, -1, &params[0]);
			expectError				(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not GL_SAMPLES or GL_NUM_SAMPLE_COUNTS.");
			glGetInternalformativ	(GL_RENDERBUFFER, GL_RGBA8, -1, 16, &params[0]);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if internalformat is not color-, depth-, or stencil-renderable.");
			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_render_snorm"))
			{
				glGetInternalformativ	(GL_RENDERBUFFER, GL_RG8_SNORM, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
				expectError				(GL_INVALID_ENUM);
			}

			glGetInternalformativ	(GL_RENDERBUFFER, GL_COMPRESSED_RGB8_ETC2, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
			expectError				(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_RENDERBUFFER.");
			glGetInternalformativ	(-1, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
			expectError				(GL_INVALID_ENUM);
			glGetInternalformativ	(GL_FRAMEBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
			expectError				(GL_INVALID_ENUM);

			if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_sparse_texture"))
			{
				glGetInternalformativ	(GL_TEXTURE_2D, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 16, &params[0]);
				expectError				(GL_INVALID_ENUM);
			}
			m_log << TestLog::EndSection;
		});

	// Query object queries

	ES3F_ADD_API_CASE(get_queryiv, "Invalid glGetQueryiv() usage",
		{
			GLint params = -1;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target or pname is not an accepted value.");
			glGetQueryiv	(GL_ANY_SAMPLES_PASSED, -1, &params);
			expectError		(GL_INVALID_ENUM);
			glGetQueryiv	(-1, GL_CURRENT_QUERY, &params);
			expectError		(GL_INVALID_ENUM);
			glGetQueryiv	(-1, -1, &params);
			expectError		(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});
	ES3F_ADD_API_CASE(get_query_objectuiv, "Invalid glGetQueryObjectuiv() usage",
		{
			GLuint params	= -1;
			GLuint id;
			glGenQueries		(1, &id);

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

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

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value.");
			glGetQueryObjectuiv	(id, -1, &params);
			expectError			(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if id is the name of a currently active query object.");
			glBeginQuery		(GL_ANY_SAMPLES_PASSED, id);
			expectError			(GL_NO_ERROR);
			glGetQueryObjectuiv	(id, GL_QUERY_RESULT_AVAILABLE, &params);
			expectError			(GL_INVALID_OPERATION);
			glEndQuery			(GL_ANY_SAMPLES_PASSED);
			expectError			(GL_NO_ERROR);
			m_log << TestLog::EndSection;

			glDeleteQueries		(1, &id);
		});

	// Sync object queries

	ES3F_ADD_API_CASE(get_synciv, "Invalid glGetSynciv() usage",
		{
			GLsizei length	= -1;
			GLint	values[32];
			GLsync	sync;

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

			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if sync is not the name of a sync object.");
			glGetSynciv	(0, GL_OBJECT_TYPE, 32, &length, &values[0]);
			expectError	(GL_INVALID_VALUE);
			m_log << TestLog::EndSection;

			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not one of the accepted tokens.");
			sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
			expectError	(GL_NO_ERROR);
			glGetSynciv	(sync, -1, 32, &length, &values[0]);
			expectError	(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});

	// Enumerated boolean state queries

	ES3F_ADD_API_CASE(is_enabled, "Invalid glIsEnabled() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if cap is not an accepted value.");
			glIsEnabled(-1);
			expectError(GL_INVALID_ENUM);
			glIsEnabled(GL_TRIANGLES);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});

	// Hints

	ES3F_ADD_API_CASE(hint, "Invalid glHint() usage",
		{
			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if either target or mode is not an accepted value.");
			glHint(GL_GENERATE_MIPMAP_HINT, -1);
			expectError(GL_INVALID_ENUM);
			glHint(-1, GL_FASTEST);
			expectError(GL_INVALID_ENUM);
			glHint(-1, -1);
			expectError(GL_INVALID_ENUM);
			m_log << TestLog::EndSection;
		});

	// Named Object Usage

	ES3F_ADD_API_CASE(is_buffer, "Invalid glIsBuffer() usage",
		{
			GLuint		buffer = 0;
			GLboolean	isBuffer;

			m_log << TestLog::Section("", "A name returned by glGenBuffers, but not yet associated with a buffer object by calling glBindBuffer, is not the name of a buffer object.");
			isBuffer		= glIsBuffer(buffer);
			checkBooleans	(isBuffer, GL_FALSE);

			glGenBuffers	(1, &buffer);
			isBuffer		= glIsBuffer(buffer);
			checkBooleans	(isBuffer, GL_FALSE);

			glBindBuffer	(GL_ARRAY_BUFFER, buffer);
			isBuffer		= glIsBuffer(buffer);
			checkBooleans	(isBuffer, GL_TRUE);

			glBindBuffer	(GL_ARRAY_BUFFER, 0);
			glDeleteBuffers	(1, &buffer);
			isBuffer		= glIsBuffer(buffer);
			checkBooleans	(isBuffer, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_framebuffer, "Invalid glIsFramebuffer() usage",
		{
			GLuint		fbo = 0;
			GLboolean	isFbo;

			m_log << TestLog::Section("", "A name returned by glGenFramebuffers, but not yet bound through a call to glBindFramebuffer is not the name of a framebuffer object.");
			isFbo				= glIsFramebuffer(fbo);
			checkBooleans		(isFbo, GL_FALSE);

			glGenFramebuffers	(1, &fbo);
			isFbo				= glIsFramebuffer(fbo);
			checkBooleans		(isFbo, GL_FALSE);

			glBindFramebuffer	(GL_FRAMEBUFFER, fbo);
			isFbo				= glIsFramebuffer(fbo);
			checkBooleans		(isFbo, GL_TRUE);

			glBindFramebuffer	(GL_FRAMEBUFFER, 0);
			glDeleteFramebuffers(1, &fbo);
			isFbo				= glIsFramebuffer(fbo);
			checkBooleans		(isFbo, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_program, "Invalid glIsProgram() usage",
		{
			GLuint		program = 0;
			GLboolean	isProgram;

			m_log << TestLog::Section("", "A name created with glCreateProgram, and not yet deleted with glDeleteProgram is a name of a program object.");
			isProgram			= glIsProgram(program);
			checkBooleans		(isProgram, GL_FALSE);

			program				= glCreateProgram();
			isProgram			= glIsProgram(program);
			checkBooleans		(isProgram, GL_TRUE);

			glDeleteProgram		(program);
			isProgram			= glIsProgram(program);
			checkBooleans		(isProgram, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_renderbuffer, "Invalid glIsRenderbuffer() usage",
		{
			GLuint		rbo = 0;
			GLboolean	isRbo;

			m_log << TestLog::Section("", "A name returned by glGenRenderbuffers, but not yet bound through a call to glBindRenderbuffer or glFramebufferRenderbuffer is not the name of a renderbuffer object.");
			isRbo					= glIsRenderbuffer(rbo);
			checkBooleans			(isRbo, GL_FALSE);

			glGenRenderbuffers		(1, &rbo);
			isRbo					= glIsRenderbuffer(rbo);
			checkBooleans			(isRbo, GL_FALSE);

			glBindRenderbuffer		(GL_RENDERBUFFER, rbo);
			isRbo					= glIsRenderbuffer(rbo);
			checkBooleans			(isRbo, GL_TRUE);

			glBindRenderbuffer		(GL_RENDERBUFFER, 0);
			glDeleteRenderbuffers	(1, &rbo);
			isRbo					= glIsRenderbuffer(rbo);
			checkBooleans			(isRbo, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_shader, "Invalid glIsShader() usage",
		{
			GLuint		shader = 0;
			GLboolean	isShader;

			m_log << TestLog::Section("", "A name created with glCreateShader, and not yet deleted with glDeleteShader is a name of a shader object.");
			isShader			= glIsProgram(shader);
			checkBooleans		(isShader, GL_FALSE);

			shader				= glCreateShader(GL_VERTEX_SHADER);
			isShader			= glIsShader(shader);
			checkBooleans		(isShader, GL_TRUE);

			glDeleteShader		(shader);
			isShader			= glIsShader(shader);
			checkBooleans		(isShader, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_texture, "Invalid glIsTexture() usage",
		{
			GLuint		texture = 0;
			GLboolean	isTexture;

			m_log << TestLog::Section("", "A name returned by glGenTextures, but not yet bound through a call to glBindTexture is not the name of a texture.");
			isTexture			= glIsTexture(texture);
			checkBooleans		(isTexture, GL_FALSE);

			glGenTextures		(1, &texture);
			isTexture			= glIsTexture(texture);
			checkBooleans		(isTexture, GL_FALSE);

			glBindTexture		(GL_TEXTURE_2D, texture);
			isTexture			= glIsTexture(texture);
			checkBooleans		(isTexture, GL_TRUE);

			glBindTexture		(GL_TEXTURE_2D, 0);
			glDeleteTextures	(1, &texture);
			isTexture			= glIsTexture(texture);
			checkBooleans		(isTexture, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_query, "Invalid glIsQuery() usage",
		{
			GLuint		query = 0;
			GLboolean	isQuery;

			m_log << TestLog::Section("", "A name returned by glGenQueries, but not yet associated with a query object by calling glBeginQuery, is not the name of a query object.");
			isQuery				= glIsQuery(query);
			checkBooleans		(isQuery, GL_FALSE);

			glGenQueries		(1, &query);
			isQuery				= glIsQuery(query);
			checkBooleans		(isQuery, GL_FALSE);

			glBeginQuery		(GL_ANY_SAMPLES_PASSED, query);
			isQuery				= glIsQuery(query);
			checkBooleans		(isQuery, GL_TRUE);

			glEndQuery			(GL_ANY_SAMPLES_PASSED);
			glDeleteQueries		(1, &query);
			isQuery				= glIsQuery(query);
			checkBooleans		(isQuery, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_sampler, "Invalid glIsSampler() usage",
		{
			GLuint		sampler = 0;
			GLboolean	isSampler;

			m_log << TestLog::Section("", "A name returned by glGenSamplers is the name of a sampler object.");
			isSampler			= glIsSampler(sampler);
			checkBooleans		(isSampler, GL_FALSE);

			glGenSamplers		(1, &sampler);
			isSampler			= glIsSampler(sampler);
			checkBooleans		(isSampler, GL_TRUE);

			glBindSampler		(0, sampler);
			isSampler			= glIsSampler(sampler);
			checkBooleans		(isSampler, GL_TRUE);

			glDeleteSamplers	(1, &sampler);
			isSampler			= glIsSampler(sampler);
			checkBooleans		(isSampler, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_sync, "Invalid glIsSync() usage",
		{
			GLsync		sync = 0;
			GLboolean	isSync;

			m_log << TestLog::Section("", "A name returned by glFenceSync is the name of a sync object.");
			isSync			= glIsSync(sync);
			checkBooleans	(isSync, GL_FALSE);

			sync			= glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
			isSync			= glIsSync(sync);
			checkBooleans	(isSync, GL_TRUE);

			glDeleteSync	(sync);
			isSync			= glIsSync(sync);
			checkBooleans	(isSync, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_transform_feedback, "Invalid glIsTransformFeedback() usage",
		{
			GLuint		tf = 0;
			GLboolean	isTF;

			m_log << TestLog::Section("", "A name returned by glGenTransformFeedbacks, but not yet bound using glBindTransformFeedback, is not the name of a transform feedback object.");
			isTF						= glIsTransformFeedback(tf);
			checkBooleans				(isTF, GL_FALSE);

			glGenTransformFeedbacks		(1, &tf);
			isTF						= glIsTransformFeedback(tf);
			checkBooleans				(isTF, GL_FALSE);

			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, tf);
			isTF						= glIsTransformFeedback(tf);
			checkBooleans				(isTF, GL_TRUE);

			glBindTransformFeedback		(GL_TRANSFORM_FEEDBACK, 0);
			glDeleteTransformFeedbacks	(1, &tf);
			isTF						= glIsTransformFeedback(tf);
			checkBooleans				(isTF, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
	ES3F_ADD_API_CASE(is_vertex_array, "Invalid glIsVertexArray() usage",
		{
			GLuint		vao = 0;
			GLboolean	isVao;

			m_log << TestLog::Section("", "A name returned by glGenVertexArrays, but not yet bound using glBindVertexArray, is not the name of a vertex array object.");
			isVao					= glIsVertexArray(vao);
			checkBooleans			(isVao, GL_FALSE);

			glGenVertexArrays			(1, &vao);
			isVao					= glIsVertexArray(vao);
			checkBooleans			(isVao, GL_FALSE);

			glBindVertexArray			(vao);
			isVao					= glIsVertexArray(vao);
			checkBooleans			(isVao, GL_TRUE);

			glBindVertexArray		(0);
			glDeleteVertexArrays	(1, &vao);
			isVao					= glIsVertexArray(vao);
			checkBooleans			(isVao, GL_FALSE);
			m_log << TestLog::EndSection;

			expectError			(GL_NO_ERROR);
		});
}

} // Functional
} // gles3
} // deqp