1848b8605Smrg/* 2848b8605Smrg * Copyright © 2013 Intel Corporation 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21848b8605Smrg * DEALINGS IN THE SOFTWARE. 22848b8605Smrg */ 23848b8605Smrg#include <gtest/gtest.h> 24848b8605Smrg#include <signal.h> 25848b8605Smrg#include <setjmp.h> 26848b8605Smrg 27848b8605Smrg#include "glxclient.h" 28848b8605Smrg#include "glx_error.h" 29848b8605Smrg 30848b8605Smrgextern bool GetGLXScreenConfigs_called; 31848b8605Smrgextern struct glx_screen *psc; 32848b8605Smrg 33848b8605Smrgstruct attribute_test_vector { 34848b8605Smrg const char *string; 35848b8605Smrg int value; 36848b8605Smrg}; 37848b8605Smrg 38848b8605Smrg#define E(x) { # x, x } 39848b8605Smrg 40848b8605Smrg 41848b8605Smrg 42848b8605Smrgstatic bool got_sigsegv; 43848b8605Smrgstatic jmp_buf jmp; 44848b8605Smrg 45848b8605Smrgstatic void 46848b8605Smrgsigsegv_handler(int sig) 47848b8605Smrg{ 48848b8605Smrg (void) sig; 49848b8605Smrg got_sigsegv = true; 50848b8605Smrg longjmp(jmp, 1); 51848b8605Smrg} 52848b8605Smrg 53848b8605Smrgstatic bool query_renderer_string_called = false; 54848b8605Smrgstatic bool query_renderer_integer_called = false; 55848b8605Smrg 56848b8605Smrgstatic int 57848b8605Smrgfake_query_renderer_integer(struct glx_screen *psc, int attribute, 58848b8605Smrg unsigned int *value) 59848b8605Smrg{ 60848b8605Smrg (void) psc; 61848b8605Smrg (void) attribute; 62848b8605Smrg (void) value; 63848b8605Smrg 64848b8605Smrg query_renderer_integer_called = true; 65848b8605Smrg 66848b8605Smrg return -1; 67848b8605Smrg} 68848b8605Smrg 69848b8605Smrgstatic int 70848b8605Smrgfake_query_renderer_string(struct glx_screen *psc, int attribute, 71848b8605Smrg const char **value) 72848b8605Smrg{ 73848b8605Smrg (void) psc; 74848b8605Smrg (void) attribute; 75848b8605Smrg (void) value; 76848b8605Smrg 77848b8605Smrg query_renderer_string_called = true; 78848b8605Smrg 79848b8605Smrg return -1; 80848b8605Smrg} 81848b8605Smrg 82848b8605Smrgstruct glx_screen_vtable fake_vtable = { 83848b8605Smrg NULL, 84848b8605Smrg NULL, 85848b8605Smrg fake_query_renderer_integer, 86848b8605Smrg fake_query_renderer_string 87848b8605Smrg}; 88848b8605Smrg 89848b8605Smrgclass query_renderer_string_test : public ::testing::Test { 90848b8605Smrgpublic: 91848b8605Smrg virtual void SetUp(); 92848b8605Smrg virtual void TearDown(); 93848b8605Smrg 94848b8605Smrg struct glx_screen scr; 95848b8605Smrg struct sigaction sa; 96848b8605Smrg struct sigaction old_sa; 97848b8605Smrg Display dpy; 98848b8605Smrg}; 99848b8605Smrg 100848b8605Smrgclass query_renderer_integer_test : public query_renderer_string_test { 101848b8605Smrg}; 102848b8605Smrg 103848b8605Smrgvoid query_renderer_string_test::SetUp() 104848b8605Smrg{ 105848b8605Smrg memset(&scr, 0, sizeof(scr)); 106848b8605Smrg scr.vtable = &fake_vtable; 107848b8605Smrg psc = &scr; 108848b8605Smrg 109848b8605Smrg got_sigsegv = false; 110848b8605Smrg 111848b8605Smrg sa.sa_handler = sigsegv_handler; 112848b8605Smrg sigemptyset(&sa.sa_mask); 113848b8605Smrg sa.sa_flags = 0; 114848b8605Smrg sigaction(SIGSEGV, &sa, &old_sa); 115848b8605Smrg} 116848b8605Smrg 117848b8605Smrgvoid query_renderer_string_test::TearDown() 118848b8605Smrg{ 119848b8605Smrg sigaction(SIGSEGV, &old_sa, NULL); 120848b8605Smrg} 121848b8605Smrg 122848b8605Smrg/** 123848b8605Smrg * glXQueryRendererStringMESA will return \c NULL if the query_render_string 124848b8605Smrg * vtable entry is \c NULL. It will also not segfault. 125848b8605Smrg */ 126848b8605SmrgTEST_F(query_renderer_string_test, null_query_render_string) 127848b8605Smrg{ 128848b8605Smrg struct glx_screen_vtable vtable = { 129848b8605Smrg NULL, 130848b8605Smrg NULL, 131848b8605Smrg NULL, 132848b8605Smrg NULL 133848b8605Smrg }; 134848b8605Smrg 135848b8605Smrg scr.vtable = &vtable; 136848b8605Smrg 137848b8605Smrg if (setjmp(jmp) == 0) { 138848b8605Smrg const char *str = 139848b8605Smrg glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA); 140848b8605Smrg EXPECT_EQ((char *)0, str); 141848b8605Smrg } else { 142848b8605Smrg EXPECT_FALSE(got_sigsegv); 143848b8605Smrg } 144848b8605Smrg} 145848b8605Smrg 146848b8605Smrg/** 147848b8605Smrg * glXQueryRendererStringMESA will not call the screen query_render_string 148848b8605Smrg * function with an invalid GLX enum value, and it will return NULL. 149848b8605Smrg */ 150848b8605SmrgTEST_F(query_renderer_string_test, invalid_attribute) 151848b8605Smrg{ 152848b8605Smrg static const attribute_test_vector invalid_attributes[] = { 153848b8605Smrg /* These values are just plain invalid for use with this extension. 154848b8605Smrg */ 155848b8605Smrg E(0), 156848b8605Smrg E(GLX_VENDOR), 157848b8605Smrg E(GLX_VERSION), 158848b8605Smrg E(GLX_EXTENSIONS), 159848b8605Smrg E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000), 160848b8605Smrg E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000), 161848b8605Smrg 162848b8605Smrg /* These enums are part of the extension, but they are not allowed for 163848b8605Smrg * the string query. 164848b8605Smrg */ 165848b8605Smrg E(GLX_RENDERER_VERSION_MESA), 166848b8605Smrg E(GLX_RENDERER_ACCELERATED_MESA), 167848b8605Smrg E(GLX_RENDERER_VIDEO_MEMORY_MESA), 168848b8605Smrg E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA), 169848b8605Smrg E(GLX_RENDERER_PREFERRED_PROFILE_MESA), 170848b8605Smrg E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA), 171848b8605Smrg E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA), 172848b8605Smrg E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA), 173848b8605Smrg E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA), 174848b8605Smrg E(GLX_RENDERER_ID_MESA), 175848b8605Smrg }; 176848b8605Smrg 177848b8605Smrg for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) { 178848b8605Smrg query_renderer_integer_called = false; 179848b8605Smrg query_renderer_string_called = false; 180848b8605Smrg 181848b8605Smrg const char *str = 182848b8605Smrg glXQueryRendererStringMESA(&dpy, 0, 0, invalid_attributes[i].value); 183848b8605Smrg EXPECT_EQ((char *)0, str) << invalid_attributes[i].string; 184848b8605Smrg EXPECT_FALSE(query_renderer_integer_called) 185848b8605Smrg << invalid_attributes[i].string; 186848b8605Smrg EXPECT_FALSE(query_renderer_string_called) 187848b8605Smrg << invalid_attributes[i].string; 188848b8605Smrg } 189848b8605Smrg} 190848b8605Smrg 191848b8605Smrg/** 192848b8605Smrg * glXQueryRendererStringMESA will not call GetGLXScreenConfigs if the display 193848b8605Smrg * pointer is \c NULL. It will also not segfault. 194848b8605Smrg */ 195848b8605SmrgTEST_F(query_renderer_string_test, null_display_pointer) 196848b8605Smrg{ 197848b8605Smrg if (setjmp(jmp) == 0) { 198848b8605Smrg GetGLXScreenConfigs_called = false; 199848b8605Smrg 200848b8605Smrg const char *str = 201848b8605Smrg glXQueryRendererStringMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA); 202848b8605Smrg EXPECT_EQ((char *)0, str); 203848b8605Smrg EXPECT_FALSE(GetGLXScreenConfigs_called); 204848b8605Smrg } else { 205848b8605Smrg EXPECT_FALSE(got_sigsegv); 206848b8605Smrg } 207848b8605Smrg} 208848b8605Smrg 209848b8605Smrg/** 210848b8605Smrg * glXQueryRendererStringMESA will return error if GetGLXScreenConfigs returns 211848b8605Smrg * NULL. It will also not segfault. 212848b8605Smrg */ 213848b8605SmrgTEST_F(query_renderer_string_test, null_screen_pointer) 214848b8605Smrg{ 215848b8605Smrg psc = NULL; 216848b8605Smrg 217848b8605Smrg if (setjmp(jmp) == 0) { 218848b8605Smrg GetGLXScreenConfigs_called = false; 219848b8605Smrg 220848b8605Smrg const char *str = 221848b8605Smrg glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA); 222848b8605Smrg EXPECT_EQ((char *)0, str); 223848b8605Smrg EXPECT_TRUE(GetGLXScreenConfigs_called); 224848b8605Smrg } else { 225848b8605Smrg EXPECT_FALSE(got_sigsegv); 226848b8605Smrg } 227848b8605Smrg} 228848b8605Smrg 229848b8605Smrg/** 230848b8605Smrg * glXQueryRendererStringMESA will not call the screen query_render_string 231848b8605Smrg * function if the renderer is invalid, and it will return NULL. 232848b8605Smrg */ 233848b8605SmrgTEST_F(query_renderer_string_test, invalid_renderer_index) 234848b8605Smrg{ 235848b8605Smrg static const int invalid_renderer_indices[] = { 236848b8605Smrg -1, 237848b8605Smrg 1, 238848b8605Smrg 999, 239848b8605Smrg }; 240848b8605Smrg 241848b8605Smrg if (setjmp(jmp) == 0) { 242848b8605Smrg for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) { 243848b8605Smrg const char *str = 244848b8605Smrg glXQueryRendererStringMESA(&dpy, 0, 245848b8605Smrg invalid_renderer_indices[i], 246848b8605Smrg GLX_RENDERER_VENDOR_ID_MESA); 247848b8605Smrg EXPECT_EQ((char *)0, str) << invalid_renderer_indices[i]; 248848b8605Smrg EXPECT_FALSE(query_renderer_integer_called) 249848b8605Smrg << invalid_renderer_indices[i]; 250848b8605Smrg EXPECT_FALSE(query_renderer_string_called) 251848b8605Smrg << invalid_renderer_indices[i]; 252848b8605Smrg } 253848b8605Smrg } else { 254848b8605Smrg EXPECT_FALSE(got_sigsegv); 255848b8605Smrg } 256848b8605Smrg} 257848b8605Smrg 258848b8605Smrg/** 259848b8605Smrg * glXQueryCurrentRendererStringMESA will return error if there is no context 260848b8605Smrg * current. It will also not segfault. 261848b8605Smrg */ 262848b8605SmrgTEST_F(query_renderer_string_test, no_current_context) 263848b8605Smrg{ 264848b8605Smrg if (setjmp(jmp) == 0) { 265848b8605Smrg const char *str = 266848b8605Smrg glXQueryCurrentRendererStringMESA(GLX_RENDERER_VENDOR_ID_MESA); 267848b8605Smrg EXPECT_EQ((char *)0, str); 268848b8605Smrg } else { 269848b8605Smrg EXPECT_FALSE(got_sigsegv); 270848b8605Smrg } 271848b8605Smrg} 272848b8605Smrg 273848b8605Smrg/** 274848b8605Smrg * glXQueryCurrentRendererIntegerMESA will return \c NULL if the 275848b8605Smrg * query_render_string vtable entry is \c NULL. It will also not segfault. 276848b8605Smrg */ 277848b8605SmrgTEST_F(query_renderer_integer_test, null_query_render_string) 278848b8605Smrg{ 279848b8605Smrg struct glx_screen_vtable vtable = { 280848b8605Smrg NULL, 281848b8605Smrg NULL, 282848b8605Smrg NULL, 283848b8605Smrg NULL 284848b8605Smrg }; 285848b8605Smrg 286848b8605Smrg scr.vtable = &vtable; 287848b8605Smrg 288848b8605Smrg if (setjmp(jmp) == 0) { 289848b8605Smrg unsigned value = 0xDEADBEEF; 290848b8605Smrg Bool success = glXQueryRendererIntegerMESA(&dpy, 0, 0, 291848b8605Smrg GLX_RENDERER_VENDOR_ID_MESA, 292848b8605Smrg &value); 293848b8605Smrg EXPECT_FALSE(success); 294848b8605Smrg EXPECT_EQ(0xDEADBEEF, value); 295848b8605Smrg } else { 296848b8605Smrg EXPECT_FALSE(got_sigsegv); 297848b8605Smrg } 298848b8605Smrg} 299848b8605Smrg 300848b8605Smrg/** 301848b8605Smrg * glXQueryCurrentRendererIntegerMESA will not call the screen 302848b8605Smrg * query_render_string function with an invalid GLX enum value, and it will 303848b8605Smrg * return NULL. 304848b8605Smrg */ 305848b8605SmrgTEST_F(query_renderer_integer_test, invalid_attribute) 306848b8605Smrg{ 307848b8605Smrg static const attribute_test_vector invalid_attributes[] = { 308848b8605Smrg /* These values are just plain invalid for use with this extension. 309848b8605Smrg */ 310848b8605Smrg E(0), 311848b8605Smrg E(GLX_VENDOR), 312848b8605Smrg E(GLX_VERSION), 313848b8605Smrg E(GLX_EXTENSIONS), 314848b8605Smrg E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000), 315848b8605Smrg E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000), 316848b8605Smrg E(GLX_RENDERER_VERSION_MESA + 0x10000), 317848b8605Smrg E(GLX_RENDERER_ACCELERATED_MESA + 0x10000), 318848b8605Smrg E(GLX_RENDERER_VIDEO_MEMORY_MESA + 0x10000), 319848b8605Smrg E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA + 0x10000), 320848b8605Smrg E(GLX_RENDERER_PREFERRED_PROFILE_MESA + 0x10000), 321848b8605Smrg E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA + 0x10000), 322848b8605Smrg E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA + 0x10000), 323848b8605Smrg E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA + 0x10000), 324848b8605Smrg E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA + 0x10000), 325848b8605Smrg E(GLX_RENDERER_ID_MESA + 0x10000), 326848b8605Smrg }; 327848b8605Smrg 328848b8605Smrg for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) { 329848b8605Smrg query_renderer_integer_called = false; 330848b8605Smrg query_renderer_string_called = false; 331848b8605Smrg 332848b8605Smrg unsigned value = 0xDEADBEEF; 333848b8605Smrg Bool success = 334848b8605Smrg glXQueryRendererIntegerMESA(&dpy, 0, 0, 335848b8605Smrg invalid_attributes[i].value, 336848b8605Smrg &value); 337848b8605Smrg EXPECT_FALSE(success) << invalid_attributes[i].string; 338848b8605Smrg EXPECT_EQ(0xDEADBEEF, value) << invalid_attributes[i].string; 339848b8605Smrg EXPECT_FALSE(query_renderer_integer_called) 340848b8605Smrg << invalid_attributes[i].string; 341848b8605Smrg EXPECT_FALSE(query_renderer_string_called) 342848b8605Smrg << invalid_attributes[i].string; 343848b8605Smrg } 344848b8605Smrg} 345848b8605Smrg 346848b8605Smrg/** 347848b8605Smrg * glXQueryCurrentRendererIntegerMESA will not call GetGLXScreenConfigs if the 348848b8605Smrg * display pointer is \c NULL. It will also not segfault. 349848b8605Smrg */ 350848b8605SmrgTEST_F(query_renderer_integer_test, null_display_pointer) 351848b8605Smrg{ 352848b8605Smrg if (setjmp(jmp) == 0) { 353848b8605Smrg GetGLXScreenConfigs_called = false; 354848b8605Smrg 355848b8605Smrg unsigned value = 0xDEADBEEF; 356848b8605Smrg Bool success = 357848b8605Smrg glXQueryRendererIntegerMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA, 358848b8605Smrg &value); 359848b8605Smrg EXPECT_FALSE(success); 360848b8605Smrg EXPECT_EQ(0xDEADBEEF, value); 361848b8605Smrg EXPECT_FALSE(GetGLXScreenConfigs_called); 362848b8605Smrg } else { 363848b8605Smrg EXPECT_FALSE(got_sigsegv); 364848b8605Smrg } 365848b8605Smrg} 366848b8605Smrg 367848b8605Smrg/** 368848b8605Smrg * glXQueryCurrentRendererIntegerMESA will return error if GetGLXScreenConfigs 369848b8605Smrg * returns NULL. It will also not segfault. 370848b8605Smrg */ 371848b8605SmrgTEST_F(query_renderer_integer_test, null_screen_pointer) 372848b8605Smrg{ 373848b8605Smrg psc = NULL; 374848b8605Smrg 375848b8605Smrg if (setjmp(jmp) == 0) { 376848b8605Smrg GetGLXScreenConfigs_called = false; 377848b8605Smrg 378848b8605Smrg unsigned value = 0xDEADBEEF; 379848b8605Smrg Bool success = 380848b8605Smrg glXQueryRendererIntegerMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA, 381848b8605Smrg &value); 382848b8605Smrg EXPECT_FALSE(success); 383848b8605Smrg EXPECT_EQ(0xDEADBEEF, value); 384848b8605Smrg EXPECT_TRUE(GetGLXScreenConfigs_called); 385848b8605Smrg } else { 386848b8605Smrg EXPECT_FALSE(got_sigsegv); 387848b8605Smrg } 388848b8605Smrg} 389848b8605Smrg 390848b8605Smrg/** 391848b8605Smrg * glXQueryRendererIntegerMESA will not call the screen query_render_integer 392848b8605Smrg * function if the renderer is invalid, and it will return NULL. 393848b8605Smrg */ 394848b8605SmrgTEST_F(query_renderer_integer_test, invalid_renderer_index) 395848b8605Smrg{ 396848b8605Smrg static const int invalid_renderer_indices[] = { 397848b8605Smrg -1, 398848b8605Smrg 1, 399848b8605Smrg 999, 400848b8605Smrg }; 401848b8605Smrg 402848b8605Smrg if (setjmp(jmp) == 0) { 403848b8605Smrg for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) { 404848b8605Smrg unsigned value = 0xDEADBEEF; 405848b8605Smrg Bool success = 406848b8605Smrg glXQueryRendererIntegerMESA(&dpy, 0, 407848b8605Smrg invalid_renderer_indices[i], 408848b8605Smrg GLX_RENDERER_VENDOR_ID_MESA, 409848b8605Smrg &value); 410848b8605Smrg EXPECT_FALSE(success) << invalid_renderer_indices[i]; 411848b8605Smrg EXPECT_EQ(0xDEADBEEF, value) << invalid_renderer_indices[i]; 412848b8605Smrg EXPECT_FALSE(query_renderer_integer_called) 413848b8605Smrg << invalid_renderer_indices[i]; 414848b8605Smrg EXPECT_FALSE(query_renderer_string_called) 415848b8605Smrg << invalid_renderer_indices[i]; 416848b8605Smrg } 417848b8605Smrg } else { 418848b8605Smrg EXPECT_FALSE(got_sigsegv); 419848b8605Smrg } 420848b8605Smrg} 421848b8605Smrg 422848b8605Smrg/** 423848b8605Smrg * glXQueryCurrentRendererIntegerMESA will return error if there is no context 424848b8605Smrg * current. It will also not segfault. 425848b8605Smrg */ 426848b8605SmrgTEST_F(query_renderer_integer_test, no_current_context) 427848b8605Smrg{ 428848b8605Smrg if (setjmp(jmp) == 0) { 429848b8605Smrg unsigned value = 0xDEADBEEF; 430848b8605Smrg Bool success = 431848b8605Smrg glXQueryCurrentRendererIntegerMESA(GLX_RENDERER_VENDOR_ID_MESA, 432848b8605Smrg &value); 433848b8605Smrg EXPECT_FALSE(success); 434848b8605Smrg EXPECT_EQ(0xDEADBEEF, value); 435848b8605Smrg } else { 436848b8605Smrg EXPECT_FALSE(got_sigsegv); 437848b8605Smrg } 438848b8605Smrg} 439