pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
pcmk__xe_dereference_children_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> // GList, GHashTable, etc.
13
16
27static void
28assert_deref(const char *xml_string, const char *element_name, ...)
29{
30 xmlNode *xml = NULL;
31 GList *list = NULL;
32 GHashTable *table = NULL;
33 va_list ap;
34
35 // Parse given XML
36 if (xml_string != NULL) {
37 xml = pcmk__xml_parse(xml_string);
38 assert_non_null(xml);
39 }
40
41 // Create a hash table with all expected child IDs
42 va_start(ap, element_name);
43 for (const char *value = va_arg(ap, const char *);
44 value != NULL; value = va_arg(ap, const char *)) {
45 if (table == NULL) {
46 table = pcmk__strkey_table(NULL, NULL);
47 }
48 g_hash_table_add(table, (gpointer) value);
49 }
50 va_end(ap);
51
52 // Call tested function on "test" child
54 NULL, NULL),
55 element_name);
56
57 // Ensure returned list has exactly the expected child IDs
58 if (table == NULL) {
59 assert_null(list);
60 } else {
61 while (list != NULL) {
62 const char *value = crm_element_value((xmlNode *) list->data,
63 "testattr");
64
65 assert_true(g_hash_table_remove(table, value));
66 list = list->next;
67 }
68 assert_int_equal(g_hash_table_size(table), 0);
69 }
70
71 g_list_free(list);
72 if (table != NULL) {
73 g_hash_table_destroy(table);
74 }
75 pcmk__xml_free(xml);
76}
77
78static void
79null_for_null(void **state)
80{
81 assert_deref(NULL, NULL, NULL);
82 assert_deref(NULL, "test", NULL);
83}
84
85#define XML_NO_CHILDREN "<xml><test/></xml>"
86#define XML_NO_ELEMENT_CHILDREN "<xml><test><!-- comment -->text</test></xml>"
87
88static void
89null_for_no_children(void **state)
90{
91 assert_deref(XML_NO_CHILDREN, NULL, NULL);
92 assert_deref(XML_NO_CHILDREN, "test", NULL);
93 assert_deref(XML_NO_ELEMENT_CHILDREN, NULL, NULL);
94 assert_deref(XML_NO_ELEMENT_CHILDREN, "test", NULL);
95}
96
97#define XML_NO_IDREF \
98 "<xml>\n" \
99 " <test>\n" \
100 " <!-- comment -->\n" \
101 " <other id='other1' testattr='othervalue1' />\n" \
102 " <child id='child1' testattr='childvalue1' />\n" \
103 " <other id='other2' testattr='othervalue2' />\n" \
104 " <child id='child2' testattr='childvalue2' />\n" \
105 " <child id='child3' testattr='childvalue3' />\n" \
106 " <other id='other3' testattr='othervalue3' />\n" \
107 " </test>\n" \
108 "</xml>\n"
109
110static void
111without_idref(void **state)
112{
113 assert_deref(XML_NO_IDREF, NULL,
114 "othervalue1", "othervalue2", "othervalue3",
115 "childvalue1", "childvalue2", "childvalue3", NULL);
116
117 assert_deref(XML_NO_IDREF, "other",
118 "othervalue1", "othervalue2", "othervalue3", NULL);
119
120 assert_deref(XML_NO_IDREF, "child",
121 "childvalue1", "childvalue2", "childvalue3", NULL);
122
123 assert_deref(XML_NO_IDREF, "nonexistent", NULL);
124}
125
126#define XML_WITH_IDREF \
127 "<xml>\n" \
128 " <other id='other1' testattr='othervalue1' />\n" \
129 " <child id='child2' testattr='childvalue2' />\n" \
130 " <test>\n" \
131 " <!-- comment -->\n" \
132 " <other id-ref='other1'/>\n" \
133 " <child id='child1' testattr='childvalue1' />\n" \
134 " <other id='other2' testattr='othervalue2' />\n" \
135 " <child id-ref='child2' />\n" \
136 " <child id='child3' testattr='childvalue3' />\n" \
137 " <other id='other3' testattr='othervalue3' />\n" \
138 " </test>\n" \
139 "</xml>\n"
140
141static void
142with_idref(void **state)
143{
144 assert_deref(XML_WITH_IDREF, NULL,
145 "othervalue1", "othervalue2", "othervalue3",
146 "childvalue1", "childvalue2", "childvalue3", NULL);
147
148 assert_deref(XML_WITH_IDREF, "other",
149 "othervalue1", "othervalue2", "othervalue3", NULL);
150
151 assert_deref(XML_WITH_IDREF, "child",
152 "childvalue1", "childvalue2", "childvalue3", NULL);
153
154 assert_deref(XML_WITH_IDREF, "nonexistent", NULL);
155}
156
157#define XML_WITH_BROKEN_IDREF \
158 "<xml>\n" \
159 " <test>\n" \
160 " <!-- comment -->\n" \
161 " <other id-ref='other1'/>\n" \
162 " <child id='child1' testattr='childvalue1' />\n" \
163 " <other id='other2' testattr='othervalue2' />\n" \
164 " <child id-ref='child2' />\n" \
165 " <child id='child3' testattr='childvalue3' />\n" \
166 " <other id='other3' testattr='othervalue3' />\n" \
167 " </test>\n" \
168 "</xml>\n"
169
170static void
171with_broken_idref(void **state)
172{
173 assert_deref(XML_WITH_BROKEN_IDREF, NULL,
174 "othervalue2", "othervalue3",
175 "childvalue1", "childvalue3", NULL);
176
177 assert_deref(XML_WITH_BROKEN_IDREF, "other",
178 "othervalue2", "othervalue3", NULL);
179
180 assert_deref(XML_WITH_BROKEN_IDREF, "child",
181 "childvalue1", "childvalue3", NULL);
182
183 assert_deref(XML_WITH_BROKEN_IDREF, "nonexistent", NULL);
184}
185
187 cmocka_unit_test(null_for_null),
188 cmocka_unit_test(null_for_no_children),
189 cmocka_unit_test(without_idref),
190 cmocka_unit_test(with_idref),
191 cmocka_unit_test(with_broken_idref))
#define XML_NO_ELEMENT_CHILDREN
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:685
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
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
Definition xml_element.c:43
GList * pcmk__xe_dereference_children(const xmlNode *xml, const char *element_name)
Definition xml_idref.c:128
void pcmk__xml_free(xmlNode *xml)
Definition xml.c:816
xmlNode * pcmk__xml_parse(const char *input)
Definition xml_io.c:167