diff options
Diffstat (limited to 'wsutil/test_wsutil.c')
-rw-r--r-- | wsutil/test_wsutil.c | 881 |
1 files changed, 881 insertions, 0 deletions
diff --git a/wsutil/test_wsutil.c b/wsutil/test_wsutil.c new file mode 100644 index 00000000..ff9e2f82 --- /dev/null +++ b/wsutil/test_wsutil.c @@ -0,0 +1,881 @@ +/* + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <stdio.h> +#include <glib.h> +#include <wsutil/utf8_entities.h> +#include <wsutil/time_util.h> + +#include "inet_addr.h" + +static void test_inet_pton4_test1(void) +{ + const char *str; + bool ok; + ws_in4_addr result, expect; + + str = "198.51.100.200"; + expect = g_htonl(3325256904); + ok = ws_inet_pton4(str, &result); + g_assert_true(ok); + g_assert_cmpint(result, ==, expect); +} + +static void test_inet_ntop4_test1(void) +{ + char result[WS_INET_ADDRSTRLEN]; + const char *expect, *ptr; + ws_in4_addr addr; + + addr = g_htonl(3325256904); + expect = "198.51.100.200"; + ptr = ws_inet_ntop4(&addr, result, sizeof(result)); + g_assert_true(ptr == result); + g_assert_cmpstr(result, ==, expect); +} + +struct in6_test { + char str[WS_INET6_ADDRSTRLEN]; + ws_in6_addr addr; +}; + +static struct in6_test in6_test1 = { + .str = "2001:db8:ffaa:ddbb:1199:2288:3377:1", + .addr = { { 0x20, 0x01, 0x0d, 0xb8, 0xff, 0xaa, 0xdd, 0xbb, + 0x11, 0x99, 0x22, 0x88, 0x33, 0x77, 0x00, 0x01 } } +}; + +static void test_inet_pton6_test1(void) +{ + bool ok; + ws_in6_addr result; + + ok = ws_inet_pton6(in6_test1.str, &result); + g_assert_true(ok); + g_assert_cmpmem(&result, sizeof(result), &in6_test1.addr, sizeof(in6_test1.addr)); +} + +static void test_inet_ntop6_test1(void) +{ + char result[WS_INET6_ADDRSTRLEN]; + const char *ptr; + + ptr = ws_inet_ntop6(&in6_test1.addr, result, sizeof(result)); + g_assert_true(ptr == result); + g_assert_cmpstr(result, ==, in6_test1.str); +} + +#include "str_util.h" + +static void test_format_size(void) +{ + char *str; + + str = format_size(10000, FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_SI); + g_assert_cmpstr(str, ==, "10 kB"); + g_free(str); + + str = format_size(100000, FORMAT_SIZE_UNIT_BYTES, FORMAT_SIZE_PREFIX_IEC); + g_assert_cmpstr(str, ==, "97 KiB"); + g_free(str); + + str = format_size(20971520, FORMAT_SIZE_UNIT_BITS, FORMAT_SIZE_PREFIX_IEC); + g_assert_cmpstr(str, ==, "20 Mib"); + g_free(str); +} + +static void test_escape_string(void) +{ + char *buf; + + buf = ws_escape_string(NULL, "quoted \"\\\" backslash", true); + g_assert_cmpstr(buf, ==, "\"quoted \\\"\\\\\\\" backslash\""); + wmem_free(NULL, buf); + + buf = ws_escape_string(NULL, "whitespace \t \n \r \f \v", true); + g_assert_cmpstr(buf, ==, "\"whitespace \\t \\n \\r \\f \\v""\""); + wmem_free(NULL, buf); + + const char s1[] = { 'a', 'b', 'c', '\0', 'e', 'f', 'g'}; + buf = ws_escape_null(NULL, s1, sizeof(s1), true); + g_assert_cmpstr(buf, ==, "\"abc\\0efg\""); + wmem_free(NULL, buf); +} + +static void test_strconcat(void) +{ + wmem_allocator_t *allocator; + char *new_str; + + allocator = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK); + + new_str = wmem_strconcat(allocator, "ABC", NULL); + g_assert_cmpstr(new_str, ==, "ABC"); + + new_str = wmem_strconcat(allocator, "ABC", "DEF", NULL); + g_assert_cmpstr(new_str, ==, "ABCDEF"); + + new_str = wmem_strconcat(allocator, "", "", "ABCDEF", "", "GH", NULL); + g_assert_cmpstr(new_str, ==, "ABCDEFGH"); + + wmem_destroy_allocator(allocator); +} + +static void test_strsplit(void) +{ + wmem_allocator_t *allocator; + char **split_str; + + allocator = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK); + + split_str = wmem_strsplit(allocator, "A-C", "-", 2); + g_assert_cmpstr(split_str[0], ==, "A"); + g_assert_cmpstr(split_str[1], ==, "C"); + g_assert_null(split_str[2]); + + split_str = wmem_strsplit(allocator, "A-C", "-", 0); + g_assert_cmpstr(split_str[0], ==, "A"); + g_assert_cmpstr(split_str[1], ==, "C"); + g_assert_null(split_str[2]); + + split_str = wmem_strsplit(allocator, "--aslkf-asio--asfj-as--", "-", 10); + g_assert_cmpstr(split_str[0], ==, ""); + g_assert_cmpstr(split_str[1], ==, ""); + g_assert_cmpstr(split_str[2], ==, "aslkf"); + g_assert_cmpstr(split_str[3], ==, "asio"); + g_assert_cmpstr(split_str[4], ==, ""); + g_assert_cmpstr(split_str[5], ==, "asfj"); + g_assert_cmpstr(split_str[6], ==, "as"); + g_assert_cmpstr(split_str[7], ==, ""); + g_assert_cmpstr(split_str[8], ==, ""); + g_assert_null(split_str[9]); + + split_str = wmem_strsplit(allocator, "--aslkf-asio--asfj-as--", "-", 5); + g_assert_cmpstr(split_str[0], ==, ""); + g_assert_cmpstr(split_str[1], ==, ""); + g_assert_cmpstr(split_str[2], ==, "aslkf"); + g_assert_cmpstr(split_str[3], ==, "asio"); + g_assert_cmpstr(split_str[4], ==, "-asfj-as--"); + g_assert_null(split_str[5]); + + split_str = wmem_strsplit(allocator, "", "-", -1); + g_assert_null(split_str[0]); + + wmem_destroy_allocator(allocator); +} + +static void test_str_ascii(void) +{ + wmem_allocator_t *allocator; + const char *orig_str; + char *new_str; + + allocator = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK); + + orig_str = "TeStAsCiIsTrDoWn"; + new_str = wmem_ascii_strdown(allocator, orig_str, -1); + g_assert_cmpstr(new_str, ==, "testasciistrdown"); + + wmem_destroy_allocator(allocator); +} + +static void test_format_text(void) +{ + const char *have, *want; + char *res; + + /* ASCII */ + have = "abcdef"; + want = "abcdef"; + res = format_text_string(NULL, have); + g_assert_cmpstr(res, ==, want); + g_free(res); + + /* ASCII with special escape characters. */ + have = "abc\td\fe\nf"; + want = "abc\\td\\fe\\nf"; + res = format_text_string(NULL, have); + g_assert_cmpstr(res, ==, want); + g_free(res); + + /* ASCII with non-printable characters. */ + have = "abc \004 def"; + want = "abc \\004 def"; + res = format_text_string(NULL, have); + g_assert_cmpstr(res, ==, want); + g_free(res); + + /* UTF-8 */ + have = u8"Γαζέες καὶ μυρτιὲς δὲν θὰ βρῶ πιὰ στὸ χρυσαφὶ ξέφωτο"; + want = u8"Γαζέες καὶ μυρτιὲς δὲν θὰ βρῶ πιὰ στὸ χρυσαφὶ ξέφωτο"; + res = format_text_string(NULL, have); + g_assert_cmpstr(res, ==, want); + g_free(res); + + /* UTF-8 with non-ASCII non-printable characters. */ + have = u8"String with BOM \ufeff"; + want = u8"String with BOM \\uFEFF"; + res = format_text_string(NULL, have); + g_assert_cmpstr(res, ==, want); + g_free(res); + +} + +#define RESOURCE_USAGE_START get_resource_usage(&start_utime, &start_stime) + +#define RESOURCE_USAGE_END \ + get_resource_usage(&end_utime, &end_stime); \ + utime_ms = (end_utime - start_utime) * 1000.0; \ + stime_ms = (end_stime - start_stime) * 1000.0 + +static void test_format_text_perf(void) +{ +#define LOOP_COUNT (1 * 1000 * 1000) + char *str; + int i; + double start_utime, start_stime, end_utime, end_stime, utime_ms, stime_ms; + + const char *text = "The quick brown fox\tjumps over the lazy \001dog"UTF8_HORIZONTAL_ELLIPSIS"\n"; + + RESOURCE_USAGE_START; + for (i = 0; i < LOOP_COUNT; i++) { + str = format_text_string(NULL, text); + g_free(str); + } + RESOURCE_USAGE_END; + g_test_minimized_result(utime_ms + stime_ms, + "format_text_string(): u %.3f ms s %.3f ms", utime_ms, stime_ms); +} + +#include "to_str.h" + +static void test_word_to_hex(void) +{ + static char buf[32]; + char *str; /* String is not NULL terminated. */ + + str = guint8_to_hex(buf, 0x34); + g_assert_true(str == buf + 2); + g_assert_cmpint(str[-1], ==, '4'); + g_assert_cmpint(str[-2], ==, '3'); + + str = word_to_hex(buf, 0x1234); + g_assert_true(str == buf + 4); + g_assert_cmpint(str[-1], ==, '4'); + g_assert_cmpint(str[-2], ==, '3'); + g_assert_cmpint(str[-3], ==, '2'); + g_assert_cmpint(str[-4], ==, '1'); + + str = dword_to_hex(buf, 0x1234); + g_assert_true(str == buf + 8); + g_assert_cmpint(str[-1], ==, '4'); + g_assert_cmpint(str[-2], ==, '3'); + g_assert_cmpint(str[-3], ==, '2'); + g_assert_cmpint(str[-4], ==, '1'); + g_assert_cmpint(str[-5], ==, '0'); + g_assert_cmpint(str[-6], ==, '0'); + g_assert_cmpint(str[-7], ==, '0'); + g_assert_cmpint(str[-8], ==, '0'); + + str = qword_to_hex(buf, G_GUINT64_CONSTANT(0xFEDCBA987654321)); + g_assert_true(str == buf + 16); + g_assert_cmpint(str[-1], ==, '1'); + g_assert_cmpint(str[-2], ==, '2'); + g_assert_cmpint(str[-3], ==, '3'); + g_assert_cmpint(str[-4], ==, '4'); + g_assert_cmpint(str[-5], ==, '5'); + g_assert_cmpint(str[-6], ==, '6'); + g_assert_cmpint(str[-7], ==, '7'); + g_assert_cmpint(str[-8], ==, '8'); + g_assert_cmpint(str[-9], ==, '9'); + g_assert_cmpint(str[-10], ==, 'a'); + g_assert_cmpint(str[-11], ==, 'b'); + g_assert_cmpint(str[-12], ==, 'c'); + g_assert_cmpint(str[-13], ==, 'd'); + g_assert_cmpint(str[-14], ==, 'e'); + g_assert_cmpint(str[-15], ==, 'f'); + g_assert_cmpint(str[-16], ==, '0'); +} + +static void test_bytes_to_str(void) +{ + char *str; + + const uint8_t buf[] = { 1, 2, 3}; + + str = bytes_to_str(NULL, buf, sizeof(buf)); + g_assert_cmpstr(str, ==, "010203"); + g_free(str); +} + +static void test_bytes_to_str_punct(void) +{ + char *str; + + const uint8_t buf[] = { 1, 2, 3}; + + str = bytes_to_str_punct(NULL, buf, sizeof(buf), ':'); + g_assert_cmpstr(str, ==, "01:02:03"); + g_free(str); +} + +static void test_bytes_to_str_punct_maxlen(void) +{ + char *str; + + const uint8_t buf[] = { 1, 2, 3}; + + str = bytes_to_str_punct_maxlen(NULL, buf, sizeof(buf), ':', 4); + g_assert_cmpstr(str, ==, "01:02:03"); + g_free(str); + + str = bytes_to_str_punct_maxlen(NULL, buf, sizeof(buf), ':', 3); + g_assert_cmpstr(str, ==, "01:02:03"); + g_free(str); + + str = bytes_to_str_punct_maxlen(NULL, buf, sizeof(buf), ':', 2); + g_assert_cmpstr(str, ==, "01:02:" UTF8_HORIZONTAL_ELLIPSIS); + g_free(str); + + str = bytes_to_str_punct_maxlen(NULL, buf, sizeof(buf), ':', 1); + g_assert_cmpstr(str, ==, "01:" UTF8_HORIZONTAL_ELLIPSIS); + g_free(str); + + str = bytes_to_str_punct_maxlen(NULL, buf, sizeof(buf), ':', 0); + g_assert_cmpstr(str, ==, "01:02:03"); + g_free(str); +} + +static void test_bytes_to_str_maxlen(void) +{ + char *str; + + const uint8_t buf[] = { 1, 2, 3}; + + str = bytes_to_str_maxlen(NULL, buf, sizeof(buf), 4); + g_assert_cmpstr(str, ==, "010203"); + g_free(str); + + str = bytes_to_str_maxlen(NULL, buf, sizeof(buf), 3); + g_assert_cmpstr(str, ==, "010203"); + g_free(str); + + str = bytes_to_str_maxlen(NULL, buf, sizeof(buf), 2); + g_assert_cmpstr(str, ==, "0102" UTF8_HORIZONTAL_ELLIPSIS); + g_free(str); + + str = bytes_to_str_maxlen(NULL, buf, sizeof(buf), 1); + g_assert_cmpstr(str, ==, "01" UTF8_HORIZONTAL_ELLIPSIS); + g_free(str); + + str = bytes_to_str_maxlen(NULL, buf, sizeof(buf), 0); + g_assert_cmpstr(str, ==, "010203"); + g_free(str); +} + +static void test_bytes_to_string_trunc1(void) +{ + char *str; + + const uint8_t buf[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA + }; + const char *expect = + "112233445566778899aa" + "112233445566778899aa" + "112233445566778899aa" + "112233445566" UTF8_HORIZONTAL_ELLIPSIS; + + str = bytes_to_str(NULL, buf, sizeof(buf)); + g_assert_cmpstr(str, ==, expect); + g_free(str); +} + +static void test_bytes_to_string_punct_trunc1(void) +{ + char *str; + + const uint8_t buf[] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA + }; + const char *expect = + "11:22:33:44:55:66:77:88:99:aa:" + "11:22:33:44:55:66:77:88:99:aa:" + "11:22:33:44:" UTF8_HORIZONTAL_ELLIPSIS; + + str = bytes_to_str_punct(NULL, buf, sizeof(buf), ':'); + g_assert_cmpstr(str, ==, expect); + g_free(str); +} + +static char to_str_back_buf[32]; +#define BACK_PTR (&to_str_back_buf[31]) /* pointer to NUL string terminator */ + +static void test_oct_to_str_back(void) +{ + char *str; + + str = oct_to_str_back(BACK_PTR, 958769886); + g_assert_cmpstr(str, ==, "07111325336"); + + str = oct_to_str_back(BACK_PTR, 781499127); + g_assert_cmpstr(str, ==, "05645135367"); + + str = oct_to_str_back(BACK_PTR, 1177329882); + g_assert_cmpstr(str, ==, "010613120332"); +} + +static void test_oct64_to_str_back(void) +{ + char *str; + + str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(13873797580070999420)); + g_assert_cmpstr(str, ==, "01402115026217563452574"); + + str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(7072159458371400691)); + g_assert_cmpstr(str, ==, "0610452670726711271763"); + + str = oct64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(12453513102400590374)); + g_assert_cmpstr(str, ==, "01263236102754220511046"); +} + +static void test_hex_to_str_back_len(void) +{ + char *str; + + str = hex_to_str_back_len(BACK_PTR, 2481, 8); + g_assert_cmpstr(str, ==, "0x000009b1"); + + str = hex_to_str_back_len(BACK_PTR, 2457, 8); + g_assert_cmpstr(str, ==, "0x00000999"); + + str = hex_to_str_back_len(BACK_PTR, 16230, 8); + g_assert_cmpstr(str, ==, "0x00003f66"); +} + +static void test_hex64_to_str_back_len(void) +{ + char *str; + + str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(1), 16); + g_assert_cmpstr(str, ==, "0x0000000000000001"); + + str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(4294967295), 16); + g_assert_cmpstr(str, ==, "0x00000000ffffffff"); + + str = hex64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(18446744073709551615), 16); + g_assert_cmpstr(str, ==, "0xffffffffffffffff"); +} + +static void test_uint_to_str_back(void) +{ + char *str; + + str = uint_to_str_back(BACK_PTR, 873735883); + g_assert_cmpstr(str, ==, "873735883"); + + str = uint_to_str_back(BACK_PTR, 1801148094); + g_assert_cmpstr(str, ==, "1801148094"); + + str = uint_to_str_back(BACK_PTR, 181787997); + g_assert_cmpstr(str, ==, "181787997"); +} + +static void test_uint64_to_str_back(void) +{ + char *str; + + str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(585143757104211265)); + g_assert_cmpstr(str, ==, "585143757104211265"); + + str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(7191580247919484847)); + g_assert_cmpstr(str, ==, "7191580247919484847"); + + str = uint64_to_str_back(BACK_PTR, G_GUINT64_CONSTANT(95778573911934485)); + g_assert_cmpstr(str, ==, "95778573911934485"); +} + +static void test_uint_to_str_back_len(void) +{ + char *str; + + str = uint_to_str_back_len(BACK_PTR, 26630, 8); + g_assert_cmpstr(str, ==, "00026630"); + + str = uint_to_str_back_len(BACK_PTR, 25313, 8); + g_assert_cmpstr(str, ==, "00025313"); + + str = uint_to_str_back_len(BACK_PTR, 18750000, 8); + g_assert_cmpstr(str, ==, "18750000"); +} + +static void test_uint64_to_str_back_len(void) +{ + char *str; + + str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(1), 16); + g_assert_cmpstr(str, ==, "0000000000000001"); + + str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(4294967295), 16); + g_assert_cmpstr(str, ==, "0000004294967295"); + + str = uint64_to_str_back_len(BACK_PTR, G_GUINT64_CONSTANT(18446744073709551615), 16); + g_assert_cmpstr(str, ==, "18446744073709551615"); +} + +static void test_int_to_str_back(void) +{ + char *str; + + str = int_to_str_back(BACK_PTR, -763689611); + g_assert_cmpstr(str, ==, "-763689611"); + + str = int_to_str_back(BACK_PTR, -296015954); + g_assert_cmpstr(str, ==, "-296015954"); + + str = int_to_str_back(BACK_PTR, 898901469); + g_assert_cmpstr(str, ==, "898901469"); +} + +static void test_int64_to_str_back(void) +{ + char *str; + + str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(-9223372036854775807)); + g_assert_cmpstr(str, ==, "-9223372036854775807"); + + str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(1)); + g_assert_cmpstr(str, ==, "1"); + + str = int64_to_str_back(BACK_PTR, G_GINT64_CONSTANT(9223372036854775807)); + g_assert_cmpstr(str, ==, "9223372036854775807"); +} + +#include "nstime.h" +#include "time_util.h" + +void test_nstime_from_iso8601(void) +{ + char *str; + const char *endp; + nstime_t result, expect; + struct tm tm1; + + memset(&tm1, 0, sizeof(tm1)); + tm1.tm_sec = 25; + tm1.tm_min = 45; + tm1.tm_hour = 23; + tm1.tm_mday = 30; + tm1.tm_mon = 4; /* starts at zero */ + tm1.tm_year = 2013 - 1900; + tm1.tm_isdst = -1; + + /* Date and time with local time. */ + str = "2013-05-30T23:45:25.349124"; + expect.secs = mktime(&tm1); + expect.nsecs = 349124 * 1000; + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); + g_assert_cmpint(result.secs, ==, expect.secs); + g_assert_cmpint(result.nsecs, ==, expect.nsecs); + + /* Date and time with UTC timezone. */ + str = "2013-05-30T23:45:25.349124Z"; + expect.secs = mktime_utc(&tm1); + expect.nsecs = 349124 * 1000; + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); + g_assert_cmpint(result.secs, ==, expect.secs); + g_assert_cmpint(result.nsecs, ==, expect.nsecs); + + /* Date and time with timezone offset with separator. */ + str = "2013-05-30T23:45:25.349124+01:00"; + expect.secs = mktime_utc(&tm1) - 1 * 60 * 60; + expect.nsecs = 349124 * 1000; + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); + g_assert_cmpint(result.secs, ==, expect.secs); + g_assert_cmpint(result.nsecs, ==, expect.nsecs); + + /* Date and time with timezone offset without separator. */ + str = "2013-05-30T23:45:25.349124+0100"; + expect.secs = mktime_utc(&tm1) - 1 * 60 * 60; + expect.nsecs = 349124 * 1000; + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); + g_assert_cmpint(result.secs, ==, expect.secs); + g_assert_cmpint(result.nsecs, ==, expect.nsecs); + + /* Date and time with timezone offset with hours only. */ + str = "2013-05-30T23:45:25.349124+01"; + expect.secs = mktime_utc(&tm1) - 1 * 60 * 60; + expect.nsecs = 349124 * 1000; + endp = iso8601_to_nstime(&result, str, ISO8601_DATETIME_AUTO); + g_assert_nonnull(endp); + g_assert(*endp == '\0'); + g_assert_cmpint(result.secs, ==, expect.secs); + g_assert_cmpint(result.nsecs, ==, expect.nsecs); +} + +#include "ws_getopt.h" + +#define ARGV_MAX 31 + +static char **new_argv(int *argc_ptr, const char *args, ...) +{ + char **argv; + int argc = 0; + va_list ap; + + argv = g_malloc((ARGV_MAX + 1) * sizeof(char *)); + + va_start(ap, args); + while (args != NULL) { + /* Increase ARGV_MAX or use a dynamic size if this assertion fails. */ + g_assert_true(argc < ARGV_MAX); + argv[argc++] = g_strdup(args); + args = va_arg(ap, const char *); + } + argv[argc] = NULL; + va_end(ap); + + *argc_ptr = argc; + return argv; +} + +static void free_argv(char **argv) +{ + for (char **p = argv; *p != NULL; p++) { + g_free(*p); + } + g_free(argv); +} + +static void test_getopt_long_basic1(void) +{ + char **argv; + int argc; + + const char *optstring = "ab:c"; + argv = new_argv(&argc, "/bin/ls", "-a", "-b", "arg1", "-c", "path", (char *)NULL); + + ws_optind = 1; + int opt; + + opt = ws_getopt_long(argc, argv, optstring, NULL, NULL); + g_assert_cmpint(opt, ==, 'a'); + g_assert_null(ws_optarg); + + opt = ws_getopt_long(argc, argv, optstring, NULL, NULL); + g_assert_cmpint(opt, ==, 'b'); + g_assert_cmpstr(ws_optarg, ==, "arg1"); + + opt = ws_getopt_long(argc, argv, optstring, NULL, NULL); + g_assert_cmpint(opt, ==, 'c'); + g_assert_null(ws_optarg); + + opt = ws_getopt_long(argc, argv, optstring, NULL, NULL); + g_assert_cmpint(opt, ==, -1); + + free_argv(argv); +} + +static void test_getopt_long_basic2(void) +{ + char **argv; + int argc; + + struct ws_option longopts[] = { + { "opt1", ws_no_argument, NULL, '1' }, + { "opt2", ws_required_argument, NULL, '2' }, + { "opt3", ws_required_argument, NULL, '3' }, + { 0, 0, 0, 0 } + }; + argv = new_argv(&argc, "/bin/ls", "--opt1", "--opt2", "arg1", "--opt3=arg2", "path", (char *)NULL); + + ws_optind = 1; + int opt; + + opt = ws_getopt_long(argc, argv, "", longopts, NULL); + g_assert_cmpint(opt, ==, '1'); + g_assert_null(ws_optarg); + + opt = ws_getopt_long(argc, argv, "", longopts, NULL); + g_assert_cmpint(opt, ==, '2'); + g_assert_cmpstr(ws_optarg, ==, "arg1"); + + opt = ws_getopt_long(argc, argv, "", longopts, NULL); + g_assert_cmpint(opt, ==, '3'); + g_assert_cmpstr(ws_optarg, ==, "arg2"); + + opt = ws_getopt_long(argc, argv, "", longopts, NULL); + g_assert_cmpint(opt, ==, -1); + + free_argv(argv); +} + +static void test_getopt_optional_argument1(void) +{ + char **argv; + int argc; + int opt; + + struct ws_option longopts_optional[] = { + { "optional", ws_optional_argument, NULL, '1' }, + { 0, 0, 0, 0 } + }; + + argv = new_argv(&argc, "/bin/ls", "--optional=arg1", (char *)NULL); + + ws_optreset = 1; + opt = ws_getopt_long(argc, argv, "", longopts_optional, NULL); + g_assert_cmpint(opt, ==, '1'); + g_assert_cmpstr(ws_optarg, ==, "arg1"); + + free_argv(argv); + argv = new_argv(&argc, "/bin/ls", "--optional", "arg1", (char *)NULL); + + ws_optreset = 1; + opt = ws_getopt_long(argc, argv, "", longopts_optional, NULL); + g_assert_cmpint(opt, ==, '1'); + /* Optional argument does not recognize the form "--arg param" (it's ambiguous). */ + g_assert_null(ws_optarg); + + free_argv(argv); + argv = new_argv(&argc, "/bin/ls", "--optional", (char *)NULL); + + ws_optreset = 1; + opt = ws_getopt_long(argc, argv, "", longopts_optional, NULL); + g_assert_cmpint(opt, ==, '1'); + g_assert_null(ws_optarg); + + free_argv(argv); +} + +static void test_getopt_opterr1(void) +{ + char **argv; + int argc; + +#ifdef _WIN32 + g_test_skip("Not supported on Windows"); + return; +#endif + + if (g_test_subprocess()) { + const char *optstring = "ab"; + argv = new_argv(&argc, "/bin/ls", "-a", "-z", "path", (char *)NULL); + + ws_optind = 0; + ws_opterr = 1; + int opt; + + opt = ws_getopt_long(argc, argv, optstring, NULL, NULL); + g_assert_cmpint(opt, ==, 'a'); + + opt = ws_getopt_long(argc, argv, optstring, NULL, NULL); + g_assert_cmpint(opt, ==, '?'); + g_assert_cmpint(ws_optopt, ==, 'z'); + + opt = ws_getopt_long(argc, argv, optstring, NULL, NULL); + g_assert_cmpint(opt, ==, -1); + + free_argv(argv); + + return; + } + + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_passed(); + g_test_trap_assert_stderr("/bin/ls: unrecognized option: z\n"); +} + +int main(int argc, char **argv) +{ + int ret; + + ws_log_init("test_wsutil", NULL); + + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/inet_addr/inet_pton4", test_inet_pton4_test1); + g_test_add_func("/inet_addr/inet_ntop4", test_inet_ntop4_test1); + g_test_add_func("/inet_addr/inet_pton6", test_inet_pton6_test1); + g_test_add_func("/inet_addr/inet_ntop6", test_inet_ntop6_test1); + + g_test_add_func("/str_util/format_size", test_format_size); + g_test_add_func("/str_util/escape_string", test_escape_string); + g_test_add_func("/str_util/strconcat", test_strconcat); + g_test_add_func("/str_util/strsplit", test_strsplit); + g_test_add_func("/str_util/str_ascii", test_str_ascii); + g_test_add_func("/str_util/format_text", test_format_text); + + if (g_test_perf()) { + g_test_add_func("/str_util/format_text_perf", test_format_text_perf); + } + + g_test_add_func("/to_str/word_to_hex", test_word_to_hex); + g_test_add_func("/to_str/bytes_to_str", test_bytes_to_str); + g_test_add_func("/to_str/bytes_to_str_punct", test_bytes_to_str_punct); + g_test_add_func("/to_str/bytes_to_str_maxlen", test_bytes_to_str_maxlen); + g_test_add_func("/to_str/bytes_to_str_punct_maxlen", test_bytes_to_str_punct_maxlen); + g_test_add_func("/to_str/bytes_to_str_trunc1", test_bytes_to_string_trunc1); + g_test_add_func("/to_str/bytes_to_str_punct_trunc1", test_bytes_to_string_punct_trunc1); + g_test_add_func("/to_str/oct_to_str_back", test_oct_to_str_back); + g_test_add_func("/to_str/oct64_to_str_back", test_oct64_to_str_back); + g_test_add_func("/to_str/hex_to_str_back_len", test_hex_to_str_back_len); + g_test_add_func("/to_str/hex64_to_str_back_len", test_hex64_to_str_back_len); + g_test_add_func("/to_str/uint_to_str_back", test_uint_to_str_back); + g_test_add_func("/to_str/uint64_to_str_back", test_uint64_to_str_back); + g_test_add_func("/to_str/uint_to_str_back_len", test_uint_to_str_back_len); + g_test_add_func("/to_str/uint64_to_str_back_len", test_uint64_to_str_back_len); + g_test_add_func("/to_str/int_to_str_back", test_int_to_str_back); + g_test_add_func("/to_str/int64_to_str_back", test_int64_to_str_back); + + g_test_add_func("/nstime/from_iso8601", test_nstime_from_iso8601); + + g_test_add_func("/ws_getopt/basic1", test_getopt_long_basic1); + g_test_add_func("/ws_getopt/basic2", test_getopt_long_basic2); + g_test_add_func("/ws_getopt/optional1", test_getopt_optional_argument1); + g_test_add_func("/ws_getopt/opterr1", test_getopt_opterr1); + + ret = g_test_run(); + + return ret; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |