Merge "Improve logging in fbo completeness tests."
diff --git a/framework/delibs/decpp/deStringUtil.cpp b/framework/delibs/decpp/deStringUtil.cpp
index c5e0166..14fccaa 100644
--- a/framework/delibs/decpp/deStringUtil.cpp
+++ b/framework/delibs/decpp/deStringUtil.cpp
@@ -22,6 +22,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "deStringUtil.hpp"
+#include "deString.h"
 
 #include <algorithm>
 #include <iterator>
@@ -113,6 +114,22 @@
 	return s.str();
 }
 
+bool beginsWith (const std::string& s, const std::string& prefix)
+{
+	return deStringBeginsWith(s.c_str(), prefix.c_str());
+}
+
+bool endsWith (const std::string& s, const std::string& suffix)
+{
+	if (suffix.length() > s.length())
+		return false;
+	else
+	{
+		const std::string::size_type offset = s.length() - suffix.length();
+		return s.find(suffix, offset) == offset;
+	}
+}
+
 char toUpper (char c)
 {
 	return std::toupper(c, std::locale::classic());
@@ -156,6 +173,25 @@
 
 	DE_TEST_ASSERT(floatToString(4, 1) == "4.0");
 
+	DE_TEST_ASSERT(beginsWith("foobar", "foobar"));
+	DE_TEST_ASSERT(beginsWith("foobar", "foo"));
+	DE_TEST_ASSERT(beginsWith("foobar", "f"));
+	DE_TEST_ASSERT(beginsWith("foobar", ""));
+	DE_TEST_ASSERT(beginsWith("", ""));
+	DE_TEST_ASSERT(!beginsWith("foobar", "bar"));
+	DE_TEST_ASSERT(!beginsWith("foobar", "foobarbaz"));
+	DE_TEST_ASSERT(!beginsWith("", "foo"));
+
+	DE_TEST_ASSERT(endsWith("foobar", "foobar"));
+	DE_TEST_ASSERT(endsWith("foobar", "bar"));
+	DE_TEST_ASSERT(endsWith("foobar", "r"));
+	DE_TEST_ASSERT(endsWith("foobar", ""));
+	DE_TEST_ASSERT(endsWith("", ""));
+	DE_TEST_ASSERT(!endsWith("foobar", "foo"));
+	DE_TEST_ASSERT(!endsWith("foobar", "bazfoobar"));
+	DE_TEST_ASSERT(!endsWith("foobar", "foobarbaz"));
+	DE_TEST_ASSERT(!endsWith("", "foo"));
+
 	DE_TEST_ASSERT(toUpper('a') == 'A');
 	DE_TEST_ASSERT(toUpper('A') == 'A');
 	DE_TEST_ASSERT(toLower('a') == 'a');
diff --git a/framework/delibs/decpp/deStringUtil.hpp b/framework/delibs/decpp/deStringUtil.hpp
index 68614d8..343619c 100644
--- a/framework/delibs/decpp/deStringUtil.hpp
+++ b/framework/delibs/decpp/deStringUtil.hpp
@@ -47,6 +47,8 @@
 std::string					capitalize		(const std::string& s);
 std::vector<std::string>	splitString		(const std::string& s, char delim='\0');
 std::string					floatToString	(float val, int precision);
+bool						beginsWith		(const std::string& s, const std::string& prefix);
+bool						endsWith		(const std::string& s, const std::string& suffix);
 char						toUpper			(char c);
 char						toLower			(char c);
 bool						isUpper			(char c);
diff --git a/modules/egl/teglImageFormatTests.cpp b/modules/egl/teglImageFormatTests.cpp
index 62df0ce..1e06500 100644
--- a/modules/egl/teglImageFormatTests.cpp
+++ b/modules/egl/teglImageFormatTests.cpp
@@ -549,6 +549,9 @@
 bool GLES2ImageApi::RenderReadPixelsRenderbuffer::invokeGLES2 (GLES2ImageApi& api, MovePtr<UniqueImage>& img, tcu::Texture2D& reference) const
 {
 	const glw::Functions&	gl				= api.m_gl;
+	const tcu::IVec4		bitDepth		= tcu::getTextureFormatMantissaBitDepth(reference.getFormat());
+	const tcu::IVec4		threshold		(2 * (tcu::IVec4(1) << (tcu::IVec4(8) - bitDepth)));
+	const tcu::RGBA			threshold8		((deUint8)(de::clamp(threshold[0], 0, 255)), (deUint8)(de::clamp(threshold[1], 0, 255)), (deUint8)(de::clamp(threshold[2], 0, 255)), (deUint8)(de::clamp(threshold[3], 0, 255)));
 	tcu::TestLog&			log				= api.getLog();
 	Framebuffer				framebuffer		(gl);
 	Renderbuffer			renderbuffer	(gl);
@@ -572,7 +575,7 @@
 
 	tcu::copy(refSurface.getAccess(), reference.getLevel(0));
 
-	return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, tcu::RGBA(1,1,1,1), tcu::COMPARE_LOG_RESULT);
+	return tcu::pixelThresholdCompare(log, "Renderbuffer read", "Result from reading renderbuffer", refSurface, screen, threshold8, tcu::COMPARE_LOG_RESULT);
 
 }
 
diff --git a/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp b/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp
index 88ae724..6d8f737 100644
--- a/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceDefinition.cpp
@@ -26,6 +26,7 @@
 #include "gluVarType.hpp"
 #include "gluShaderProgram.hpp"
 #include "deSTLUtil.hpp"
+#include "deStringUtil.hpp"
 #include "glwEnums.hpp"
 
 #include <set>
@@ -634,7 +635,7 @@
 	for (int ndx = 0; ndx < (int)m_xfbVaryings.size(); ++ndx)
 	{
 		// user-defined
-		if (m_xfbVaryings[ndx].find("gl_") != 0)
+		if (!de::beginsWith(m_xfbVaryings[ndx], "gl_"))
 		{
 			std::vector<ProgramInterfaceDefinition::VariablePathComponent> path;
 			if (!findProgramVariablePathByPathName(path, this, m_xfbVaryings[ndx], VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(this), glu::STORAGE_OUT)))
diff --git a/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp b/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
index 15c6431..778ef6f 100644
--- a/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceQueryTestCase.cpp
@@ -46,14 +46,6 @@
 using ProgramInterfaceDefinition::VariablePathComponent;
 using ProgramInterfaceDefinition::VariableSearchFilter;
 
-static bool stringEndsWith (const std::string& str, const std::string& suffix)
-{
-	if (suffix.length() > str.length())
-		return false;
-	else
-		return str.substr(str.length() - suffix.length()) == suffix;
-}
-
 static glw::GLenum getProgramDefaultBlockInterfaceFromStorage (glu::Storage storage)
 {
 	switch (storage)
@@ -1966,7 +1958,7 @@
 
 			if (recoveryStrategies[strategyNdx].removeTrailingArray)
 			{
-				if (stringEndsWith(resourceName, "[0]"))
+				if (de::endsWith(resourceName, "[0]"))
 					simplifiedResourceName = resourceName.substr(0, resourceName.length() - 3);
 				else
 					continue;
diff --git a/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp b/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
index 0bc1efc..bfc85d9 100644
--- a/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
+++ b/modules/gles31/functional/es31fProgramInterfaceQueryTests.cpp
@@ -52,14 +52,6 @@
 namespace
 {
 
-static bool stringEndsWith (const std::string& str, const std::string& suffix)
-{
-	if (suffix.length() > str.length())
-		return false;
-	else
-		return str.substr(str.length() - suffix.length()) == suffix;
-}
-
 static int getTypeSize (glu::DataType type)
 {
 	if (type == glu::TYPE_FLOAT)
@@ -1106,7 +1098,7 @@
 	{
 		for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx)
 		{
-			if (stringEndsWith(referenceResources[ndx], "[0]"))
+			if (de::endsWith(referenceResources[ndx], "[0]"))
 			{
 				const std::string	queryString	= referenceResources[ndx].substr(0, referenceResources[ndx].length()-3);
 				const glw::GLuint	index		= gl.getProgramResourceIndex(program, programInterface, queryString.c_str());
@@ -1233,7 +1225,7 @@
 				if (arrayedInterface && isImplicitlySizedArray)
 				{
 					// omit implicit arrayness from name, i.e. remove trailing "_array"
-					DE_ASSERT(stringEndsWith(buf, "_array"));
+					DE_ASSERT(de::endsWith(buf, "_array"));
 					buf = buf.substr(0, buf.length() - 6);
 				}