1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief String Query tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fStringQueryTests.hpp"
25#include "es3fApiCase.hpp"
26#include "gluRenderContext.hpp"
27#include "glwEnums.hpp"
28#include "glwFunctions.hpp"
29#include "deString.h"
30
31#include <algorithm>
32#include <sstream>
33#include <string>
34
35using namespace glw; // GLint and other GL types
36
37namespace deqp
38{
39namespace gles3
40{
41namespace Functional
42{
43
44StringQueryTests::StringQueryTests (Context& context)
45	: TestCaseGroup (context, "string", "String Query tests")
46{
47}
48
49StringQueryTests::~StringQueryTests (void)
50{
51}
52
53void StringQueryTests::init (void)
54{
55	using tcu::TestLog;
56
57	ES3F_ADD_API_CASE(renderer, "RENDERER",
58	{
59		const GLubyte* string = glGetString(GL_RENDERER);
60		if (string == NULL)
61			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid string");
62	});
63	ES3F_ADD_API_CASE(vendor, "VENDOR",
64	{
65		const GLubyte* string = glGetString(GL_VENDOR);
66		if (string == NULL)
67			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid string");
68	});
69	ES3F_ADD_API_CASE(version, "VERSION",
70	{
71		bool isES = glu::isContextTypeES(m_context.getRenderContext().getType());
72
73		const char* string		= (const char*)glGetString(GL_VERSION);
74		const char *referenceString	= isES ? "OpenGL ES 3." : "4.";
75
76		if (string == NULL)
77			TCU_FAIL("Got invalid string");
78
79		if (!deStringBeginsWith(string, referenceString))
80			TCU_FAIL("Got invalid string prefix");
81
82		{
83			std::string tmpString;
84			char		versionDelimiter;
85			int			glMajor				= 0;
86			int			glMinor				= 0;
87			GLint		stateVersionMinor	= 0;
88
89			std::istringstream versionStream(string);
90
91			if (isES) {
92				versionStream >> tmpString;			// OpenGL
93				versionStream >> tmpString;			// ES
94			}
95
96			versionStream >> glMajor;			// 3
97			versionStream >> std::noskipws;
98			versionStream >> versionDelimiter;	// .
99			versionStream >> glMinor;			// x
100
101			if (!versionStream)
102				TCU_FAIL("Got invalid string format");
103
104			glGetIntegerv(GL_MINOR_VERSION, &stateVersionMinor);
105			if (glMinor != stateVersionMinor)
106			{
107				m_testCtx.getLog() << TestLog::Message << "// ERROR: MINOR_VERSION is " << stateVersionMinor << TestLog::EndMessage;
108				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid version.");
109				return;
110			}
111		}
112	});
113	ES3F_ADD_API_CASE(shading_language_version, "SHADING_LANGUAGE_VERSION",
114	{
115		bool isES = glu::isContextTypeES(m_context.getRenderContext().getType());
116
117		const char* string		= (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
118		const char *referenceString	= isES ? "OpenGL ES GLSL ES " : "4.";
119
120		if (string == NULL)
121			TCU_FAIL("Got invalid string");
122
123		if (!deStringBeginsWith(string, referenceString))
124			TCU_FAIL("Got invalid string prefix");
125
126		{
127			std::string tmpString;
128			char		versionDelimiter;
129			int			glslMajor			= 0;
130			char		glslMinorDigit1		= 0;
131			char		glslMinorDigit2		= 0;
132			bool		digitsAreValid;
133
134			std::istringstream versionStream(string);
135
136			if (isES) {
137				versionStream >> tmpString;			// OpenGL
138				versionStream >> tmpString;			// ES
139				versionStream >> tmpString;			// GLSL
140				versionStream >> tmpString;			// ES
141			}
142
143			versionStream >> glslMajor;			// x
144			versionStream >> std::noskipws;
145			versionStream >> versionDelimiter;	// .
146			versionStream >> glslMinorDigit1;	// x
147			versionStream >> glslMinorDigit2;	// x
148
149			digitsAreValid =	glslMinorDigit1 >= '0' && glslMinorDigit1 <= '9' &&
150								glslMinorDigit2 >= '0' && glslMinorDigit2 <= '9';
151
152			if (!versionStream || !digitsAreValid)
153				TCU_FAIL("Got invalid string format");
154		}
155	});
156	ES3F_ADD_API_CASE(extensions, "EXTENSIONS",
157	{
158		const char* extensions_cstring = (const char*)glGetString(GL_EXTENSIONS);
159		if (extensions_cstring == NULL) {
160			bool isES = glu::isContextTypeES(m_context.getRenderContext().getType());
161
162			// GL_EXTENSIONS has been deprecated on desktop GL
163			if (!isES) {
164				m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Got NULL string for deprecated enum");
165				expectError(GL_INVALID_ENUM);
166				return;
167			}
168
169			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid string");
170			return;
171                }
172
173		// split extensions_string at ' '
174
175		std::istringstream extensionStream((std::string)(extensions_cstring));
176		std::vector<std::string> extensions;
177
178		for (;;)
179		{
180			std::string extension;
181			if (std::getline(extensionStream, extension, ' '))
182				extensions.push_back(extension);
183			else
184				break;
185		}
186
187		GLint numExtensions = 0;
188		glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
189		expectError(GL_NO_ERROR);
190
191		if (extensions.size() != (size_t)numExtensions)
192		{
193			m_testCtx.getLog() << TestLog::Message << "// ERROR:  NUM_EXTENSIONS is " << numExtensions << "; got " << extensions.size() << " extensions" << TestLog::EndMessage;
194			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
195				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got non-consistent number of extensions");
196		}
197
198		// all in glGetStringi(GL_EXTENSIONS) in must be in glGetString
199
200		for (int i = 0; i < numExtensions; ++i)
201		{
202			std::string extension((const char*)glGetStringi(GL_EXTENSIONS, i));
203
204			if (std::find(extensions.begin(), extensions.end(), extension) == extensions.end())
205			{
206				m_testCtx.getLog() << TestLog::Message << "// ERROR: extension " << extension << " found with GetStringi was not found in glGetString(GL_EXTENSIONS)" << TestLog::EndMessage;
207				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
208					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Extension query methods are not consistent.");
209			}
210		}
211
212		// only elements in glGetStringi(GL_EXTENSIONS) can be in glGetString
213
214		for (int i = 0; i < numExtensions; ++i)
215		{
216			std::string extension((const char*)glGetStringi(GL_EXTENSIONS, i));
217
218			std::vector<std::string>::iterator it = std::find(extensions.begin(), extensions.end(), extension);
219			if (it != extensions.end())
220				extensions.erase(it);
221		}
222
223		if (!extensions.empty())
224		{
225			for (size_t ndx = 0; ndx < extensions.size(); ++ndx)
226				m_testCtx.getLog() << TestLog::Message << "// ERROR: extension \"" << extensions[ndx] << "\" found with GetString was not found with GetStringi(GL_EXTENSIONS, ind)" << TestLog::EndMessage;
227
228			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
229				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Extension query methods are not consistent.");
230		}
231
232	});
233}
234
235} // Functional
236} // gles3
237} // deqp
238