1#include <check.h> 2#include <stdio.h> 3#include <string.h> 4#include <stdlib.h> 5#ifdef __unix__ 6#include <unistd.h> 7#endif 8#include "check_suites.h" 9#include "xcb.h" 10#include "xcbext.h" 11 12/* xcb_parse_display tests {{{ */ 13 14typedef enum test_type_t { 15 TEST_ARGUMENT, TEST_ENVIRONMENT, TEST_END 16} test_type_t; 17static const char *const test_string[] = { "", "via $DISPLAY " }; 18 19/* putenv(3) takes a pointer to a writable string that it adds directly 20 to the environment, so it must be in persistent memory, not on the stack */ 21static char display_env[] = "DISPLAY="; 22 23static void parse_display_pass(const char *name, const char *host, const int display, const int screen) 24{ 25 int success; 26 char *got_host; 27 int got_display, got_screen; 28 const char *argument = 0; 29 test_type_t test_type; 30 31 for(test_type = TEST_ARGUMENT; test_type != TEST_END; test_type++) 32 { 33 if(test_type == TEST_ARGUMENT) 34 { 35 argument = name; 36 putenv(display_env); 37 } 38 else if(test_type == TEST_ENVIRONMENT) 39 { 40 argument = 0; 41 setenv("DISPLAY", name, 1); 42 } 43 44 got_host = (char *) -1; 45 got_display = got_screen = -42; 46 mark_point(); 47 success = xcb_parse_display(argument, &got_host, &got_display, &got_screen); 48 ck_assert_msg(success, "unexpected parse failure %sfor '%s'", test_string[test_type], name); 49 ck_assert_msg(strcmp(host, got_host) == 0, "parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host); 50 ck_assert_msg(display == got_display, "parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display); 51 ck_assert_msg(screen == got_screen, "parse %sproduced unexpected screen '%d' for '%s': expected '%d'", test_string[test_type], got_screen, name, screen); 52 53 got_host = (char *) -1; 54 got_display = got_screen = -42; 55 mark_point(); 56 success = xcb_parse_display(argument, &got_host, &got_display, 0); 57 ck_assert_msg(success, "unexpected screenless parse failure %sfor '%s'", test_string[test_type], name); 58 ck_assert_msg(strcmp(host, got_host) == 0, "screenless parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host); 59 ck_assert_msg(display == got_display, "screenless parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display); 60 } 61 putenv(display_env); 62} 63 64static void parse_display_fail(const char *name) 65{ 66 int success; 67 char *got_host; 68 int got_display, got_screen; 69 const char *argument = 0; 70 test_type_t test_type; 71 72 for(test_type = TEST_ARGUMENT; test_type != TEST_END; test_type++) 73 { 74 if(test_type == TEST_ARGUMENT) 75 { 76 argument = name; 77 putenv(display_env); 78 } 79 else if(test_type == TEST_ENVIRONMENT) 80 { 81 if (!name) break; 82 argument = 0; 83 setenv("DISPLAY", name, 1); 84 } 85 86 got_host = (char *) -1; 87 got_display = got_screen = -42; 88 mark_point(); 89 success = xcb_parse_display(argument, &got_host, &got_display, &got_screen); 90 ck_assert_msg(!success, "unexpected parse success %sfor '%s'", test_string[test_type], name); 91 ck_assert_msg(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host); 92 ck_assert_msg(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display); 93 ck_assert_msg(got_screen == -42, "screen changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_screen); 94 95 got_host = (char *) -1; 96 got_display = got_screen = -42; 97 mark_point(); 98 success = xcb_parse_display(argument, &got_host, &got_display, 0); 99 ck_assert_msg(!success, "unexpected screenless parse success %sfor '%s'", test_string[test_type], name); 100 ck_assert_msg(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host); 101 ck_assert_msg(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display); 102 } 103 putenv(display_env); 104} 105 106START_TEST(parse_display_unix) 107{ 108#ifdef __unix__ 109 char buf[sizeof "/tmp/xcb-test.XXXXXXX"]; 110 char buf2[sizeof(buf) + 7]; 111 int r, v; 112 memcpy(buf, "/tmp/xcb-test.XXXXXXX", sizeof buf); 113 v = mkstemp(buf); 114 ck_assert_msg(v >= 0, "cannot create temporary file"); 115 parse_display_pass(buf, buf, 0, 0); 116 r = snprintf(buf2, sizeof buf2, "unix:%s", buf); 117 if (r < 5 || r >= (int)sizeof buf2) { 118 ck_assert_msg(0, "snprintf() failed (return value %d)", r); 119 unlink(buf); 120 return; 121 } 122 parse_display_pass(buf2, buf, 0, 0); 123 r = snprintf(buf2, sizeof buf2, "unix:%s.1", buf); 124 if (r < 7 || r >= (int)sizeof buf2) { 125 ck_assert_msg(0, "snprintf() failed (return value %d)", r); 126 unlink(buf); 127 return; 128 } 129 parse_display_pass(buf2, buf, 0, 1); 130 r = snprintf(buf2, sizeof buf2, "%s.1", buf); 131 if (r < 2 || r >= (int)sizeof buf2) { 132 ck_assert_msg(0, "snprintf() failed (return value %d)", r); 133 unlink(buf); 134 return; 135 } 136 parse_display_pass(buf2, buf, 0, 1); 137 unlink(buf); 138#endif 139 parse_display_pass(":0", "", 0, 0); 140 parse_display_pass(":1", "", 1, 0); 141 parse_display_pass(":0.1", "", 0, 1); 142} 143END_TEST 144 145START_TEST(parse_display_ip) 146{ 147 parse_display_pass("x.org:0", "x.org", 0, 0); 148 parse_display_pass("expo:0", "expo", 0, 0); 149 parse_display_pass("bigmachine:1", "bigmachine", 1, 0); 150 parse_display_pass("hydra:0.1", "hydra", 0, 1); 151} 152END_TEST 153 154START_TEST(parse_display_ipv4) 155{ 156 parse_display_pass("198.112.45.11:0", "198.112.45.11", 0, 0); 157 parse_display_pass("198.112.45.11:0.1", "198.112.45.11", 0, 1); 158} 159END_TEST 160 161START_TEST(parse_display_ipv6) 162{ 163 parse_display_pass(":::0", "::", 0, 0); 164 parse_display_pass("1:::0", "1::", 0, 0); 165 parse_display_pass("::1:0", "::1", 0, 0); 166 parse_display_pass("::1:0.1", "::1", 0, 1); 167 parse_display_pass("::127.0.0.1:0", "::127.0.0.1", 0, 0); 168 parse_display_pass("::ffff:127.0.0.1:0", "::ffff:127.0.0.1", 0, 0); 169 parse_display_pass("2002:83fc:d052::1:0", "2002:83fc:d052::1", 0, 0); 170 parse_display_pass("2002:83fc:d052::1:0.1", "2002:83fc:d052::1", 0, 1); 171 parse_display_pass("[::]:0", "[::]", 0, 0); 172 parse_display_pass("[1::]:0", "[1::]", 0, 0); 173 parse_display_pass("[::1]:0", "[::1]", 0, 0); 174 parse_display_pass("[::1]:0.1", "[::1]", 0, 1); 175 parse_display_pass("[::127.0.0.1]:0", "[::127.0.0.1]", 0, 0); 176 parse_display_pass("[::ffff:127.0.0.1]:0", "[::ffff:127.0.0.1]", 0, 0); 177 parse_display_pass("[2002:83fc:d052::1]:0", "[2002:83fc:d052::1]", 0, 0); 178 parse_display_pass("[2002:83fc:d052::1]:0.1", "[2002:83fc:d052::1]", 0, 1); 179} 180END_TEST 181 182START_TEST(parse_display_decnet) 183{ 184 parse_display_pass("myws::0", "myws:", 0, 0); 185 parse_display_pass("big::1", "big:", 1, 0); 186 parse_display_pass("hydra::0.1", "hydra:", 0, 1); 187} 188END_TEST 189 190START_TEST(parse_display_negative) 191{ 192 parse_display_fail(0); 193 parse_display_fail(""); 194 parse_display_fail(":"); 195 parse_display_fail("::"); 196 parse_display_fail(":::"); 197 parse_display_fail(":."); 198 parse_display_fail(":a"); 199 parse_display_fail(":a."); 200 parse_display_fail(":0."); 201 parse_display_fail(":.a"); 202 parse_display_fail(":.0"); 203 parse_display_fail(":0.a"); 204 parse_display_fail(":0.0."); 205 206 parse_display_fail("127.0.0.1"); 207 parse_display_fail("127.0.0.1:"); 208 parse_display_fail("127.0.0.1::"); 209 parse_display_fail("::127.0.0.1"); 210 parse_display_fail("::127.0.0.1:"); 211 parse_display_fail("::127.0.0.1::"); 212 parse_display_fail("::ffff:127.0.0.1"); 213 parse_display_fail("::ffff:127.0.0.1:"); 214 parse_display_fail("::ffff:127.0.0.1::"); 215 parse_display_fail("localhost"); 216 parse_display_fail("localhost:"); 217 parse_display_fail("localhost::"); 218} 219END_TEST 220 221/* }}} */ 222 223static void popcount_eq(uint32_t bits, int count) 224{ 225 ck_assert_msg(xcb_popcount(bits) == count, "unexpected popcount(%08x) != %d", bits, count); 226} 227 228START_TEST(popcount) 229{ 230 uint32_t mask; 231 int count; 232 233 for (mask = 0xffffffff, count = 32; count >= 0; mask >>= 1, --count) { 234 popcount_eq(mask, count); 235 } 236 for (mask = 0x80000000; mask; mask >>= 1) { 237 popcount_eq(mask, 1); 238 } 239 for (mask = 0x80000000; mask > 1; mask >>= 1) { 240 popcount_eq(mask | 1, 2); 241 } 242} 243END_TEST 244 245Suite *public_suite(void) 246{ 247 Suite *s = suite_create("Public API"); 248 putenv(display_env); 249 suite_add_test(s, parse_display_unix, "xcb_parse_display unix"); 250 suite_add_test(s, parse_display_ip, "xcb_parse_display ip"); 251 suite_add_test(s, parse_display_ipv4, "xcb_parse_display ipv4"); 252 suite_add_test(s, parse_display_ipv6, "xcb_parse_display ipv6"); 253 suite_add_test(s, parse_display_decnet, "xcb_parse_display decnet"); 254 suite_add_test(s, parse_display_negative, "xcb_parse_display negative"); 255 suite_add_test(s, popcount, "xcb_popcount"); 256 return s; 257} 258