/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 2.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 Shader API tests.
 *//*--------------------------------------------------------------------*/

#include "es2fShaderApiTests.hpp"
#include "es2fApiCase.hpp"
#include "tcuTestLog.hpp"

#include "gluRenderContext.hpp"
#include "gluShaderProgram.hpp"
#include "gluContextInfo.hpp"
#include "glwFunctions.hpp"
#include "glwDefs.hpp"
#include "glwEnums.hpp"

#include "deString.h"

#include "deRandom.hpp"
#include "deStringUtil.hpp"

#include <string>
#include <vector>
#include <map>

using namespace glw; // GL types

namespace deqp
{
namespace gles2
{
namespace Functional
{

using tcu::TestLog;

namespace
{

enum ShaderSourceCaseFlags
{
	CASE_EXPLICIT_SOURCE_LENGTHS	= 1,
	CASE_RANDOM_NULL_TERMINATED		= 2
};

struct ShaderSources
{
	std::vector<std::string>	strings;
	std::vector<int>			lengths;
};

// Simple shaders

const char* getSimpleShaderSource (const glu::ShaderType shaderType)
{
	const char* simpleVertexShaderSource	= "void main (void) { gl_Position = vec4(0.0); }\n";
	const char* simpleFragmentShaderSource	= "void main (void) { gl_FragColor = vec4(0.0); }\n";

	switch (shaderType)
	{
		case glu::SHADERTYPE_VERTEX:
			return simpleVertexShaderSource;
		case glu::SHADERTYPE_FRAGMENT:
			return simpleFragmentShaderSource;
		default:
			DE_ASSERT(DE_FALSE);
	}

	return 0;
}

void setShaderSources (glu::Shader& shader, const ShaderSources& sources)
{
	std::vector<const char*> cStrings (sources.strings.size(), 0);

	for (size_t ndx = 0; ndx < sources.strings.size(); ndx++)
		cStrings[ndx] = sources.strings[ndx].c_str();

	if (sources.lengths.size() > 0)
		shader.setSources((int)cStrings.size(), &cStrings[0], &sources.lengths[0]);
	else
		shader.setSources((int)cStrings.size(), &cStrings[0], 0);
}

void sliceSourceString (const std::string& in, ShaderSources& out, const int numSlices, const size_t paddingLength = 0)
{
	DE_ASSERT(numSlices > 0);

	const size_t		sliceSize			= in.length() / numSlices;
	const size_t		sliceSizeRemainder	= in.length() - (sliceSize * numSlices);
	const std::string	padding				(paddingLength, 'E');

	for (int i = 0; i < numSlices; i++)
	{
		out.strings.push_back(in.substr(i * sliceSize, sliceSize) + padding);

		if (paddingLength > 0)
			out.lengths.push_back((int)sliceSize);
	}

	if (sliceSizeRemainder > 0)
	{
		const std::string	lastString			= in.substr(numSlices * sliceSize);
		const int			lastStringLength	= (int)lastString.length();

		out.strings.push_back(lastString + padding);

		if (paddingLength > 0)
			out.lengths.push_back(lastStringLength);
	}
}

void queryShaderInfo (glu::RenderContext& renderCtx, deUint32 shader, glu::ShaderInfo& info)
{
	const glw::Functions& gl = renderCtx.getFunctions();

	info.compileOk		= false;
	info.compileTimeUs	= 0;
	info.infoLog.clear();

	// Query source, status & log.
	{
		int	compileStatus	= 0;
		int sourceLen		= 0;
		int	infoLogLen		= 0;
		int	unusedLen;

		gl.getShaderiv(shader, GL_COMPILE_STATUS,			&compileStatus);
		gl.getShaderiv(shader, GL_SHADER_SOURCE_LENGTH,	&sourceLen);
		gl.getShaderiv(shader, GL_INFO_LOG_LENGTH,		&infoLogLen);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");

		info.compileOk = compileStatus != GL_FALSE;

		if (sourceLen > 0)
		{
			std::vector<char> source(sourceLen);
			gl.getShaderSource(shader, (int)source.size(), &unusedLen, &source[0]);
			info.source = std::string(&source[0], sourceLen);
		}

		if (infoLogLen > 0)
		{
			std::vector<char> infoLog(infoLogLen);
			gl.getShaderInfoLog(shader, (int)infoLog.size(), &unusedLen, &infoLog[0]);
			info.infoLog = std::string(&infoLog[0], infoLogLen);
		}
	}
}

// Shader source generator

class SourceGenerator
{
public:
	virtual				~SourceGenerator	(void)	{}

	virtual std::string	next				(const glu::ShaderType shaderType)			= 0;
	virtual bool		finished			(const glu::ShaderType shaderType) const	= 0;
};

class ConstantShaderGenerator : public SourceGenerator
{
public:
				ConstantShaderGenerator		(de::Random& rnd)	: m_rnd(rnd)	{}
				~ConstantShaderGenerator	(void)								{}

	bool		finished					(const glu::ShaderType shaderType) const	{ DE_UNREF(shaderType); return false; }

	std::string	next						(const glu::ShaderType shaderType);

private:
	de::Random	m_rnd;
};

std::string ConstantShaderGenerator::next (const glu::ShaderType shaderType)
{
	DE_ASSERT(shaderType == glu::SHADERTYPE_VERTEX || shaderType == glu::SHADERTYPE_FRAGMENT);

	const float			value		= m_rnd.getFloat(0.0f, 1.0f);
	const std::string	valueString	= de::toString(value);
	const std::string	outputName	= (shaderType == glu::SHADERTYPE_VERTEX) ? "gl_Position" : "gl_FragColor";

	std::string source =
		"#version 100\n"
		"void main (void) { " + outputName + " = vec4(" + valueString + "); }\n";

	return source;
}

// Shader allocation utility

class ShaderAllocator
{
public:
					ShaderAllocator		(glu::RenderContext& context, SourceGenerator& generator);
					~ShaderAllocator	(void);

	bool			hasShader			(const glu::ShaderType shaderType);

	void			setSource			(const glu::ShaderType shaderType);

	glu::Shader&	createShader		(const glu::ShaderType shaderType);
	void			deleteShader		(const glu::ShaderType shaderType);

	glu::Shader&	get					(const glu::ShaderType shaderType)	{ DE_ASSERT(hasShader(shaderType)); return *m_shaders[shaderType]; }

private:
	const glu::RenderContext&				m_context;
	SourceGenerator&						m_srcGen;
	std::map<glu::ShaderType, glu::Shader*>	m_shaders;
};

ShaderAllocator::ShaderAllocator (glu::RenderContext& context, SourceGenerator& generator)
	: m_context	(context)
	, m_srcGen	(generator)
{
}

ShaderAllocator::~ShaderAllocator (void)
{
	for (std::map<glu::ShaderType, glu::Shader*>::iterator shaderIter = m_shaders.begin(); shaderIter != m_shaders.end(); shaderIter++)
		delete shaderIter->second;
	m_shaders.clear();
}

bool ShaderAllocator::hasShader (const glu::ShaderType shaderType)
{
	if (m_shaders.find(shaderType) != m_shaders.end())
		return true;
	else
		return false;
}

glu::Shader& ShaderAllocator::createShader (const glu::ShaderType shaderType)
{
	DE_ASSERT(!this->hasShader(shaderType));

	glu::Shader* const	shader	= new glu::Shader(m_context, shaderType);

	m_shaders[shaderType] = shader;
	this->setSource(shaderType);

	return *shader;
}

void ShaderAllocator::deleteShader (const glu::ShaderType shaderType)
{
	DE_ASSERT(this->hasShader(shaderType));

	delete m_shaders[shaderType];
	m_shaders.erase(shaderType);
}

void ShaderAllocator::setSource (const glu::ShaderType shaderType)
{
	DE_ASSERT(this->hasShader(shaderType));
	DE_ASSERT(!m_srcGen.finished(shaderType));

	const std::string	source	= m_srcGen.next(shaderType);
	const char* const	cSource	= source.c_str();

	m_shaders[shaderType]->setSources(1, &cSource, 0);
}

// Logging utilities

void logShader (TestLog& log, glu::RenderContext& renderCtx, glu::Shader& shader)
{
	glu::ShaderInfo info;
	queryShaderInfo(renderCtx, shader.getShader(), info);

	log << TestLog::Shader(getLogShaderType(shader.getType()), info.source, info.compileOk, info.infoLog);
}

void logProgram (TestLog& log, glu::RenderContext& renderCtx, glu::Program& program, ShaderAllocator& shaders)
{
	log << TestLog::ShaderProgram(program.getLinkStatus(), program.getInfoLog());

	for (int shaderTypeInt = 0; shaderTypeInt < glu::SHADERTYPE_LAST; shaderTypeInt++)
	{
		const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeInt;

		if (shaders.hasShader(shaderType))
			logShader(log, renderCtx, shaders.get(shaderType));
	}

	log << TestLog::EndShaderProgram;
}

void logVertexFragmentProgram (TestLog& log, glu::RenderContext& renderCtx, glu::Program& program, glu::Shader& vertShader, glu::Shader& fragShader)
{
	DE_ASSERT(vertShader.getType() == glu::SHADERTYPE_VERTEX && fragShader.getType() == glu::SHADERTYPE_FRAGMENT);

	log << TestLog::ShaderProgram(program.getLinkStatus(), program.getInfoLog());

	logShader(log, renderCtx, vertShader);
	logShader(log, renderCtx, fragShader);

	log << TestLog::EndShaderProgram;
}

} // anonymous

// Simple glCreateShader() case

class CreateShaderCase : public ApiCase
{
public:
	CreateShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ApiCase		(context, name, desc)
		, m_shaderType	(shaderType)
	{
	}

	void test (void)
	{
		const GLuint shaderObject = glCreateShader(glu::getGLShaderType(m_shaderType));

		TCU_CHECK(shaderObject != 0);

		glDeleteShader(shaderObject);
	}

private:
	const glu::ShaderType m_shaderType;
};

// Simple glCompileShader() case

class CompileShaderCase : public ApiCase
{
public:
	CompileShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ApiCase		(context, name, desc)
		, m_shaderType	(shaderType)
	{
	}

	bool checkCompileStatus (const GLuint shaderObject)
	{
		GLint compileStatus = -1;
		glGetShaderiv(shaderObject, GL_COMPILE_STATUS, &compileStatus);
		GLU_CHECK();

		return (compileStatus == GL_TRUE);
	}

	void test (void)
	{
		const char*		shaderSource	= getSimpleShaderSource(m_shaderType);
		const GLuint	shaderObject	= glCreateShader(glu::getGLShaderType(m_shaderType));

		TCU_CHECK(shaderObject != 0);

		glShaderSource(shaderObject, 1, &shaderSource, 0);
		glCompileShader(shaderObject);

		TCU_CHECK(checkCompileStatus(shaderObject));

		glDeleteShader(shaderObject);
	}

private:
	const glu::ShaderType m_shaderType;
};

// Base class for simple program API tests

class SimpleProgramCase : public ApiCase
{
public:
	SimpleProgramCase (Context& context, const char* name, const char* desc)
		: ApiCase		(context, name, desc)
		, m_vertShader	(0)
		, m_fragShader	(0)
		, m_program		(0)
	{
	}

	virtual ~SimpleProgramCase (void)
	{
	}

	virtual void compileShaders (void)
	{
		const char*		vertSource	= getSimpleShaderSource(glu::SHADERTYPE_VERTEX);
		const char*		fragSource	= getSimpleShaderSource(glu::SHADERTYPE_FRAGMENT);

		const GLuint	vertShader	= glCreateShader(GL_VERTEX_SHADER);
		const GLuint	fragShader	= glCreateShader(GL_FRAGMENT_SHADER);

		TCU_CHECK(vertShader != 0);
		TCU_CHECK(fragShader != 0);

		glShaderSource(vertShader, 1, &vertSource, 0);
		glCompileShader(vertShader);

		glShaderSource(fragShader, 1, &fragSource, 0);
		glCompileShader(fragShader);

		GLU_CHECK();

		m_vertShader = vertShader;
		m_fragShader = fragShader;
	}

	void linkProgram (void)
	{
		const GLuint program = glCreateProgram();

		TCU_CHECK(program != 0);

		glAttachShader(program, m_vertShader);
		glAttachShader(program, m_fragShader);
		GLU_CHECK();

		glLinkProgram(program);

		m_program = program;
	}

	void cleanup (void)
	{
		glDeleteShader(m_vertShader);
		glDeleteShader(m_fragShader);
		glDeleteProgram(m_program);
	}

protected:
	GLuint	m_vertShader;
	GLuint	m_fragShader;
	GLuint	m_program;
};

// glDeleteShader() case

class DeleteShaderCase : public SimpleProgramCase
{
public:
	DeleteShaderCase (Context& context, const char* name, const char* desc)
		: SimpleProgramCase (context, name, desc)
	{
	}

	bool checkDeleteStatus(GLuint shader)
	{
		GLint deleteStatus = -1;
		glGetShaderiv(shader, GL_DELETE_STATUS, &deleteStatus);
		GLU_CHECK();

		return (deleteStatus == GL_TRUE);
	}

	void deleteShaders (void)
	{
		glDeleteShader(m_vertShader);
		glDeleteShader(m_fragShader);
		GLU_CHECK();
	}

	void test (void)
	{
		compileShaders();
		linkProgram();
		GLU_CHECK();

		deleteShaders();

		TCU_CHECK(checkDeleteStatus(m_vertShader) && checkDeleteStatus(m_fragShader));

		glDeleteProgram(m_program);

		TCU_CHECK(!(glIsShader(m_vertShader) || glIsShader(m_fragShader)));
	}
};

// Simple glLinkProgram() case

class LinkVertexFragmentCase : public SimpleProgramCase
{
public:
	LinkVertexFragmentCase (Context& context, const char* name, const char* desc)
		: SimpleProgramCase (context, name, desc)
	{
	}

	bool checkLinkStatus (const GLuint programObject)
	{
		GLint linkStatus = -1;
		glGetProgramiv(programObject, GL_LINK_STATUS, &linkStatus);
		GLU_CHECK();

		return (linkStatus == GL_TRUE);
	}

	void test (void)
	{
		compileShaders();
		linkProgram();

		GLU_CHECK_MSG("Linking failed.");
		TCU_CHECK_MSG(checkLinkStatus(m_program), "Fail, expected LINK_STATUS to be TRUE.");

		cleanup();
	}
};

class ShaderSourceReplaceCase : public ApiCase
{
public:
	ShaderSourceReplaceCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ApiCase		(context, name, desc)
		, m_shaderType	(shaderType)
	{
	}

	std::string generateFirstSource (void)
	{
		return getSimpleShaderSource(m_shaderType);
	}

	std::string generateSecondSource (void)
	{
		std::string str;

		str  = "#version 100\n";
		str += "precision highp float;\n\n";

		str += "void main()\n";
		str += "{\n";
		str += "	float variable = 1.0;\n";

		if		(m_shaderType == glu::SHADERTYPE_VERTEX)	str += "	gl_Position = vec4(variable);\n";
		else if	(m_shaderType == glu::SHADERTYPE_FRAGMENT)	str += "	gl_FragColor = vec4(variable);\n";

		str += "}\n";

		return str;
	}

	GLint getSourceLength (glu::Shader& shader)
	{
		GLint sourceLength = 0;
		glGetShaderiv(shader.getShader(), GL_SHADER_SOURCE_LENGTH, &sourceLength);
		GLU_CHECK();

		return sourceLength;
	}

	std::string readSource (glu::Shader& shader)
	{
		const GLint			sourceLength	= getSourceLength(shader);
		std::vector<char>	sourceBuffer	(sourceLength + 1);

		glGetShaderSource(shader.getShader(), (GLsizei)sourceBuffer.size(), 0, &sourceBuffer[0]);

		return std::string(&sourceBuffer[0]);
	}

	void verifyShaderSourceReplaced (glu::Shader& shader, const std::string& firstSource, const std::string& secondSource)
	{
		TestLog&			log		= m_testCtx.getLog();
		const std::string	result	= readSource(shader);

		if (result == firstSource)
		{
			log << TestLog::Message << "Fail, source was not replaced." << TestLog::EndMessage;
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader source nor replaced");
		}
		else if (result != secondSource)
		{
			log << TestLog::Message << "Fail, invalid shader source." << TestLog::EndMessage;
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid source");
		}
	}

	void test (void)
	{
		TestLog&			log				= m_testCtx.getLog();

		glu::Shader			shader			(m_context.getRenderContext(), m_shaderType);

		const std::string	firstSourceStr	= generateFirstSource();
		const std::string	secondSourceStr	= generateSecondSource();

		const char*			firstSource		= firstSourceStr.c_str();
		const char*			secondSource	= secondSourceStr.c_str();

		log << TestLog::Message << "Setting shader source." << TestLog::EndMessage;

		shader.setSources(1, &firstSource, 0);
		GLU_CHECK();

		log << TestLog::Message << "Replacing shader source." << TestLog::EndMessage;

		shader.setSources(1, &secondSource, 0);
		GLU_CHECK();

		verifyShaderSourceReplaced(shader, firstSourceStr, secondSourceStr);
	}

private:
	glu::ShaderType	m_shaderType;
};

// glShaderSource() split source case

class ShaderSourceSplitCase : public ApiCase
{
public:
	ShaderSourceSplitCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType, const int numSlices, const deUint32 flags = 0)
		: ApiCase			(context, name, desc)
		, m_rnd				(deStringHash(getName()) ^ 0x4fb2337d)
		, m_shaderType		(shaderType)
		, m_numSlices		(numSlices)
		, m_explicitLengths	((flags & CASE_EXPLICIT_SOURCE_LENGTHS)	!= 0)
		, m_randomNullTerm	((flags & CASE_RANDOM_NULL_TERMINATED)	!= 0)
	{
		DE_ASSERT(m_shaderType == glu::SHADERTYPE_VERTEX || m_shaderType == glu::SHADERTYPE_FRAGMENT);
	}

	virtual ~ShaderSourceSplitCase (void)
	{
	}

	std::string generateFullSource (void)
	{
		std::string str;

		str  = "#version 100\n";
		str += "precision highp float;\n\n";

		str += "void main()\n";
		str += "{\n";
		str += "	float variable = 1.0;\n";

		if		(m_shaderType == glu::SHADERTYPE_VERTEX)	str += "	gl_Position = vec4(variable);\n";
		else if	(m_shaderType == glu::SHADERTYPE_FRAGMENT)	str += "	gl_FragColor = vec4(variable);\n";

		str += "}\n";

		return str;
	}

	void insertRandomNullTermStrings (ShaderSources& sources)
	{
		const int			numInserts	= de::max(m_numSlices >> 2, 1);
		std::vector<int>	indices		(sources.strings.size(), 0);

		DE_ASSERT(sources.lengths.size() > 0);
		DE_ASSERT(sources.lengths.size() == sources.strings.size());

		for (int i = 0; i < (int)sources.strings.size(); i++)
			indices[i] = i;

		m_rnd.shuffle(indices.begin(), indices.end());

		for (int i = 0; i < numInserts; i++)
		{
			const int			ndx				= indices[i];
			const int			unpaddedLength	= sources.lengths[ndx];
			const std::string	unpaddedString	= sources.strings[ndx].substr(0, unpaddedLength);

			sources.strings[ndx] = unpaddedString;
			sources.lengths[ndx] = m_rnd.getInt(-10, -1);
		}
	}

	void generateSources (ShaderSources& sources)
	{
		const size_t	paddingLength	= (m_explicitLengths ? 10 : 0);
		std::string		str				= generateFullSource();

		sliceSourceString(str, sources, m_numSlices, paddingLength);

		if (m_randomNullTerm)
			insertRandomNullTermStrings(sources);
	}

	void buildProgram (glu::Shader& shader)
	{
		TestLog&				log					= m_testCtx.getLog();
		glu::RenderContext&		renderCtx			= m_context.getRenderContext();

		const glu::ShaderType	supportShaderType	= (m_shaderType == glu::SHADERTYPE_FRAGMENT ? glu::SHADERTYPE_VERTEX : glu::SHADERTYPE_FRAGMENT);
		const char*				supportShaderSource	= getSimpleShaderSource(supportShaderType);
		glu::Shader				supportShader		(renderCtx, supportShaderType);

		glu::Program			program				(renderCtx);

		supportShader.setSources(1, &supportShaderSource, 0);
		supportShader.compile();

		program.attachShader(shader.getShader());
		program.attachShader(supportShader.getShader());

		program.link();

		if (m_shaderType == glu::SHADERTYPE_VERTEX)
			logVertexFragmentProgram(log, renderCtx, program, shader, supportShader);
		else
			logVertexFragmentProgram(log, renderCtx, program, supportShader, shader);
	}

	void test (void)
	{
		TestLog&			log			= m_testCtx.getLog();
		glu::RenderContext&	renderCtx	= m_context.getRenderContext();

		ShaderSources		sources;
		glu::Shader			shader		(renderCtx, m_shaderType);

		generateSources(sources);
		setShaderSources(shader, sources);
		shader.compile();

		buildProgram(shader);

		if (!shader.getCompileStatus())
		{
			log << TestLog::Message << "Compilation failed." << TestLog::EndMessage;
			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
		}
	}

private:
	de::Random		m_rnd;

	glu::ShaderType	m_shaderType;
	const int		m_numSlices;

	const bool		m_explicitLengths;
	const bool		m_randomNullTerm;
};

// Base class for program state persistence cases

class ProgramStateCase : public ApiCase
{
public:
					ProgramStateCase	(Context& context, const char* name, const char* desc, glu::ShaderType shaderType);
	virtual			~ProgramStateCase	(void)	{}

	void			buildProgram		(glu::Program& program, ShaderAllocator& shaders);
	void			verify				(glu::Program& program, const glu::ProgramInfo& reference);

	void			test				(void);

	virtual void	executeForProgram	(glu::Program& program, ShaderAllocator& shaders)	= 0;

protected:
	de::Random					m_rnd;
	const glu::ShaderType		m_shaderType;
};

ProgramStateCase::ProgramStateCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
	: ApiCase		(context, name, desc)
	, m_rnd			(deStringHash(name) ^ 0x713de0ca)
	, m_shaderType	(shaderType)
{
	DE_ASSERT(m_shaderType == glu::SHADERTYPE_VERTEX || m_shaderType == glu::SHADERTYPE_FRAGMENT);
}

void ProgramStateCase::buildProgram (glu::Program& program, ShaderAllocator& shaders)
{
	TestLog&		log			= m_testCtx.getLog();

	glu::Shader&	vertShader	= shaders.createShader(glu::SHADERTYPE_VERTEX);
	glu::Shader&	fragShader	= shaders.createShader(glu::SHADERTYPE_FRAGMENT);

	vertShader.compile();
	fragShader.compile();

	program.attachShader(vertShader.getShader());
	program.attachShader(fragShader.getShader());
	program.link();

	logProgram(log, m_context.getRenderContext(), program, shaders);
}

void ProgramStateCase::verify (glu::Program& program, const glu::ProgramInfo& reference)
{
	TestLog&				log			= m_testCtx.getLog();
	const glu::ProgramInfo&	programInfo	= program.getInfo();

	if (!programInfo.linkOk)
	{
		log << TestLog::Message << "Fail, link status may only change as a result of linking or loading a program binary." << TestLog::EndMessage;
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Link status changed");
	}

	if (programInfo.linkTimeUs != reference.linkTimeUs)
	{
		log << TestLog::Message << "Fail, reported link time changed." << TestLog::EndMessage;
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Link time changed");
	}

	if (programInfo.infoLog != reference.infoLog)
	{
		log << TestLog::Message << "Fail, program infolog changed." << TestLog::EndMessage;
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Infolog changed");
	}
}

void ProgramStateCase::test (void)
{
	TestLog&				log			= m_testCtx.getLog();
	glu::RenderContext&		renderCtx	= m_context.getRenderContext();

	ConstantShaderGenerator	sourceGen	(m_rnd);

	ShaderAllocator			shaders		(renderCtx, sourceGen);
	glu::Program			program		(renderCtx);

	buildProgram(program, shaders);

	if (program.getLinkStatus())
	{
		glu::ProgramInfo programInfo = program.getInfo();

		executeForProgram(program, shaders);

		verify(program, programInfo);

		logProgram(log, renderCtx, program, shaders);
	}
	else
	{
		log << TestLog::Message << "Fail, couldn't link program." << TestLog::EndMessage;
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Linking failed");
	}
}

// Program state case utilities

namespace
{

template<class T>
void addProgramStateCase (TestCaseGroup* group, Context& context, const std::string& name, const std::string& desc)
{
	for (int shaderTypeInt = 0; shaderTypeInt < 2; shaderTypeInt++)
	{
		const glu::ShaderType	shaderType		= (shaderTypeInt == 1) ? glu::SHADERTYPE_FRAGMENT : glu::SHADERTYPE_VERTEX;
		const std::string		shaderTypeName	= getShaderTypeName(shaderType);

		const std::string		caseName		= name + "_" + shaderTypeName;
		const std::string		caseDesc		= "Build program, " + desc + ", for " + shaderTypeName + " shader.";

		group->addChild(new T(context, caseName.c_str(), caseDesc.c_str(), shaderType));
	}
}

} // anonymous

// Specialized program state cases

class ProgramStateDetachShaderCase : public ProgramStateCase
{
public:
	ProgramStateDetachShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ProgramStateCase (context, name, desc, shaderType)
	{
	}

	virtual ~ProgramStateDetachShaderCase (void)
	{
	}

	void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
	{
		TestLog&		log			= m_testCtx.getLog();
		glu::Shader&	caseShader	= shaders.get(m_shaderType);

		log << TestLog::Message << "Detaching " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
		program.detachShader(caseShader.getShader());
	}
};

class ProgramStateReattachShaderCase : public ProgramStateCase
{
public:
	ProgramStateReattachShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ProgramStateCase (context, name, desc, shaderType)
	{
	}

	virtual ~ProgramStateReattachShaderCase (void)
	{
	}

	void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
	{
		TestLog&		log			= m_testCtx.getLog();
		glu::Shader&	caseShader	= shaders.get(m_shaderType);

		log << TestLog::Message << "Reattaching " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
		program.detachShader(caseShader.getShader());
		program.attachShader(caseShader.getShader());
	}
};

class ProgramStateDeleteShaderCase : public ProgramStateCase
{
public:
	ProgramStateDeleteShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ProgramStateCase (context, name, desc, shaderType)
	{
	}

	virtual ~ProgramStateDeleteShaderCase (void)
	{
	}

	void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
	{
		TestLog&		log			= m_testCtx.getLog();
		glu::Shader&	caseShader	= shaders.get(m_shaderType);

		log << TestLog::Message << "Deleting " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
		program.detachShader(caseShader.getShader());
		shaders.deleteShader(m_shaderType);
	}
};

class ProgramStateReplaceShaderCase : public ProgramStateCase
{
public:
	ProgramStateReplaceShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ProgramStateCase (context, name, desc, shaderType)
	{
	}

	virtual ~ProgramStateReplaceShaderCase (void)
	{
	}

	void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
	{
		TestLog&		log			= m_testCtx.getLog();
		glu::Shader&	caseShader	= shaders.get(m_shaderType);

		log << TestLog::Message << "Deleting and replacing " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
		program.detachShader(caseShader.getShader());
		shaders.deleteShader(m_shaderType);
		program.attachShader(shaders.createShader(m_shaderType).getShader());
	}
};

class ProgramStateRecompileShaderCase : public ProgramStateCase
{
public:
	ProgramStateRecompileShaderCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ProgramStateCase (context, name, desc, shaderType)
	{
	}

	virtual ~ProgramStateRecompileShaderCase (void)
	{
	}

	void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
	{
		TestLog&		log			= m_testCtx.getLog();
		glu::Shader&	caseShader	= shaders.get(m_shaderType);

		log << TestLog::Message << "Recompiling " + std::string(getShaderTypeName(m_shaderType)) + " shader" << TestLog::EndMessage;
		caseShader.compile();
		DE_UNREF(program);
	}
};

class ProgramStateReplaceSourceCase : public ProgramStateCase
{
public:
	ProgramStateReplaceSourceCase (Context& context, const char* name, const char* desc, glu::ShaderType shaderType)
		: ProgramStateCase (context, name, desc, shaderType)
	{
	}

	virtual ~ProgramStateReplaceSourceCase (void)
	{
	}

	void executeForProgram (glu::Program& program, ShaderAllocator& shaders)
	{
		TestLog&		log			= m_testCtx.getLog();
		glu::Shader&	caseShader	= shaders.get(m_shaderType);

		log << TestLog::Message << "Replacing " + std::string(getShaderTypeName(m_shaderType)) + " shader source and recompiling" << TestLog::EndMessage;
		shaders.setSource(m_shaderType);
		caseShader.compile();
		DE_UNREF(program);
	}
};

// Test group

ShaderApiTests::ShaderApiTests (Context& context)
	: TestCaseGroup(context, "shader_api", "Shader API Cases")
{
}

ShaderApiTests::~ShaderApiTests (void)
{
}

void ShaderApiTests::init (void)
{
	// create and delete shaders
	{
		TestCaseGroup* createDeleteGroup = new TestCaseGroup(m_context, "create_delete", "glCreateShader() tests");
		addChild(createDeleteGroup);

		createDeleteGroup->addChild(new CreateShaderCase(m_context,	"create_vertex_shader",		"Create vertex shader object",		glu::SHADERTYPE_VERTEX));
		createDeleteGroup->addChild(new CreateShaderCase(m_context,	"create_fragment_shader",	"Create fragment shader object",	glu::SHADERTYPE_FRAGMENT));

		createDeleteGroup->addChild(new DeleteShaderCase(m_context,	"delete_vertex_fragment",	"Delete vertex shader and fragment shader"));
	}

	// compile and link
	{
		TestCaseGroup* compileLinkGroup = new TestCaseGroup(m_context, "compile_link", "Compile and link tests");
		addChild(compileLinkGroup);

		compileLinkGroup->addChild(new CompileShaderCase(m_context,	"compile_vertex_shader",	"Compile vertex shader",	glu::SHADERTYPE_VERTEX));
		compileLinkGroup->addChild(new CompileShaderCase(m_context,	"compile_fragment_shader",	"Compile fragment shader",	glu::SHADERTYPE_FRAGMENT));

		compileLinkGroup->addChild(new LinkVertexFragmentCase(m_context,	"link_vertex_fragment",	"Link vertex and fragment shaders"));
	}

	// shader source
	{
		TestCaseGroup* shaderSourceGroup = new TestCaseGroup(m_context, "shader_source", "glShaderSource() tests");
		addChild(shaderSourceGroup);

		for (int shaderTypeInt = 0; shaderTypeInt < 2; shaderTypeInt++)
		{
			const glu::ShaderType	shaderType	= (shaderTypeInt == 1) ? glu::SHADERTYPE_FRAGMENT : glu::SHADERTYPE_VERTEX;

			const std::string		caseName	= std::string("replace_source") + ((shaderType == glu::SHADERTYPE_FRAGMENT) ? "_fragment" : "_vertex");
			const std::string		caseDesc	= std::string("Replace source code of ") + ((shaderType == glu::SHADERTYPE_FRAGMENT) ? "fragment" : "vertex") + " shader.";

			shaderSourceGroup->addChild(new ShaderSourceReplaceCase(m_context, caseName.c_str(), caseDesc.c_str(), shaderType));
		}

		for (int stringLengthsInt	= 0; stringLengthsInt < 3; stringLengthsInt++)
		for (int caseNdx = 1; caseNdx <= 3; caseNdx++)
		for (int shaderTypeInt = 0; shaderTypeInt < 2; shaderTypeInt++)
		{
			const int				numSlices		= 1 << caseNdx;
			const glu::ShaderType	shaderType		= (shaderTypeInt == 1) ? glu::SHADERTYPE_FRAGMENT : glu::SHADERTYPE_VERTEX;

			const bool				explicitLengths	= (stringLengthsInt != 0);
			const bool				randomNullTerm	= (stringLengthsInt == 2);

			const deUint32			flags			= (explicitLengths	? CASE_EXPLICIT_SOURCE_LENGTHS	: 0)
													| (randomNullTerm	? CASE_RANDOM_NULL_TERMINATED	: 0);

			const std::string		caseName		= "split_source_"
													+ de::toString(numSlices)
													+ (randomNullTerm ? "_random_negative_length" : (explicitLengths ? "_specify_lengths" : "_null_terminated"))
													+ ((shaderType == glu::SHADERTYPE_FRAGMENT) ? "_fragment" : "_vertex");

			const std::string		caseDesc		= std::string((shaderType == glu::SHADERTYPE_FRAGMENT) ? "Fragment" : "Vertex")
													+ " shader source split into "
													+ de::toString(numSlices)
													+ " pieces"
													+ (explicitLengths ? ", using explicitly specified string lengths" : "")
													+ (randomNullTerm ? " with random negative length values" : "");

			shaderSourceGroup->addChild(new ShaderSourceSplitCase(m_context, caseName.c_str(), caseDesc.c_str(), shaderType, numSlices, flags));
		}
	}

	// link status and infolog
	{
		TestCaseGroup* linkStatusGroup = new TestCaseGroup(m_context, "program_state", "Program state persistence tests");
		addChild(linkStatusGroup);

		addProgramStateCase<ProgramStateDetachShaderCase>		(linkStatusGroup,	m_context,	"detach_shader",	"detach shader");
		addProgramStateCase<ProgramStateReattachShaderCase>		(linkStatusGroup,	m_context,	"reattach_shader",	"reattach shader");
		addProgramStateCase<ProgramStateDeleteShaderCase>		(linkStatusGroup,	m_context,	"delete_shader",	"delete shader");
		addProgramStateCase<ProgramStateReplaceShaderCase>		(linkStatusGroup,	m_context,	"replace_shader",	"replace shader object");
		addProgramStateCase<ProgramStateRecompileShaderCase>	(linkStatusGroup,	m_context,	"recompile_shader",	"recompile shader");
		addProgramStateCase<ProgramStateReplaceSourceCase>		(linkStatusGroup,	m_context,	"replace_source",	"replace shader source");
	}
}

} // Functional
} // gles2
} // deqp
