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