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