glx: change query_renderer_integer() value param to unsigned
[mesa.git] / src / glx / tests / query_renderer_unittest.cpp
1 /*
2 * Copyright © 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #include <gtest/gtest.h>
24 #include <signal.h>
25 #include <setjmp.h>
26
27 extern "C" {
28 #include "glxclient.h"
29 #include "glx_error.h"
30 }
31
32 extern bool GetGLXScreenConfigs_called;
33 extern struct glx_screen *psc;
34
35 struct attribute_test_vector {
36 const char *string;
37 int value;
38 };
39
40 #define E(x) { # x, x }
41
42
43
44 static bool got_sigsegv;
45 static jmp_buf jmp;
46
47 static void
48 sigsegv_handler(int sig)
49 {
50 (void) sig;
51 got_sigsegv = true;
52 longjmp(jmp, 1);
53 }
54
55 static bool query_renderer_string_called = false;
56 static bool query_renderer_integer_called = false;
57
58 static int
59 fake_query_renderer_integer(struct glx_screen *psc, int attribute,
60 unsigned int *value)
61 {
62 (void) psc;
63 (void) attribute;
64 (void) value;
65
66 query_renderer_integer_called = true;
67
68 return -1;
69 }
70
71 static int
72 fake_query_renderer_string(struct glx_screen *psc, int attribute,
73 const char **value)
74 {
75 (void) psc;
76 (void) attribute;
77 (void) value;
78
79 query_renderer_string_called = true;
80
81 return -1;
82 }
83
84 struct glx_screen_vtable fake_vtable = {
85 NULL,
86 NULL,
87 fake_query_renderer_integer,
88 fake_query_renderer_string
89 };
90
91 class query_renderer_string_test : public ::testing::Test {
92 public:
93 virtual void SetUp();
94 virtual void TearDown();
95
96 struct glx_screen scr;
97 struct sigaction sa;
98 struct sigaction old_sa;
99 Display dpy;
100 };
101
102 class query_renderer_integer_test : public query_renderer_string_test {
103 };
104
105 void query_renderer_string_test::SetUp()
106 {
107 memset(&scr, 0, sizeof(scr));
108 scr.vtable = &fake_vtable;
109 psc = &scr;
110
111 got_sigsegv = false;
112
113 sa.sa_handler = sigsegv_handler;
114 sigemptyset(&sa.sa_mask);
115 sa.sa_flags = 0;
116 sigaction(SIGSEGV, &sa, &old_sa);
117 }
118
119 void query_renderer_string_test::TearDown()
120 {
121 sigaction(SIGSEGV, &old_sa, NULL);
122 }
123
124 /**
125 * glXQueryRendererStringMESA will return \c NULL if the query_render_string
126 * vtable entry is \c NULL. It will also not segfault.
127 */
128 TEST_F(query_renderer_string_test, null_query_render_string)
129 {
130 struct glx_screen_vtable vtable = {
131 NULL,
132 NULL,
133 NULL,
134 NULL
135 };
136
137 scr.vtable = &vtable;
138
139 if (setjmp(jmp) == 0) {
140 const char *str =
141 glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
142 EXPECT_EQ((char *)0, str);
143 } else {
144 EXPECT_FALSE(got_sigsegv);
145 }
146 }
147
148 /**
149 * glXQueryRendererStringMESA will not call the screen query_render_string
150 * function with an invalid GLX enum value, and it will return NULL.
151 */
152 TEST_F(query_renderer_string_test, invalid_attribute)
153 {
154 static const attribute_test_vector invalid_attributes[] = {
155 /* These values are just plain invalid for use with this extension.
156 */
157 E(0),
158 E(GLX_VENDOR),
159 E(GLX_VERSION),
160 E(GLX_EXTENSIONS),
161 E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000),
162 E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000),
163
164 /* These enums are part of the extension, but they are not allowed for
165 * the string query.
166 */
167 E(GLX_RENDERER_VERSION_MESA),
168 E(GLX_RENDERER_ACCELERATED_MESA),
169 E(GLX_RENDERER_VIDEO_MEMORY_MESA),
170 E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA),
171 E(GLX_RENDERER_PREFERRED_PROFILE_MESA),
172 E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA),
173 E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA),
174 E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA),
175 E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA),
176 E(GLX_RENDERER_ID_MESA),
177 };
178
179 for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
180 query_renderer_integer_called = false;
181 query_renderer_string_called = false;
182
183 const char *str =
184 glXQueryRendererStringMESA(&dpy, 0, 0, invalid_attributes[i].value);
185 EXPECT_EQ((char *)0, str) << invalid_attributes[i].string;
186 EXPECT_FALSE(query_renderer_integer_called)
187 << invalid_attributes[i].string;
188 EXPECT_FALSE(query_renderer_string_called)
189 << invalid_attributes[i].string;
190 }
191 }
192
193 /**
194 * glXQueryRendererStringMESA will not call GetGLXScreenConfigs if the display
195 * pointer is \c NULL. It will also not segfault.
196 */
197 TEST_F(query_renderer_string_test, null_display_pointer)
198 {
199 if (setjmp(jmp) == 0) {
200 GetGLXScreenConfigs_called = false;
201
202 const char *str =
203 glXQueryRendererStringMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
204 EXPECT_EQ((char *)0, str);
205 EXPECT_FALSE(GetGLXScreenConfigs_called);
206 } else {
207 EXPECT_FALSE(got_sigsegv);
208 }
209 }
210
211 /**
212 * glXQueryRendererStringMESA will return error if GetGLXScreenConfigs returns
213 * NULL. It will also not segfault.
214 */
215 TEST_F(query_renderer_string_test, null_screen_pointer)
216 {
217 psc = NULL;
218
219 if (setjmp(jmp) == 0) {
220 GetGLXScreenConfigs_called = false;
221
222 const char *str =
223 glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
224 EXPECT_EQ((char *)0, str);
225 EXPECT_TRUE(GetGLXScreenConfigs_called);
226 } else {
227 EXPECT_FALSE(got_sigsegv);
228 }
229 }
230
231 /**
232 * glXQueryRendererStringMESA will not call the screen query_render_string
233 * function if the renderer is invalid, and it will return NULL.
234 */
235 TEST_F(query_renderer_string_test, invalid_renderer_index)
236 {
237 static const int invalid_renderer_indices[] = {
238 -1,
239 1,
240 999,
241 };
242
243 if (setjmp(jmp) == 0) {
244 for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
245 const char *str =
246 glXQueryRendererStringMESA(&dpy, 0,
247 invalid_renderer_indices[i],
248 GLX_RENDERER_VENDOR_ID_MESA);
249 EXPECT_EQ((char *)0, str) << invalid_renderer_indices[i];
250 EXPECT_FALSE(query_renderer_integer_called)
251 << invalid_renderer_indices[i];
252 EXPECT_FALSE(query_renderer_string_called)
253 << invalid_renderer_indices[i];
254 }
255 } else {
256 EXPECT_FALSE(got_sigsegv);
257 }
258 }
259
260 /**
261 * glXQueryCurrentRendererStringMESA will return error if there is no context
262 * current. It will also not segfault.
263 */
264 TEST_F(query_renderer_string_test, no_current_context)
265 {
266 if (setjmp(jmp) == 0) {
267 const char *str =
268 glXQueryCurrentRendererStringMESA(GLX_RENDERER_VENDOR_ID_MESA);
269 EXPECT_EQ((char *)0, str);
270 } else {
271 EXPECT_FALSE(got_sigsegv);
272 }
273 }
274
275 /**
276 * glXQueryCurrentRendererIntegerMESA will return \c NULL if the
277 * query_render_string vtable entry is \c NULL. It will also not segfault.
278 */
279 TEST_F(query_renderer_integer_test, null_query_render_string)
280 {
281 struct glx_screen_vtable vtable = {
282 NULL,
283 NULL,
284 NULL,
285 NULL
286 };
287
288 scr.vtable = &vtable;
289
290 if (setjmp(jmp) == 0) {
291 unsigned value = 0xDEADBEEF;
292 Bool success = glXQueryRendererIntegerMESA(&dpy, 0, 0,
293 GLX_RENDERER_VENDOR_ID_MESA,
294 &value);
295 EXPECT_FALSE(success);
296 EXPECT_EQ(0xDEADBEEF, value);
297 } else {
298 EXPECT_FALSE(got_sigsegv);
299 }
300 }
301
302 /**
303 * glXQueryCurrentRendererIntegerMESA will not call the screen
304 * query_render_string function with an invalid GLX enum value, and it will
305 * return NULL.
306 */
307 TEST_F(query_renderer_integer_test, invalid_attribute)
308 {
309 static const attribute_test_vector invalid_attributes[] = {
310 /* These values are just plain invalid for use with this extension.
311 */
312 E(0),
313 E(GLX_VENDOR),
314 E(GLX_VERSION),
315 E(GLX_EXTENSIONS),
316 E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000),
317 E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000),
318 E(GLX_RENDERER_VERSION_MESA + 0x10000),
319 E(GLX_RENDERER_ACCELERATED_MESA + 0x10000),
320 E(GLX_RENDERER_VIDEO_MEMORY_MESA + 0x10000),
321 E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA + 0x10000),
322 E(GLX_RENDERER_PREFERRED_PROFILE_MESA + 0x10000),
323 E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA + 0x10000),
324 E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA + 0x10000),
325 E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA + 0x10000),
326 E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA + 0x10000),
327 E(GLX_RENDERER_ID_MESA + 0x10000),
328 };
329
330 for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
331 query_renderer_integer_called = false;
332 query_renderer_string_called = false;
333
334 unsigned value = 0xDEADBEEF;
335 Bool success =
336 glXQueryRendererIntegerMESA(&dpy, 0, 0,
337 invalid_attributes[i].value,
338 &value);
339 EXPECT_FALSE(success) << invalid_attributes[i].string;
340 EXPECT_EQ(0xDEADBEEF, value) << invalid_attributes[i].string;
341 EXPECT_FALSE(query_renderer_integer_called)
342 << invalid_attributes[i].string;
343 EXPECT_FALSE(query_renderer_string_called)
344 << invalid_attributes[i].string;
345 }
346 }
347
348 /**
349 * glXQueryCurrentRendererIntegerMESA will not call GetGLXScreenConfigs if the
350 * display pointer is \c NULL. It will also not segfault.
351 */
352 TEST_F(query_renderer_integer_test, null_display_pointer)
353 {
354 if (setjmp(jmp) == 0) {
355 GetGLXScreenConfigs_called = false;
356
357 unsigned value = 0xDEADBEEF;
358 Bool success =
359 glXQueryRendererIntegerMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
360 &value);
361 EXPECT_FALSE(success);
362 EXPECT_EQ(0xDEADBEEF, value);
363 EXPECT_FALSE(GetGLXScreenConfigs_called);
364 } else {
365 EXPECT_FALSE(got_sigsegv);
366 }
367 }
368
369 /**
370 * glXQueryCurrentRendererIntegerMESA will return error if GetGLXScreenConfigs
371 * returns NULL. It will also not segfault.
372 */
373 TEST_F(query_renderer_integer_test, null_screen_pointer)
374 {
375 psc = NULL;
376
377 if (setjmp(jmp) == 0) {
378 GetGLXScreenConfigs_called = false;
379
380 unsigned value = 0xDEADBEEF;
381 Bool success =
382 glXQueryRendererIntegerMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
383 &value);
384 EXPECT_FALSE(success);
385 EXPECT_EQ(0xDEADBEEF, value);
386 EXPECT_TRUE(GetGLXScreenConfigs_called);
387 } else {
388 EXPECT_FALSE(got_sigsegv);
389 }
390 }
391
392 /**
393 * glXQueryRendererIntegerMESA will not call the screen query_render_integer
394 * function if the renderer is invalid, and it will return NULL.
395 */
396 TEST_F(query_renderer_integer_test, invalid_renderer_index)
397 {
398 static const int invalid_renderer_indices[] = {
399 -1,
400 1,
401 999,
402 };
403
404 if (setjmp(jmp) == 0) {
405 for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
406 unsigned value = 0xDEADBEEF;
407 Bool success =
408 glXQueryRendererIntegerMESA(&dpy, 0,
409 invalid_renderer_indices[i],
410 GLX_RENDERER_VENDOR_ID_MESA,
411 &value);
412 EXPECT_FALSE(success) << invalid_renderer_indices[i];
413 EXPECT_EQ(0xDEADBEEF, value) << invalid_renderer_indices[i];
414 EXPECT_FALSE(query_renderer_integer_called)
415 << invalid_renderer_indices[i];
416 EXPECT_FALSE(query_renderer_string_called)
417 << invalid_renderer_indices[i];
418 }
419 } else {
420 EXPECT_FALSE(got_sigsegv);
421 }
422 }
423
424 /**
425 * glXQueryCurrentRendererIntegerMESA will return error if there is no context
426 * current. It will also not segfault.
427 */
428 TEST_F(query_renderer_integer_test, no_current_context)
429 {
430 if (setjmp(jmp) == 0) {
431 unsigned value = 0xDEADBEEF;
432 Bool success =
433 glXQueryCurrentRendererIntegerMESA(GLX_RENDERER_VENDOR_ID_MESA,
434 &value);
435 EXPECT_FALSE(success);
436 EXPECT_EQ(0xDEADBEEF, value);
437 } else {
438 EXPECT_FALSE(got_sigsegv);
439 }
440 }