pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk_unpack_nvpair_blocks_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 <glib.h>
13#include <libxml/tree.h>
14
16
17#include <crm/common/iso8601.h>
18#include <crm/common/xml.h>
19
20/* The test XML is designed so that:
21 * - The blocks are, lowest score to highest, #2 #3 #1 (to test sorting)
22 * - The first block can be used to test rule evaluation by setting "now"
23 * - The first block has a different element name than the other two,
24 * to test specifying an element name
25 * - The middle block can be used to test ID precedence
26*/
27#define XML_BLOCKS \
28 "<xml>\n" \
29 "<" PCMK_XE_META_ATTRIBUTES " " PCMK_XA_ID "='ia1' " \
30 PCMK_XA_SCORE "='100' >" \
31 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp1-1' " \
32 PCMK_XA_NAME "='name1' " PCMK_XA_VALUE "='1' />\n" \
33 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp1-2' " \
34 PCMK_XA_NAME "='name2' " PCMK_XA_VALUE "='1' />\n" \
35 "<" PCMK_XE_RULE " " PCMK_XA_ID "='rp' >\n" \
36 "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='ep' " \
37 PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
38 PCMK_XA_START "='2024-11-05 00:00:00' />\n" \
39 "</" PCMK_XE_RULE ">\n" \
40 "</" PCMK_XE_META_ATTRIBUTES ">\n" \
41 "<" PCMK_XE_INSTANCE_ATTRIBUTES " " PCMK_XA_ID "='ia2' " \
42 PCMK_XA_SCORE "='2' >" \
43 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp2-1' " \
44 PCMK_XA_NAME "='name1' " PCMK_XA_VALUE "='2' />\n" \
45 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp2-2' " \
46 PCMK_XA_NAME "='name2' " PCMK_XA_VALUE "='2' />\n" \
47 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp2-3' " \
48 PCMK_XA_NAME "='name3' " PCMK_XA_VALUE "='2' />\n" \
49 "</" PCMK_XE_INSTANCE_ATTRIBUTES ">\n" \
50 "<" PCMK_XE_INSTANCE_ATTRIBUTES " " PCMK_XA_ID "='ia3' " \
51 PCMK_XA_SCORE "='30' >" \
52 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp3-1' " \
53 PCMK_XA_NAME "='name1' " PCMK_XA_VALUE "='3' />\n" \
54 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp3-2' " \
55 PCMK_XA_NAME "='name2' " PCMK_XA_VALUE "='3' />\n" \
56 "<" PCMK_XE_NVPAIR " " PCMK_XA_ID "='nvp3-3' " \
57 PCMK_XA_NAME "='name3' " PCMK_XA_VALUE "='3' />\n" \
58 "</" PCMK_XE_INSTANCE_ATTRIBUTES ">\n" \
59 "</xml>\n"
60
61
62static void
63null_xml(void **state)
64{
65 GHashTable *values = pcmk__strkey_table(free, free);
66 crm_time_t *now = crm_time_new("2024-01-01 15:00:00");
67 crm_time_t *next_change = crm_time_new("2024-01-01 20:00:00");
68 pcmk_rule_input_t rule_input = {
69 .now = now,
70 };
71
72 // This mainly tests that it doesn't crash
74 &rule_input, values, next_change);
75 assert_int_equal(g_hash_table_size(values), 0);
76 g_hash_table_destroy(values);
77 crm_time_free(now);
78 crm_time_free(next_change);
79}
80
81static void
82null_table(void **state)
83{
84 xmlNode *xml = pcmk__xml_parse(XML_BLOCKS);
85 crm_time_t *now = crm_time_new("2024-01-01 15:00:00");
86 crm_time_t *next_change = crm_time_new("2024-01-01 20:00:00");
87 pcmk_rule_input_t rule_input = {
88 .now = now,
89 };
90
91 assert_non_null(xml);
94 "id1", &rule_input, NULL,
95 next_change));
96 pcmk__xml_free(xml);
97 crm_time_free(next_change);
98 crm_time_free(now);
99}
100
101static void
102rule_passes(void **state)
103{
104 xmlNode *xml = pcmk__xml_parse(XML_BLOCKS);
105 crm_time_t *now = crm_time_new("2024-11-06 15:00:00");
106 crm_time_t *next_change = crm_time_new("2024-11-06 20:00:00");
107 GHashTable *values = pcmk__strkey_table(free, free);
108 pcmk_rule_input_t rule_input = {
109 .now = now,
110 };
111
112 assert_non_null(xml);
113 pcmk_unpack_nvpair_blocks(xml, NULL, "id1", &rule_input, values,
114 next_change);
115 assert_int_equal(g_hash_table_size(values), 3);
116 assert_string_equal(g_hash_table_lookup(values, "name1"), "1");
117 assert_string_equal(g_hash_table_lookup(values, "name2"), "1");
118 assert_string_equal(g_hash_table_lookup(values, "name3"), "3");
119
120 pcmk__xml_free(xml);
121 crm_time_free(next_change);
122 crm_time_free(now);
123 g_hash_table_destroy(values);
124}
125
126static void
127rule_fails(void **state)
128{
129 xmlNode *xml = pcmk__xml_parse(XML_BLOCKS);
130 crm_time_t *now = crm_time_new("2024-11-04 15:00:00");
131 crm_time_t *next_change = crm_time_new("2024-11-05 20:00:00");
132 crm_time_t *expected_next_change = crm_time_new("2024-11-05 00:00:01");
133 GHashTable *values = pcmk__strkey_table(free, free);
134 pcmk_rule_input_t rule_input = {
135 .now = now,
136 };
137
138 // This also tests that next_change is set when appropriate
139
140 assert_non_null(xml);
141 pcmk_unpack_nvpair_blocks(xml, NULL, "id1", &rule_input, values,
142 next_change);
143 assert_int_equal(g_hash_table_size(values), 3);
144 assert_string_equal(g_hash_table_lookup(values, "name1"), "3");
145 assert_string_equal(g_hash_table_lookup(values, "name2"), "3");
146 assert_string_equal(g_hash_table_lookup(values, "name3"), "3");
147 assert_int_equal(crm_time_compare(next_change, expected_next_change), 0);
148
149 pcmk__xml_free(xml);
150 crm_time_free(now);
151 crm_time_free(next_change);
152 crm_time_free(expected_next_change);
153 g_hash_table_destroy(values);
154}
155
156static void
157element_name(void **state)
158{
159 xmlNode *xml = pcmk__xml_parse(XML_BLOCKS);
160 crm_time_t *now = crm_time_new("2024-11-06 15:00:00");
161 GHashTable *values = pcmk__strkey_table(free, free);
162 pcmk_rule_input_t rule_input = {
163 .now = now,
164 };
165
166 assert_non_null(xml);
167
168 /* This also tests that NULL first_id and next_change are handled without
169 * problems
170 */
171
173 values, NULL);
174 assert_int_equal(g_hash_table_size(values), 2);
175 assert_string_equal(g_hash_table_lookup(values, "name1"), "1");
176 assert_string_equal(g_hash_table_lookup(values, "name2"), "1");
177 assert_null(g_hash_table_lookup(values, "name3"));
178 g_hash_table_remove_all(values);
179
181 &rule_input, values, NULL);
182 assert_int_equal(g_hash_table_size(values), 3);
183 assert_string_equal(g_hash_table_lookup(values, "name1"), "3");
184 assert_string_equal(g_hash_table_lookup(values, "name2"), "3");
185 assert_string_equal(g_hash_table_lookup(values, "name3"), "3");
186
187 pcmk__xml_free(xml);
188 crm_time_free(now);
189 g_hash_table_destroy(values);
190}
191
192static void
193first_id(void **state)
194{
195 xmlNode *xml = pcmk__xml_parse(XML_BLOCKS);
196 GHashTable *values = pcmk__strkey_table(free, free);
197
198 assert_non_null(xml);
199
200 // This also tests that NULL rule_input is handled without problems
201
202 pcmk_unpack_nvpair_blocks(xml, NULL, "ia2", NULL, values, NULL);
203 assert_int_equal(g_hash_table_size(values), 3);
204 assert_string_equal(g_hash_table_lookup(values, "name1"), "2");
205 assert_string_equal(g_hash_table_lookup(values, "name2"), "2");
206 assert_string_equal(g_hash_table_lookup(values, "name3"), "2");
207
208 pcmk__xml_free(xml);
209 g_hash_table_destroy(values);
210}
211
213 cmocka_unit_test(null_xml),
214 cmocka_unit_test(null_table),
215 cmocka_unit_test(rule_passes),
216 cmocka_unit_test(rule_fails),
217 cmocka_unit_test(element_name),
218 cmocka_unit_test(first_id))
ISO_8601 Date handling.
void crm_time_free(crm_time_t *dt)
Definition iso8601.c:150
crm_time_t * crm_time_new(const char *string)
Definition iso8601.c:112
struct crm_time_s crm_time_t
Definition iso8601.h:32
int crm_time_compare(const crm_time_t *a, const crm_time_t *b)
Definition iso8601.c:1736
void pcmk_unpack_nvpair_blocks(const xmlNode *xml, const char *element_name, const char *first_id, const pcmk_rule_input_t *rule_input, GHashTable *values, crm_time_t *next_change)
Unpack nvpair blocks contained by an XML element into a hash table, evaluated for any rules.
Definition nvpair.c:483
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:685
Data used to evaluate a rule (any NULL items are ignored)
Definition rules.h:57
#define pcmk__assert_asserts(stmt)
int pcmk__xml_test_teardown_group(void **state)
Definition unittest.c:105
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
int pcmk__xml_test_setup_group(void **state)
Definition unittest.c:87
Wrappers for and extensions to libxml2.
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816
xmlNode * pcmk__xml_parse(const char *input)
Definition xml_io.c:167
#define PCMK_XE_INSTANCE_ATTRIBUTES
Definition xml_names.h:122
#define PCMK_XE_META_ATTRIBUTES
Definition xml_names.h:130