From e5a812082ae033afb1eed82c0f2df3d0f6bdc93f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 08:53:20 +0200 Subject: Adding upstream version 2.1.6. Signed-off-by: Daniel Baumann --- lib/common/tests/strings/Makefile.am | 41 ++++++ lib/common/tests/strings/crm_get_msec_test.c | 50 +++++++ lib/common/tests/strings/crm_is_true_test.c | 57 ++++++++ lib/common/tests/strings/crm_str_to_boolean_test.c | 92 ++++++++++++ lib/common/tests/strings/pcmk__add_word_test.c | 93 ++++++++++++ lib/common/tests/strings/pcmk__btoa_test.c | 22 +++ .../tests/strings/pcmk__char_in_any_str_test.c | 46 ++++++ lib/common/tests/strings/pcmk__compress_test.c | 58 ++++++++ lib/common/tests/strings/pcmk__ends_with_test.c | 57 ++++++++ lib/common/tests/strings/pcmk__g_strcat_test.c | 73 ++++++++++ .../tests/strings/pcmk__guint_from_hash_test.c | 76 ++++++++++ .../tests/strings/pcmk__numeric_strcasecmp_test.c | 79 +++++++++++ .../tests/strings/pcmk__parse_ll_range_test.c | 117 +++++++++++++++ lib/common/tests/strings/pcmk__s_test.c | 29 ++++ lib/common/tests/strings/pcmk__scan_double_test.c | 158 +++++++++++++++++++++ lib/common/tests/strings/pcmk__scan_min_int_test.c | 60 ++++++++ lib/common/tests/strings/pcmk__scan_port_test.c | 59 ++++++++ lib/common/tests/strings/pcmk__starts_with_test.c | 35 +++++ lib/common/tests/strings/pcmk__str_any_of_test.c | 48 +++++++ lib/common/tests/strings/pcmk__str_in_list_test.c | 107 ++++++++++++++ .../tests/strings/pcmk__str_table_dup_test.c | 59 ++++++++ lib/common/tests/strings/pcmk__str_update_test.c | 78 ++++++++++ lib/common/tests/strings/pcmk__strcmp_test.c | 80 +++++++++++ .../tests/strings/pcmk__strikey_table_test.c | 40 ++++++ lib/common/tests/strings/pcmk__strkey_table_test.c | 40 ++++++ lib/common/tests/strings/pcmk__trim_test.c | 72 ++++++++++ 26 files changed, 1726 insertions(+) create mode 100644 lib/common/tests/strings/Makefile.am create mode 100644 lib/common/tests/strings/crm_get_msec_test.c create mode 100644 lib/common/tests/strings/crm_is_true_test.c create mode 100644 lib/common/tests/strings/crm_str_to_boolean_test.c create mode 100644 lib/common/tests/strings/pcmk__add_word_test.c create mode 100644 lib/common/tests/strings/pcmk__btoa_test.c create mode 100644 lib/common/tests/strings/pcmk__char_in_any_str_test.c create mode 100644 lib/common/tests/strings/pcmk__compress_test.c create mode 100644 lib/common/tests/strings/pcmk__ends_with_test.c create mode 100644 lib/common/tests/strings/pcmk__g_strcat_test.c create mode 100644 lib/common/tests/strings/pcmk__guint_from_hash_test.c create mode 100644 lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c create mode 100644 lib/common/tests/strings/pcmk__parse_ll_range_test.c create mode 100644 lib/common/tests/strings/pcmk__s_test.c create mode 100644 lib/common/tests/strings/pcmk__scan_double_test.c create mode 100644 lib/common/tests/strings/pcmk__scan_min_int_test.c create mode 100644 lib/common/tests/strings/pcmk__scan_port_test.c create mode 100644 lib/common/tests/strings/pcmk__starts_with_test.c create mode 100644 lib/common/tests/strings/pcmk__str_any_of_test.c create mode 100644 lib/common/tests/strings/pcmk__str_in_list_test.c create mode 100644 lib/common/tests/strings/pcmk__str_table_dup_test.c create mode 100644 lib/common/tests/strings/pcmk__str_update_test.c create mode 100644 lib/common/tests/strings/pcmk__strcmp_test.c create mode 100644 lib/common/tests/strings/pcmk__strikey_table_test.c create mode 100644 lib/common/tests/strings/pcmk__strkey_table_test.c create mode 100644 lib/common/tests/strings/pcmk__trim_test.c (limited to 'lib/common/tests/strings') diff --git a/lib/common/tests/strings/Makefile.am b/lib/common/tests/strings/Makefile.am new file mode 100644 index 0000000..9abb8e9 --- /dev/null +++ b/lib/common/tests/strings/Makefile.am @@ -0,0 +1,41 @@ +# +# Copyright 2020-2022 the Pacemaker project contributors +# +# The version control history for this file may have further details. +# +# This source code is licensed under the GNU General Public License version 2 +# or later (GPLv2+) WITHOUT ANY WARRANTY. +# + +include $(top_srcdir)/mk/tap.mk +include $(top_srcdir)/mk/unittest.mk + +# Add "_test" to the end of all test program names to simplify .gitignore. +check_PROGRAMS = \ + crm_get_msec_test \ + crm_is_true_test \ + crm_str_to_boolean_test \ + pcmk__add_word_test \ + pcmk__btoa_test \ + pcmk__char_in_any_str_test \ + pcmk__compress_test \ + pcmk__ends_with_test \ + pcmk__g_strcat_test \ + pcmk__guint_from_hash_test \ + pcmk__numeric_strcasecmp_test \ + pcmk__parse_ll_range_test \ + pcmk__s_test \ + pcmk__scan_double_test \ + pcmk__scan_min_int_test \ + pcmk__scan_port_test \ + pcmk__starts_with_test \ + pcmk__str_any_of_test \ + pcmk__str_in_list_test \ + pcmk__str_table_dup_test \ + pcmk__str_update_test \ + pcmk__strcmp_test \ + pcmk__strkey_table_test \ + pcmk__strikey_table_test \ + pcmk__trim_test + +TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/strings/crm_get_msec_test.c b/lib/common/tests/strings/crm_get_msec_test.c new file mode 100644 index 0000000..5da548b --- /dev/null +++ b/lib/common/tests/strings/crm_get_msec_test.c @@ -0,0 +1,50 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +bad_input(void **state) { + assert_int_equal(crm_get_msec(NULL), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec(" "), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec("abcxyz"), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec("100xs"), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec(" 100 xs "), PCMK__PARSE_INT_DEFAULT); + assert_int_equal(crm_get_msec("-100ms"), PCMK__PARSE_INT_DEFAULT); +} + +static void +good_input(void **state) { + assert_int_equal(crm_get_msec("100"), 100000); + assert_int_equal(crm_get_msec(" 100 "), 100000); + assert_int_equal(crm_get_msec("\t100\n"), 100000); + + assert_int_equal(crm_get_msec("100ms"), 100); + assert_int_equal(crm_get_msec("100 MSEC"), 100); + assert_int_equal(crm_get_msec("1000US"), 1); + assert_int_equal(crm_get_msec("1000usec"), 1); + assert_int_equal(crm_get_msec("12s"), 12000); + assert_int_equal(crm_get_msec("12 sec"), 12000); + assert_int_equal(crm_get_msec("1m"), 60000); + assert_int_equal(crm_get_msec("13 min"), 780000); + assert_int_equal(crm_get_msec("2\th"), 7200000); + assert_int_equal(crm_get_msec("1 hr"), 3600000); +} + +static void +overflow(void **state) { + assert_int_equal(crm_get_msec("9223372036854775807s"), LLONG_MAX); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(bad_input), + cmocka_unit_test(good_input), + cmocka_unit_test(overflow)) diff --git a/lib/common/tests/strings/crm_is_true_test.c b/lib/common/tests/strings/crm_is_true_test.c new file mode 100644 index 0000000..2a9e31c --- /dev/null +++ b/lib/common/tests/strings/crm_is_true_test.c @@ -0,0 +1,57 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +bad_input(void **state) { + assert_false(crm_is_true(NULL)); +} + +static void +is_true(void **state) { + assert_true(crm_is_true("true")); + assert_true(crm_is_true("TrUe")); + assert_true(crm_is_true("on")); + assert_true(crm_is_true("ON")); + assert_true(crm_is_true("yes")); + assert_true(crm_is_true("yES")); + assert_true(crm_is_true("y")); + assert_true(crm_is_true("Y")); + assert_true(crm_is_true("1")); +} + +static void +is_false(void **state) { + assert_false(crm_is_true("false")); + assert_false(crm_is_true("fAlSe")); + assert_false(crm_is_true("off")); + assert_false(crm_is_true("OFF")); + assert_false(crm_is_true("no")); + assert_false(crm_is_true("No")); + assert_false(crm_is_true("n")); + assert_false(crm_is_true("N")); + assert_false(crm_is_true("0")); + + assert_false(crm_is_true("")); + assert_false(crm_is_true("blahblah")); + + assert_false(crm_is_true("truedat")); + assert_false(crm_is_true("onnn")); + assert_false(crm_is_true("yep")); + assert_false(crm_is_true("Y!")); + assert_false(crm_is_true("100")); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(bad_input), + cmocka_unit_test(is_true), + cmocka_unit_test(is_false)) diff --git a/lib/common/tests/strings/crm_str_to_boolean_test.c b/lib/common/tests/strings/crm_str_to_boolean_test.c new file mode 100644 index 0000000..3bd2e5d --- /dev/null +++ b/lib/common/tests/strings/crm_str_to_boolean_test.c @@ -0,0 +1,92 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +bad_input(void **state) { + assert_int_equal(crm_str_to_boolean(NULL, NULL), -1); + assert_int_equal(crm_str_to_boolean("", NULL), -1); + assert_int_equal(crm_str_to_boolean("blahblah", NULL), -1); +} + +static void +is_true(void **state) { + int ret; + + assert_int_equal(crm_str_to_boolean("true", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("TrUe", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("on", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("ON", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("yes", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("yES", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("y", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("Y", &ret), 1); + assert_true(ret); + assert_int_equal(crm_str_to_boolean("1", &ret), 1); + assert_true(ret); +} + +static void +is_not_true(void **state) { + assert_int_equal(crm_str_to_boolean("truedat", NULL), -1); + assert_int_equal(crm_str_to_boolean("onnn", NULL), -1); + assert_int_equal(crm_str_to_boolean("yep", NULL), -1); + assert_int_equal(crm_str_to_boolean("Y!", NULL), -1); + assert_int_equal(crm_str_to_boolean("100", NULL), -1); +} + +static void +is_false(void **state) { + int ret; + + assert_int_equal(crm_str_to_boolean("false", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("fAlSe", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("off", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("OFF", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("no", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("No", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("n", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("N", &ret), 1); + assert_false(ret); + assert_int_equal(crm_str_to_boolean("0", &ret), 1); + assert_false(ret); +} + +static void +is_not_false(void **state) { + assert_int_equal(crm_str_to_boolean("falseee", NULL), -1); + assert_int_equal(crm_str_to_boolean("of", NULL), -1); + assert_int_equal(crm_str_to_boolean("nope", NULL), -1); + assert_int_equal(crm_str_to_boolean("N!", NULL), -1); + assert_int_equal(crm_str_to_boolean("000", NULL), -1); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(bad_input), + cmocka_unit_test(is_true), + cmocka_unit_test(is_not_true), + cmocka_unit_test(is_false), + cmocka_unit_test(is_not_false)) diff --git a/lib/common/tests/strings/pcmk__add_word_test.c b/lib/common/tests/strings/pcmk__add_word_test.c new file mode 100644 index 0000000..16a749e --- /dev/null +++ b/lib/common/tests/strings/pcmk__add_word_test.c @@ -0,0 +1,93 @@ +/* + * Copyright 2020-2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +add_words(void **state) +{ + GString *list = NULL; + + pcmk__add_word(&list, 16, "hello"); + pcmk__add_word(&list, 16, "world"); + assert_int_equal(strcmp((const char *) list->str, "hello world"), 0); + g_string_free(list, TRUE); +} + +static void +add_with_no_len(void **state) +{ + GString *list = NULL; + + pcmk__add_word(&list, 0, "hello"); + pcmk__add_word(&list, 0, "world"); + assert_int_equal(strcmp((const char *) list->str, "hello world"), 0); + g_string_free(list, TRUE); +} + +static void +add_nothing(void **state) +{ + GString *list = NULL; + + pcmk__add_word(&list, 0, "hello"); + pcmk__add_word(&list, 0, NULL); + pcmk__add_word(&list, 0, ""); + assert_int_equal(strcmp((const char *) list->str, "hello"), 0); + g_string_free(list, TRUE); +} + +static void +add_with_null(void **state) +{ + GString *list = NULL; + + pcmk__add_separated_word(&list, 32, "hello", NULL); + pcmk__add_separated_word(&list, 32, "world", NULL); + pcmk__add_separated_word(&list, 32, "I am a unit test", NULL); + assert_int_equal(strcmp((const char *) list->str, + "hello world I am a unit test"), 0); + g_string_free(list, TRUE); +} + +static void +add_with_comma(void **state) +{ + GString *list = NULL; + + pcmk__add_separated_word(&list, 32, "hello", ","); + pcmk__add_separated_word(&list, 32, "world", ","); + pcmk__add_separated_word(&list, 32, "I am a unit test", ","); + assert_int_equal(strcmp((const char *) list->str, + "hello,world,I am a unit test"), 0); + g_string_free(list, TRUE); +} + +static void +add_with_comma_and_space(void **state) +{ + GString *list = NULL; + + pcmk__add_separated_word(&list, 32, "hello", ", "); + pcmk__add_separated_word(&list, 32, "world", ", "); + pcmk__add_separated_word(&list, 32, "I am a unit test", ", "); + assert_int_equal(strcmp((const char *) list->str, + "hello, world, I am a unit test"), 0); + g_string_free(list, TRUE); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(add_words), + cmocka_unit_test(add_with_no_len), + cmocka_unit_test(add_nothing), + cmocka_unit_test(add_with_null), + cmocka_unit_test(add_with_comma), + cmocka_unit_test(add_with_comma_and_space)) diff --git a/lib/common/tests/strings/pcmk__btoa_test.c b/lib/common/tests/strings/pcmk__btoa_test.c new file mode 100644 index 0000000..f7dee9e --- /dev/null +++ b/lib/common/tests/strings/pcmk__btoa_test.c @@ -0,0 +1,22 @@ +/* + * Copyright 2020-2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +btoa(void **state) { + assert_string_equal(pcmk__btoa(false), "false"); + assert_string_equal(pcmk__btoa(true), "true"); + assert_string_equal(pcmk__btoa(1 == 0), "false"); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(btoa)) diff --git a/lib/common/tests/strings/pcmk__char_in_any_str_test.c b/lib/common/tests/strings/pcmk__char_in_any_str_test.c new file mode 100644 index 0000000..e70dfb4 --- /dev/null +++ b/lib/common/tests/strings/pcmk__char_in_any_str_test.c @@ -0,0 +1,46 @@ +/* + * Copyright 2020-2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +empty_list(void **state) +{ + assert_false(pcmk__char_in_any_str('x', NULL)); + assert_false(pcmk__char_in_any_str('\0', NULL)); +} + +static void +null_char(void **state) +{ + assert_true(pcmk__char_in_any_str('\0', "xxx", "yyy", NULL)); + assert_true(pcmk__char_in_any_str('\0', "", NULL)); +} + +static void +in_list(void **state) +{ + assert_true(pcmk__char_in_any_str('x', "aaa", "bbb", "xxx", NULL)); +} + +static void +not_in_list(void **state) +{ + assert_false(pcmk__char_in_any_str('x', "aaa", "bbb", NULL)); + assert_false(pcmk__char_in_any_str('A', "aaa", "bbb", NULL)); + assert_false(pcmk__char_in_any_str('x', "", NULL)); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_list), + cmocka_unit_test(null_char), + cmocka_unit_test(in_list), + cmocka_unit_test(not_in_list)) diff --git a/lib/common/tests/strings/pcmk__compress_test.c b/lib/common/tests/strings/pcmk__compress_test.c new file mode 100644 index 0000000..7480937 --- /dev/null +++ b/lib/common/tests/strings/pcmk__compress_test.c @@ -0,0 +1,58 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include "mock_private.h" + +#define SIMPLE_DATA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + +const char *SIMPLE_COMPRESSED = "BZh41AY&SYO\x1ai"; + +static void +simple_compress(void **state) +{ + char *result = calloc(1024, sizeof(char)); + unsigned int len; + + assert_int_equal(pcmk__compress(SIMPLE_DATA, 40, 0, &result, &len), pcmk_rc_ok); + assert_memory_equal(result, SIMPLE_COMPRESSED, 13); +} + +static void +max_too_small(void **state) +{ + char *result = calloc(1024, sizeof(char)); + unsigned int len; + + assert_int_equal(pcmk__compress(SIMPLE_DATA, 40, 10, &result, &len), pcmk_rc_error); +} + +static void +calloc_fails(void **state) { + char *result = calloc(1024, sizeof(char)); + unsigned int len; + + pcmk__assert_asserts( + { + pcmk__mock_calloc = true; // calloc() will return NULL + expect_value(__wrap_calloc, nmemb, (size_t) ((40 * 1.01) + 601)); + expect_value(__wrap_calloc, size, sizeof(char)); + pcmk__compress(SIMPLE_DATA, 40, 0, &result, &len); + pcmk__mock_calloc = false; // Use the real calloc() + } + ); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(simple_compress), + cmocka_unit_test(max_too_small), + cmocka_unit_test(calloc_fails)) diff --git a/lib/common/tests/strings/pcmk__ends_with_test.c b/lib/common/tests/strings/pcmk__ends_with_test.c new file mode 100644 index 0000000..7503571 --- /dev/null +++ b/lib/common/tests/strings/pcmk__ends_with_test.c @@ -0,0 +1,57 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +bad_input(void **state) { + assert_false(pcmk__ends_with(NULL, "xyz")); + + assert_true(pcmk__ends_with(NULL, NULL)); + assert_true(pcmk__ends_with(NULL, "")); + assert_true(pcmk__ends_with("", NULL)); + assert_true(pcmk__ends_with("", "")); + assert_true(pcmk__ends_with("abc", NULL)); + assert_true(pcmk__ends_with("abc", "")); +} + +static void +ends_with(void **state) { + assert_true(pcmk__ends_with("abc", "abc")); + assert_true(pcmk__ends_with("abc", "bc")); + assert_true(pcmk__ends_with("abc", "c")); + assert_true(pcmk__ends_with("abcbc", "bc")); + + assert_false(pcmk__ends_with("abc", "def")); + assert_false(pcmk__ends_with("abc", "defg")); + assert_false(pcmk__ends_with("abc", "bcd")); + assert_false(pcmk__ends_with("abc", "ab")); + + assert_false(pcmk__ends_with("abc", "BC")); +} + +static void +ends_with_ext(void **state) { + assert_true(pcmk__ends_with_ext("ab.c", ".c")); + assert_true(pcmk__ends_with_ext("ab.cb.c", ".c")); + + assert_false(pcmk__ends_with_ext("ab.c", ".def")); + assert_false(pcmk__ends_with_ext("ab.c", ".defg")); + assert_false(pcmk__ends_with_ext("ab.c", ".cd")); + assert_false(pcmk__ends_with_ext("ab.c", "ab")); + + assert_false(pcmk__ends_with_ext("ab.c", ".C")); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(bad_input), + cmocka_unit_test(ends_with), + cmocka_unit_test(ends_with_ext)) diff --git a/lib/common/tests/strings/pcmk__g_strcat_test.c b/lib/common/tests/strings/pcmk__g_strcat_test.c new file mode 100644 index 0000000..2116f0e --- /dev/null +++ b/lib/common/tests/strings/pcmk__g_strcat_test.c @@ -0,0 +1,73 @@ +/* + * Copyright 2020-2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +add_to_null(void **state) +{ + pcmk__assert_asserts(pcmk__g_strcat(NULL, NULL)); + pcmk__assert_asserts(pcmk__g_strcat(NULL, "hello", NULL)); +} + +static void +add_nothing(void **state) +{ + GString *buf = g_string_new(NULL); + + // Start with empty string + pcmk__g_strcat(buf, NULL); + assert_string_equal((const char *) buf->str, ""); + + pcmk__g_strcat(buf, "", NULL); + assert_string_equal((const char *) buf->str, ""); + + // Start with populated string + g_string_append(buf, "hello"); + pcmk__g_strcat(buf, NULL); + assert_string_equal((const char *) buf->str, "hello"); + + pcmk__g_strcat(buf, "", NULL); + assert_string_equal((const char *) buf->str, "hello"); + g_string_free(buf, TRUE); +} + +static void +add_words(void **state) +{ + GString *buf = g_string_new(NULL); + + // Verify a call with multiple words + pcmk__g_strcat(buf, "hello", " ", NULL); + assert_string_equal((const char *) buf->str, "hello "); + + // Verify that a second call doesn't overwrite the first one + pcmk__g_strcat(buf, "world", NULL); + assert_string_equal((const char *) buf->str, "hello world"); + g_string_free(buf, TRUE); +} + +static void +stop_early(void **state) +{ + GString *buf = g_string_new(NULL); + + // NULL anywhere after buf in the arg list should cause a return + pcmk__g_strcat(buf, "hello", NULL, " world", NULL); + assert_string_equal((const char *) buf->str, "hello"); + g_string_free(buf, TRUE); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(add_to_null), + cmocka_unit_test(add_nothing), + cmocka_unit_test(add_words), + cmocka_unit_test(stop_early)) diff --git a/lib/common/tests/strings/pcmk__guint_from_hash_test.c b/lib/common/tests/strings/pcmk__guint_from_hash_test.c new file mode 100644 index 0000000..e2b4762 --- /dev/null +++ b/lib/common/tests/strings/pcmk__guint_from_hash_test.c @@ -0,0 +1,76 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include + +static void +null_args(void **state) +{ + GHashTable *tbl = pcmk__strkey_table(free, free); + guint result; + + assert_int_equal(pcmk__guint_from_hash(NULL, "abc", 123, &result), EINVAL); + assert_int_equal(pcmk__guint_from_hash(tbl, NULL, 123, &result), EINVAL); + + g_hash_table_destroy(tbl); +} + +static void +missing_key(void **state) +{ + GHashTable *tbl = pcmk__strkey_table(free, free); + guint result; + + assert_int_equal(pcmk__guint_from_hash(tbl, "abc", 123, &result), pcmk_rc_ok); + assert_int_equal(result, 123); + + g_hash_table_destroy(tbl); +} + +static void +standard_usage(void **state) +{ + GHashTable *tbl = pcmk__strkey_table(free, free); + guint result; + + g_hash_table_insert(tbl, strdup("abc"), strdup("123")); + + assert_int_equal(pcmk__guint_from_hash(tbl, "abc", 456, &result), pcmk_rc_ok); + assert_int_equal(result, 123); + + g_hash_table_destroy(tbl); +} + +static void +conversion_errors(void **state) +{ + GHashTable *tbl = pcmk__strkey_table(free, free); + guint result; + + g_hash_table_insert(tbl, strdup("negative"), strdup("-3")); + g_hash_table_insert(tbl, strdup("toobig"), strdup("20000000000000000")); + + assert_int_equal(pcmk__guint_from_hash(tbl, "negative", 456, &result), ERANGE); + assert_int_equal(result, 456); + + assert_int_equal(pcmk__guint_from_hash(tbl, "toobig", 456, &result), ERANGE); + assert_int_equal(result, 456); + + g_hash_table_destroy(tbl); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(null_args), + cmocka_unit_test(missing_key), + cmocka_unit_test(standard_usage), + cmocka_unit_test(conversion_errors)) diff --git a/lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c b/lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c new file mode 100644 index 0000000..df7b11c --- /dev/null +++ b/lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c @@ -0,0 +1,79 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +null_ptr(void **state) +{ + pcmk__assert_asserts(pcmk__numeric_strcasecmp(NULL, NULL)); + pcmk__assert_asserts(pcmk__numeric_strcasecmp("a", NULL)); + pcmk__assert_asserts(pcmk__numeric_strcasecmp(NULL, "a")); +} + +static void +no_numbers(void **state) +{ + /* All comparisons are done case-insensitively. */ + assert_int_equal(pcmk__numeric_strcasecmp("abcd", "efgh"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("abcd", "abcd"), 0); + assert_int_equal(pcmk__numeric_strcasecmp("efgh", "abcd"), 1); + + assert_int_equal(pcmk__numeric_strcasecmp("AbCd", "eFgH"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("ABCD", "abcd"), 0); + assert_int_equal(pcmk__numeric_strcasecmp("EFgh", "ABcd"), 1); +} + +static void +trailing_numbers(void **state) +{ + assert_int_equal(pcmk__numeric_strcasecmp("node1", "node2"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("node1", "node1"), 0); + assert_int_equal(pcmk__numeric_strcasecmp("node2", "node1"), 1); + + assert_int_equal(pcmk__numeric_strcasecmp("node1", "node10"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("node10", "node10"), 0); + assert_int_equal(pcmk__numeric_strcasecmp("node10", "node1"), 1); + + assert_int_equal(pcmk__numeric_strcasecmp("node10", "remotenode9"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("remotenode9", "node10"), 1); + + /* Longer numbers sort higher than shorter numbers. */ + assert_int_equal(pcmk__numeric_strcasecmp("node001", "node1"), 1); + assert_int_equal(pcmk__numeric_strcasecmp("node1", "node001"), -1); +} + +static void +middle_numbers(void **state) +{ + assert_int_equal(pcmk__numeric_strcasecmp("node1abc", "node1def"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("node1def", "node1abc"), 1); + + assert_int_equal(pcmk__numeric_strcasecmp("node1abc", "node2abc"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("node2abc", "node1abc"), 1); +} + +static void +unequal_lengths(void **state) +{ + assert_int_equal(pcmk__numeric_strcasecmp("node-ab", "node-abc"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("node-abc", "node-ab"), 1); + + assert_int_equal(pcmk__numeric_strcasecmp("node1ab", "node1abc"), -1); + assert_int_equal(pcmk__numeric_strcasecmp("node1abc", "node1ab"), 1); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(null_ptr), + cmocka_unit_test(no_numbers), + cmocka_unit_test(trailing_numbers), + cmocka_unit_test(middle_numbers), + cmocka_unit_test(unequal_lengths)) diff --git a/lib/common/tests/strings/pcmk__parse_ll_range_test.c b/lib/common/tests/strings/pcmk__parse_ll_range_test.c new file mode 100644 index 0000000..7656ad7 --- /dev/null +++ b/lib/common/tests/strings/pcmk__parse_ll_range_test.c @@ -0,0 +1,117 @@ +/* + * Copyright 2020-2023 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include "crm/common/results.h" +#include + +#include + +static void +empty_input_string(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range(NULL, &start, &end), ENODATA); + assert_int_equal(pcmk__parse_ll_range("", &start, &end), ENODATA); +} + +static void +null_input_variables(void **state) +{ + long long start, end; + + pcmk__assert_asserts(pcmk__parse_ll_range("1234", NULL, &end)); + pcmk__assert_asserts(pcmk__parse_ll_range("1234", &start, NULL)); +} + +static void +missing_separator(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range("1234", &start, &end), pcmk_rc_ok); + assert_int_equal(start, 1234); + assert_int_equal(end, 1234); +} + +static void +only_separator(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range("-", &start, &end), pcmk_rc_bad_input); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); +} + +static void +no_range_end(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range("2000-", &start, &end), pcmk_rc_ok); + assert_int_equal(start, 2000); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); +} + +static void +no_range_start(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range("-2020", &start, &end), pcmk_rc_ok); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, 2020); +} + +static void +range_start_and_end(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range("2000-2020", &start, &end), pcmk_rc_ok); + assert_int_equal(start, 2000); + assert_int_equal(end, 2020); + + assert_int_equal(pcmk__parse_ll_range("2000-2020-2030", &start, &end), pcmk_rc_bad_input); +} + +static void +garbage(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range("2000x-", &start, &end), pcmk_rc_bad_input); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); + + assert_int_equal(pcmk__parse_ll_range("-x2000", &start, &end), pcmk_rc_bad_input); + assert_int_equal(start, PCMK__PARSE_INT_DEFAULT); + assert_int_equal(end, PCMK__PARSE_INT_DEFAULT); +} + +static void +strtoll_errors(void **state) +{ + long long start, end; + + assert_int_equal(pcmk__parse_ll_range("20000000000000000000-", &start, &end), EOVERFLOW); + assert_int_equal(pcmk__parse_ll_range("100-20000000000000000000", &start, &end), EOVERFLOW); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_input_string), + cmocka_unit_test(null_input_variables), + cmocka_unit_test(missing_separator), + cmocka_unit_test(only_separator), + cmocka_unit_test(no_range_end), + cmocka_unit_test(no_range_start), + cmocka_unit_test(range_start_and_end), + cmocka_unit_test(strtoll_errors), + cmocka_unit_test(garbage)) diff --git a/lib/common/tests/strings/pcmk__s_test.c b/lib/common/tests/strings/pcmk__s_test.c new file mode 100644 index 0000000..cdc2551 --- /dev/null +++ b/lib/common/tests/strings/pcmk__s_test.c @@ -0,0 +1,29 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +s_is_null(void **state) { + assert_null(pcmk__s(NULL, NULL)); + assert_string_equal(pcmk__s(NULL, ""), ""); + assert_string_equal(pcmk__s(NULL, "something"), "something"); +} + +static void +s_is_not_null(void **state) { + assert_string_equal(pcmk__s("something", NULL), "something"); + assert_string_equal(pcmk__s("something", "default"), "something"); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(s_is_null), + cmocka_unit_test(s_is_not_null)) diff --git a/lib/common/tests/strings/pcmk__scan_double_test.c b/lib/common/tests/strings/pcmk__scan_double_test.c new file mode 100644 index 0000000..a1a180a --- /dev/null +++ b/lib/common/tests/strings/pcmk__scan_double_test.c @@ -0,0 +1,158 @@ +/* + * Copyright 2004-2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include // DBL_MAX, etc. +#include // fabs() + +// Ensure plenty of characters for %f display +#define LOCAL_BUF_SIZE 2 * DBL_MAX_10_EXP + +/* + * assert_float_equal doesn't exist for older versions of cmocka installed on some + * of our builders, so define it in terms of regular assert() here in that case. + */ +#if HAVE_DECL_ASSERT_FLOAT_EQUAL == 0 +#define assert_float_equal(a, b, epsilon) assert_true(fabs((a) - (b)) < (epsilon)) +#endif + +static void +empty_input_string(void **state) +{ + double result; + + // Without default_text + assert_int_equal(pcmk__scan_double(NULL, &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); + + assert_int_equal(pcmk__scan_double("", &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); + + // With default_text + assert_int_equal(pcmk__scan_double(NULL, &result, "2.0", NULL), pcmk_rc_ok); + assert_float_equal(result, 2.0, DBL_EPSILON); + + assert_int_equal(pcmk__scan_double("", &result, "2.0", NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); +} + +static void +bad_input_string(void **state) +{ + double result; + + // Without default text + assert_int_equal(pcmk__scan_double("asdf", &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); + + assert_int_equal(pcmk__scan_double("as2.0", &result, NULL, NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); + + // With default text (not used) + assert_int_equal(pcmk__scan_double("asdf", &result, "2.0", NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); + + assert_int_equal(pcmk__scan_double("as2.0", &result, "2.0", NULL), EINVAL); + assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON); +} + +static void +trailing_chars(void **state) +{ + double result; + char *end_text; + + assert_int_equal(pcmk__scan_double("2.0asdf", &result, NULL, &end_text), pcmk_rc_ok); + assert_float_equal(result, 2.0, DBL_EPSILON); + assert_string_equal(end_text, "asdf"); +} + +static void +no_result_variable(void **state) +{ + pcmk__assert_asserts(pcmk__scan_double("asdf", NULL, NULL, NULL)); +} + +static void +typical_case(void **state) +{ + char str[LOCAL_BUF_SIZE]; + double result; + + assert_int_equal(pcmk__scan_double("0.0", &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, 0.0, DBL_EPSILON); + + assert_int_equal(pcmk__scan_double("1.0", &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, 1.0, DBL_EPSILON); + + assert_int_equal(pcmk__scan_double("-1.0", &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, -1.0, DBL_EPSILON); + + snprintf(str, LOCAL_BUF_SIZE, "%f", DBL_MAX); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, DBL_MAX, DBL_EPSILON); + + snprintf(str, LOCAL_BUF_SIZE, "%f", -DBL_MAX); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_ok); + assert_float_equal(result, -DBL_MAX, DBL_EPSILON); +} + +static void +double_overflow(void **state) +{ + char str[LOCAL_BUF_SIZE]; + double result; + + /* + * 1e(DBL_MAX_10_EXP + 1) produces an inf value + * Can't use assert_float_equal() because (inf - inf) == NaN + */ + snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MAX_10_EXP + 1); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), EOVERFLOW); + assert_true(result > DBL_MAX); + + snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MAX_10_EXP + 1); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), EOVERFLOW); + assert_true(result < -DBL_MAX); +} + +static void +double_underflow(void **state) +{ + char str[LOCAL_BUF_SIZE]; + double result; + + /* + * 1e(DBL_MIN_10_EXP - 1) produces a denormalized value (between 0 + * and DBL_MIN) + * + * C99/C11: result will be **no greater than** DBL_MIN + */ + snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MIN_10_EXP - 1); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_underflow); + assert_true(result >= 0.0); + assert_true(result <= DBL_MIN); + + snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MIN_10_EXP - 1); + assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_underflow); + assert_true(result <= 0.0); + assert_true(result >= -DBL_MIN); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_input_string), + cmocka_unit_test(bad_input_string), + cmocka_unit_test(trailing_chars), + cmocka_unit_test(no_result_variable), + cmocka_unit_test(typical_case), + cmocka_unit_test(double_overflow), + cmocka_unit_test(double_underflow)) diff --git a/lib/common/tests/strings/pcmk__scan_min_int_test.c b/lib/common/tests/strings/pcmk__scan_min_int_test.c new file mode 100644 index 0000000..90c3e87 --- /dev/null +++ b/lib/common/tests/strings/pcmk__scan_min_int_test.c @@ -0,0 +1,60 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +empty_input_string(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_min_int("", &result, 1), EINVAL); + assert_int_equal(result, 1); + + assert_int_equal(pcmk__scan_min_int(NULL, &result, 1), pcmk_rc_ok); + assert_int_equal(result, 1); +} + +static void +input_below_minimum(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_min_int("100", &result, 1024), pcmk_rc_ok); + assert_int_equal(result, 1024); +} + +static void +input_above_maximum(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_min_int("20000000000000000", &result, 100), EOVERFLOW); + assert_int_equal(result, INT_MAX); +} + +static void +input_just_right(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_min_int("1024", &result, 1024), pcmk_rc_ok); + assert_int_equal(result, 1024); + + assert_int_equal(pcmk__scan_min_int("2048", &result, 1024), pcmk_rc_ok); + assert_int_equal(result, 2048); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_input_string), + cmocka_unit_test(input_below_minimum), + cmocka_unit_test(input_above_maximum), + cmocka_unit_test(input_just_right)) diff --git a/lib/common/tests/strings/pcmk__scan_port_test.c b/lib/common/tests/strings/pcmk__scan_port_test.c new file mode 100644 index 0000000..cf927e4 --- /dev/null +++ b/lib/common/tests/strings/pcmk__scan_port_test.c @@ -0,0 +1,59 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +empty_input_string(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_port("", &result), EINVAL); + assert_int_equal(result, -1); +} + +static void +bad_input_string(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_port("abc", &result), EINVAL); + assert_int_equal(result, -1); +} + +static void +out_of_range(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_port("-1", &result), pcmk_rc_before_range); + assert_int_equal(result, -1); + assert_int_equal(pcmk__scan_port("65536", &result), pcmk_rc_after_range); + assert_int_equal(result, -1); +} + +static void +typical_case(void **state) +{ + int result; + + assert_int_equal(pcmk__scan_port("0", &result), pcmk_rc_ok); + assert_int_equal(result, 0); + + assert_int_equal(pcmk__scan_port("80", &result), pcmk_rc_ok); + assert_int_equal(result, 80); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_input_string), + cmocka_unit_test(bad_input_string), + cmocka_unit_test(out_of_range), + cmocka_unit_test(typical_case)) diff --git a/lib/common/tests/strings/pcmk__starts_with_test.c b/lib/common/tests/strings/pcmk__starts_with_test.c new file mode 100644 index 0000000..5429417 --- /dev/null +++ b/lib/common/tests/strings/pcmk__starts_with_test.c @@ -0,0 +1,35 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +bad_input(void **state) { + assert_false(pcmk__starts_with(NULL, "x")); + assert_false(pcmk__starts_with("abc", NULL)); +} + +static void +starts_with(void **state) { + assert_true(pcmk__starts_with("abc", "a")); + assert_true(pcmk__starts_with("abc", "ab")); + assert_true(pcmk__starts_with("abc", "abc")); + + assert_false(pcmk__starts_with("abc", "A")); + assert_false(pcmk__starts_with("abc", "bc")); + + assert_false(pcmk__starts_with("", "x")); + assert_true(pcmk__starts_with("xyz", "")); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(bad_input), + cmocka_unit_test(starts_with)) diff --git a/lib/common/tests/strings/pcmk__str_any_of_test.c b/lib/common/tests/strings/pcmk__str_any_of_test.c new file mode 100644 index 0000000..bd4ae2c --- /dev/null +++ b/lib/common/tests/strings/pcmk__str_any_of_test.c @@ -0,0 +1,48 @@ +/* + * Copyright 2020-2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +empty_input_list(void **state) { + assert_false(pcmk__strcase_any_of("xxx", NULL)); + assert_false(pcmk__str_any_of("xxx", NULL)); + assert_false(pcmk__strcase_any_of("", NULL)); + assert_false(pcmk__str_any_of("", NULL)); +} + +static void +empty_string(void **state) { + assert_false(pcmk__strcase_any_of("", "xxx", "yyy", NULL)); + assert_false(pcmk__str_any_of("", "xxx", "yyy", NULL)); + assert_false(pcmk__strcase_any_of(NULL, "xxx", "yyy", NULL)); + assert_false(pcmk__str_any_of(NULL, "xxx", "yyy", NULL)); +} + +static void +in_list(void **state) { + assert_true(pcmk__strcase_any_of("xxx", "aaa", "bbb", "xxx", NULL)); + assert_true(pcmk__str_any_of("xxx", "aaa", "bbb", "xxx", NULL)); + assert_true(pcmk__strcase_any_of("XXX", "aaa", "bbb", "xxx", NULL)); +} + +static void +not_in_list(void **state) { + assert_false(pcmk__strcase_any_of("xxx", "aaa", "bbb", NULL)); + assert_false(pcmk__str_any_of("xxx", "aaa", "bbb", NULL)); + assert_false(pcmk__str_any_of("AAA", "aaa", "bbb", NULL)); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_input_list), + cmocka_unit_test(empty_string), + cmocka_unit_test(in_list), + cmocka_unit_test(not_in_list)) diff --git a/lib/common/tests/strings/pcmk__str_in_list_test.c b/lib/common/tests/strings/pcmk__str_in_list_test.c new file mode 100644 index 0000000..cff536a --- /dev/null +++ b/lib/common/tests/strings/pcmk__str_in_list_test.c @@ -0,0 +1,107 @@ +/* + * Copyright 2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include + +static void +empty_input_list(void **state) { + assert_false(pcmk__str_in_list(NULL, NULL, pcmk__str_none)); + assert_false(pcmk__str_in_list(NULL, NULL, pcmk__str_null_matches)); + assert_false(pcmk__str_in_list("xxx", NULL, pcmk__str_none)); + assert_false(pcmk__str_in_list("", NULL, pcmk__str_none)); +} + +static void +empty_string(void **state) { + GList *list = NULL; + + list = g_list_prepend(list, (gpointer) "xxx"); + + assert_false(pcmk__str_in_list(NULL, list, pcmk__str_none)); + assert_true(pcmk__str_in_list(NULL, list, pcmk__str_null_matches)); + assert_false(pcmk__str_in_list("", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("", list, pcmk__str_null_matches)); + + g_list_free(list); +} + +static void +star_matches(void **state) { + GList *list = NULL; + + list = g_list_prepend(list, (gpointer) "*"); + list = g_list_append(list, (gpointer) "more"); + + assert_true(pcmk__str_in_list("xxx", list, pcmk__str_star_matches)); + assert_true(pcmk__str_in_list("yyy", list, pcmk__str_star_matches)); + assert_true(pcmk__str_in_list("XXX", list, pcmk__str_star_matches|pcmk__str_casei)); + assert_true(pcmk__str_in_list("", list, pcmk__str_star_matches)); + + g_list_free(list); +} + +static void +star_doesnt_match(void **state) { + GList *list = NULL; + + list = g_list_prepend(list, (gpointer) "*"); + + assert_false(pcmk__str_in_list("xxx", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("yyy", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("XXX", list, pcmk__str_casei)); + assert_false(pcmk__str_in_list("", list, pcmk__str_none)); + assert_false(pcmk__str_in_list(NULL, list, pcmk__str_star_matches)); + + g_list_free(list); +} + +static void +in_list(void **state) { + GList *list = NULL; + + list = g_list_prepend(list, (gpointer) "xxx"); + list = g_list_prepend(list, (gpointer) "yyy"); + list = g_list_prepend(list, (gpointer) "zzz"); + + assert_true(pcmk__str_in_list("xxx", list, pcmk__str_none)); + assert_true(pcmk__str_in_list("XXX", list, pcmk__str_casei)); + assert_true(pcmk__str_in_list("yyy", list, pcmk__str_none)); + assert_true(pcmk__str_in_list("YYY", list, pcmk__str_casei)); + assert_true(pcmk__str_in_list("zzz", list, pcmk__str_none)); + assert_true(pcmk__str_in_list("ZZZ", list, pcmk__str_casei)); + + g_list_free(list); +} + +static void +not_in_list(void **state) { + GList *list = NULL; + + list = g_list_prepend(list, (gpointer) "xxx"); + list = g_list_prepend(list, (gpointer) "yyy"); + + assert_false(pcmk__str_in_list("xx", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("XXX", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("zzz", list, pcmk__str_none)); + assert_false(pcmk__str_in_list("zzz", list, pcmk__str_casei)); + + g_list_free(list); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_input_list), + cmocka_unit_test(empty_string), + cmocka_unit_test(star_matches), + cmocka_unit_test(star_doesnt_match), + cmocka_unit_test(in_list), + cmocka_unit_test(not_in_list)) diff --git a/lib/common/tests/strings/pcmk__str_table_dup_test.c b/lib/common/tests/strings/pcmk__str_table_dup_test.c new file mode 100644 index 0000000..754bde6 --- /dev/null +++ b/lib/common/tests/strings/pcmk__str_table_dup_test.c @@ -0,0 +1,59 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include + +static void +null_input_table(void **state) +{ + assert_null(pcmk__str_table_dup(NULL)); +} + +static void +empty_input_table(void **state) +{ + GHashTable *tbl = pcmk__strkey_table(free, free); + GHashTable *copy = NULL; + + copy = pcmk__str_table_dup(tbl); + assert_int_equal(g_hash_table_size(copy), 0); + + g_hash_table_destroy(tbl); + g_hash_table_destroy(copy); +} + +static void +regular_input_table(void **state) +{ + GHashTable *tbl = pcmk__strkey_table(free, free); + GHashTable *copy = NULL; + + g_hash_table_insert(tbl, strdup("abc"), strdup("123")); + g_hash_table_insert(tbl, strdup("def"), strdup("456")); + g_hash_table_insert(tbl, strdup("ghi"), strdup("789")); + + copy = pcmk__str_table_dup(tbl); + assert_int_equal(g_hash_table_size(copy), 3); + + assert_string_equal(g_hash_table_lookup(tbl, "abc"), "123"); + assert_string_equal(g_hash_table_lookup(tbl, "def"), "456"); + assert_string_equal(g_hash_table_lookup(tbl, "ghi"), "789"); + + g_hash_table_destroy(tbl); + g_hash_table_destroy(copy); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(null_input_table), + cmocka_unit_test(empty_input_table), + cmocka_unit_test(regular_input_table)) diff --git a/lib/common/tests/strings/pcmk__str_update_test.c b/lib/common/tests/strings/pcmk__str_update_test.c new file mode 100644 index 0000000..571031d --- /dev/null +++ b/lib/common/tests/strings/pcmk__str_update_test.c @@ -0,0 +1,78 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include "mock_private.h" + +static void +update_null(void **state) { + char *str = NULL; + + // These just make sure they don't crash + pcmk__str_update(NULL, NULL); + pcmk__str_update(NULL, "value"); + + // Update an already NULL string to NULL + pcmk__str_update(&str, NULL); + assert_null(str); + + // Update an already allocated string to NULL + str = strdup("hello"); + pcmk__str_update(&str, NULL); + assert_null(str); +} + +static void +update_same(void **state) { + char *str = NULL; + char *saved = NULL; + + str = strdup("hello"); + saved = str; + pcmk__str_update(&str, "hello"); + assert_ptr_equal(saved, str); // No free and reallocation + free(str); +} + +static void +update_different(void **state) { + char *str = NULL; + + str = strdup("hello"); + pcmk__str_update(&str, "world"); + assert_string_equal(str, "world"); + free(str); +} + +static void +strdup_fails(void **state) { + char *str = NULL; + + str = strdup("hello"); + + pcmk__assert_asserts( + { + pcmk__mock_strdup = true; // strdup() will return NULL + expect_string(__wrap_strdup, s, "world"); + pcmk__str_update(&str, "world"); + pcmk__mock_strdup = false; // Use the real strdup() + } + ); + + free(str); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(update_null), + cmocka_unit_test(update_same), + cmocka_unit_test(update_different), + cmocka_unit_test(strdup_fails)) diff --git a/lib/common/tests/strings/pcmk__strcmp_test.c b/lib/common/tests/strings/pcmk__strcmp_test.c new file mode 100644 index 0000000..a709f18 --- /dev/null +++ b/lib/common/tests/strings/pcmk__strcmp_test.c @@ -0,0 +1,80 @@ +/* + * Copyright 2020-2021 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +static void +same_pointer(void **state) { + const char *s1 = "abcd"; + const char *s2 = "wxyz"; + + assert_int_equal(pcmk__strcmp(s1, s1, pcmk__str_none), 0); + assert_true(pcmk__str_eq(s1, s1, pcmk__str_none)); + assert_int_not_equal(pcmk__strcmp(s1, s2, pcmk__str_none), 0); + assert_false(pcmk__str_eq(s1, s2, pcmk__str_none)); + assert_int_equal(pcmk__strcmp(NULL, NULL, pcmk__str_none), 0); +} + +static void +one_is_null(void **state) { + const char *s1 = "abcd"; + + assert_int_equal(pcmk__strcmp(s1, NULL, pcmk__str_null_matches), 0); + assert_true(pcmk__str_eq(s1, NULL, pcmk__str_null_matches)); + assert_int_equal(pcmk__strcmp(NULL, s1, pcmk__str_null_matches), 0); + assert_true(pcmk__strcmp(s1, NULL, pcmk__str_none) > 0); + assert_false(pcmk__str_eq(s1, NULL, pcmk__str_none)); + assert_true(pcmk__strcmp(NULL, s1, pcmk__str_none) < 0); +} + +static void +case_matters(void **state) { + const char *s1 = "abcd"; + const char *s2 = "ABCD"; + + assert_true(pcmk__strcmp(s1, s2, pcmk__str_none) > 0); + assert_false(pcmk__str_eq(s1, s2, pcmk__str_none)); + assert_true(pcmk__strcmp(s2, s1, pcmk__str_none) < 0); +} + +static void +case_insensitive(void **state) { + const char *s1 = "abcd"; + const char *s2 = "ABCD"; + + assert_int_equal(pcmk__strcmp(s1, s2, pcmk__str_casei), 0); + assert_true(pcmk__str_eq(s1, s2, pcmk__str_casei)); +} + +static void +regex(void **state) { + const char *s1 = "abcd"; + const char *s2 = "ABCD"; + + assert_true(pcmk__strcmp(NULL, "a..d", pcmk__str_regex) > 0); + assert_true(pcmk__strcmp(s1, NULL, pcmk__str_regex) > 0); + assert_int_equal(pcmk__strcmp(s1, "a..d", pcmk__str_regex), 0); + assert_true(pcmk__str_eq(s1, "a..d", pcmk__str_regex)); + assert_int_not_equal(pcmk__strcmp(s1, "xxyy", pcmk__str_regex), 0); + assert_false(pcmk__str_eq(s1, "xxyy", pcmk__str_regex)); + assert_int_equal(pcmk__strcmp(s2, "a..d", pcmk__str_regex|pcmk__str_casei), 0); + assert_true(pcmk__str_eq(s2, "a..d", pcmk__str_regex|pcmk__str_casei)); + assert_int_not_equal(pcmk__strcmp(s2, "a..d", pcmk__str_regex), 0); + assert_false(pcmk__str_eq(s2, "a..d", pcmk__str_regex)); + assert_true(pcmk__strcmp(s2, "*ab", pcmk__str_regex) > 0); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(same_pointer), + cmocka_unit_test(one_is_null), + cmocka_unit_test(case_matters), + cmocka_unit_test(case_insensitive), + cmocka_unit_test(regex)) diff --git a/lib/common/tests/strings/pcmk__strikey_table_test.c b/lib/common/tests/strings/pcmk__strikey_table_test.c new file mode 100644 index 0000000..d5f8635 --- /dev/null +++ b/lib/common/tests/strings/pcmk__strikey_table_test.c @@ -0,0 +1,40 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include + +static void +store_strs(void **state) +{ + GHashTable *tbl = NULL; + + tbl = pcmk__strikey_table(free, free); + assert_non_null(tbl); + + assert_true(g_hash_table_insert(tbl, strdup("key-abc"), strdup("val-abc"))); + assert_int_equal(g_hash_table_size(tbl), 1); + assert_string_equal(g_hash_table_lookup(tbl, "key-abc"), "val-abc"); + + assert_false(g_hash_table_insert(tbl, strdup("key-abc"), strdup("val-def"))); + assert_int_equal(g_hash_table_size(tbl), 1); + assert_string_equal(g_hash_table_lookup(tbl, "key-abc"), "val-def"); + + assert_false(g_hash_table_insert(tbl, strdup("key-ABC"), strdup("val-ABC"))); + assert_int_equal(g_hash_table_size(tbl), 1); + assert_string_equal(g_hash_table_lookup(tbl, "key-ABC"), "val-ABC"); + + g_hash_table_destroy(tbl); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(store_strs)) diff --git a/lib/common/tests/strings/pcmk__strkey_table_test.c b/lib/common/tests/strings/pcmk__strkey_table_test.c new file mode 100644 index 0000000..ac6d92e --- /dev/null +++ b/lib/common/tests/strings/pcmk__strkey_table_test.c @@ -0,0 +1,40 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include + +static void +store_strs(void **state) +{ + GHashTable *tbl = NULL; + + tbl = pcmk__strkey_table(free, free); + assert_non_null(tbl); + + assert_true(g_hash_table_insert(tbl, strdup("key-abc"), strdup("val-abc"))); + assert_int_equal(g_hash_table_size(tbl), 1); + assert_string_equal(g_hash_table_lookup(tbl, "key-abc"), "val-abc"); + + assert_false(g_hash_table_insert(tbl, strdup("key-abc"), strdup("val-def"))); + assert_int_equal(g_hash_table_size(tbl), 1); + assert_string_equal(g_hash_table_lookup(tbl, "key-abc"), "val-def"); + + assert_true(g_hash_table_insert(tbl, strdup("key-ABC"), strdup("val-abc"))); + assert_int_equal(g_hash_table_size(tbl), 2); + assert_string_equal(g_hash_table_lookup(tbl, "key-ABC"), "val-abc"); + + g_hash_table_destroy(tbl); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(store_strs)) diff --git a/lib/common/tests/strings/pcmk__trim_test.c b/lib/common/tests/strings/pcmk__trim_test.c new file mode 100644 index 0000000..56bdd17 --- /dev/null +++ b/lib/common/tests/strings/pcmk__trim_test.c @@ -0,0 +1,72 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU General Public License version 2 + * or later (GPLv2+) WITHOUT ANY WARRANTY. + */ + +#include + +#include + +#include + +static void +empty_input(void **state) +{ + char *s = strdup(""); + + assert_null(pcmk__trim(NULL)); + assert_string_equal(pcmk__trim(s), ""); + + free(s); +} + +static void +leading_newline(void **state) +{ + char *s = strdup("\nabcd"); + + assert_string_equal(pcmk__trim(s), "\nabcd"); + free(s); +} + +static void +middle_newline(void **state) +{ + char *s = strdup("ab\ncd"); + + assert_string_equal(pcmk__trim(s), "ab\ncd"); + free(s); +} + +static void +trailing_newline(void **state) +{ + char *s = strdup("abcd\n\n"); + + assert_string_equal(pcmk__trim(s), "abcd"); + free(s); + + s = strdup("abcd\n "); + assert_string_equal(pcmk__trim(s), "abcd\n "); + free(s); +} + +static void +other_whitespace(void **state) +{ + char *s = strdup(" ab\t\ncd \t"); + + assert_string_equal(pcmk__trim(s), " ab\t\ncd \t"); + free(s); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(empty_input), + cmocka_unit_test(leading_newline), + cmocka_unit_test(middle_newline), + cmocka_unit_test(trailing_newline), + cmocka_unit_test(other_whitespace)) -- cgit v1.2.3