/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) 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 Common object lifetime tests.
 *//*--------------------------------------------------------------------*/

#include "glsLifetimeTests.hpp"

#include "deString.h"
#include "deRandom.hpp"
#include "deSTLUtil.hpp"
#include "deStringUtil.hpp"
#include "tcuRGBA.hpp"
#include "tcuImageCompare.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuTestLog.hpp"
#include "gluDrawUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "gluPixelTransfer.hpp"
#include "gluShaderProgram.hpp"
#include "gluDefs.hpp"
#include "gluTextureUtil.hpp"
#include "gluStrUtil.hpp"
#include "glwFunctions.hpp"

#include <vector>
#include <map>
#include <algorithm>
#include <sstream>

namespace deqp
{
namespace gls
{
namespace LifetimeTests
{
namespace details
{

using std::map;
using std::string;
using std::ostringstream;
using de::Random;
using tcu::RenderTarget;
using tcu::RGBA;
using tcu::StringTemplate;
using tcu::TestCase;
typedef TestCase::IterateResult IterateResult;
using tcu::TestLog;
using tcu::ScopedLogSection;
using glu::Program;
using glu::Shader;
using glu::Framebuffer;
using glu::SHADERTYPE_VERTEX;
using glu::SHADERTYPE_FRAGMENT;
using namespace glw;

enum { VIEWPORT_SIZE = 128, FRAMEBUFFER_SIZE = 128 };

GLint getInteger (ContextWrapper& gl, GLenum queryParam)
{
	GLint ret = 0;
	GLU_CHECK_CALL_ERROR(
		gl.glGetIntegerv(queryParam, &ret),
		gl.glGetError());
	gl.log() << TestLog::Message << "// Single integer output: " << ret << TestLog::EndMessage;
	return ret;
}

#define GLSL100_SRC(BODY) ("#version 100\n" #BODY "\n")

static const char* const s_vertexShaderSrc = GLSL100_SRC(
	attribute vec2 pos;
	void main()
	{
		gl_Position = vec4(pos.xy, 0.0, 1.0);
	}
	);

static const char* const s_fragmentShaderSrc = GLSL100_SRC(
	void main()
	{
		gl_FragColor = vec4(1.0);
	}
	);

class CheckedShader : public Shader
{
public:
	CheckedShader (const RenderContext& renderCtx, glu::ShaderType type, const string& src)
		: Shader (renderCtx, type)
	{
		const char* const srcStr = src.c_str();
		setSources(1, &srcStr, DE_NULL);
		compile();
		TCU_CHECK(getCompileStatus());
	}
};

class CheckedProgram : public Program
{
public:
	CheckedProgram	(const RenderContext& renderCtx, GLuint vtxShader, GLuint fragShader)
		: Program	(renderCtx)
	{
		attachShader(vtxShader);
		attachShader(fragShader);
		link();
		TCU_CHECK(getLinkStatus());
	}
};

ContextWrapper::ContextWrapper (const Context& ctx)
	: CallLogWrapper	(ctx.gl(), ctx.log())
	, m_ctx				(ctx)
{
	enableLogging(true);
}

void SimpleBinder::bind (GLuint name)
{
	(this->*m_bindFunc)(m_bindTarget, name);
}

GLuint SimpleBinder::getBinding (void)
{
	return getInteger(*this, m_bindingParam);
}

GLuint SimpleType::gen (void)
{
	GLuint ret;
	(this->*m_genFunc)(1, &ret);
	return ret;
}

class VertexArrayBinder : public SimpleBinder
{
public:
						VertexArrayBinder	(Context& ctx)
							: SimpleBinder	(ctx, 0, GL_NONE, GL_VERTEX_ARRAY_BINDING, true) {}
	void				bind				(GLuint name) { glBindVertexArray(name); }
};

class QueryBinder : public Binder
{
public:
						QueryBinder		(Context& ctx) : Binder(ctx) {}
	void				bind			(GLuint name)
	{
		if (name != 0)
			glBeginQuery(GL_ANY_SAMPLES_PASSED, name);
		else
			glEndQuery(GL_ANY_SAMPLES_PASSED);
	}
	GLuint				getBinding		(void) { return 0; }
};

bool ProgramType::isDeleteFlagged (GLuint name)
{
	GLint deleteFlagged = 0;
	glGetProgramiv(name, GL_DELETE_STATUS, &deleteFlagged);
	return deleteFlagged != 0;
}

bool ShaderType::isDeleteFlagged (GLuint name)
{
	GLint deleteFlagged = 0;
	glGetShaderiv(name, GL_DELETE_STATUS, &deleteFlagged);
	return deleteFlagged != 0;
}

void setupFbo (const Context& ctx, GLuint seed, GLuint fbo)
{
	const Functions& gl = ctx.getRenderContext().getFunctions();

	GLU_CHECK_CALL_ERROR(gl.bindFramebuffer(GL_FRAMEBUFFER, fbo),
						 gl.getError());

	if (seed == 0)
	{
		gl.clearColor(0.0, 0.0, 0.0, 1.0);
		GLU_CHECK_CALL_ERROR(gl.clear(GL_COLOR_BUFFER_BIT), gl.getError());
	}
	else
	{
		Random			rnd		(seed);
		const GLsizei	width	= rnd.getInt(0, FRAMEBUFFER_SIZE);
		const GLsizei	height	= rnd.getInt(0, FRAMEBUFFER_SIZE);
		const GLint		x		= rnd.getInt(0, FRAMEBUFFER_SIZE - width);
		const GLint		y		= rnd.getInt(0, FRAMEBUFFER_SIZE - height);
		const GLfloat	r1		= rnd.getFloat();
		const GLfloat	g1		= rnd.getFloat();
		const GLfloat	b1		= rnd.getFloat();
		const GLfloat	a1		= rnd.getFloat();
		const GLfloat	r2		= rnd.getFloat();
		const GLfloat	g2		= rnd.getFloat();
		const GLfloat	b2		= rnd.getFloat();
		const GLfloat	a2		= rnd.getFloat();

		GLU_CHECK_CALL_ERROR(gl.clearColor(r1, g1, b1, a1), gl.getError());
		GLU_CHECK_CALL_ERROR(gl.clear(GL_COLOR_BUFFER_BIT), gl.getError());
		gl.scissor(x, y, width, height);
		gl.enable(GL_SCISSOR_TEST);
		gl.clearColor(r2, g2, b2, a2);
		gl.clear(GL_COLOR_BUFFER_BIT);
		gl.disable(GL_SCISSOR_TEST);
	}

	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
	GLU_CHECK_ERROR(gl.getError());
}

void drawFbo (const Context& ctx, GLuint fbo, Surface& dst)
{
	const RenderContext& renderCtx = ctx.getRenderContext();
	const Functions& gl = renderCtx.getFunctions();

	GLU_CHECK_CALL_ERROR(
		gl.bindFramebuffer(GL_FRAMEBUFFER, fbo),
		gl.getError());

	dst.setSize(FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE);
	glu::readPixels(renderCtx, 0, 0, dst.getAccess());
	GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels from framebuffer");

	GLU_CHECK_CALL_ERROR(
		gl.bindFramebuffer(GL_FRAMEBUFFER, 0),
		gl.getError());
}

GLuint getFboAttachment (const Functions& gl, GLuint fbo, GLenum requiredType)
{
	GLint type = 0, name = 0;
	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
	GLU_CHECK_CALL_ERROR(
		gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
											   GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
											   &type),
		gl.getError());

	if (GLenum(type) != requiredType || GLenum(type) == GL_NONE)
		return 0;

	GLU_CHECK_CALL_ERROR(
		gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
											   GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
											   &name),
		gl.getError());
	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
	GLU_CHECK_ERROR(gl.getError());

	return name;
}

void FboAttacher::initAttachment (GLuint seed, GLuint element)
{
	Binder& binder = *getElementType().binder();
	Framebuffer fbo(getRenderContext());

	enableLogging(false);

	binder.enableLogging(false);
	binder.bind(element);
	initStorage();
	binder.bind(0);
	binder.enableLogging(true);

	attach(element, *fbo);
	setupFbo(getContext(), seed, *fbo);
	detach(element, *fbo);

	enableLogging(true);

	log() << TestLog::Message
		  << "// Drew to " << getElementType().getName() << " " << element
		  << " with seed " << seed << "."
		  << TestLog::EndMessage;
}

void FboInputAttacher::drawContainer (GLuint fbo, Surface& dst)
{
	drawFbo(getContext(), fbo, dst);
	log() << TestLog::Message
		  << "// Read pixels from framebuffer " << fbo << " to output image."
		  << TestLog::EndMessage;
}

void FboOutputAttacher::setupContainer (GLuint seed, GLuint fbo)
{
	setupFbo(getContext(), seed, fbo);
	log() << TestLog::Message
		  << "// Drew to framebuffer " << fbo << " with seed " << seed << "."
		  << TestLog::EndMessage;
}

void FboOutputAttacher::drawAttachment (GLuint element, Surface& dst)
{
	Framebuffer fbo(getRenderContext());
	m_attacher.enableLogging(false);
	m_attacher.attach(element, *fbo);
	drawFbo(getContext(), *fbo, dst);
	m_attacher.detach(element, *fbo);
	m_attacher.enableLogging(true);
	log() << TestLog::Message
		  << "// Read pixels from " << m_attacher.getElementType().getName() << " " << element
		  << " to output image."
		  << TestLog::EndMessage;
	GLU_CHECK_ERROR(gl().getError());
}

void TextureFboAttacher::attach (GLuint texture, GLuint fbo)
{
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, fbo),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
								  GL_TEXTURE_2D, texture, 0),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, 0),
		gl().getError());
}

void TextureFboAttacher::detach (GLuint texture, GLuint fbo)
{
	DE_UNREF(texture);
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, fbo),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, 0),
		gl().getError());
}

GLuint TextureFboAttacher::getAttachment (GLuint fbo)
{
	return getFboAttachment(gl(), fbo, GL_TEXTURE);
}

static bool isTextureFormatColorRenderable (const glu::RenderContext& renderCtx, const glu::TransferFormat& format)
{
	const glw::Functions&	gl			= renderCtx.getFunctions();
	deUint32				curFbo		= ~0u;
	deUint32				curTex		= ~0u;
	deUint32				testFbo		= 0u;
	deUint32				testTex		= 0u;
	GLenum					status		= GL_NONE;

	GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_FRAMEBUFFER_BINDING, (deInt32*)&curFbo));
	GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_TEXTURE_BINDING_2D, (deInt32*)&curTex));

	try
	{
		GLU_CHECK_GLW_CALL(gl, genTextures(1, &testTex));
		GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, testTex));
		GLU_CHECK_GLW_CALL(gl, texImage2D(GL_TEXTURE_2D, 0, format.format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE, 0,
										  format.format, format.dataType, DE_NULL));

		GLU_CHECK_GLW_CALL(gl, genFramebuffers(1, &testFbo));
		GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, testFbo));
		GLU_CHECK_GLW_CALL(gl, framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, testTex, 0));

		status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
		GLU_CHECK_GLW_MSG(gl, "glCheckFramebufferStatus(GL_FRAMEBUFFER)");

		GLU_CHECK_GLW_CALL(gl, bindTexture(GL_TEXTURE_2D, curTex));
		GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, curFbo));

		GLU_CHECK_GLW_CALL(gl, deleteTextures(1, &testTex));
		GLU_CHECK_GLW_CALL(gl, deleteFramebuffers(1, &testFbo));
	}
	catch (...)
	{
		if (testTex != 0)
			gl.deleteTextures(1, &testTex);

		if (testFbo != 0)
			gl.deleteFramebuffers(1, &testFbo);

		throw;
	}

	if (status == GL_FRAMEBUFFER_COMPLETE)
		return true;
	else if (status == GL_FRAMEBUFFER_UNSUPPORTED)
		return false;
	else
		TCU_THROW(TestError, (std::string("glCheckFramebufferStatus() returned invalid result code ")
							  + de::toString(glu::getFramebufferStatusStr(status))).c_str());
}

static glu::TransferFormat getRenderableColorTextureFormat (const glu::RenderContext& renderCtx)
{
	if (glu::contextSupports(renderCtx.getType(), glu::ApiType::es(3,0)))
		return glu::TransferFormat(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);

	{
		const glu::TransferFormat	candidates[]	=
		{
			glu::TransferFormat(GL_RGBA,	GL_UNSIGNED_SHORT_4_4_4_4),
			glu::TransferFormat(GL_RGBA,	GL_UNSIGNED_SHORT_5_5_5_1),
			glu::TransferFormat(GL_RGB,		GL_UNSIGNED_SHORT_5_6_5),
			glu::TransferFormat(GL_RGBA,	GL_UNSIGNED_BYTE),
		};

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(candidates); ++ndx)
		{
			if (isTextureFormatColorRenderable(renderCtx, candidates[ndx]))
				return candidates[ndx];
		}
	}

	return glu::TransferFormat(GL_NONE, GL_NONE);
}

void TextureFboAttacher::initStorage (void)
{
	const glu::TransferFormat	format	= getRenderableColorTextureFormat(getRenderContext());

	if (format.format == GL_NONE)
		TCU_THROW(NotSupportedError, "No renderable texture format found");

	GLU_CHECK_CALL_ERROR(
		glTexImage2D(GL_TEXTURE_2D, 0, format.format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE, 0,
					 format.format, format.dataType, DE_NULL),
		gl().getError());
}

static bool isRenderbufferFormatColorRenderable (const glu::RenderContext& renderCtx, const deUint32 format)
{
	const glw::Functions&	gl			= renderCtx.getFunctions();
	deUint32				curFbo		= ~0u;
	deUint32				curRbo		= ~0u;
	deUint32				testFbo		= 0u;
	deUint32				testRbo		= 0u;
	GLenum					status		= GL_NONE;

	GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_FRAMEBUFFER_BINDING, (deInt32*)&curFbo));
	GLU_CHECK_GLW_CALL(gl, getIntegerv(GL_RENDERBUFFER_BINDING, (deInt32*)&curRbo));

	try
	{
		GLU_CHECK_GLW_CALL(gl, genRenderbuffers(1, &testRbo));
		GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, testRbo));
		GLU_CHECK_GLW_CALL(gl, renderbufferStorage(GL_RENDERBUFFER, format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE));

		GLU_CHECK_GLW_CALL(gl, genFramebuffers(1, &testFbo));
		GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, testFbo));
		GLU_CHECK_GLW_CALL(gl, framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, testRbo));

		status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
		GLU_CHECK_GLW_MSG(gl, "glCheckFramebufferStatus(GL_FRAMEBUFFER)");

		GLU_CHECK_GLW_CALL(gl, bindRenderbuffer(GL_RENDERBUFFER, curRbo));
		GLU_CHECK_GLW_CALL(gl, bindFramebuffer(GL_FRAMEBUFFER, curFbo));

		GLU_CHECK_GLW_CALL(gl, deleteRenderbuffers(1, &testRbo));
		GLU_CHECK_GLW_CALL(gl, deleteFramebuffers(1, &testFbo));
	}
	catch (...)
	{
		if (testRbo != 0)
			gl.deleteRenderbuffers(1, &testRbo);

		if (testFbo != 0)
			gl.deleteFramebuffers(1, &testFbo);

		throw;
	}

	if (status == GL_FRAMEBUFFER_COMPLETE)
		return true;
	else if (status == GL_FRAMEBUFFER_UNSUPPORTED)
		return false;
	else
		TCU_THROW(TestError, (std::string("glCheckFramebufferStatus() returned invalid result code ")
							  + de::toString(glu::getFramebufferStatusStr(status))).c_str());
}

static deUint32 getRenderableColorRenderbufferFormat (const glu::RenderContext& renderCtx)
{
	if (glu::contextSupports(renderCtx.getType(), glu::ApiType::es(3,0)))
		return GL_RGBA4;

	{
		const deUint32	candidates[]	=
		{
			GL_RGBA4,
			GL_RGB5_A1,
			GL_RGB565,
		};

		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(candidates); ++ndx)
		{
			if (isRenderbufferFormatColorRenderable(renderCtx, candidates[ndx]))
				return candidates[ndx];
		}
	}

	return GL_NONE;
}

void RboFboAttacher::initStorage (void)
{
	const deUint32	format	= getRenderableColorRenderbufferFormat(getRenderContext());

	if (format == GL_NONE)
		TCU_THROW(TestError, "No color-renderable renderbuffer format found");

	GLU_CHECK_CALL_ERROR(
		glRenderbufferStorage(GL_RENDERBUFFER, format, FRAMEBUFFER_SIZE, FRAMEBUFFER_SIZE),
		gl().getError());
}

void RboFboAttacher::attach (GLuint rbo, GLuint fbo)
{
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, fbo),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, 0),
		gl().getError());
}

void RboFboAttacher::detach (GLuint rbo, GLuint fbo)
{
	DE_UNREF(rbo);
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, fbo),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0),
		gl().getError());
	GLU_CHECK_CALL_ERROR(
		glBindFramebuffer(GL_FRAMEBUFFER, 0),
		gl().getError());
}

GLuint RboFboAttacher::getAttachment (GLuint fbo)
{
	return getFboAttachment(gl(), fbo, GL_RENDERBUFFER);
}

static const char* const s_fragmentShaderTemplate = GLSL100_SRC(
	void main()
	{
		gl_FragColor = vec4(${RED}, ${GREEN}, ${BLUE}, 1.0);
	}
	);

void ShaderProgramAttacher::initAttachment (GLuint seed, GLuint shader)
{
	using					de::insert;
	using					de::floatToString;

	Random					rnd(seed);
	map<string, string>		params;
	const StringTemplate	sourceTmpl	(s_fragmentShaderTemplate);

	insert(params, "RED",	floatToString(rnd.getFloat(), 4));
	insert(params, "GREEN",	floatToString(rnd.getFloat(), 4));
	insert(params, "BLUE",	floatToString(rnd.getFloat(), 4));

	{
		const string			source		= sourceTmpl.specialize(params);
		const char* const		sourceStr	= source.c_str();

		GLU_CHECK_CALL_ERROR(glShaderSource(shader, 1, &sourceStr, DE_NULL), gl().getError());
		GLU_CHECK_CALL_ERROR(glCompileShader(shader), gl().getError());

		{
			GLint compileStatus = 0;
			gl().getShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
			TCU_CHECK_MSG(compileStatus != 0, sourceStr);
		}
	}
}

void ShaderProgramAttacher::attach (GLuint shader, GLuint program)
{
	GLU_CHECK_CALL_ERROR(
		glAttachShader(program, shader),
		gl().getError());
}

void ShaderProgramAttacher::detach (GLuint shader, GLuint program)
{
	GLU_CHECK_CALL_ERROR(
		glDetachShader(program, shader),
		gl().getError());
}

GLuint ShaderProgramAttacher::getAttachment (GLuint program)
{
	GLuint			shaders[2]	= { 0, 0 };
	const GLsizei	shadersLen	= DE_LENGTH_OF_ARRAY(shaders);
	GLsizei			numShaders	= 0;
	GLuint			ret			= 0;

	gl().getAttachedShaders(program, shadersLen, &numShaders, shaders);

	// There should ever be at most one attached shader in normal use, but if
	// something is wrong, the temporary vertex shader might not have been
	// detached properly, so let's find the fragment shader explicitly.
	for (int ndx = 0; ndx < de::min<GLsizei>(shadersLen, numShaders); ++ndx)
	{
		GLint shaderType = GL_NONE;
		gl().getShaderiv(shaders[ndx], GL_SHADER_TYPE, &shaderType);

		if (shaderType == GL_FRAGMENT_SHADER)
		{
			ret = shaders[ndx];
			break;
		}
	}

	return ret;
}

void setViewport (const RenderContext& renderCtx, const Rectangle& rect)
{
	renderCtx.getFunctions().viewport(rect.x, rect.y, rect.width, rect.height);
}

void readRectangle (const RenderContext& renderCtx, const Rectangle& rect, Surface& dst)
{
	dst.setSize(rect.width, rect.height);
	glu::readPixels(renderCtx, rect.x, rect.y, dst.getAccess());
}

Rectangle randomViewport (const RenderContext& ctx, GLint maxWidth, GLint maxHeight,
						  Random& rnd)
{
	const RenderTarget&	target	= ctx.getRenderTarget();
	const GLint			width	= de::min(target.getWidth(), maxWidth);
	const GLint			xOff	= rnd.getInt(0, target.getWidth() - width);
	const GLint			height	= de::min(target.getHeight(), maxHeight);
	const GLint			yOff	= rnd.getInt(0, target.getHeight() - height);

	return Rectangle(xOff, yOff, width, height);
}

void ShaderProgramInputAttacher::drawContainer (GLuint program, Surface& dst)
{
	static const float	s_vertices[6]	= { -1.0, 0.0, 1.0, 1.0, 0.0, -1.0 };
	Random				rnd				(program);
	CheckedShader		vtxShader		(getRenderContext(),
										 SHADERTYPE_VERTEX, s_vertexShaderSrc);
	const Rectangle		viewport		= randomViewport(getRenderContext(),
														 VIEWPORT_SIZE, VIEWPORT_SIZE, rnd);

	gl().attachShader(program, vtxShader.getShader());
	gl().linkProgram(program);

	{
		GLint linkStatus = 0;
		gl().getProgramiv(program, GL_LINK_STATUS, &linkStatus);
		TCU_CHECK(linkStatus != 0);
	}

	log() << TestLog::Message
		  << "// Attached a temporary vertex shader and linked program " << program
		  << TestLog::EndMessage;

	setViewport(getRenderContext(), viewport);
	log() << TestLog::Message << "// Positioned viewport randomly" << TestLog::EndMessage;

	glUseProgram(program);
	{
		GLint posLoc = gl().getAttribLocation(program, "pos");
		TCU_CHECK(posLoc >= 0);

		gl().enableVertexAttribArray(posLoc);

		gl().clearColor(0, 0, 0, 1);
		gl().clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		gl().vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, s_vertices);
		gl().drawArrays(GL_TRIANGLES, 0, 3);

		gl().disableVertexAttribArray(posLoc);
		log () << TestLog::Message << "// Drew a fixed triangle" << TestLog::EndMessage;
	}
	glUseProgram(0);

	readRectangle(getRenderContext(), viewport, dst);
	log() << TestLog::Message << "// Copied viewport to output image" << TestLog::EndMessage;

	gl().detachShader(program, vtxShader.getShader());
	log() << TestLog::Message << "// Removed temporary vertex shader" << TestLog::EndMessage;
}

ES2Types::ES2Types (const Context& ctx)
	: Types			(ctx)
	, m_bufferBind	(ctx, &CallLogWrapper::glBindBuffer,
					 GL_ARRAY_BUFFER, GL_ARRAY_BUFFER_BINDING)
	, m_bufferType	(ctx, "buffer", &CallLogWrapper::glGenBuffers,
					 &CallLogWrapper::glDeleteBuffers,
					 &CallLogWrapper::glIsBuffer, &m_bufferBind)
	, m_textureBind	(ctx, &CallLogWrapper::glBindTexture, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D)
	, m_textureType	(ctx, "texture", &CallLogWrapper::glGenTextures,
					 &CallLogWrapper::glDeleteTextures,
					 &CallLogWrapper::glIsTexture, &m_textureBind)
	, m_rboBind		(ctx, &CallLogWrapper::glBindRenderbuffer,
					 GL_RENDERBUFFER, GL_RENDERBUFFER_BINDING)
	, m_rboType		(ctx, "renderbuffer",
					 &CallLogWrapper::glGenRenderbuffers,
					 &CallLogWrapper::glDeleteRenderbuffers,
					 &CallLogWrapper::glIsRenderbuffer, &m_rboBind)
	, m_fboBind		(ctx, &CallLogWrapper::glBindFramebuffer,
					 GL_FRAMEBUFFER, GL_FRAMEBUFFER_BINDING)
	, m_fboType		(ctx, "framebuffer",
					 &CallLogWrapper::glGenFramebuffers,
					 &CallLogWrapper::glDeleteFramebuffers,
					 &CallLogWrapper::glIsFramebuffer, &m_fboBind)
	, m_shaderType	(ctx)
	, m_programType	(ctx)
	, m_texFboAtt	(ctx, m_textureType, m_fboType)
	, m_texFboInAtt	(m_texFboAtt)
	, m_texFboOutAtt(m_texFboAtt)
	, m_rboFboAtt	(ctx, m_rboType, m_fboType)
	, m_rboFboInAtt	(m_rboFboAtt)
	, m_rboFboOutAtt(m_rboFboAtt)
	, m_shaderAtt	(ctx, m_shaderType, m_programType)
	, m_shaderInAtt	(m_shaderAtt)
{
	Type* const types[] =
	{
		&m_bufferType, &m_textureType, &m_rboType, &m_fboType, &m_shaderType, &m_programType
	};
	m_types.insert(m_types.end(), DE_ARRAY_BEGIN(types), DE_ARRAY_END(types));

	m_attachers.push_back(&m_texFboAtt);
	m_attachers.push_back(&m_rboFboAtt);
	m_attachers.push_back(&m_shaderAtt);

	m_inAttachers.push_back(&m_texFboInAtt);
	m_inAttachers.push_back(&m_rboFboInAtt);
	m_inAttachers.push_back(&m_shaderInAtt);

	m_outAttachers.push_back(&m_texFboOutAtt);
	m_outAttachers.push_back(&m_rboFboOutAtt);
}

class Name
{
public:
				Name		(Type& type) : m_type(type), m_name(type.gen()) {}
				Name		(Type& type, GLuint name) : m_type(type), m_name(name) {}
				~Name		(void) { m_type.release(m_name); }
	GLuint		operator*	(void) const { return m_name; }

private:
	Type&			m_type;
	const GLuint	m_name;
};

class ResultCollector
{
public:
					ResultCollector		(TestContext& testCtx);
	bool			check				(bool cond, const char* msg);
	void			fail				(const char* msg);
	void			warn				(const char* msg);
					~ResultCollector	(void);

private:
	void			addResult			(qpTestResult result, const char* msg);

	TestContext&	m_testCtx;
	TestLog&		m_log;
	qpTestResult	m_result;
	const char*		m_message;
};

ResultCollector::ResultCollector (TestContext& testCtx)
	: m_testCtx		(testCtx)
	, m_log			(testCtx.getLog())
	, m_result		(QP_TEST_RESULT_PASS)
	, m_message		("Pass")
{
}

bool ResultCollector::check (bool cond, const char* msg)
{
	if (!cond)
		fail(msg);
	return cond;
}

void ResultCollector::addResult (qpTestResult result, const char* msg)
{
	m_log << TestLog::Message << "// Fail: " << msg << TestLog::EndMessage;
	if (m_result == QP_TEST_RESULT_PASS)
	{
		m_result = result;
		m_message = msg;
	}
	else
	{
		if (result == QP_TEST_RESULT_FAIL)
			m_result = result;
		m_message = "Multiple problems, see log for details";
	}
}

void ResultCollector::fail (const char* msg)
{
	addResult(QP_TEST_RESULT_FAIL, msg);
}

void ResultCollector::warn (const char* msg)
{
	addResult(QP_TEST_RESULT_QUALITY_WARNING, msg);
}

ResultCollector::~ResultCollector (void)
{
	m_testCtx.setTestResult(m_result, m_message);
}

class TestBase : public TestCase, protected CallLogWrapper
{
protected:
							TestBase			(const char*	name,
												 const char*	description,
												 const Context&	ctx);

	// Copy ContextWrapper since MI (except for CallLogWrapper) is a no-no.
	const Context&			getContext			(void) const { return m_ctx; }
	const RenderContext&	getRenderContext	(void) const { return m_ctx.getRenderContext(); }
	const Functions&		gl					(void) const { return m_ctx.gl(); }
	TestLog&				log					(void) const { return m_ctx.log(); }
	void					init				(void);

	Context					m_ctx;
	Random					m_rnd;
};

TestBase::TestBase (const char* name, const char* description, const Context& ctx)
	: TestCase			(ctx.getTestContext(), name, description)
	, CallLogWrapper	(ctx.gl(), ctx.log())
	, m_ctx				(ctx)
	, m_rnd				(deStringHash(name))
{
	enableLogging(true);
}

void TestBase::init (void)
{
	m_rnd = Random(deStringHash(getName()));
}

class LifeTest : public TestBase
{
public:
	typedef void			(LifeTest::*TestFunction)	(void);

							LifeTest					(const char*	name,
														 const char*	description,
														 Type&			type,
														 TestFunction	test)
								: TestBase		(name, description, type.getContext())
								, m_type		(type)
								, m_test		(test) {}

	IterateResult			iterate						(void);

	void					testGen						(void);
	void					testDelete					(void);
	void					testBind					(void);
	void					testDeleteBound				(void);
	void					testBindNoGen				(void);
	void					testDeleteUsed				(void);

private:
	Binder&					binder						(void) { return *m_type.binder(); }

	Type&					m_type;
	TestFunction			m_test;
};

IterateResult LifeTest::iterate (void)
{
	(this->*m_test)();
	return STOP;
}

void LifeTest::testGen (void)
{
	ResultCollector	errors	(getTestContext());
	Name			name	(m_type);

	if (m_type.genCreates())
		errors.check(m_type.exists(*name), "Gen* should have created an object, but didn't");
	else
		errors.check(!m_type.exists(*name), "Gen* should not have created an object, but did");
}

void LifeTest::testDelete (void)
{
	ResultCollector	errors	(getTestContext());
	GLuint			name	= m_type.gen();

	m_type.release(name);
	errors.check(!m_type.exists(name), "Object still exists after deletion");
}

void LifeTest::testBind (void)
{
	ResultCollector	errors	(getTestContext());
	Name			name	(m_type);

	binder().bind(*name);
	GLU_EXPECT_NO_ERROR(gl().getError(), "Bind failed");
	errors.check(m_type.exists(*name), "Object does not exist after binding");
	binder().bind(0);
}

void LifeTest::testDeleteBound (void)
{
	const GLuint	id		= m_type.gen();
	ResultCollector	errors	(getTestContext());

	binder().bind(id);
	m_type.release(id);

	if (m_type.nameLingers())
	{
		errors.check(gl().getError() == GL_NO_ERROR, "Deleting bound object failed");
		errors.check(binder().getBinding() == id,
					 "Deleting bound object did not retain binding");
		errors.check(m_type.exists(id),
					 "Deleting bound object made its name invalid");
		errors.check(m_type.isDeleteFlagged(id),
					 "Deleting bound object did not flag the object for deletion");
		binder().bind(0);
	}
	else
	{
		errors.check(gl().getError() == GL_NO_ERROR, "Deleting bound object failed");
		errors.check(binder().getBinding() == 0,
					 "Deleting bound object did not remove binding");
		errors.check(!m_type.exists(id),
					 "Deleting bound object did not make its name invalid");
		binder().bind(0);
	}

	errors.check(binder().getBinding() == 0, "Unbinding didn't remove binding");
	errors.check(!m_type.exists(id), "Name is still valid after deleting and unbinding");
}

void LifeTest::testBindNoGen (void)
{
	ResultCollector	errors	(getTestContext());
	const GLuint	id		= m_rnd.getUint32();

	if (!errors.check(!m_type.exists(id), "Randomly chosen identifier already exists"))
		return;

	Name			name	(m_type, id);
	binder().bind(*name);

	if (binder().genRequired())
	{
		errors.check(glGetError() == GL_INVALID_OPERATION,
					 "Did not fail when binding a name not generated by Gen* call");
		errors.check(!m_type.exists(*name),
					 "Bind* created an object for a name not generated by a Gen* call");
	}
	else
	{
		errors.check(glGetError() == GL_NO_ERROR,
					 "Failed when binding a name not generated by Gen* call");
		errors.check(m_type.exists(*name),
					 "Object was not created by the Bind* call");
	}
}

void LifeTest::testDeleteUsed (void)
{
	ResultCollector	errors(getTestContext());
	GLuint			programId = 0;

	{
		CheckedShader	vtxShader	(getRenderContext(),
									 SHADERTYPE_VERTEX, s_vertexShaderSrc);
		CheckedShader	fragShader	(getRenderContext(),
									 SHADERTYPE_FRAGMENT, s_fragmentShaderSrc);
		CheckedProgram	program		(getRenderContext(),
									 vtxShader.getShader(), fragShader.getShader());

		programId = program.getProgram();

		log() << TestLog::Message << "// Created and linked program " << programId
			  << TestLog::EndMessage;
		GLU_CHECK_CALL_ERROR(glUseProgram(programId), gl().getError());

		log() << TestLog::Message << "// Deleted program " << programId
			  << TestLog::EndMessage;
	}
	TCU_CHECK(glIsProgram(programId));
	{
		GLint deleteFlagged = 0;
		glGetProgramiv(programId, GL_DELETE_STATUS, &deleteFlagged);
		errors.check(deleteFlagged != 0, "Program object was not flagged as deleted");
	}
	GLU_CHECK_CALL_ERROR(glUseProgram(0), gl().getError());
	errors.check(!gl().isProgram(programId),
				 "Deleted program name still valid after being made non-current");
}

class AttachmentTest : public TestBase
{
public:
	typedef void			(AttachmentTest::*TestFunction)	(void);
							AttachmentTest					(const char*	name,
															 const char*	description,
															 Attacher&		attacher,
															 TestFunction	test)
								: TestBase		(name, description, attacher.getContext())
								, m_attacher	(attacher)
								, m_test		(test) {}
	IterateResult			iterate							(void);

	void					testDeletedNames				(void);
	void					testDeletedBinding				(void);
	void					testDeletedReattach				(void);

private:
	Attacher&				m_attacher;
	const TestFunction		m_test;
};

IterateResult AttachmentTest::iterate (void)
{
	(this->*m_test)();
	return STOP;
}

GLuint getAttachment (Attacher& attacher, GLuint container)
{
	const GLuint queriedAttachment = attacher.getAttachment(container);
	attacher.log() << TestLog::Message
				   << "// Result of query for " << attacher.getElementType().getName()
				   << " attached to " << attacher.getContainerType().getName() << " "
				   << container << ": " << queriedAttachment << "."
				   << TestLog::EndMessage;
	return queriedAttachment;
}

void AttachmentTest::testDeletedNames (void)
{
	Type&			elemType		= m_attacher.getElementType();
	Type&			containerType	= m_attacher.getContainerType();
	Name			container		(containerType);
	ResultCollector	errors			(getTestContext());
	GLuint			elementId		= 0;

	{
		Name element(elemType);
		elementId = *element;
		m_attacher.initAttachment(0, *element);
		m_attacher.attach(*element, *container);
		errors.check(getAttachment(m_attacher, *container) == elementId,
					 "Attachment name not returned by query even before deletion.");
	}

	// "Such a container or other context may continue using the object, and
	// may still contain state identifying its name as being currently bound"
	//
	// We here interpret "may" to mean that whenever the container has a
	// deleted object attached to it, a query will return that object's former
	// name.
	errors.check(getAttachment(m_attacher, *container) == elementId,
				 "Attachment name not returned by query after attachment was deleted.");

	if (elemType.nameLingers())
		errors.check(elemType.exists(elementId),
					 "Attached object name no longer valid after deletion.");
	else
		errors.check(!elemType.exists(elementId),
					 "Attached object name still valid after deletion.");

	m_attacher.detach(elementId, *container);
	errors.check(getAttachment(m_attacher, *container) == 0,
				 "Attachment name returned by query even after detachment.");
	errors.check(!elemType.exists(elementId),
				 "Deleted attached object name still usable after detachment.");
}

class InputAttachmentTest : public TestBase
{
public:
					InputAttachmentTest	(const char*	name,
										 const char*	description,
										 InputAttacher&	inputAttacher)
						: TestBase			(name, description, inputAttacher.getContext())
						, m_inputAttacher	(inputAttacher) {}

	IterateResult	iterate				(void);

private:
	InputAttacher&	m_inputAttacher;
};

GLuint replaceName (Type& type, GLuint oldName, TestLog& log)
{
	const Binder* const	binder		= type.binder();
	const bool			genRequired	= binder == DE_NULL || binder->genRequired();

	if (genRequired)
		return type.gen();

	log << TestLog::Message
		<< "// Type does not require Gen* for binding, reusing old id " << oldName << "."
		<< TestLog::EndMessage;

	return oldName;
}

IterateResult InputAttachmentTest::iterate (void)
{
	Attacher&		attacher		= m_inputAttacher.getAttacher();
	Type&			containerType	= attacher.getContainerType();
	Type&			elementType		= attacher.getElementType();
	Name			container		(containerType);
	GLuint			elementId		= 0;
	const GLuint	refSeed			= m_rnd.getUint32();
	const GLuint	newSeed			= m_rnd.getUint32();
	ResultCollector	errors			(getTestContext());

	Surface			refSurface;		// Surface from drawing with refSeed-seeded attachment
	Surface			delSurface;		// Surface from drawing with deleted refSeed attachment
	Surface			newSurface;		// Surface from drawing with newSeed-seeded attachment

	log() << TestLog::Message
		  << "Testing if writing to a newly created object modifies a deleted attachment"
		  << TestLog::EndMessage;

	{
		ScopedLogSection	section	(log(),
									 "Write to original", "Writing to an original attachment");
		const Name			element	(elementType);

		elementId = *element;
		attacher.initAttachment(refSeed, elementId);
		attacher.attach(elementId, *container);
		m_inputAttacher.drawContainer(*container, refSurface);
		// element gets deleted here
		log() << TestLog::Message << "// Deleting attachment";
	}
	{
		ScopedLogSection section	(log(), "Write to new",
									 "Writing to a new attachment after deleting the original");
		const GLuint	newId		= replaceName(elementType, elementId, log());
		const Name		newElement	(elementType, newId);

		attacher.initAttachment(newSeed, newId);

		m_inputAttacher.drawContainer(*container, delSurface);
		attacher.detach(elementId, *container);

		attacher.attach(newId, *container);
		m_inputAttacher.drawContainer(*container, newSurface);
		attacher.detach(newId, *container);
	}
	{
		const bool surfacesMatch = tcu::pixelThresholdCompare(
			log(), "Reading from deleted",
			"Comparison result from reading from a container with a deleted attachment "
			"before and after writing to a fresh object.",
			refSurface, delSurface, RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);

		errors.check(
			surfacesMatch,
			"Writing to a fresh object modified the container with a deleted attachment.");

		if (!surfacesMatch)
			log() << TestLog::Image("New attachment",
									"Container state after attached to the fresh object",
									newSurface);
	}

	return STOP;
}

class OutputAttachmentTest : public TestBase
{
public:
						OutputAttachmentTest			(const char*		name,
														 const char*		description,
														 OutputAttacher&	outputAttacher)
							: TestBase			(name, description,
												 outputAttacher.getContext())
							, m_outputAttacher	(outputAttacher) {}
	IterateResult		iterate							(void);

private:
	OutputAttacher&		m_outputAttacher;
};

IterateResult OutputAttachmentTest::iterate (void)
{
	Attacher&		attacher		= m_outputAttacher.getAttacher();
	Type&			containerType	= attacher.getContainerType();
	Type&			elementType		= attacher.getElementType();
	Name			container		(containerType);
	GLuint			elementId		= 0;
	const GLuint	refSeed			= m_rnd.getUint32();
	const GLuint	newSeed			= m_rnd.getUint32();
	ResultCollector	errors			(getTestContext());
	Surface			refSurface;		// Surface drawn from attachment to refSeed container
	Surface			newSurface;		// Surface drawn from attachment to newSeed container
	Surface			delSurface;		// Like newSurface, after writing to a deleted attachment

	log() << TestLog::Message
		  << "Testing if writing to a container with a deleted attachment "
		  << "modifies a newly created object"
		  << TestLog::EndMessage;

	{
		ScopedLogSection	section	(log(), "Write to existing",
									 "Writing to a container with an existing attachment");
		const Name			element	(elementType);

		elementId = *element;
		attacher.initAttachment(0, elementId);
		attacher.attach(elementId, *container);

		// For reference purposes, make note of what refSeed looks like.
		m_outputAttacher.setupContainer(refSeed, *container);
		m_outputAttacher.drawAttachment(elementId, refSurface);
	}
	{
		ScopedLogSection	section		(log(), "Write to deleted",
										 "Writing to a container after deletion of attachment");
		const GLuint		newId		= replaceName(elementType, elementId, log());
		const Name			newElement	(elementType, newId);

		log() << TestLog::Message
			  << "Creating a new object " << newId
			  << TestLog::EndMessage;

		log() << TestLog::Message
			  << "Recording state of new object before writing to container"
			  << TestLog::EndMessage;
		attacher.initAttachment(newSeed, newId);
		m_outputAttacher.drawAttachment(newId, newSurface);

		log() << TestLog::Message
			  << "Writing to container"
			  << TestLog::EndMessage;

		// Now re-write refSeed to the container.
		m_outputAttacher.setupContainer(refSeed, *container);
		// Does it affect the newly created attachment object?
		m_outputAttacher.drawAttachment(newId, delSurface);
	}
	attacher.detach(elementId, *container);

	const bool surfacesMatch = tcu::pixelThresholdCompare(
		log(), "Writing to deleted",
		"Comparison result from reading from a fresh object before and after "
		"writing to a container with a deleted attachment",
		newSurface, delSurface, RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);

	errors.check(surfacesMatch,
				 "Writing to container with deleted attachment modified a new object.");

	if (!surfacesMatch)
		log() << TestLog::Image(
			"Original attachment",
			"Result of container modification on original attachment before deletion.",
			refSurface);
	return STOP;
}

struct LifeTestSpec
{
	const char*				name;
	LifeTest::TestFunction	func;
	bool					needBind;
};

MovePtr<TestCaseGroup> createLifeTestGroup (TestContext& testCtx,
											const LifeTestSpec& spec,
											const vector<Type*>& types)
{
	MovePtr<TestCaseGroup> group(new TestCaseGroup(testCtx, spec.name, spec.name));

	for (vector<Type*>::const_iterator it = types.begin(); it != types.end(); ++it)
	{
		Type& type = **it;
		const char* name = type.getName();
		if (!spec.needBind || type.binder() != DE_NULL)
			group->addChild(new LifeTest(name, name, type, spec.func));
	}

	return group;
}

static const LifeTestSpec s_lifeTests[] =
{
	{ "gen",			&LifeTest::testGen,			false	},
	{ "delete",			&LifeTest::testDelete,		false	},
	{ "bind",			&LifeTest::testBind,		true	},
	{ "delete_bound",	&LifeTest::testDeleteBound,	true	},
	{ "bind_no_gen",	&LifeTest::testBindNoGen,	true	},
};

string attacherName (Attacher& attacher)
{
	ostringstream os;
	os << attacher.getElementType().getName() << "_" <<  attacher.getContainerType().getName();
	return os.str();
}

void addTestCases (TestCaseGroup& group, Types& types)
{
	TestContext& testCtx = types.getTestContext();

	for (const LifeTestSpec* it = DE_ARRAY_BEGIN(s_lifeTests);
		 it != DE_ARRAY_END(s_lifeTests); ++it)
		group.addChild(createLifeTestGroup(testCtx, *it, types.getTypes()).release());

	{
		TestCaseGroup* const delUsedGroup =
			new TestCaseGroup(testCtx, "delete_used", "Delete current program");
		group.addChild(delUsedGroup);

		delUsedGroup->addChild(
			new LifeTest("program", "program", types.getProgramType(),
						 &LifeTest::testDeleteUsed));
	}

	{
		TestCaseGroup* const	attGroup	= new TestCaseGroup(
			testCtx, "attach", "Attachment tests");
		group.addChild(attGroup);

		{
			TestCaseGroup* const	nameGroup	= new TestCaseGroup(
				testCtx, "deleted_name", "Name of deleted attachment");
			attGroup->addChild(nameGroup);

			const vector<Attacher*>& atts = types.getAttachers();
			for (vector<Attacher*>::const_iterator it = atts.begin(); it != atts.end(); ++it)
			{
				const string name = attacherName(**it);
				nameGroup->addChild(new AttachmentTest(name.c_str(), name.c_str(), **it,
													   &AttachmentTest::testDeletedNames));
			}
		}
		{
			TestCaseGroup* inputGroup = new TestCaseGroup(
				testCtx, "deleted_input", "Input from deleted attachment");
			attGroup->addChild(inputGroup);

			const vector<InputAttacher*>& inAtts = types.getInputAttachers();
			for (vector<InputAttacher*>::const_iterator it = inAtts.begin();
				 it != inAtts.end(); ++it)
			{
				const string name = attacherName((*it)->getAttacher());
				inputGroup->addChild(new InputAttachmentTest(name.c_str(), name.c_str(), **it));
			}
		}
		{
			TestCaseGroup* outputGroup = new TestCaseGroup(
				testCtx, "deleted_output", "Output to deleted attachment");
			attGroup->addChild(outputGroup);

			const vector<OutputAttacher*>& outAtts = types.getOutputAttachers();
			for (vector<OutputAttacher*>::const_iterator it = outAtts.begin();
				 it != outAtts.end(); ++it)
			{
				string name = attacherName((*it)->getAttacher());
				outputGroup->addChild(new OutputAttachmentTest(name.c_str(), name.c_str(),
															   **it));
			}
		}
	}
}

} // details
} // LifetimeTests
} // gls
} // deqp
