pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
pcmk__evaluate_condition_test.c
Go to the documentation of this file.
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>
18 
19 /*
20  * Shared data
21  */
22 
23 static pcmk_rule_input_t rule_input = {
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 EXPR_ATTRIBUTE \
37  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
38  PCMK_XA_ATTRIBUTE "='foo' " \
39  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
40  PCMK_XA_VALUE "='bar' />"
41 
42 static void
43 null_invalid(void **state)
44 {
45  xmlNode *xml = NULL;
46  crm_time_t *next_change = crm_time_new_undefined();
47 
48  assert_int_equal(pcmk__evaluate_condition(NULL, NULL, next_change), EINVAL);
49 
51  assert_int_equal(pcmk__evaluate_condition(xml, NULL, next_change), EINVAL);
52  free_xml(xml);
53 
54  assert_int_equal(pcmk__evaluate_condition(NULL, &rule_input, next_change),
55  EINVAL);
56 
57  crm_time_free(next_change);
58 }
59 
60 
61 #define EXPR_INVALID "<not_an_expression " PCMK_XA_ID "='e' />"
62 
63 static void
64 invalid_expression(void **state)
65 {
66  xmlNode *xml = pcmk__xml_parse(EXPR_INVALID);
67  crm_time_t *next_change = crm_time_new_undefined();
68 
69  assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, next_change),
71 
72  crm_time_free(next_change);
73  free_xml(xml);
74 }
75 
76 
77 /* Each expression type function already has unit tests, so we just need to test
78  * that they are called correctly (essentially, one of each one's own tests).
79  */
80 
81 static void
82 attribute_expression(void **state)
83 {
84  xmlNode *xml = pcmk__xml_parse(EXPR_ATTRIBUTE);
85 
86  rule_input.node_attrs = pcmk__strkey_table(free, free);
87  pcmk__insert_dup(rule_input.node_attrs, "foo", "bar");
88 
89  assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, NULL),
90  pcmk_rc_ok);
91 
92  g_hash_table_destroy(rule_input.node_attrs);
93  rule_input.node_attrs = NULL;
94  free_xml(xml);
95 }
96 
97 #define EXPR_LOCATION \
98  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
99  PCMK_XA_ATTRIBUTE "='" CRM_ATTR_UNAME "' " \
100  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
101  PCMK_XA_VALUE "='node1' />"
102 
103 static void
104 location_expression(void **state)
105 {
106  xmlNode *xml = pcmk__xml_parse(EXPR_LOCATION);
107 
108  rule_input.node_attrs = pcmk__strkey_table(free, free);
109  pcmk__insert_dup(rule_input.node_attrs, CRM_ATTR_UNAME, "node1");
110 
111  assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, NULL),
112  pcmk_rc_ok);
113 
114  g_hash_table_destroy(rule_input.node_attrs);
115  rule_input.node_attrs = NULL;
116  free_xml(xml);
117 }
118 
119 #define EXPR_DATE \
120  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
121  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
122  PCMK_XA_START "='2024-02-01 12:00:00' " \
123  PCMK_XA_END "='2024-02-01 15:00:00' />"
124 
125 static void
126 date_expression(void **state)
127 {
128  xmlNode *xml = pcmk__xml_parse(EXPR_DATE);
129  crm_time_t *now = crm_time_new("2024-02-01 11:59:59");
130  crm_time_t *next_change = crm_time_new("2024-02-01 14:00:00");
131  crm_time_t *reference = crm_time_new("2024-02-01 12:00:00");
132 
133  rule_input.now = now;
134  assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, next_change),
136  assert_int_equal(crm_time_compare(next_change, reference), 0);
137  rule_input.now = NULL;
138 
139  crm_time_free(reference);
140  crm_time_free(next_change);
141  crm_time_free(now);
142 }
143 
144 #define EXPR_RESOURCE \
145  "<" PCMK_XE_RSC_EXPRESSION " " PCMK_XA_ID "='e' " \
146  PCMK_XA_CLASS "='" PCMK_RESOURCE_CLASS_OCF "' " \
147  PCMK_XA_TYPE "='IPaddr2' />"
148 
149 static void
150 resource_expression(void **state)
151 {
152  xmlNode *xml = pcmk__xml_parse(EXPR_RESOURCE);
153 
154  assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, NULL),
155  pcmk_rc_ok);
156  free_xml(xml);
157 }
158 
159 #define EXPR_OP \
160  "<" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e' " \
161  PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' " \
162  PCMK_XA_INTERVAL "='10s' />"
163 
164 static void
165 op_expression(void **state)
166 {
167  xmlNode *xml = pcmk__xml_parse(EXPR_OP);
168 
169  assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, NULL),
170  pcmk_rc_ok);
171  free_xml(xml);
172 }
173 
174 #define EXPR_SUBRULE \
175  "<" PCMK_XE_RULE " " PCMK_XA_ID "='r' " \
176  " <" PCMK_XE_OP_EXPRESSION " " PCMK_XA_ID "='e' " \
177  PCMK_XA_NAME "='" PCMK_ACTION_MONITOR "' " \
178  PCMK_XA_INTERVAL "='10s' /> />"
179 
180 static void
181 subrule(void **state)
182 {
183  xmlNode *xml = pcmk__xml_parse(EXPR_SUBRULE);
184  assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, NULL),
185  pcmk_rc_ok);
186  free_xml(xml);
187 }
188 
190  cmocka_unit_test(null_invalid),
191  cmocka_unit_test(invalid_expression),
192  cmocka_unit_test(attribute_expression),
193  cmocka_unit_test(location_expression),
194  cmocka_unit_test(date_expression),
195  cmocka_unit_test(resource_expression),
196  cmocka_unit_test(op_expression),
197  cmocka_unit_test(subrule))
crm_time_t * crm_time_new_undefined(void)
Allocate memory for an uninitialized time object.
Definition: iso8601.c:129
const crm_time_t * now
Current time for rule evaluation purposes.
Definition: rules.h:59
Data used to evaluate a rule (any NULL items are ignored)
Definition: rules.h:57
struct crm_time_s crm_time_t
Definition: iso8601.h:32
#define PCMK_ACTION_MONITOR
Definition: actions.h:60
#define EXPR_SUBRULE
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
#define PCMK_RESOURCE_CLASS_OCF
Definition: agents.h:27
#define EXPR_RESOURCE
#define CRM_ATTR_UNAME
Definition: crm.h:99
#define EXPR_ATTRIBUTE
int pcmk__xml_test_setup_group(void **state)
Definition: unittest.c:85
Wrappers for and extensions to libxml2.
const char * rsc_standard
Resource standard that rule applies to.
Definition: rules.h:62
void free_xml(xmlNode *child)
Definition: xml.c:958
int pcmk__xml_test_teardown_group(void **state)
Definition: unittest.c:104
xmlNode * pcmk__xml_parse(const char *input)
Definition: xml_io.c:245
int crm_time_compare(const crm_time_t *a, const crm_time_t *b)
Definition: iso8601.c:1736
int pcmk__evaluate_condition(xmlNode *expr, const pcmk_rule_input_t *rule_input, crm_time_t *next_change)
Definition: rules.c:1334
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:695
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:112
#define EXPR_LOCATION
GHashTable * node_attrs
Operation interval that rule applies to.
Definition: rules.h:77
#define EXPR_INVALID
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:713
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:150