| 1 | #include <array_length.h> |
| 2 | #include <errno.h> |
| 3 | #include <stdio.h> |
| 4 | #include <support/check.h> |
| 5 | #include <sys/types.h> |
| 6 | #include <wchar.h> |
| 7 | |
| 8 | |
| 9 | static wchar_t buf[100]; |
| 10 | static const struct |
| 11 | { |
| 12 | size_t n; |
| 13 | const char *str; |
| 14 | ssize_t exp; |
| 15 | } tests[] = |
| 16 | { |
| 17 | { array_length (buf), "hello world" , 11 }, |
| 18 | { 0, "hello world" , -1 }, |
| 19 | { 1, "hello world" , -1 }, |
| 20 | { 2, "hello world" , -1 }, |
| 21 | { 11, "hello world" , -1 }, |
| 22 | { 12, "hello world" , 11 }, |
| 23 | { 0, "" , -1 }, |
| 24 | { array_length (buf), "" , 0 } |
| 25 | }; |
| 26 | |
| 27 | static int |
| 28 | do_test (void) |
| 29 | { |
| 30 | size_t n; |
| 31 | |
| 32 | TEST_COMPARE (swprintf (buf, array_length (buf), L"Hello %s" , "world" ), 11); |
| 33 | TEST_COMPARE_STRING_WIDE (buf, L"Hello world" ); |
| 34 | |
| 35 | TEST_COMPARE (swprintf (buf, array_length (buf), L"Is this >%g< 3.1?" , 3.1), |
| 36 | 18); |
| 37 | TEST_COMPARE_STRING_WIDE (buf, L"Is this >3.1< 3.1?" ); |
| 38 | |
| 39 | for (n = 0; n < array_length (tests); ++n) |
| 40 | { |
| 41 | wmemset (buf, 0xabcd, array_length (buf)); |
| 42 | errno = 0; |
| 43 | ssize_t res = swprintf (s: buf, n: tests[n].n, format: L"%s" , tests[n].str); |
| 44 | |
| 45 | if (tests[n].exp < 0 && res >= 0) |
| 46 | { |
| 47 | support_record_failure (); |
| 48 | printf (format: "swprintf (buf, %zu, L\"%%s\", \"%s\") expected to fail\n" , |
| 49 | tests[n].n, tests[n].str); |
| 50 | } |
| 51 | else if (tests[n].exp >= 0 && tests[n].exp != res) |
| 52 | { |
| 53 | support_record_failure (); |
| 54 | printf (format: "\ |
| 55 | swprintf (buf, %zu, L\"%%s\", \"%s\") expected to return %zd, but got %zd\n" , |
| 56 | tests[n].n, tests[n].str, tests[n].exp, res); |
| 57 | } |
| 58 | else if (res < 0 |
| 59 | && tests[n].n > 0 |
| 60 | && wcsnlen (s: buf, array_length (buf)) == array_length (buf)) |
| 61 | { |
| 62 | support_record_failure (); |
| 63 | printf (format: "\ |
| 64 | error: swprintf (buf, %zu, L\"%%s\", \"%s\") missing null terminator\n" , |
| 65 | tests[n].n, tests[n].str); |
| 66 | } |
| 67 | else if (res < 0 |
| 68 | && tests[n].n > 0 |
| 69 | && wcsnlen (s: buf, array_length (buf)) < array_length (buf) |
| 70 | && buf[wcsnlen (s: buf, array_length (buf)) + 1] != 0xabcd) |
| 71 | { |
| 72 | support_record_failure (); |
| 73 | printf (format: "\ |
| 74 | error: swprintf (buf, %zu, L\"%%s\", \"%s\") out of bounds write\n" , |
| 75 | tests[n].n, tests[n].str); |
| 76 | } |
| 77 | |
| 78 | if (res < 0 && tests[n].n < 0) |
| 79 | TEST_COMPARE (errno, E2BIG); |
| 80 | |
| 81 | printf (format: "swprintf (buf, %zu, L\"%%s\", \"%s\") OK\n" , |
| 82 | tests[n].n, tests[n].str); |
| 83 | } |
| 84 | |
| 85 | TEST_COMPARE (swprintf (buf, array_length (buf), L"%.0s" , "foo" ), 0); |
| 86 | TEST_COMPARE_STRING_WIDE (buf, L"" ); |
| 87 | |
| 88 | TEST_COMPARE (swprintf (buf, array_length (buf), L"%.0ls" , L"foo" ), 0); |
| 89 | TEST_COMPARE_STRING_WIDE (buf, L"" ); |
| 90 | |
| 91 | return 0; |
| 92 | } |
| 93 | |
| 94 | #include <support/test-driver.c> |
| 95 | |