pacemaker  2.1.8-3980678f03
Scalable High-Availability cluster resource manager
pcmk_ticket_set_attr_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 <crm/cib/internal.h>
14 #include <crm/common/xml.h>
15 #include <pacemaker.h>
16 
17 static char *cib_path = NULL;
18 
19 static void
20 cib_not_connected(void **state)
21 {
22  xmlNode *xml = NULL;
23 
24  /* Without any special setup, cib_new() in pcmk_ticket_set_attr will use the
25  * native CIB which means IPC calls. But there's nothing listening for those
26  * calls, so signon() will return ENOTCONN. Check that we handle that.
27  */
28  assert_int_equal(pcmk_ticket_set_attr(&xml, NULL, NULL, false), ENOTCONN);
30  free_xml(xml);
31 }
32 
33 static int
34 setup_test(void **state)
35 {
36  cib_path = pcmk__cib_test_copy_cib("tickets.xml");
37 
38  if (cib_path == NULL) {
39  return -1;
40  }
41 
42  return 0;
43 }
44 
45 static int
46 teardown_test(void **state)
47 {
48  pcmk__cib_test_cleanup(cib_path);
49  cib_path = NULL;
50  return 0;
51 }
52 
53 static void
54 bad_arguments(void **state)
55 {
56  xmlNode *xml = NULL;
57 
58  assert_int_equal(pcmk_ticket_set_attr(NULL, "ticketA", NULL, false), EINVAL);
59 
60  assert_int_equal(pcmk_ticket_set_attr(&xml, NULL, NULL, false), EINVAL);
62  free_xml(xml);
63 }
64 
65 static void
66 unknown_ticket_no_attrs(void **state)
67 {
68  GHashTable *attrs = pcmk__strkey_table(free, free);
69  xmlNode *xml = NULL;
70  xmlNode *xml_search = NULL;
71  cib_t *cib = cib_new();
72 
74 
75  /* Setting no attributes on a ticket that doesn't exist is a no-op */
76  assert_int_equal(pcmk_ticket_set_attr(&xml, "XYZ", NULL, false), pcmk_rc_ok);
78  free_xml(xml);
79  xml = NULL;
80 
81  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"XYZ\"]",
82  &xml_search, cib_xpath | cib_scope_local);
83  assert_null(xml_search);
84 
85  /* Another way of specifying no attributes */
86  assert_int_equal(pcmk_ticket_set_attr(&xml, "XYZ", attrs, false), pcmk_rc_ok);
88  free_xml(xml);
89 
90  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"XYZ\"]",
91  &xml_search, cib_xpath | cib_scope_local);
92  assert_null(xml_search);
93 
94  g_hash_table_destroy(attrs);
96 }
97 
98 static void
99 unknown_ticket_with_attrs(void **state)
100 {
101  GHashTable *attrs = pcmk__strkey_table(free, free);
102  xmlNode *xml = NULL;
103  xmlNode *xml_search = NULL;
104  cib_t *cib;
105 
106  pcmk__insert_dup(attrs, "attrA", "123");
107  pcmk__insert_dup(attrs, "attrB", "456");
108 
109  /* Setting attributes on a ticket that doesn't exist causes the ticket to
110  * be created with the given attributes
111  */
112  assert_int_equal(pcmk_ticket_set_attr(&xml, "XYZ", attrs, false), pcmk_rc_ok);
114  free_xml(xml);
115 
116  cib = cib_new();
117  cib->cmds->signon(cib, crm_system_name, cib_command);
118  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"XYZ\"]",
119  &xml_search, cib_xpath | cib_scope_local);
120 
121  assert_string_equal("123", crm_element_value(xml_search, "attrA"));
122  assert_string_equal("456", crm_element_value(xml_search, "attrB"));
123 
124  free_xml(xml_search);
125  g_hash_table_destroy(attrs);
127 }
128 
129 static void
130 overwrite_existing_attr(void **state)
131 {
132  GHashTable *attrs = pcmk__strkey_table(free, free);
133  xmlNode *xml = NULL;
134  xmlNode *xml_search = NULL;
135  cib_t *cib;
136 
137  pcmk__insert_dup(attrs, "owner", "2");
138 
139  assert_int_equal(pcmk_ticket_set_attr(&xml, "ticketA", attrs, false), pcmk_rc_ok);
141  free_xml(xml);
142 
143  cib = cib_new();
144  cib->cmds->signon(cib, crm_system_name, cib_command);
145  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"ticketA\"]",
146  &xml_search, cib_xpath | cib_scope_local);
147 
148  assert_string_equal("2", crm_element_value(xml_search, "owner"));
149 
150  free_xml(xml_search);
151  g_hash_table_destroy(attrs);
153 }
154 
155 static void
156 not_granted_to_granted_without_force(void **state)
157 {
158  GHashTable *attrs = pcmk__strkey_table(free, free);
159  xmlNode *xml = NULL;
160  xmlNode *xml_search = NULL;
161  cib_t *cib;
162 
163  pcmk__insert_dup(attrs, PCMK__XA_GRANTED, "true");
164 
165  assert_int_equal(pcmk_ticket_set_attr(&xml, "ticketA", attrs, false), EACCES);
167  free_xml(xml);
168 
169  cib = cib_new();
170  cib->cmds->signon(cib, crm_system_name, cib_command);
171  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"ticketA\"]",
172  &xml_search, cib_xpath | cib_scope_local);
173 
174  assert_string_equal("false", crm_element_value(xml_search, PCMK__XA_GRANTED));
175  assert_null(crm_element_value(xml_search, PCMK_XA_LAST_GRANTED));
176 
177  free_xml(xml_search);
178  g_hash_table_destroy(attrs);
180 }
181 
182 static void
183 not_granted_to_granted_with_force(void **state)
184 {
185  GHashTable *attrs = pcmk__strkey_table(free, free);
186  xmlNode *xml = NULL;
187  xmlNode *xml_search = NULL;
188  cib_t *cib;
189 
190  pcmk__insert_dup(attrs, PCMK__XA_GRANTED, "true");
191 
192  assert_int_equal(pcmk_ticket_set_attr(&xml, "ticketA", attrs, true), pcmk_rc_ok);
194  free_xml(xml);
195 
196  cib = cib_new();
197  cib->cmds->signon(cib, crm_system_name, cib_command);
198  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"ticketA\"]",
199  &xml_search, cib_xpath | cib_scope_local);
200 
201  assert_string_equal("true", crm_element_value(xml_search, PCMK__XA_GRANTED));
202  assert_non_null(crm_element_value(xml_search, PCMK_XA_LAST_GRANTED));
203 
204  free_xml(xml_search);
205  g_hash_table_destroy(attrs);
207 }
208 
209 static void
210 granted_to_not_granted_without_force(void **state)
211 {
212  GHashTable *attrs = pcmk__strkey_table(free, free);
213  xmlNode *xml = NULL;
214  xmlNode *xml_search = NULL;
215  cib_t *cib;
216 
217  pcmk__insert_dup(attrs, PCMK__XA_GRANTED, "false");
218 
219  assert_int_equal(pcmk_ticket_set_attr(&xml, "ticketB", attrs, false), EACCES);
221  free_xml(xml);
222 
223  cib = cib_new();
224  cib->cmds->signon(cib, crm_system_name, cib_command);
225  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"ticketB\"]",
226  &xml_search, cib_xpath | cib_scope_local);
227 
228  assert_string_equal("true", crm_element_value(xml_search, PCMK__XA_GRANTED));
229  assert_null(crm_element_value(xml_search, PCMK_XA_LAST_GRANTED));
230 
231  free_xml(xml_search);
232  g_hash_table_destroy(attrs);
234 }
235 
236 static void
237 granted_to_not_granted_with_force(void **state)
238 {
239  GHashTable *attrs = pcmk__strkey_table(free, free);
240  xmlNode *xml = NULL;
241  xmlNode *xml_search = NULL;
242  cib_t *cib;
243 
244  pcmk__insert_dup(attrs, PCMK__XA_GRANTED, "false");
245 
246  assert_int_equal(pcmk_ticket_set_attr(&xml, "ticketB", attrs, true), pcmk_rc_ok);
248  free_xml(xml);
249 
250  cib = cib_new();
251  cib->cmds->signon(cib, crm_system_name, cib_command);
252  cib->cmds->query(cib, "//" PCMK__XE_TICKET_STATE "[@" PCMK_XA_ID "=\"ticketB\"]",
253  &xml_search, cib_xpath | cib_scope_local);
254 
255  assert_string_equal("false", crm_element_value(xml_search, PCMK__XA_GRANTED));
256  assert_null(crm_element_value(xml_search, PCMK_XA_LAST_GRANTED));
257 
258  free_xml(xml_search);
259  g_hash_table_destroy(attrs);
261 }
262 
263 /* There are two kinds of tests in this file:
264  *
265  * (1) Those that test what happens if the CIB is not set up correctly, and
266  * (2) Those that test what happens when run against a CIB.
267  *
268  * Therefore, we need two kinds of setup/teardown functions. We only do
269  * minimal overall setup for the entire group, and then setup the CIB for
270  * those tests that need it.
271  */
273  cmocka_unit_test(cib_not_connected),
274  cmocka_unit_test_setup_teardown(bad_arguments, setup_test, teardown_test),
275  cmocka_unit_test_setup_teardown(unknown_ticket_no_attrs, setup_test, teardown_test),
276  cmocka_unit_test_setup_teardown(unknown_ticket_with_attrs, setup_test, teardown_test),
277  cmocka_unit_test_setup_teardown(overwrite_existing_attr, setup_test, teardown_test),
278  cmocka_unit_test_setup_teardown(not_granted_to_granted_without_force, setup_test, teardown_test),
279  cmocka_unit_test_setup_teardown(not_granted_to_granted_with_force, setup_test, teardown_test),
280  cmocka_unit_test_setup_teardown(granted_to_not_granted_without_force, setup_test, teardown_test),
281  cmocka_unit_test_setup_teardown(granted_to_not_granted_with_force, setup_test, teardown_test))
#define PCMK__XE_TICKET_STATE
cib_t * cib_new(void)
Create a new CIB connection object.
Definition: cib_client.c:616
High Level API.
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
char * crm_system_name
Definition: utils.c:50
cib_api_operations_t * cmds
Definition: cib_types.h:399
int(* signon)(cib_t *cib, const char *name, enum cib_conn_type type)
Definition: cib_types.h:159
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:446
int pcmk_ticket_set_attr(xmlNodePtr *xml, const char *ticket_id, GHashTable *attr_set, bool force)
Set the given attribute(s) on a ticket.
Definition: pcmk_ticket.c:484
int pcmk__xml_test_setup_group(void **state)
Definition: unittest.c:74
Wrappers for and extensions to libxml2.
int(* query)(cib_t *cib, const char *section, xmlNode **output_data, int call_options)
Definition: cib_types.h:198
#define PCMK_XA_ID
Definition: xml_names.h:296
void free_xml(xmlNode *child)
Definition: xml.c:867
int cib__clean_up_connection(cib_t **cib)
Definition: cib_utils.c:1046
void pcmk__cib_test_cleanup(char *out_path)
Definition: unittest.c:121
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:683
void pcmk__assert_validates(xmlNode *xml)
Definition: unittest.c:20
char * pcmk__cib_test_copy_cib(const char *in_file)
Definition: unittest.c:86
#define PCMK__XA_GRANTED
#define PCMK_XA_LAST_GRANTED
Definition: xml_names.h:310
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:701