root/lib/common/tests/rules/pcmk_evaluate_rule_test.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. null_invalid
  2. id_missing
  3. good_idref
  4. bad_idref
  5. empty_default
  6. empty_and
  7. empty_or
  8. default_boolean_op
  9. invalid_boolean_op
  10. and_passes
  11. lonely_and_passes
  12. and_one_fails
  13. and_two_fail
  14. or_one_passes
  15. or_two_pass
  16. lonely_or_passes
  17. or_fails

   1 /*
   2  * Copyright 2024 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <stdio.h>
  13 #include <glib.h>
  14 
  15 #include <crm/common/xml.h>
  16 #include <crm/common/rules_internal.h>
  17 #include <crm/common/unittest_internal.h>
  18 
  19 /*
  20  * Shared data
  21  */
  22 
  23 static pcmk_rule_input_t rule_input = {
  24     .rsc_standard = PCMK_RESOURCE_CLASS_OCF,
  25     .rsc_provider = "heartbeat",
  26     .rsc_agent = "IPaddr2",
  27     .op_name = PCMK_ACTION_MONITOR,
  28     .op_interval_ms = 10000,
  29 };
  30 
  31 
  32 /*
  33  * Test invalid arguments
  34  */
  35 
  36 #define RULE_OP                                         \
  37     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' > "           \
  38     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e' "  \
  39           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "    \
  40           PCMK_XA_INTERVAL "='10s' />"                  \
  41     "</" PCMK_XE_RULE ">"
  42 
  43 static void
  44 null_invalid(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46     xmlNode *xml = NULL;
  47     crm_time_t *next_change = crm_time_new_undefined();
  48 
  49     assert_int_equal(pcmk_evaluate_rule(NULL, NULL, next_change),
  50                      EINVAL);
  51 
  52     xml = pcmk__xml_parse(RULE_OP);
  53     assert_int_equal(pcmk_evaluate_rule(xml, NULL, next_change), EINVAL);
  54     pcmk__xml_free(xml);
  55 
  56     assert_int_equal(pcmk_evaluate_rule(NULL, &rule_input, next_change),
  57                      EINVAL);
  58 
  59     crm_time_free(next_change);
  60 }
  61 
  62 #define RULE_OP_MISSING_ID                              \
  63     "<" PCMK_XE_RULE "> "                               \
  64     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e' "  \
  65           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "    \
  66           PCMK_XA_INTERVAL "='10s' />"                  \
  67     "</" PCMK_XE_RULE ">"
  68 
  69 static void
  70 id_missing(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72     xmlNode *xml = pcmk__xml_parse(RULE_OP_MISSING_ID);
  73     crm_time_t *next_change = crm_time_new_undefined();
  74 
  75     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, next_change),
  76                      pcmk_rc_unpack_error);
  77 
  78     crm_time_free(next_change);
  79     pcmk__xml_free(xml);
  80 }
  81 
  82 #define RULE_IDREF_PARENT "<" PCMK_XE_CIB ">" RULE_OP "</" PCMK_XE_CIB ">"
  83 
  84 static void
  85 good_idref(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87     xmlNode *parent_xml = pcmk__xml_parse(RULE_IDREF_PARENT);
  88     xmlNode *rule_xml = pcmk__xe_create(parent_xml, PCMK_XE_RULE);
  89     crm_time_t *next_change = crm_time_new_undefined();
  90 
  91     crm_xml_add(rule_xml, PCMK_XA_ID_REF, "r");
  92     assert_int_equal(pcmk_evaluate_rule(rule_xml, &rule_input, next_change),
  93                      pcmk_rc_ok);
  94 
  95     crm_time_free(next_change);
  96     pcmk__xml_free(parent_xml);
  97 }
  98 
  99 static void
 100 bad_idref(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102     xmlNode *parent_xml = pcmk__xml_parse(RULE_IDREF_PARENT);
 103     xmlNode *rule_xml = pcmk__xe_create(parent_xml, PCMK_XE_RULE);
 104     crm_time_t *next_change = crm_time_new_undefined();
 105 
 106     crm_xml_add(rule_xml, PCMK_XA_ID_REF, "x");
 107     assert_int_equal(pcmk_evaluate_rule(rule_xml, &rule_input, next_change),
 108                      pcmk_rc_unpack_error);
 109 
 110     crm_time_free(next_change);
 111     pcmk__xml_free(parent_xml);
 112 }
 113 
 114 #define RULE_EMPTY "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' />"
 115 
 116 static void
 117 empty_default(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119     // Currently acceptable
 120     xmlNode *xml = pcmk__xml_parse(RULE_EMPTY);
 121 
 122     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 123                      pcmk_rc_ok);
 124 
 125     pcmk__xml_free(xml);
 126 }
 127 
 128 #define RULE_EMPTY_AND                                  \
 129     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "             \
 130         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_AND "' />"
 131 
 132 static void
 133 empty_and(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135     // Currently acceptable
 136     xmlNode *xml = pcmk__xml_parse(RULE_EMPTY_AND);
 137 
 138     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 139                      pcmk_rc_ok);
 140 
 141     pcmk__xml_free(xml);
 142 }
 143 
 144 #define RULE_EMPTY_OR                                   \
 145     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "             \
 146         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_OR "' />"
 147 
 148 static void
 149 empty_or(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151     xmlNode *xml = pcmk__xml_parse(RULE_EMPTY_OR);
 152 
 153     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 154                      pcmk_rc_ok);
 155 
 156     pcmk__xml_free(xml);
 157 }
 158 
 159 #define RULE_DEFAULT_BOOLEAN_OP                             \
 160     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' >"                \
 161     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 162           PCMK_XA_TYPE "='Dummy' />"                        \
 163     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 164           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 165           PCMK_XA_INTERVAL "='10s' />"                      \
 166     "</" PCMK_XE_RULE ">"
 167 
 168 static void
 169 default_boolean_op(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171     // Defaults to PCMK_VALUE_AND
 172     xmlNode *xml = pcmk__xml_parse(RULE_DEFAULT_BOOLEAN_OP);
 173 
 174     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 175                      pcmk_rc_op_unsatisfied);
 176 
 177     pcmk__xml_free(xml);
 178 }
 179 
 180 #define RULE_INVALID_BOOLEAN_OP                             \
 181     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 182         PCMK_XA_BOOLEAN_OP "='not-an-op' >"                 \
 183     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 184           PCMK_XA_TYPE "='Dummy' />"                        \
 185     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 186           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 187           PCMK_XA_INTERVAL "='10s' />"                      \
 188     "</" PCMK_XE_RULE ">"
 189 
 190 static void
 191 invalid_boolean_op(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193     xmlNode *xml = pcmk__xml_parse(RULE_INVALID_BOOLEAN_OP);
 194 
 195     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 196                      pcmk_rc_unpack_error);
 197 
 198     pcmk__xml_free(xml);
 199 }
 200 
 201 #define RULE_AND_PASSES                                     \
 202     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 203         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_AND "' >"        \
 204     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 205           PCMK_XA_TYPE "='IPaddr2' />"                      \
 206     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 207           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 208           PCMK_XA_INTERVAL "='10s' />"                      \
 209     "</" PCMK_XE_RULE ">"
 210 
 211 static void
 212 and_passes(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 213 {
 214     xmlNode *xml = pcmk__xml_parse(RULE_AND_PASSES);
 215 
 216     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL), pcmk_rc_ok);
 217 
 218     pcmk__xml_free(xml);
 219 }
 220 
 221 #define RULE_LONELY_AND                                     \
 222     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 223         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_AND "' >"        \
 224     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 225           PCMK_XA_TYPE "='IPaddr2' />"                      \
 226     "</" PCMK_XE_RULE ">"
 227 
 228 static void
 229 lonely_and_passes(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 230 {
 231     xmlNode *xml = pcmk__xml_parse(RULE_LONELY_AND);
 232 
 233     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL), pcmk_rc_ok);
 234 
 235     pcmk__xml_free(xml);
 236 }
 237 
 238 #define RULE_AND_ONE_FAILS                                  \
 239     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 240         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_AND "' >"        \
 241     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 242           PCMK_XA_TYPE "='Dummy' />"                        \
 243     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 244           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 245           PCMK_XA_INTERVAL "='10s' />"                      \
 246     "</" PCMK_XE_RULE ">"
 247 
 248 static void
 249 and_one_fails(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 250 {
 251     xmlNode *xml = pcmk__xml_parse(RULE_AND_ONE_FAILS);
 252 
 253     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 254                      pcmk_rc_op_unsatisfied);
 255 
 256     pcmk__xml_free(xml);
 257 }
 258 
 259 #define RULE_AND_TWO_FAIL                                   \
 260     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 261         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_AND "' >"        \
 262     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 263           PCMK_XA_TYPE "='Dummy' />"                        \
 264     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 265           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 266           PCMK_XA_INTERVAL "='9s' />"                       \
 267     "</" PCMK_XE_RULE ">"
 268 
 269 static void
 270 and_two_fail(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272     xmlNode *xml = pcmk__xml_parse(RULE_AND_TWO_FAIL);
 273 
 274     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 275                      pcmk_rc_op_unsatisfied);
 276 
 277     pcmk__xml_free(xml);
 278 }
 279 
 280 #define RULE_OR_ONE_PASSES                                  \
 281     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 282         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_OR "' >"         \
 283     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 284           PCMK_XA_TYPE "='Dummy' />"                        \
 285     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 286           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 287           PCMK_XA_INTERVAL "='10s' />"                      \
 288     "</" PCMK_XE_RULE ">"
 289 
 290 static void
 291 or_one_passes(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293     xmlNode *xml = pcmk__xml_parse(RULE_OR_ONE_PASSES);
 294 
 295     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL), pcmk_rc_ok);
 296 
 297     pcmk__xml_free(xml);
 298 }
 299 
 300 #define RULE_OR_TWO_PASS                                    \
 301     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 302         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_OR "' >"         \
 303     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 304           PCMK_XA_TYPE "='IPAddr2' />"                      \
 305     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 306           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 307           PCMK_XA_INTERVAL "='10s' />"                      \
 308     "</" PCMK_XE_RULE ">"
 309 
 310 static void
 311 or_two_pass(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313     xmlNode *xml = pcmk__xml_parse(RULE_OR_TWO_PASS);
 314 
 315     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL), pcmk_rc_ok);
 316 
 317     pcmk__xml_free(xml);
 318 }
 319 
 320 #define RULE_LONELY_OR                                      \
 321     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 322         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_OR "' >"         \
 323     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 324           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 325           PCMK_XA_INTERVAL "='10s' />"                      \
 326     "</" PCMK_XE_RULE ">"
 327 
 328 static void
 329 lonely_or_passes(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 330 {
 331     xmlNode *xml = pcmk__xml_parse(RULE_LONELY_OR);
 332 
 333     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL), pcmk_rc_ok);
 334 
 335     pcmk__xml_free(xml);
 336 }
 337 
 338 #define RULE_OR_FAILS                                       \
 339     "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' "                 \
 340         PCMK_XA_BOOLEAN_OP "='" PCMK_VALUE_OR "' >"         \
 341     "  <" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e1' "    \
 342           PCMK_XA_TYPE "='Dummy' />"                        \
 343     "  <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e2' "     \
 344           PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' "        \
 345           PCMK_XA_INTERVAL "='20s' />"                      \
 346     "</" PCMK_XE_RULE ">"
 347 
 348 static void
 349 or_fails(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351     xmlNode *xml = pcmk__xml_parse(RULE_OR_FAILS);
 352 
 353     assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, NULL),
 354                      pcmk_rc_op_unsatisfied);
 355 
 356     pcmk__xml_free(xml);
 357 }
 358 
 359 PCMK__UNIT_TEST(pcmk__xml_test_setup_group, pcmk__xml_test_teardown_group,
 360                 cmocka_unit_test(null_invalid),
 361                 cmocka_unit_test(id_missing),
 362                 cmocka_unit_test(good_idref),
 363                 cmocka_unit_test(bad_idref),
 364                 cmocka_unit_test(empty_default),
 365                 cmocka_unit_test(empty_and),
 366                 cmocka_unit_test(empty_or),
 367                 cmocka_unit_test(default_boolean_op),
 368                 cmocka_unit_test(invalid_boolean_op),
 369                 cmocka_unit_test(and_passes),
 370                 cmocka_unit_test(lonely_and_passes),
 371                 cmocka_unit_test(and_one_fails),
 372                 cmocka_unit_test(and_two_fail),
 373                 cmocka_unit_test(or_one_passes),
 374                 cmocka_unit_test(or_two_pass),
 375                 cmocka_unit_test(lonely_or_passes),
 376                 cmocka_unit_test(or_fails))

/* [previous][next][first][last][top][bottom][index][help] */