Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. }
  441.