1 /*
2  * Copyright © 2011 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 <string.h>
25 
26 extern "C" {
27 #include "glxclient.h"
28 }
29 
30 #include <xcb/glx.h>
31 
32 #include "mock_xdisplay.h"
33 #include "fake_glx_screen.h"
34 
35 /**
36  * \name Wrappers around some X structures to make the more usable for tests
37  */
38 /*@{*/
39 class fake_glx_screen;
40 
41 class fake_glx_display : public glx_display {
42 public:
fake_glx_display(mock_XDisplay * dpy,int major,int minor)43    fake_glx_display(mock_XDisplay *dpy, int major, int minor)
44    {
45       this->next = 0;
46       this->dpy = dpy;
47       this->majorOpcode = 0;
48       this->majorVersion = major;
49       this->minorVersion = minor;
50       this->serverGLXvendor = 0;
51       this->serverGLXversion = 0;
52       this->glXDrawHash = 0;
53 
54       this->screens = new glx_screen *[dpy->nscreens];
55       memset(this->screens, 0, sizeof(struct glx_screen *) * dpy->nscreens);
56    }
57 
~fake_glx_display()58    ~fake_glx_display()
59    {
60       for (int i = 0; i < this->dpy->nscreens; i++) {
61 	 if (this->screens[i] != NULL)
62 	    delete this->screens[i];
63       }
64 
65       delete [] this->screens;
66    }
67 
68    void init_screen(int i, const char *ext);
69 };
70 
71 class glX_send_client_info_test : public ::testing::Test {
72 public:
73    glX_send_client_info_test();
74    virtual ~glX_send_client_info_test();
75    virtual void SetUp();
76 
77    void common_protocol_expected_false_test(unsigned major, unsigned minor,
78 					    const char *glx_ext, bool *value);
79 
80    void common_protocol_expected_true_test(unsigned major, unsigned minor,
81 					   const char *glx_ext, bool *value);
82 
83    void create_single_screen_display(unsigned major, unsigned minor,
84 				     const char *glx_ext);
85 
86    void destroy_display();
87 
88 protected:
89    fake_glx_display *glx_dpy;
90    mock_XDisplay *display;
91 };
92 
93 void
init_screen(int i,const char * ext)94 fake_glx_display::init_screen(int i, const char *ext)
95 {
96    if (this->screens[i] != NULL)
97       delete this->screens[i];
98 
99    this->screens[i] = new fake_glx_screen(this, i, ext);
100 }
101 /*@}*/
102 
103 static const char ext[] = "GL_XXX_dummy";
104 
105 static bool ClientInfo_was_sent;
106 static bool SetClientInfoARB_was_sent;
107 static bool SetClientInfo2ARB_was_sent;
108 static xcb_connection_t *connection_used;
109 static int gl_ext_length;
110 static char *gl_ext_string;
111 static int glx_ext_length;
112 static char *glx_ext_string;
113 static int num_gl_versions;
114 static uint32_t *gl_versions;
115 static int glx_major;
116 static int glx_minor;
117 
118 extern "C" xcb_connection_t *
XGetXCBConnection(Display * dpy)119 XGetXCBConnection(Display *dpy)
120 {
121    return (xcb_connection_t *) 0xdeadbeef;
122 }
123 
124 extern "C" xcb_void_cookie_t
xcb_glx_client_info(xcb_connection_t * c,uint32_t major_version,uint32_t minor_version,uint32_t str_len,const char * string)125 xcb_glx_client_info(xcb_connection_t *c,
126 		    uint32_t major_version,
127 		    uint32_t minor_version,
128 		    uint32_t str_len,
129 		    const char *string)
130 {
131    xcb_void_cookie_t cookie;
132 
133    ClientInfo_was_sent = true;
134    connection_used = c;
135 
136    gl_ext_string = (char *) malloc(str_len);
137    memcpy(gl_ext_string, string, str_len);
138    gl_ext_length = str_len;
139 
140    glx_major = major_version;
141    glx_minor = minor_version;
142 
143    cookie.sequence = 0;
144    return cookie;
145 }
146 
147 extern "C" xcb_void_cookie_t
xcb_glx_set_client_info_arb(xcb_connection_t * c,uint32_t major_version,uint32_t minor_version,uint32_t num_versions,uint32_t gl_str_len,uint32_t glx_str_len,const uint32_t * versions,const char * gl_string,const char * glx_string)148 xcb_glx_set_client_info_arb(xcb_connection_t *c,
149 			    uint32_t major_version,
150 			    uint32_t minor_version,
151 			    uint32_t num_versions,
152 			    uint32_t gl_str_len,
153 			    uint32_t glx_str_len,
154 			    const uint32_t *versions,
155 			    const char *gl_string,
156 			    const char *glx_string)
157 {
158    xcb_void_cookie_t cookie;
159 
160    SetClientInfoARB_was_sent = true;
161    connection_used = c;
162 
163    gl_ext_string = new char[gl_str_len];
164    memcpy(gl_ext_string, gl_string, gl_str_len);
165    gl_ext_length = gl_str_len;
166 
167    glx_ext_string = new char[glx_str_len];
168    memcpy(glx_ext_string, glx_string, glx_str_len);
169    glx_ext_length = glx_str_len;
170 
171    gl_versions = new uint32_t[num_versions * 2];
172    memcpy(gl_versions, versions, sizeof(uint32_t) * num_versions * 2);
173    num_gl_versions = num_versions;
174 
175    glx_major = major_version;
176    glx_minor = minor_version;
177 
178    cookie.sequence = 0;
179    return cookie;
180 }
181 
182 extern "C" xcb_void_cookie_t
xcb_glx_set_client_info_2arb(xcb_connection_t * c,uint32_t major_version,uint32_t minor_version,uint32_t num_versions,uint32_t gl_str_len,uint32_t glx_str_len,const uint32_t * versions,const char * gl_string,const char * glx_string)183 xcb_glx_set_client_info_2arb(xcb_connection_t *c,
184 			     uint32_t major_version,
185 			     uint32_t minor_version,
186 			     uint32_t num_versions,
187 			     uint32_t gl_str_len,
188 			     uint32_t glx_str_len,
189 			     const uint32_t *versions,
190 			     const char *gl_string,
191 			     const char *glx_string)
192 {
193    xcb_void_cookie_t cookie;
194 
195    SetClientInfo2ARB_was_sent = true;
196    connection_used = c;
197 
198    gl_ext_string = new char[gl_str_len];
199    memcpy(gl_ext_string, gl_string, gl_str_len);
200    gl_ext_length = gl_str_len;
201 
202    glx_ext_string = new char[glx_str_len];
203    memcpy(glx_ext_string, glx_string, glx_str_len);
204    glx_ext_length = glx_str_len;
205 
206    gl_versions = new uint32_t[num_versions * 3];
207    memcpy(gl_versions, versions, sizeof(uint32_t) * num_versions * 3);
208    num_gl_versions = num_versions;
209 
210    glx_major = major_version;
211    glx_minor = minor_version;
212 
213    cookie.sequence = 0;
214    return cookie;
215 }
216 
217 extern "C" char *
__glXGetClientGLExtensionString()218 __glXGetClientGLExtensionString()
219 {
220    char *str = (char *) malloc(sizeof(ext));
221 
222    memcpy(str, ext, sizeof(ext));
223    return str;
224 }
225 
glX_send_client_info_test()226 glX_send_client_info_test::glX_send_client_info_test()
227    : glx_dpy(0), display(0)
228 {
229    /* empty */
230 }
231 
~glX_send_client_info_test()232 glX_send_client_info_test::~glX_send_client_info_test()
233 {
234    if (glx_dpy)
235       delete glx_dpy;
236 
237    if (display)
238       delete display;
239 }
240 
241 void
destroy_display()242 glX_send_client_info_test::destroy_display()
243 {
244    if (this->glx_dpy != NULL) {
245       if (this->glx_dpy->screens != NULL) {
246 	 for (int i = 0; i < this->display->nscreens; i++) {
247 	    delete [] this->glx_dpy->screens[i]->serverGLXexts;
248 	    delete this->glx_dpy->screens[i];
249 	 }
250 
251 	 delete [] this->glx_dpy->screens;
252       }
253 
254       delete this->glx_dpy;
255       delete this->display;
256    }
257 }
258 
259 void
SetUp()260 glX_send_client_info_test::SetUp()
261 {
262    ClientInfo_was_sent = false;
263    SetClientInfoARB_was_sent = false;
264    SetClientInfo2ARB_was_sent = false;
265    connection_used = (xcb_connection_t *) ~0;
266    gl_ext_length = 0;
267    gl_ext_string = (char *) 0;
268    glx_ext_length = 0;
269    glx_ext_string = (char *) 0;
270    num_gl_versions = 0;
271    gl_versions = (uint32_t *) 0;
272    glx_major = 0;
273    glx_minor = 0;
274 }
275 
276 void
create_single_screen_display(unsigned major,unsigned minor,const char * glx_ext)277 glX_send_client_info_test::create_single_screen_display(unsigned major,
278 							unsigned minor,
279 							const char *glx_ext)
280 {
281    this->display = new mock_XDisplay(1);
282 
283    this->glx_dpy = new fake_glx_display(this->display, major, minor);
284    this->glx_dpy->init_screen(0, glx_ext);
285 }
286 
287 void
common_protocol_expected_false_test(unsigned major,unsigned minor,const char * glx_ext,bool * value)288 glX_send_client_info_test::common_protocol_expected_false_test(unsigned major,
289 							       unsigned minor,
290 							       const char *glx_ext,
291 							       bool *value)
292 {
293    create_single_screen_display(major, minor, glx_ext);
294    __glX_send_client_info(this->glx_dpy);
295    EXPECT_FALSE(*value);
296 }
297 
298 void
common_protocol_expected_true_test(unsigned major,unsigned minor,const char * glx_ext,bool * value)299 glX_send_client_info_test::common_protocol_expected_true_test(unsigned major,
300 							      unsigned minor,
301 							      const char *glx_ext,
302 							      bool *value)
303 {
304    create_single_screen_display(major, minor, glx_ext);
305    __glX_send_client_info(this->glx_dpy);
306    EXPECT_TRUE(*value);
307 }
308 
TEST_F(glX_send_client_info_test,doesnt_send_ClientInfo_for_1_0)309 TEST_F(glX_send_client_info_test, doesnt_send_ClientInfo_for_1_0)
310 {
311    /* The glXClientInfo protocol was added in GLX 1.1.  Verify that no
312     * glXClientInfo is sent to a GLX server that only has GLX 1.0.
313     */
314    common_protocol_expected_false_test(1, 0, "", &ClientInfo_was_sent);
315 }
316 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_0)317 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_0)
318 {
319    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
320     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
321     * sent to a GLX server that only has GLX 1.0 regardless of the extension
322     * setting.
323     */
324    common_protocol_expected_false_test(1, 0,
325 				       "GLX_ARB_create_context",
326 				       &SetClientInfoARB_was_sent);
327 }
328 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_1)329 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_1)
330 {
331    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
332     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
333     * sent to a GLX server that only has GLX 1.0 regardless of the extension
334     * setting.
335     */
336    common_protocol_expected_false_test(1, 1,
337 				       "GLX_ARB_create_context",
338 				       &SetClientInfoARB_was_sent);
339 }
340 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_with_empty_extensions)341 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_with_empty_extensions)
342 {
343    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
344     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
345     * sent to a GLX server that has GLX 1.4 but has an empty extension string
346     * (i.e., no extensions at all).
347     */
348    common_protocol_expected_false_test(1, 4,
349 				       "",
350 				       &SetClientInfoARB_was_sent);
351 }
352 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_without_extension)353 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_without_extension)
354 {
355    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
356     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
357     * sent to a GLX server that has GLX 1.4 but doesn't have the extension.
358     */
359    common_protocol_expected_false_test(1, 4,
360 				       "GLX_EXT_texture_from_pixmap",
361 				       &SetClientInfoARB_was_sent);
362 }
363 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_with_wrong_extension)364 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_with_wrong_extension)
365 {
366    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
367     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
368     * sent to a GLX server that has GLX 1.4 but does not have the extension.
369     *
370     * This test differs from
371     * doesnt_send_SetClientInfoARB_for_1_4_without_extension in that an
372     * extension exists that looks like the correct extension but isn't.
373     */
374    common_protocol_expected_false_test(1, 4,
375 				       "GLX_ARB_create_context2",
376 				       &SetClientInfoARB_was_sent);
377 }
378 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfoARB_for_1_4_with_profile_extension)379 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_with_profile_extension)
380 {
381    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
382     * GLX_ARB_create_context extension.  Verify that no glXSetClientInfoARB is
383     * sent to a GLX server that has GLX 1.4 but does not have the extension.
384     *
385     * This test differs from
386     * doesnt_send_SetClientInfoARB_for_1_4_without_extension in that an
387     * extension exists that looks like the correct extension but isn't.
388     */
389    common_protocol_expected_false_test(1, 4,
390 				       "GLX_ARB_create_context_profile",
391 				       &SetClientInfoARB_was_sent);
392 }
393 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_0)394 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_0)
395 {
396    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
397     * GLX_ARB_create_context_profile extension.  Verify that no
398     * glXSetClientInfo2ARB is sent to a GLX server that only has GLX 1.0
399     * regardless of the extension setting.
400     */
401    common_protocol_expected_false_test(1, 0,
402 				       "GLX_ARB_create_context_profile",
403 				       &SetClientInfo2ARB_was_sent);
404 }
405 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_1)406 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_1)
407 {
408    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
409     * GLX_ARB_create_context_profile extension.  Verify that no
410     * glXSetClientInfo2ARB is sent to a GLX server that only has GLX 1.1
411     * regardless of the extension setting.
412     */
413    common_protocol_expected_false_test(1, 1,
414 				       "GLX_ARB_create_context_profile",
415 				       &SetClientInfo2ARB_was_sent);
416 }
417 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_4_with_empty_extensions)418 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_4_with_empty_extensions)
419 {
420    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
421     * GLX_ARB_create_context_profile extension.  Verify that no
422     * glXSetClientInfo2ARB is sent to a GLX server that has GLX 1.4 but has an
423     * empty extension string (i.e., no extensions at all).
424     */
425    common_protocol_expected_false_test(1, 4,
426 				       "",
427 				       &SetClientInfo2ARB_was_sent);
428 }
429 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_4_without_extension)430 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_4_without_extension)
431 {
432    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
433     * GLX_ARB_create_context_profile extension.  Verify that no
434     * glXSetClientInfo2ARB is sent to a GLX server that has GLX 1.4 but
435     * doesn't have the extension.
436     */
437    common_protocol_expected_false_test(1, 4,
438 				       "GLX_EXT_texture_from_pixmap",
439 				       &SetClientInfo2ARB_was_sent);
440 }
441 
TEST_F(glX_send_client_info_test,doesnt_send_SetClientInfo2ARB_for_1_4_with_wrong_extension)442 TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_4_with_wrong_extension)
443 {
444    /* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
445     * GLX_ARB_create_context_profile extension.  Verify that no
446     * glXSetClientInfo2ARB is sent to a GLX server that has GLX 1.4 but does
447     * not have the extension.
448     *
449     * This test differs from
450     * doesnt_send_SetClientInfo2ARB_for_1_4_without_extension in that an
451     * extension exists that looks like the correct extension but isn't.
452     */
453    common_protocol_expected_false_test(1, 4,
454 				       "GLX_ARB_create_context_profile2",
455 				       &SetClientInfo2ARB_was_sent);
456 }
457 
TEST_F(glX_send_client_info_test,does_send_ClientInfo_for_1_1)458 TEST_F(glX_send_client_info_test, does_send_ClientInfo_for_1_1)
459 {
460    /* The glXClientInfo protocol was added in GLX 1.1.  Verify that
461     * glXClientInfo is sent to a GLX server that has GLX 1.1.
462     */
463    common_protocol_expected_true_test(1, 1,
464 				      "",
465 				      &ClientInfo_was_sent);
466 }
467 
TEST_F(glX_send_client_info_test,does_send_SetClientInfoARB_for_1_4_with_extension)468 TEST_F(glX_send_client_info_test, does_send_SetClientInfoARB_for_1_4_with_extension)
469 {
470    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
471     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
472     * sent to a GLX server that has GLX 1.4 and the extension.
473     */
474    common_protocol_expected_true_test(1, 4,
475 				      "GLX_ARB_create_context",
476 				      &SetClientInfoARB_was_sent);
477 }
478 
TEST_F(glX_send_client_info_test,does_send_SetClientInfo2ARB_for_1_4_with_just_profile_extension)479 TEST_F(glX_send_client_info_test, does_send_SetClientInfo2ARB_for_1_4_with_just_profile_extension)
480 {
481    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
482     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
483     * sent to a GLX server that has GLX 1.4 and the extension.
484     */
485    common_protocol_expected_true_test(1, 4,
486 				      "GLX_ARB_create_context_profile",
487 				      &SetClientInfo2ARB_was_sent);
488 }
489 
TEST_F(glX_send_client_info_test,does_send_SetClientInfo2ARB_for_1_4_with_both_extensions)490 TEST_F(glX_send_client_info_test, does_send_SetClientInfo2ARB_for_1_4_with_both_extensions)
491 {
492    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
493     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
494     * sent to a GLX server that has GLX 1.4 and the extension.
495     */
496    common_protocol_expected_true_test(1, 4,
497 				      "GLX_ARB_create_context "
498 				      "GLX_ARB_create_context_profile",
499 				      &SetClientInfo2ARB_was_sent);
500 }
501 
TEST_F(glX_send_client_info_test,does_send_SetClientInfo2ARB_for_1_4_with_both_extensions_reversed)502 TEST_F(glX_send_client_info_test, does_send_SetClientInfo2ARB_for_1_4_with_both_extensions_reversed)
503 {
504    /* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
505     * GLX_ARB_create_context extension.  Verify that glXSetClientInfoARB is
506     * sent to a GLX server that has GLX 1.4 and the extension.
507     */
508    common_protocol_expected_true_test(1, 4,
509 				      "GLX_ARB_create_context_profile "
510 				      "GLX_ARB_create_context",
511 				      &SetClientInfo2ARB_was_sent);
512 }
513 
TEST_F(glX_send_client_info_test,uses_correct_connection)514 TEST_F(glX_send_client_info_test, uses_correct_connection)
515 {
516    create_single_screen_display(1, 1, "");
517    __glX_send_client_info(this->glx_dpy);
518    EXPECT_EQ((xcb_connection_t *) 0xdeadbeef, connection_used);
519 }
520 
TEST_F(glX_send_client_info_test,sends_correct_gl_extension_string)521 TEST_F(glX_send_client_info_test, sends_correct_gl_extension_string)
522 {
523    create_single_screen_display(1, 1, "");
524    __glX_send_client_info(this->glx_dpy);
525 
526    ASSERT_EQ((int) sizeof(ext), gl_ext_length);
527    ASSERT_NE((char *) 0, gl_ext_string);
528    EXPECT_EQ(0, memcmp(gl_ext_string, ext, sizeof(ext)));
529 }
530 
TEST_F(glX_send_client_info_test,gl_versions_are_sane)531 TEST_F(glX_send_client_info_test, gl_versions_are_sane)
532 {
533    create_single_screen_display(1, 4, "GLX_ARB_create_context");
534    __glX_send_client_info(this->glx_dpy);
535 
536    ASSERT_NE(0, num_gl_versions);
537 
538    unsigned versions_below_3_0 = 0;
539    for (int i = 0; i < num_gl_versions; i++) {
540       EXPECT_LT(0u, gl_versions[i * 2]);
541       EXPECT_GE(4u, gl_versions[i * 2]);
542 
543       /* Verify that the minor version advertised with the major version makes
544        * sense.
545        */
546       switch (gl_versions[i * 2]) {
547       case 1:
548 	 EXPECT_GE(5u, gl_versions[i * 2 + 1]);
549 	 versions_below_3_0++;
550 	 break;
551       case 2:
552 	 EXPECT_GE(1u, gl_versions[i * 2 + 1]);
553 	 versions_below_3_0++;
554 	 break;
555       case 3:
556 	 EXPECT_GE(3u, gl_versions[i * 2 + 1]);
557 	 break;
558       case 4:
559 	 EXPECT_GE(2u, gl_versions[i * 2 + 1]);
560 	 break;
561       }
562    }
563 
564    /* From the GLX_ARB_create_context spec:
565     *
566     *     "Only the highest supported version below 3.0 should be sent, since
567     *     OpenGL 2.1 is backwards compatible with all earlier versions."
568     */
569    EXPECT_LE(versions_below_3_0, 1u);
570 }
571 
TEST_F(glX_send_client_info_test,gl_versions_and_profiles_are_sane)572 TEST_F(glX_send_client_info_test, gl_versions_and_profiles_are_sane)
573 {
574    create_single_screen_display(1, 4, "GLX_ARB_create_context_profile");
575    __glX_send_client_info(this->glx_dpy);
576 
577    ASSERT_NE(0, num_gl_versions);
578 
579    const uint32_t all_valid_bits = GLX_CONTEXT_CORE_PROFILE_BIT_ARB
580       | GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
581 
582    unsigned versions_below_3_0 = 0;
583 
584    for (int i = 0; i < num_gl_versions; i++) {
585       EXPECT_LT(0u, gl_versions[i * 3]);
586       EXPECT_GE(4u, gl_versions[i * 3]);
587 
588       /* Verify that the minor version advertised with the major version makes
589        * sense.
590        */
591       switch (gl_versions[i * 3]) {
592       case 1:
593 	 EXPECT_GE(5u, gl_versions[i * 3 + 1]);
594 	 EXPECT_EQ(0u, gl_versions[i * 3 + 2]);
595 	 versions_below_3_0++;
596 	 break;
597       case 2:
598 	 EXPECT_GE(1u, gl_versions[i * 3 + 1]);
599 	 EXPECT_EQ(0u, gl_versions[i * 3 + 2]);
600 	 versions_below_3_0++;
601 	 break;
602       case 3:
603 	 EXPECT_GE(3u, gl_versions[i * 3 + 1]);
604 
605 	 /* Profiles were not introduced until OpenGL 3.2.
606 	  */
607 	 if (gl_versions[i * 3 + 1] < 2) {
608 	    EXPECT_EQ(0u, gl_versions[i * 3 + 2]);
609 	 } else {
610 	    EXPECT_EQ(0u, gl_versions[i * 3 + 2] & ~all_valid_bits);
611 	 }
612 	 break;
613       case 4:
614 	 EXPECT_GE(2u, gl_versions[i * 3 + 1]);
615 	 EXPECT_EQ(0u, gl_versions[i * 3 + 2] & ~all_valid_bits);
616 	 break;
617       }
618    }
619 
620    /* From the GLX_ARB_create_context_profile spec:
621     *
622     *     "Only the highest supported version below 3.0 should be sent, since
623     *     OpenGL 2.1 is backwards compatible with all earlier versions."
624     */
625    EXPECT_LE(versions_below_3_0, 1u);
626 }
627 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_1)628 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_1)
629 {
630    create_single_screen_display(1, 1, "");
631    __glX_send_client_info(this->glx_dpy);
632 
633    EXPECT_EQ(1, glx_major);
634    EXPECT_EQ(4, glx_minor);
635 }
636 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_4)637 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_4)
638 {
639    create_single_screen_display(1, 4, "");
640    __glX_send_client_info(this->glx_dpy);
641 
642    EXPECT_EQ(1, glx_major);
643    EXPECT_EQ(4, glx_minor);
644 }
645 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_4_with_ARB_create_context)646 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_4_with_ARB_create_context)
647 {
648    create_single_screen_display(1, 4, "GLX_ARB_create_context");
649    __glX_send_client_info(this->glx_dpy);
650 
651    EXPECT_EQ(1, glx_major);
652    EXPECT_EQ(4, glx_minor);
653 }
654 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_4_with_ARB_create_context_profile)655 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_4_with_ARB_create_context_profile)
656 {
657    create_single_screen_display(1, 4, "GLX_ARB_create_context_profile");
658    __glX_send_client_info(this->glx_dpy);
659 
660    EXPECT_EQ(1, glx_major);
661    EXPECT_EQ(4, glx_minor);
662 }
663 
TEST_F(glX_send_client_info_test,glx_version_is_1_4_for_1_5)664 TEST_F(glX_send_client_info_test, glx_version_is_1_4_for_1_5)
665 {
666    create_single_screen_display(1, 5, "");
667    __glX_send_client_info(this->glx_dpy);
668 
669    EXPECT_EQ(1, glx_major);
670    EXPECT_EQ(4, glx_minor);
671 }
672 
TEST_F(glX_send_client_info_test,glx_extensions_has_GLX_ARB_create_context)673 TEST_F(glX_send_client_info_test, glx_extensions_has_GLX_ARB_create_context)
674 {
675    create_single_screen_display(1, 4, "GLX_ARB_create_context");
676    __glX_send_client_info(this->glx_dpy);
677 
678    ASSERT_NE(0, glx_ext_length);
679    ASSERT_NE((char *) 0, glx_ext_string);
680 
681    bool found_GLX_ARB_create_context = false;
682    const char *const needle = "GLX_ARB_create_context";
683    const unsigned len = strlen(needle);
684    char *haystack = glx_ext_string;
685    while (haystack != NULL) {
686       char *match = strstr(haystack, needle);
687 
688       if (match[len] == '\0' || match[len] == ' ') {
689 	 found_GLX_ARB_create_context = true;
690 	 break;
691       }
692 
693       haystack = match + len;
694    }
695 
696    EXPECT_TRUE(found_GLX_ARB_create_context);
697 }
698 
TEST_F(glX_send_client_info_test,glx_extensions_has_GLX_ARB_create_context_profile)699 TEST_F(glX_send_client_info_test, glx_extensions_has_GLX_ARB_create_context_profile)
700 {
701    create_single_screen_display(1, 4, "GLX_ARB_create_context_profile");
702    __glX_send_client_info(this->glx_dpy);
703 
704    ASSERT_NE(0, glx_ext_length);
705    ASSERT_NE((char *) 0, glx_ext_string);
706 
707    bool found_GLX_ARB_create_context_profile = false;
708    const char *const needle = "GLX_ARB_create_context_profile";
709    const unsigned len = strlen(needle);
710    char *haystack = glx_ext_string;
711    while (haystack != NULL) {
712       char *match = strstr(haystack, needle);
713 
714       if (match[len] == '\0' || match[len] == ' ') {
715 	 found_GLX_ARB_create_context_profile = true;
716 	 break;
717       }
718 
719       haystack = match + len;
720    }
721 
722    EXPECT_TRUE(found_GLX_ARB_create_context_profile);
723 }
724