diff --git a/doc/sphinx/Pacemaker_Development/helpers.rst b/doc/sphinx/Pacemaker_Development/helpers.rst index 94b83d4e00..ecca7d2b67 100644 --- a/doc/sphinx/Pacemaker_Development/helpers.rst +++ b/doc/sphinx/Pacemaker_Development/helpers.rst @@ -1,467 +1,485 @@ C Development Helpers --------------------- .. index:: single: unit testing Refactoring ########### Pacemaker uses an optional tool called `coccinelle `_ to do automatic refactoring. coccinelle is a very complicated tool that can be difficult to understand, and the existing documentation makes it pretty tough to get started. Much of the documentation is either aimed at kernel developers or takes the form of grammars. However, it can apply very complex transformations across an entire source tree. This is useful for tasks like code refactoring, changing APIs (number or type of arguments, etc.), catching functions that should not be called, and changing existing patterns. coccinelle is driven by input scripts called `semantic patches `_ written in its own language. These scripts bear a passing resemblance to source code patches and tell coccinelle how to match and modify a piece of source code. They are stored in ``devel/coccinelle`` and each script either contains a single source transformation or several related transformations. In general, we try to keep these as simple as possible. In Pacemaker development, we use a couple targets in ``devel/Makefile.am`` to control coccinelle. The ``cocci`` target tries to apply each script to every Pacemaker source file, printing out any changes it would make to the console. The ``cocci-inplace`` target does the same but also makes those changes to the source files. A variety of warnings might also be printed. If you aren't working on a new script, these can usually be ignored. If you are working on a new coccinelle script, it can be useful (and faster) to skip everything else and only run the new script. The ``COCCI_FILES`` variable can be used for this: .. code-block:: none $ make -C devel COCCI_FILES=coccinelle/new-file.cocci cocci This variable is also used for preventing some coccinelle scripts in the Pacemaker source tree from running. Some scripts are disabled because they are not currently fully working or because they are there as templates. When adding a new script, remember to add it to this variable if it should always be run. One complication when writing coccinelle scripts is that certain Pacemaker source files may not use private functions (those whose name starts with ``pcmk__``). Handling this requires work in both the Makefile and in the coccinelle scripts. The Makefile deals with this by maintaining two lists of source files: those that may use private functions and those that may not. For those that may, a special argument (``-D internal``) is added to the coccinelle command line. This creates a virtual dependency named ``internal``. In the coccinelle scripts, those transformations that modify source code to use a private function also have a dependency on ``internal``. If that dependency was given on the command line, the transformation will be run. Otherwise, it will be skipped. This means that not all instances of an older style of code will be changed after running a given transformation. Some developer intervention is still necessary to know whether a source code block should have been changed or not. Probably the easiest way to learn how to use coccinelle is by following other people's scripts. In addition to the ones in the Pacemaker source directory, there's several others on the `coccinelle website `_. Sanitizers ########## gcc supports a variety of run-time checks called sanitizers. These can be used to catch programming errors with memory, race conditions, various undefined behavior conditions, and more. Because these are run-time checks, they should only be used during development and not in compiled packages or production code. Certain sanitizers cannot be combined with others because their run-time checks cause interfere. Instead of trying to figure out which combinations work, it is simplest to just enable one at a time. Each supported sanitizer requires an installed libray. In addition to just enabling the sanitizer, their use can be configured with environment variables. For example: .. code-block:: none $ ASAN_OPTIONS=verbosity=1:replace_str=true crm_mon -1R Pacemaker supports the following subset of gcc's sanitizers: +--------------------+-------------------------+----------+----------------------+ | Sanitizer | Configure Option | Library | Environment Variable | +====================+=========================+==========+======================+ | Address | --with-sanitizers=asan | libasan | ASAN_OPTIONS | +--------------------+-------------------------+----------+----------------------+ | Threads | --with-sanitizers=tsan | libtsan | TSAN_OPTIONS | +--------------------+-------------------------+----------+----------------------+ | Undefined behavior | --with-sanitizers=ubsan | libubsan | UBSAN_OPTIONS | +--------------------+-------------------------+----------+----------------------+ The undefined behavior sanitizer further supports suboptions that need to be given as CFLAGS when configuring pacemaker: .. code-block:: none $ CFLAGS=-fsanitize=integer-divide-by-zero ./configure --with-sanitizers=ubsan For more information, see the `gcc documentation `_ which also provides links to more information on each sanitizer. Unit Testing ############ Where possible, changes to the C side of Pacemaker should be accompanied by unit tests. Much of Pacemaker cannot effectively be unit tested (and there are other testing systems used for those parts), but the ``lib`` subdirectory is pretty easy to write tests for. Pacemaker uses the `cmocka unit testing framework `_ which looks a lot like other unit testing frameworks for C and should be fairly familiar. In addition to regular unit tests, cmocka also gives us the ability to use `mock functions `_ for unit testing functions that would otherwise be difficult to test. Organization ____________ Pay close attention to the organization and naming of test cases to ensure the unit tests continue to work as they should. Tests are spread throughout the source tree, alongside the source code they test. For instance, all the tests for the source code in ``lib/common/`` are in the ``lib/common/tests`` directory. If there is no ``tests`` subdirectory, there are no tests for that library yet. Under that directory, there is a ``Makefile.am`` and additional subdirectories. Each subdirectory contains the tests for a single library source file. For instance, all the tests for ``lib/common/strings.c`` are in the ``lib/common/tests/strings`` directory. Note that the test subdirectory does not have a ``.c`` suffix. If there is no test subdirectory, there are no tests for that file yet. Finally, under that directory, there is a ``Makefile.am`` and then various source files. Each of these source files tests the single function that it is named after. For instance, ``lib/common/tests/strings/pcmk__btoa_test.c`` tests the ``pcmk__btoa()`` function in ``lib/common/strings.c``. If there is no test source file, there are no tests for that function yet. The ``_test`` suffix on the test source file is important. All tests have this suffix, which means all the compiled test cases will also end with this suffix. That lets us ignore all the compiled tests with a single line in ``.gitignore``: .. code-block:: none /lib/*/tests/*/*_test Adding a test _____________ Testing a new function in an already testable source file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Follow these steps if you want to test a function in a source file where there are already other tested functions. For the purposes of this example, we will add a test for the ``pcmk__scan_port()`` function in ``lib/common/strings.c``. As you can see, there are already tests for other functions in this same file in the ``lib/common/tests/strings`` directory. * cd into ``lib/common/tests/strings`` * Add the new file to the the ``check_PROGRAMS`` variable in ``Makefile.am``, making it something like this: .. code-block:: none check_PROGRAMS = \ pcmk__add_word_test \ pcmk__btoa_test \ pcmk__scan_port_test -* Double check the setting of ``AM_LDFLAGS`` in ``Makefile.am``. If none of the - tests of this source file require using a mocked function, this should be empty, - like so: - - .. code-block:: none - - AM_LDFLAGS = - - However, if any test (including your new one) uses a mocked function, it should - be set: - - .. code-block:: none - - AM_LDFLAGS = $(LDFLAGS_WRAP) - * Create a new ``pcmk__scan_port_test.c`` file, copying the copyright and include boilerplate from another file in the same directory. * Continue with the steps in `Writing the test`_. Testing a function in a source file without tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Follow these steps if you want to test a function in a source file where there are not already other tested functions, but there are tests for other files in the same library. For the purposes of this example, we will add a test for the ``pcmk_acl_required()`` function in ``lib/common/acls.c``. At the time of this documentation being written, no tests existed for that source file, so there is no ``lib/common/tests/acls`` directory. * Add to ``AC_CONFIG_FILES`` in the top-level ``configure.ac`` file so the build process knows to use directory we're about to create. That variable would now look something like: .. code-block:: none dnl Other files we output AC_CONFIG_FILES(Makefile \ ... lib/common/tests/Makefile \ lib/common/tests/acls/Makefile \ lib/common/tests/agents/Makefile \ ... ) * cd into ``lib/common/tests`` * Add to the ``SUBDIRS`` variable in ``Makefile.am``, making it something like: .. code-block:: none SUBDIRS = agents acls cmdline flags operations strings utils xpath results * Create a new ``acls`` directory, copying the ``Makefile.am`` from some other - directory. + directory. At this time, each ``Makefile.am`` is largely boilerplate with + very little that needs to change from directory to directory. * cd into ``acls`` * Get rid of any existing values for ``check_PROGRAMS`` and set it to ``pcmk_acl_required_test`` like so: .. code-block:: none check_PROGRAMS = pcmk_acl_required_test +* Double check that ``-I$(top_srcdir)/lib/common`` is present in ``AM_CPPFLAGS``. + +* Double check the settings of variables at the top of ``Makefile.am``. The + following block should be present: + + .. code-block:: none + + LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la + AM_CFLAGS = -DPCMK__UNIT_TESTING + AM_LDFLAGS = $(LDFLAGS_WRAP) + * Follow the steps in `Testing a new function in an already testable source file`_ to create the new ``pcmk_acl_required_test.c`` file. Testing a function in a library without tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Adding a test case for a function in a library that doesn't have any test cases to begin with is only slightly more complicated. In general, the steps are the same as for the previous section, except with an additional layer of directory creation. For the purposes of this example, we will add a test case for the ``lrmd_send_resource_alert()`` function in ``lib/lrmd/lrmd_alerts.c``. Note that this may not be a very good function or even library to write actual unit tests for. * Add to ``AC_CONFIG_FILES`` in the top-level ``configure.ac`` file so the build process knows to use directory we're about to create. That variable would now look something like: .. code-block:: none dnl Other files we output AC_CONFIG_FILES(Makefile \ ... lib/lrmd/Makefile \ lib/lrmd/tests/Makefile \ lib/services/Makefile \ ... ) * cd into ``lib/lrmd`` * Create a ``SUBDIRS`` variable in ``Makefile.am`` if it doesn't already exist. Most libraries should not have this variable already. .. code-block:: none SUBDIRS = tests * Create a new ``tests`` directory and add a ``Makefile.am`` with the following contents: .. code-block:: none SUBDIRS = lrmd_alerts * Follow the steps in `Testing a function in a source file without tests`_ to create the rest of the new directory structure. * Follow the steps in `Testing a new function in an already testable source file`_ to create the new ``lrmd_send_resource_alert_test.c`` file. Adding to an existing test case ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If all you need to do is add additional test cases to an existing file, none of the above work is necessary. All you need to do is find the test source file with the name matching your function and add to it and then follow the instructions in `Writing the test`_. Writing the test ________________ A test case file contains a fair amount of boilerplate. For this reason, it's usually easiest to just copy an existing file and adapt it to your needs. However, here's the basic structure: .. code-block:: c /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include - #include - #include - #include - #include - #include + #include /* Put your test-specific includes here */ /* Put your test functions here */ int main(int argc, char **argv) { /* Register your test functions here */ cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } Each test-specific function should test one aspect of the library function, though it can include many assertions if there are many ways of testing that one aspect. For instance, there might be multiple ways of testing regular expression matching: .. code-block:: c 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); } Each test-specific function must also be registered or it will not be called. This is done with ``cmocka_unit_test()`` in the ``main`` function: .. code-block:: c const struct CMUnitTest tests[] = { cmocka_unit_test(regex), }; +Assertions +__________ + +In addition to the `assertions provided by `_, +``unittest_internal.h`` also provides ``pcmk__assert_asserts``. This macro takes an +expression and verifies that the expression aborts due to a failed call to +``CRM_ASSERT`` or some other similar function. It can be used like so: + +.. code-block:: c + + 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)); + } + +Here, ``pcmk__parse_ll_range`` expects non-NULL for its second and third +arguments. If one of those arguments is NULL, ``CRM_ASSERT`` will fail and +the program will abort. ``pcmk__assert_asserts`` checks that the code would +abort and the test passes. If the code does not abort, the test fails. + + Running _______ If you had to create any new files or directories, you will first need to run ``./configure`` from the top level of the source directory. This will regenerate the Makefiles throughout the tree. If you skip this step, your changes will be skipped and you'll be left wondering why the output doesn't match what you expected. To run the tests, simply run ``make check`` after previously building the source with ``make``. The test cases in each directory will be built and then run. This should not take long. If all the tests succeed, you will be back at the prompt. Scrolling back through the history, you should see lines like the following: .. code-block:: none PASS: pcmk__strcmp_test 1 - same_pointer PASS: pcmk__strcmp_test 2 - one_is_null PASS: pcmk__strcmp_test 3 - case_matters PASS: pcmk__strcmp_test 4 - case_insensitive PASS: pcmk__strcmp_test 5 - regex ============================================================================ Testsuite summary for pacemaker 2.1.0 ============================================================================ # TOTAL: 33 # PASS: 33 # SKIP: 0 # XFAIL: 0 # FAIL: 0 # XPASS: 0 # ERROR: 0 ============================================================================ make[7]: Leaving directory '/home/clumens/src/pacemaker/lib/common/tests/strings' The testing process will quit on the first failed test, and you will see lines like these: .. code-block:: none PASS: pcmk__scan_double_test 3 - trailing_chars FAIL: pcmk__scan_double_test 4 - typical_case PASS: pcmk__scan_double_test 5 - double_overflow PASS: pcmk__scan_double_test 6 - double_underflow ERROR: pcmk__scan_double_test - exited with status 1 PASS: pcmk__starts_with_test 1 - bad_input ============================================================================ Testsuite summary for pacemaker 2.1.0 ============================================================================ # TOTAL: 56 # PASS: 54 # SKIP: 0 # XFAIL: 0 # FAIL: 1 # XPASS: 0 # ERROR: 1 ============================================================================ See lib/common/tests/strings/test-suite.log Please report to users@clusterlabs.org ============================================================================ make[7]: *** [Makefile:1218: test-suite.log] Error 1 make[7]: Leaving directory '/home/clumens/src/pacemaker/lib/common/tests/strings' The failure is in ``lib/common/tests/strings/test-suite.log``: .. code-block:: none ERROR: pcmk__scan_double_test ============================= 1..6 ok 1 - empty_input_string PASS: pcmk__scan_double_test 1 - empty_input_string ok 2 - bad_input_string PASS: pcmk__scan_double_test 2 - bad_input_string ok 3 - trailing_chars PASS: pcmk__scan_double_test 3 - trailing_chars not ok 4 - typical_case FAIL: pcmk__scan_double_test 4 - typical_case # 0.000000 != 3.000000 # pcmk__scan_double_test.c:80: error: Failure! ok 5 - double_overflow PASS: pcmk__scan_double_test 5 - double_overflow ok 6 - double_underflow PASS: pcmk__scan_double_test 6 - double_underflow # not ok - tests ERROR: pcmk__scan_double_test - exited with status 1 At this point, you need to determine whether your test case is incorrect or whether the code being tested is incorrect. Fix whichever is wrong and continue. Debugging ######### gdb ___ If you use ``gdb`` for debugging, some helper functions are defined in ``devel/gdbhelpers``, which can be given to ``gdb`` using the ``-x`` option. From within the debugger, you can then invoke the ``pcmk`` command that will describe the helper functions available. diff --git a/include/crm/common/Makefile.am b/include/crm/common/Makefile.am index dcfe7ce926..e181123358 100644 --- a/include/crm/common/Makefile.am +++ b/include/crm/common/Makefile.am @@ -1,53 +1,54 @@ # # 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. # MAINTAINERCLEANFILES = Makefile.in headerdir=$(pkgincludedir)/crm/common header_HEADERS = acl.h \ agents.h \ agents_compat.h \ cib.h \ ipc.h \ ipc_attrd_internal.h \ ipc_controld.h \ ipc_pacemakerd.h \ ipc_schedulerd.h \ iso8601.h \ logging.h \ logging_compat.h \ mainloop.h \ mainloop_compat.h \ nvpair.h \ output.h \ results.h \ results_compat.h \ util.h \ util_compat.h \ xml.h \ xml_compat.h noinst_HEADERS = acl_internal.h \ alerts_internal.h \ attrd_internal.h \ cmdline_internal.h \ health_internal.h \ internal.h \ ipc_internal.h \ iso8601_internal.h \ lists_internal.h \ logging_internal.h \ messages_internal.h \ options_internal.h \ output_internal.h \ remote_internal.h \ results_internal.h \ strings_internal.h \ + unittest_internal.h \ xml_internal.h diff --git a/include/crm/common/unittest_internal.h b/include/crm/common/unittest_internal.h new file mode 100644 index 0000000000..096b2072d3 --- /dev/null +++ b/include/crm/common/unittest_internal.h @@ -0,0 +1,56 @@ +/* + * 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 Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef CRM_COMMON_UNITTEST_INTERNAL__H +#define CRM_COMMON_UNITTEST_INTERNAL__H + +/* internal unit testing related utilities */ + +/* A cmocka-like assert macro for use in unit testing. This one verifies that + * an expression aborts through CRM_ASSERT, erroring out if that is not the case. + * + * This macro works by running the expression in a forked child process with core + * dumps disabled (CRM_ASSERT calls abort(), which will write out a core dump). + * The parent waits for the child to exit and checks why. If the child received + * a SIGABRT, the test passes. For all other cases, the test fails. + */ +#define pcmk__assert_asserts(expr) \ + do { \ + pid_t p = fork(); \ + if (p == 0) { \ + struct rlimit cores = { 0, 0 }; \ + setrlimit(RLIMIT_CORE, &cores); \ + expr; \ + _exit(0); \ + } else if (p > 0) { \ + int wstatus = 0; \ + if (waitpid(p, &wstatus, 0) == -1) { \ + fail_msg("waitpid failed"); \ + } \ + if (!(WIFSIGNALED(wstatus) && WTERMSIG(wstatus) == SIGABRT)) { \ + fail_msg("expr terminated without asserting"); \ + } \ + } else { \ + fail_msg("unable to fork for assert test"); \ + } \ + } while (0); + +#endif /* CRM_COMMON_UNITTEST_INTERNAL__H */ diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am index 68a8e9ab5c..1311738ed2 100644 --- a/lib/common/Makefile.am +++ b/lib/common/Makefile.am @@ -1,112 +1,121 @@ # # 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 $(top_srcdir)/mk/common.mk AM_CPPFLAGS += -I$(top_builddir)/lib/gnu -I$(top_srcdir)/lib/gnu ## libraries lib_LTLIBRARIES = libcrmcommon.la check_LTLIBRARIES = libcrmcommon_test.la # Disable -Wcast-qual if used, because we do some hacky casting, # and because libxml2 has some signatures that should be const but aren't # for backward compatibility reasons. # s390 needs -fPIC # s390-suse-linux/bin/ld: .libs/ipc.o: relocation R_390_PC32DBL against `__stack_chk_fail@@GLIBC_2.4' can not be used when making a shared object; recompile with -fPIC CFLAGS = $(CFLAGS_COPY:-Wcast-qual=) -fPIC # Without "." here, check-recursive will run through the subdirectories first # and then run "make check" here. This will fail, because there's things in # the subdirectories that need check_LTLIBRARIES built first. Adding "." here # changes the order so the subdirectories are processed afterwards. SUBDIRS = . tests noinst_HEADERS = crmcommon_private.h mock_private.h libcrmcommon_la_LDFLAGS = -version-info 43:1:9 libcrmcommon_la_CFLAGS = $(CFLAGS_HARDENED_LIB) libcrmcommon_la_LDFLAGS += $(LDFLAGS_HARDENED_LIB) libcrmcommon_la_LIBADD = @LIBADD_DL@ $(top_builddir)/lib/gnu/libgnu.la # If configured with --with-profiling or --with-coverage, BUILD_PROFILING will # be set and -fno-builtin will be added to the CFLAGS. However, libcrmcommon # uses the fabs() function which is normally supplied by gcc as one of its # builtins. Therefore we need to explicitly link against libm here or the # tests won't link. if BUILD_PROFILING libcrmcommon_la_LIBADD += -lm endif # Use += rather than backlashed continuation lines for parsing by bumplibs libcrmcommon_la_SOURCES = libcrmcommon_la_SOURCES += acl.c libcrmcommon_la_SOURCES += agents.c libcrmcommon_la_SOURCES += alerts.c libcrmcommon_la_SOURCES += attrs.c libcrmcommon_la_SOURCES += cib.c if BUILD_CIBSECRETS libcrmcommon_la_SOURCES += cib_secrets.c endif libcrmcommon_la_SOURCES += cmdline.c libcrmcommon_la_SOURCES += digest.c libcrmcommon_la_SOURCES += health.c libcrmcommon_la_SOURCES += io.c libcrmcommon_la_SOURCES += ipc_attrd.c libcrmcommon_la_SOURCES += ipc_client.c libcrmcommon_la_SOURCES += ipc_common.c libcrmcommon_la_SOURCES += ipc_controld.c libcrmcommon_la_SOURCES += ipc_pacemakerd.c libcrmcommon_la_SOURCES += ipc_schedulerd.c libcrmcommon_la_SOURCES += ipc_server.c libcrmcommon_la_SOURCES += iso8601.c libcrmcommon_la_SOURCES += lists.c libcrmcommon_la_SOURCES += logging.c libcrmcommon_la_SOURCES += mainloop.c libcrmcommon_la_SOURCES += messages.c libcrmcommon_la_SOURCES += nvpair.c libcrmcommon_la_SOURCES += operations.c libcrmcommon_la_SOURCES += options.c libcrmcommon_la_SOURCES += output.c libcrmcommon_la_SOURCES += output_html.c libcrmcommon_la_SOURCES += output_log.c libcrmcommon_la_SOURCES += output_none.c libcrmcommon_la_SOURCES += output_text.c libcrmcommon_la_SOURCES += output_xml.c libcrmcommon_la_SOURCES += patchset.c libcrmcommon_la_SOURCES += pid.c libcrmcommon_la_SOURCES += procfs.c libcrmcommon_la_SOURCES += remote.c libcrmcommon_la_SOURCES += results.c libcrmcommon_la_SOURCES += schemas.c libcrmcommon_la_SOURCES += scores.c libcrmcommon_la_SOURCES += strings.c libcrmcommon_la_SOURCES += utils.c libcrmcommon_la_SOURCES += watchdog.c libcrmcommon_la_SOURCES += xml.c libcrmcommon_la_SOURCES += xpath.c # # libcrmcommon_test is used only with unit tests, so we can mock system calls. # See mock.c for details. # +include $(top_srcdir)/mk/tap.mk + libcrmcommon_test_la_SOURCES = $(libcrmcommon_la_SOURCES) libcrmcommon_test_la_SOURCES += mock.c -libcrmcommon_test_la_LDFLAGS = $(LDFLAGS_HARDENED_LIB) -libcrmcommon_test_la_CFLAGS = $(libcrmcommon_la_CFLAGS) -libcrmcommon_test_la_LIBADD = $(libcrmcommon_la_LIBADD) -lcmocka +libcrmcommon_test_la_LDFLAGS = $(libcrmcommon_la_LDFLAGS) -rpath $(libdir) $(LDFLAGS_WRAP) +# If GCC emits a builtin function in place of something we've mocked up, that will +# get used instead of the mocked version which leads to unexpected test results. So +# disable all builtins. Older versions of GCC (at least, on RHEL7) will still emit +# replacement code for strdup (and possibly other functions) unless -fno-inline is +# also added. +libcrmcommon_test_la_CFLAGS = $(libcrmcommon_la_CFLAGS) -DPCMK__UNIT_TESTING -fno-builtin -fno-inline +# If -fno-builtin is used, -lm also needs to be added. See the comment at +# BUILD_PROFILING above. +libcrmcommon_test_la_LIBADD = $(libcrmcommon_la_LIBADD) -lcmocka -lm nodist_libcrmcommon_test_la_SOURCES = $(nodist_libcrmcommon_la_SOURCES) clean-generic: rm -f *.log *.debug *.xml *~ diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h index db0a25984b..b11ff2b4c9 100644 --- a/lib/common/crmcommon_private.h +++ b/lib/common/crmcommon_private.h @@ -1,289 +1,294 @@ /* - * Copyright 2018-2021 the Pacemaker project contributors + * Copyright 2018-2022 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #ifndef CRMCOMMON_PRIVATE__H # define CRMCOMMON_PRIVATE__H /* This header is for the sole use of libcrmcommon, so that functions can be * declared with G_GNUC_INTERNAL for efficiency. */ #include // uint8_t, uint32_t #include // bool #include // size_t #include // GList #include // xmlNode, xmlAttr #include // struct qb_ipc_response_header // Decent chunk size for processing large amounts of data #define PCMK__BUFFER_SIZE 4096 +#if defined(PCMK__UNIT_TESTING) +#undef G_GNUC_INTERNAL +#define G_GNUC_INTERNAL +#endif + /* When deleting portions of an XML tree, we keep a record so we can know later * (e.g. when checking differences) that something was deleted. */ typedef struct pcmk__deleted_xml_s { char *path; int position; } pcmk__deleted_xml_t; typedef struct xml_private_s { long check; uint32_t flags; char *user; GList *acls; GList *deleted_objs; // List of pcmk__deleted_xml_t } xml_private_t; #define pcmk__set_xml_flags(xml_priv, flags_to_set) do { \ (xml_priv)->flags = pcmk__set_flags_as(__func__, __LINE__, \ LOG_NEVER, "XML", "XML node", (xml_priv)->flags, \ (flags_to_set), #flags_to_set); \ } while (0) #define pcmk__clear_xml_flags(xml_priv, flags_to_clear) do { \ (xml_priv)->flags = pcmk__clear_flags_as(__func__, __LINE__, \ LOG_NEVER, "XML", "XML node", (xml_priv)->flags, \ (flags_to_clear), #flags_to_clear); \ } while (0) G_GNUC_INTERNAL void pcmk__xml2text(xmlNode *data, int options, char **buffer, int *offset, int *max, int depth); G_GNUC_INTERNAL void pcmk__buffer_add_char(char **buffer, int *offset, int *max, char c); G_GNUC_INTERNAL bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy); G_GNUC_INTERNAL int pcmk__element_xpath(const char *prefix, xmlNode *xml, char *buffer, int offset, size_t buffer_size); G_GNUC_INTERNAL void pcmk__mark_xml_created(xmlNode *xml); G_GNUC_INTERNAL int pcmk__xml_position(xmlNode *xml, enum xml_private_flags ignore_if_set); G_GNUC_INTERNAL xmlNode *pcmk__xml_match(xmlNode *haystack, xmlNode *needle, bool exact); G_GNUC_INTERNAL void pcmk__xe_log(int log_level, const char *file, const char *function, int line, const char *prefix, xmlNode *data, int depth, int options); G_GNUC_INTERNAL void pcmk__xml_update(xmlNode *parent, xmlNode *target, xmlNode *update, bool as_diff); G_GNUC_INTERNAL xmlNode *pcmk__xc_match(xmlNode *root, xmlNode *search_comment, bool exact); G_GNUC_INTERNAL void pcmk__xc_update(xmlNode *parent, xmlNode *target, xmlNode *update); G_GNUC_INTERNAL void pcmk__free_acls(GList *acls); G_GNUC_INTERNAL void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user); G_GNUC_INTERNAL bool pcmk__is_user_in_group(const char *user, const char *group); G_GNUC_INTERNAL void pcmk__apply_acl(xmlNode *xml); G_GNUC_INTERNAL void pcmk__apply_creation_acl(xmlNode *xml, bool check_top); G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a); G_GNUC_INTERNAL bool pcmk__xa_filterable(const char *name); static inline const char * pcmk__xml_attr_value(const xmlAttr *attr) { return ((attr == NULL) || (attr->children == NULL))? NULL : (const char *) attr->children->content; } /* * IPC */ #define PCMK__IPC_VERSION 1 #define PCMK__CONTROLD_API_MAJOR "1" #define PCMK__CONTROLD_API_MINOR "0" // IPC behavior that varies by daemon typedef struct pcmk__ipc_methods_s { /*! * \internal * \brief Allocate any private data needed by daemon IPC * * \param[in] api IPC API connection * * \return Standard Pacemaker return code */ int (*new_data)(pcmk_ipc_api_t *api); /*! * \internal * \brief Free any private data used by daemon IPC * * \param[in] api_data Data allocated by new_data() method */ void (*free_data)(void *api_data); /*! * \internal * \brief Perform daemon-specific handling after successful connection * * Some daemons require clients to register before sending any other * commands. The controller requires a CRM_OP_HELLO (with no reply), and * the CIB manager, executor, and fencer require a CRM_OP_REGISTER (with a * reply). Ideally this would be consistent across all daemons, but for now * this allows each to do its own authorization. * * \param[in] api IPC API connection * * \return Standard Pacemaker return code */ int (*post_connect)(pcmk_ipc_api_t *api); /*! * \internal * \brief Check whether an IPC request results in a reply * * \param[in] api IPC API connection * \param[in] request IPC request XML * * \return true if request would result in an IPC reply, false otherwise */ bool (*reply_expected)(pcmk_ipc_api_t *api, xmlNode *request); /*! * \internal * \brief Perform daemon-specific handling of an IPC message * * \param[in] api IPC API connection * \param[in] msg Message read from IPC connection * * \return true if more IPC reply messages should be expected */ bool (*dispatch)(pcmk_ipc_api_t *api, xmlNode *msg); /*! * \internal * \brief Perform daemon-specific handling of an IPC disconnect * * \param[in] api IPC API connection */ void (*post_disconnect)(pcmk_ipc_api_t *api); } pcmk__ipc_methods_t; // Implementation of pcmk_ipc_api_t struct pcmk_ipc_api_s { enum pcmk_ipc_server server; // Daemon this IPC API instance is for enum pcmk_ipc_dispatch dispatch_type; // How replies should be dispatched size_t ipc_size_max; // maximum IPC buffer size crm_ipc_t *ipc; // IPC connection mainloop_io_t *mainloop_io; // If using mainloop, I/O source for IPC bool free_on_disconnect; // Whether disconnect should free object pcmk_ipc_callback_t cb; // Caller-registered callback (if any) void *user_data; // Caller-registered data (if any) void *api_data; // For daemon-specific use pcmk__ipc_methods_t *cmds; // Behavior that varies by daemon }; typedef struct pcmk__ipc_header_s { struct qb_ipc_response_header qb; uint32_t size_uncompressed; uint32_t size_compressed; uint32_t flags; uint8_t version; } pcmk__ipc_header_t; G_GNUC_INTERNAL int pcmk__send_ipc_request(pcmk_ipc_api_t *api, xmlNode *request); G_GNUC_INTERNAL void pcmk__call_ipc_callback(pcmk_ipc_api_t *api, enum pcmk_ipc_event event_type, crm_exit_t status, void *event_data); G_GNUC_INTERNAL unsigned int pcmk__ipc_buffer_size(unsigned int max); G_GNUC_INTERNAL bool pcmk__valid_ipc_header(const pcmk__ipc_header_t *header); G_GNUC_INTERNAL pcmk__ipc_methods_t *pcmk__attrd_api_methods(void); G_GNUC_INTERNAL pcmk__ipc_methods_t *pcmk__controld_api_methods(void); G_GNUC_INTERNAL pcmk__ipc_methods_t *pcmk__pacemakerd_api_methods(void); G_GNUC_INTERNAL pcmk__ipc_methods_t *pcmk__schedulerd_api_methods(void); /* * Logging */ /*! * \brief Check the authenticity of the IPC socket peer process * * If everything goes well, peer's authenticity is verified by the means * of comparing against provided referential UID and GID (either satisfies), * and the result of this check can be deduced from the return value. * As an exception, detected UID of 0 ("root") satisfies arbitrary * provided referential daemon's credentials. * * \param[in] qb_ipc libqb client connection if available * \param[in] sock IPC related, connected Unix socket to check peer of * \param[in] refuid referential UID to check against * \param[in] refgid referential GID to check against * \param[out] gotpid to optionally store obtained PID of the peer * (not available on FreeBSD, special value of 1 * used instead, and the caller is required to * special case this value respectively) * \param[out] gotuid to optionally store obtained UID of the peer * \param[out] gotgid to optionally store obtained GID of the peer * * \return Standard Pacemaker return code * ie: 0 if it the connection is authentic * pcmk_rc_ipc_unauthorized if the connection is not authentic, * standard errors. * * \note While this function is tolerant on what constitutes authorized * IPC daemon process (its effective user matches UID=0 or \p refuid, * or at least its group matches \p refgid), either or both (in case * of UID=0) mismatches on the expected credentials of such peer * process \e shall be investigated at the caller when value of 1 * gets returned there, since higher-than-expected privileges in * respect to the expected/intended credentials possibly violate * the least privilege principle and may pose an additional risk * (i.e. such accidental inconsistency shall be eventually fixed). */ int pcmk__crm_ipc_is_authentic_process(qb_ipcc_connection_t *qb_ipc, int sock, uid_t refuid, gid_t refgid, pid_t *gotpid, uid_t *gotuid, gid_t *gotgid); #endif // CRMCOMMON_PRIVATE__H diff --git a/lib/common/mock.c b/lib/common/mock.c index 64321aa36d..bd4e4b86c7 100644 --- a/lib/common/mock.c +++ b/lib/common/mock.c @@ -1,249 +1,264 @@ /* * Copyright 2021-2022 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mock_private.h" /* This file is only used when running "make check". It is built into * libcrmcommon_test.a, not into libcrmcommon.so. It is used to support * constructing mock versions of library functions for unit testing. * * HOW TO ADD A MOCKED FUNCTION: * * - In this file, declare a bool pcmk__mock_X variable, and define a __wrap_X * function with the same prototype as the actual function that performs the * desired behavior if pcmk__mock_X is true and calls __real_X otherwise. * You can use cmocka's mock_type() and mock_ptr_type() to pass extra * information to the mocked function (see existing examples for details). * * - In mock_private.h, add declarations for extern bool pcmk__mock_X and the * __real_X and __wrap_X function prototypes. * * - In mk/tap.mk, add the function name to the WRAPPED variable. * * HOW TO USE A MOCKED FUNCTION: * * - #include "mock_private.h" in your test file. * * - Write your test cases using pcmk__mock_X and cmocka's will_return() as * needed per the comments for the mocked function below. See existing test * cases for examples. */ /* calloc() * * If pcmk__mock_calloc is set to true, later calls to malloc() will return * NULL. */ bool pcmk__mock_calloc = false; void * __wrap_calloc(size_t nmemb, size_t size) { return pcmk__mock_calloc? NULL : __real_calloc(nmemb, size); } /* getenv() * * If pcmk__mock_getenv is set to true, later calls to getenv() must be preceded * by: * * will_return(__wrap_getenv, return_value); */ bool pcmk__mock_getenv = false; char * __wrap_getenv(const char *name) { return pcmk__mock_getenv? mock_ptr_type(char *) : __real_getenv(name); } /* setgrent(), getgrent() and endgrent() * * If pcmk__mock_grent is set to true, getgrent() will behave as if the only * groups on the system are: * * - grp0 (user0, user1) * - grp1 (user1) * - grp2 (user2, user1) */ bool pcmk__mock_grent = false; // Index of group that will be returned next from getgrent() static int group_idx = 0; // Data used for testing static const char* grp0_members[] = { "user0", "user1", NULL }; static const char* grp1_members[] = { "user1", NULL }; static const char* grp2_members[] = { "user2", "user1", NULL }; /* An array of "groups" (a struct from grp.h) * * The members of the groups are initalized here to some testing data, casting * away the consts to make the compiler happy and simplify initialization. We * never actually change these variables during the test! * * string literal = const char* (cannot be changed b/c ? ) * vs. char* (it's getting casted to this) */ static const int NUM_GROUPS = 3; static struct group groups[] = { {(char*)"grp0", (char*)"", 0, (char**)grp0_members}, {(char*)"grp1", (char*)"", 1, (char**)grp1_members}, {(char*)"grp2", (char*)"", 2, (char**)grp2_members}, }; // This function resets the group_idx to 0. void __wrap_setgrent(void) { if (pcmk__mock_grent) { group_idx = 0; } else { __real_setgrent(); } } /* This function returns the next group entry in the list of groups, or * NULL if there aren't any left. * group_idx is a global variable which keeps track of where you are in the list */ struct group * __wrap_getgrent(void) { if (pcmk__mock_grent) { if (group_idx >= NUM_GROUPS) { return NULL; } return &groups[group_idx++]; } else { return __real_getgrent(); } } void __wrap_endgrent(void) { if (!pcmk__mock_grent) { __real_endgrent(); } } /* getpwnam_r() * * If pcmk__mock_getpwnam_r is set to true, later calls to getpwnam_r() must be * preceded by: * * will_return(__wrap_getpwnam_r, return_value); * will_return(__wrap_getpwnam_r, ptr_to_result_struct); */ bool pcmk__mock_getpwnam_r = false; int __wrap_getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result) { if (pcmk__mock_getpwnam_r) { int retval = mock_type(int); *result = mock_ptr_type(struct passwd *); return retval; } else { return __real_getpwnam_r(name, pwd, buf, buflen, result); } } /* * If pcmk__mock_readlink is set to true, later calls to readlink() must be * preceded by: * * will_return(__wrap_readlink, errno_to_set); * will_return(__wrap_readlink, link_contents); * * The mocked function will return 0 if errno_to_set is 0, and -1 otherwise. */ bool pcmk__mock_readlink = false; ssize_t __wrap_readlink(const char *restrict path, char *restrict buf, size_t bufsize) { if (pcmk__mock_readlink) { const char *contents = NULL; errno = mock_type(int); contents = mock_ptr_type(const char *); if (errno == 0) { strncpy(buf, contents, bufsize - 1); return strlen(contents); } return -1; } else { return __real_readlink(path, buf, bufsize); } } +/* strdup() + * + * If pcmk__mock_strdup is set to true, later calls to strdup() will return + * NULL. + */ + +bool pcmk__mock_strdup = false; + +char * +__wrap_strdup(const char *s) +{ + return pcmk__mock_strdup? NULL : __real_strdup(s); +} + + /* uname() * * If pcmk__mock_uname is set to true, later calls to uname() must be preceded * by: * * will_return(__wrap_uname, return_value); * will_return(__wrap_uname, node_name_for_buf_parameter_to_uname); */ bool pcmk__mock_uname = false; int __wrap_uname(struct utsname *buf) { if (pcmk__mock_uname) { int retval = mock_type(int); char *result = mock_ptr_type(char *); if (result != NULL) { strcpy(buf->nodename, result); } return retval; } else { return __real_uname(buf); } } diff --git a/lib/common/mock_private.h b/lib/common/mock_private.h index 2ed6c0867a..e5be1e0707 100644 --- a/lib/common/mock_private.h +++ b/lib/common/mock_private.h @@ -1,54 +1,59 @@ /* * Copyright 2021-2022 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #ifndef MOCK_PRIVATE__H # define MOCK_PRIVATE__H #include #include #include +#include #include #include #include /* This header is for the sole use of libcrmcommon_test and unit tests */ extern bool pcmk__mock_calloc; void *__real_calloc(size_t nmemb, size_t size); void *__wrap_calloc(size_t nmemb, size_t size); extern bool pcmk__mock_getenv; char *__real_getenv(const char *name); char *__wrap_getenv(const char *name); extern bool pcmk__mock_grent; void __real_setgrent(void); void __wrap_setgrent(void); struct group * __wrap_getgrent(void); struct group * __real_getgrent(void); void __wrap_endgrent(void); void __real_endgrent(void); extern bool pcmk__mock_getpwnam_r; int __real_getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); int __wrap_getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); extern bool pcmk__mock_readlink; ssize_t __real_readlink(const char *restrict path, char *restrict buf, size_t bufsize); ssize_t __wrap_readlink(const char *restrict path, char *restrict buf, size_t bufsize); +extern bool pcmk__mock_strdup; +char *__real_strdup(const char *s); +char *__wrap_strdup(const char *s); + extern bool pcmk__mock_uname; int __real_uname(struct utsname *buf); int __wrap_uname(struct utsname *buf); #endif // MOCK_PRIVATE__H diff --git a/lib/common/tests/acl/Makefile.am b/lib/common/tests/acl/Makefile.am index 93aa87a5f6..96460e8d8e 100644 --- a/lib/common/tests/acl/Makefile.am +++ b/lib/common/tests/acl/Makefile.am @@ -1,26 +1,28 @@ # # Copyright 2021-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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = \ pcmk__is_user_in_group_test \ pcmk_acl_required_test \ xml_acl_denied_test \ xml_acl_enabled_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/acl/pcmk__is_user_in_group_test.c b/lib/common/tests/acl/pcmk__is_user_in_group_test.c index b902f5c902..75fe85c4e2 100644 --- a/lib/common/tests/acl/pcmk__is_user_in_group_test.c +++ b/lib/common/tests/acl/pcmk__is_user_in_group_test.c @@ -1,50 +1,46 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include #include -#include "../../crmcommon_private.h" +#include "../../crmcommon_private.h" #include "mock_private.h" -#include -#include -#include -#include -#include - static void is_pcmk__is_user_in_group(void **state) { pcmk__mock_grent = true; // null user assert_false(pcmk__is_user_in_group(NULL, "grp0")); // null group assert_false(pcmk__is_user_in_group("user0", NULL)); // nonexistent group assert_false(pcmk__is_user_in_group("user0", "nonexistent_group")); // user is in group assert_true(pcmk__is_user_in_group("user0", "grp0")); // user is not in group assert_false(pcmk__is_user_in_group("user2", "grp0")); pcmk__mock_grent = false; } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(is_pcmk__is_user_in_group) }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/acl/pcmk_acl_required_test.c b/lib/common/tests/acl/pcmk_acl_required_test.c index 87bfe494f8..4e9cf31cc2 100644 --- a/lib/common/tests/acl/pcmk_acl_required_test.c +++ b/lib/common/tests/acl/pcmk_acl_required_test.c @@ -1,38 +1,34 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include +#include +#include static void is_pcmk_acl_required(void **state) { assert_false(pcmk_acl_required(NULL)); assert_false(pcmk_acl_required("")); assert_true(pcmk_acl_required("123")); assert_false(pcmk_acl_required(CRM_DAEMON_USER)); assert_false(pcmk_acl_required("root")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(is_pcmk_acl_required), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/acl/xml_acl_denied_test.c b/lib/common/tests/acl/xml_acl_denied_test.c index 7e01177854..72ac1a6964 100644 --- a/lib/common/tests/acl/xml_acl_denied_test.c +++ b/lib/common/tests/acl/xml_acl_denied_test.c @@ -1,72 +1,69 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include #include -#include "../../crmcommon_private.h" -#include -#include -#include -#include -#include +#include "../../crmcommon_private.h" static void is_xml_acl_denied_without_node(void **state) { xmlNode *test_xml = create_xml_node(NULL, "test_xml"); assert_false(xml_acl_denied(test_xml)); test_xml->doc->_private = NULL; assert_false(xml_acl_denied(test_xml)); test_xml->doc = NULL; assert_false(xml_acl_denied(test_xml)); test_xml = NULL; assert_false(xml_acl_denied(test_xml)); } static void is_xml_acl_denied_with_node(void **state) { xml_private_t *p; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); // allocate memory for _private, which is NULL by default test_xml->doc->_private = calloc(1, sizeof(xml_private_t)); assert_false(xml_acl_denied(test_xml)); // cast _private from void* to xml_private_t* p = test_xml->doc->_private; // enable an irrelevant flag p->flags |= pcmk__xf_acl_enabled; assert_false(xml_acl_denied(test_xml)); // enable pcmk__xf_acl_denied p->flags |= pcmk__xf_acl_denied; assert_true(xml_acl_denied(test_xml)); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(is_xml_acl_denied_without_node), cmocka_unit_test(is_xml_acl_denied_with_node), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/acl/xml_acl_enabled_test.c b/lib/common/tests/acl/xml_acl_enabled_test.c index 669aaec7e5..4cf76e5cf2 100644 --- a/lib/common/tests/acl/xml_acl_enabled_test.c +++ b/lib/common/tests/acl/xml_acl_enabled_test.c @@ -1,72 +1,69 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include #include -#include "../../crmcommon_private.h" -#include -#include -#include -#include -#include +#include "../../crmcommon_private.h" static void is_xml_acl_enabled_without_node(void **state) { xmlNode *test_xml = create_xml_node(NULL, "test_xml"); assert_false(xml_acl_enabled(test_xml)); test_xml->doc->_private = NULL; assert_false(xml_acl_enabled(test_xml)); test_xml->doc = NULL; assert_false(xml_acl_enabled(test_xml)); test_xml = NULL; assert_false(xml_acl_enabled(test_xml)); } static void is_xml_acl_enabled_with_node(void **state) { xml_private_t *p; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); // allocate memory for _private, which is NULL by default test_xml->doc->_private = calloc(1, sizeof(xml_private_t)); assert_false(xml_acl_enabled(test_xml)); // cast _private from void* to xml_private_t* p = test_xml->doc->_private; // enable an irrelevant flag p->flags |= pcmk__xf_acl_denied; assert_false(xml_acl_enabled(test_xml)); // enable pcmk__xf_acl_enabled p->flags |= pcmk__xf_acl_enabled; assert_true(xml_acl_enabled(test_xml)); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(is_xml_acl_enabled_without_node), cmocka_unit_test(is_xml_acl_enabled_with_node), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/agents/Makefile.am b/lib/common/tests/agents/Makefile.am index 056c8765d9..a9b839b877 100644 --- a/lib/common/tests/agents/Makefile.am +++ b/lib/common/tests/agents/Makefile.am @@ -1,21 +1,23 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk_stonith_param_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/agents/pcmk_stonith_param_test.c b/lib/common/tests/agents/pcmk_stonith_param_test.c index f1dce83633..44d7f92266 100644 --- a/lib/common/tests/agents/pcmk_stonith_param_test.c +++ b/lib/common/tests/agents/pcmk_stonith_param_test.c @@ -1,62 +1,58 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include +#include +#include static void is_stonith_param(void **state) { assert_false(pcmk_stonith_param(NULL)); assert_false(pcmk_stonith_param("")); assert_false(pcmk_stonith_param("unrecognized")); assert_false(pcmk_stonith_param("pcmk_unrecognized")); assert_false(pcmk_stonith_param("x" PCMK_STONITH_ACTION_LIMIT)); assert_false(pcmk_stonith_param(PCMK_STONITH_ACTION_LIMIT "x")); assert_true(pcmk_stonith_param(PCMK_STONITH_ACTION_LIMIT)); assert_true(pcmk_stonith_param(PCMK_STONITH_DELAY_BASE)); assert_true(pcmk_stonith_param(PCMK_STONITH_DELAY_MAX)); assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_ARGUMENT)); assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_CHECK)); assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_LIST)); assert_true(pcmk_stonith_param(PCMK_STONITH_HOST_MAP)); assert_true(pcmk_stonith_param(PCMK_STONITH_PROVIDES)); assert_true(pcmk_stonith_param(PCMK_STONITH_STONITH_TIMEOUT)); } static void is_stonith_action_param(void **state) { /* Currently, the function accepts any string not containing underbars as * the action name, so we do not need to verify particular action names. */ assert_false(pcmk_stonith_param("pcmk_on_unrecognized")); assert_true(pcmk_stonith_param("pcmk_on_action")); assert_true(pcmk_stonith_param("pcmk_on_timeout")); assert_true(pcmk_stonith_param("pcmk_on_retries")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(is_stonith_param), cmocka_unit_test(is_stonith_action_param), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/cmdline/Makefile.am b/lib/common/tests/cmdline/Makefile.am index a0a5e58345..907ae7474b 100644 --- a/lib/common/tests/cmdline/Makefile.am +++ b/lib/common/tests/cmdline/Makefile.am @@ -1,22 +1,24 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk__cmdline_preproc_test \ pcmk__quote_cmdline_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c index 64d7669735..da2859dc22 100644 --- a/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c +++ b/lib/common/tests/cmdline/pcmk__cmdline_preproc_test.c @@ -1,166 +1,163 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include #include -#include -#include -#include -#include -#include #include #define LISTS_EQ(a, b) { \ assert_int_equal(g_strv_length((gchar **) (a)), g_strv_length((gchar **) (b))); \ for (int i = 0; i < g_strv_length((a)); i++) { \ assert_string_equal((a)[i], (b)[i]); \ } \ } static void empty_input(void **state) { assert_null(pcmk__cmdline_preproc(NULL, "")); } static void no_specials(void **state) { const char *argv[] = { "crm_mon", "-a", "-b", "-c", "-d", "-1", NULL }; const gchar *expected[] = { "crm_mon", "-a", "-b", "-c", "-d", "-1", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); processed = pcmk__cmdline_preproc((char **) argv, ""); LISTS_EQ(processed, expected); g_strfreev(processed); } static void single_dash(void **state) { const char *argv[] = { "crm_mon", "-", NULL }; const gchar *expected[] = { "crm_mon", "-", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void double_dash(void **state) { const char *argv[] = { "crm_mon", "-a", "--", "-bc", NULL }; const gchar *expected[] = { "crm_mon", "-a", "--", "-bc", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void special_args(void **state) { const char *argv[] = { "crm_mon", "-aX", "-Fval", NULL }; const gchar *expected[] = { "crm_mon", "-a", "X", "-F", "val", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "aF"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void special_arg_at_end(void **state) { const char *argv[] = { "crm_mon", "-a", NULL }; const gchar *expected[] = { "crm_mon", "-a", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "a"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void long_arg(void **state) { const char *argv[] = { "crm_mon", "--blah=foo", NULL }; const gchar *expected[] = { "crm_mon", "--blah=foo", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void negative_score(void **state) { const char *argv[] = { "crm_mon", "-v", "-1000", NULL }; const gchar *expected[] = { "crm_mon", "-v", "-1000", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "v"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void negative_score_2(void **state) { const char *argv[] = { "crm_mon", "-1i3", NULL }; const gchar *expected[] = { "crm_mon", "-1", "-i", "-3", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, NULL); LISTS_EQ(processed, expected); g_strfreev(processed); } static void string_arg_with_dash(void **state) { const char *argv[] = { "crm_mon", "-n", "crm_mon_options", "-v", "--opt1 --opt2", NULL }; const gchar *expected[] = { "crm_mon", "-n", "crm_mon_options", "-v", "--opt1 --opt2", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "v"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void string_arg_with_dash_2(void **state) { const char *argv[] = { "crm_mon", "-n", "crm_mon_options", "-v", "-1i3", NULL }; const gchar *expected[] = { "crm_mon", "-n", "crm_mon_options", "-v", "-1i3", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "v"); LISTS_EQ(processed, expected); g_strfreev(processed); } static void string_arg_with_dash_3(void **state) { const char *argv[] = { "crm_mon", "-abc", "-1i3", NULL }; const gchar *expected[] = { "crm_mon", "-a", "-b", "-c", "-1i3", NULL }; gchar **processed = pcmk__cmdline_preproc((char **) argv, "c"); LISTS_EQ(processed, expected); g_strfreev(processed); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input), cmocka_unit_test(no_specials), cmocka_unit_test(single_dash), cmocka_unit_test(double_dash), cmocka_unit_test(special_args), cmocka_unit_test(special_arg_at_end), cmocka_unit_test(long_arg), cmocka_unit_test(negative_score), cmocka_unit_test(negative_score_2), cmocka_unit_test(string_arg_with_dash), cmocka_unit_test(string_arg_with_dash_2), cmocka_unit_test(string_arg_with_dash_3), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c b/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c index 85769b2486..58d0cb5f75 100644 --- a/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c +++ b/lib/common/tests/cmdline/pcmk__quote_cmdline_test.c @@ -1,67 +1,64 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include #include -#include -#include -#include -#include -#include #include static void empty_input(void **state) { assert_null(pcmk__quote_cmdline(NULL)); } static void no_spaces(void **state) { const char *argv[] = { "crm_resource", "-r", "rsc1", "--meta", "-p", "comment", "-v", "hello", "--output-as=xml", NULL }; const gchar *expected = "crm_resource -r rsc1 --meta -p comment -v hello --output-as=xml"; gchar *processed = pcmk__quote_cmdline((gchar **) argv); assert_string_equal(processed, expected); g_free(processed); } static void spaces_no_quote(void **state) { const char *argv[] = { "crm_resource", "-r", "rsc1", "--meta", "-p", "comment", "-v", "hello world", "--output-as=xml", NULL }; const gchar *expected = "crm_resource -r rsc1 --meta -p comment -v 'hello world' --output-as=xml"; gchar *processed = pcmk__quote_cmdline((gchar **) argv); assert_string_equal(processed, expected); g_free(processed); } static void spaces_with_quote(void **state) { const char *argv[] = { "crm_resource", "-r", "rsc1", "--meta", "-p", "comment", "-v", "here's johnny", "--output-as=xml", NULL }; const gchar *expected = "crm_resource -r rsc1 --meta -p comment -v 'here\\\'s johnny' --output-as=xml"; gchar *processed = pcmk__quote_cmdline((gchar **) argv); assert_string_equal(processed, expected); g_free(processed); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input), cmocka_unit_test(no_spaces), cmocka_unit_test(spaces_no_quote), cmocka_unit_test(spaces_with_quote), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/Makefile.am b/lib/common/tests/flags/Makefile.am index 3f9be62218..d50b9f7b12 100644 --- a/lib/common/tests/flags/Makefile.am +++ b/lib/common/tests/flags/Makefile.am @@ -1,25 +1,27 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = \ pcmk__clear_flags_as_test \ pcmk__set_flags_as_test \ pcmk_all_flags_set_test \ pcmk_any_flags_set_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/flags/pcmk__clear_flags_as_test.c b/lib/common/tests/flags/pcmk__clear_flags_as_test.c index 8a1fa1358c..ea54ed5bd8 100644 --- a/lib/common/tests/flags/pcmk__clear_flags_as_test.c +++ b/lib/common/tests/flags/pcmk__clear_flags_as_test.c @@ -1,53 +1,49 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void clear_none(void **state) { assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0x00f, NULL), 0x0f0); assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0xf0f, NULL), 0x0f0); } static void clear_some(void **state) { assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0x020, NULL), 0x0d0); assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0x030, NULL), 0x0c0); } static void clear_all(void **state) { assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0x0f0, NULL), 0x000); assert_int_equal(pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0xfff, NULL), 0x000); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(clear_none), cmocka_unit_test(clear_some), cmocka_unit_test(clear_all), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/pcmk__set_flags_as_test.c b/lib/common/tests/flags/pcmk__set_flags_as_test.c index 1a927bbf7b..9a5db7535d 100644 --- a/lib/common/tests/flags/pcmk__set_flags_as_test.c +++ b/lib/common/tests/flags/pcmk__set_flags_as_test.c @@ -1,37 +1,33 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void set_flags(void **state) { assert_int_equal(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0x00f, NULL), 0x0ff); assert_int_equal(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0xf0f, NULL), 0xfff); assert_int_equal(pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE, "Test", "test", 0x0f0, 0xfff, NULL), 0xfff); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(set_flags), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/pcmk_all_flags_set_test.c b/lib/common/tests/flags/pcmk_all_flags_set_test.c index 4596ad9490..eeb70ac2ec 100644 --- a/lib/common/tests/flags/pcmk_all_flags_set_test.c +++ b/lib/common/tests/flags/pcmk_all_flags_set_test.c @@ -1,45 +1,41 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void all_set(void **state) { assert_false(pcmk_all_flags_set(0x000, 0x003)); assert_true(pcmk_all_flags_set(0x00f, 0x003)); assert_false(pcmk_all_flags_set(0x00f, 0x010)); assert_false(pcmk_all_flags_set(0x00f, 0x011)); assert_true(pcmk_all_flags_set(0x000, 0x000)); assert_true(pcmk_all_flags_set(0x00f, 0x000)); } static void one_is_set(void **state) { // pcmk_is_set() is a simple macro alias for pcmk_all_flags_set() assert_true(pcmk_is_set(0x00f, 0x001)); assert_false(pcmk_is_set(0x00f, 0x010)); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(all_set), cmocka_unit_test(one_is_set), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/flags/pcmk_any_flags_set_test.c b/lib/common/tests/flags/pcmk_any_flags_set_test.c index 1d3407dc84..36e48262be 100644 --- a/lib/common/tests/flags/pcmk_any_flags_set_test.c +++ b/lib/common/tests/flags/pcmk_any_flags_set_test.c @@ -1,38 +1,34 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void any_set(void **state) { assert_false(pcmk_any_flags_set(0x000, 0x000)); assert_false(pcmk_any_flags_set(0x000, 0x001)); assert_true(pcmk_any_flags_set(0x00f, 0x001)); assert_false(pcmk_any_flags_set(0x00f, 0x010)); assert_true(pcmk_any_flags_set(0x00f, 0x011)); assert_false(pcmk_any_flags_set(0x000, 0x000)); assert_false(pcmk_any_flags_set(0x00f, 0x000)); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(any_set), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/health/Makefile.am b/lib/common/tests/health/Makefile.am index b26bcccd77..ebb51cb09c 100644 --- a/lib/common/tests/health/Makefile.am +++ b/lib/common/tests/health/Makefile.am @@ -1,22 +1,24 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk__parse_health_strategy_test \ pcmk__validate_health_strategy_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/health/pcmk__parse_health_strategy_test.c b/lib/common/tests/health/pcmk__parse_health_strategy_test.c index cf76169336..a054e4966c 100644 --- a/lib/common/tests/health/pcmk__parse_health_strategy_test.c +++ b/lib/common/tests/health/pcmk__parse_health_strategy_test.c @@ -1,68 +1,64 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void valid(void **state) { assert_int_equal(pcmk__parse_health_strategy(NULL), pcmk__health_strategy_none); assert_int_equal(pcmk__parse_health_strategy("none"), pcmk__health_strategy_none); assert_int_equal(pcmk__parse_health_strategy("NONE"), pcmk__health_strategy_none); assert_int_equal(pcmk__parse_health_strategy("None"), pcmk__health_strategy_none); assert_int_equal(pcmk__parse_health_strategy("nOnE"), pcmk__health_strategy_none); assert_int_equal(pcmk__parse_health_strategy("migrate-on-red"), pcmk__health_strategy_no_red); assert_int_equal(pcmk__parse_health_strategy("only-green"), pcmk__health_strategy_only_green); assert_int_equal(pcmk__parse_health_strategy("progressive"), pcmk__health_strategy_progressive); assert_int_equal(pcmk__parse_health_strategy("custom"), pcmk__health_strategy_custom); } static void invalid(void **state) { assert_int_equal(pcmk__parse_health_strategy("foo"), pcmk__health_strategy_none); assert_int_equal(pcmk__parse_health_strategy("custom1"), pcmk__health_strategy_none); assert_int_equal(pcmk__parse_health_strategy("not-only-green-here"), pcmk__health_strategy_none); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(valid), cmocka_unit_test(invalid), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/health/pcmk__validate_health_strategy_test.c b/lib/common/tests/health/pcmk__validate_health_strategy_test.c index 0e7d8423ea..7832efab3a 100644 --- a/lib/common/tests/health/pcmk__validate_health_strategy_test.c +++ b/lib/common/tests/health/pcmk__validate_health_strategy_test.c @@ -1,49 +1,45 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include // Test functions static void valid_strategy(void **state) { assert_true(pcmk__validate_health_strategy("none")); assert_true(pcmk__validate_health_strategy("None")); assert_true(pcmk__validate_health_strategy("NONE")); assert_true(pcmk__validate_health_strategy("NoNe")); assert_true(pcmk__validate_health_strategy("migrate-on-red")); assert_true(pcmk__validate_health_strategy("only-green")); assert_true(pcmk__validate_health_strategy("progressive")); assert_true(pcmk__validate_health_strategy("custom")); } static void invalid_strategy(void **state) { assert_false(pcmk__validate_health_strategy(NULL)); assert_false(pcmk__validate_health_strategy("")); assert_false(pcmk__validate_health_strategy("none to speak of")); assert_false(pcmk__validate_health_strategy("customized")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(valid_strategy), cmocka_unit_test(invalid_strategy), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/io/Makefile.am b/lib/common/tests/io/Makefile.am index 8b26993c30..cb56c8683a 100644 --- a/lib/common/tests/io/Makefile.am +++ b/lib/common/tests/io/Makefile.am @@ -1,24 +1,25 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = \ pcmk__full_path_test \ pcmk__get_tmpdir_test TESTS = $(check_PROGRAMS) - diff --git a/lib/common/tests/io/pcmk__full_path_test.c b/lib/common/tests/io/pcmk__full_path_test.c index 47333e4d85..7c8bddade6 100644 --- a/lib/common/tests/io/pcmk__full_path_test.c +++ b/lib/common/tests/io/pcmk__full_path_test.c @@ -1,47 +1,55 @@ /* - * Copyright 2020-2021 the Pacemaker project contributors + * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include -#include +#include + +#include "mock_private.h" + +static void +function_asserts(void **state) +{ + pcmk__assert_asserts(pcmk__full_path(NULL, "/dir")); + pcmk__assert_asserts(pcmk__full_path("file", NULL)); + + pcmk__mock_strdup = true; // strdup() will return NULL + pcmk__assert_asserts(pcmk__full_path("/full/path", "/dir")); + pcmk__mock_strdup = false; // Use real strdup() +} static void full_path(void **state) { char *path = NULL; path = pcmk__full_path("file", "/dir"); assert_int_equal(strcmp(path, "/dir/file"), 0); free(path); path = pcmk__full_path("/full/path", "/dir"); assert_int_equal(strcmp(path, "/full/path"), 0); free(path); path = pcmk__full_path("../relative/path", "/dir"); assert_int_equal(strcmp(path, "/dir/../relative/path"), 0); free(path); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { + cmocka_unit_test(function_asserts), cmocka_unit_test(full_path), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/io/pcmk__get_tmpdir_test.c b/lib/common/tests/io/pcmk__get_tmpdir_test.c index 803ed0185f..eac8fc0f82 100644 --- a/lib/common/tests/io/pcmk__get_tmpdir_test.c +++ b/lib/common/tests/io/pcmk__get_tmpdir_test.c @@ -1,76 +1,70 @@ /* * Copyright 2021-2022 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include "mock_private.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include + +#include "mock_private.h" static void getenv_returns_invalid(void **state) { const char *result; pcmk__mock_getenv = true; will_return(__wrap_getenv, NULL); // getenv("TMPDIR") return value result = pcmk__get_tmpdir(); assert_string_equal(result, "/tmp"); will_return(__wrap_getenv, ""); // getenv("TMPDIR") return value result = pcmk__get_tmpdir(); assert_string_equal(result, "/tmp"); will_return(__wrap_getenv, "subpath"); // getenv("TMPDIR") return value result = pcmk__get_tmpdir(); assert_string_equal(result, "/tmp"); pcmk__mock_getenv = false; } static void getenv_returns_valid(void **state) { const char *result; pcmk__mock_getenv = true; will_return(__wrap_getenv, "/var/tmp"); // getenv("TMPDIR") return value result = pcmk__get_tmpdir(); assert_string_equal(result, "/var/tmp"); will_return(__wrap_getenv, "/"); // getenv("TMPDIR") return value result = pcmk__get_tmpdir(); assert_string_equal(result, "/"); will_return(__wrap_getenv, "/tmp/abcd.1234"); // getenv("TMPDIR") return value result = pcmk__get_tmpdir(); assert_string_equal(result, "/tmp/abcd.1234"); pcmk__mock_getenv = false; } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(getenv_returns_invalid), cmocka_unit_test(getenv_returns_valid), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/iso8601/Makefile.am b/lib/common/tests/iso8601/Makefile.am index 60bf1959b4..ceb3085ade 100644 --- a/lib/common/tests/iso8601/Makefile.am +++ b/lib/common/tests/iso8601/Makefile.am @@ -1,21 +1,23 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk__readable_interval_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/iso8601/pcmk__readable_interval_test.c b/lib/common/tests/iso8601/pcmk__readable_interval_test.c index 62b74e9935..b6a7cc2422 100644 --- a/lib/common/tests/iso8601/pcmk__readable_interval_test.c +++ b/lib/common/tests/iso8601/pcmk__readable_interval_test.c @@ -1,38 +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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include + #include -#include -#include -#include -#include -#include static void readable_interval(void **state) { assert_string_equal(pcmk__readable_interval(0), "0s"); assert_string_equal(pcmk__readable_interval(30000), "30s"); assert_string_equal(pcmk__readable_interval(150000), "2m30s"); assert_string_equal(pcmk__readable_interval(3333), "3.333s"); assert_string_equal(pcmk__readable_interval(UINT_MAX), "49d17h2m47.295s"); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(readable_interval), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/lists/Makefile.am b/lib/common/tests/lists/Makefile.am index 801a9a93db..79c60e3d52 100644 --- a/lib/common/tests/lists/Makefile.am +++ b/lib/common/tests/lists/Makefile.am @@ -1,23 +1,25 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = \ pcmk__subtract_lists_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/lists/pcmk__subtract_lists_test.c b/lib/common/tests/lists/pcmk__subtract_lists_test.c index f27522c46a..f92b840a9e 100644 --- a/lib/common/tests/lists/pcmk__subtract_lists_test.c +++ b/lib/common/tests/lists/pcmk__subtract_lists_test.c @@ -1,158 +1,152 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include static void different_lists(void **state) { GList *from = NULL; GList *items = NULL; GList *result = NULL; from = g_list_append(from, strdup("abc")); from = g_list_append(from, strdup("def")); from = g_list_append(from, strdup("ghi")); items = g_list_append(items, strdup("123")); items = g_list_append(items, strdup("456")); result = pcmk__subtract_lists(from, items, (GCompareFunc) strcmp); assert_int_equal(g_list_length(result), 3); assert_string_equal(g_list_nth_data(result, 0), "abc"); assert_string_equal(g_list_nth_data(result, 1), "def"); assert_string_equal(g_list_nth_data(result, 2), "ghi"); g_list_free(result); g_list_free_full(from, free); g_list_free_full(items, free); } static void remove_first_item(void **state) { GList *from = NULL; GList *items = NULL; GList *result = NULL; from = g_list_append(from, strdup("abc")); from = g_list_append(from, strdup("def")); from = g_list_append(from, strdup("ghi")); items = g_list_append(items, strdup("abc")); result = pcmk__subtract_lists(from, items, (GCompareFunc) strcmp); assert_int_equal(g_list_length(result), 2); assert_string_equal(g_list_nth_data(result, 0), "def"); assert_string_equal(g_list_nth_data(result, 1), "ghi"); g_list_free(result); g_list_free_full(from, free); g_list_free_full(items, free); } static void remove_middle_item(void **state) { GList *from = NULL; GList *items = NULL; GList *result = NULL; from = g_list_append(from, strdup("abc")); from = g_list_append(from, strdup("def")); from = g_list_append(from, strdup("ghi")); items = g_list_append(items, strdup("def")); result = pcmk__subtract_lists(from, items, (GCompareFunc) strcmp); assert_int_equal(g_list_length(result), 2); assert_string_equal(g_list_nth_data(result, 0), "abc"); assert_string_equal(g_list_nth_data(result, 1), "ghi"); g_list_free(result); g_list_free_full(from, free); g_list_free_full(items, free); } static void remove_last_item(void **state) { GList *from = NULL; GList *items = NULL; GList *result = NULL; from = g_list_append(from, strdup("abc")); from = g_list_append(from, strdup("def")); from = g_list_append(from, strdup("ghi")); items = g_list_append(items, strdup("ghi")); result = pcmk__subtract_lists(from, items, (GCompareFunc) strcmp); assert_int_equal(g_list_length(result), 2); assert_string_equal(g_list_nth_data(result, 0), "abc"); assert_string_equal(g_list_nth_data(result, 1), "def"); g_list_free(result); g_list_free_full(from, free); g_list_free_full(items, free); } static void remove_all_items(void **state) { GList *from = NULL; GList *items = NULL; GList *result = NULL; from = g_list_append(from, strdup("abc")); from = g_list_append(from, strdup("def")); from = g_list_append(from, strdup("ghi")); items = g_list_append(items, strdup("abc")); items = g_list_append(items, strdup("def")); items = g_list_append(items, strdup("ghi")); result = pcmk__subtract_lists(from, items, (GCompareFunc) strcmp); assert_int_equal(g_list_length(result), 0); g_list_free(result); g_list_free_full(from, free); g_list_free_full(items, free); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(different_lists), cmocka_unit_test(remove_first_item), cmocka_unit_test(remove_middle_item), cmocka_unit_test(remove_last_item), cmocka_unit_test(remove_all_items), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/nvpair/Makefile.am b/lib/common/tests/nvpair/Makefile.am index b52d6781ed..8b8866994d 100644 --- a/lib/common/tests/nvpair/Makefile.am +++ b/lib/common/tests/nvpair/Makefile.am @@ -1,23 +1,25 @@ # # Copyright 2021-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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk__xe_attr_is_true_test \ pcmk__xe_get_bool_attr_test \ pcmk__xe_set_bool_attr_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/nvpair/pcmk__xe_attr_is_true_test.c b/lib/common/tests/nvpair/pcmk__xe_attr_is_true_test.c index b8d5e4ee25..69ec199df8 100644 --- a/lib/common/tests/nvpair/pcmk__xe_attr_is_true_test.c +++ b/lib/common/tests/nvpair/pcmk__xe_attr_is_true_test.c @@ -1,64 +1,58 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include static void empty_input(void **state) { xmlNode *node = string2xml(""); assert_false(pcmk__xe_attr_is_true(NULL, NULL)); assert_false(pcmk__xe_attr_is_true(NULL, "whatever")); assert_false(pcmk__xe_attr_is_true(node, NULL)); free_xml(node); } static void attr_missing(void **state) { xmlNode *node = string2xml(""); assert_false(pcmk__xe_attr_is_true(node, "c")); free_xml(node); } static void attr_present(void **state) { xmlNode *node = string2xml(""); assert_true(pcmk__xe_attr_is_true(node, "a")); assert_false(pcmk__xe_attr_is_true(node, "b")); free_xml(node); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input), cmocka_unit_test(attr_missing), cmocka_unit_test(attr_present), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/nvpair/pcmk__xe_get_bool_attr_test.c b/lib/common/tests/nvpair/pcmk__xe_get_bool_attr_test.c index 3b4263d76b..e3577f2847 100644 --- a/lib/common/tests/nvpair/pcmk__xe_get_bool_attr_test.c +++ b/lib/common/tests/nvpair/pcmk__xe_get_bool_attr_test.c @@ -1,74 +1,67 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ -#include "crm/common/results.h" #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include static void empty_input(void **state) { xmlNode *node = string2xml(""); bool value; assert_int_equal(pcmk__xe_get_bool_attr(NULL, NULL, &value), ENODATA); assert_int_equal(pcmk__xe_get_bool_attr(NULL, "whatever", &value), ENODATA); assert_int_equal(pcmk__xe_get_bool_attr(node, NULL, &value), EINVAL); assert_int_equal(pcmk__xe_get_bool_attr(node, "whatever", NULL), EINVAL); free_xml(node); } static void attr_missing(void **state) { xmlNode *node = string2xml(""); bool value; assert_int_equal(pcmk__xe_get_bool_attr(node, "c", &value), ENODATA); free_xml(node); } static void attr_present(void **state) { xmlNode *node = string2xml(""); bool value; value = false; assert_int_equal(pcmk__xe_get_bool_attr(node, "a", &value), pcmk_rc_ok); assert_true(value); value = true; assert_int_equal(pcmk__xe_get_bool_attr(node, "b", &value), pcmk_rc_ok); assert_false(value); assert_int_equal(pcmk__xe_get_bool_attr(node, "c", &value), pcmk_rc_unknown_format); free_xml(node); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input), cmocka_unit_test(attr_missing), cmocka_unit_test(attr_present), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/nvpair/pcmk__xe_set_bool_attr_test.c b/lib/common/tests/nvpair/pcmk__xe_set_bool_attr_test.c index bd7eac1030..03ec0eb878 100644 --- a/lib/common/tests/nvpair/pcmk__xe_set_bool_attr_test.c +++ b/lib/common/tests/nvpair/pcmk__xe_set_bool_attr_test.c @@ -1,45 +1,39 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include #include #include -#include -#include -#include -#include -#include -#include -#include - static void set_attr(void **state) { xmlNode *node = string2xml(""); pcmk__xe_set_bool_attr(node, "a", true); pcmk__xe_set_bool_attr(node, "b", false); assert_string_equal(crm_element_value(node, "a"), XML_BOOLEAN_TRUE); assert_string_equal(crm_element_value(node, "b"), XML_BOOLEAN_FALSE); free_xml(node); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(set_attr), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/Makefile.am b/lib/common/tests/operations/Makefile.am index 9f975e474c..aad5346a93 100644 --- a/lib/common/tests/operations/Makefile.am +++ b/lib/common/tests/operations/Makefile.am @@ -1,27 +1,29 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = copy_in_properties_test \ expand_plus_plus_test \ fix_plus_plus_recursive_test \ parse_op_key_test \ pcmk_is_probe_test \ pcmk_xe_is_probe_test \ pcmk_xe_mask_probe_failure_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/operations/copy_in_properties_test.c b/lib/common/tests/operations/copy_in_properties_test.c index 3a652e7233..c410a65621 100644 --- a/lib/common/tests/operations/copy_in_properties_test.c +++ b/lib/common/tests/operations/copy_in_properties_test.c @@ -1,73 +1,69 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include + #include -#include -#include -#include -#include -#include -#include static void target_is_NULL(void **state) { xmlNode *test_xml_1 = create_xml_node(NULL, "test_xml_1"); xmlNode *test_xml_2 = NULL; pcmk__xe_set_props(test_xml_1, "test_prop", "test_value", NULL); copy_in_properties(test_xml_2, test_xml_1); assert_ptr_equal(test_xml_2, NULL); } static void src_is_NULL(void **state) { xmlNode *test_xml_1 = NULL; xmlNode *test_xml_2 = create_xml_node(NULL, "test_xml_2"); copy_in_properties(test_xml_2, test_xml_1); assert_ptr_equal(test_xml_2->properties, NULL); } static void copying_is_successful(void **state) { const char *xml_1_value; const char *xml_2_value; xmlNode *test_xml_1 = create_xml_node(NULL, "test_xml_1"); xmlNode *test_xml_2 = create_xml_node(NULL, "test_xml_2"); pcmk__xe_set_props(test_xml_1, "test_prop", "test_value", NULL); copy_in_properties(test_xml_2, test_xml_1); xml_1_value = crm_element_value(test_xml_1, "test_prop"); xml_2_value = crm_element_value(test_xml_2, "test_prop"); assert_string_equal(xml_1_value, xml_2_value); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(target_is_NULL), cmocka_unit_test(src_is_NULL), cmocka_unit_test(copying_is_successful), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/expand_plus_plus_test.c b/lib/common/tests/operations/expand_plus_plus_test.c index cbc1382c32..4db455089f 100644 --- a/lib/common/tests/operations/expand_plus_plus_test.c +++ b/lib/common/tests/operations/expand_plus_plus_test.c @@ -1,267 +1,263 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include + #include -#include -#include -#include -#include -#include -#include static void value_is_name_plus_plus(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "6"); } static void value_is_name_plus_equals_integer(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "X+=2"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "7"); } // NULL input static void target_is_NULL(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(NULL, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "5"); } static void name_is_NULL(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, NULL, "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "5"); } static void value_is_NULL(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", NULL); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "5"); } // the value input doesn't start with the name input static void value_is_wrong_name(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "Y++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "Y++"); } static void value_is_only_an_integer(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "2"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "2"); } // non-integers static void variable_is_initialized_to_be_NULL(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", NULL); expand_plus_plus(test_xml, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "X++"); } static void variable_is_initialized_to_be_non_numeric(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "hello"); expand_plus_plus(test_xml, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "1"); } static void variable_is_initialized_to_be_non_numeric_2(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "hello"); expand_plus_plus(test_xml, "X", "X+=2"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "2"); } static void variable_is_initialized_to_be_numeric_and_decimal_point_containing(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5.01"); expand_plus_plus(test_xml, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "6"); } static void variable_is_initialized_to_be_numeric_and_decimal_point_containing_2(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5.50"); expand_plus_plus(test_xml, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "6"); } static void variable_is_initialized_to_be_numeric_and_decimal_point_containing_3(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5.99"); expand_plus_plus(test_xml, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "6"); } static void value_is_non_numeric(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "X+=hello"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "5"); } static void value_is_numeric_and_decimal_point_containing(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "X+=2.01"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "7"); } static void value_is_numeric_and_decimal_point_containing_2(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "X+=1.50"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "6"); } static void value_is_numeric_and_decimal_point_containing_3(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "X+=1.99"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "6"); } // undefined input static void name_is_undefined(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "Y", "5"); expand_plus_plus(test_xml, "X", "X++"); new_value = crm_element_value(test_xml, "X"); assert_string_equal(new_value, "X++"); } // large input static void assignment_result_is_too_large(void **state) { const char *new_value; xmlNode *test_xml = create_xml_node(NULL, "test_xml"); crm_xml_add(test_xml, "X", "5"); expand_plus_plus(test_xml, "X", "X+=100000000000"); new_value = crm_element_value(test_xml, "X"); printf("assignment result is too large %s\n", new_value); assert_string_equal(new_value, "1000000"); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(value_is_name_plus_plus), cmocka_unit_test(value_is_name_plus_equals_integer), cmocka_unit_test(target_is_NULL), cmocka_unit_test(name_is_NULL), cmocka_unit_test(value_is_NULL), cmocka_unit_test(value_is_wrong_name), cmocka_unit_test(value_is_only_an_integer), cmocka_unit_test(variable_is_initialized_to_be_NULL), cmocka_unit_test(variable_is_initialized_to_be_non_numeric), cmocka_unit_test(variable_is_initialized_to_be_non_numeric_2), cmocka_unit_test(variable_is_initialized_to_be_numeric_and_decimal_point_containing), cmocka_unit_test(variable_is_initialized_to_be_numeric_and_decimal_point_containing_2), cmocka_unit_test(variable_is_initialized_to_be_numeric_and_decimal_point_containing_3), cmocka_unit_test(value_is_non_numeric), cmocka_unit_test(value_is_numeric_and_decimal_point_containing), cmocka_unit_test(value_is_numeric_and_decimal_point_containing_2), cmocka_unit_test(value_is_numeric_and_decimal_point_containing_3), cmocka_unit_test(name_is_undefined), cmocka_unit_test(assignment_result_is_too_large), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/fix_plus_plus_recursive_test.c b/lib/common/tests/operations/fix_plus_plus_recursive_test.c index 9ad48b58e4..8aaada5980 100644 --- a/lib/common/tests/operations/fix_plus_plus_recursive_test.c +++ b/lib/common/tests/operations/fix_plus_plus_recursive_test.c @@ -1,58 +1,54 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include + #include -#include -#include -#include -#include -#include -#include static void element_nodes(void **state) { const char *new_value_root; const char *new_value_child; const char *new_value_grandchild; xmlNode *test_xml_root = create_xml_node(NULL, "test_xml_root"); xmlNode *test_xml_child = create_xml_node(test_xml_root, "test_xml_child"); xmlNode *test_xml_grandchild = create_xml_node(test_xml_child, "test_xml_grandchild"); xmlNode *test_xml_text = pcmk_create_xml_text_node(test_xml_root, "text_xml_text", "content"); xmlNode *test_xml_comment = string2xml(""); crm_xml_add(test_xml_root, "X", "5"); crm_xml_add(test_xml_child, "X", "X++"); crm_xml_add(test_xml_grandchild, "X", "X+=2"); crm_xml_add(test_xml_text, "X", "X++"); fix_plus_plus_recursive(test_xml_root); fix_plus_plus_recursive(test_xml_comment); new_value_root = crm_element_value(test_xml_root, "X"); new_value_child = crm_element_value(test_xml_child, "X"); new_value_grandchild = crm_element_value(test_xml_grandchild, "X"); assert_string_equal(new_value_root, "5"); assert_string_equal(new_value_child, "1"); assert_string_equal(new_value_grandchild, "2"); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(element_nodes), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/parse_op_key_test.c b/lib/common/tests/operations/parse_op_key_test.c index daac346e12..a830adf307 100644 --- a/lib/common/tests/operations/parse_op_key_test.c +++ b/lib/common/tests/operations/parse_op_key_test.c @@ -1,234 +1,230 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include +#include + #include -#include -#include -#include -#include -#include -#include static void basic(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; assert_true(parse_op_key("Fencing_monitor_60000", &rsc, &ty, &ms)); assert_string_equal(rsc, "Fencing"); assert_string_equal(ty, "monitor"); assert_int_equal(ms, 60000); free(rsc); free(ty); } static void colon_in_rsc(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; assert_true(parse_op_key("ClusterIP:0_start_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "ClusterIP:0"); assert_string_equal(ty, "start"); assert_int_equal(ms, 0); free(rsc); free(ty); assert_true(parse_op_key("imagestoreclone:1_post_notify_stop_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "imagestoreclone:1"); assert_string_equal(ty, "post_notify_stop"); assert_int_equal(ms, 0); free(rsc); free(ty); } static void dashes_in_rsc(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; assert_true(parse_op_key("httpd-bundle-0_monitor_30000", &rsc, &ty, &ms)); assert_string_equal(rsc, "httpd-bundle-0"); assert_string_equal(ty, "monitor"); assert_int_equal(ms, 30000); free(rsc); free(ty); assert_true(parse_op_key("httpd-bundle-ip-192.168.122.132_start_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "httpd-bundle-ip-192.168.122.132"); assert_string_equal(ty, "start"); assert_int_equal(ms, 0); free(rsc); free(ty); } static void migrate_to_from(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; assert_true(parse_op_key("vm_migrate_from_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "vm"); assert_string_equal(ty, "migrate_from"); assert_int_equal(ms, 0); free(rsc); free(ty); assert_true(parse_op_key("vm_migrate_to_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "vm"); assert_string_equal(ty, "migrate_to"); assert_int_equal(ms, 0); free(rsc); free(ty); assert_true(parse_op_key("vm_idcc_devel_migrate_to_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "vm_idcc_devel"); assert_string_equal(ty, "migrate_to"); assert_int_equal(ms, 0); free(rsc); free(ty); } static void pre_post(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; assert_true(parse_op_key("rsc_drbd_7788:1_post_notify_start_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "rsc_drbd_7788:1"); assert_string_equal(ty, "post_notify_start"); assert_int_equal(ms, 0); free(rsc); free(ty); assert_true(parse_op_key("rabbitmq-bundle-clone_pre_notify_stop_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "rabbitmq-bundle-clone"); assert_string_equal(ty, "pre_notify_stop"); assert_int_equal(ms, 0); free(rsc); free(ty); assert_true(parse_op_key("post_notify_start_0", &rsc, &ty, &ms)); assert_string_equal(rsc, "post_notify"); assert_string_equal(ty, "start"); assert_int_equal(ms, 0); free(rsc); free(ty); } static void skip_rsc(void **state) { char *ty = NULL; guint ms = 0; assert_true(parse_op_key("Fencing_monitor_60000", NULL, &ty, &ms)); assert_string_equal(ty, "monitor"); assert_int_equal(ms, 60000); free(ty); } static void skip_ty(void **state) { char *rsc = NULL; guint ms = 0; assert_true(parse_op_key("Fencing_monitor_60000", &rsc, NULL, &ms)); assert_string_equal(rsc, "Fencing"); assert_int_equal(ms, 60000); free(rsc); } static void skip_ms(void **state) { char *rsc = NULL; char *ty = NULL; assert_true(parse_op_key("Fencing_monitor_60000", &rsc, &ty, NULL)); assert_string_equal(rsc, "Fencing"); assert_string_equal(ty, "monitor"); free(rsc); free(ty); } static void empty_input(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; assert_false(parse_op_key("", &rsc, &ty, &ms)); assert_null(rsc); assert_null(ty); assert_int_equal(ms, 0); assert_false(parse_op_key(NULL, &rsc, &ty, &ms)); assert_null(rsc); assert_null(ty); assert_int_equal(ms, 0); } static void malformed_input(void **state) { char *rsc = NULL; char *ty = NULL; guint ms = 0; assert_false(parse_op_key("httpd-bundle-0", &rsc, &ty, &ms)); assert_null(rsc); assert_null(ty); assert_int_equal(ms, 0); assert_false(parse_op_key("httpd-bundle-0_monitor", &rsc, &ty, &ms)); assert_null(rsc); assert_null(ty); assert_int_equal(ms, 0); assert_false(parse_op_key("httpd-bundle-0_30000", &rsc, &ty, &ms)); assert_null(rsc); assert_null(ty); assert_int_equal(ms, 0); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(basic), cmocka_unit_test(colon_in_rsc), cmocka_unit_test(dashes_in_rsc), cmocka_unit_test(migrate_to_from), cmocka_unit_test(pre_post), cmocka_unit_test(skip_rsc), cmocka_unit_test(skip_ty), cmocka_unit_test(skip_ms), cmocka_unit_test(empty_input), cmocka_unit_test(malformed_input), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/pcmk_is_probe_test.c b/lib/common/tests/operations/pcmk_is_probe_test.c index 9b449f1a70..07b2d45493 100644 --- a/lib/common/tests/operations/pcmk_is_probe_test.c +++ b/lib/common/tests/operations/pcmk_is_probe_test.c @@ -1,37 +1,32 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include +#include static void is_probe_test(void **state) { assert_false(pcmk_is_probe(NULL, 0)); assert_false(pcmk_is_probe("", 0)); assert_false(pcmk_is_probe("blahblah", 0)); assert_false(pcmk_is_probe("monitor", 1)); assert_true(pcmk_is_probe("monitor", 0)); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(is_probe_test), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/pcmk_xe_is_probe_test.c b/lib/common/tests/operations/pcmk_xe_is_probe_test.c index 0283d1c145..28312160a3 100644 --- a/lib/common/tests/operations/pcmk_xe_is_probe_test.c +++ b/lib/common/tests/operations/pcmk_xe_is_probe_test.c @@ -1,55 +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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include +#include static void op_is_probe_test(void **state) { xmlNode *node = NULL; assert_false(pcmk_xe_is_probe(NULL)); node = string2xml(""); assert_false(pcmk_xe_is_probe(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_is_probe(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_is_probe(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_is_probe(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_is_probe(node)); free_xml(node); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(op_is_probe_test), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/operations/pcmk_xe_mask_probe_failure_test.c b/lib/common/tests/operations/pcmk_xe_mask_probe_failure_test.c index a13f6d98f4..51b9a29c88 100644 --- a/lib/common/tests/operations/pcmk_xe_mask_probe_failure_test.c +++ b/lib/common/tests/operations/pcmk_xe_mask_probe_failure_test.c @@ -1,162 +1,157 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include +#include static void op_is_not_probe_test(void **state) { xmlNode *node = NULL; /* Not worth testing this thoroughly since it's just a duplicate of whether * pcmk_op_is_probe works or not. */ node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); } static void op_does_not_have_right_values_test(void **state) { xmlNode *node = NULL; node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); } static void check_values_test(void **state) { xmlNode *node = NULL; /* PCMK_EXEC_NOT_SUPPORTED */ node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); /* PCMK_EXEC_DONE */ node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); /* PCMK_EXEC_NOT_INSTALLED */ node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); /* PCMK_EXEC_ERROR */ node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); /* PCMK_EXEC_ERROR_HARD */ node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); /* PCMK_EXEC_ERROR_FATAL */ node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_true(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); node = string2xml(""); assert_false(pcmk_xe_mask_probe_failure(node)); free_xml(node); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(op_is_not_probe_test), cmocka_unit_test(op_does_not_have_right_values_test), cmocka_unit_test(check_values_test), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/procfs/Makefile.am b/lib/common/tests/procfs/Makefile.am index 2bf936c9d2..5affdd353c 100644 --- a/lib/common/tests/procfs/Makefile.am +++ b/lib/common/tests/procfs/Makefile.am @@ -1,23 +1,25 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk__procfs_has_pids_false_test \ pcmk__procfs_has_pids_true_test \ pcmk__procfs_pid2path_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/procfs/pcmk__procfs_has_pids_false_test.c b/lib/common/tests/procfs/pcmk__procfs_has_pids_false_test.c index 888ecb1f70..2f11c2d615 100644 --- a/lib/common/tests/procfs/pcmk__procfs_has_pids_false_test.c +++ b/lib/common/tests/procfs/pcmk__procfs_has_pids_false_test.c @@ -1,51 +1,47 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include "mock_private.h" -#include -#include -#include -#include -#include -#include +#include + +#include "mock_private.h" #include #include #include #if SUPPORT_PROCFS static void no_pids(void **state) { // Set readlink() errno and link contents (for /proc/PID/exe) pcmk__mock_readlink = true; will_return(__wrap_readlink, ENOENT); will_return(__wrap_readlink, NULL); assert_false(pcmk__procfs_has_pids()); pcmk__mock_readlink = false; } #endif // SUPPORT_PROCFS int main(int argc, char **argv) { const struct CMUnitTest tests[] = { #if SUPPORT_PROCFS cmocka_unit_test(no_pids), #endif }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/procfs/pcmk__procfs_has_pids_true_test.c b/lib/common/tests/procfs/pcmk__procfs_has_pids_true_test.c index 7c61b50a10..f9730a6baf 100644 --- a/lib/common/tests/procfs/pcmk__procfs_has_pids_true_test.c +++ b/lib/common/tests/procfs/pcmk__procfs_has_pids_true_test.c @@ -1,51 +1,47 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include "mock_private.h" -#include -#include -#include -#include -#include -#include +#include + +#include "mock_private.h" #include #include #include #if SUPPORT_PROCFS static void has_pids(void **state) { // Set readlink() errno and link contents (for /proc/PID/exe) pcmk__mock_readlink = true; will_return(__wrap_readlink, 0); will_return(__wrap_readlink, "/ok"); assert_true(pcmk__procfs_has_pids()); pcmk__mock_readlink = false; } #endif // SUPPORT_PROCFS int main(int argc, char **argv) { const struct CMUnitTest tests[] = { #if SUPPORT_PROCFS cmocka_unit_test(has_pids), #endif }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c b/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c index acb56e807b..aaba7e29a7 100644 --- a/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c +++ b/lib/common/tests/procfs/pcmk__procfs_pid2path_test.c @@ -1,88 +1,84 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include "mock_private.h" -#include -#include -#include -#include -#include -#include +#include + +#include "mock_private.h" #include #include #include #if SUPPORT_PROCFS static void no_exe_file(void **state) { char path[PATH_MAX]; // Set readlink() errno and link contents pcmk__mock_readlink = true; will_return(__wrap_readlink, ENOENT); will_return(__wrap_readlink, NULL); assert_int_equal(pcmk__procfs_pid2path(1000, path, sizeof(path)), ENOENT); pcmk__mock_readlink = false; } static void contents_too_long(void **state) { char path[10]; // Set readlink() errno and link contents pcmk__mock_readlink = true; will_return(__wrap_readlink, 0); will_return(__wrap_readlink, "/more/than/10/characters"); assert_int_equal(pcmk__procfs_pid2path(1000, path, sizeof(path)), ENAMETOOLONG); pcmk__mock_readlink = false; } static void contents_ok(void **state) { char path[PATH_MAX]; // Set readlink() errno and link contents pcmk__mock_readlink = true; will_return(__wrap_readlink, 0); will_return(__wrap_readlink, "/ok"); assert_int_equal(pcmk__procfs_pid2path((pid_t) 1000, path, sizeof(path)), pcmk_rc_ok); assert_string_equal(path, "/ok"); pcmk__mock_readlink = false; } #endif // SUPPORT_PROCFS int main(int argc, char **argv) { const struct CMUnitTest tests[] = { #if SUPPORT_PROCFS cmocka_unit_test(no_exe_file), cmocka_unit_test(contents_too_long), cmocka_unit_test(contents_ok), #endif }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/results/Makefile.am b/lib/common/tests/results/Makefile.am index d77207ecdd..9476e80a9d 100644 --- a/lib/common/tests/results/Makefile.am +++ b/lib/common/tests/results/Makefile.am @@ -1,21 +1,23 @@ # # Copyright 2021-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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk__results_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/results/pcmk__results_test.c b/lib/common/tests/results/pcmk__results_test.c index e08d4b6261..e646b7bbcf 100644 --- a/lib/common/tests/results/pcmk__results_test.c +++ b/lib/common/tests/results/pcmk__results_test.c @@ -1,71 +1,67 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include #include #include static void test_for_pcmk_rc_name(void **state) { assert_string_equal(pcmk_rc_name(pcmk_rc_error-1), "pcmk_rc_unknown_format"); assert_string_equal(pcmk_rc_name(pcmk_rc_ok), "pcmk_rc_ok"); assert_string_equal(pcmk_rc_name(pcmk_rc_ok), "pcmk_rc_ok"); assert_string_equal(pcmk_rc_name(-7777777), "Unknown"); } static void test_for_pcmk_rc_str(void **state) { assert_string_equal(pcmk_rc_str(pcmk_rc_error-1), "Unknown output format"); assert_string_equal(pcmk_rc_str(pcmk_rc_ok), "OK"); assert_string_equal(pcmk_rc_str(-1), "Error"); } static void test_for_crm_exit_name(void **state) { assert_string_equal(crm_exit_name(CRM_EX_OK), "CRM_EX_OK"); } static void test_for_crm_exit_str(void **state) { assert_string_equal(crm_exit_str(CRM_EX_OK), "OK"); assert_string_equal(crm_exit_str(129), "Interrupted by signal"); assert_string_equal(crm_exit_str(-7777777), "Unknown exit status"); } static void test_for_pcmk_rc2exitc(void **state) { assert_int_equal(pcmk_rc2exitc(pcmk_rc_ok), CRM_EX_OK); assert_int_equal(pcmk_rc2exitc(-7777777), CRM_EX_ERROR); } static void test_for_bz2_strerror(void **state) { assert_string_equal(bz2_strerror(BZ_STREAM_END), "Ok"); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_for_pcmk_rc_name), cmocka_unit_test(test_for_pcmk_rc_str), cmocka_unit_test(test_for_crm_exit_name), cmocka_unit_test(test_for_crm_exit_str), cmocka_unit_test(test_for_pcmk_rc2exitc), cmocka_unit_test(test_for_bz2_strerror), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/scores/Makefile.am b/lib/common/tests/scores/Makefile.am index b4e24b09a1..edcbc1e863 100644 --- a/lib/common/tests/scores/Makefile.am +++ b/lib/common/tests/scores/Makefile.am @@ -1,24 +1,26 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = \ char2score_test \ pcmk__add_scores_test \ pcmk_readable_score_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/scores/char2score_test.c b/lib/common/tests/scores/char2score_test.c index 49560cc41d..3c0631a1c2 100644 --- a/lib/common/tests/scores/char2score_test.c +++ b/lib/common/tests/scores/char2score_test.c @@ -1,86 +1,82 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include extern int pcmk__score_red; extern int pcmk__score_green; extern int pcmk__score_yellow; static void empty_input(void **state) { assert_int_equal(char2score(NULL), 0); } static void bad_input(void **state) { assert_int_equal(char2score("PQRST"), 0); assert_int_equal(char2score("3.141592"), 3); assert_int_equal(char2score("0xf00d"), 0); } static void special_values(void **state) { assert_int_equal(char2score("-INFINITY"), -CRM_SCORE_INFINITY); assert_int_equal(char2score("INFINITY"), CRM_SCORE_INFINITY); assert_int_equal(char2score("+INFINITY"), CRM_SCORE_INFINITY); pcmk__score_red = 10; pcmk__score_green = 20; pcmk__score_yellow = 30; assert_int_equal(char2score("red"), pcmk__score_red); assert_int_equal(char2score("green"), pcmk__score_green); assert_int_equal(char2score("yellow"), pcmk__score_yellow); assert_int_equal(char2score("ReD"), pcmk__score_red); assert_int_equal(char2score("GrEeN"), pcmk__score_green); assert_int_equal(char2score("yElLoW"), pcmk__score_yellow); } /* These ridiculous macros turn an integer constant into a string constant. */ #define A(x) #x #define B(x) A(x) static void outside_limits(void **state) { assert_int_equal(char2score(B(CRM_SCORE_INFINITY) "00"), CRM_SCORE_INFINITY); assert_int_equal(char2score("-" B(CRM_SCORE_INFINITY) "00"), -CRM_SCORE_INFINITY); } static void inside_limits(void **state) { assert_int_equal(char2score("1234"), 1234); assert_int_equal(char2score("-1234"), -1234); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input), cmocka_unit_test(bad_input), cmocka_unit_test(special_values), cmocka_unit_test(outside_limits), cmocka_unit_test(inside_limits), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/scores/pcmk__add_scores_test.c b/lib/common/tests/scores/pcmk__add_scores_test.c index bf7f0cf956..52d0a4e31b 100644 --- a/lib/common/tests/scores/pcmk__add_scores_test.c +++ b/lib/common/tests/scores/pcmk__add_scores_test.c @@ -1,85 +1,81 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void score1_minus_inf(void **state) { assert_int_equal(pcmk__add_scores(-CRM_SCORE_INFINITY, -CRM_SCORE_INFINITY), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(-CRM_SCORE_INFINITY, -1), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(-CRM_SCORE_INFINITY, 0), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(-CRM_SCORE_INFINITY, 1), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(-CRM_SCORE_INFINITY, CRM_SCORE_INFINITY), -CRM_SCORE_INFINITY); } static void score2_minus_inf(void **state) { assert_int_equal(pcmk__add_scores(-1, -CRM_SCORE_INFINITY), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(0, -CRM_SCORE_INFINITY), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(1, -CRM_SCORE_INFINITY), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(CRM_SCORE_INFINITY, -CRM_SCORE_INFINITY), -CRM_SCORE_INFINITY); } static void score1_pos_inf(void **state) { assert_int_equal(pcmk__add_scores(CRM_SCORE_INFINITY, CRM_SCORE_INFINITY), CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(CRM_SCORE_INFINITY, -1), CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(CRM_SCORE_INFINITY, 0), CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(CRM_SCORE_INFINITY, 1), CRM_SCORE_INFINITY); } static void score2_pos_inf(void **state) { assert_int_equal(pcmk__add_scores(-1, CRM_SCORE_INFINITY), CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(0, CRM_SCORE_INFINITY), CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(1, CRM_SCORE_INFINITY), CRM_SCORE_INFINITY); } static void result_infinite(void **state) { assert_int_equal(pcmk__add_scores(INT_MAX, INT_MAX), CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(INT_MIN, INT_MIN), -CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(2000000, 50), CRM_SCORE_INFINITY); assert_int_equal(pcmk__add_scores(-4000000, 50), -CRM_SCORE_INFINITY); } static void result_finite(void **state) { assert_int_equal(pcmk__add_scores(0, 0), 0); assert_int_equal(pcmk__add_scores(0, 100), 100); assert_int_equal(pcmk__add_scores(200, 0), 200); assert_int_equal(pcmk__add_scores(200, -50), 150); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(score1_minus_inf), cmocka_unit_test(score2_minus_inf), cmocka_unit_test(score1_pos_inf), cmocka_unit_test(score2_pos_inf), cmocka_unit_test(result_infinite), cmocka_unit_test(result_finite), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/scores/pcmk_readable_score_test.c b/lib/common/tests/scores/pcmk_readable_score_test.c index 72d7f9975e..c46528156b 100644 --- a/lib/common/tests/scores/pcmk_readable_score_test.c +++ b/lib/common/tests/scores/pcmk_readable_score_test.c @@ -1,44 +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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void outside_limits(void **state) { assert_string_equal(pcmk_readable_score(CRM_SCORE_INFINITY * 2), CRM_INFINITY_S); assert_string_equal(pcmk_readable_score(-CRM_SCORE_INFINITY * 2), CRM_MINUS_INFINITY_S); } static void inside_limits(void **state) { assert_string_equal(pcmk_readable_score(0), "0"); assert_string_equal(pcmk_readable_score(1024), "1024"); assert_string_equal(pcmk_readable_score(-1024), "-1024"); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(outside_limits), cmocka_unit_test(inside_limits), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/Makefile.am b/lib/common/tests/strings/Makefile.am index cb84a123dc..8337d889d0 100644 --- a/lib/common/tests/strings/Makefile.am +++ b/lib/common/tests/strings/Makefile.am @@ -1,44 +1,46 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.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__guint_from_hash_test \ pcmk__numeric_strcasecmp_test \ pcmk__parse_ll_range_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 index ad6b43bb0f..a17651eae9 100644 --- a/lib/common/tests/strings/crm_get_msec_test.c +++ b/lib/common/tests/strings/crm_get_msec_test.c @@ -1,62 +1,58 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(bad_input), cmocka_unit_test(good_input), cmocka_unit_test(overflow), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/crm_is_true_test.c b/lib/common/tests/strings/crm_is_true_test.c index b1d5c9cab7..8f7c810296 100644 --- a/lib/common/tests/strings/crm_is_true_test.c +++ b/lib/common/tests/strings/crm_is_true_test.c @@ -1,69 +1,65 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(bad_input), cmocka_unit_test(is_true), cmocka_unit_test(is_false), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/crm_str_to_boolean_test.c b/lib/common/tests/strings/crm_str_to_boolean_test.c index 6e9748aa91..e04435d78b 100644 --- a/lib/common/tests/strings/crm_str_to_boolean_test.c +++ b/lib/common/tests/strings/crm_str_to_boolean_test.c @@ -1,104 +1,100 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { 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), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__add_word_test.c b/lib/common/tests/strings/pcmk__add_word_test.c index 50f2599c5e..369c8670b2 100644 --- a/lib/common/tests/strings/pcmk__add_word_test.c +++ b/lib/common/tests/strings/pcmk__add_word_test.c @@ -1,108 +1,102 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include -#include +#include static void add_words(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_word(&list, &list_len, "hello"); pcmk__add_word(&list, &list_len, "world"); assert_int_equal(strcmp(list, "hello world"), 0); free(list); } static void add_with_no_len(void **state) { char *list = NULL; pcmk__add_word(&list, NULL, "hello"); pcmk__add_word(&list, NULL, "world"); assert_int_equal(strcmp(list, "hello world"), 0); free(list); } static void add_nothing(void **state) { char *list = NULL; pcmk__add_word(&list, NULL, "hello"); pcmk__add_word(&list, NULL, NULL); pcmk__add_word(&list, NULL, ""); assert_int_equal(strcmp(list, "hello"), 0); free(list); } static void add_with_null(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_separated_word(&list, &list_len, "hello", NULL); pcmk__add_separated_word(&list, &list_len, "world", NULL); pcmk__add_separated_word(&list, &list_len, "I am a unit test", NULL); assert_int_equal(strcmp(list, "hello world I am a unit test"), 0); free(list); } static void add_with_comma(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_separated_word(&list, &list_len, "hello", ","); pcmk__add_separated_word(&list, &list_len, "world", ","); pcmk__add_separated_word(&list, &list_len, "I am a unit test", ","); assert_int_equal(strcmp(list, "hello,world,I am a unit test"), 0); free(list); } static void add_with_comma_and_space(void **state) { char *list = NULL; size_t list_len = 0; pcmk__add_separated_word(&list, &list_len, "hello", ", "); pcmk__add_separated_word(&list, &list_len, "world", ", "); pcmk__add_separated_word(&list, &list_len, "I am a unit test", ", "); assert_int_equal(strcmp(list, "hello, world, I am a unit test"), 0); free(list); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { 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), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__btoa_test.c b/lib/common/tests/strings/pcmk__btoa_test.c index 10261f5623..77efd5bd16 100644 --- a/lib/common/tests/strings/pcmk__btoa_test.c +++ b/lib/common/tests/strings/pcmk__btoa_test.c @@ -1,34 +1,30 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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"); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(btoa), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } 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 index cd469af990..7e61f0c62f 100644 --- a/lib/common/tests/strings/pcmk__char_in_any_str_test.c +++ b/lib/common/tests/strings/pcmk__char_in_any_str_test.c @@ -1,58 +1,54 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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)); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_list), cmocka_unit_test(null_char), cmocka_unit_test(in_list), cmocka_unit_test(not_in_list), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__compress_test.c b/lib/common/tests/strings/pcmk__compress_test.c index b6e6df74ed..5e131b768d 100644 --- a/lib/common/tests/strings/pcmk__compress_test.c +++ b/lib/common/tests/strings/pcmk__compress_test.c @@ -1,51 +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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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__mock_calloc = true; // calloc() will return NULL + pcmk__assert_asserts(pcmk__compress(SIMPLE_DATA, 40, 0, &result, &len)); + pcmk__mock_calloc = false; // Use the real calloc() +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(simple_compress), cmocka_unit_test(max_too_small), + cmocka_unit_test(calloc_fails), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__ends_with_test.c b/lib/common/tests/strings/pcmk__ends_with_test.c index 00a08445aa..aafe548dff 100644 --- a/lib/common/tests/strings/pcmk__ends_with_test.c +++ b/lib/common/tests/strings/pcmk__ends_with_test.c @@ -1,69 +1,65 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(bad_input), cmocka_unit_test(ends_with), cmocka_unit_test(ends_with_ext), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__guint_from_hash_test.c b/lib/common/tests/strings/pcmk__guint_from_hash_test.c index 0a0653ccbf..7f951ff95f 100644 --- a/lib/common/tests/strings/pcmk__guint_from_hash_test.c +++ b/lib/common/tests/strings/pcmk__guint_from_hash_test.c @@ -1,86 +1,82 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(null_args), cmocka_unit_test(missing_key), cmocka_unit_test(standard_usage), cmocka_unit_test(conversion_errors), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c b/lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c index 4ead552563..05b1e3610a 100644 --- a/lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c +++ b/lib/common/tests/strings/pcmk__numeric_strcasecmp_test.c @@ -1,82 +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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include 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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(no_numbers), cmocka_unit_test(trailing_numbers), cmocka_unit_test(middle_numbers), cmocka_unit_test(unequal_lengths), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__parse_ll_range_test.c b/lib/common/tests/strings/pcmk__parse_ll_range_test.c index e6b8e48959..5ec020f69b 100644 --- a/lib/common/tests/strings/pcmk__parse_ll_range_test.c +++ b/lib/common/tests/strings/pcmk__parse_ll_range_test.c @@ -1,118 +1,124 @@ /* - * Copyright 2020-2021 the Pacemaker project contributors + * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void empty_input_string(void **state) { long long start, end; assert_int_equal(pcmk__parse_ll_range(NULL, &start, &end), pcmk_rc_unknown_format); assert_int_equal(pcmk__parse_ll_range("", &start, &end), pcmk_rc_unknown_format); } +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_unknown_format); 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_unknown_format); } static void garbage(void **state) { long long start, end; assert_int_equal(pcmk__parse_ll_range("2000x-", &start, &end), pcmk_rc_unknown_format); 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_unknown_format); 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), pcmk_rc_unknown_format); assert_int_equal(pcmk__parse_ll_range("100-20000000000000000000", &start, &end), pcmk_rc_unknown_format); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { 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), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__scan_double_test.c b/lib/common/tests/strings/pcmk__scan_double_test.c index 26684233f8..3c15402077 100644 --- a/lib/common/tests/strings/pcmk__scan_double_test.c +++ b/lib/common/tests/strings/pcmk__scan_double_test.c @@ -1,166 +1,169 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { // Test for input string issues cmocka_unit_test(empty_input_string), cmocka_unit_test(bad_input_string), cmocka_unit_test(trailing_chars), + cmocka_unit_test(no_result_variable), // Test for numeric issues cmocka_unit_test(typical_case), cmocka_unit_test(double_overflow), cmocka_unit_test(double_underflow), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__scan_min_int_test.c b/lib/common/tests/strings/pcmk__scan_min_int_test.c index 9c5d073ddb..bb08edf8c2 100644 --- a/lib/common/tests/strings/pcmk__scan_min_int_test.c +++ b/lib/common/tests/strings/pcmk__scan_min_int_test.c @@ -1,72 +1,68 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input_string), cmocka_unit_test(input_below_minimum), cmocka_unit_test(input_above_maximum), cmocka_unit_test(input_just_right), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__scan_port_test.c b/lib/common/tests/strings/pcmk__scan_port_test.c index 0a6a1a96d2..50c3a03d0e 100644 --- a/lib/common/tests/strings/pcmk__scan_port_test.c +++ b/lib/common/tests/strings/pcmk__scan_port_test.c @@ -1,71 +1,67 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input_string), cmocka_unit_test(bad_input_string), cmocka_unit_test(out_of_range), cmocka_unit_test(typical_case), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__starts_with_test.c b/lib/common/tests/strings/pcmk__starts_with_test.c index f6427dd8e7..a77add9772 100644 --- a/lib/common/tests/strings/pcmk__starts_with_test.c +++ b/lib/common/tests/strings/pcmk__starts_with_test.c @@ -1,47 +1,43 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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", "")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(bad_input), cmocka_unit_test(starts_with), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__str_any_of_test.c b/lib/common/tests/strings/pcmk__str_any_of_test.c index ee5b1ab8d8..e940186194 100644 --- a/lib/common/tests/strings/pcmk__str_any_of_test.c +++ b/lib/common/tests/strings/pcmk__str_any_of_test.c @@ -1,59 +1,55 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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)); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input_list), cmocka_unit_test(empty_string), cmocka_unit_test(in_list), cmocka_unit_test(not_in_list), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__str_in_list_test.c b/lib/common/tests/strings/pcmk__str_in_list_test.c index 8d3367f559..2dd7902d2f 100644 --- a/lib/common/tests/strings/pcmk__str_in_list_test.c +++ b/lib/common/tests/strings/pcmk__str_in_list_test.c @@ -1,118 +1,114 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include +#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { 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), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__str_table_dup_test.c b/lib/common/tests/strings/pcmk__str_table_dup_test.c index de7e41a077..5d53ff69f5 100644 --- a/lib/common/tests/strings/pcmk__str_table_dup_test.c +++ b/lib/common/tests/strings/pcmk__str_table_dup_test.c @@ -1,69 +1,65 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(null_input_table), cmocka_unit_test(empty_input_table), cmocka_unit_test(regular_input_table), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__str_update_test.c b/lib/common/tests/strings/pcmk__str_update_test.c index 3f5cb30ade..7d1b0cf780 100644 --- a/lib/common/tests/strings/pcmk__str_update_test.c +++ b/lib/common/tests/strings/pcmk__str_update_test.c @@ -1,69 +1,81 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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__mock_strdup = true; // strdup() will return NULL + pcmk__assert_asserts(pcmk__str_update(&str, "world")); + pcmk__mock_strdup = false; // Use the real strdup() + + free(str); +} + int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(update_null), cmocka_unit_test(update_same), cmocka_unit_test(update_different), + cmocka_unit_test(strdup_fails), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__strcmp_test.c b/lib/common/tests/strings/pcmk__strcmp_test.c index 26b78995e3..b90177dcfa 100644 --- a/lib/common/tests/strings/pcmk__strcmp_test.c +++ b/lib/common/tests/strings/pcmk__strcmp_test.c @@ -1,90 +1,86 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { 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), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__strikey_table_test.c b/lib/common/tests/strings/pcmk__strikey_table_test.c index 03d12a7761..e6823ff569 100644 --- a/lib/common/tests/strings/pcmk__strikey_table_test.c +++ b/lib/common/tests/strings/pcmk__strikey_table_test.c @@ -1,50 +1,46 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(store_strs), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__strkey_table_test.c b/lib/common/tests/strings/pcmk__strkey_table_test.c index 3d4c3b1f03..e5f9834eb6 100644 --- a/lib/common/tests/strings/pcmk__strkey_table_test.c +++ b/lib/common/tests/strings/pcmk__strkey_table_test.c @@ -1,50 +1,46 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(store_strs), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/strings/pcmk__trim_test.c b/lib/common/tests/strings/pcmk__trim_test.c index 1b9196ac80..c9784d9969 100644 --- a/lib/common/tests/strings/pcmk__trim_test.c +++ b/lib/common/tests/strings/pcmk__trim_test.c @@ -1,82 +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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#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); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { 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), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/Makefile.am b/lib/common/tests/utils/Makefile.am index 7266b0e624..b264a9a1e1 100644 --- a/lib/common/tests/utils/Makefile.am +++ b/lib/common/tests/utils/Makefile.am @@ -1,32 +1,34 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = \ compare_version_test \ crm_meta_name_test \ crm_meta_value_test \ crm_user_lookup_test \ pcmk_daemon_user_test \ pcmk_str_is_infinity_test \ pcmk_str_is_minus_infinity_test if WRAPPABLE_UNAME check_PROGRAMS += pcmk_hostname_test endif TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/utils/compare_version_test.c b/lib/common/tests/utils/compare_version_test.c index b380ea49c5..4bcabe472d 100644 --- a/lib/common/tests/utils/compare_version_test.c +++ b/lib/common/tests/utils/compare_version_test.c @@ -1,66 +1,62 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void empty_params(void **state) { assert_int_equal(compare_version(NULL, NULL), 0); assert_int_equal(compare_version(NULL, "abc"), -1); assert_int_equal(compare_version(NULL, "1.0.1"), -1); assert_int_equal(compare_version("abc", NULL), 1); assert_int_equal(compare_version("1.0.1", NULL), 1); } static void equal_versions(void **state) { assert_int_equal(compare_version("0.4.7", "0.4.7"), 0); assert_int_equal(compare_version("1.0", "1.0"), 0); } static void unequal_versions(void **state) { assert_int_equal(compare_version("0.4.7", "0.4.8"), -1); assert_int_equal(compare_version("0.4.8", "0.4.7"), 1); assert_int_equal(compare_version("0.2.3", "0.3"), -1); assert_int_equal(compare_version("0.3", "0.2.3"), 1); assert_int_equal(compare_version("0.99", "1.0"), -1); assert_int_equal(compare_version("1.0", "0.99"), 1); } static void shorter_versions(void **state) { assert_int_equal(compare_version("1.0", "1.0.1"), -1); assert_int_equal(compare_version("1.0.1", "1.0"), 1); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_params), cmocka_unit_test(equal_versions), cmocka_unit_test(unequal_versions), cmocka_unit_test(shorter_versions), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/crm_meta_name_test.c b/lib/common/tests/utils/crm_meta_name_test.c index 3de34d71a4..5f8f393d2d 100644 --- a/lib/common/tests/utils/crm_meta_name_test.c +++ b/lib/common/tests/utils/crm_meta_name_test.c @@ -1,52 +1,48 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include +#include +#include static void empty_params(void **state) { assert_null(crm_meta_name(NULL)); } static void standard_usage(void **state) { char *s = NULL; s = crm_meta_name(XML_RSC_ATTR_NOTIFY); assert_string_equal(s, "CRM_meta_notify"); free(s); s = crm_meta_name(XML_RSC_ATTR_STICKINESS); assert_string_equal(s, "CRM_meta_resource_stickiness"); free(s); s = crm_meta_name("blah"); assert_string_equal(s, "CRM_meta_blah"); free(s); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_params), cmocka_unit_test(standard_usage), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/crm_meta_value_test.c b/lib/common/tests/utils/crm_meta_value_test.c index 049ada0b27..cc5e7bbb21 100644 --- a/lib/common/tests/utils/crm_meta_value_test.c +++ b/lib/common/tests/utils/crm_meta_value_test.c @@ -1,67 +1,63 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include +#include +#include #include static void empty_params(void **state) { GHashTable *tbl = pcmk__strkey_table(free, free); assert_null(crm_meta_value(NULL, NULL)); assert_null(crm_meta_value(tbl, NULL)); g_hash_table_destroy(tbl); } static void key_not_in_table(void **state) { GHashTable *tbl = pcmk__strkey_table(free, free); assert_null(crm_meta_value(tbl, XML_RSC_ATTR_NOTIFY)); assert_null(crm_meta_value(tbl, XML_RSC_ATTR_STICKINESS)); g_hash_table_destroy(tbl); } static void key_in_table(void **state) { GHashTable *tbl = pcmk__strkey_table(free, free); g_hash_table_insert(tbl, crm_meta_name(XML_RSC_ATTR_NOTIFY), strdup("1")); g_hash_table_insert(tbl, crm_meta_name(XML_RSC_ATTR_STICKINESS), strdup("2")); assert_string_equal(crm_meta_value(tbl, XML_RSC_ATTR_NOTIFY), "1"); assert_string_equal(crm_meta_value(tbl, XML_RSC_ATTR_STICKINESS), "2"); g_hash_table_destroy(tbl); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_params), cmocka_unit_test(key_not_in_table), cmocka_unit_test(key_in_table), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/crm_user_lookup_test.c b/lib/common/tests/utils/crm_user_lookup_test.c index c2e3aaf09d..f40e318e25 100644 --- a/lib/common/tests/utils/crm_user_lookup_test.c +++ b/lib/common/tests/utils/crm_user_lookup_test.c @@ -1,110 +1,108 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include + #include "mock_private.h" #include -#include -#include -#include -#include -#include #include static void calloc_fails(void **state) { uid_t uid; gid_t gid; pcmk__mock_calloc = true; // calloc() will return NULL assert_int_equal(crm_user_lookup("hauser", &uid, &gid), -ENOMEM); pcmk__mock_calloc = false; // Use real calloc() } static void getpwnam_r_fails(void **state) { uid_t uid; gid_t gid; // Set getpwnam_r() return value and result parameter pcmk__mock_getpwnam_r = true; will_return(__wrap_getpwnam_r, EIO); will_return(__wrap_getpwnam_r, NULL); assert_int_equal(crm_user_lookup("hauser", &uid, &gid), -EIO); pcmk__mock_getpwnam_r = false; } static void no_matching_pwent(void **state) { uid_t uid; gid_t gid; // Set getpwnam_r() return value and result parameter pcmk__mock_getpwnam_r = true; will_return(__wrap_getpwnam_r, 0); will_return(__wrap_getpwnam_r, NULL); assert_int_equal(crm_user_lookup("hauser", &uid, &gid), -EINVAL); pcmk__mock_getpwnam_r = false; } static void entry_found(void **state) { uid_t uid; gid_t gid; /* We don't care about any of the other fields of the password entry, so just * leave them blank. */ struct passwd returned_ent = { .pw_uid = 1000, .pw_gid = 1000 }; /* Test getpwnam_r returning a valid passwd entry, but we don't pass uid or gid. */ // Set getpwnam_r() return value and result parameter pcmk__mock_getpwnam_r = true; will_return(__wrap_getpwnam_r, 0); will_return(__wrap_getpwnam_r, &returned_ent); assert_int_equal(crm_user_lookup("hauser", NULL, NULL), 0); /* Test getpwnam_r returning a valid passwd entry, and we do pass uid and gid. */ // Set getpwnam_r() return value and result parameter will_return(__wrap_getpwnam_r, 0); will_return(__wrap_getpwnam_r, &returned_ent); assert_int_equal(crm_user_lookup("hauser", &uid, &gid), 0); assert_int_equal(uid, 1000); assert_int_equal(gid, 1000); pcmk__mock_getpwnam_r = false; } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(calloc_fails), cmocka_unit_test(getpwnam_r_fails), cmocka_unit_test(no_matching_pwent), cmocka_unit_test(entry_found), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/pcmk_daemon_user_test.c b/lib/common/tests/utils/pcmk_daemon_user_test.c index c911166d77..d904a7ffb4 100644 --- a/lib/common/tests/utils/pcmk_daemon_user_test.c +++ b/lib/common/tests/utils/pcmk_daemon_user_test.c @@ -1,79 +1,77 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include + +#include + #include "mock_private.h" #include -#include -#include -#include -#include -#include #include static void no_matching_pwent(void **state) { uid_t uid; gid_t gid; // Set getpwnam_r() return value and result parameter pcmk__mock_getpwnam_r = true; will_return(__wrap_getpwnam_r, ENOENT); will_return(__wrap_getpwnam_r, NULL); assert_int_equal(pcmk_daemon_user(&uid, &gid), -ENOENT); pcmk__mock_getpwnam_r = false; } static void entry_found(void **state) { uid_t uid; gid_t gid; /* We don't care about any of the other fields of the password entry, so just * leave them blank. */ struct passwd returned_ent = { .pw_uid = 1000, .pw_gid = 1000 }; /* Test getpwnam_r returning a valid passwd entry, but we don't pass uid or gid. */ // Set getpwnam_r() return value and result parameter pcmk__mock_getpwnam_r = true; will_return(__wrap_getpwnam_r, 0); will_return(__wrap_getpwnam_r, &returned_ent); assert_int_equal(pcmk_daemon_user(NULL, NULL), 0); /* Test getpwnam_r returning a valid passwd entry, and we do pass uid and gid. */ /* We don't need to call will_return() again because pcmk_daemon_user() * will have cached the uid/gid from the previous call and won't make * another call to getpwnam_r(). */ assert_int_equal(pcmk_daemon_user(&uid, &gid), 0); assert_int_equal(uid, 1000); assert_int_equal(gid, 1000); pcmk__mock_getpwnam_r = false; } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(no_matching_pwent), cmocka_unit_test(entry_found), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/pcmk_hostname_test.c b/lib/common/tests/utils/pcmk_hostname_test.c index c6f156c940..7faadee436 100644 --- a/lib/common/tests/utils/pcmk_hostname_test.c +++ b/lib/common/tests/utils/pcmk_hostname_test.c @@ -1,65 +1,60 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include "mock_private.h" -#include -#include -#include -#include -#include -#include -#include +#include + +#include "mock_private.h" #include static void uname_succeeded_test(void **state) { char *retval; // Set uname() return value and buf parameter node name pcmk__mock_uname = true; will_return(__wrap_uname, 0); will_return(__wrap_uname, "somename"); retval = pcmk_hostname(); assert_non_null(retval); assert_string_equal("somename", retval); free(retval); pcmk__mock_uname = false; } static void uname_failed_test(void **state) { // Set uname() return value and buf parameter node name pcmk__mock_uname = true; will_return(__wrap_uname, -1); will_return(__wrap_uname, NULL); assert_null(pcmk_hostname()); pcmk__mock_uname = false; } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(uname_succeeded_test), cmocka_unit_test(uname_failed_test), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/pcmk_str_is_infinity_test.c b/lib/common/tests/utils/pcmk_str_is_infinity_test.c index 750f36f431..ef91b48924 100644 --- a/lib/common/tests/utils/pcmk_str_is_infinity_test.c +++ b/lib/common/tests/utils/pcmk_str_is_infinity_test.c @@ -1,68 +1,64 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void uppercase_str_passes(void **state) { assert_true(pcmk_str_is_infinity("INFINITY")); assert_true(pcmk_str_is_infinity("+INFINITY")); } static void mixed_case_str_fails(void **state) { assert_false(pcmk_str_is_infinity("infinity")); assert_false(pcmk_str_is_infinity("+infinity")); assert_false(pcmk_str_is_infinity("Infinity")); assert_false(pcmk_str_is_infinity("+Infinity")); } static void added_whitespace_fails(void **state) { assert_false(pcmk_str_is_infinity(" INFINITY")); assert_false(pcmk_str_is_infinity("INFINITY ")); assert_false(pcmk_str_is_infinity(" INFINITY ")); assert_false(pcmk_str_is_infinity("+ INFINITY")); } static void empty_str_fails(void **state) { assert_false(pcmk_str_is_infinity(NULL)); assert_false(pcmk_str_is_infinity("")); } static void minus_infinity_fails(void **state) { assert_false(pcmk_str_is_infinity("-INFINITY")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(uppercase_str_passes), cmocka_unit_test(mixed_case_str_fails), cmocka_unit_test(added_whitespace_fails), cmocka_unit_test(empty_str_fails), cmocka_unit_test(minus_infinity_fails), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c b/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c index f321ad4b04..11c0da2d26 100644 --- a/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c +++ b/lib/common/tests/utils/pcmk_str_is_minus_infinity_test.c @@ -1,65 +1,61 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include static void uppercase_str_passes(void **state) { assert_true(pcmk_str_is_minus_infinity("-INFINITY")); } static void mixed_case_str_fails(void **state) { assert_false(pcmk_str_is_minus_infinity("-infinity")); assert_false(pcmk_str_is_minus_infinity("-Infinity")); } static void added_whitespace_fails(void **state) { assert_false(pcmk_str_is_minus_infinity(" -INFINITY")); assert_false(pcmk_str_is_minus_infinity("-INFINITY ")); assert_false(pcmk_str_is_minus_infinity(" -INFINITY ")); assert_false(pcmk_str_is_minus_infinity("- INFINITY")); } static void empty_str_fails(void **state) { assert_false(pcmk_str_is_minus_infinity(NULL)); assert_false(pcmk_str_is_minus_infinity("")); } static void infinity_fails(void **state) { assert_false(pcmk_str_is_minus_infinity("INFINITY")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(uppercase_str_passes), cmocka_unit_test(mixed_case_str_fails), cmocka_unit_test(added_whitespace_fails), cmocka_unit_test(empty_str_fails), cmocka_unit_test(infinity_fails), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/common/tests/xpath/Makefile.am b/lib/common/tests/xpath/Makefile.am index 0ee2333607..cddd5237b7 100644 --- a/lib/common/tests/xpath/Makefile.am +++ b/lib/common/tests/xpath/Makefile.am @@ -1,21 +1,23 @@ # # Copyright 2021-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. # AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/lib/common -LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la -AM_LDFLAGS = +LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ + -lcmocka +AM_CFLAGS = -DPCMK__UNIT_TESTING +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pcmk__xpath_node_id_test TESTS = $(check_PROGRAMS) diff --git a/lib/common/tests/xpath/pcmk__xpath_node_id_test.c b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c index 718f92db7b..65a905cfb7 100644 --- a/lib/common/tests/xpath/pcmk__xpath_node_id_test.c +++ b/lib/common/tests/xpath/pcmk__xpath_node_id_test.c @@ -1,60 +1,60 @@ /* - * Copyright 2021 the Pacemaker project contributors + * Copyright 2021-2022 the Pacemaker project contributors * * The version control history for this file may have further details. * * This source code is licensed under the GNU Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include static void empty_input(void **state) { assert_null(pcmk__xpath_node_id(NULL, "lrm")); assert_null(pcmk__xpath_node_id("", "lrm")); assert_null(pcmk__xpath_node_id("/blah/blah", NULL)); assert_null(pcmk__xpath_node_id("/blah/blah", "")); assert_null(pcmk__xpath_node_id(NULL, NULL)); } +static void +no_quotes(void **state) { + pcmk__assert_asserts(pcmk__xpath_node_id("/some/xpath/lrm[@id=xyz]", "lrm")); +} + static void not_present(void **state) { assert_null(pcmk__xpath_node_id("/some/xpath/string[@id='xyz']", "lrm")); assert_null(pcmk__xpath_node_id("/some/xpath/containing[@id='lrm']", "lrm")); } static void present(void **state) { char *s = NULL; s = pcmk__xpath_node_id("/some/xpath/containing/lrm[@id='xyz']", "lrm"); assert_int_equal(strcmp(s, "xyz"), 0); free(s); s = pcmk__xpath_node_id("/some/other/lrm[@id='xyz']/xpath", "lrm"); assert_int_equal(strcmp(s, "xyz"), 0); free(s); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_input), + cmocka_unit_test(no_quotes), cmocka_unit_test(not_present), cmocka_unit_test(present), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/native/Makefile.am b/lib/pengine/tests/native/Makefile.am index 3fb8b40f58..29a31ddd9b 100644 --- a/lib/pengine/tests/native/Makefile.am +++ b/lib/pengine/tests/native/Makefile.am @@ -1,23 +1,24 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include \ -I$(top_builddir) -I$(top_srcdir) LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ $(top_builddir)/lib/pengine/libpe_status_test.la \ -lcmocka +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk AM_TESTS_ENVIRONMENT += PCMK_CTS_CLI_DIR=$(top_srcdir)/cts/cli # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = native_find_rsc_test \ pe_base_name_eq_test TESTS = $(check_PROGRAMS) diff --git a/lib/pengine/tests/native/native_find_rsc_test.c b/lib/pengine/tests/native/native_find_rsc_test.c index 264bad28f3..80bea9c696 100644 --- a/lib/pengine/tests/native/native_find_rsc_test.c +++ b/lib/pengine/tests/native/native_find_rsc_test.c @@ -1,689 +1,684 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include - +#include #include #include #include #include /* Needed to access replicas inside a bundle. */ #define PE__VARIANT_BUNDLE 1 #include xmlNode *input = NULL; pe_working_set_t *data_set = NULL; pe_node_t *cluster01, *cluster02, *httpd_bundle_0; pe_resource_t *exim_group, *inactive_group, *promotable_clone, *inactive_clone; pe_resource_t *httpd_bundle, *mysql_clone_group; static int setup(void **state) { char *path = NULL; crm_xml_init(); path = crm_strdup_printf("%s/crm_mon.xml", getenv("PCMK_CTS_CLI_DIR")); input = filename2xml(path); free(path); if (input == NULL) { return 1; } data_set = pe_new_working_set(); if (data_set == NULL) { return 1; } pe__set_working_set_flags(data_set, pe_flag_no_counts|pe_flag_no_compat); data_set->input = input; cluster_status(data_set); /* Get references to the cluster nodes so we don't have to find them repeatedly. */ cluster01 = pe_find_node(data_set->nodes, "cluster01"); cluster02 = pe_find_node(data_set->nodes, "cluster02"); httpd_bundle_0 = pe_find_node(data_set->nodes, "httpd-bundle-0"); /* Get references to several resources we use frequently. */ for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "exim-group") == 0) { exim_group = rsc; } else if (strcmp(rsc->id, "httpd-bundle") == 0) { httpd_bundle = rsc; } else if (strcmp(rsc->id, "inactive-clone") == 0) { inactive_clone = rsc; } else if (strcmp(rsc->id, "inactive-group") == 0) { inactive_group = rsc; } else if (strcmp(rsc->id, "mysql-clone-group") == 0) { mysql_clone_group = rsc; } else if (strcmp(rsc->id, "promotable-clone") == 0) { promotable_clone = rsc; } } return 0; } static int teardown(void **state) { pe_free_working_set(data_set); return 0; } static void bad_args(void **state) { pe_resource_t *rsc = (pe_resource_t *) g_list_first(data_set->resources)->data; char *id = rsc->id; char *name = NULL; assert_non_null(rsc); assert_null(native_find_rsc(NULL, "dummy", NULL, 0)); assert_null(native_find_rsc(rsc, NULL, NULL, 0)); /* No resources exist with these names. */ name = crm_strdup_printf("%sX", rsc->id); assert_null(native_find_rsc(rsc, name, NULL, 0)); free(name); name = crm_strdup_printf("x%s", rsc->id); assert_null(native_find_rsc(rsc, name, NULL, 0)); free(name); name = g_ascii_strup(rsc->id, -1); assert_null(native_find_rsc(rsc, name, NULL, 0)); g_free(name); /* Fails because resource ID is NULL. */ rsc->id = NULL; assert_null(native_find_rsc(rsc, id, NULL, 0)); rsc->id = id; } static void primitive_rsc(void **state) { pe_resource_t *dummy = NULL; /* Find the "dummy" resource, which is the only one with that ID in the set. */ for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "dummy") == 0) { dummy = rsc; break; } } assert_non_null(dummy); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(dummy, native_find_rsc(dummy, "dummy", NULL, 0)); assert_ptr_equal(dummy, native_find_rsc(dummy, "dummy", NULL, pe_find_current)); /* Fails because resource is not a clone (nor cloned). */ assert_null(native_find_rsc(dummy, "dummy", NULL, pe_find_clone)); assert_null(native_find_rsc(dummy, "dummy", cluster02, pe_find_clone)); /* Fails because dummy is not running on cluster01, even with the right flags. */ assert_null(native_find_rsc(dummy, "dummy", cluster01, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(dummy, "dummy", cluster02, 0)); /* Passes because dummy is running on cluster02. */ assert_ptr_equal(dummy, native_find_rsc(dummy, "dummy", cluster02, pe_find_current)); } static void group_rsc(void **state) { assert_non_null(exim_group); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(exim_group, native_find_rsc(exim_group, "exim-group", NULL, 0)); assert_ptr_equal(exim_group, native_find_rsc(exim_group, "exim-group", NULL, pe_find_current)); /* Fails because resource is not a clone (nor cloned). */ assert_null(native_find_rsc(exim_group, "exim-group", NULL, pe_find_clone)); assert_null(native_find_rsc(exim_group, "exim-group", cluster01, pe_find_clone)); /* Fails because none of exim-group's children are running on cluster01, even with the right flags. */ assert_null(native_find_rsc(exim_group, "exim-group", cluster01, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(exim_group, "exim-group", cluster01, 0)); /* Passes because one of exim-group's children is running on cluster02. */ assert_ptr_equal(exim_group, native_find_rsc(exim_group, "exim-group", cluster02, pe_find_current)); } static void inactive_group_rsc(void **state) { assert_non_null(inactive_group); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(inactive_group, native_find_rsc(inactive_group, "inactive-group", NULL, 0)); assert_ptr_equal(inactive_group, native_find_rsc(inactive_group, "inactive-group", NULL, pe_find_current)); assert_ptr_equal(inactive_group, native_find_rsc(inactive_group, "inactive-group", NULL, pe_find_inactive)); /* Fails because resource is not a clone (nor cloned). */ assert_null(native_find_rsc(inactive_group, "inactive-group", NULL, pe_find_clone)); assert_null(native_find_rsc(inactive_group, "inactive-group", cluster01, pe_find_clone)); /* Fails because none of inactive-group's children are running. */ assert_null(native_find_rsc(inactive_group, "inactive-group", cluster01, pe_find_current)); assert_null(native_find_rsc(inactive_group, "inactive-group", cluster02, pe_find_current)); /* Passes because of flags. */ assert_ptr_equal(inactive_group, native_find_rsc(inactive_group, "inactive-group", cluster01, pe_find_inactive)); /* Passes because of flags. */ assert_ptr_equal(inactive_group, native_find_rsc(inactive_group, "inactive-group", cluster02, pe_find_inactive)); } static void group_member_rsc(void **state) { pe_resource_t *public_ip = NULL; /* Find the "Public-IP" resource, a member of "exim-group". */ for (GList *iter = exim_group->children; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "Public-IP") == 0) { public_ip = rsc; break; } } assert_non_null(public_ip); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(public_ip, native_find_rsc(public_ip, "Public-IP", NULL, 0)); assert_ptr_equal(public_ip, native_find_rsc(public_ip, "Public-IP", NULL, pe_find_current)); /* Fails because resource is not a clone (nor cloned). */ assert_null(native_find_rsc(public_ip, "Public-IP", NULL, pe_find_clone)); assert_null(native_find_rsc(public_ip, "Public-IP", cluster02, pe_find_clone)); /* Fails because Public-IP is not running on cluster01, even with the right flags. */ assert_null(native_find_rsc(public_ip, "Public-IP", cluster01, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(public_ip, "Public-IP", cluster02, 0)); /* Passes because Public-IP is running on cluster02. */ assert_ptr_equal(public_ip, native_find_rsc(public_ip, "Public-IP", cluster02, pe_find_current)); } static void inactive_group_member_rsc(void **state) { pe_resource_t *inactive_dummy_1 = NULL; /* Find the "inactive-dummy-1" resource, a member of "inactive-group". */ for (GList *iter = inactive_group->children; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "inactive-dummy-1") == 0) { inactive_dummy_1 = rsc; break; } } assert_non_null(inactive_dummy_1); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(inactive_dummy_1, native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL, 0)); assert_ptr_equal(inactive_dummy_1, native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL, pe_find_current)); /* Fails because resource is not a clone (nor cloned). */ assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", NULL, pe_find_clone)); assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster01, pe_find_clone)); /* Fails because inactive-dummy-1 is not running. */ assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster01, pe_find_current)); assert_null(native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster02, pe_find_current)); /* Passes because of flags. */ assert_ptr_equal(inactive_dummy_1, native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster01, pe_find_inactive)); /* Passes because of flags. */ assert_ptr_equal(inactive_dummy_1, native_find_rsc(inactive_dummy_1, "inactive-dummy-1", cluster02, pe_find_inactive)); } static void clone_rsc(void **state) { assert_non_null(promotable_clone); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", NULL, 0)); assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", NULL, pe_find_current)); assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", NULL, pe_find_clone)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(promotable_clone, "promotable-clone", cluster01, 0)); /* Passes because one of ping-clone's children is running on cluster01. */ assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", cluster01, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(promotable_clone, "promotable-clone", cluster02, 0)); /* Passes because one of ping_clone's children is running on cluster02. */ assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", cluster02, pe_find_current)); /* Passes for previous reasons, plus includes pe_find_clone check. */ assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", cluster01, pe_find_clone|pe_find_current)); assert_ptr_equal(promotable_clone, native_find_rsc(promotable_clone, "promotable-clone", cluster02, pe_find_clone|pe_find_current)); } static void inactive_clone_rsc(void **state) { assert_non_null(inactive_clone); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", NULL, 0)); assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", NULL, pe_find_current)); assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", NULL, pe_find_clone)); assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", NULL, pe_find_inactive)); /* Fails because none of inactive-clone's children are running. */ assert_null(native_find_rsc(inactive_clone, "inactive-clone", cluster01, pe_find_current|pe_find_clone)); assert_null(native_find_rsc(inactive_clone, "inactive-clone", cluster02, pe_find_current|pe_find_clone)); /* Passes because of flags. */ assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", cluster01, pe_find_inactive)); /* Passes because of flags. */ assert_ptr_equal(inactive_clone, native_find_rsc(inactive_clone, "inactive-clone", cluster02, pe_find_inactive)); } static void clone_instance_rsc(void **state) { pe_resource_t *promotable_0 = NULL; pe_resource_t *promotable_1 = NULL; /* Find the "promotable-rsc:0" and "promotable-rsc:1" resources, members of "promotable-clone". */ for (GList *iter = promotable_clone->children; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "promotable-rsc:0") == 0) { promotable_0 = rsc; } else if (strcmp(rsc->id, "promotable-rsc:1") == 0) { promotable_1 = rsc; } } assert_non_null(promotable_0); assert_non_null(promotable_1); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc:0", NULL, 0)); assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc:0", NULL, pe_find_current)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc:1", NULL, 0)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc:1", NULL, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(promotable_0, "promotable-rsc:0", cluster02, 0)); assert_null(native_find_rsc(promotable_1, "promotable-rsc:1", cluster01, 0)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc:0", cluster02, pe_find_current)); assert_null(native_find_rsc(promotable_0, "promotable-rsc:0", cluster01, pe_find_current)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc:1", cluster01, pe_find_current)); assert_null(native_find_rsc(promotable_1, "promotable-rsc:1", cluster02, pe_find_current)); /* Passes because NULL was passed for node and primitive name was given, with correct flags. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc", NULL, pe_find_clone)); /* Passes because pe_find_any matches any instance's base name. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc", NULL, pe_find_any)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc", NULL, pe_find_any)); /* Passes because pe_find_anon matches. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc", NULL, pe_find_anon)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc", NULL, pe_find_anon)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc", cluster02, pe_find_any|pe_find_current)); assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc", cluster02, pe_find_anon|pe_find_current)); assert_null(native_find_rsc(promotable_0, "promotable-rsc", cluster01, pe_find_any|pe_find_current)); assert_null(native_find_rsc(promotable_0, "promotable-rsc", cluster01, pe_find_anon|pe_find_current)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc", cluster01, pe_find_any|pe_find_current)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc", cluster01, pe_find_anon|pe_find_current)); assert_null(native_find_rsc(promotable_1, "promotable-rsc", cluster02, pe_find_any|pe_find_current)); assert_null(native_find_rsc(promotable_1, "promotable-rsc", cluster02, pe_find_anon|pe_find_current)); /* Fails because incorrect flags were given along with primitive name. */ assert_null(native_find_rsc(promotable_0, "promotable-rsc", NULL, pe_find_current)); assert_null(native_find_rsc(promotable_1, "promotable-rsc", NULL, pe_find_current)); /* And then we check failure possibilities again, except passing promotable_clone * instead of promotable_X as the first argument to native_find_rsc. */ /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(promotable_clone, "promotable-rsc:0", cluster02, 0)); assert_null(native_find_rsc(promotable_clone, "promotable-rsc:1", cluster01, 0)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_clone, "promotable-rsc:0", cluster02, pe_find_current)); assert_ptr_equal(promotable_0, native_find_rsc(promotable_clone, "promotable-rsc", cluster02, pe_find_any|pe_find_current)); assert_ptr_equal(promotable_0, native_find_rsc(promotable_clone, "promotable-rsc", cluster02, pe_find_anon|pe_find_current)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_clone, "promotable-rsc:1", cluster01, pe_find_current)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_clone, "promotable-rsc", cluster01, pe_find_any|pe_find_current)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_clone, "promotable-rsc", cluster01, pe_find_anon|pe_find_current)); } static void renamed_rsc(void **state) { pe_resource_t *promotable_0 = NULL; pe_resource_t *promotable_1 = NULL; /* Find the "promotable-rsc:0" and "promotable-rsc:1" resources, members of "promotable-clone". */ for (GList *iter = promotable_clone->children; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "promotable-rsc:0") == 0) { promotable_0 = rsc; } else if (strcmp(rsc->id, "promotable-rsc:1") == 0) { promotable_1 = rsc; } } assert_non_null(promotable_0); assert_non_null(promotable_1); /* Passes because pe_find_renamed means the base name matches clone_name. */ assert_ptr_equal(promotable_0, native_find_rsc(promotable_0, "promotable-rsc", NULL, pe_find_renamed)); assert_ptr_equal(promotable_1, native_find_rsc(promotable_1, "promotable-rsc", NULL, pe_find_renamed)); } static void bundle_rsc(void **state) { assert_non_null(httpd_bundle); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(httpd_bundle, native_find_rsc(httpd_bundle, "httpd-bundle", NULL, 0)); assert_ptr_equal(httpd_bundle, native_find_rsc(httpd_bundle, "httpd-bundle", NULL, pe_find_current)); /* Fails because resource is not a clone (nor cloned). */ assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", NULL, pe_find_clone)); assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", cluster01, pe_find_clone)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(httpd_bundle, "httpd-bundle", cluster01, 0)); /* Passes because one of httpd_bundle's children is running on cluster01. */ assert_ptr_equal(httpd_bundle, native_find_rsc(httpd_bundle, "httpd-bundle", cluster01, pe_find_current)); } static void bundle_replica_rsc(void **state) { pe__bundle_variant_data_t *bundle_data = NULL; pe__bundle_replica_t *replica_0 = NULL; pe_resource_t *ip_0 = NULL; pe_resource_t *child_0 = NULL; pe_resource_t *container_0 = NULL; pe_resource_t *remote_0 = NULL; get_bundle_variant_data(bundle_data, httpd_bundle); replica_0 = (pe__bundle_replica_t *) bundle_data->replicas->data; ip_0 = replica_0->ip; child_0 = replica_0->child; container_0 = replica_0->container; remote_0 = replica_0->remote; assert_non_null(ip_0); assert_non_null(child_0); assert_non_null(container_0); assert_non_null(remote_0); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(ip_0, native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", NULL, 0)); assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd:0", NULL, 0)); assert_ptr_equal(container_0, native_find_rsc(container_0, "httpd-bundle-docker-0", NULL, 0)); assert_ptr_equal(remote_0, native_find_rsc(remote_0, "httpd-bundle-0", NULL, 0)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", cluster01, 0)); assert_null(native_find_rsc(child_0, "httpd:0", httpd_bundle_0, 0)); assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0", cluster01, 0)); assert_null(native_find_rsc(remote_0, "httpd-bundle-0", cluster01, 0)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(ip_0, native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", cluster01, pe_find_current)); assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", cluster02, pe_find_current)); assert_null(native_find_rsc(ip_0, "httpd-bundle-ip-192.168.122.131", httpd_bundle_0, pe_find_current)); assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd:0", httpd_bundle_0, pe_find_current)); assert_null(native_find_rsc(child_0, "httpd:0", cluster01, pe_find_current)); assert_null(native_find_rsc(child_0, "httpd:0", cluster02, pe_find_current)); assert_ptr_equal(container_0, native_find_rsc(container_0, "httpd-bundle-docker-0", cluster01, pe_find_current)); assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0", cluster02, pe_find_current)); assert_null(native_find_rsc(container_0, "httpd-bundle-docker-0", httpd_bundle_0, pe_find_current)); assert_ptr_equal(remote_0, native_find_rsc(remote_0, "httpd-bundle-0", cluster01, pe_find_current)); assert_null(native_find_rsc(remote_0, "httpd-bundle-0", cluster02, pe_find_current)); assert_null(native_find_rsc(remote_0, "httpd-bundle-0", httpd_bundle_0, pe_find_current)); /* Passes because pe_find_any matches any replica's base name. */ assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd", NULL, pe_find_any)); /* Passes because pe_find_anon matches. */ assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd", NULL, pe_find_anon)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd", httpd_bundle_0, pe_find_any|pe_find_current)); assert_ptr_equal(child_0, native_find_rsc(child_0, "httpd", httpd_bundle_0, pe_find_anon|pe_find_current)); assert_null(native_find_rsc(child_0, "httpd", cluster01, pe_find_any|pe_find_current)); assert_null(native_find_rsc(child_0, "httpd", cluster01, pe_find_anon|pe_find_current)); assert_null(native_find_rsc(child_0, "httpd", cluster02, pe_find_any|pe_find_current)); assert_null(native_find_rsc(child_0, "httpd", cluster02, pe_find_anon|pe_find_current)); /* Fails because incorrect flags were given along with base name. */ assert_null(native_find_rsc(child_0, "httpd", NULL, pe_find_current)); /* And then we check failure possibilities again, except passing httpd-bundle * instead of X_0 as the first argument to native_find_rsc. */ /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-ip-192.168.122.131", cluster01, 0)); assert_null(native_find_rsc(httpd_bundle, "httpd:0", httpd_bundle_0, 0)); assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-docker-0", cluster01, 0)); assert_null(native_find_rsc(httpd_bundle, "httpd-bundle-0", cluster01, 0)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(ip_0, native_find_rsc(httpd_bundle, "httpd-bundle-ip-192.168.122.131", cluster01, pe_find_current)); assert_ptr_equal(child_0, native_find_rsc(httpd_bundle, "httpd:0", httpd_bundle_0, pe_find_current)); assert_ptr_equal(container_0, native_find_rsc(httpd_bundle, "httpd-bundle-docker-0", cluster01, pe_find_current)); assert_ptr_equal(remote_0, native_find_rsc(httpd_bundle, "httpd-bundle-0", cluster01, pe_find_current)); } static void clone_group_rsc(void **rsc) { assert_non_null(mysql_clone_group); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", NULL, 0)); assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", NULL, pe_find_current)); assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", NULL, pe_find_clone)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster01, 0)); /* Passes because one of mysql-clone-group's children is running on cluster01. */ assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster01, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster02, 0)); /* Passes because one of mysql-clone-group's children is running on cluster02. */ assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster02, pe_find_current)); /* Passes for previous reasons, plus includes pe_find_clone check. */ assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster01, pe_find_clone|pe_find_current)); assert_ptr_equal(mysql_clone_group, native_find_rsc(mysql_clone_group, "mysql-clone-group", cluster02, pe_find_clone|pe_find_current)); } static void clone_group_instance_rsc(void **rsc) { pe_resource_t *mysql_group_0 = NULL; pe_resource_t *mysql_group_1 = NULL; /* Find the "mysql-group:0" and "mysql-group:1" resources, members of "mysql-clone-group". */ for (GList *iter = mysql_clone_group->children; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "mysql-group:0") == 0) { mysql_group_0 = rsc; } else if (strcmp(rsc->id, "mysql-group:1") == 0) { mysql_group_1 = rsc; } } assert_non_null(mysql_group_0); assert_non_null(mysql_group_1); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group:0", NULL, 0)); assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group:0", NULL, pe_find_current)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group:1", NULL, 0)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group:1", NULL, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(mysql_group_0, "mysql-group:0", cluster02, 0)); assert_null(native_find_rsc(mysql_group_1, "mysql-group:1", cluster01, 0)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group:0", cluster02, pe_find_current)); assert_null(native_find_rsc(mysql_group_0, "mysql-group:0", cluster01, pe_find_current)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group:1", cluster01, pe_find_current)); assert_null(native_find_rsc(mysql_group_1, "mysql-group:1", cluster02, pe_find_current)); /* Passes because NULL was passed for node and base name was given, with correct flags. */ assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group" , NULL, pe_find_clone)); /* Passes because pe_find_any matches any base name. */ assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group" , NULL, pe_find_any)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group" , NULL, pe_find_any)); /* Passes because pe_find_anon matches. */ assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group" , NULL, pe_find_anon)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group" , NULL, pe_find_anon)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group", cluster02, pe_find_any|pe_find_current)); assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_group_0, "mysql-group", cluster02, pe_find_anon|pe_find_current)); assert_null(native_find_rsc(mysql_group_0, "mysql-group", cluster01, pe_find_any|pe_find_current)); assert_null(native_find_rsc(mysql_group_0, "mysql-group", cluster01, pe_find_anon|pe_find_current)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group", cluster01, pe_find_any|pe_find_current)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_group_1, "mysql-group", cluster01, pe_find_anon|pe_find_current)); assert_null(native_find_rsc(mysql_group_1, "mysql-group", cluster02, pe_find_any|pe_find_current)); assert_null(native_find_rsc(mysql_group_1, "mysql-group", cluster02, pe_find_anon|pe_find_current)); /* Fails because incorrect flags were given along with base name. */ assert_null(native_find_rsc(mysql_group_0, "mysql-group", NULL, pe_find_current)); assert_null(native_find_rsc(mysql_group_1, "mysql-group", NULL, pe_find_current)); /* And then we check failure possibilities again, except passing mysql_clone_group * instead of mysql_group_X as the first argument to native_find_rsc. */ /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(mysql_clone_group, "mysql-group:0", cluster02, 0)); assert_null(native_find_rsc(mysql_clone_group, "mysql-group:1", cluster01, 0)); /* Check that the resource is running on the node we expect. */ assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_clone_group, "mysql-group:0", cluster02, pe_find_current)); assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_clone_group, "mysql-group", cluster02, pe_find_any|pe_find_current)); assert_ptr_equal(mysql_group_0, native_find_rsc(mysql_clone_group, "mysql-group", cluster02, pe_find_anon|pe_find_current)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_clone_group, "mysql-group:1", cluster01, pe_find_current)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_clone_group, "mysql-group", cluster01, pe_find_any|pe_find_current)); assert_ptr_equal(mysql_group_1, native_find_rsc(mysql_clone_group, "mysql-group", cluster01, pe_find_anon|pe_find_current)); } static void clone_group_member_rsc(void **state) { pe_resource_t *mysql_proxy = NULL; /* Find the "mysql-proxy" resource, a member of "mysql-group". */ for (GList *iter = mysql_clone_group->children; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "mysql-group:0") == 0) { for (GList *iter2 = rsc->children; iter2 != NULL; iter2 = iter2->next) { pe_resource_t *child = (pe_resource_t *) iter2->data; if (strcmp(child->id, "mysql-proxy:0") == 0) { mysql_proxy = child; break; } } break; } } assert_non_null(mysql_proxy); /* Passes because NULL was passed for node, regardless of flags. */ assert_ptr_equal(mysql_proxy, native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL, 0)); assert_ptr_equal(mysql_proxy, native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL, pe_find_current)); /* Passes because resource's parent is a clone. */ assert_ptr_equal(mysql_proxy, native_find_rsc(mysql_proxy, "mysql-proxy:0", NULL, pe_find_clone)); assert_ptr_equal(mysql_proxy, native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02, pe_find_clone|pe_find_current)); /* Fails because mysql-proxy:0 is not running on cluster01, even with the right flags. */ assert_null(native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster01, pe_find_current)); /* Fails because pe_find_current is required if a node is given. */ assert_null(native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02, 0)); /* Passes because mysql-proxy:0 is running on cluster02. */ assert_ptr_equal(mysql_proxy, native_find_rsc(mysql_proxy, "mysql-proxy:0", cluster02, pe_find_current)); } int main(int argc, char **argv) { /* TODO: Add tests for finding on allocated node (passing a node without * pe_find_current, after scheduling, for a resource that is starting/stopping/moving. */ const struct CMUnitTest tests[] = { cmocka_unit_test(bad_args), cmocka_unit_test(primitive_rsc), cmocka_unit_test(group_rsc), cmocka_unit_test(inactive_group_rsc), cmocka_unit_test(group_member_rsc), cmocka_unit_test(inactive_group_member_rsc), cmocka_unit_test(clone_rsc), cmocka_unit_test(inactive_clone_rsc), cmocka_unit_test(clone_instance_rsc), cmocka_unit_test(renamed_rsc), cmocka_unit_test(bundle_rsc), cmocka_unit_test(bundle_replica_rsc), cmocka_unit_test(clone_group_rsc), cmocka_unit_test(clone_group_instance_rsc), cmocka_unit_test(clone_group_member_rsc), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, setup, teardown); } diff --git a/lib/pengine/tests/native/pe_base_name_eq_test.c b/lib/pengine/tests/native/pe_base_name_eq_test.c index 86d12e719f..0e0749ec4a 100644 --- a/lib/pengine/tests/native/pe_base_name_eq_test.c +++ b/lib/pengine/tests/native/pe_base_name_eq_test.c @@ -1,159 +1,155 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include +#include #include #include #include #include xmlNode *input = NULL; pe_working_set_t *data_set = NULL; pe_resource_t *exim_group, *promotable_0, *promotable_1, *dummy; pe_resource_t *httpd_bundle, *mysql_group_0, *mysql_group_1; static int setup(void **state) { char *path = NULL; crm_xml_init(); path = crm_strdup_printf("%s/crm_mon.xml", getenv("PCMK_CTS_CLI_DIR")); input = filename2xml(path); free(path); if (input == NULL) { return 1; } data_set = pe_new_working_set(); if (data_set == NULL) { return 1; } pe__set_working_set_flags(data_set, pe_flag_no_counts|pe_flag_no_compat); data_set->input = input; cluster_status(data_set); /* Get references to several resources we use frequently. */ for (GList *iter = data_set->resources; iter != NULL; iter = iter->next) { pe_resource_t *rsc = (pe_resource_t *) iter->data; if (strcmp(rsc->id, "dummy") == 0) { dummy = rsc; } else if (strcmp(rsc->id, "exim-group") == 0) { exim_group = rsc; } else if (strcmp(rsc->id, "httpd-bundle") == 0) { httpd_bundle = rsc; } else if (strcmp(rsc->id, "mysql-clone-group") == 0) { for (GList *iter = rsc->children; iter != NULL; iter = iter->next) { pe_resource_t *child = (pe_resource_t *) iter->data; if (strcmp(child->id, "mysql-group:0") == 0) { mysql_group_0 = child; } else if (strcmp(child->id, "mysql-group:1") == 0) { mysql_group_1 = child; } } } else if (strcmp(rsc->id, "promotable-clone") == 0) { for (GList *iter = rsc->children; iter != NULL; iter = iter->next) { pe_resource_t *child = (pe_resource_t *) iter->data; if (strcmp(child->id, "promotable-rsc:0") == 0) { promotable_0 = child; } else if (strcmp(child->id, "promotable-rsc:1") == 0) { promotable_1 = child; } } } } return 0; } static int teardown(void **state) { pe_free_working_set(data_set); return 0; } static void bad_args(void **state) { char *id = dummy->id; assert_false(pe_base_name_eq(NULL, "dummy")); assert_false(pe_base_name_eq(dummy, NULL)); dummy->id = NULL; assert_false(pe_base_name_eq(dummy, "dummy")); dummy->id = id; } static void primitive_rsc(void **state) { assert_true(pe_base_name_eq(dummy, "dummy")); assert_false(pe_base_name_eq(dummy, "DUMMY")); assert_false(pe_base_name_eq(dummy, "dUmMy")); assert_false(pe_base_name_eq(dummy, "dummy0")); assert_false(pe_base_name_eq(dummy, "dummy:0")); } static void group_rsc(void **state) { assert_true(pe_base_name_eq(exim_group, "exim-group")); assert_false(pe_base_name_eq(exim_group, "EXIM-GROUP")); assert_false(pe_base_name_eq(exim_group, "exim-group0")); assert_false(pe_base_name_eq(exim_group, "exim-group:0")); assert_false(pe_base_name_eq(exim_group, "Public-IP")); } static void clone_rsc(void **state) { assert_true(pe_base_name_eq(promotable_0, "promotable-rsc")); assert_true(pe_base_name_eq(promotable_1, "promotable-rsc")); assert_false(pe_base_name_eq(promotable_0, "promotable-rsc:0")); assert_false(pe_base_name_eq(promotable_1, "promotable-rsc:1")); assert_false(pe_base_name_eq(promotable_0, "PROMOTABLE-RSC")); assert_false(pe_base_name_eq(promotable_1, "PROMOTABLE-RSC")); assert_false(pe_base_name_eq(promotable_0, "Promotable-rsc")); assert_false(pe_base_name_eq(promotable_1, "Promotable-rsc")); } static void bundle_rsc(void **state) { assert_true(pe_base_name_eq(httpd_bundle, "httpd-bundle")); assert_false(pe_base_name_eq(httpd_bundle, "HTTPD-BUNDLE")); assert_false(pe_base_name_eq(httpd_bundle, "httpd")); assert_false(pe_base_name_eq(httpd_bundle, "httpd-docker-0")); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(bad_args), cmocka_unit_test(primitive_rsc), cmocka_unit_test(group_rsc), cmocka_unit_test(clone_rsc), cmocka_unit_test(bundle_rsc), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, setup, teardown); } diff --git a/lib/pengine/tests/rules/Makefile.am b/lib/pengine/tests/rules/Makefile.am index 26ce1e4b2a..e4c33d921f 100644 --- a/lib/pengine/tests/rules/Makefile.am +++ b/lib/pengine/tests/rules/Makefile.am @@ -1,19 +1,20 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ $(top_builddir)/lib/pengine/libpe_rules_test.la \ -lcmocka +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pe_cron_range_satisfied_test TESTS = $(check_PROGRAMS) diff --git a/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c b/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c index 4494d09639..0cdcb425cf 100644 --- a/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c +++ b/lib/pengine/tests/rules/pe_cron_range_satisfied_test.c @@ -1,141 +1,138 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ +#include + #include +#include #include #include -#include -#include -#include -#include -#include - static void run_one_test(const char *t, const char *x, int expected) { crm_time_t *tm = crm_time_new(t); xmlNodePtr xml = string2xml(x); assert_int_equal(pe_cron_range_satisfied(tm, xml), expected); crm_time_free(tm); free_xml(xml); } static void no_time_given(void **state) { assert_int_equal(pe_cron_range_satisfied(NULL, NULL), pcmk_rc_op_unsatisfied); } static void any_time_satisfies_empty_spec(void **state) { crm_time_t *tm = crm_time_new(NULL); assert_int_equal(pe_cron_range_satisfied(tm, NULL), pcmk_rc_ok); crm_time_free(tm); } static void time_satisfies_year_spec(void **state) { run_one_test("2020-01-01", "", pcmk_rc_ok); } static void time_after_year_spec(void **state) { run_one_test("2020-01-01", "", pcmk_rc_after_range); } static void time_satisfies_year_range(void **state) { run_one_test("2020-01-01", "", pcmk_rc_ok); } static void time_before_year_range(void **state) { run_one_test("2000-01-01", "", pcmk_rc_before_range); } static void time_after_year_range(void **state) { run_one_test("2020-01-01", "", pcmk_rc_after_range); } static void range_without_start_year_passes(void **state) { run_one_test("2010-01-01", "", pcmk_rc_ok); } static void range_without_end_year_passes(void **state) { run_one_test("2010-01-01", "", pcmk_rc_ok); run_one_test("2000-10-01", "", pcmk_rc_ok); } static void yeardays_satisfies(void **state) { run_one_test("2020-01-30", "", pcmk_rc_ok); } static void time_after_yeardays_spec(void **state) { run_one_test("2020-02-15", "", pcmk_rc_after_range); } static void yeardays_feb_29_satisfies(void **state) { run_one_test("2016-02-29", "", pcmk_rc_ok); } static void exact_ymd_satisfies(void **state) { run_one_test("2001-12-31", "", pcmk_rc_ok); } static void range_in_month_satisfies(void **state) { run_one_test("2001-06-10", "", pcmk_rc_ok); } static void exact_ymd_after_range(void **state) { run_one_test("2001-12-31", "", pcmk_rc_after_range); } static void time_after_monthdays_range(void **state) { run_one_test("2001-06-10", "", pcmk_rc_before_range); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(no_time_given), cmocka_unit_test(any_time_satisfies_empty_spec), cmocka_unit_test(time_satisfies_year_spec), cmocka_unit_test(time_after_year_spec), cmocka_unit_test(time_satisfies_year_range), cmocka_unit_test(time_before_year_range), cmocka_unit_test(time_after_year_range), cmocka_unit_test(range_without_start_year_passes), cmocka_unit_test(range_without_end_year_passes), cmocka_unit_test(yeardays_satisfies), cmocka_unit_test(time_after_yeardays_spec), cmocka_unit_test(yeardays_feb_29_satisfies), cmocka_unit_test(exact_ymd_satisfies), cmocka_unit_test(range_in_month_satisfies), cmocka_unit_test(exact_ymd_after_range), cmocka_unit_test(time_after_monthdays_range), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/status/pe_find_node_any_test.c b/lib/pengine/tests/status/pe_find_node_any_test.c index ba5f8f8c7a..2deffcbf64 100644 --- a/lib/pengine/tests/status/pe_find_node_any_test.c +++ b/lib/pengine/tests/status/pe_find_node_any_test.c @@ -1,73 +1,68 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include - +#include #include static void empty_list(void **state) { assert_null(pe_find_node_any(NULL, NULL, NULL)); assert_null(pe_find_node_any(NULL, NULL, "cluster1")); assert_null(pe_find_node_any(NULL, "id1", NULL)); assert_null(pe_find_node_any(NULL, "id1", "cluster1")); } static void non_null_list(void **state) { GList *nodes = NULL; pe_node_t *a = calloc(1, sizeof(pe_node_t)); pe_node_t *b = calloc(1, sizeof(pe_node_t)); a->details = calloc(1, sizeof(struct pe_node_shared_s)); a->details->uname = "cluster1"; a->details->id = "id1"; b->details = calloc(1, sizeof(struct pe_node_shared_s)); b->details->uname = "cluster2"; b->details->id = "id2"; nodes = g_list_append(nodes, a); nodes = g_list_append(nodes, b); assert_ptr_equal(b, pe_find_node_any(nodes, "id2", NULL)); assert_ptr_equal(b, pe_find_node_any(nodes, "ID2", NULL)); assert_ptr_equal(a, pe_find_node_any(nodes, "xyz", "cluster1")); assert_ptr_equal(a, pe_find_node_any(nodes, NULL, "cluster1")); assert_null(pe_find_node_any(nodes, "id10", NULL)); assert_null(pe_find_node_any(nodes, "nodeid1", NULL)); assert_null(pe_find_node_any(nodes, NULL, "cluster10")); assert_null(pe_find_node_any(nodes, NULL, "nodecluster1")); assert_null(pe_find_node_any(nodes, "id3", "cluster3")); assert_null(pe_find_node_any(nodes, NULL, NULL)); free(a->details); free(a); free(b->details); free(b); g_list_free(nodes); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_list), cmocka_unit_test(non_null_list), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/status/pe_find_node_id_test.c b/lib/pengine/tests/status/pe_find_node_id_test.c index 23a18e14bc..253bdc393d 100644 --- a/lib/pengine/tests/status/pe_find_node_id_test.c +++ b/lib/pengine/tests/status/pe_find_node_id_test.c @@ -1,62 +1,57 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include - +#include #include static void empty_list(void **state) { assert_null(pe_find_node_id(NULL, NULL)); assert_null(pe_find_node_id(NULL, "id1")); } static void non_null_list(void **state) { GList *nodes = NULL; pe_node_t *a = calloc(1, sizeof(pe_node_t)); pe_node_t *b = calloc(1, sizeof(pe_node_t)); a->details = calloc(1, sizeof(struct pe_node_shared_s)); a->details->id = "id1"; b->details = calloc(1, sizeof(struct pe_node_shared_s)); b->details->id = "id2"; nodes = g_list_append(nodes, a); nodes = g_list_append(nodes, b); assert_ptr_equal(a, pe_find_node_id(nodes, "id1")); assert_null(pe_find_node_id(nodes, "id10")); assert_null(pe_find_node_id(nodes, "nodeid1")); assert_ptr_equal(b, pe_find_node_id(nodes, "ID2")); assert_null(pe_find_node_id(nodes, "xyz")); free(a->details); free(a); free(b->details); free(b); g_list_free(nodes); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_list), cmocka_unit_test(non_null_list), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/status/pe_find_node_test.c b/lib/pengine/tests/status/pe_find_node_test.c index 672380581e..acfa506623 100644 --- a/lib/pengine/tests/status/pe_find_node_test.c +++ b/lib/pengine/tests/status/pe_find_node_test.c @@ -1,62 +1,57 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include - +#include #include static void empty_list(void **state) { assert_null(pe_find_node(NULL, NULL)); assert_null(pe_find_node(NULL, "cluster1")); } static void non_null_list(void **state) { GList *nodes = NULL; pe_node_t *a = calloc(1, sizeof(pe_node_t)); pe_node_t *b = calloc(1, sizeof(pe_node_t)); a->details = calloc(1, sizeof(struct pe_node_shared_s)); a->details->uname = "cluster1"; b->details = calloc(1, sizeof(struct pe_node_shared_s)); b->details->uname = "cluster2"; nodes = g_list_append(nodes, a); nodes = g_list_append(nodes, b); assert_ptr_equal(a, pe_find_node(nodes, "cluster1")); assert_null(pe_find_node(nodes, "cluster10")); assert_null(pe_find_node(nodes, "nodecluster1")); assert_ptr_equal(b, pe_find_node(nodes, "CLUSTER2")); assert_null(pe_find_node(nodes, "xyz")); free(a->details); free(a); free(b->details); free(b); g_list_free(nodes); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(empty_list), cmocka_unit_test(non_null_list), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/status/pe_new_working_set_test.c b/lib/pengine/tests/status/pe_new_working_set_test.c index c2065b740b..888d5d9ed0 100644 --- a/lib/pengine/tests/status/pe_new_working_set_test.c +++ b/lib/pengine/tests/status/pe_new_working_set_test.c @@ -1,54 +1,50 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include "mock_private.h" - -#include -#include -#include -#include -#include +#include #include +#include "mock_private.h" + static void calloc_fails(void **state) { pcmk__mock_calloc = true; // calloc() will return NULL assert_null(pe_new_working_set()); pcmk__mock_calloc = false; // Use real calloc() } static void calloc_succeeds(void **state) { pe_working_set_t *data_set = pe_new_working_set(); /* Nothing else to test about this function, as all it does is call * set_working_set_defaults which is also a public function and should * get its own unit test. */ assert_non_null(data_set); /* Avoid calling pe_free_working_set here so we don't artificially * inflate the coverage numbers. */ free(data_set); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(calloc_fails), cmocka_unit_test(calloc_succeeds), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/status/set_working_set_defaults_test.c b/lib/pengine/tests/status/set_working_set_defaults_test.c index 38c9574a81..2371e6723a 100644 --- a/lib/pengine/tests/status/set_working_set_defaults_test.c +++ b/lib/pengine/tests/status/set_working_set_defaults_test.c @@ -1,56 +1,52 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include "mock_private.h" - -#include -#include -#include -#include -#include +#include #include #include #include +#include "mock_private.h" + static void check_defaults(void **state) { uint32_t flags; pe_working_set_t *data_set = calloc(1, sizeof(pe_working_set_t)); set_working_set_defaults(data_set); flags = pe_flag_stop_rsc_orphans|pe_flag_symmetric_cluster|pe_flag_stop_action_orphans; if (!strcmp(PCMK__CONCURRENT_FENCING_DEFAULT, "true")) { flags |= pe_flag_concurrent_fencing; } assert_null(data_set->priv); assert_int_equal(data_set->order_id, 1); assert_int_equal(data_set->action_id, 1); assert_int_equal(data_set->no_quorum_policy, no_quorum_stop); assert_int_equal(data_set->flags, flags); /* Avoid calling pe_free_working_set here so we don't artificially * inflate the coverage numbers. */ free(data_set); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(check_defaults), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/lib/pengine/tests/unpack/Makefile.am b/lib/pengine/tests/unpack/Makefile.am index af3be904c1..8699d7565e 100644 --- a/lib/pengine/tests/unpack/Makefile.am +++ b/lib/pengine/tests/unpack/Makefile.am @@ -1,19 +1,20 @@ # # 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. # AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include LDADD = $(top_builddir)/lib/common/libcrmcommon_test.la \ $(top_builddir)/lib/pengine/libpe_status_test.la \ -lcmocka +AM_LDFLAGS = $(LDFLAGS_WRAP) include $(top_srcdir)/mk/tap.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = pe_base_name_end_test TESTS = $(check_PROGRAMS) diff --git a/lib/pengine/tests/unpack/pe_base_name_end_test.c b/lib/pengine/tests/unpack/pe_base_name_end_test.c index fe37b4a938..4cf7f9d270 100644 --- a/lib/pengine/tests/unpack/pe_base_name_end_test.c +++ b/lib/pengine/tests/unpack/pe_base_name_end_test.c @@ -1,47 +1,42 @@ /* * 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 Lesser General Public License * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. */ #include -#include -#include -#include -#include -#include - +#include #include static void bad_args(void **state) { assert_null(pe_base_name_end(NULL)); assert_null(pe_base_name_end("")); } static void no_suffix(void **state) { assert_string_equal(pe_base_name_end("rsc"), "c"); assert_string_equal(pe_base_name_end("rsc0"), "0"); } static void has_suffix(void **state) { assert_string_equal(pe_base_name_end("rsc:0"), "c:0"); assert_string_equal(pe_base_name_end("rsc:100"), "c:100"); } int main(int argc, char **argv) { const struct CMUnitTest tests[] = { cmocka_unit_test(bad_args), cmocka_unit_test(no_suffix), cmocka_unit_test(has_suffix), }; cmocka_set_message_output(CM_OUTPUT_TAP); return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/mk/tap.mk b/mk/tap.mk index a4ec5409d4..ae53a8f727 100644 --- a/mk/tap.mk +++ b/mk/tap.mk @@ -1,26 +1,27 @@ # # Copyright 2021-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. # AM_TESTS_ENVIRONMENT= \ G_DEBUG=gc-friendly \ MALLOC_CHECK_=2 \ MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tests/tap-driver.sh LOG_COMPILER = $(top_srcdir)/tests/tap-test CLEANFILES = *.log *.trs WRAPPED = calloc \ endgrent \ getenv \ getgrent \ getpwnam_r \ readlink \ setgrent \ + strdup \ uname LDFLAGS_WRAP = $(foreach fn,$(WRAPPED),-Wl,--wrap=$(fn))