Home | History | Annotate | Download | only in tests
      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 #include "glxclient.h"
     28 #include "glx_error.h"
     29 
     30 extern bool GetGLXScreenConfigs_called;
     31 extern struct glx_screen *psc;
     32 
     33 struct attribute_test_vector {
     34    const char *string;
     35    int value;
     36 };
     37 
     38 #define E(x) { # x, x }
     39 
     40 
     41 
     42 static bool got_sigsegv;
     43 static jmp_buf jmp;
     44 
     45 static void
     46 sigsegv_handler(int sig)
     47 {
     48    (void) sig;
     49    got_sigsegv = true;
     50    longjmp(jmp, 1);
     51 }
     52 
     53 static bool query_renderer_string_called = false;
     54 static bool query_renderer_integer_called = false;
     55 
     56 static int
     57 fake_query_renderer_integer(struct glx_screen *psc, int attribute,
     58                             unsigned int *value)
     59 {
     60    (void) psc;
     61    (void) attribute;
     62    (void) value;
     63 
     64    query_renderer_integer_called = true;
     65 
     66    return -1;
     67 }
     68 
     69 static int
     70 fake_query_renderer_string(struct glx_screen *psc, int attribute,
     71                            const char **value)
     72 {
     73    (void) psc;
     74    (void) attribute;
     75    (void) value;
     76 
     77    query_renderer_string_called = true;
     78 
     79    return -1;
     80 }
     81 
     82 struct glx_screen_vtable fake_vtable = {
     83    NULL,
     84    NULL,
     85    fake_query_renderer_integer,
     86    fake_query_renderer_string
     87 };
     88 
     89 class query_renderer_string_test : public ::testing::Test {
     90 public:
     91    virtual void SetUp();
     92    virtual void TearDown();
     93 
     94    struct glx_screen scr;
     95    struct sigaction sa;
     96    struct sigaction old_sa;
     97    Display dpy;
     98 };
     99 
    100 class query_renderer_integer_test : public query_renderer_string_test {
    101 };
    102 
    103 void query_renderer_string_test::SetUp()
    104 {
    105    memset(&scr, 0, sizeof(scr));
    106    scr.vtable = &fake_vtable;
    107    psc = &scr;
    108 
    109    got_sigsegv = false;
    110 
    111    sa.sa_handler = sigsegv_handler;
    112    sigemptyset(&sa.sa_mask);
    113    sa.sa_flags = 0;
    114    sigaction(SIGSEGV, &sa, &old_sa);
    115 }
    116 
    117 void query_renderer_string_test::TearDown()
    118 {
    119    sigaction(SIGSEGV, &old_sa, NULL);
    120 }
    121 
    122 /**
    123  * glXQueryRendererStringMESA will return \c NULL if the query_render_string
    124  * vtable entry is \c NULL.  It will also not segfault.
    125  */
    126 TEST_F(query_renderer_string_test, null_query_render_string)
    127 {
    128    struct glx_screen_vtable vtable = {
    129       NULL,
    130       NULL,
    131       NULL,
    132       NULL
    133    };
    134 
    135    scr.vtable = &vtable;
    136 
    137    if (setjmp(jmp) == 0) {
    138       const char *str =
    139          glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
    140       EXPECT_EQ((char *)0, str);
    141    } else {
    142       EXPECT_FALSE(got_sigsegv);
    143    }
    144 }
    145 
    146 /**
    147  * glXQueryRendererStringMESA will not call the screen query_render_string
    148  * function with an invalid GLX enum value, and it will return NULL.
    149  */
    150 TEST_F(query_renderer_string_test, invalid_attribute)
    151 {
    152    static const attribute_test_vector invalid_attributes[] = {
    153       /* These values are just plain invalid for use with this extension.
    154        */
    155       E(0),
    156       E(GLX_VENDOR),
    157       E(GLX_VERSION),
    158       E(GLX_EXTENSIONS),
    159       E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000),
    160       E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000),
    161 
    162       /* These enums are part of the extension, but they are not allowed for
    163        * the string query.
    164        */
    165       E(GLX_RENDERER_VERSION_MESA),
    166       E(GLX_RENDERER_ACCELERATED_MESA),
    167       E(GLX_RENDERER_VIDEO_MEMORY_MESA),
    168       E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA),
    169       E(GLX_RENDERER_PREFERRED_PROFILE_MESA),
    170       E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA),
    171       E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA),
    172       E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA),
    173       E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA),
    174       E(GLX_RENDERER_ID_MESA),
    175    };
    176 
    177    for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
    178       query_renderer_integer_called = false;
    179       query_renderer_string_called = false;
    180 
    181       const char *str =
    182          glXQueryRendererStringMESA(&dpy, 0, 0, invalid_attributes[i].value);
    183       EXPECT_EQ((char *)0, str) << invalid_attributes[i].string;
    184       EXPECT_FALSE(query_renderer_integer_called)
    185          << invalid_attributes[i].string;
    186       EXPECT_FALSE(query_renderer_string_called)
    187          << invalid_attributes[i].string;
    188    }
    189 }
    190 
    191 /**
    192  * glXQueryRendererStringMESA will not call GetGLXScreenConfigs if the display
    193  * pointer is \c NULL.  It will also not segfault.
    194  */
    195 TEST_F(query_renderer_string_test, null_display_pointer)
    196 {
    197    if (setjmp(jmp) == 0) {
    198       GetGLXScreenConfigs_called = false;
    199 
    200       const char *str =
    201          glXQueryRendererStringMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
    202       EXPECT_EQ((char *)0, str);
    203       EXPECT_FALSE(GetGLXScreenConfigs_called);
    204    } else {
    205       EXPECT_FALSE(got_sigsegv);
    206    }
    207 }
    208 
    209 /**
    210  * glXQueryRendererStringMESA will return error if GetGLXScreenConfigs returns
    211  * NULL.  It will also not segfault.
    212  */
    213 TEST_F(query_renderer_string_test, null_screen_pointer)
    214 {
    215    psc = NULL;
    216 
    217    if (setjmp(jmp) == 0) {
    218       GetGLXScreenConfigs_called = false;
    219 
    220       const char *str =
    221          glXQueryRendererStringMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA);
    222       EXPECT_EQ((char *)0, str);
    223       EXPECT_TRUE(GetGLXScreenConfigs_called);
    224    } else {
    225       EXPECT_FALSE(got_sigsegv);
    226    }
    227 }
    228 
    229 /**
    230  * glXQueryRendererStringMESA will not call the screen query_render_string
    231  * function if the renderer is invalid, and it will return NULL.
    232  */
    233 TEST_F(query_renderer_string_test, invalid_renderer_index)
    234 {
    235    static const int invalid_renderer_indices[] = {
    236       -1,
    237       1,
    238       999,
    239    };
    240 
    241    if (setjmp(jmp) == 0) {
    242       for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
    243          const char *str =
    244             glXQueryRendererStringMESA(&dpy, 0,
    245                                        invalid_renderer_indices[i],
    246                                        GLX_RENDERER_VENDOR_ID_MESA);
    247          EXPECT_EQ((char *)0, str) << invalid_renderer_indices[i];
    248          EXPECT_FALSE(query_renderer_integer_called)
    249             << invalid_renderer_indices[i];
    250          EXPECT_FALSE(query_renderer_string_called)
    251             << invalid_renderer_indices[i];
    252       }
    253    } else {
    254       EXPECT_FALSE(got_sigsegv);
    255    }
    256 }
    257 
    258 /**
    259  * glXQueryCurrentRendererStringMESA will return error if there is no context
    260  * current.  It will also not segfault.
    261  */
    262 TEST_F(query_renderer_string_test, no_current_context)
    263 {
    264    if (setjmp(jmp) == 0) {
    265       const char *str =
    266          glXQueryCurrentRendererStringMESA(GLX_RENDERER_VENDOR_ID_MESA);
    267       EXPECT_EQ((char *)0, str);
    268    } else {
    269       EXPECT_FALSE(got_sigsegv);
    270    }
    271 }
    272 
    273 /**
    274  * glXQueryCurrentRendererIntegerMESA will return \c NULL if the
    275  * query_render_string vtable entry is \c NULL.  It will also not segfault.
    276  */
    277 TEST_F(query_renderer_integer_test, null_query_render_string)
    278 {
    279    struct glx_screen_vtable vtable = {
    280       NULL,
    281       NULL,
    282       NULL,
    283       NULL
    284    };
    285 
    286    scr.vtable = &vtable;
    287 
    288    if (setjmp(jmp) == 0) {
    289       unsigned value = 0xDEADBEEF;
    290       Bool success = glXQueryRendererIntegerMESA(&dpy, 0, 0,
    291                                                  GLX_RENDERER_VENDOR_ID_MESA,
    292                                                  &value);
    293       EXPECT_FALSE(success);
    294       EXPECT_EQ(0xDEADBEEF, value);
    295    } else {
    296       EXPECT_FALSE(got_sigsegv);
    297    }
    298 }
    299 
    300 /**
    301  * glXQueryCurrentRendererIntegerMESA will not call the screen
    302  * query_render_string function with an invalid GLX enum value, and it will
    303  * return NULL.
    304  */
    305 TEST_F(query_renderer_integer_test, invalid_attribute)
    306 {
    307    static const attribute_test_vector invalid_attributes[] = {
    308       /* These values are just plain invalid for use with this extension.
    309        */
    310       E(0),
    311       E(GLX_VENDOR),
    312       E(GLX_VERSION),
    313       E(GLX_EXTENSIONS),
    314       E(GLX_RENDERER_VENDOR_ID_MESA + 0x10000),
    315       E(GLX_RENDERER_DEVICE_ID_MESA + 0x10000),
    316       E(GLX_RENDERER_VERSION_MESA + 0x10000),
    317       E(GLX_RENDERER_ACCELERATED_MESA + 0x10000),
    318       E(GLX_RENDERER_VIDEO_MEMORY_MESA + 0x10000),
    319       E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA + 0x10000),
    320       E(GLX_RENDERER_PREFERRED_PROFILE_MESA + 0x10000),
    321       E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA + 0x10000),
    322       E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA + 0x10000),
    323       E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA + 0x10000),
    324       E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA + 0x10000),
    325       E(GLX_RENDERER_ID_MESA + 0x10000),
    326    };
    327 
    328    for (unsigned i = 0; i < ARRAY_SIZE(invalid_attributes); i++) {
    329       query_renderer_integer_called = false;
    330       query_renderer_string_called = false;
    331 
    332       unsigned value = 0xDEADBEEF;
    333       Bool success =
    334          glXQueryRendererIntegerMESA(&dpy, 0, 0,
    335                                      invalid_attributes[i].value,
    336                                      &value);
    337       EXPECT_FALSE(success) << invalid_attributes[i].string;
    338       EXPECT_EQ(0xDEADBEEF, value) << invalid_attributes[i].string;
    339       EXPECT_FALSE(query_renderer_integer_called)
    340          << invalid_attributes[i].string;
    341       EXPECT_FALSE(query_renderer_string_called)
    342          << invalid_attributes[i].string;
    343    }
    344 }
    345 
    346 /**
    347  * glXQueryCurrentRendererIntegerMESA will not call GetGLXScreenConfigs if the
    348  * display pointer is \c NULL.  It will also not segfault.
    349  */
    350 TEST_F(query_renderer_integer_test, null_display_pointer)
    351 {
    352    if (setjmp(jmp) == 0) {
    353       GetGLXScreenConfigs_called = false;
    354 
    355       unsigned value = 0xDEADBEEF;
    356       Bool success =
    357          glXQueryRendererIntegerMESA(NULL, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
    358                                      &value);
    359       EXPECT_FALSE(success);
    360       EXPECT_EQ(0xDEADBEEF, value);
    361       EXPECT_FALSE(GetGLXScreenConfigs_called);
    362    } else {
    363       EXPECT_FALSE(got_sigsegv);
    364    }
    365 }
    366 
    367 /**
    368  * glXQueryCurrentRendererIntegerMESA will return error if GetGLXScreenConfigs
    369  * returns NULL.  It will also not segfault.
    370  */
    371 TEST_F(query_renderer_integer_test, null_screen_pointer)
    372 {
    373    psc = NULL;
    374 
    375    if (setjmp(jmp) == 0) {
    376       GetGLXScreenConfigs_called = false;
    377 
    378       unsigned value = 0xDEADBEEF;
    379       Bool success =
    380          glXQueryRendererIntegerMESA(&dpy, 0, 0, GLX_RENDERER_VENDOR_ID_MESA,
    381             &value);
    382       EXPECT_FALSE(success);
    383       EXPECT_EQ(0xDEADBEEF, value);
    384       EXPECT_TRUE(GetGLXScreenConfigs_called);
    385    } else {
    386       EXPECT_FALSE(got_sigsegv);
    387    }
    388 }
    389 
    390 /**
    391  * glXQueryRendererIntegerMESA will not call the screen query_render_integer
    392  * function if the renderer is invalid, and it will return NULL.
    393  */
    394 TEST_F(query_renderer_integer_test, invalid_renderer_index)
    395 {
    396    static const int invalid_renderer_indices[] = {
    397       -1,
    398       1,
    399       999,
    400    };
    401 
    402    if (setjmp(jmp) == 0) {
    403       for (unsigned i = 0; i < ARRAY_SIZE(invalid_renderer_indices); i++) {
    404          unsigned value = 0xDEADBEEF;
    405          Bool success =
    406             glXQueryRendererIntegerMESA(&dpy, 0,
    407                                         invalid_renderer_indices[i],
    408                                         GLX_RENDERER_VENDOR_ID_MESA,
    409                                         &value);
    410          EXPECT_FALSE(success) << invalid_renderer_indices[i];
    411          EXPECT_EQ(0xDEADBEEF, value) << invalid_renderer_indices[i];
    412          EXPECT_FALSE(query_renderer_integer_called)
    413             << invalid_renderer_indices[i];
    414          EXPECT_FALSE(query_renderer_string_called)
    415             << invalid_renderer_indices[i];
    416       }
    417    } else {
    418       EXPECT_FALSE(got_sigsegv);
    419    }
    420 }
    421 
    422 /**
    423  * glXQueryCurrentRendererIntegerMESA will return error if there is no context
    424  * current.  It will also not segfault.
    425  */
    426 TEST_F(query_renderer_integer_test, no_current_context)
    427 {
    428    if (setjmp(jmp) == 0) {
    429       unsigned value = 0xDEADBEEF;
    430       Bool success =
    431          glXQueryCurrentRendererIntegerMESA(GLX_RENDERER_VENDOR_ID_MESA,
    432                                             &value);
    433       EXPECT_FALSE(success);
    434       EXPECT_EQ(0xDEADBEEF, value);
    435    } else {
    436       EXPECT_FALSE(got_sigsegv);
    437    }
    438 }
    439