Line data Source code
1 : // Copyright (c) 2011-2025 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/libaddr
4 : // contact@m2osw.com
5 : //
6 : // Permission is hereby granted, free of charge, to any
7 : // person obtaining a copy of this software and
8 : // associated documentation files (the "Software"), to
9 : // deal in the Software without restriction, including
10 : // without limitation the rights to use, copy, modify,
11 : // merge, publish, distribute, sublicense, and/or sell
12 : // copies of the Software, and to permit persons to whom
13 : // the Software is furnished to do so, subject to the
14 : // following conditions:
15 : //
16 : // The above copyright notice and this permission notice
17 : // shall be included in all copies or substantial
18 : // portions of the Software.
19 : //
20 : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
21 : // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 : // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23 : // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
24 : // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 : // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 : // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 : // ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 : // SOFTWARE.
30 :
31 :
32 : /** \file
33 : * \brief Test the Unix address.
34 : *
35 : * These tests verify that the Unix address functions as expected.
36 : */
37 :
38 : // addr
39 : //
40 : #include <libaddr/addr_unix.h>
41 :
42 :
43 : // self
44 : //
45 : #include "catch_main.h"
46 :
47 :
48 : // libutf8
49 : //
50 : #include <libutf8/libutf8.h>
51 : #include <libutf8/exception.h>
52 :
53 :
54 : // snapdev
55 : //
56 : #include <snapdev/raii_generic_deleter.h>
57 :
58 :
59 : // C
60 : //
61 : #include <sys/stat.h>
62 :
63 :
64 : // last include
65 : //
66 : #include <snapdev/poison.h>
67 :
68 :
69 :
70 :
71 :
72 :
73 :
74 5 : CATCH_TEST_CASE("addr_unix::unnamed", "[addr_unix]")
75 : {
76 5 : CATCH_START_SECTION("addr_unix::unnamed: addr_unix() defaults (a.k.a. unnamed address)")
77 : {
78 1 : addr::addr_unix u;
79 :
80 1 : CATCH_REQUIRE_FALSE(u.is_file());
81 1 : CATCH_REQUIRE_FALSE(u.is_abstract());
82 1 : CATCH_REQUIRE(u.is_unnamed());
83 1 : CATCH_REQUIRE(u.to_string() == std::string());
84 1 : CATCH_REQUIRE(u.to_uri() == "unix:");
85 :
86 1 : sockaddr_un un;
87 1 : u.get_un(un);
88 1 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
89 109 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
90 : {
91 108 : CATCH_CHECK(un.sun_path[idx] == 0);
92 : }
93 1 : }
94 5 : CATCH_END_SECTION()
95 :
96 5 : CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with an unnamed address")
97 : {
98 1 : sockaddr_un init = addr::init_un();
99 1 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
100 109 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
101 : {
102 108 : CATCH_CHECK(init.sun_path[idx] == 0);
103 : }
104 :
105 1 : addr::addr_unix u(init);
106 :
107 1 : CATCH_REQUIRE_FALSE(u.is_file());
108 1 : CATCH_REQUIRE_FALSE(u.is_abstract());
109 1 : CATCH_REQUIRE(u.is_unnamed());
110 1 : CATCH_REQUIRE(u.to_string() == std::string());
111 1 : CATCH_REQUIRE(u.to_uri() == "unix:");
112 :
113 1 : sockaddr_un un;
114 1 : u.get_un(un);
115 1 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
116 109 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
117 : {
118 108 : CATCH_CHECK(un.sun_path[idx] == 0);
119 : }
120 1 : }
121 5 : CATCH_END_SECTION()
122 :
123 5 : CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with an unnamed string")
124 : {
125 1 : std::string no_name;
126 1 : addr::addr_unix u(no_name);
127 :
128 1 : CATCH_REQUIRE_FALSE(u.is_file());
129 1 : CATCH_REQUIRE_FALSE(u.is_abstract());
130 1 : CATCH_REQUIRE(u.is_unnamed());
131 1 : CATCH_REQUIRE(u.to_string() == std::string());
132 1 : CATCH_REQUIRE(u.to_uri() == "unix:");
133 :
134 1 : sockaddr_un un;
135 1 : u.get_un(un);
136 1 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
137 109 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
138 : {
139 108 : CATCH_CHECK(un.sun_path[idx] == 0);
140 : }
141 1 : }
142 5 : CATCH_END_SECTION()
143 :
144 5 : CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with a forced unnamed URI")
145 : {
146 1 : addr::addr_unix u;
147 :
148 3 : u.set_uri("unix:?unnamed");
149 :
150 1 : CATCH_REQUIRE_FALSE(u.is_file());
151 1 : CATCH_REQUIRE_FALSE(u.is_abstract());
152 1 : CATCH_REQUIRE(u.is_unnamed());
153 1 : CATCH_REQUIRE(u.to_string() == std::string());
154 1 : CATCH_REQUIRE(u.to_uri() == "unix:");
155 1 : CATCH_REQUIRE(u.unlink() == 0);
156 :
157 1 : sockaddr_un un;
158 1 : u.get_un(un);
159 1 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
160 109 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
161 : {
162 108 : CATCH_CHECK(un.sun_path[idx] == 0);
163 : }
164 1 : }
165 5 : CATCH_END_SECTION()
166 :
167 5 : CATCH_START_SECTION("addr_unix::unnamed: addr_unix() with an unnamed which we re-collect from socket")
168 : {
169 1 : sockaddr_un un;
170 :
171 1 : addr::addr_unix u;
172 :
173 1 : CATCH_REQUIRE_FALSE(u.is_file());
174 1 : CATCH_REQUIRE_FALSE(u.is_abstract());
175 1 : CATCH_REQUIRE(u.is_unnamed());
176 1 : CATCH_REQUIRE(u.to_string() == std::string());
177 1 : CATCH_REQUIRE(u.to_uri() == "unix:");
178 :
179 1 : u.get_un(un);
180 1 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
181 109 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
182 : {
183 108 : CATCH_CHECK(un.sun_path[idx] == 0);
184 : }
185 :
186 1 : snapdev::raii_fd_t s(socket(AF_UNIX, SOCK_STREAM, 0));
187 1 : CATCH_REQUIRE(s != nullptr);
188 :
189 : // unnamed sockets are unbound...
190 :
191 1 : addr::addr_unix retrieve;
192 1 : retrieve.set_from_socket(s.get());
193 1 : CATCH_REQUIRE(retrieve == u);
194 1 : }
195 5 : CATCH_END_SECTION()
196 5 : }
197 :
198 :
199 7 : CATCH_TEST_CASE("addr_unix::file", "[addr_unix]")
200 : {
201 7 : CATCH_START_SECTION("addr_unix::file: addr_unix() with a relative file name")
202 : {
203 11 : for(int count(0); count < 10; ++count)
204 : {
205 30 : std::string name("test");
206 10 : int const max(rand() % 5 + 3);
207 60 : for(int id(0); id < max; ++id)
208 : {
209 50 : name += '0' + rand() % 10;
210 : }
211 :
212 : // verify the init_un() as we're at it
213 : //
214 10 : sockaddr_un init = addr::init_un();
215 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
216 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
217 : {
218 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
219 : }
220 10 : strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
221 :
222 10 : addr::addr_unix u(init);
223 :
224 10 : CATCH_REQUIRE(u.is_file());
225 10 : CATCH_REQUIRE_FALSE(u.is_abstract());
226 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
227 10 : CATCH_REQUIRE(u.to_string() == name);
228 10 : CATCH_REQUIRE(u.to_uri() == "unix:" + name);
229 :
230 10 : sockaddr_un un;
231 10 : u.get_un(un);
232 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
233 10 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
234 1000 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
235 : {
236 990 : CATCH_CHECK(un.sun_path[idx] == 0);
237 : }
238 10 : }
239 : }
240 7 : CATCH_END_SECTION()
241 :
242 7 : CATCH_START_SECTION("addr_unix::file: addr_unix() with a relative file name; string constructor")
243 : {
244 11 : for(int count(0); count < 10; ++count)
245 : {
246 30 : std::string name("test");
247 10 : int const max(rand() % 5 + 3);
248 59 : for(int id(0); id < max; ++id)
249 : {
250 49 : name += '0' + rand() % 10;
251 : }
252 :
253 10 : addr::addr_unix u(name);
254 :
255 10 : CATCH_REQUIRE(u.is_file());
256 10 : CATCH_REQUIRE_FALSE(u.is_abstract());
257 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
258 10 : CATCH_REQUIRE(u.to_string() == name);
259 10 : CATCH_REQUIRE(u.to_uri() == "unix:" + name);
260 :
261 10 : sockaddr_un un;
262 10 : u.get_un(un);
263 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
264 10 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
265 1001 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
266 : {
267 991 : CATCH_CHECK(un.sun_path[idx] == 0);
268 : }
269 10 : }
270 : }
271 7 : CATCH_END_SECTION()
272 :
273 7 : CATCH_START_SECTION("addr_unix::file: addr_unix() with a relative file name using set_file()")
274 : {
275 1 : addr::addr_unix u;
276 :
277 11 : for(int count(0); count < 10; ++count)
278 : {
279 30 : std::string name("test");
280 10 : int const max(rand() % 25 + 3); // vary more to correctly verify that we clear the end of the buffer
281 181 : for(int id(0); id < max; ++id)
282 : {
283 171 : name += '0' + rand() % 10;
284 : }
285 :
286 : // verify the init_un() as we're at it
287 : //
288 10 : sockaddr_un init = addr::init_un();
289 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
290 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
291 : {
292 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
293 : }
294 10 : strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
295 :
296 10 : u.set_file(name);
297 :
298 10 : CATCH_REQUIRE(u.is_file());
299 10 : CATCH_REQUIRE_FALSE(u.is_abstract());
300 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
301 10 : CATCH_REQUIRE(u.to_string() == name);
302 10 : CATCH_REQUIRE(u.to_uri() == "unix:" + name);
303 :
304 10 : sockaddr_un un;
305 10 : u.get_un(un);
306 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
307 10 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
308 879 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
309 : {
310 869 : CATCH_CHECK(un.sun_path[idx] == 0);
311 : }
312 10 : }
313 1 : }
314 7 : CATCH_END_SECTION()
315 :
316 7 : CATCH_START_SECTION("addr_unix::file: addr_unix() with a full file name")
317 : {
318 11 : for(int count(0); count < 10; ++count)
319 : {
320 30 : std::string name("/run/snapwebsites/sockets/test");
321 10 : int const max(rand() % 25 + 3);
322 166 : for(int id(0); id < max; ++id)
323 : {
324 156 : name += '0' + rand() % 10;
325 : }
326 :
327 : // verify the init_un() as we're at it
328 : //
329 10 : sockaddr_un init = addr::init_un();
330 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
331 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
332 : {
333 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
334 : }
335 10 : strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
336 :
337 10 : addr::addr_unix u(init);
338 :
339 10 : CATCH_REQUIRE(u.is_file());
340 10 : CATCH_REQUIRE_FALSE(u.is_abstract());
341 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
342 10 : CATCH_REQUIRE(u.to_string() == name);
343 10 : CATCH_REQUIRE(u.to_uri() == "unix://" + name);
344 :
345 10 : sockaddr_un un;
346 10 : u.get_un(un);
347 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
348 10 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
349 634 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
350 : {
351 624 : CATCH_CHECK(un.sun_path[idx] == 0);
352 : }
353 10 : }
354 : }
355 7 : CATCH_END_SECTION()
356 :
357 7 : CATCH_START_SECTION("addr_unix::file: addr_unix() with a long file name")
358 : {
359 1 : sockaddr_un un;
360 107 : for(int count(1); count < static_cast<int>(sizeof(un.sun_path) - 1); ++count)
361 : {
362 106 : std::string name;
363 5777 : for(int id(0); id < count; ++id)
364 : {
365 5671 : name += '0' + rand() % 10;
366 : }
367 :
368 106 : addr::addr_unix u(name);
369 :
370 106 : CATCH_REQUIRE(u.is_file());
371 106 : CATCH_REQUIRE_FALSE(u.is_abstract());
372 106 : CATCH_REQUIRE_FALSE(u.is_unnamed());
373 106 : CATCH_REQUIRE(u.to_string() == name);
374 106 : CATCH_REQUIRE(u.to_uri() == "unix:" + name);
375 :
376 106 : u.get_un(un);
377 106 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
378 106 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
379 5883 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
380 : {
381 5777 : CATCH_CHECK(un.sun_path[idx] == 0);
382 : }
383 106 : }
384 : }
385 7 : CATCH_END_SECTION()
386 :
387 7 : CATCH_START_SECTION("addr_unix::file: addr_unix() verify that file gets unlink()'ed")
388 : {
389 11 : for(int count(0); count < 10; ++count)
390 : {
391 30 : std::string name("test");
392 10 : int const max(rand() % 5 + 3);
393 53 : for(int id(0); id < max; ++id)
394 : {
395 43 : name += '0' + rand() % 10;
396 : }
397 :
398 : // verify the init_un() as we're at it
399 : //
400 10 : addr::addr_unix u(name);
401 :
402 30 : std::string cmd("touch ");
403 10 : cmd += name;
404 10 : CATCH_REQUIRE(system(cmd.c_str()) == 0);
405 :
406 10 : struct stat s;
407 10 : CATCH_REQUIRE(stat(name.c_str(), &s) == 0);
408 :
409 10 : CATCH_REQUIRE(u.unlink() == 0);
410 :
411 10 : CATCH_REQUIRE(stat(name.c_str(), &s) != 0);
412 10 : }
413 : }
414 7 : CATCH_END_SECTION()
415 :
416 7 : CATCH_START_SECTION("addr_unix::file: addr_unix() with a file name which we re-collect from socket")
417 : {
418 1 : sockaddr_un un;
419 :
420 3 : std::string name("socket-test");
421 1 : int count(rand() % 5 + 3);
422 4 : for(int id(0); id < count; ++id)
423 : {
424 3 : name += '0' + rand() % 10;
425 : }
426 1 : unlink(name.c_str());
427 :
428 1 : addr::addr_unix u(name);
429 :
430 1 : CATCH_REQUIRE(u.is_file());
431 1 : CATCH_REQUIRE_FALSE(u.is_abstract());
432 1 : CATCH_REQUIRE_FALSE(u.is_unnamed());
433 1 : CATCH_REQUIRE(u.to_string() == name);
434 1 : CATCH_REQUIRE(u.to_uri() == "unix:" + name);
435 :
436 1 : u.get_un(un);
437 1 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
438 1 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
439 95 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
440 : {
441 94 : CATCH_CHECK(un.sun_path[idx] == 0);
442 : }
443 :
444 1 : snapdev::raii_fd_t s(socket(AF_UNIX, SOCK_STREAM, 0));
445 1 : CATCH_REQUIRE(s != nullptr);
446 1 : sockaddr_un address;
447 1 : u.get_un(address);
448 1 : CATCH_REQUIRE(bind(s.get(), reinterpret_cast<sockaddr *>(&address), sizeof(address)) == 0);
449 :
450 1 : addr::addr_unix retrieve;
451 1 : retrieve.set_from_socket(s.get());
452 1 : CATCH_REQUIRE(retrieve == u);
453 1 : }
454 7 : CATCH_END_SECTION()
455 7 : }
456 :
457 :
458 6 : CATCH_TEST_CASE("addr_unix::abstract", "[addr_unix]")
459 : {
460 6 : CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a relative abstract name")
461 : {
462 11 : for(int count(0); count < 10; ++count)
463 : {
464 30 : std::string name("abstract/test");
465 10 : int const max(rand() % 25 + 3);
466 129 : for(int id(0); id < max; ++id)
467 : {
468 119 : name += '0' + rand() % 10;
469 : }
470 :
471 : // verify the init_un() as we're at it
472 : //
473 10 : sockaddr_un init = addr::init_un();
474 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
475 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
476 : {
477 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
478 : }
479 10 : strncpy(init.sun_path + 1, name.c_str(), sizeof(init.sun_path) - 2);
480 :
481 10 : addr::addr_unix u(init);
482 :
483 10 : CATCH_REQUIRE_FALSE(u.is_file());
484 10 : CATCH_REQUIRE(u.is_abstract());
485 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
486 10 : CATCH_REQUIRE(u.to_string() == name);
487 10 : CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
488 10 : CATCH_REQUIRE(u.unlink() == 0);
489 :
490 10 : sockaddr_un un;
491 10 : u.get_un(un);
492 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
493 10 : CATCH_REQUIRE(un.sun_path[0] == '\0');
494 10 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
495 831 : for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
496 : {
497 821 : CATCH_CHECK(un.sun_path[idx] == 0);
498 : }
499 10 : }
500 : }
501 6 : CATCH_END_SECTION()
502 :
503 6 : CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a relative abstract name with string constructor")
504 : {
505 11 : for(int count(0); count < 10; ++count)
506 : {
507 30 : std::string name("abstract/test");
508 10 : int const max(rand() % 25 + 3);
509 197 : for(int id(0); id < max; ++id)
510 : {
511 187 : name += '0' + rand() % 10;
512 : }
513 :
514 10 : addr::addr_unix u(name, true);
515 :
516 10 : CATCH_REQUIRE_FALSE(u.is_file());
517 10 : CATCH_REQUIRE(u.is_abstract());
518 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
519 10 : CATCH_REQUIRE(u.to_string() == name);
520 10 : CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
521 :
522 10 : sockaddr_un un;
523 10 : u.get_un(un);
524 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
525 10 : CATCH_REQUIRE(un.sun_path[0] == '\0');
526 10 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
527 763 : for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
528 : {
529 753 : CATCH_CHECK(un.sun_path[idx] == 0);
530 : }
531 10 : }
532 : }
533 6 : CATCH_END_SECTION()
534 :
535 6 : CATCH_START_SECTION("addr_unix::abstract: addr_unix() with an abstract name using set_abstract()")
536 : {
537 1 : addr::addr_unix u;
538 :
539 11 : for(int count(0); count < 10; ++count)
540 : {
541 30 : std::string name("test");
542 10 : int const max(rand() % 25 + 3); // vary more to correctly verify that we clear the end of the buffer
543 164 : for(int id(0); id < max; ++id)
544 : {
545 154 : name += '0' + rand() % 10;
546 : }
547 :
548 : // verify the init_un() as we're at it
549 : //
550 10 : sockaddr_un init = addr::init_un();
551 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
552 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
553 : {
554 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
555 : }
556 10 : strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
557 :
558 10 : u.set_abstract(name);
559 :
560 10 : CATCH_REQUIRE_FALSE(u.is_file());
561 10 : CATCH_REQUIRE(u.is_abstract());
562 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
563 10 : CATCH_REQUIRE(u.to_string() == name);
564 10 : CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
565 :
566 10 : sockaddr_un un;
567 10 : u.get_un(un);
568 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
569 10 : CATCH_REQUIRE(un.sun_path[0] == '\0');
570 10 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
571 886 : for(std::size_t idx(name.length() +1); idx < sizeof(un.sun_path); ++idx)
572 : {
573 876 : CATCH_CHECK(un.sun_path[idx] == 0);
574 : }
575 10 : }
576 1 : }
577 6 : CATCH_END_SECTION()
578 :
579 6 : CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a full abstract name")
580 : {
581 11 : for(int count(0); count < 10; ++count)
582 : {
583 30 : std::string name("/net/snapwebsites/settings/test");
584 10 : int const max(rand() % 25 + 3);
585 204 : for(int id(0); id < max; ++id)
586 : {
587 194 : name += '0' + rand() % 10;
588 : }
589 :
590 : // verify the init_un() as we're at it
591 : //
592 10 : sockaddr_un init = addr::init_un();
593 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
594 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
595 : {
596 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
597 : }
598 10 : strncpy(init.sun_path + 1, name.c_str(), sizeof(init.sun_path) - 2);
599 :
600 10 : addr::addr_unix u(init);
601 :
602 10 : CATCH_REQUIRE_FALSE(u.is_file());
603 10 : CATCH_REQUIRE(u.is_abstract());
604 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
605 10 : CATCH_REQUIRE(u.to_string() == name);
606 10 : CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
607 :
608 10 : sockaddr_un un;
609 10 : u.get_un(un);
610 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
611 10 : CATCH_REQUIRE(un.sun_path[0] == '\0');
612 10 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
613 576 : for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
614 : {
615 566 : CATCH_CHECK(un.sun_path[idx] == 0);
616 : }
617 10 : }
618 : }
619 6 : CATCH_END_SECTION()
620 :
621 6 : CATCH_START_SECTION("addr_unix::abstract: addr_unix() with a long abstract name")
622 : {
623 1 : sockaddr_un un;
624 106 : for(int count(1); count < static_cast<int>(sizeof(un.sun_path) - 2); ++count)
625 : {
626 105 : std::string name;
627 5670 : for(int id(0); id < count; ++id)
628 : {
629 5565 : name += '0' + rand() % 10;
630 : }
631 :
632 105 : addr::addr_unix u(name, true);
633 :
634 105 : CATCH_REQUIRE_FALSE(u.is_file());
635 105 : CATCH_REQUIRE(u.is_abstract());
636 105 : CATCH_REQUIRE_FALSE(u.is_unnamed());
637 105 : CATCH_REQUIRE(u.to_string() == name);
638 105 : CATCH_REQUIRE(u.to_uri() == "unix:" + name + "?abstract");
639 :
640 105 : u.get_un(un);
641 105 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
642 105 : CATCH_REQUIRE(un.sun_path[0] == '\0');
643 105 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
644 5775 : for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
645 : {
646 5670 : CATCH_CHECK(un.sun_path[idx] == 0);
647 : }
648 105 : }
649 : }
650 6 : CATCH_END_SECTION()
651 :
652 6 : CATCH_START_SECTION("addr_unix::abstract: addr_unix() with an abstract name which we re-collect from socket")
653 : {
654 1 : sockaddr_un un;
655 :
656 3 : std::string name("/net/snapwebsites/test");
657 1 : int count(rand() % 5 + 3);
658 7 : for(int id(0); id < count; ++id)
659 : {
660 6 : name += '0' + rand() % 10;
661 : }
662 :
663 1 : addr::addr_unix u(name, true);
664 :
665 1 : CATCH_REQUIRE_FALSE(u.is_file());
666 1 : CATCH_REQUIRE(u.is_abstract());
667 1 : CATCH_REQUIRE_FALSE(u.is_unnamed());
668 1 : CATCH_REQUIRE(u.to_string() == name);
669 1 : CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
670 :
671 1 : u.get_un(un);
672 1 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
673 1 : CATCH_REQUIRE(un.sun_path[0] == '\0');
674 1 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
675 80 : for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
676 : {
677 79 : CATCH_CHECK(un.sun_path[idx] == 0);
678 : }
679 :
680 1 : snapdev::raii_fd_t s(socket(AF_UNIX, SOCK_STREAM, 0));
681 1 : CATCH_REQUIRE(s != nullptr);
682 1 : sockaddr_un address;
683 1 : u.get_un(address);
684 1 : socklen_t const len(sizeof(address.sun_family) + 1 + strlen(address.sun_path + 1));
685 1 : CATCH_REQUIRE(bind(s.get(), reinterpret_cast<sockaddr *>(&address), len) == 0);
686 :
687 1 : addr::addr_unix retrieve;
688 1 : retrieve.set_from_socket(s.get());
689 1 : CATCH_REQUIRE(retrieve == u);
690 1 : }
691 6 : CATCH_END_SECTION()
692 6 : }
693 :
694 :
695 2 : CATCH_TEST_CASE("addr_unix::compare", "[addr_unix]")
696 : {
697 2 : CATCH_START_SECTION("addr_unix::compare: two addr_unix() to compare with ==, !=, <, <=, >, >=")
698 : {
699 1 : addr::addr_unix a;
700 1 : addr::addr_unix b;
701 :
702 1 : CATCH_REQUIRE(a == b);
703 1 : CATCH_REQUIRE_FALSE(a != b);
704 1 : CATCH_REQUIRE_FALSE(a < b);
705 1 : CATCH_REQUIRE(a <= b);
706 1 : CATCH_REQUIRE_FALSE(a > b);
707 1 : CATCH_REQUIRE(a >= b);
708 :
709 3 : a.set_uri("unix:flowers");
710 3 : b.set_uri("unix:oranges");
711 :
712 1 : CATCH_REQUIRE_FALSE(a == b);
713 1 : CATCH_REQUIRE(a != b);
714 1 : CATCH_REQUIRE(a < b);
715 1 : CATCH_REQUIRE(a <= b);
716 1 : CATCH_REQUIRE_FALSE(a > b);
717 1 : CATCH_REQUIRE_FALSE(a >= b);
718 :
719 1 : std::swap(a, b);
720 :
721 1 : CATCH_REQUIRE_FALSE(a == b);
722 1 : CATCH_REQUIRE(a != b);
723 1 : CATCH_REQUIRE_FALSE(a < b);
724 1 : CATCH_REQUIRE_FALSE(a <= b);
725 1 : CATCH_REQUIRE(a > b);
726 1 : CATCH_REQUIRE(a >= b);
727 1 : }
728 2 : CATCH_END_SECTION()
729 :
730 2 : CATCH_START_SECTION("addr_unix::compare: two sockaddr_un to compare with ==, !=, <, <=, >, >=")
731 : {
732 1 : sockaddr_un a = addr::init_un();
733 1 : sockaddr_un b = addr::init_un();
734 :
735 1 : CATCH_REQUIRE(a == b);
736 1 : CATCH_REQUIRE_FALSE(a != b);
737 1 : CATCH_REQUIRE_FALSE(a < b);
738 1 : CATCH_REQUIRE(a <= b);
739 1 : CATCH_REQUIRE_FALSE(a > b);
740 1 : CATCH_REQUIRE(a >= b);
741 :
742 1 : strncpy(a.sun_path, "unix:flowers", sizeof(a.sun_path) - 1);
743 1 : strncpy(b.sun_path, "unix:oranges", sizeof(a.sun_path) - 1);
744 :
745 1 : CATCH_REQUIRE_FALSE(a == b);
746 1 : CATCH_REQUIRE(a != b);
747 1 : CATCH_REQUIRE(a < b);
748 1 : CATCH_REQUIRE(a <= b);
749 1 : CATCH_REQUIRE_FALSE(a > b);
750 1 : CATCH_REQUIRE_FALSE(a >= b);
751 :
752 1 : std::swap(a, b);
753 :
754 1 : CATCH_REQUIRE_FALSE(a == b);
755 1 : CATCH_REQUIRE(a != b);
756 1 : CATCH_REQUIRE_FALSE(a < b);
757 1 : CATCH_REQUIRE_FALSE(a <= b);
758 1 : CATCH_REQUIRE(a > b);
759 1 : CATCH_REQUIRE(a >= b);
760 : }
761 2 : CATCH_END_SECTION()
762 2 : }
763 :
764 :
765 3 : CATCH_TEST_CASE("addr_unix::mix", "[addr_unix]")
766 : {
767 3 : CATCH_START_SECTION("addr_unix::mix: addr_unix() with a relative file name then unnamed")
768 : {
769 11 : for(int count(0); count < 10; ++count)
770 : {
771 30 : std::string name("test");
772 10 : int const max(rand() % 5 + 3);
773 58 : for(int id(0); id < max; ++id)
774 : {
775 48 : name += '0' + rand() % 10;
776 : }
777 :
778 : // verify the init_un() as we're at it
779 : //
780 10 : sockaddr_un init = addr::init_un();
781 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
782 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
783 : {
784 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
785 : }
786 10 : strncpy(init.sun_path, name.c_str(), sizeof(init.sun_path) - 1);
787 :
788 10 : addr::addr_unix u(init);
789 :
790 10 : CATCH_REQUIRE(u.is_file());
791 10 : CATCH_REQUIRE_FALSE(u.is_abstract());
792 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
793 10 : CATCH_REQUIRE(u.to_string() == name);
794 10 : CATCH_REQUIRE(u.to_uri() == "unix:" + name);
795 :
796 10 : sockaddr_un un;
797 10 : u.get_un(un);
798 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
799 10 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
800 1002 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
801 : {
802 992 : CATCH_CHECK(un.sun_path[idx] == 0);
803 : }
804 :
805 10 : u.make_unnamed();
806 :
807 10 : CATCH_REQUIRE_FALSE(u.is_file());
808 10 : CATCH_REQUIRE_FALSE(u.is_abstract());
809 10 : CATCH_REQUIRE(u.is_unnamed());
810 10 : CATCH_REQUIRE(u.to_string() == std::string());
811 10 : CATCH_REQUIRE(u.to_uri() == "unix:");
812 :
813 10 : u.get_un(un);
814 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
815 1090 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
816 : {
817 1080 : CATCH_CHECK(un.sun_path[idx] == 0);
818 : }
819 10 : }
820 : }
821 3 : CATCH_END_SECTION()
822 :
823 3 : CATCH_START_SECTION("addr_unix::mix: addr_unix() with a full abstract name then unnamed")
824 : {
825 11 : for(int count(0); count < 10; ++count)
826 : {
827 30 : std::string name("/net/snapwebsites/settings/test");
828 10 : int const max(rand() % 25 + 3);
829 134 : for(int id(0); id < max; ++id)
830 : {
831 124 : name += '0' + rand() % 10;
832 : }
833 :
834 : // verify the init_un() as we're at it
835 : //
836 10 : sockaddr_un init = addr::init_un();
837 10 : CATCH_REQUIRE(init.sun_family == AF_UNIX);
838 1090 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
839 : {
840 1080 : CATCH_CHECK(init.sun_path[idx] == 0);
841 : }
842 10 : strncpy(init.sun_path + 1, name.c_str(), sizeof(init.sun_path) - 2);
843 :
844 10 : addr::addr_unix u(init);
845 :
846 10 : CATCH_REQUIRE_FALSE(u.is_file());
847 10 : CATCH_REQUIRE(u.is_abstract());
848 10 : CATCH_REQUIRE_FALSE(u.is_unnamed());
849 10 : CATCH_REQUIRE(u.to_string() == name);
850 10 : CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
851 :
852 10 : sockaddr_un un;
853 10 : u.get_un(un);
854 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
855 10 : CATCH_REQUIRE(un.sun_path[0] == '\0');
856 10 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
857 646 : for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
858 : {
859 636 : CATCH_CHECK(un.sun_path[idx] == 0);
860 : }
861 :
862 10 : u.make_unnamed();
863 :
864 10 : CATCH_REQUIRE_FALSE(u.is_file());
865 10 : CATCH_REQUIRE_FALSE(u.is_abstract());
866 10 : CATCH_REQUIRE(u.is_unnamed());
867 10 : CATCH_REQUIRE(u.to_string() == std::string());
868 10 : CATCH_REQUIRE(u.to_uri() == "unix:");
869 :
870 10 : u.get_un(un);
871 10 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
872 1090 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
873 : {
874 1080 : CATCH_CHECK(un.sun_path[idx] == 0);
875 : }
876 10 : }
877 : }
878 3 : CATCH_END_SECTION()
879 :
880 3 : CATCH_START_SECTION("addr_unix::mix: addr_unix() with various set_uri()")
881 : {
882 1 : addr::addr_unix u;
883 :
884 223 : for(int count(0); count < 222; ++count)
885 : {
886 222 : int type(count % 3);
887 :
888 222 : std::string name;
889 222 : if(type != 2)
890 : {
891 148 : name = "/run/snapwebsites/sockets/test";
892 148 : int const max(rand() % 25 + 3);
893 148 : switch(rand() % 4)
894 : {
895 36 : case 0:
896 36 : break;
897 :
898 35 : case 1:
899 35 : name += '-';
900 35 : break;
901 :
902 44 : case 2:
903 44 : name += '+';
904 44 : break;
905 :
906 33 : case 3:
907 33 : name += '.';
908 33 : break;
909 :
910 0 : default:
911 0 : throw std::runtime_error("unexpected case");
912 :
913 : }
914 2422 : for(int id(0); id < max; ++id)
915 : {
916 2274 : name += '0' + rand() % 10;
917 : }
918 : }
919 :
920 222 : bool force(count % 6 != type);
921 :
922 222 : sockaddr_un un;
923 222 : switch(count % 3)
924 : {
925 74 : case 0:
926 74 : u.set_uri("unix://" + name + (force ? "?file" : ""));
927 :
928 74 : CATCH_REQUIRE(u.is_file());
929 74 : CATCH_REQUIRE_FALSE(u.is_abstract());
930 74 : CATCH_REQUIRE_FALSE(u.is_unnamed());
931 74 : CATCH_REQUIRE(u.to_string() == name);
932 74 : CATCH_REQUIRE(u.to_uri() == "unix://" + name);
933 :
934 74 : u.get_un(un);
935 74 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
936 74 : CATCH_REQUIRE(strcmp(un.sun_path, name.c_str()) == 0);
937 4657 : for(std::size_t idx(name.length()); idx < sizeof(un.sun_path); ++idx)
938 : {
939 4583 : CATCH_CHECK(un.sun_path[idx] == 0);
940 : }
941 74 : break;
942 :
943 74 : case 1:
944 74 : u.set_uri("unix://" + name + "?abstract");
945 :
946 74 : CATCH_REQUIRE_FALSE(u.is_file());
947 74 : CATCH_REQUIRE(u.is_abstract());
948 74 : CATCH_REQUIRE_FALSE(u.is_unnamed());
949 74 : CATCH_REQUIRE(u.to_string() == name);
950 74 : CATCH_REQUIRE(u.to_uri() == "unix://" + name + "?abstract");
951 :
952 74 : u.get_un(un);
953 74 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
954 74 : CATCH_REQUIRE(un.sun_path[0] == '\0');
955 74 : CATCH_REQUIRE(strcmp(un.sun_path + 1, name.c_str()) == 0);
956 4575 : for(std::size_t idx(name.length() + 1); idx < sizeof(un.sun_path); ++idx)
957 : {
958 4501 : CATCH_CHECK(un.sun_path[idx] == 0);
959 : }
960 74 : break;
961 :
962 74 : case 2:
963 222 : u.set_uri(force ? "unix:?unnamed" : "unix:");
964 :
965 74 : CATCH_REQUIRE_FALSE(u.is_file());
966 74 : CATCH_REQUIRE_FALSE(u.is_abstract());
967 74 : CATCH_REQUIRE(u.is_unnamed());
968 74 : CATCH_REQUIRE(u.to_string() == std::string());
969 74 : CATCH_REQUIRE(u.to_uri() == "unix:");
970 :
971 74 : u.get_un(un);
972 74 : CATCH_REQUIRE(un.sun_family == AF_UNIX);
973 8066 : for(std::size_t idx(0); idx < sizeof(un.sun_path); ++idx)
974 : {
975 7992 : CATCH_CHECK(un.sun_path[idx] == 0);
976 : }
977 74 : break;
978 :
979 : }
980 222 : }
981 1 : }
982 3 : CATCH_END_SECTION()
983 3 : }
984 :
985 :
986 2 : CATCH_TEST_CASE("addr_unix::owner", "[addr_unix]")
987 : {
988 2 : CATCH_START_SECTION("addr_unix::owner: addr_unix() check group")
989 : {
990 1 : addr::addr_unix u;
991 :
992 11 : for(int count(0); count < 10; ++count)
993 : {
994 30 : std::string name("grp");
995 10 : int const max(rand() % 5 + 3);
996 57 : for(int id(0); id < max; ++id)
997 : {
998 47 : name += '0' + rand() % 10;
999 : }
1000 10 : u.set_group(name);
1001 10 : CATCH_REQUIRE(u.get_group() == name);
1002 10 : }
1003 1 : }
1004 2 : CATCH_END_SECTION()
1005 :
1006 2 : CATCH_START_SECTION("addr_unix::owner: addr_unix() check mode")
1007 : {
1008 1 : addr::addr_unix u;
1009 :
1010 1024 : for(int m(0); m < 01777; ++m)
1011 : {
1012 1023 : u.set_mode(m);
1013 1023 : CATCH_REQUIRE(u.get_mode() == m);
1014 : }
1015 1 : }
1016 2 : CATCH_END_SECTION()
1017 2 : }
1018 :
1019 :
1020 14 : CATCH_TEST_CASE("addr_unix::invalid", "[addr_unix]")
1021 : {
1022 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with an invalid address family")
1023 : {
1024 52 : for(int family(-25); family <= 25; ++family)
1025 : {
1026 51 : if(family == AF_UNIX)
1027 : {
1028 1 : continue;
1029 : }
1030 :
1031 50 : sockaddr_un init = addr::init_un();
1032 50 : init.sun_family = family;
1033 :
1034 : // constructor
1035 : //
1036 100 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(init), addr::addr_invalid_structure);
1037 :
1038 : // set_un()
1039 : //
1040 50 : addr::addr_unix u;
1041 50 : CATCH_REQUIRE_THROWS_AS(u.set_un(init), addr::addr_invalid_structure);
1042 50 : }
1043 : }
1044 14 : CATCH_END_SECTION()
1045 :
1046 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with an unnamed string but marked abstract")
1047 : {
1048 4 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(std::string(), true), addr::addr_invalid_argument);
1049 : }
1050 14 : CATCH_END_SECTION()
1051 :
1052 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a URI but a missing path")
1053 : {
1054 1 : addr::addr_unix u;
1055 5 : CATCH_REQUIRE_THROWS_AS(u.set_uri("unix://"), addr::addr_invalid_argument);
1056 1 : }
1057 14 : CATCH_END_SECTION()
1058 :
1059 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a URI but a missing scheme")
1060 : {
1061 1 : addr::addr_unix u;
1062 5 : CATCH_REQUIRE_THROWS_AS(u.set_uri("://address"), addr::addr_invalid_argument);
1063 1 : }
1064 14 : CATCH_END_SECTION()
1065 :
1066 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a URI but an invalid scheme")
1067 : {
1068 1 : addr::addr_unix u;
1069 :
1070 7 : CATCH_REQUIRE_THROWS_MATCHES(
1071 : u.set_uri("bad(scheme)://address")
1072 : , addr::addr_invalid_argument
1073 : , Catch::Matchers::ExceptionMessage("addr_error: \"bad(scheme)\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
1074 :
1075 7 : CATCH_REQUIRE_THROWS_MATCHES(
1076 : u.set_uri("other;scheme://address")
1077 : , addr::addr_invalid_argument
1078 : , Catch::Matchers::ExceptionMessage("addr_error: \"other;scheme\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
1079 :
1080 7 : CATCH_REQUIRE_THROWS_MATCHES(
1081 : u.set_uri("unknown|scheme://address")
1082 : , addr::addr_invalid_argument
1083 : , Catch::Matchers::ExceptionMessage("addr_error: \"unknown|scheme\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
1084 1 : }
1085 14 : CATCH_END_SECTION()
1086 :
1087 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with too long a file name")
1088 : {
1089 : sockaddr_un un;
1090 12 : for(int count(static_cast<int>(sizeof(un.sun_path)));
1091 12 : count < static_cast<int>(sizeof(un.sun_path) + 11);
1092 : ++count)
1093 : {
1094 11 : std::string name;
1095 1254 : for(int id(0); id < count; ++id)
1096 : {
1097 1243 : name += '0' + rand() % 10;
1098 : }
1099 :
1100 22 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), addr::addr_invalid_argument);
1101 :
1102 11 : addr::addr_unix u;
1103 33 : CATCH_REQUIRE_THROWS_AS(u.set_uri("unix:" + name), addr::addr_invalid_argument);
1104 11 : }
1105 : }
1106 14 : CATCH_END_SECTION()
1107 :
1108 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with too long an abstract name")
1109 : {
1110 : sockaddr_un un;
1111 12 : for(int count(static_cast<int>(sizeof(un.sun_path) - 1));
1112 12 : count < static_cast<int>(sizeof(un.sun_path) + 10);
1113 : ++count)
1114 : {
1115 11 : std::string name;
1116 1243 : for(int id(0); id < count; ++id)
1117 : {
1118 1232 : name += '0' + rand() % 10;
1119 : }
1120 :
1121 22 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name, true), addr::addr_invalid_argument);
1122 :
1123 11 : addr::addr_unix u;
1124 55 : CATCH_REQUIRE_THROWS_AS(u.set_uri("unix:" + name + "?abstract"), addr::addr_invalid_argument);
1125 11 : }
1126 : }
1127 14 : CATCH_END_SECTION()
1128 :
1129 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a long filename (missing '\\0')")
1130 : {
1131 1 : sockaddr_un init = addr::init_un();
1132 109 : for(std::size_t idx(0); idx < sizeof(init.sun_path); ++idx)
1133 : {
1134 108 : init.sun_path[idx] = '0' + rand() % 10;
1135 : }
1136 :
1137 : // constructor
1138 : //
1139 2 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(init), addr::addr_invalid_argument);
1140 :
1141 : // set_un()
1142 : //
1143 1 : addr::addr_unix u;
1144 1 : CATCH_REQUIRE_THROWS_AS(u.set_un(init), addr::addr_invalid_argument);
1145 1 : }
1146 14 : CATCH_END_SECTION()
1147 :
1148 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a long abstract name (missing '\\0')")
1149 : {
1150 1 : sockaddr_un init = addr::init_un();
1151 108 : for(std::size_t idx(1); idx < sizeof(init.sun_path); ++idx)
1152 : {
1153 107 : init.sun_path[idx] = '0' + rand() % 10;
1154 : }
1155 :
1156 : // constructor
1157 : //
1158 2 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(init), addr::addr_invalid_argument);
1159 :
1160 : // set_un()
1161 : //
1162 1 : addr::addr_unix u;
1163 1 : CATCH_REQUIRE_THROWS_AS(u.set_un(init), addr::addr_invalid_argument);
1164 1 : }
1165 14 : CATCH_END_SECTION()
1166 :
1167 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with a long abstract name (missing '\\0')")
1168 : {
1169 1 : addr::addr_unix u;
1170 :
1171 : // missing ":"
1172 : //
1173 7 : CATCH_REQUIRE_THROWS_MATCHES(
1174 : u.set_uri("cu/run/snapwebsites/sockets")
1175 : , addr::addr_invalid_argument
1176 : , Catch::Matchers::ExceptionMessage("addr_error: invalid URI for a Unix address, scheme not found (':' missing)."));
1177 :
1178 : // "?alexis"
1179 : //
1180 7 : CATCH_REQUIRE_THROWS_MATCHES(
1181 : u.set_uri("unix:/run/snapwebsites/sockets?alexis")
1182 : , addr::addr_invalid_argument
1183 : , Catch::Matchers::ExceptionMessage("addr_error: \"alexis\" is not a supported URI query string for a Unix address; supported query strings are one of: \"unnamed\", \"file\" and \"abstract\"."));
1184 :
1185 : // "_test:"
1186 : //
1187 7 : CATCH_REQUIRE_THROWS_MATCHES(
1188 : u.set_uri("_test:/run/snapwebsites/sockets?abstract")
1189 : , addr::addr_invalid_argument
1190 : , Catch::Matchers::ExceptionMessage("addr_error: \"_test\" is not a supported URI scheme for a Unix address; supported scheme are limited to `[a-zA-Z][-+.a-zA-Z0-9]*`."));
1191 :
1192 : // name with "?unnamed"
1193 : //
1194 7 : CATCH_REQUIRE_THROWS_MATCHES(
1195 : u.set_uri("cd:not-empty?unnamed")
1196 : , addr::addr_invalid_argument
1197 : , Catch::Matchers::ExceptionMessage("addr_error: address \"not-empty\" must be empty to represent an unnamed Unix address."));
1198 1 : }
1199 14 : CATCH_END_SECTION()
1200 :
1201 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with invalid characters (controls)")
1202 : {
1203 32 : for(int c(1); c < 0x20; ++c)
1204 : {
1205 31 : std::string name;
1206 31 : name += c;
1207 62 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), addr::addr_invalid_argument);
1208 31 : }
1209 :
1210 34 : for(int c(0x7F); c < 0xA0; ++c)
1211 : {
1212 33 : std::u32string u32;
1213 33 : u32 += c;
1214 33 : std::string name(libutf8::to_u8string(u32));
1215 66 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), addr::addr_invalid_argument);
1216 33 : }
1217 : }
1218 14 : CATCH_END_SECTION()
1219 :
1220 14 : CATCH_START_SECTION("addr_unix::invalid: addr_unix() with invalid UTF-8 characters")
1221 : {
1222 1 : std::string name;
1223 11 : for(int c(0); c < 10; ++c)
1224 : {
1225 10 : name += static_cast<char>(0x80);
1226 : }
1227 2 : CATCH_REQUIRE_THROWS_AS(addr::addr_unix(name), libutf8::libutf8_exception_decoding);
1228 1 : }
1229 14 : CATCH_END_SECTION()
1230 :
1231 14 : CATCH_START_SECTION("addr_unix::invalid: get addr_unix() of socket set to -1")
1232 : {
1233 1 : addr::addr_unix u;
1234 1 : bool const result(u.set_from_socket(-1));
1235 1 : int const e(errno);
1236 1 : CATCH_REQUIRE_FALSE(result);
1237 1 : CATCH_REQUIRE(e == EBADF);
1238 1 : }
1239 14 : CATCH_END_SECTION()
1240 :
1241 14 : CATCH_START_SECTION("addr_unix::invalid: get addr_unix() of socket set to UDP")
1242 : {
1243 10 : addr::addr udp(addr::string_to_addr(
1244 : "127.0.0.1:3999"
1245 : , "127.0.0.1"
1246 : , 3999
1247 7 : , "udp"));
1248 1 : snapdev::raii_fd_t s(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
1249 1 : CATCH_REQUIRE(s != nullptr);
1250 1 : sockaddr_in in;
1251 1 : udp.get_ipv4(in);
1252 1 : CATCH_REQUIRE(bind(s.get(), reinterpret_cast<sockaddr *>(&in), sizeof(in)) == 0);
1253 :
1254 1 : addr::addr_unix u;
1255 1 : bool const result(u.set_from_socket(s.get()));
1256 1 : int const e(errno);
1257 1 : CATCH_REQUIRE_FALSE(result);
1258 1 : CATCH_REQUIRE(e == EADDRNOTAVAIL);
1259 1 : }
1260 14 : CATCH_END_SECTION()
1261 14 : }
1262 :
1263 :
1264 : // vim: ts=4 sw=4 et
|