query_renderer_unittest.cpp revision af69d88d
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 27extern "C" { 28#include "glxclient.h" 29#include "glx_error.h" 30} 31 32extern bool GetGLXScreenConfigs_called; 33extern struct glx_screen *psc; 34 35struct attribute_test_vector { 36 const char *string; 37 int value; 38}; 39 40#define E(x) { # x, x } 41 42 43 44static bool got_sigsegv; 45static jmp_buf jmp; 46 47static void 48sigsegv_handler(int sig) 49{ 50 (void) sig; 51 got_sigsegv = true; 52 longjmp(jmp, 1); 53} 54 55static bool query_renderer_string_called = false; 56static bool query_renderer_integer_called = false; 57 58static int 59fake_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 71static int 72fake_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 84struct glx_screen_vtable fake_vtable = { 85 NULL, 86 NULL, 87 fake_query_renderer_integer, 88 fake_query_renderer_string 89}; 90 91class query_renderer_string_test : public ::testing::Test { 92public: 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 102class query_renderer_integer_test : public query_renderer_string_test { 103}; 104 105void 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 119void 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 */ 128TEST_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 */ 152TEST_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 */ 197TEST_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 */ 215TEST_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 */ 235TEST_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 */ 264TEST_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 */ 279TEST_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 */ 307TEST_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 */ 352TEST_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 */ 373TEST_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 */ 396TEST_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 */ 428TEST_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} 441