Merge "Do not require signed zero support in ldexp tests()" into lmp-mr1-dev
diff --git a/framework/common/tcuDefs.cpp b/framework/common/tcuDefs.cpp
index 154aea7..10eb1fa 100644
--- a/framework/common/tcuDefs.cpp
+++ b/framework/common/tcuDefs.cpp
@@ -73,43 +73,55 @@
 {
 }
 
+TestException::TestException (const char* message, const char* expr, const char* file, int line, qpTestResult result)
+	: Exception	(formatError(message, expr, file, line))
+	, m_result	(result)
+{
+}
+
+TestException::TestException (const std::string& message, qpTestResult result)
+	: Exception	(message)
+	, m_result	(result)
+{
+}
+
 TestError::TestError (const char* message, const char* expr, const char* file, int line)
-	: Exception(message, expr, file, line)
+	: TestException(message, expr, file, line, QP_TEST_RESULT_FAIL)
 {
 }
 
 TestError::TestError (const std::string& message)
-	: Exception(message)
+	: TestException(message, QP_TEST_RESULT_FAIL)
 {
 }
 
 InternalError::InternalError (const char* message, const char* expr, const char* file, int line)
-	: Exception(message, expr, file, line)
+	: TestException(message, expr, file, line, QP_TEST_RESULT_INTERNAL_ERROR)
 {
 }
 
 InternalError::InternalError (const std::string& message)
-	: Exception(message)
+	: TestException(message, QP_TEST_RESULT_INTERNAL_ERROR)
 {
 }
 
 ResourceError::ResourceError (const char* message, const char* expr, const char* file, int line)
-	: Exception(message, expr, file, line)
+	: TestException(message, expr, file, line, QP_TEST_RESULT_RESOURCE_ERROR)
 {
 }
 
 ResourceError::ResourceError (const std::string& message)
-	: Exception(message)
+	: TestException(message, QP_TEST_RESULT_RESOURCE_ERROR)
 {
 }
 
 NotSupportedError::NotSupportedError (const char* message, const char* expr, const char* file, int line)
-	: Exception(message, expr, file, line)
+	: TestException(message, expr, file, line, QP_TEST_RESULT_NOT_SUPPORTED)
 {
 }
 
 NotSupportedError::NotSupportedError (const std::string& message)
-	: Exception(message)
+	: TestException(message, QP_TEST_RESULT_NOT_SUPPORTED)
 {
 }
 
diff --git a/framework/common/tcuDefs.hpp b/framework/common/tcuDefs.hpp
index 1ed3af5..047c64f 100644
--- a/framework/common/tcuDefs.hpp
+++ b/framework/common/tcuDefs.hpp
@@ -24,6 +24,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "deDefs.hpp"
+#include "qpTestLog.h"
 
 #include <string>
 #include <stdexcept>
@@ -47,18 +48,33 @@
 class Exception : public std::runtime_error
 {
 public:
-					Exception			(const char* message, const char* expr, const char* file, int line);
-					Exception			(const std::string& message);
-	virtual			~Exception			(void) throw() {}
+						Exception			(const char* message, const char* expr, const char* file, int line);
+						Exception			(const std::string& message);
+	virtual				~Exception			(void) throw() {}
 
-	const char*		getMessage			(void) const { return m_message.c_str(); }
+	const char*			getMessage			(void) const { return m_message.c_str(); }
 
 private:
-	std::string		m_message;
+	const std::string	m_message;
+};
+
+//! Base exception class for test exceptions that affect test result
+class TestException : public Exception
+{
+public:
+						TestException		(const char* message, const char* expr, const char* file, int line, qpTestResult result);
+						TestException		(const std::string& message, qpTestResult result);
+	virtual				~TestException		(void) throw() {}
+
+	qpTestResult		getTestResult		(void) const { return m_result; }
+	virtual bool		isFatal				(void) const { return false; }
+
+private:
+	const qpTestResult	m_result;
 };
 
 //! Exception for test errors.
-class TestError : public Exception
+class TestError : public TestException
 {
 public:
 					TestError			(const char* message, const char* expr, const char* file, int line);
@@ -67,7 +83,7 @@
 };
 
 //! Exception for internal errors.
-class InternalError : public Exception
+class InternalError : public TestException
 {
 public:
 					InternalError		(const char* message, const char* expr, const char* file, int line);
@@ -76,16 +92,18 @@
 };
 
 //! Resource error. Tester will terminate if thrown out of test case.
-class ResourceError : public Exception
+class ResourceError : public TestException
 {
 public:
 					ResourceError		(const char* message, const char* expr, const char* file, int line);
 					ResourceError		(const std::string& message);
 	virtual			~ResourceError		(void) throw() {}
+
+	virtual bool	isFatal				(void) const { return true; }
 };
 
 //! Not supported error.
-class NotSupportedError : public Exception
+class NotSupportedError : public TestException
 {
 public:
 					NotSupportedError	(const char* message, const char* expr, const char* file, int line);
diff --git a/framework/common/tcuTestCaseWrapper.cpp b/framework/common/tcuTestCaseWrapper.cpp
index 2639bb7..b8e2eb5 100644
--- a/framework/common/tcuTestCaseWrapper.cpp
+++ b/framework/common/tcuTestCaseWrapper.cpp
@@ -56,23 +56,13 @@
 	{
 		DE_ASSERT(!success);
 		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Failed to allocate memory in test case init");
+		m_testCtx.setTerminateAfter(true);
 	}
-	catch (const tcu::ResourceError& e)
+	catch (const tcu::TestException& e)
 	{
 		DE_ASSERT(!success);
-		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, e.getMessage());
-		log << e;
-	}
-	catch (const tcu::NotSupportedError& e)
-	{
-		DE_ASSERT(!success);
-		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, e.getMessage());
-		log << e;
-	}
-	catch (const tcu::InternalError& e)
-	{
-		DE_ASSERT(!success);
-		m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, e.getMessage());
+		m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
+		m_testCtx.setTerminateAfter(e.isFatal());
 		log << e;
 	}
 	catch (const tcu::Exception& e)
@@ -125,21 +115,13 @@
 	catch (const std::bad_alloc&)
 	{
 		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Failed to allocate memory during test execution");
+		m_testCtx.setTerminateAfter(true);
 	}
-	catch (const tcu::ResourceError& e)
+	catch (const tcu::TestException& e)
 	{
 		log << e;
-		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, e.getMessage());
-	}
-	catch (const tcu::NotSupportedError& e)
-	{
-		log << e;
-		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, e.getMessage());
-	}
-	catch (const tcu::InternalError& e)
-	{
-		log << e;
-		m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, e.getMessage());
+		m_testCtx.setTestResult(e.getTestResult(), e.getMessage());
+		m_testCtx.setTerminateAfter(e.isFatal());
 	}
 	catch (const tcu::Exception& e)
 	{
diff --git a/framework/common/tcuTestContext.cpp b/framework/common/tcuTestContext.cpp
index a3317b2..bfa6d88 100644
--- a/framework/common/tcuTestContext.cpp
+++ b/framework/common/tcuTestContext.cpp
@@ -41,6 +41,7 @@
 	, m_watchDog		(watchDog)
 	, m_curArchive		(DE_NULL)
 	, m_testResult		(QP_TEST_RESULT_LAST)
+	, m_terminateAfter	(false)
 {
 	setCurrentArchive(m_rootArchive);
 }
diff --git a/framework/common/tcuTestContext.hpp b/framework/common/tcuTestContext.hpp
index 35e5577..3196154 100644
--- a/framework/common/tcuTestContext.hpp
+++ b/framework/common/tcuTestContext.hpp
@@ -67,6 +67,8 @@
 	Archive&				getRootArchive		(void) const		{ return m_rootArchive;		}
 	void					setCurrentArchive	(Archive& archive)	{ m_curArchive = &archive;	}
 
+	void					setTerminateAfter	(bool terminate)	{ m_terminateAfter = terminate;	}
+	bool					getTerminateAfter	(void) const		{ return m_terminateAfter; 		}
 protected:
 	Platform&				m_platform;			//!< Platform port implementation.
 	Archive&				m_rootArchive;		//!< Root archive.
@@ -77,6 +79,7 @@
 	Archive*				m_curArchive;		//!< Current archive for test cases.
 	qpTestResult			m_testResult;		//!< Latest test result.
 	std::string				m_testResultDesc;	//!< Latest test result description.
+	bool					m_terminateAfter;	//!< Should tester terminate after execution of the current test
 };
 
 /*--------------------------------------------------------------------*//*!
diff --git a/framework/common/tcuTestExecutor.cpp b/framework/common/tcuTestExecutor.cpp
index 21c1b0a..69500a2 100644
--- a/framework/common/tcuTestExecutor.cpp
+++ b/framework/common/tcuTestExecutor.cpp
@@ -194,11 +194,18 @@
 	const RunMode runMode = m_cmdLine.getRunMode();
 	if (runMode == RUNMODE_EXECUTE)
 	{
-		// Update statistics.
-		qpTestResult testResult = m_testCtx.getTestResult();
+		// De-init case.
+		const bool			deinitOk		= m_testCaseWrapper->deinitTestCase(testCase);
+		const qpTestResult	testResult		= m_testCtx.getTestResult();
+		const char* const	testResultDesc	= m_testCtx.getTestResultDesc();
+		const bool			terminateAfter	= m_testCtx.getTerminateAfter();
 		DE_ASSERT(testResult != QP_TEST_RESULT_LAST);
 
-		print("  %s (%s)\n", qpGetTestResultName(testResult), m_testCtx.getTestResultDesc());
+		m_isInTestCase = false;
+		m_testCtx.getLog().endCase(testResult, testResultDesc);
+
+		// Update statistics.
+		print("  %s (%s)\n", qpGetTestResultName(testResult), testResultDesc);
 
 		m_result.numExecuted += 1;
 		switch (testResult)
@@ -210,14 +217,8 @@
 			default:									m_result.numFailed			+= 1;	break;
 		}
 
-		// De-init case.
-		bool deinitOk = m_testCaseWrapper->deinitTestCase(testCase);
-
-		m_isInTestCase = false;
-		m_testCtx.getLog().endCase(m_testCtx.getTestResult(), m_testCtx.getTestResultDesc());
-
-		// Resource error or any error in deinit means that execution should end
-		if (!deinitOk || testResult == QP_TEST_RESULT_RESOURCE_ERROR)
+		// terminateAfter, Resource error or any error in deinit means that execution should end
+		if (terminateAfter || !deinitOk || testResult == QP_TEST_RESULT_RESOURCE_ERROR)
 			m_abortSession = true;
 
 		// \todo [2011-02-09 pyry] Disable watchdog temporarily?
diff --git a/modules/gles2/tes2TestCaseWrapper.cpp b/modules/gles2/tes2TestCaseWrapper.cpp
index c7c2eb9..dc3fa2c 100644
--- a/modules/gles2/tes2TestCaseWrapper.cpp
+++ b/modules/gles2/tes2TestCaseWrapper.cpp
@@ -95,6 +95,7 @@
 	{
 		m_testCtx.getLog() << e;
 		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
+		m_testCtx.setTerminateAfter(true);
 		return tcu::TestNode::STOP;
 	}
 	catch (const std::exception& e)
diff --git a/modules/gles3/functional/es3fTextureMipmapTests.cpp b/modules/gles3/functional/es3fTextureMipmapTests.cpp
index fee9b0e..dd78b96 100644
--- a/modules/gles3/functional/es3fTextureMipmapTests.cpp
+++ b/modules/gles3/functional/es3fTextureMipmapTests.cpp
@@ -721,7 +721,7 @@
 		lookupPrec.coordBits			= isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
 		lookupPrec.uvwBits				= tcu::IVec3(5,5,0);
 		lodPrec.derivateBits			= 10;
-		lodPrec.lodBits					= isProjected ? 4 : 6;
+		lodPrec.lodBits					= isProjected ? 3 : 6;
 
 		for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
 		{
diff --git a/modules/gles3/tes3TestCaseWrapper.cpp b/modules/gles3/tes3TestCaseWrapper.cpp
index 76cb78d..d2e2446 100644
--- a/modules/gles3/tes3TestCaseWrapper.cpp
+++ b/modules/gles3/tes3TestCaseWrapper.cpp
@@ -95,6 +95,7 @@
 	{
 		m_testCtx.getLog() << e;
 		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
+		m_testCtx.setTerminateAfter(true);
 		return tcu::TestNode::STOP;
 	}
 	catch (const std::exception& e)
diff --git a/modules/gles31/functional/es31fDrawTests.cpp b/modules/gles31/functional/es31fDrawTests.cpp
index 7f28d98..89d904a 100644
--- a/modules/gles31/functional/es31fDrawTests.cpp
+++ b/modules/gles31/functional/es31fDrawTests.cpp
@@ -1179,6 +1179,7 @@
 	{
 		m_testCtx.getLog() << tcu::TestLog::Message << "Got GL_OUT_OF_MEMORY." << tcu::TestLog::EndMessage;
 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Got GL_OUT_OF_MEMORY");
+		m_testCtx.setTerminateAfter(true); // Do not rely on implementation to be able to recover from OOM
 		return STOP;
 	}
 
diff --git a/modules/gles31/functional/es31fGeometryShaderTests.cpp b/modules/gles31/functional/es31fGeometryShaderTests.cpp
index 6e374a5..e3b0891 100644
--- a/modules/gles31/functional/es31fGeometryShaderTests.cpp
+++ b/modules/gles31/functional/es31fGeometryShaderTests.cpp
@@ -3878,7 +3878,12 @@
 	// not linked -case (INVALID OP)
 	{
 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "NotLinkedProgram", "Shader program not linked");
-		const std::string			geometrySource	= "#version 310 es\nlayout (triangles) in;\n" + std::string(s_geometryBody);
+		const std::string			geometrySource	= "#version 310 es\n"
+													  "#extension GL_EXT_geometry_shader : require\n"
+													  "layout (triangles) in;\n"
+													  "layout (points, max_vertices = 3) out;\n"
+													  + std::string(s_geometryBody);
+
 
 		glu::Shader					vertexShader	(m_context.getRenderContext(), glu::SHADERTYPE_VERTEX);
 		glu::Shader					fragmentShader	(m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT);
diff --git a/modules/gles31/tes31TestCaseWrapper.cpp b/modules/gles31/tes31TestCaseWrapper.cpp
index 05b89e3..e45ab8e 100644
--- a/modules/gles31/tes31TestCaseWrapper.cpp
+++ b/modules/gles31/tes31TestCaseWrapper.cpp
@@ -86,6 +86,7 @@
 	{
 		m_testCtx.getLog() << e;
 		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Resource error in context post-iteration routine");
+		m_testCtx.setTerminateAfter(true);
 		return tcu::TestNode::STOP;
 	}
 	catch (const std::exception& e)
diff --git a/modules/glshared/glsTextureTestUtil.cpp b/modules/glshared/glsTextureTestUtil.cpp
index 9cf6258..438ba02 100644
--- a/modules/glshared/glsTextureTestUtil.cpp
+++ b/modules/glshared/glsTextureTestUtil.cpp
@@ -2005,7 +2005,7 @@
 		tcu::Vec2(-1, -1),
 		tcu::Vec2(-1, +1),
 		tcu::Vec2(+1, -1),
-		tcu::Vec2(+1, -1),
+		tcu::Vec2(+1, +1),
 	};
 
 	tcu::clear(errorMask, tcu::RGBA::green.toVec());