Add class to build seeds from variables.

Add simple stream like seed builder utility class for building seeds
from data types. This can be used to generate a seed for the rng from
the parameters of the test case instead of using name of the test case.

Change-Id: Ib276dc54a55c8a38878a220b17e3f9a2750cb774
diff --git a/Android.mk b/Android.mk
index 4a46e45..1ef241e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -63,6 +63,7 @@
 	framework/common/tcuTextureUtil.cpp \
 	framework/common/tcuTexVerifierUtil.cpp \
 	framework/common/tcuThreadUtil.cpp \
+	framework/common/tcuSeedBuilder.cpp \
 	framework/delibs/debase/deDefs.c \
 	framework/delibs/debase/deFloat16.c \
 	framework/delibs/debase/deInt32.c \
@@ -486,6 +487,7 @@
 	modules/internal/ditTestCase.cpp \
 	modules/internal/ditTestLogTests.cpp \
 	modules/internal/ditTestPackage.cpp \
+	modules/internal/ditSeedBuilderTests.cpp \
 	modules/internal/ditTestPackageEntry.cpp
 
 LOCAL_C_INCLUDES := \
diff --git a/framework/common/CMakeLists.txt b/framework/common/CMakeLists.txt
index 29a34bc..48893a7 100644
--- a/framework/common/CMakeLists.txt
+++ b/framework/common/CMakeLists.txt
@@ -73,6 +73,8 @@
 	tcuCPUWarmup.hpp
 	tcuFactoryRegistry.hpp
 	tcuFactoryRegistry.cpp
+	tcuSeedBuilder.hpp
+	tcuSeedBuilder.cpp
 	)
 
 set(TCUTIL_LIBS
diff --git a/framework/common/tcuSeedBuilder.cpp b/framework/common/tcuSeedBuilder.cpp
new file mode 100644
index 0000000..41162a4
--- /dev/null
+++ b/framework/common/tcuSeedBuilder.cpp
@@ -0,0 +1,160 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * 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 Utility class to build seeds from different data types.
+ *
+ * Values are first XORed with type specifig mask, which makes sure that
+ * two values with different types, but same bit presentation produce
+ * different results. Then values are passed through 32 bit crc.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuSeedBuilder.hpp"
+
+namespace tcu
+{
+
+namespace
+{
+
+deUint32 advanceCrc32 (deUint32 oldCrc, size_t len, const deUint8* data)
+{
+	const deUint32	generator	= 0x04C11DB7u;
+	deUint32		crc			= oldCrc;
+
+	for (size_t i = 0; i < len; i++)
+	{
+		const deUint32 current = static_cast<deUint32>(data[i]);
+		crc = crc ^ current;
+
+		for (size_t bitNdx = 0; bitNdx < 8; bitNdx++)
+		{
+			if (crc & 1u)
+				crc = (crc >> 1u) ^ generator;
+			else
+				crc = (crc >> 1u);
+		}
+	}
+
+	return crc;
+}
+
+} // anonymous
+
+SeedBuilder::SeedBuilder (void)
+	: m_hash (0xccf139d7u)
+{
+}
+
+void SeedBuilder::feed (size_t size, const void* ptr)
+{
+	m_hash = advanceCrc32(m_hash, size, (const deUint8*)ptr);
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, bool value)
+{
+	const deUint8 val = (value ? 54: 7);
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deInt8 value)
+{
+	const deInt8 val = value ^ 75;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deUint8 value)
+{
+	const deInt8 val = value ^ 140u;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deInt16 value)
+{
+	const deInt16 val = value ^ 555;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deUint16 value)
+{
+	const deUint16 val = value ^ 37323u;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deInt32 value)
+{
+	const deInt32 val = value ^ 53054741;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deUint32 value)
+{
+	const deUint32 val = value ^ 1977303630u;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deInt64 value)
+{
+	const deInt64 val = value ^ 772935234179004386ll;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, deUint64 value)
+{
+	const deUint64 val = value ^ 4664937258000467599ull;
+
+	builder.feed(sizeof(val), &val);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, float value)
+{
+	builder.feed(sizeof(value), &value);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, double value)
+{
+	builder.feed(sizeof(value), &value);
+	return builder;
+}
+
+SeedBuilder& operator<< (SeedBuilder& builder, const std::string& value)
+{
+	builder.feed(value.length(), value.c_str());
+	return builder;
+}
+
+} // tcu
diff --git a/framework/common/tcuSeedBuilder.hpp b/framework/common/tcuSeedBuilder.hpp
new file mode 100644
index 0000000..9dba292
--- /dev/null
+++ b/framework/common/tcuSeedBuilder.hpp
@@ -0,0 +1,79 @@
+#ifndef _TCUSEEDBUILDER_HPP
+#define _TCUSEEDBUILDER_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * 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 Utility class to build seeds from different data types.
+ *
+ * Values are first XORed with type specifig mask, which makes sure that
+ * two values with different types, but same bit presentation produce
+ * different results. Then values are passed through 32 bit crc.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuVector.hpp"
+
+#include <string>
+#include <vector>
+
+namespace tcu
+{
+
+class SeedBuilder
+{
+public:
+				SeedBuilder	(void);
+	deUint32	get			(void) const { return m_hash; }
+	void		feed		(size_t size, const void* ptr);
+
+private:
+	deUint32	m_hash;
+};
+
+SeedBuilder& operator<< (SeedBuilder& builder, bool value);
+SeedBuilder& operator<< (SeedBuilder& builder, deInt8 value);
+SeedBuilder& operator<< (SeedBuilder& builder, deUint8 value);
+
+SeedBuilder& operator<< (SeedBuilder& builder, deInt16 value);
+SeedBuilder& operator<< (SeedBuilder& builder, deUint16 value);
+
+SeedBuilder& operator<< (SeedBuilder& builder, deInt32 value);
+SeedBuilder& operator<< (SeedBuilder& builder, deUint32 value);
+
+SeedBuilder& operator<< (SeedBuilder& builder, deInt64 value);
+SeedBuilder& operator<< (SeedBuilder& builder, deUint64 value);
+
+SeedBuilder& operator<< (SeedBuilder& builder, float value);
+SeedBuilder& operator<< (SeedBuilder& builder, double value);
+
+SeedBuilder& operator<< (SeedBuilder& builder, const std::string& value);
+
+template<class T, int Size>
+SeedBuilder& operator<< (SeedBuilder& builder, const tcu::Vector<T, Size>& value)
+{
+	for (int i = 0; i < Size; i++)
+		builder << value[i];
+
+	return builder;
+}
+
+} // tcu
+
+#endif // _TCUSEEDBUILDER_HPP
diff --git a/modules/internal/CMakeLists.txt b/modules/internal/CMakeLists.txt
index 567bb60..c226c0c 100644
--- a/modules/internal/CMakeLists.txt
+++ b/modules/internal/CMakeLists.txt
@@ -17,6 +17,8 @@
 	ditTestLogTests.hpp
 	ditTestPackage.cpp
 	ditTestPackage.hpp
+	ditSeedBuilderTests.hpp
+	ditSeedBuilderTests.cpp
 	)
 
 set(DE_INTERNAL_TESTS_LIBS
diff --git a/modules/internal/ditSeedBuilderTests.cpp b/modules/internal/ditSeedBuilderTests.cpp
new file mode 100644
index 0000000..b8f9785
--- /dev/null
+++ b/modules/internal/ditSeedBuilderTests.cpp
@@ -0,0 +1,182 @@
+/*-------------------------------------------------------------------------
+ * drawElements Internal Test 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 Seed builder tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "ditSeedBuilderTests.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuVector.hpp"
+#include "tcuSeedBuilder.hpp"
+
+using tcu::IVec2;
+using tcu::IVec3;
+using tcu::IVec4;
+using tcu::TestLog;
+
+namespace dit
+{
+namespace
+{
+
+template<class T>
+class SeedBuilderTest : public tcu::TestCase
+{
+public:
+	SeedBuilderTest (tcu::TestContext& testCtx, const T& value, deUint32 seed, const char* name, const char* description)
+		: tcu::TestCase	(testCtx, name, description)
+		, m_value		(value)
+		, m_seed		(seed)
+	{
+	}
+
+	IterateResult iterate (void)
+	{
+		TestLog&			log		= m_testCtx.getLog();
+		tcu::SeedBuilder	builder;
+
+		builder << m_value;
+
+		log << TestLog::Message << "Value: " << m_value << TestLog::EndMessage;
+		log << TestLog::Message << "Expected seed: " << m_seed << TestLog::EndMessage;
+		log << TestLog::Message << "Got seed: " << builder.get() << TestLog::EndMessage;
+
+		if (builder.get() != m_seed)
+			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid seed");
+		else
+			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+
+		return STOP;
+	}
+
+private:
+	T			m_value;
+	deUint32	m_seed;
+};
+
+class SeedBuilderMultipleValuesTest : public tcu::TestCase
+{
+public:
+	SeedBuilderMultipleValuesTest (tcu::TestContext& testCtx)
+		: tcu::TestCase(testCtx, "multiple_values", "Test that multiple values all change the seed.")
+	{
+	}
+
+	IterateResult iterate (void)
+	{
+		TestLog&			log			= m_testCtx.getLog();
+		const deUint32		a			= 77740203u;
+		const deUint32		b			= 3830824200u;
+
+		tcu::SeedBuilder	builderA;
+		tcu::SeedBuilder	builderB;
+		tcu::SeedBuilder	builderAB;
+
+		builderA << a;
+		builderB << b;
+
+		builderAB << a << b;
+
+		log << TestLog::Message << "Value a: " << a << ", Seed a: " << builderA.get() << TestLog::EndMessage;
+		log << TestLog::Message << "Value b: " << b << ", Seed b: " << builderB.get() << TestLog::EndMessage;
+		log << TestLog::Message << "Seed ab: " << builderAB.get() << TestLog::EndMessage;
+
+		if (builderA.get() == builderAB.get())
+			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Seed seems to only depends on first value.");
+		else if (builderB.get() == builderAB.get())
+			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Seed seems to only depends on second value.");
+		else
+			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+
+		return STOP;
+	}
+};
+
+class SeedBuilderTests : public tcu::TestCaseGroup
+{
+public:
+	SeedBuilderTests (tcu::TestContext& testCtx)
+		: tcu::TestCaseGroup(testCtx, "seed_builder", "Seed builder tests.")
+	{
+	}
+
+	void init (void)
+	{
+		addChild(new SeedBuilderTest<bool>(m_testCtx, true,  132088003u, "bool_true", "Seed from boolean true."));
+		addChild(new SeedBuilderTest<bool>(m_testCtx, false,  50600761u, "bool_false", "Seed from boolean false."));
+
+		addChild(new SeedBuilderTest<deInt8>(m_testCtx,  0,  62533730u, "int8_zero", "Seed from int8 zero."));
+		addChild(new SeedBuilderTest<deInt8>(m_testCtx,  1,  93914869u, "int8_one", "Seed from int8 one."));
+		addChild(new SeedBuilderTest<deInt8>(m_testCtx, -1, 115002165u, "int8_minus_one", "Seed from int8 minus one."));
+
+		addChild(new SeedBuilderTest<deInt16>(m_testCtx,  0, 133071403u, "int16_zero", "Seed from int16 zero."));
+		addChild(new SeedBuilderTest<deInt16>(m_testCtx,  1,  57421642u, "int16_one", "Seed from int16 one."));
+		addChild(new SeedBuilderTest<deInt16>(m_testCtx, -1,  74389771u, "int16_minus_one", "Seed from int16 minus one."));
+
+		addChild(new SeedBuilderTest<deInt32>(m_testCtx,  0, 75951701u, "int32_zero", "Seed from int32 zero."));
+		addChild(new SeedBuilderTest<deInt32>(m_testCtx,  1, 95780822u, "int32_one", "Seed from int32 one."));
+		addChild(new SeedBuilderTest<deInt32>(m_testCtx, -1, 73949483u, "int32_minus_one", "Seed from int32 minus one."));
+
+		addChild(new SeedBuilderTest<deUint8>(m_testCtx, 0,		  3623298u, "uint8_zero", "Seed from uint8 zero."));
+		addChild(new SeedBuilderTest<deUint8>(m_testCtx, 1,		102006549u, "uint8_one", "Seed from uint8 one."));
+		addChild(new SeedBuilderTest<deUint8>(m_testCtx, 255,	 89633493u, "uint8_max", "Seed from uint8 max."));
+
+		addChild(new SeedBuilderTest<deUint16>(m_testCtx, 0,		 78413740u, "uint16_zero", "Seed from uint16 zero."));
+		addChild(new SeedBuilderTest<deUint16>(m_testCtx, 1,		  3068621u, "uint16_one", "Seed from uint16 one."));
+		addChild(new SeedBuilderTest<deUint16>(m_testCtx, 65535,	120448140u, "uint16_max", "Seed from uint16 max."));
+
+		addChild(new SeedBuilderTest<deUint32>(m_testCtx, 0u, 			41006057u, "uint32_zero", "Seed from uint32 zero."));
+		addChild(new SeedBuilderTest<deUint32>(m_testCtx, 1u,			54665834u, "uint32_one", "Seed from uint32 one."));
+		addChild(new SeedBuilderTest<deUint32>(m_testCtx, 4294967295u,	43990167u, "uint32_max", "Seed from uint32 max."));
+
+		addChild(new SeedBuilderTest<float>(m_testCtx, 0.0f, 	 41165361u, "float_zero", "Seed from float zero."));
+		addChild(new SeedBuilderTest<float>(m_testCtx, -0.0f,	112541574u, "float_negative_zero", "Seed from float negative zero."));
+		addChild(new SeedBuilderTest<float>(m_testCtx, 1.0f, 	 44355905u, "float_one", "Seed from float one."));
+		addChild(new SeedBuilderTest<float>(m_testCtx, -1.0f,	107334902u, "float_negative_one", "Seed from float negative one."));
+
+		addChild(new SeedBuilderTest<double>(m_testCtx, 0.0,	133470681u, "double_zero", "Seed from double zero."));
+		addChild(new SeedBuilderTest<double>(m_testCtx, -0.0,	 53838958u, "double_negative_zero", "Seed from double negative zero."));
+		addChild(new SeedBuilderTest<double>(m_testCtx, 1.0,	 16975104u, "double_one", "Seed from double one."));
+		addChild(new SeedBuilderTest<double>(m_testCtx, -1.0,	 96606391u, "double_negative_one", "Seed from double negative one."));
+
+		addChild(new SeedBuilderTest<IVec2>(m_testCtx, IVec2(0),	 1111532u, "ivec2_zero", "Seed from zero vector."));
+		addChild(new SeedBuilderTest<IVec3>(m_testCtx, IVec3(0),	22277704u, "ivec3_zero", "Seed from zero vector."));
+		addChild(new SeedBuilderTest<IVec4>(m_testCtx, IVec4(0),	73989201u, "ivec4_zero", "Seed from zero vector."));
+
+		addChild(new SeedBuilderTest<IVec2>(m_testCtx, IVec2(1),	 12819708u, "ivec2_one", "Seed from one vector."));
+		addChild(new SeedBuilderTest<IVec3>(m_testCtx, IVec3(1),	134047100u, "ivec3_one", "Seed from one vector."));
+		addChild(new SeedBuilderTest<IVec4>(m_testCtx, IVec4(1),	 90609878u, "ivec4_one", "Seed from one vector."));
+
+		addChild(new SeedBuilderTest<IVec4>(m_testCtx, IVec4(1, 2, 3, 4),	 6202236u, "ivec4_1_2_3_4", "Seed from (1, 2, 3, 4) vector."));
+		addChild(new SeedBuilderTest<IVec4>(m_testCtx, IVec4(4, 3, 2, 1),	26964618u, "ivec4_4_3_2_1", "Seed from (4, 3, 2, 1) vector."));
+
+		addChild(new SeedBuilderMultipleValuesTest(m_testCtx));
+	}
+};
+
+} // anonymous
+
+tcu::TestCaseGroup* createSeedBuilderTests (tcu::TestContext& testCtx)
+{
+	return new SeedBuilderTests(testCtx);
+}
+
+} // dit
diff --git a/modules/internal/ditSeedBuilderTests.hpp b/modules/internal/ditSeedBuilderTests.hpp
new file mode 100644
index 0000000..170309f
--- /dev/null
+++ b/modules/internal/ditSeedBuilderTests.hpp
@@ -0,0 +1,36 @@
+#ifndef _DITSEEDBUILDERTESTS_HPP
+#define _DITSEEDBUILDERTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Internal Test 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 Seed builder tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace dit
+{
+
+tcu::TestCaseGroup* createSeedBuilderTests (tcu::TestContext& testCtx);
+
+} // dit
+
+#endif // _DITSEEDBUILDERTESTS_HPP
diff --git a/modules/internal/ditTestPackage.cpp b/modules/internal/ditTestPackage.cpp
index 6af0657..22c75b2 100644
--- a/modules/internal/ditTestPackage.cpp
+++ b/modules/internal/ditTestPackage.cpp
@@ -28,6 +28,7 @@
 #include "ditImageIOTests.hpp"
 #include "ditImageCompareTests.hpp"
 #include "ditTestLogTests.hpp"
+#include "ditSeedBuilderTests.hpp"
 
 namespace dit
 {
@@ -45,6 +46,7 @@
 		addChild(new TestLogTests		(m_testCtx));
 		addChild(new ImageIOTests		(m_testCtx));
 		addChild(new ImageCompareTests	(m_testCtx));
+		addChild(createSeedBuilderTests	(m_testCtx));
 	}
 };