diff --git a/lib/common/tests/rules/Makefile.am b/lib/common/tests/rules/Makefile.am index 3343e2c8a6..7e8c38c391 100644 --- a/lib/common/tests/rules/Makefile.am +++ b/lib/common/tests/rules/Makefile.am @@ -1,18 +1,19 @@ # # Copyright 2020-2024 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 = pcmk__evaluate_date_expression_test \ pcmk__evaluate_date_spec_test \ + pcmk__replace_submatches_test \ pcmk__unpack_duration_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/rules/pcmk__replace_submatches_test.c b/lib/common/tests/rules/pcmk__replace_submatches_test.c new file mode 100644 index 0000000000..e95f20c3e7 --- /dev/null +++ b/lib/common/tests/rules/pcmk__replace_submatches_test.c @@ -0,0 +1,79 @@ +/* + * Copyright 2024 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 // regmatch_t + +#include +#include + +// An example matched string with submatches +static const char *match = "this is a string"; +static const regmatch_t submatches[] = { + { .rm_so = 0, .rm_eo = 16 }, // %0 = entire string + { .rm_so = 5, .rm_eo = 7 }, // %1 = "is" + { .rm_so = 9, .rm_eo = 9 }, // %2 = empty match +}; +static const int nmatches = 3; + +static void +assert_submatch(const char *string, const char *reference) +{ + char *expanded = NULL; + + expanded = pcmk__replace_submatches(string, match, submatches, nmatches); + if ((expanded == NULL) || (reference == NULL)) { + assert_null(expanded); + assert_null(reference); + } else { + assert_int_equal(strcmp(expanded, reference), 0); + } + free(expanded); +} + +static void +no_source(void **state) +{ + assert_null(pcmk__replace_submatches(NULL, NULL, NULL, 0)); + assert_submatch(NULL, NULL); + assert_submatch("", NULL); +} + +static void +source_has_no_variables(void **state) +{ + assert_submatch("this has no submatch variables", + "this has no submatch variables"); + assert_submatch("this ends in a %", "this ends in a %"); + assert_submatch("%this starts with one", "%this starts with one"); +} + +static void +without_matches(void **state) +{ + assert_submatch("this has an empty submatch %2", + "this has an empty submatch "); + assert_submatch("this has a nonexistent submatch %3", + "this has a nonexistent submatch "); +} + +static void +with_matches(void **state) +{ + assert_submatch("%0", match); // %0 matches entire string + assert_submatch("this %1", "this is"); + assert_submatch("%1 this %ok", "is this %ok"); +} + +PCMK__UNIT_TEST(NULL, NULL, + cmocka_unit_test(no_source), + cmocka_unit_test(source_has_no_variables), + cmocka_unit_test(without_matches), + cmocka_unit_test(with_matches))