summaryrefslogtreecommitdiffstats
path: root/lib/common/tests/actions
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common/tests/actions')
-rw-r--r--lib/common/tests/actions/Makefile.am22
-rw-r--r--lib/common/tests/actions/copy_in_properties_test.c62
-rw-r--r--lib/common/tests/actions/expand_plus_plus_test.c256
-rw-r--r--lib/common/tests/actions/fix_plus_plus_recursive_test.c47
-rw-r--r--lib/common/tests/actions/parse_op_key_test.c275
-rw-r--r--lib/common/tests/actions/pcmk_is_probe_test.c25
-rw-r--r--lib/common/tests/actions/pcmk_xe_is_probe_test.c43
-rw-r--r--lib/common/tests/actions/pcmk_xe_mask_probe_failure_test.c150
8 files changed, 880 insertions, 0 deletions
diff --git a/lib/common/tests/actions/Makefile.am b/lib/common/tests/actions/Makefile.am
new file mode 100644
index 0000000..6890b84
--- /dev/null
+++ b/lib/common/tests/actions/Makefile.am
@@ -0,0 +1,22 @@
+#
+# Copyright 2020-2023 the Pacemaker project contributors
+#
+# The version control history for this file may have further details.
+#
+# This source code is licensed under the GNU General Public License version 2
+# or later (GPLv2+) WITHOUT ANY WARRANTY.
+#
+
+include $(top_srcdir)/mk/tap.mk
+include $(top_srcdir)/mk/unittest.mk
+
+# Add "_test" to the end of all test program names to simplify .gitignore.
+check_PROGRAMS = 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/actions/copy_in_properties_test.c b/lib/common/tests/actions/copy_in_properties_test.c
new file mode 100644
index 0000000..7882551
--- /dev/null
+++ b/lib/common/tests/actions/copy_in_properties_test.c
@@ -0,0 +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 General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <crm/common/unittest_internal.h>
+
+#include <glib.h>
+
+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);
+}
+
+PCMK__UNIT_TEST(NULL, NULL,
+ cmocka_unit_test(target_is_NULL),
+ cmocka_unit_test(src_is_NULL),
+ cmocka_unit_test(copying_is_successful))
diff --git a/lib/common/tests/actions/expand_plus_plus_test.c b/lib/common/tests/actions/expand_plus_plus_test.c
new file mode 100644
index 0000000..41471f9
--- /dev/null
+++ b/lib/common/tests/actions/expand_plus_plus_test.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2022 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <crm/common/unittest_internal.h>
+
+#include <glib.h>
+
+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");
+}
+
+PCMK__UNIT_TEST(NULL, NULL,
+ 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))
diff --git a/lib/common/tests/actions/fix_plus_plus_recursive_test.c b/lib/common/tests/actions/fix_plus_plus_recursive_test.c
new file mode 100644
index 0000000..b3c7cc2
--- /dev/null
+++ b/lib/common/tests/actions/fix_plus_plus_recursive_test.c
@@ -0,0 +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 General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <crm/common/unittest_internal.h>
+
+#include <glib.h>
+
+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("<!-- a comment -->");
+
+ 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");
+}
+
+PCMK__UNIT_TEST(NULL, NULL,
+ cmocka_unit_test(element_nodes))
diff --git a/lib/common/tests/actions/parse_op_key_test.c b/lib/common/tests/actions/parse_op_key_test.c
new file mode 100644
index 0000000..1b1bfff
--- /dev/null
+++ b/lib/common/tests/actions/parse_op_key_test.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2020-2023 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <crm/common/unittest_internal.h>
+
+#include <glib.h>
+
+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);
+
+ // Single-character resource name
+ assert_true(parse_op_key("R_monitor_100000", &rsc, &ty, &ms));
+ assert_string_equal(rsc, "R");
+ assert_string_equal(ty, "monitor");
+ assert_int_equal(ms, 100000);
+ free(rsc);
+ free(ty);
+
+ // Single-character action name
+ assert_true(parse_op_key("R_A_0", &rsc, &ty, &ms));
+ assert_string_equal(rsc, "R");
+ assert_string_equal(ty, "A");
+ assert_int_equal(ms, 0);
+ free(rsc);
+ free(ty);
+}
+
+static void
+rsc_just_underbars(void **state)
+{
+ char *rsc = NULL;
+ char *ty = NULL;
+ guint ms = 0;
+
+ assert_true(parse_op_key("__monitor_1000", &rsc, &ty, &ms));
+ assert_string_equal(rsc, "_");
+ assert_string_equal(ty, "monitor");
+ assert_int_equal(ms, 1000);
+ free(rsc);
+ free(ty);
+
+ assert_true(parse_op_key("___migrate_from_0", &rsc, &ty, &ms));
+ assert_string_equal(rsc, "__");
+ assert_string_equal(ty, "migrate_from");
+ assert_int_equal(ms, 0);
+ free(rsc);
+ free(ty);
+
+ assert_true(parse_op_key("____pre_notify_stop_0", &rsc, &ty, &ms));
+ assert_string_equal(rsc, "___");
+ assert_string_equal(ty, "pre_notify_stop");
+ assert_int_equal(ms, 0);
+ 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);
+
+ assert_true(parse_op_key("r_confirmed-post_notify_start_0",
+ &rsc, &ty, &ms));
+ assert_string_equal(rsc, "r");
+ assert_string_equal(ty, "confirmed-post_notify_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);
+}
+
+PCMK__UNIT_TEST(NULL, NULL,
+ cmocka_unit_test(basic),
+ cmocka_unit_test(rsc_just_underbars),
+ 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))
diff --git a/lib/common/tests/actions/pcmk_is_probe_test.c b/lib/common/tests/actions/pcmk_is_probe_test.c
new file mode 100644
index 0000000..4a65e3f
--- /dev/null
+++ b/lib/common/tests/actions/pcmk_is_probe_test.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <crm/common/unittest_internal.h>
+
+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));
+}
+
+PCMK__UNIT_TEST(NULL, NULL,
+ cmocka_unit_test(is_probe_test))
diff --git a/lib/common/tests/actions/pcmk_xe_is_probe_test.c b/lib/common/tests/actions/pcmk_xe_is_probe_test.c
new file mode 100644
index 0000000..62b21d9
--- /dev/null
+++ b/lib/common/tests/actions/pcmk_xe_is_probe_test.c
@@ -0,0 +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 General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <crm/common/unittest_internal.h>
+
+static void
+op_is_probe_test(void **state)
+{
+ xmlNode *node = NULL;
+
+ assert_false(pcmk_xe_is_probe(NULL));
+
+ node = string2xml("<lrm_rsc_op/>");
+ assert_false(pcmk_xe_is_probe(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation_key=\"blah\" interval=\"30s\"/>");
+ assert_false(pcmk_xe_is_probe(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"30s\"/>");
+ assert_false(pcmk_xe_is_probe(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"start\" interval=\"0\"/>");
+ assert_false(pcmk_xe_is_probe(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\"/>");
+ assert_true(pcmk_xe_is_probe(node));
+ free_xml(node);
+}
+
+PCMK__UNIT_TEST(NULL, NULL,
+ cmocka_unit_test(op_is_probe_test))
diff --git a/lib/common/tests/actions/pcmk_xe_mask_probe_failure_test.c b/lib/common/tests/actions/pcmk_xe_mask_probe_failure_test.c
new file mode 100644
index 0000000..9e38019
--- /dev/null
+++ b/lib/common/tests/actions/pcmk_xe_mask_probe_failure_test.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2021 the Pacemaker project contributors
+ *
+ * The version control history for this file may have further details.
+ *
+ * This source code is licensed under the GNU General Public License version 2
+ * or later (GPLv2+) WITHOUT ANY WARRANTY.
+ */
+
+#include <crm_internal.h>
+
+#include <crm/common/unittest_internal.h>
+
+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("<lrm_rsc_op operation=\"start\" interval=\"0\"/>");
+ 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("<lrm_rsc_op operation=\"monitor\" interval=\"0\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"0\" op-status=\"\"/>");
+ 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("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"0\" op-status=\"3\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"5\" op-status=\"3\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ /* PCMK_EXEC_DONE */
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"0\" op-status=\"0\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"2\" op-status=\"0\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"5\" op-status=\"0\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"6\" op-status=\"0\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"7\" op-status=\"0\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ /* PCMK_EXEC_NOT_INSTALLED */
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"0\" op-status=\"7\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"5\" op-status=\"7\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ /* PCMK_EXEC_ERROR */
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"0\" op-status=\"4\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"2\" op-status=\"4\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"5\" op-status=\"4\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"6\" op-status=\"4\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"7\" op-status=\"4\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ /* PCMK_EXEC_ERROR_HARD */
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"0\" op-status=\"5\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"2\" op-status=\"5\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"5\" op-status=\"5\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"6\" op-status=\"5\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"7\" op-status=\"5\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ /* PCMK_EXEC_ERROR_FATAL */
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"0\" op-status=\"6\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"2\" op-status=\"6\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"5\" op-status=\"6\"/>");
+ assert_true(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"6\" op-status=\"6\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+
+ node = string2xml("<lrm_rsc_op operation=\"monitor\" interval=\"0\" rc-code=\"7\" op-status=\"6\"/>");
+ assert_false(pcmk_xe_mask_probe_failure(node));
+ free_xml(node);
+}
+
+PCMK__UNIT_TEST(NULL, NULL,
+ cmocka_unit_test(op_is_not_probe_test),
+ cmocka_unit_test(op_does_not_have_right_values_test),
+ cmocka_unit_test(check_values_test))