1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-2018 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24/**
25 * \file  glcKHRDebugTests.cpp
26 * \brief Implements conformance tests for "KHR Debug" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29#include "glcKHRDebugTests.hpp"
30
31#include "gluPlatform.hpp"
32#include "gluRenderConfig.hpp"
33#include "gluRenderContext.hpp"
34#include "gluStrUtil.hpp"
35#include "glwEnums.hpp"
36#include "glwFunctions.hpp"
37#include "tcuCommandLine.hpp"
38#include "tcuTestLog.hpp"
39//
40//#include <string>
41
42#define DEBUG_ENBALE_MESSAGE_CALLBACK 0
43
44#if DEBUG_ENBALE_MESSAGE_CALLBACK
45//#include <iomanip>
46#endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
47
48using namespace glw;
49
50namespace glcts
51{
52namespace KHRDebug
53{
54/** Macro, verifies generated error, logs error message and throws failure
55 *
56 * @param expected_error Expected error value
57 * @param error_message  Message logged if generated error is not the expected one
58 **/
59#define CHECK_ERROR(expected_error, error_message)                                                      \
60	do {                                                                                                \
61		GLenum generated_error = m_gl->getError();                                                      \
62                                                                                                        \
63		if (expected_error != generated_error)                                                          \
64		{                                                                                               \
65			m_testCtx.getLog()                                                                          \
66				<< tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__              \
67				<< ". Got wrong error: " << glu::getErrorStr(generated_error)                           \
68				<< ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \
69				<< tcu::TestLog::EndMessage;                                                            \
70			TestBase::done();                                                                           \
71			TCU_FAIL("Invalid error generated");                                                        \
72		}                                                                                               \
73	} while (0)
74
75/** Pop all groups from stack
76 *
77 * @param gl GL functions
78 **/
79void cleanGroupStack(const Functions* gl)
80{
81	while (1)
82	{
83		gl->popDebugGroup();
84
85		const GLenum err = gl->getError();
86
87		if (GL_STACK_UNDERFLOW == err)
88		{
89			break;
90		}
91
92		GLU_EXPECT_NO_ERROR(err, "PopDebugGroup");
93	}
94}
95
96/** Extracts all messages from log
97 *
98 * @param gl GL functions
99 **/
100void cleanMessageLog(const Functions* gl)
101{
102	static const GLuint count = 16;
103
104	while (1)
105	{
106		GLuint ret = gl->getDebugMessageLog(count /* count */, 0 /* bufSize */, 0 /* sources */, 0 /* types */,
107											0 /* ids */, 0 /* severities */, 0 /* lengths */, 0 /* messageLog */);
108
109		GLU_EXPECT_NO_ERROR(gl->getError(), "GetDebugMessageLog");
110
111		if (0 == ret)
112		{
113			break;
114		}
115	}
116}
117
118/** Fill stack of groups
119 *
120 * @param gl GL functions
121 **/
122void fillGroupStack(const Functions* gl)
123{
124	static const GLchar  message[] = "Foo";
125	static const GLsizei length	= (GLsizei)(sizeof(message) / sizeof(message[0]));
126
127	while (1)
128	{
129		gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */,
130						   message /* message */);
131
132		const GLenum err = gl->getError();
133
134		if (GL_STACK_OVERFLOW == err)
135		{
136			break;
137		}
138
139		GLU_EXPECT_NO_ERROR(err, "PopDebugGroup");
140	}
141}
142
143/** Constructor
144 * Creates and set as current new context that should be used by test.
145 *
146 * @param testCtx  Test context
147 * @param is_debug Selects if debug or non-debug context should be created
148 **/
149TestBase::TestBase(tcu::TestContext& testContext, glu::ApiType apiType, bool is_debug)
150	: m_gl(0), m_is_debug(is_debug), m_rc(0), m_testContext(testContext), m_apiType(apiType)
151{
152	/* Nothing to be done here */
153}
154
155/** Destructor
156 * Destroys context used by test and set original context as current
157 **/
158TestBase::~TestBase()
159{
160	if (0 != m_rc)
161	{
162		done();
163	}
164}
165
166/** Initialize rendering context
167 **/
168void TestBase::init()
169{
170	if (true == m_is_debug)
171	{
172		initDebug();
173	}
174	else
175	{
176		initNonDebug();
177	}
178
179	/* Get functions */
180	m_gl = &m_rc->getFunctions();
181}
182
183/** Prepares debug context
184 **/
185void TestBase::initDebug()
186{
187	tcu::Platform&	platform = m_testContext.getPlatform();
188	glu::RenderConfig renderCfg(glu::ContextType(m_apiType, glu::CONTEXT_DEBUG));
189
190	const tcu::CommandLine& commandLine = m_testContext.getCommandLine();
191	parseRenderConfig(&renderCfg, commandLine);
192
193	if (commandLine.getSurfaceType() != tcu::SURFACETYPE_WINDOW)
194		throw tcu::NotSupportedError("Test not supported in non-windowed context");
195
196	m_rc = createRenderContext(platform, commandLine, renderCfg);
197	m_rc->makeCurrent();
198}
199
200/** Prepares non-debug context
201 **/
202void TestBase::initNonDebug()
203{
204	tcu::Platform&	platform = m_testContext.getPlatform();
205	glu::RenderConfig renderCfg(glu::ContextType(m_apiType, glu::ContextFlags(0)));
206
207	const tcu::CommandLine& commandLine = m_testContext.getCommandLine();
208	parseRenderConfig(&renderCfg, commandLine);
209
210	if (commandLine.getSurfaceType() != tcu::SURFACETYPE_WINDOW)
211		throw tcu::NotSupportedError("Test not supported in non-windowed context");
212
213	m_rc = createRenderContext(platform, commandLine, renderCfg);
214	m_rc->makeCurrent();
215}
216
217/** Finalize rendering context
218 **/
219void TestBase::done()
220{
221	/* Delete context used by test and make no context current */
222	delete m_rc;
223
224	m_rc = 0;
225	m_gl = 0;
226}
227
228/** Constructor
229 *
230 * @param testCtx  Test context
231 * @param is_debug Selects if debug or non-debug context should be used
232 * @param name     Name of test
233 **/
234APIErrorsTest::APIErrorsTest(tcu::TestContext& testCtx, glu::ApiType apiType, bool is_debug, const GLchar* name)
235	: TestBase(testCtx, apiType, is_debug), TestCase(testCtx, name, "Verifies that errors are generated as expected")
236{
237	/* Nothing to be done */
238}
239
240/** Execute test
241 *
242 * @return tcu::TestNode::STOP
243 **/
244tcu::TestNode::IterateResult APIErrorsTest::iterate()
245{
246	/* Initialize rendering context */
247	TestBase::init();
248
249	/* Get maximum label length */
250	GLint max_label = 0;
251
252	m_gl->getIntegerv(GL_MAX_LABEL_LENGTH, &max_label);
253	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
254
255	/* Prepare too long label */
256	std::vector<GLchar> too_long_label;
257
258	too_long_label.resize(max_label + 2);
259
260	for (GLint i = 0; i <= max_label; ++i)
261	{
262		too_long_label[i] = 'f';
263	}
264
265	too_long_label[max_label + 1] = 0;
266
267	/* Get maximum message length */
268	GLint max_length = 0;
269
270	m_gl->getIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &max_length);
271	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
272
273	/* Prepare too long message */
274	std::vector<GLchar> too_long_message;
275
276	too_long_message.resize(max_length + 2);
277
278	for (GLint i = 0; i <= max_length; ++i)
279	{
280		too_long_message[i] = 'f';
281	}
282
283	too_long_message[max_length + 1] = 0;
284
285	/* Get maximum number of groups on stack */
286	GLint max_groups = 0;
287
288	m_gl->getIntegerv(GL_MAX_DEBUG_GROUP_STACK_DEPTH, &max_groups);
289	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
290
291	/*
292	 * DebugMessageControl function should generate:
293	 * - INVALID_ENUM when <source> is invalid;
294	 * - INVALID_ENUM when <type> is invalid;
295	 * - INVALID_ENUM when <severity> is invalid;
296	 * - INVALID_VALUE when <count> is negative;
297	 * - INVALID_OPERATION when <count> is not zero and <source> is DONT_CARE;
298	 * - INVALID_OPERATION when <count> is not zero and <type> is DONT_CARE;
299	 * - INVALID_OPERATION when <count> is not zero and <severity> is not
300	 * DONT_CARE.
301	 */
302	{
303		static const GLuint  ids[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
304		static const GLsizei n_ids = (GLsizei)(sizeof(ids) / sizeof(ids[0]));
305
306		m_gl->debugMessageControl(GL_ARRAY_BUFFER /* source */, GL_DEBUG_TYPE_ERROR /* type */,
307								  GL_DEBUG_SEVERITY_LOW /* severity */, 0 /* count */, 0 /* ids */,
308								  GL_TRUE /* enabled */);
309		CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <source> set to GL_ARRAY_BUFFER");
310
311		m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_ARRAY_BUFFER /* type */,
312								  GL_DEBUG_SEVERITY_LOW /* severity */, 0 /* count */, 0 /* ids */,
313								  GL_TRUE /* enabled */);
314		CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <type> set to GL_ARRAY_BUFFER");
315
316		m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */,
317								  GL_ARRAY_BUFFER /* severity */, 0 /* count */, 0 /* ids */, GL_TRUE /* enabled */);
318		CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <severity> set to GL_ARRAY_BUFFER");
319
320		m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */,
321								  GL_DEBUG_SEVERITY_LOW /* severity */, -1 /* count */, ids /* ids */,
322								  GL_TRUE /* enabled */);
323		CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageControl with <count> set to -1");
324
325		m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
326								  GL_DONT_CARE /* severity */, n_ids /* count */, ids /* ids */, GL_TRUE /* enabled */);
327		CHECK_ERROR(GL_INVALID_OPERATION, "DebugMessageControl with <source> set to GL_DONT_CARE and non zero <count>");
328
329		m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DONT_CARE /* type */,
330								  GL_DONT_CARE /* severity */, n_ids /* count */, ids /* ids */, GL_TRUE /* enabled */);
331		CHECK_ERROR(GL_INVALID_OPERATION, "DebugMessageControl with <type> set to GL_DONT_CARE and non zero <count>");
332
333		m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */,
334								  GL_DEBUG_SEVERITY_LOW /* severity */, n_ids /* count */, ids /* ids */,
335								  GL_TRUE /* enabled */);
336		CHECK_ERROR(GL_INVALID_OPERATION,
337					"DebugMessageControl with <severity> set to GL_DEBUG_SEVERITY_LOW and non zero <count>");
338	}
339
340	/*
341	 * GetDebugMessageLog function should generate:
342	 * - INVALID_VALUE when <bufSize> is negative and messageLog is not NULL.
343	 */
344	{
345		static const GLsizei bufSize = 32;
346		static const GLuint  count   = 4;
347
348		GLenum  ids[count];
349		GLsizei lengths[count];
350		GLchar  messageLog[bufSize];
351		GLenum  types[count];
352		GLenum  severities[count];
353		GLenum  sources[count];
354
355		m_gl->getDebugMessageLog(count /* count */, -1 /* bufSize */, sources, types, ids, severities, lengths,
356								 messageLog);
357		CHECK_ERROR(GL_INVALID_VALUE, "GetDebugMessageLog with <bufSize> set to -1");
358	}
359
360	/*
361	 * DebugMessageInsert function should generate:
362	 * - INVALID_ENUM when <source> is not DEBUG_SOURCE_APPLICATION or
363	 * DEBUG_SOURCE_THIRD_PARTY;
364	 * - INVALID_ENUM when <type> is invalid;
365	 * - INVALID_ENUM when <severity> is invalid;
366	 * - INVALID_VALUE when length of string <buf> is not less than
367	 * MAX_DEBUG_MESSAGE_LENGTH.
368	 */
369	{
370		static const GLchar  message[] = "Foo";
371		static const GLsizei length	= (GLsizei)(sizeof(message) / sizeof(message[0]));
372
373		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
374								 0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, length /* length */,
375								 message /* message */);
376		CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <source> set to GL_DEBUG_SOURCE_API");
377
378		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_ARRAY_BUFFER /* type */, 0 /* id */,
379								 GL_DEBUG_SEVERITY_LOW /* severity */, length /* length */, message /* message */);
380		CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <type> set to GL_ARRAY_BUFFER");
381
382		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
383								 0 /* id */, GL_ARRAY_BUFFER /* severity */, length /* length */,
384								 message /* message */);
385		CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <severity> set to GL_ARRAY_BUFFER");
386
387		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
388								 0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, max_length + 1 /* length */,
389								 message /* message */);
390		CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageInsert with <length> set to GL_MAX_DEBUG_MESSAGE_LENGTH + 1");
391
392		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */,
393								 0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, -1 /* length */,
394								 &too_long_message[0] /* message */);
395		CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageInsert with too long message");
396	}
397
398	/*
399	 * PushDebugGroup function should generate:
400	 * - INVALID_ENUM when <source> is not DEBUG_SOURCE_APPLICATION or
401	 * DEBUG_SOURCE_THIRD_PARTY;
402	 * - INVALID_VALUE when length of string <message> is not less than
403	 * MAX_DEBUG_MESSAGE_LENGTH;
404	 * - STACK_OVERFLOW when stack contains MAX_DEBUG_GROUP_STACK_DEPTH entries.
405	 */
406	{
407		static const GLchar  message[] = "Foo";
408		static const GLsizei length	= (GLsizei)(sizeof(message) / sizeof(message[0]));
409
410		m_gl->pushDebugGroup(GL_DEBUG_SOURCE_API /* source */, 1 /* id */, length /* length */, message /* message */);
411		CHECK_ERROR(GL_INVALID_ENUM, "PushDebugGroup with <source> set to GL_DEBUG_SOURCE_API");
412
413		m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, max_length + 1 /* length */,
414							 message /* message */);
415		CHECK_ERROR(GL_INVALID_VALUE, "PushDebugGroup with <length> set to GL_MAX_DEBUG_MESSAGE_LENGTH + 1");
416
417		m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, -1 /* length */,
418							 &too_long_message[0] /* message */);
419		CHECK_ERROR(GL_INVALID_VALUE, "PushDebugGroup with too long message");
420
421		/* Clean stack */
422		cleanGroupStack(m_gl);
423
424		/* Fill stack */
425		for (GLint i = 0; i < max_groups - 1; ++i)
426		{
427			m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */,
428								 message /* message */);
429			GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup");
430		}
431
432		/* Overflow stack */
433		m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */,
434							 message /* message */);
435		CHECK_ERROR(GL_STACK_OVERFLOW, "PushDebugGroup called GL_MAX_DEBUG_GROUP_STACK_DEPTH times");
436
437		/* Clean stack */
438		cleanGroupStack(m_gl);
439	}
440
441	/*
442	 * PopDebugGroup function should generate:
443	 * - STACK_UNDERFLOW when stack contains no entries.
444	 */
445	{
446		fillGroupStack(m_gl);
447
448		for (GLint i = 0; i < max_groups - 1; ++i)
449		{
450			m_gl->popDebugGroup();
451
452			GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup");
453		}
454
455		m_gl->popDebugGroup();
456		CHECK_ERROR(GL_STACK_UNDERFLOW, "PopDebugGroup called GL_MAX_DEBUG_GROUP_STACK_DEPTH times");
457	}
458
459	/*
460	 * ObjectLabel function should generate:
461	 * - INVALID_ENUM when <identifier> is invalid;
462	 * - INVALID_VALUE when if <name> is not valid object name of type specified by
463	 * <identifier>;
464	 * - INVALID_VALUE when length of string <label> is not less than
465	 * MAX_LABEL_LENGTH.
466	 */
467	{
468		static const GLchar  label[] = "Foo";
469		static const GLsizei length  = (GLsizei)(sizeof(label) / sizeof(label[0]));
470
471		GLuint texture_id = 0;
472		GLuint invalid_id = 1;
473		m_gl->genTextures(1, &texture_id);
474		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenTextures");
475		m_gl->bindTexture(GL_TEXTURE_BUFFER, texture_id);
476		GLU_EXPECT_NO_ERROR(m_gl->getError(), "BindTexture");
477
478		try
479		{
480			m_gl->objectLabel(GL_TEXTURE_BUFFER /* identifier */, texture_id /* name */, length /* length */,
481							  label /* label */);
482			CHECK_ERROR(GL_INVALID_ENUM, "ObjectLabel with <identifier> set to GL_TEXTURE_BUFFER");
483
484			while (GL_TRUE == m_gl->isTexture(invalid_id))
485			{
486				invalid_id += 1;
487			}
488
489			m_gl->objectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, length /* length */,
490							  label /* label */);
491			CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with <name> set to not generated value");
492
493			m_gl->objectLabel(GL_TEXTURE /* identifier */, texture_id /* name */, max_label + 1 /* length */,
494							  label /* label */);
495			CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with <label> set to MAX_LABEL_LENGTH + 1");
496
497			m_gl->objectLabel(GL_TEXTURE /* identifier */, texture_id /* name */, -1 /* length */,
498							  &too_long_label[0] /* label */);
499			CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with too long label");
500		}
501		catch (const std::exception& exc)
502		{
503			m_gl->deleteTextures(1, &texture_id);
504			TCU_FAIL(exc.what());
505		}
506
507		m_gl->deleteTextures(1, &texture_id);
508	}
509
510	/*
511	 * GetObjectLabel function should generate:
512	 * - INVALID_ENUM when <identifier> is invalid;
513	 * - INVALID_VALUE when if <name> is not valid object name of type specified by
514	 * <identifier>;
515	 * - INVALID_VALUE when <bufSize> is negative.
516	 */
517	{
518		static const GLsizei bufSize = 32;
519
520		GLchar  label[bufSize];
521		GLsizei length = 0;
522
523		GLuint texture_id = 0;
524		GLuint invalid_id = 1;
525		m_gl->genTextures(1, &texture_id);
526		m_gl->bindTexture(GL_TEXTURE_2D, texture_id);
527		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenTextures");
528
529		try
530		{
531			m_gl->getObjectLabel(GL_TEXTURE_BUFFER /* identifier */, texture_id /* name */, bufSize /* bufSize */,
532								 &length /* length */, label /* label */);
533			CHECK_ERROR(GL_INVALID_ENUM, "GetObjectLabel with <identifier> set to GL_TEXTURE_BUFFER");
534
535			while (GL_TRUE == m_gl->isTexture(invalid_id))
536			{
537				invalid_id += 1;
538			}
539
540			m_gl->getObjectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, bufSize /* bufSize */,
541								 &length /* length */, label /* label */);
542			CHECK_ERROR(GL_INVALID_VALUE, "GetObjectLabel with <name> set to not generated value");
543
544			m_gl->getObjectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, -1 /* bufSize */,
545								 &length /* length */, label /* label */);
546			CHECK_ERROR(GL_INVALID_VALUE, "GetObjectLabel with <bufSize> set to -1");
547		}
548		catch (const std::exception& exc)
549		{
550			m_gl->deleteTextures(1, &texture_id);
551			TCU_FAIL(exc.what());
552		}
553
554		m_gl->deleteTextures(1, &texture_id);
555	}
556
557	/*
558	 * ObjectPtrLabel function should generate:
559	 * - INVALID_VALUE when <ptr> is not the name of sync object;
560	 * - INVALID_VALUE when length of string <label> is not less than
561	 * MAX_LABEL_LENGTH.
562	 */
563	{
564		static const GLchar  label[] = "Foo";
565		static const GLsizei length  = (GLsizei)(sizeof(label) / sizeof(label[0]));
566
567		GLsync sync_id	= 0;
568		GLsync invalid_id = 0;
569		sync_id			  = m_gl->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
570		GLU_EXPECT_NO_ERROR(m_gl->getError(), "FenceSync");
571
572		try
573		{
574			while (GL_TRUE == m_gl->isSync(invalid_id))
575			{
576				invalid_id = (GLsync)(((unsigned long long)invalid_id) + 1);
577			}
578
579			m_gl->objectPtrLabel(invalid_id /* name */, length /* length */, label /* label */);
580			CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with <ptr> set to not generated value");
581
582			m_gl->objectPtrLabel(sync_id /* name */, max_label + 1 /* length */, label /* label */);
583			CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with <length> set to MAX_LABEL_LENGTH + 1");
584
585			m_gl->objectPtrLabel(sync_id /* name */, -1 /* length */, &too_long_label[0] /* label */);
586			CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with too long label");
587		}
588		catch (const std::exception& exc)
589		{
590			m_gl->deleteSync(sync_id);
591			TCU_FAIL(exc.what());
592		}
593
594		m_gl->deleteSync(sync_id);
595	}
596
597	/*
598	 * GetObjectPtrLabel function should generate:
599	 * - INVALID_VALUE when <ptr> is not the name of sync object;
600	 * - INVALID_VALUE when <bufSize> is negative.
601	 */
602	{
603		static const GLsizei bufSize = 32;
604
605		GLchar  label[bufSize];
606		GLsizei length = 0;
607
608		GLsync sync_id	= 0;
609		GLsync invalid_id = 0;
610		sync_id			  = m_gl->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
611		GLU_EXPECT_NO_ERROR(m_gl->getError(), "FenceSync");
612
613		try
614		{
615			while (GL_TRUE == m_gl->isSync(invalid_id))
616			{
617				invalid_id = (GLsync)(((unsigned long long)invalid_id) + 1);
618			}
619
620			m_gl->getObjectPtrLabel(invalid_id /* name */, bufSize /* bufSize */, &length /* length */,
621									label /* label */);
622			CHECK_ERROR(GL_INVALID_VALUE, "GetObjectPtrLabel with <ptr> set to not generated value");
623
624			m_gl->getObjectPtrLabel(sync_id /* name */, -1 /* bufSize */, &length /* length */, label /* label */);
625			CHECK_ERROR(GL_INVALID_VALUE, "GetObjectPtrLabel with <bufSize> set to -1");
626		}
627		catch (const std::exception& exc)
628		{
629			m_gl->deleteSync(sync_id);
630			TCU_FAIL(exc.what());
631		}
632
633		m_gl->deleteSync(sync_id);
634	}
635
636	/*
637	 * GetPointerv function should generate:
638	 * - INVALID_ENUM when <pname> is invalid.
639	 **/
640	{
641		GLuint  uint;
642		GLuint* uint_ptr = &uint;
643
644		m_gl->getPointerv(GL_ARRAY_BUFFER, (GLvoid**)&uint_ptr);
645		CHECK_ERROR(GL_INVALID_ENUM, "GetPointerv with <pname> set to GL_ARRAY_BUFFER");
646	}
647
648	/* Set result */
649	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
650
651	/* Done */
652	TestBase::done();
653
654	return tcu::TestNode::STOP;
655}
656
657/** Constructor
658 *
659 * @param testCtx  Test context
660 * @param is_debug Selects if debug or non-debug context should be used
661 * @param name     Name of test
662 **/
663LabelsTest::LabelsTest(tcu::TestContext& testCtx, glu::ApiType apiType, bool is_debug, const GLchar* name)
664	: TestCase(testCtx, name, "Verifies that labels can be assigned and queried"), TestBase(testCtx, apiType, is_debug)
665{
666	/* Nothing to be done */
667}
668
669/** Represnets case for LabelsTest **/
670struct labelsTestCase
671{
672	GLenum m_identifier;
673	GLuint (*m_create)(const glw::Functions* gl, const glu::RenderContext*);
674	GLvoid (*m_destroy)(const glw::Functions* gl, GLuint id);
675	const GLchar* m_name;
676};
677
678/** Execute test
679 *
680 * @return tcu::TestNode::STOP
681 **/
682tcu::TestNode::IterateResult LabelsTest::iterate()
683{
684	static const labelsTestCase test_cases[] = {
685		{ GL_BUFFER, createBuffer, deleteBuffer, "Buffer" },
686		{ GL_FRAMEBUFFER, createFramebuffer, deleteFramebuffer, "Framebuffer" },
687		{ GL_PROGRAM, createProgram, deleteProgram, "Program" },
688		{ GL_PROGRAM_PIPELINE, createProgramPipeline, deleteProgramPipeline, "ProgramPipeline" },
689		{ GL_QUERY, createQuery, deleteQuery, "Query" },
690		{ GL_RENDERBUFFER, createRenderbuffer, deleteRenderbuffer, "Renderbuffer" },
691		{ GL_SAMPLER, createSampler, deleteSampler, "Sampler" },
692		{ GL_SHADER, createShader, deleteShader, "Shader" },
693		{ GL_TEXTURE, createTexture, deleteTexture, "Texture" },
694		{ GL_TRANSFORM_FEEDBACK, createTransformFeedback, deleteTransformFeedback, "TransformFeedback" },
695		{ GL_VERTEX_ARRAY, createVertexArray, deleteVertexArray, "VertexArray" },
696	};
697
698	static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
699
700	static const GLsizei bufSize	  = 32;
701	static const GLchar  label[]	  = "foo";
702	static const GLsizei label_length = (GLsizei)(sizeof(label) / sizeof(label[0]) - 1);
703
704	/* Initialize render context */
705	TestBase::init();
706
707	/* For each test case */
708	for (size_t test_case_index = 0; test_case_index < n_test_cases; ++test_case_index)
709	{
710		const labelsTestCase& test_case = test_cases[test_case_index];
711
712		const GLenum identifier = test_case.m_identifier;
713		const GLuint id			= test_case.m_create(m_gl, m_rc);
714
715		try
716		{
717			GLchar  buffer[bufSize] = "HelloWorld";
718			GLsizei length;
719
720			/*
721			 * - query label; It is expected that result will be an empty string and length
722			 * will be zero;
723			 */
724			m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
725			GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
726
727			if (0 != length)
728			{
729				TCU_FAIL("Just created object has label of length != 0");
730			}
731
732			if (0 != buffer[0])
733			{
734				TCU_FAIL("Just created object has not empty label");
735			}
736
737			/*
738			 * - assign label to object;
739			 * - query label; It is expected that result will be equal to the provided
740			 * label and length will be correct;
741			 */
742			m_gl->objectLabel(identifier, id, -1 /* length */, label);
743			GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel");
744
745			m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
746			GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
747
748			if (label_length != length)
749			{
750				TCU_FAIL("Length is different than length of set label");
751			}
752
753			if (0 != strcmp(buffer, label))
754			{
755				TCU_FAIL("Different label returned");
756			}
757
758			/*
759			 * - query length only; Correct value is expected;
760			 */
761			length = 0;
762
763			m_gl->getObjectLabel(identifier, id, 0 /* bufSize */, &length, 0 /* label */);
764			GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
765
766			if (label_length != length)
767			{
768				TCU_FAIL("Invalid length returned when label and bufSize are set to 0");
769			}
770
771			/*
772			 * - query label with <bufSize> less than actual length of label; It is
773			 * expected that only <bufSize> characters will be stored in buffer (including
774			 * NULL);
775			 */
776			length = 0;
777			strcpy(buffer, "HelloWorld");
778
779			m_gl->getObjectLabel(identifier, id, 2 /* bufSize */, &length, buffer);
780			GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
781
782			if (buffer[0] != label[0])
783			{
784				TCU_FAIL("Different label returned");
785			}
786
787			if (buffer[1] != 0)
788			{
789				TCU_FAIL("GetObjectLabel did not stored NULL at the end of string");
790			}
791
792			if (buffer[2] != 'l')
793			{
794				TCU_FAIL("GetObjectLabel overflowed buffer");
795			}
796
797			/*
798			 * - query label with <bufSize> equal zero; It is expected that buffer contents
799			 * will not be modified;
800			 */
801			length = 0;
802			strcpy(buffer, "HelloWorld");
803
804			m_gl->getObjectLabel(identifier, id, 0 /* bufSize */, &length, buffer);
805			GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
806
807			if (0 != strcmp(buffer, "HelloWorld"))
808			{
809				TCU_FAIL("GetObjectLabel modified buffer, bufSize set to 0");
810			}
811
812			/*
813			 * - assign empty string as label to object;
814			 * - query label, it is expected that result will be an empty string and length
815			 * will be zero;
816			 */
817			m_gl->objectLabel(identifier, id, -1 /* length */, "");
818			GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel");
819
820			m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
821			GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
822
823			if (0 != length)
824			{
825				TCU_FAIL("Label length is != 0, empty string was set");
826			}
827
828			if (0 != buffer[0])
829			{
830				TCU_FAIL("Non empty label returned, empty string was set");
831			}
832
833			/*
834			 * - assign NULL as label to object;
835			 * - query label, it is expected that result will be an empty string and length
836			 * will be zero;
837			 */
838			m_gl->objectLabel(identifier, id, 2, 0 /* label */);
839			GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel");
840
841			m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer);
842			GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel");
843
844			if (0 != length)
845			{
846				TCU_FAIL("Label length is != 0, label was removed");
847			}
848
849			if (0 != buffer[0])
850			{
851				TCU_FAIL("Different label returned, label was removed");
852			}
853		}
854		catch (const std::exception& exc)
855		{
856			test_case.m_destroy(m_gl, id);
857
858			m_testCtx.getLog()
859				<< tcu::TestLog::Message << "Error during test case: " << test_case.m_name << tcu::TestLog::EndMessage;
860
861			TCU_FAIL(exc.what());
862		}
863
864		test_case.m_destroy(m_gl, id);
865	}
866
867	/* Set result */
868	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
869
870	/* Done */
871	TestBase::done();
872
873	return tcu::TestNode::STOP;
874}
875
876/** Create buffer
877 *
878 * @param gl GL functions
879 *
880 * @return ID of created resource
881 **/
882GLuint LabelsTest::createBuffer(const Functions* gl, const glu::RenderContext* rc)
883{
884	GLuint id = 0;
885
886	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
887	{
888		gl->createBuffers(1, &id);
889		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateBuffers");
890	}
891	else
892	{
893		gl->genBuffers(1, &id);
894		gl->bindBuffer(GL_ARRAY_BUFFER, id);
895		GLU_EXPECT_NO_ERROR(gl->getError(), "GenBuffers");
896	}
897
898	return id;
899}
900
901/** Create FBO
902 *
903 * @param gl GL functions
904 *
905 * @return ID of created resource
906 **/
907GLuint LabelsTest::createFramebuffer(const Functions* gl, const glu::RenderContext* rc)
908{
909	GLuint id = 0;
910	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
911	{
912		gl->createFramebuffers(1, &id);
913		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateFramebuffers");
914	}
915	else
916	{
917		GLint currentFbo;
918		gl->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFbo);
919		gl->genFramebuffers(1, &id);
920		gl->bindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
921		gl->bindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFbo);
922		GLU_EXPECT_NO_ERROR(gl->getError(), "GenFramebuffers / BindFramebuffer");
923	}
924
925	return id;
926}
927
928/** Create program
929 *
930 * @param gl GL functions
931 *
932 * @return ID of created resource
933 **/
934GLuint LabelsTest::createProgram(const Functions* gl, const glu::RenderContext*)
935{
936	GLuint id = gl->createProgram();
937	GLU_EXPECT_NO_ERROR(gl->getError(), "CreateProgram");
938
939	return id;
940}
941
942/** Create pipeline
943 *
944 * @param gl GL functions
945 *
946 * @return ID of created resource
947 **/
948GLuint LabelsTest::createProgramPipeline(const Functions* gl, const glu::RenderContext* rc)
949{
950	GLuint id = 0;
951	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
952	{
953		gl->createProgramPipelines(1, &id);
954		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateProgramPipelines");
955	}
956	else
957	{
958		gl->genProgramPipelines(1, &id);
959		gl->bindProgramPipeline(id);
960		GLU_EXPECT_NO_ERROR(gl->getError(), "GenProgramPipelines / BindProgramPipeline");
961	}
962
963	return id;
964}
965
966/** Create query
967 *
968 * @param gl GL functions
969 *
970 * @return ID of created resource
971 **/
972GLuint LabelsTest::createQuery(const Functions* gl, const glu::RenderContext* rc)
973{
974	GLuint id = 0;
975	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
976	{
977		gl->createQueries(GL_TIMESTAMP, 1, &id);
978		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateQueries");
979	}
980	else
981	{
982		gl->genQueries(1, &id);
983		gl->beginQuery(GL_SAMPLES_PASSED, id);
984		gl->endQuery(GL_SAMPLES_PASSED);
985		GLU_EXPECT_NO_ERROR(gl->getError(), "GenQueries / BeginQuery / EndQuery");
986	}
987
988	return id;
989}
990
991/** Create render buffer
992 *
993 * @param gl GL functions
994 *
995 * @return ID of created resource
996 **/
997GLuint LabelsTest::createRenderbuffer(const Functions* gl, const glu::RenderContext* rc)
998{
999	GLuint id = 0;
1000
1001	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1002	{
1003		gl->createRenderbuffers(1, &id);
1004		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateRenderbuffers");
1005	}
1006	else
1007	{
1008		gl->genRenderbuffers(1, &id);
1009		gl->bindRenderbuffer(GL_RENDERBUFFER, id);
1010		gl->bindRenderbuffer(GL_RENDERBUFFER, 0);
1011		GLU_EXPECT_NO_ERROR(gl->getError(), "GenRenderbuffers / BindRenderbuffer");
1012	}
1013
1014	return id;
1015}
1016
1017/** Create sampler
1018 *
1019 * @param gl GL functions
1020 *
1021 * @return ID of created resource
1022 **/
1023GLuint LabelsTest::createSampler(const Functions* gl, const glu::RenderContext* rc)
1024{
1025	GLuint id = 0;
1026	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1027	{
1028		gl->createSamplers(1, &id);
1029		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateSamplers");
1030	}
1031	else
1032	{
1033		gl->genSamplers(1, &id);
1034		gl->bindSampler(0, id);
1035		gl->bindSampler(0, 0);
1036		GLU_EXPECT_NO_ERROR(gl->getError(), "GenSamplers / BindSampler");
1037	}
1038
1039	return id;
1040}
1041
1042/** Create shader
1043 *
1044 * @param gl GL functions
1045 *
1046 * @return ID of created resource
1047 **/
1048GLuint LabelsTest::createShader(const Functions* gl, const glu::RenderContext*)
1049{
1050	GLuint id = gl->createShader(GL_VERTEX_SHADER);
1051	GLU_EXPECT_NO_ERROR(gl->getError(), "CreateShader");
1052
1053	return id;
1054}
1055
1056/** Create texture
1057 *
1058 * @param gl GL functions
1059 *
1060 * @return ID of created resource
1061 **/
1062GLuint LabelsTest::createTexture(const Functions* gl, const glu::RenderContext* rc)
1063{
1064	GLuint id = 0;
1065	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1066	{
1067		gl->createTextures(GL_TEXTURE_2D, 1, &id);
1068		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateTextures");
1069	}
1070	else
1071	{
1072		gl->genTextures(1, &id);
1073		gl->bindTexture(GL_TEXTURE_2D, id);
1074		gl->bindTexture(GL_TEXTURE_2D, 0);
1075		GLU_EXPECT_NO_ERROR(gl->getError(), "GenTextures / BindTexture");
1076	}
1077
1078	return id;
1079}
1080
1081/** Create XFB
1082 *
1083 * @param gl GL functions
1084 *
1085 * @return ID of created resource
1086 **/
1087GLuint LabelsTest::createTransformFeedback(const Functions* gl, const glu::RenderContext* rc)
1088{
1089	GLuint id = 0;
1090	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1091	{
1092		gl->createTransformFeedbacks(1, &id);
1093		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateTransformFeedbacks");
1094	}
1095	else
1096	{
1097		gl->genTransformFeedbacks(1, &id);
1098		gl->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, id);
1099		gl->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1100		GLU_EXPECT_NO_ERROR(gl->getError(), "GenTransformFeedbacks / BindTransformFeedback");
1101	}
1102
1103	return id;
1104}
1105
1106/** Create VAO
1107 *
1108 * @param gl GL functions
1109 *
1110 * @return ID of created resource
1111 **/
1112GLuint LabelsTest::createVertexArray(const Functions* gl, const glu::RenderContext* rc)
1113{
1114	GLuint id = 0;
1115
1116	if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5)))
1117	{
1118		gl->createVertexArrays(1, &id);
1119		GLU_EXPECT_NO_ERROR(gl->getError(), "CreateVertexArrays");
1120	}
1121	else
1122	{
1123		gl->genVertexArrays(1, &id);
1124		gl->bindVertexArray(id);
1125		gl->bindVertexArray(0);
1126		GLU_EXPECT_NO_ERROR(gl->getError(), "GenVertexArrays / BindVertexArrays");
1127	}
1128
1129	return id;
1130}
1131
1132/** Destroy buffer
1133 *
1134 * @param gl GL functions
1135 * @param id ID of resource
1136 **/
1137GLvoid LabelsTest::deleteBuffer(const Functions* gl, GLuint id)
1138{
1139	gl->deleteBuffers(1, &id);
1140	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteBuffers");
1141}
1142
1143/** Destroy FBO
1144 *
1145 * @param gl GL functions
1146 * @param id ID of resource
1147 **/
1148GLvoid LabelsTest::deleteFramebuffer(const Functions* gl, GLuint id)
1149{
1150	gl->deleteFramebuffers(1, &id);
1151	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteFramebuffers");
1152}
1153
1154/** Destroy program
1155 *
1156 * @param gl GL functions
1157 * @param id ID of resource
1158 **/
1159GLvoid LabelsTest::deleteProgram(const Functions* gl, GLuint id)
1160{
1161	gl->deleteProgram(id);
1162	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteProgram");
1163}
1164
1165/** Destroy pipeline
1166 *
1167 * @param gl GL functions
1168 * @param id ID of resource
1169 **/
1170GLvoid LabelsTest::deleteProgramPipeline(const Functions* gl, GLuint id)
1171{
1172	gl->deleteProgramPipelines(1, &id);
1173	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteProgramPipelines");
1174}
1175
1176/** Destroy query
1177 *
1178 * @param gl GL functions
1179 * @param id ID of resource
1180 **/
1181GLvoid LabelsTest::deleteQuery(const Functions* gl, GLuint id)
1182{
1183	gl->deleteQueries(1, &id);
1184	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteQueries");
1185}
1186
1187/** Destroy render buffer
1188 *
1189 * @param gl GL functions
1190 * @param id ID of resource
1191 **/
1192GLvoid LabelsTest::deleteRenderbuffer(const Functions* gl, GLuint id)
1193{
1194	gl->deleteRenderbuffers(1, &id);
1195	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteRenderbuffers");
1196}
1197
1198/** Destroy sampler
1199 *
1200 * @param gl GL functions
1201 * @param id ID of resource
1202 **/
1203GLvoid LabelsTest::deleteSampler(const Functions* gl, GLuint id)
1204{
1205	gl->deleteSamplers(1, &id);
1206	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteSamplers");
1207}
1208
1209/** Destroy shader
1210 *
1211 * @param gl GL functions
1212 * @param id ID of resource
1213 **/
1214GLvoid LabelsTest::deleteShader(const Functions* gl, GLuint id)
1215{
1216	gl->deleteShader(id);
1217	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteShader");
1218}
1219
1220/** Destroy texture
1221 *
1222 * @param gl GL functions
1223 * @param id ID of resource
1224 **/
1225GLvoid LabelsTest::deleteTexture(const Functions* gl, GLuint id)
1226{
1227	gl->deleteTextures(1, &id);
1228	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteTextures");
1229}
1230
1231/** Destroy XFB
1232 *
1233 * @param gl GL functions
1234 * @param id ID of resource
1235 **/
1236GLvoid LabelsTest::deleteTransformFeedback(const Functions* gl, GLuint id)
1237{
1238	gl->deleteTransformFeedbacks(1, &id);
1239	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteTransformFeedbacks");
1240}
1241
1242/** Destroy VAO
1243 *
1244 * @param gl GL functions
1245 * @param id ID of resource
1246 **/
1247GLvoid LabelsTest::deleteVertexArray(const Functions* gl, GLuint id)
1248{
1249	gl->deleteVertexArrays(1, &id);
1250	GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteVertexArrays");
1251}
1252
1253/** Constructor
1254 *
1255 * @param testCtx  Test context
1256 * @param is_debug Selects if debug or non-debug context should be used
1257 * @param name     Name of test
1258 **/
1259ReceivingMessagesTest::ReceivingMessagesTest(tcu::TestContext& testCtx, glu::ApiType apiType)
1260	: TestCase(testCtx, "receiving_messages", "Verifies that messages can be received")
1261	, TestBase(testCtx, apiType, true /* is_debug */)
1262{
1263	/* Nothing to be done */
1264}
1265
1266/** Execute test
1267 *
1268 * @return tcu::TestNode::STOP
1269 **/
1270tcu::TestNode::IterateResult ReceivingMessagesTest::iterate()
1271{
1272	static const size_t bufSize		  = 32;
1273	static const GLchar label[]		  = "foo";
1274	static const size_t label_length  = sizeof(label) / sizeof(label[0]) - 1;
1275	static const size_t read_messages = 4;
1276
1277	GLuint callback_counter   = 0;
1278	GLint  max_debug_messages = 0;
1279
1280	/* Initialize render context */
1281	TestBase::init();
1282
1283	/* Get max number of debug messages */
1284	m_gl->getIntegerv(GL_MAX_DEBUG_LOGGED_MESSAGES, &max_debug_messages);
1285	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1286
1287	/*
1288	 * - verify that the state of DEBUG_OUTPUT is enabled as it should be by
1289	 * default;
1290	 * - verify that state of DEBUG_CALLBACK_FUNCTION and
1291	 * DEBUG_CALLBACK_USER_PARAM are NULL;
1292	 */
1293	{
1294		inspectDebugState(GL_TRUE, 0 /* cb */, 0 /* info */);
1295	}
1296
1297	/*
1298	 * Ignore spurious performance messages
1299	 */
1300	m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_PERFORMANCE /* type */,
1301							  GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
1302
1303	/*
1304	 * - insert a message with DebugMessageInsert;
1305	 * - inspect message log to check if the message is reported;
1306	 * - inspect message log again, there should be no messages;
1307	 */
1308	{
1309		GLchar  messageLog[bufSize];
1310		GLenum  sources[read_messages];
1311		GLenum  types[read_messages];
1312		GLuint  ids[read_messages];
1313		GLenum  severities[read_messages];
1314		GLsizei lengths[read_messages];
1315
1316		cleanMessageLog(m_gl);
1317
1318		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1319								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1320		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1321
1322		GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, sources /* sources */,
1323											  types /* types */, ids /* ids */, severities /* severities */,
1324											  lengths /* lengths */, messageLog /* messageLog */);
1325		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1326
1327		if (1 != ret)
1328		{
1329			m_testCtx.getLog() << tcu::TestLog::Message
1330												<< "GetDebugMessageLog returned invalid number of messages: " << ret
1331												<< ", expected 1" << tcu::TestLog::EndMessage;
1332
1333			TCU_FAIL("Invalid value returned by GetDebugMessageLog");
1334		}
1335
1336		if (GL_DEBUG_SOURCE_APPLICATION != sources[0])
1337		{
1338			TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1339		}
1340
1341		if (GL_DEBUG_TYPE_ERROR != types[0])
1342		{
1343			TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1344		}
1345
1346		if (11 != ids[0])
1347		{
1348			TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1349		}
1350
1351		if (GL_DEBUG_SEVERITY_HIGH != severities[0])
1352		{
1353			TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1354		}
1355
1356		// DebugMessageInsert's length does not include null-terminated character (if length is positive)
1357		// But GetDebugMessageLog's length include null-terminated character
1358		// OpenGL 4.5 Core Spec, Page 530 and Page 535
1359		if (label_length + 1 != lengths[0])
1360		{
1361			TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1362		}
1363
1364		if (0 != strcmp(label, messageLog))
1365		{
1366			TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1367		}
1368	}
1369
1370	/*
1371	 * - disable DEBUG_OUTPUT;
1372	 * - insert a message with DebugMessageInsert;
1373	 * - inspect message log again, there should be no messages;
1374	 */
1375	{
1376		m_gl->disable(GL_DEBUG_OUTPUT);
1377		GLU_EXPECT_NO_ERROR(m_gl->getError(), "Disable");
1378
1379		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1380								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1381		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1382
1383		inspectMessageLog(0);
1384	}
1385
1386	/*
1387	 * - enable DEBUG_OUTPUT;
1388	 * - register debug message callback with DebugMessageCallback;
1389	 * - verify that the state of DEBUG_CALLBACK_FUNCTION and
1390	 * DEBUG_CALLBACK_USER_PARAM are correct;
1391	 * - insert a message with DebugMessageInsert;
1392	 * - it is expected that debug message callback will be executed for
1393	 * the message;
1394	 * - inspect message log to check there are no messages;
1395	 */
1396	{
1397		m_gl->enable(GL_DEBUG_OUTPUT);
1398		GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable");
1399
1400		m_gl->debugMessageCallback(debug_proc, &callback_counter);
1401		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageCallback");
1402
1403		inspectDebugState(GL_TRUE, debug_proc, &callback_counter);
1404
1405		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1406								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1407		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1408
1409		inspectCallbackCounter(callback_counter, 1);
1410
1411		inspectMessageLog(0);
1412	}
1413
1414	/*
1415	 * - disable DEBUG_OUTPUT;
1416	 * - insert a message with DebugMessageInsert;
1417	 * - debug message callback should not be called;
1418	 * - inspect message log to check there are no messages;
1419	 */
1420	{
1421		m_gl->disable(GL_DEBUG_OUTPUT);
1422		GLU_EXPECT_NO_ERROR(m_gl->getError(), "Disable");
1423
1424		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1425								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1426		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1427
1428		inspectCallbackCounter(callback_counter, 1);
1429
1430		inspectMessageLog(0);
1431	}
1432
1433	/*
1434	 * - enable DEBUG_OUTPUT;
1435	 * - execute DebugMessageControl with <type> DEBUG_TYPE_ERROR, <severity>
1436	 * DEBUG_SEVERITY_HIGH and <enabled> FALSE;
1437	 * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_ERROR
1438	 * and <severity> DEBUG_SEVERITY_MEDIUM;
1439	 * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1440	 * and <severity> DEBUG_SEVERITY_HIGH;
1441	 * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1442	 * and <severity> DEBUG_SEVERITY_LOW;
1443	 * - debug message callback should not be called;
1444	 * - inspect message log to check there are no messages;
1445	 */
1446	{
1447		m_gl->enable(GL_DEBUG_OUTPUT);
1448		GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable");
1449
1450		m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1451								  GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
1452
1453		m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DONT_CARE /* type */,
1454								  GL_DEBUG_SEVERITY_HIGH /* severity */, 0 /* counts */, 0 /* ids */,
1455								  GL_FALSE /* enabled */);
1456		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
1457
1458		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1459								 GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */, label);
1460		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1461
1462		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1463								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1464		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1465
1466		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1467								 GL_DEBUG_SEVERITY_LOW /* severity */, label_length /* length */, label);
1468		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1469
1470		inspectCallbackCounter(callback_counter, 1);
1471
1472		inspectMessageLog(0);
1473	}
1474
1475	/*
1476	 * - set NULL as debug message callback;
1477	 * - verify that state of DEBUG_CALLBACK_FUNCTION and
1478	 * DEBUG_CALLBACK_USER_PARAM are NULL;
1479	 * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_ERROR
1480	 * and <severity> DEBUG_SEVERITY_MEDIUM;
1481	 * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1482	 * and <severity> DEBUG_SEVERITY_HIGH;
1483	 * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER
1484	 * and <severity> DEBUG_SEVERITY_LOW;
1485	 * - inspect message log to check there are no messages;
1486	 */
1487	{
1488		m_gl->debugMessageCallback(0, 0);
1489
1490		inspectDebugState(GL_TRUE, 0, 0);
1491
1492		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1493								 GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */, label);
1494		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1495
1496		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1497								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1498		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1499
1500		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1501								 GL_DEBUG_SEVERITY_LOW /* severity */, label_length /* length */, label);
1502		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1503
1504		inspectMessageLog(0);
1505	}
1506
1507	/*
1508	 * - execute DebugMessageControl to enable messages of <type> DEBUG_TYPE_ERROR
1509	 * and <severity> DEBUG_SEVERITY_HIGH.
1510	 */
1511	{
1512		m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1513								  GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_TRUE /* enabled */);
1514
1515		m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DONT_CARE /* type */,
1516								  GL_DEBUG_SEVERITY_HIGH /* severity */, 0 /* counts */, 0 /* ids */,
1517								  GL_TRUE /* enabled */);
1518		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
1519	}
1520
1521	/*
1522	 * - insert MAX_DEBUG_LOGGED_MESSAGES + 1 unique messages with
1523	 * DebugMessageInsert;
1524	 * - check state of DEBUG_LOGGED_MESSAGES; It is expected that
1525	 * MAX_DEBUG_LOGGED_MESSAGES will be reported;
1526	 */
1527	{
1528		for (GLint i = 0; i < max_debug_messages + 1; ++i)
1529		{
1530			m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1531									 i /* id */, GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */,
1532									 label);
1533			GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1534		}
1535
1536		GLint n_debug_messages = 0;
1537
1538		m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1539		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1540
1541		if (n_debug_messages != max_debug_messages)
1542		{
1543			m_testCtx.getLog()
1544				<< tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected "
1545				<< max_debug_messages << tcu::TestLog::EndMessage;
1546
1547			TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1548		}
1549	}
1550
1551	/*
1552	 * If MAX_DEBUG_LOGGED_MESSAGES is greater than 1:
1553	 * - inspect first half of the message log by specifying proper <count>; Verify
1554	 * that messages are reported in order from the oldest to the newest; Check
1555	 * that <count> messages were stored into provided buffers;
1556	 * - check state of DEBUG_LOGGED_MESSAGES; It is expected that <count> messages
1557	 * were removed from log;
1558	 * - inspect rest of the message log with <bufSize> too small to held last
1559	 * message; Verify that messages are reported in order from the oldest to the
1560	 * newest; Verify that maximum <bufSize> characters were written to
1561	 * <messageLog>;
1562	 * - check state of DEBUG_LOGGED_MESSAGES; It is expected that one message is
1563	 * available;
1564	 * - fetch the message and verify it is the newest one;
1565	 */
1566	if (1 != max_debug_messages)
1567	{
1568		GLint half_count	   = max_debug_messages / 2;
1569		GLint n_debug_messages = 0;
1570		GLint rest_count	   = max_debug_messages - half_count;
1571
1572		GLsizei buf_size = (GLsizei)((half_count + 1) * (label_length + 1));
1573
1574		std::vector<GLchar>  messageLog;
1575		std::vector<GLenum>  sources;
1576		std::vector<GLenum>  types;
1577		std::vector<GLuint>  ids;
1578		std::vector<GLenum>  severities;
1579		std::vector<GLsizei> lengths;
1580
1581		messageLog.resize(buf_size);
1582		sources.resize(half_count + 1);
1583		types.resize(half_count + 1);
1584		ids.resize(half_count + 1);
1585		severities.resize(half_count + 1);
1586		lengths.resize(half_count + 1);
1587
1588		GLuint ret = m_gl->getDebugMessageLog(half_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */,
1589											  &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */,
1590											  &lengths[0] /* lengths */, &messageLog[0] /* messageLog */);
1591		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1592
1593		if (ret != (GLuint)half_count)
1594		{
1595			m_testCtx.getLog() << tcu::TestLog::Message
1596												<< "GetDebugMessageLog returned unexpected number of messages: " << ret
1597												<< ", expected " << half_count << tcu::TestLog::EndMessage;
1598
1599			TCU_FAIL("Invalid number of meessages");
1600		}
1601
1602		m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1603		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1604
1605		if (n_debug_messages != rest_count)
1606		{
1607			m_testCtx.getLog()
1608				<< tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected "
1609				<< rest_count << tcu::TestLog::EndMessage;
1610
1611			TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1612		}
1613
1614		for (GLint i = 0; i < half_count; ++i)
1615		{
1616			if (GL_DEBUG_SOURCE_APPLICATION != sources[i])
1617			{
1618				TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1619			}
1620
1621			if (GL_DEBUG_TYPE_ERROR != types[i])
1622			{
1623				TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1624			}
1625
1626			if ((GLuint)i != ids[i])
1627			{
1628				TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1629			}
1630
1631			if (GL_DEBUG_SEVERITY_MEDIUM != severities[i])
1632			{
1633				TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1634			}
1635
1636			// DebugMessageInsert's length does not include null-terminated character (if length is positive)
1637			// But GetDebugMessageLog's length include null-terminated character
1638			// OpenGL 4.5 Core Spec, Page 530 and Page 535
1639			if (label_length + 1 != lengths[i])
1640			{
1641				TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1642			}
1643
1644			if (0 != strcmp(label, &messageLog[i * (label_length + 1)]))
1645			{
1646				TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1647			}
1648		}
1649
1650		/* */
1651		buf_size = (GLsizei)((rest_count - 1) * (label_length + 1) + label_length);
1652		memset(&messageLog[0], 0, messageLog.size());
1653
1654		ret = m_gl->getDebugMessageLog(rest_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */,
1655									   &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */,
1656									   &lengths[0] /* lengths */, &messageLog[0] /* messageLog */);
1657		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1658
1659		if (ret != (GLuint)(rest_count - 1))
1660		{
1661			m_testCtx.getLog() << tcu::TestLog::Message
1662												<< "GetDebugMessageLog returned unexpected number of messages: " << ret
1663												<< ", expected " << (rest_count - 1) << tcu::TestLog::EndMessage;
1664
1665			TCU_FAIL("Invalid number of meessages");
1666		}
1667
1668		m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1669		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1670
1671		if (n_debug_messages != 1)
1672		{
1673			m_testCtx.getLog()
1674				<< tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected "
1675				<< (rest_count - 1) << tcu::TestLog::EndMessage;
1676
1677			TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1678		}
1679
1680		for (GLint i = 0; i < (rest_count - 1); ++i)
1681		{
1682			if (GL_DEBUG_SOURCE_APPLICATION != sources[i])
1683			{
1684				TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1685			}
1686
1687			if (GL_DEBUG_TYPE_ERROR != types[i])
1688			{
1689				TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1690			}
1691
1692			if ((GLuint)(i + half_count) != ids[i])
1693			{
1694				TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1695			}
1696
1697			if (GL_DEBUG_SEVERITY_MEDIUM != severities[i])
1698			{
1699				TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1700			}
1701
1702			// DebugMessageInsert's length does not include null-terminated character (if length is positive)
1703			// But GetDebugMessageLog's length include null-terminated character
1704			// OpenGL 4.5 Core Spec, Page 530 and Page 535
1705			if (label_length + 1 != lengths[i])
1706			{
1707				TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1708			}
1709
1710			if (0 != strcmp(label, &messageLog[i * (label_length + 1)]))
1711			{
1712				TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1713			}
1714		}
1715
1716		/* */
1717		memset(&messageLog[0], 0, messageLog.size());
1718
1719		ret = m_gl->getDebugMessageLog(rest_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */,
1720									   &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */,
1721									   &lengths[0] /* lengths */, &messageLog[0] /* messageLog */);
1722		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1723
1724		if (ret != 1)
1725		{
1726			m_testCtx.getLog() << tcu::TestLog::Message
1727												<< "GetDebugMessageLog returned unexpected number of messages: " << ret
1728												<< ", expected 1" << tcu::TestLog::EndMessage;
1729
1730			TCU_FAIL("Invalid number of meessages");
1731		}
1732
1733		m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages);
1734		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
1735
1736		if (n_debug_messages != 0)
1737		{
1738			m_testCtx.getLog()
1739				<< tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected 1"
1740				<< tcu::TestLog::EndMessage;
1741
1742			TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES");
1743		}
1744
1745		if (GL_DEBUG_SOURCE_APPLICATION != sources[0])
1746		{
1747			TCU_FAIL("Invalid source value returned by GetDebugMessageLog");
1748		}
1749
1750		if (GL_DEBUG_TYPE_ERROR != types[0])
1751		{
1752			TCU_FAIL("Invalid type value returned by GetDebugMessageLog");
1753		}
1754
1755		if ((GLuint)(max_debug_messages - 1) != ids[0])
1756		{
1757			TCU_FAIL("Invalid id value returned by GetDebugMessageLog");
1758		}
1759
1760		if (GL_DEBUG_SEVERITY_MEDIUM != severities[0])
1761		{
1762			TCU_FAIL("Invalid severity value returned by GetDebugMessageLog");
1763		}
1764
1765		// DebugMessageInsert's length does not include null-terminated character (if length is positive)
1766		// But GetDebugMessageLog's length include null-terminated character
1767		// OpenGL 4.5 Core Spec, Page 530 and Page 535
1768		if (label_length + 1 != lengths[0])
1769		{
1770			TCU_FAIL("Invalid length value returned by GetDebugMessageLog");
1771		}
1772
1773		if (0 != strcmp(label, &messageLog[0]))
1774		{
1775			TCU_FAIL("Invalid message returned by GetDebugMessageLog");
1776		}
1777	}
1778
1779	/* Set result */
1780	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1781
1782	/* Done */
1783	TestBase::done();
1784
1785	return tcu::TestNode::STOP;
1786}
1787
1788/** Debug callback used by the test, increase counter by one
1789 *
1790 * @param ignored
1791 * @param ignored
1792 * @param ignored
1793 * @param ignored
1794 * @param ignored
1795 * @param ignored
1796 * @param info    Pointer to uint counter
1797 **/
1798void ReceivingMessagesTest::debug_proc(glw::GLenum /* source */, glw::GLenum /* type */, glw::GLuint /* id */,
1799										glw::GLenum /* severity */, glw::GLsizei /* length */,
1800										const glw::GLchar* /* message */, const void* info)
1801{
1802	GLuint* counter = (GLuint*)info;
1803
1804	*counter += 1;
1805}
1806
1807/** Inspects state of DEBUG_OUTPUT and debug callback
1808 *
1809 * @param expected_state     Expected state of DEBUG_OUTPUT
1810 * @param expected_callback  Expected state of DEBUG_CALLBACK_FUNCTION
1811 * @param expected_user_info Expected state of DEBUG_CALLBACK_USER_PARAM
1812 **/
1813void ReceivingMessagesTest::inspectDebugState(GLboolean expected_state, GLDEBUGPROC expected_callback,
1814											   GLvoid* expected_user_info) const
1815{
1816	GLboolean debug_state = -1;
1817	m_gl->getBooleanv(GL_DEBUG_OUTPUT, &debug_state);
1818	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetBooleanv");
1819
1820	if (expected_state != debug_state)
1821	{
1822		m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_OUTPUT: " << debug_state
1823											<< ", expected " << expected_state << tcu::TestLog::EndMessage;
1824
1825		TCU_FAIL("Invalid state of DEBUG_OUTPUT");
1826	}
1827
1828	GLvoid* callback_procedure = 0;
1829	m_gl->getPointerv(GL_DEBUG_CALLBACK_FUNCTION, &callback_procedure);
1830	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetPointerv");
1831
1832	if (expected_callback != callback_procedure)
1833	{
1834		TCU_FAIL("Invalid state of DEBUG_CALLBACK_FUNCTION");
1835	}
1836
1837	GLvoid* callback_user_info = 0;
1838	m_gl->getPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &callback_user_info);
1839	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetPointerv");
1840
1841	if (expected_user_info != callback_user_info)
1842	{
1843		TCU_FAIL("Invalid state of DEBUG_CALLBACK_USER_PARAM");
1844	}
1845}
1846
1847/** Inspects value of counter used by callback
1848 *
1849 * @param callback_counter            Reference to counter
1850 * @param expected_number_of_messages Expected value of counter
1851 **/
1852void ReceivingMessagesTest::inspectCallbackCounter(GLuint& callback_counter, GLuint expected_number_of_messages) const
1853{
1854	m_gl->finish();
1855	GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish");
1856
1857	if (expected_number_of_messages != callback_counter)
1858	{
1859		m_testCtx.getLog()
1860			<< tcu::TestLog::Message << "Debug callback was executed invalid number of times: " << callback_counter
1861			<< ", expected " << expected_number_of_messages << tcu::TestLog::EndMessage;
1862
1863		TCU_FAIL("Invalid execution of debug callback");
1864	}
1865}
1866
1867/** Inspects amount of messages stored in log
1868 *
1869 * @param expected_number_of_messages Expected number of messages
1870 **/
1871void ReceivingMessagesTest::inspectMessageLog(GLuint expected_number_of_messages) const
1872{
1873	static const size_t bufSize		  = 32;
1874	static const size_t read_messages = 4;
1875
1876	GLchar  messageLog[bufSize];
1877	GLenum  sources[read_messages];
1878	GLenum  types[read_messages];
1879	GLuint  ids[read_messages];
1880	GLenum  severities[read_messages];
1881	GLsizei lengths[read_messages];
1882
1883	GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, sources /* sources */,
1884										  types /* types */, ids /* ids */, severities /* severities */,
1885										  lengths /* lengths */, messageLog /* messageLog */);
1886	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
1887
1888	if (expected_number_of_messages != ret)
1889	{
1890		m_testCtx.getLog() << tcu::TestLog::Message
1891											<< "GetDebugMessageLog returned invalid number of messages: " << ret
1892											<< ", expected " << expected_number_of_messages << tcu::TestLog::EndMessage;
1893
1894		TCU_FAIL("Invalid value returned by GetDebugMessageLog");
1895	}
1896}
1897
1898/** Constructor
1899 *
1900 * @param testCtx  Test context
1901 * @param is_debug Selects if debug or non-debug context should be used
1902 * @param name     Name of test
1903 **/
1904GroupsTest::GroupsTest(tcu::TestContext& testCtx, glu::ApiType apiType)
1905	: TestCase(testCtx, "groups", "Verifies that groups can be used to control generated messages")
1906	, TestBase(testCtx, apiType, true /* is_debug */)
1907{
1908	/* Nothing to be done */
1909}
1910
1911/** Execute test
1912 *
1913 * @return tcu::TestNode::STOP
1914 **/
1915tcu::TestNode::IterateResult GroupsTest::iterate()
1916{
1917	static const GLchar label[]		 = "foo";
1918	static const size_t label_length = sizeof(label) / sizeof(label[0]) - 1;
1919
1920	/* Initialize render context */
1921	TestBase::init();
1922
1923	cleanMessageLog(m_gl);
1924
1925	/*
1926	 * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 1;
1927	 */
1928	inspectGroupStack(1);
1929
1930	/*
1931	 * - insert message with <type> DEBUG_TYPE_ERROR;
1932	 * - inspect message log to check if the message is reported;
1933	 * - insert message with <type> DEBUG_TYPE_OTHER;
1934	 * - inspect message log to check if the message is reported;
1935	 */
1936	{
1937		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1938								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1939		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1940
1941		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1942						  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1943
1944		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1945								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1946		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1947
1948		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1949						  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1950	}
1951
1952	/*
1953	 * - push debug group with unique <id> and <message>;
1954	 * - inspect message log to check if the message about push is reported;
1955	 * - disable messages with <type> DEBUG_TYPE_ERROR;
1956	 * - insert message with <type> DEBUG_TYPE_ERROR;
1957	 * - inspect message log to check there are no messages;
1958	 * - insert message with <type> DEBUG_TYPE_OTHER;
1959	 * - inspect message log to check if the message is reported;
1960	 */
1961	{
1962		m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 0xabcd0123 /* id */, -1 /* length */, label);
1963		GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup");
1964
1965		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_PUSH_GROUP /* type */,
1966						  0xabcd0123 /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
1967						  label);
1968
1969		m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */,
1970								  GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
1971		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
1972
1973		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
1974								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1975		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1976
1977		verifyEmptyLog();
1978
1979		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1980								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1981		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
1982
1983		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
1984						  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
1985	}
1986
1987	/*
1988	 * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 2;
1989	 */
1990	inspectGroupStack(2);
1991
1992	/*
1993	 * - push debug group with unique <id> and <message>;
1994	 * - inspect message log to check if the message about push is reported;
1995	 * - disable messages with <type> DEBUG_TYPE_OTHER;
1996	 * - insert message with <type> DEBUG_TYPE_ERROR;
1997	 * - inspect message log to check there are no messages;
1998	 * - insert message with <type> DEBUG_TYPE_OTHER;
1999	 * - inspect message log to check there are no messages;
2000	 */
2001	{
2002		m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 0x0123abcd /* id */, -1 /* length */, label);
2003		GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup");
2004
2005		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_PUSH_GROUP /* type */,
2006						  0x0123abcd /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
2007						  label);
2008
2009		m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_OTHER /* type */,
2010								  GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */);
2011		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl");
2012
2013		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2014								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2015		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2016
2017		verifyEmptyLog();
2018
2019		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2020								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2021		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2022
2023		verifyEmptyLog();
2024	}
2025
2026	/*
2027	 * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 3;
2028	 */
2029	inspectGroupStack(3);
2030
2031	/*
2032	 * - pop debug group;
2033	 * - inspect message log to check if the message about pop is reported and
2034	 * corresponds with the second push;
2035	 * - insert message with <type> DEBUG_TYPE_ERROR;
2036	 * - inspect message log to check there are no messages;
2037	 * - insert message with <type> DEBUG_TYPE_OTHER;
2038	 * - inspect message log to check if the message is reported;
2039	 */
2040	{
2041		m_gl->popDebugGroup();
2042		GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup");
2043
2044		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_POP_GROUP /* type */,
2045						  0x0123abcd /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
2046						  label);
2047
2048		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2049								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2050		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2051
2052		verifyEmptyLog();
2053
2054		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2055								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2056		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2057
2058		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2059						  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2060	}
2061
2062	/*
2063	 * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 2;
2064	 */
2065	inspectGroupStack(2);
2066
2067	/*
2068	 * - pop debug group;
2069	 * - inspect message log to check if the message about pop is reported and
2070	 * corresponds with the first push;
2071	 * - insert message with <type> DEBUG_TYPE_ERROR;
2072	 * - inspect message log to check if the message is reported;
2073	 * - insert message with <type> DEBUG_TYPE_OTHER;
2074	 * - inspect message log to check if the message is reported;
2075	 */
2076	{
2077		m_gl->popDebugGroup();
2078		GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup");
2079
2080		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_POP_GROUP /* type */,
2081						  0xabcd0123 /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */,
2082						  label);
2083
2084		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2085								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2086		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2087
2088		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2089						  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2090
2091		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2092								 GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2093		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2094
2095		inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */,
2096						  GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label);
2097	}
2098
2099	/*
2100	 * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 1;
2101	 */
2102	inspectGroupStack(1);
2103
2104	/* Set result */
2105	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2106
2107	/* Done */
2108	TestBase::done();
2109
2110	return tcu::TestNode::STOP;
2111}
2112
2113/** Inspects amount of groups on stack
2114 *
2115 * @param expected_depth Expected number of groups
2116 **/
2117void GroupsTest::inspectGroupStack(GLuint expected_depth) const
2118{
2119	GLint stack_depth = 0;
2120
2121	m_gl->getIntegerv(GL_DEBUG_GROUP_STACK_DEPTH, &stack_depth);
2122	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv");
2123
2124	if (expected_depth != (GLuint)stack_depth)
2125	{
2126		m_testCtx.getLog() << tcu::TestLog::Message
2127											<< "State of DEBUG_GROUP_STACK_DEPTH: " << stack_depth << ", expected "
2128											<< expected_depth << tcu::TestLog::EndMessage;
2129
2130		TCU_FAIL("Invalid state of DEBUG_GROUP_STACK_DEPTH");
2131	}
2132}
2133
2134/** Inspects first message stored in log
2135 *
2136 * @param expected_source   Expected source of messages
2137 * @param expected_type     Expected type of messages
2138 * @param expected_id       Expected id of messages
2139 * @param expected_severity Expected severity of messages
2140 * @param expected_length   Expected length of messages
2141 * @param expected_label    Expected label of messages
2142 **/
2143void GroupsTest::inspectMessageLog(glw::GLenum expected_source, glw::GLenum expected_type, glw::GLuint expected_id,
2144								   glw::GLenum expected_severity, glw::GLsizei expected_length,
2145								   const glw::GLchar* expected_label) const
2146{
2147	static const size_t bufSize		  = 32;
2148	static const size_t read_messages = 1;
2149
2150	GLchar  messageLog[bufSize];
2151	GLenum  source;
2152	GLenum  type;
2153	GLuint  id;
2154	GLenum  severity;
2155	GLsizei length;
2156
2157	GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, &source /* sources */,
2158										  &type /* types */, &id /* ids */, &severity /* severities */,
2159										  &length /* lengths */, messageLog /* messageLog */);
2160	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
2161
2162	if (0 == ret)
2163	{
2164		TCU_FAIL("GetDebugMessageLog returned 0 messages");
2165	}
2166
2167	if (expected_source != source)
2168	{
2169		m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid source: " << source
2170											<< ", expected " << expected_source << tcu::TestLog::EndMessage;
2171
2172		TCU_FAIL("Invalid source of message");
2173	}
2174
2175	if (expected_type != type)
2176	{
2177		m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid type: " << type
2178											<< ", expected " << expected_type << tcu::TestLog::EndMessage;
2179
2180		TCU_FAIL("Invalid type of message");
2181	}
2182
2183	if (expected_id != id)
2184	{
2185		m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid id: " << id
2186											<< ", expected " << expected_id << tcu::TestLog::EndMessage;
2187
2188		TCU_FAIL("Invalid id of message");
2189	}
2190
2191	if (expected_severity != severity)
2192	{
2193		m_testCtx.getLog() << tcu::TestLog::Message
2194											<< "Got message with invalid severity: " << severity << ", expected "
2195											<< expected_severity << tcu::TestLog::EndMessage;
2196
2197		TCU_FAIL("Invalid severity of message");
2198	}
2199
2200	// DebugMessageInsert's length does not include null-terminated character (if length is positive)
2201	// But GetDebugMessageLog's length include null-terminated character
2202	// OpenGL 4.5 Core Spec, Page 530 and Page 535
2203	if (expected_length + 1 != length)
2204	{
2205		m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid length: " << length
2206											<< ", expected " << expected_length << tcu::TestLog::EndMessage;
2207
2208		TCU_FAIL("Invalid length of message");
2209	}
2210
2211	if (0 != strcmp(expected_label, messageLog))
2212	{
2213		m_testCtx.getLog() << tcu::TestLog::Message
2214											<< "Got message with invalid message: " << messageLog << ", expected "
2215											<< expected_label << tcu::TestLog::EndMessage;
2216
2217		TCU_FAIL("Invalid message");
2218	}
2219}
2220
2221/** Verifies that message log is empty
2222 *
2223 **/
2224void GroupsTest::verifyEmptyLog() const
2225{
2226	static const size_t bufSize		  = 32;
2227	static const size_t read_messages = 1;
2228
2229	GLchar  messageLog[bufSize];
2230	GLenum  source;
2231	GLenum  type;
2232	GLuint  id;
2233	GLenum  severity;
2234	GLsizei length;
2235
2236	GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, &source /* sources */,
2237										  &type /* types */, &id /* ids */, &severity /* severities */,
2238										  &length /* lengths */, messageLog /* messageLog */);
2239	GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog");
2240
2241	if (0 != ret)
2242	{
2243		TCU_FAIL("GetDebugMessageLog returned unexpected messages");
2244	}
2245}
2246
2247/** Constructor
2248 *
2249 * @param testCtx  Test context
2250 * @param is_debug Selects if debug or non-debug context should be used
2251 * @param name     Name of test
2252 **/
2253SynchronousCallsTest::SynchronousCallsTest(tcu::TestContext& testCtx, glu::ApiType apiType)
2254	: TestCase(testCtx, "synchronous_calls", "Verifies that messages can be received")
2255	, TestBase(testCtx, apiType, true /* is_debug */)
2256{
2257	/* Create pthread_key_t visible to all threads
2258	 * The key has value NULL associated with it in all existing
2259	 * or about to be created threads
2260	 */
2261	m_uid = 0;
2262}
2263
2264/** Execute test
2265 *
2266 * @return tcu::TestNode::STOP
2267 **/
2268tcu::TestNode::IterateResult SynchronousCallsTest::iterate()
2269{
2270	m_uid++;
2271
2272	/* associate  some unique id with the current thread */
2273	m_tls.set((void*)(deUintptr)m_uid);
2274
2275	static const GLchar label[] = "foo";
2276
2277	GLuint buffer_id = 0;
2278
2279	/* Initialize render context */
2280	TestBase::init();
2281
2282	/* - set callback_executed to 0; */
2283	int callback_executed = 0;
2284
2285	/*
2286	 *- enable DEBUG_OUTPUT_SYNCHRONOUS;
2287	 */
2288	m_gl->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
2289	GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable");
2290
2291	/*
2292	 * - register debug message callback with DebugMessageCallback; Provide the
2293	 * instance of UserParam structure as <userParam>; Routine should do the
2294	 * following:
2295	 *   * set callback_executed to 1;
2296	 */
2297	m_gl->debugMessageCallback(debug_proc, &callback_executed);
2298	try
2299	{
2300		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageCallback");
2301
2302		/*
2303		 * - insert a message with DebugMessageInsert;
2304		 */
2305		m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */,
2306								 GL_DEBUG_SEVERITY_HIGH /* severity */, -1 /* length */, label);
2307		GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert");
2308
2309		/* Make sure execution finished before we check results */
2310		m_gl->finish();
2311		GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish");
2312
2313		/*
2314		 * - check if:
2315		 *   * callback_executed is set to 1;
2316		 */
2317		if (1 != callback_executed)
2318		{
2319			TCU_FAIL("callback_executed is not set to 1");
2320		}
2321
2322		/* Check that the message was recorded by the current thread */
2323		if ((deUintptr)(m_tls.get()) != m_uid)
2324		{
2325			TCU_FAIL("thread id stored by callback is not the same as \"test\" thread");
2326		}
2327
2328		/*
2329		 * - reset callback_executed;
2330		 */
2331		callback_executed = 0;
2332
2333		/*
2334		 * - execute BindBufferBase with GL_ARRAY_BUFFER <target>, GL_INVALID_ENUM
2335		 * error should be generated;
2336		 */
2337		m_gl->genBuffers(1, &buffer_id);
2338		GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenBuffers");
2339
2340		m_gl->bindBufferBase(GL_ARRAY_BUFFER, 0 /* index */, buffer_id);
2341		if (GL_INVALID_ENUM != m_gl->getError())
2342		{
2343			TCU_FAIL("Unexpected error generated");
2344		}
2345
2346		/* Make sure execution finished before we check results */
2347		m_gl->finish();
2348		GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish");
2349
2350		/*
2351		 * - test pass if:
2352		 *   * callback_executed is set to 0 - implementation does not send messages;
2353		 *   * callback_executed is set to 1 and thread_id is the same
2354		 *   as "test" thread - implementation sent message to proper thread;
2355		 */
2356		if (1 == callback_executed)
2357		{
2358			/* Check that the error was recorded by the current thread */
2359			if ((deUintptr)(m_tls.get()) != m_uid)
2360			{
2361				TCU_FAIL("thread id stored by callback is not the same as \"test\" thread");
2362			}
2363		}
2364
2365		/* Clean */
2366		m_gl->deleteBuffers(1, &buffer_id);
2367		buffer_id = 0;
2368	}
2369	catch (const std::exception& exc)
2370	{
2371		if (0 != buffer_id)
2372		{
2373			m_gl->deleteBuffers(1, &buffer_id);
2374			buffer_id = 0;
2375		}
2376
2377		TCU_FAIL(exc.what());
2378	}
2379
2380	/* Set result */
2381	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2382
2383	/* Done */
2384	TestBase::done();
2385
2386	return tcu::TestNode::STOP;
2387}
2388
2389/** Destructor */
2390SynchronousCallsTest::~SynchronousCallsTest(void)
2391{
2392}
2393
2394/** Debug callback used by the test, sets callback_executed to 1 and stores 0 to tls
2395 *
2396 * @param ignored
2397 * @param ignored
2398 * @param ignored
2399 * @param ignored
2400 * @param ignored
2401 * @param ignored
2402 * @param info    Pointer to uint counter
2403 **/
2404void SynchronousCallsTest::debug_proc(glw::GLenum /* source */, glw::GLenum /* type */, glw::GLuint /* id */,
2405									  glw::GLenum /* severity */, glw::GLsizei /* length */,
2406									  const glw::GLchar* /* message */, const void* info)
2407{
2408	int* callback_executed = (int*)info;
2409
2410	*callback_executed = 1;
2411}
2412} /* KHRDebug */
2413
2414/** Constructor.
2415 *
2416 *  @param context Rendering context.
2417 **/
2418KHRDebugTests::KHRDebugTests(tcu::TestContext& testCtx, glu::ApiType apiType)
2419	: TestCaseGroup(testCtx, "khr_debug", "Verifies \"khr debug\" functionality")
2420	, m_apiType(apiType)
2421
2422{
2423	/* Left blank on purpose */
2424}
2425
2426/** Initializes a khr_debug test group.
2427 *
2428 **/
2429void KHRDebugTests::init(void)
2430{
2431	addChild(new KHRDebug::APIErrorsTest(m_testCtx, m_apiType, false, "api_errors_non_debug"));
2432	addChild(new KHRDebug::LabelsTest(m_testCtx, m_apiType, false, "labels_non_debug"));
2433	addChild(new KHRDebug::ReceivingMessagesTest(m_testCtx, m_apiType));
2434	addChild(new KHRDebug::GroupsTest(m_testCtx, m_apiType));
2435	addChild(new KHRDebug::APIErrorsTest(m_testCtx, m_apiType, true, "api_errors_debug"));
2436	addChild(new KHRDebug::LabelsTest(m_testCtx, m_apiType, true, "labels_debug"));
2437	addChild(new KHRDebug::SynchronousCallsTest(m_testCtx, m_apiType));
2438}
2439
2440} /* glcts namespace */
2441