glx/tests: Add unit tests for the DRI2 part of GLX_MESA_query_renderer
[mesa.git] / src / glx / tests / query_renderer_implementation_unittest.cpp
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 #include "xf86drm.h"
31 #include "dri2.h"
32 #include "dri_interface.h"
33 #include "dri2_priv.h"
34 }
35
36 struct attribute_test_vector {
37 const char *glx_string;
38 const char *dri_string;
39 int glx_attribute;
40 int dri_attribute;
41 };
42
43 #define E(g, d) { # g, # d, g, d }
44
45 static bool got_sigsegv;
46 static jmp_buf jmp;
47
48 static void
49 sigsegv_handler(int sig)
50 {
51 (void) sig;
52 got_sigsegv = true;
53 longjmp(jmp, 1);
54 }
55
56 class dri2_query_renderer_string_test : public ::testing::Test {
57 public:
58 virtual void SetUp();
59 virtual void TearDown();
60
61 struct sigaction sa;
62 struct sigaction old_sa;
63 };
64
65 class dri2_query_renderer_integer_test :
66 public dri2_query_renderer_string_test {
67 };
68
69 static bool queryString_called = false;
70 static int queryString_attribute = -1;
71
72 static bool queryInteger_called = false;
73 static int queryInteger_attribute = -1;
74
75 static int
76 fake_queryInteger(__DRIscreen *screen, int attribute, unsigned int *val)
77 {
78 (void) screen;
79
80 queryInteger_attribute = attribute;
81 queryInteger_called = true;
82
83 switch (attribute) {
84 case __DRI2_RENDERER_VENDOR_ID:
85 *val = ~__DRI2_RENDERER_VENDOR_ID;
86 return 0;
87 case __DRI2_RENDERER_DEVICE_ID:
88 *val = ~__DRI2_RENDERER_DEVICE_ID;
89 return 0;
90 case __DRI2_RENDERER_VERSION:
91 *val = ~__DRI2_RENDERER_VERSION;
92 return 0;
93 case __DRI2_RENDERER_ACCELERATED:
94 *val = ~__DRI2_RENDERER_ACCELERATED;
95 return 0;
96 case __DRI2_RENDERER_VIDEO_MEMORY:
97 *val = ~__DRI2_RENDERER_VIDEO_MEMORY;
98 return 0;
99 case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
100 *val = ~__DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE;
101 return 0;
102 case __DRI2_RENDERER_PREFERRED_PROFILE:
103 *val = ~__DRI2_RENDERER_PREFERRED_PROFILE;
104 return 0;
105 case __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION:
106 *val = ~__DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION;
107 return 0;
108 case __DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION:
109 *val = ~__DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION;
110 return 0;
111 case __DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION:
112 *val = ~__DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION;
113 return 0;
114 case __DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION:
115 *val = ~__DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION;
116 return 0;
117 }
118
119 return -1;
120 }
121
122 static int
123 fake_queryString(__DRIscreen *screen, int attribute, const char **val)
124 {
125 (void) screen;
126
127 queryString_attribute = attribute;
128 queryString_called = true;
129
130 switch (attribute) {
131 case __DRI2_RENDERER_VENDOR_ID:
132 *val = "__DRI2_RENDERER_VENDOR_ID";
133 return 0;
134 case __DRI2_RENDERER_DEVICE_ID:
135 *val = "__DRI2_RENDERER_DEVICE_ID";
136 return 0;
137 }
138
139 return -1;
140 }
141
142 struct __DRI2rendererQueryExtensionRec rendererQueryExt = {
143 { __DRI2_RENDERER_QUERY, 1 },
144
145 fake_queryInteger,
146 fake_queryString
147 };
148
149 void dri2_query_renderer_string_test::SetUp()
150 {
151 got_sigsegv = false;
152
153 sa.sa_handler = sigsegv_handler;
154 sigemptyset(&sa.sa_mask);
155 sa.sa_flags = 0;
156 sigaction(SIGSEGV, &sa, &old_sa);
157 }
158
159 void dri2_query_renderer_string_test::TearDown()
160 {
161 sigaction(SIGSEGV, &old_sa, NULL);
162 }
163
164 /**
165 * dri2_query_renderer_string will return an error if the rendererQuery
166 * extension is not present. It will also not segfault.
167 */
168 TEST_F(dri2_query_renderer_string_test, DRI2_RENDERER_QUERY_not_supported)
169 {
170 struct dri2_screen dsc;
171
172 memset(&dsc, 0, sizeof(dsc));
173
174 if (setjmp(jmp) == 0) {
175 static const char original_value[] = "0xDEADBEEF";
176 const char *value = original_value;
177 const int success =
178 dri2_query_renderer_string(&dsc.base,
179 GLX_RENDERER_VENDOR_ID_MESA, &value);
180
181 EXPECT_EQ(-1, success);
182 EXPECT_EQ(original_value, value);
183 } else {
184 EXPECT_FALSE(got_sigsegv);
185 }
186 }
187
188 /**
189 * dri2_query_renderer_string will call queryString with the correct DRI2 enum
190 * for each GLX attribute value.
191 *
192 * \note
193 * This test does \b not perform any checking for invalid GLX attribte values.
194 * Other unit tests verify that invalid values are filtered before
195 * dri2_query_renderer_string is called.
196 */
197 TEST_F(dri2_query_renderer_string_test, valid_attribute_mapping)
198 {
199 struct dri2_screen dsc;
200 struct attribute_test_vector valid_attributes[] = {
201 E(GLX_RENDERER_VENDOR_ID_MESA,
202 __DRI2_RENDERER_VENDOR_ID),
203 E(GLX_RENDERER_DEVICE_ID_MESA,
204 __DRI2_RENDERER_DEVICE_ID),
205 };
206
207 memset(&dsc, 0, sizeof(dsc));
208 dsc.rendererQuery = &rendererQueryExt;
209
210 if (setjmp(jmp) == 0) {
211 for (unsigned i = 0; i < ARRAY_SIZE(valid_attributes); i++) {
212 static const char original_value[] = "original value";
213 const char *value = original_value;
214 const int success =
215 dri2_query_renderer_string(&dsc.base,
216 valid_attributes[i].glx_attribute,
217 &value);
218
219 EXPECT_EQ(0, success);
220 EXPECT_EQ(valid_attributes[i].dri_attribute, queryString_attribute)
221 << valid_attributes[i].glx_string;
222 EXPECT_STREQ(valid_attributes[i].dri_string, value)
223 << valid_attributes[i].glx_string;
224 }
225 } else {
226 EXPECT_FALSE(got_sigsegv);
227 }
228 }
229
230 /**
231 * dri2_query_renderer_integer will return an error if the rendererQuery
232 * extension is not present. It will also not segfault.
233 */
234 TEST_F(dri2_query_renderer_integer_test, DRI2_RENDERER_QUERY_not_supported)
235 {
236 struct dri2_screen dsc;
237
238 memset(&dsc, 0, sizeof(dsc));
239
240 if (setjmp(jmp) == 0) {
241 unsigned int value = 0xDEADBEEF;
242 const int success =
243 dri2_query_renderer_integer(&dsc.base,
244 GLX_RENDERER_VENDOR_ID_MESA, &value);
245
246 EXPECT_EQ(-1, success);
247 EXPECT_EQ(0xDEADBEEF, value);
248 } else {
249 EXPECT_FALSE(got_sigsegv);
250 }
251 }
252
253 /**
254 * dri2_query_renderer_integer will call queryInteger with the correct DRI2 enum
255 * for each GLX attribute value.
256 *
257 * \note
258 * This test does \b not perform any checking for invalid GLX attribte values.
259 * Other unit tests verify that invalid values are filtered before
260 * dri2_query_renderer_integer is called.
261 */
262 TEST_F(dri2_query_renderer_integer_test, valid_attribute_mapping)
263 {
264 struct dri2_screen dsc;
265 struct attribute_test_vector valid_attributes[] = {
266 E(GLX_RENDERER_VENDOR_ID_MESA,
267 __DRI2_RENDERER_VENDOR_ID),
268 E(GLX_RENDERER_DEVICE_ID_MESA,
269 __DRI2_RENDERER_DEVICE_ID),
270 E(GLX_RENDERER_VERSION_MESA,
271 __DRI2_RENDERER_VERSION),
272 E(GLX_RENDERER_ACCELERATED_MESA,
273 __DRI2_RENDERER_ACCELERATED),
274 E(GLX_RENDERER_VIDEO_MEMORY_MESA,
275 __DRI2_RENDERER_VIDEO_MEMORY),
276 E(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA,
277 __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE),
278 E(GLX_RENDERER_PREFERRED_PROFILE_MESA,
279 __DRI2_RENDERER_PREFERRED_PROFILE),
280 E(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA,
281 __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION),
282 E(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA,
283 __DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION),
284 E(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA,
285 __DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION),
286 E(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA,
287 __DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION),
288 };
289
290 memset(&dsc, 0, sizeof(dsc));
291 dsc.rendererQuery = &rendererQueryExt;
292
293 if (setjmp(jmp) == 0) {
294 for (unsigned i = 0; i < ARRAY_SIZE(valid_attributes); i++) {
295 unsigned int value = 0xDEADBEEF;
296 const int success =
297 dri2_query_renderer_integer(&dsc.base,
298 valid_attributes[i].glx_attribute,
299 &value);
300
301 EXPECT_EQ(0, success);
302 EXPECT_EQ(valid_attributes[i].dri_attribute, queryInteger_attribute)
303 << valid_attributes[i].glx_string;
304 EXPECT_EQ((unsigned int) ~valid_attributes[i].dri_attribute, value)
305 << valid_attributes[i].glx_string;
306 }
307 } else {
308 EXPECT_FALSE(got_sigsegv);
309 }
310 }