pacemaker  2.1.9-49aab99839
Scalable High-Availability cluster resource manager
pcmk__evaluate_attr_expression_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 #include "crmcommon_private.h"
19 
20 /*
21  * Shared data
22  */
23 
24 #define MATCHED_STRING "server-north"
25 
26 static const regmatch_t submatches[] = {
27  { .rm_so = 0, .rm_eo = 12 }, // %0 = Entire string
28  { .rm_so = 7, .rm_eo = 12 }, // %1 = "north"
29 };
30 
31 static pcmk_rule_input_t rule_input = {
32  // These are the only members used to evaluate attribute expressions
33 
34  // Used to replace submatches in attribute name
36  .rsc_id_submatches = submatches,
37  .rsc_id_nmatches = 2,
38 
39  // Used when source is instance attributes
40  .rsc_params = NULL,
41 
42  // Used when source is meta-attributes
43  .rsc_meta = NULL,
44 
45  // Used to get actual value of node attribute
46  .node_attrs = NULL,
47 };
48 
49 static int
50 setup(void **state)
51 {
52  rule_input.rsc_params = pcmk__strkey_table(free, free);
53  pcmk__insert_dup(rule_input.rsc_params, "foo-param", "bar");
54  pcmk__insert_dup(rule_input.rsc_params, "myparam", "different");
55 
56  rule_input.rsc_meta = pcmk__strkey_table(free, free);
57  pcmk__insert_dup(rule_input.rsc_meta, "foo-meta", "bar");
58  pcmk__insert_dup(rule_input.rsc_params, "mymeta", "different");
59 
60  rule_input.node_attrs = pcmk__strkey_table(free, free);
61  pcmk__insert_dup(rule_input.node_attrs, "foo", "bar");
62  pcmk__insert_dup(rule_input.node_attrs, "num", "10");
63  pcmk__insert_dup(rule_input.node_attrs, "ver", "3.5.0");
64  pcmk__insert_dup(rule_input.node_attrs, "prefer-north", "100");
65 
66  return 0;
67 }
68 
69 static int
70 teardown(void **state)
71 {
72  g_hash_table_destroy(rule_input.rsc_params);
73  g_hash_table_destroy(rule_input.rsc_meta);
74  g_hash_table_destroy(rule_input.node_attrs);
75  return 0;
76 }
77 
85 static void
86 assert_attr_expression(const char *xml_string, int reference_rc)
87 {
88  xmlNode *xml = pcmk__xml_parse(xml_string);
89 
90  assert_int_equal(pcmk__evaluate_attr_expression(xml, &rule_input),
91  reference_rc);
92  free_xml(xml);
93 }
94 
95 
96 /*
97  * Invalid arguments
98  */
99 
100 #define EXPR_SOURCE_LITERAL_PASSES \
101  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
102  PCMK_XA_ATTRIBUTE "='foo' " \
103  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
104  PCMK_XA_VALUE "='bar' " \
105  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
106 
107 static void
108 null_invalid(void **state)
109 {
111 
112  assert_int_equal(pcmk__evaluate_attr_expression(NULL, NULL), EINVAL);
113  assert_int_equal(pcmk__evaluate_attr_expression(xml, NULL), EINVAL);
114  assert_int_equal(pcmk__evaluate_attr_expression(NULL, &rule_input), EINVAL);
115 
116  free_xml(xml);
117 }
118 
119 
120 /*
121  * Test PCMK_XA_ID
122  */
123 
124 #define EXPR_ID_MISSING \
125  "<" PCMK_XE_EXPRESSION " " \
126  PCMK_XA_ATTRIBUTE "='foo' " \
127  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
128  PCMK_XA_VALUE "='bar' />"
129 
130 static void
131 id_missing(void **state)
132 {
133  // Currently acceptable
134  assert_attr_expression(EXPR_ID_MISSING, pcmk_rc_ok);
135 }
136 
137 
138 /*
139  * Test PCMK_XA_ATTRIBUTE
140  */
141 
142 #define EXPR_ATTR_MISSING \
143  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
144  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
145  PCMK_XA_VALUE "='bar' />"
146 
147 static void
148 attr_missing(void **state)
149 {
150  assert_attr_expression(EXPR_ATTR_MISSING, pcmk_rc_unpack_error);
151 }
152 
153 #define EXPR_ATTR_SUBMATCH_PASSES \
154  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
155  PCMK_XA_ATTRIBUTE "='prefer-%1' " \
156  PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
157 
158 static void
159 attr_with_submatch_passes(void **state)
160 {
161  assert_attr_expression(EXPR_ATTR_SUBMATCH_PASSES, pcmk_rc_ok);
162 }
163 
164 #define EXPR_ATTR_SUBMATCH_FAILS \
165  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
166  PCMK_XA_ATTRIBUTE "='undefined-%1' " \
167  PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
168 
169 static void
170 attr_with_submatch_fails(void **state)
171 {
172  assert_attr_expression(EXPR_ATTR_SUBMATCH_FAILS, pcmk_rc_op_unsatisfied);
173 }
174 
175 
176 /*
177  * Test PCMK_XA_VALUE_SOURCE
178  */
179 
180 #define EXPR_SOURCE_MISSING \
181  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
182  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
183  PCMK_XA_ATTRIBUTE "='foo' " \
184  PCMK_XA_VALUE "='bar' />"
185 
186 static void
187 source_missing(void **state)
188 {
189  // Defaults to literal
190  assert_attr_expression(EXPR_SOURCE_MISSING, pcmk_rc_ok);
191 }
192 
193 #define EXPR_SOURCE_INVALID \
194  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
195  PCMK_XA_ATTRIBUTE "='foo' " \
196  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
197  PCMK_XA_VALUE "='bar' " \
198  PCMK_XA_VALUE_SOURCE "='not-a-source' />"
199 
200 static void
201 source_invalid(void **state)
202 {
203  // Currently treated as literal
204  assert_attr_expression(EXPR_SOURCE_INVALID, pcmk_rc_ok);
205 }
206 
207 static void
208 source_literal_passes(void **state)
209 {
210  assert_attr_expression(EXPR_SOURCE_LITERAL_PASSES, pcmk_rc_ok);
211 }
212 
213 #define EXPR_SOURCE_LITERAL_VALUE_FAILS \
214  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
215  PCMK_XA_ATTRIBUTE "='foo' " \
216  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
217  PCMK_XA_VALUE "='wrong-value' " \
218  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
219 
220 static void
221 source_literal_value_fails(void **state)
222 {
223  assert_attr_expression(EXPR_SOURCE_LITERAL_VALUE_FAILS,
225 }
226 
227 #define EXPR_SOURCE_LITERAL_ATTR_FAILS \
228  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
229  PCMK_XA_ATTRIBUTE "='not-an-attribute' " \
230  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
231  PCMK_XA_VALUE "='bar' " \
232  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
233 
234 static void
235 source_literal_attr_fails(void **state)
236 {
237  assert_attr_expression(EXPR_SOURCE_LITERAL_ATTR_FAILS,
239 }
240 
241 #define EXPR_SOURCE_PARAM_MISSING \
242  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
243  PCMK_XA_ATTRIBUTE "='foo' " \
244  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
245  PCMK_XA_VALUE "='not-a-param' " \
246  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_PARAM "' />"
247 
248 static void
249 source_params_missing(void **state)
250 {
251  assert_attr_expression(EXPR_SOURCE_PARAM_MISSING, pcmk_rc_op_unsatisfied);
252 }
253 
254 #define EXPR_SOURCE_PARAM_PASSES \
255  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
256  PCMK_XA_ATTRIBUTE "='foo' " \
257  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
258  PCMK_XA_VALUE "='foo-param' " \
259  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_PARAM "' />"
260 
261 static void
262 source_params_passes(void **state)
263 {
264  assert_attr_expression(EXPR_SOURCE_PARAM_PASSES, pcmk_rc_ok);
265 }
266 
267 #define EXPR_SOURCE_PARAM_FAILS \
268  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
269  PCMK_XA_ATTRIBUTE "='foo' " \
270  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
271  PCMK_XA_VALUE "='myparam' " \
272  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_PARAM "' />"
273 
274 static void
275 source_params_fails(void **state)
276 {
277  assert_attr_expression(EXPR_SOURCE_PARAM_FAILS, pcmk_rc_op_unsatisfied);
278 }
279 
280 #define EXPR_SOURCE_META_MISSING \
281  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
282  PCMK_XA_ATTRIBUTE "='foo' " \
283  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
284  PCMK_XA_VALUE "='not-a-meta' " \
285  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_META "' />"
286 
287 static void
288 source_meta_missing(void **state)
289 {
290  assert_attr_expression(EXPR_SOURCE_META_MISSING, pcmk_rc_op_unsatisfied);
291 }
292 
293 #define EXPR_SOURCE_META_PASSES \
294  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
295  PCMK_XA_ATTRIBUTE "='foo' " \
296  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
297  PCMK_XA_VALUE "='foo-meta' " \
298  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_META "' />"
299 
300 static void
301 source_meta_passes(void **state)
302 {
303  assert_attr_expression(EXPR_SOURCE_META_PASSES, pcmk_rc_ok);
304 }
305 
306 #define EXPR_SOURCE_META_FAILS \
307  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
308  PCMK_XA_ATTRIBUTE "='foo' " \
309  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
310  PCMK_XA_VALUE "='mymeta' " \
311  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_META "' />"
312 
313 static void
314 source_meta_fails(void **state)
315 {
316  assert_attr_expression(EXPR_SOURCE_META_FAILS, pcmk_rc_op_unsatisfied);
317 }
318 
319 
320 /*
321  * Test PCMK_XA_TYPE
322  */
323 
324 #define EXPR_TYPE_DEFAULT_NUMBER \
325  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
326  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
327  PCMK_XA_ATTRIBUTE "='num' " \
328  PCMK_XA_VALUE "='2.5' />"
329 
330 static void
331 type_default_number(void **state)
332 {
333  // Defaults to number for "gt" if either value contains a decimal point
334  assert_attr_expression(EXPR_TYPE_DEFAULT_NUMBER, pcmk_rc_ok);
335 }
336 
337 #define EXPR_TYPE_DEFAULT_INT \
338  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
339  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
340  PCMK_XA_ATTRIBUTE "='num' " \
341  PCMK_XA_VALUE "='2' />"
342 
343 static void
344 type_default_int(void **state)
345 {
346  // Defaults to integer for "gt" if neither value contains a decimal point
347  assert_attr_expression(EXPR_TYPE_DEFAULT_INT, pcmk_rc_ok);
348 }
349 
350 #define EXPR_TYPE_STRING_PASSES \
351  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
352  PCMK_XA_TYPE "='" PCMK_VALUE_STRING "' " \
353  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
354  PCMK_XA_ATTRIBUTE "='foo' " \
355  PCMK_XA_VALUE "='bar' />"
356 
357 static void
358 type_string_passes(void **state)
359 {
360  assert_attr_expression(EXPR_TYPE_STRING_PASSES, pcmk_rc_ok);
361 }
362 
363 #define EXPR_TYPE_STRING_FAILS \
364  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
365  PCMK_XA_TYPE "='" PCMK_VALUE_STRING "' " \
366  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
367  PCMK_XA_ATTRIBUTE "='foo' " \
368  PCMK_XA_VALUE "='bat' />"
369 
370 static void
371 type_string_fails(void **state)
372 {
373  assert_attr_expression(EXPR_TYPE_STRING_FAILS, pcmk_rc_op_unsatisfied);
374 }
375 
376 #define EXPR_TYPE_INTEGER_PASSES \
377  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
378  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
379  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
380  PCMK_XA_ATTRIBUTE "='num' " \
381  PCMK_XA_VALUE "='10' />"
382 
383 static void
384 type_integer_passes(void **state)
385 {
386  assert_attr_expression(EXPR_TYPE_INTEGER_PASSES, pcmk_rc_ok);
387 }
388 
389 #define EXPR_TYPE_INTEGER_FAILS \
390  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
391  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
392  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
393  PCMK_XA_ATTRIBUTE "='num' " \
394  PCMK_XA_VALUE "='11' />"
395 
396 static void
397 type_integer_fails(void **state)
398 {
399  assert_attr_expression(EXPR_TYPE_INTEGER_FAILS, pcmk_rc_op_unsatisfied);
400 }
401 
402 #define EXPR_TYPE_INTEGER_TRUNCATION \
403  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
404  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
405  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
406  PCMK_XA_ATTRIBUTE "='num' " \
407  PCMK_XA_VALUE "='10.5' />"
408 
409 static void
410 type_integer_truncation(void **state)
411 {
412  assert_attr_expression(EXPR_TYPE_INTEGER_TRUNCATION, pcmk_rc_ok);
413 }
414 
415 #define EXPR_TYPE_NUMBER_PASSES \
416  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
417  PCMK_XA_TYPE "='" PCMK_VALUE_NUMBER "' " \
418  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
419  PCMK_XA_ATTRIBUTE "='num' " \
420  PCMK_XA_VALUE "='10.0' />"
421 
422 static void
423 type_number_passes(void **state)
424 {
425  assert_attr_expression(EXPR_TYPE_NUMBER_PASSES, pcmk_rc_ok);
426 }
427 
428 #define EXPR_TYPE_NUMBER_FAILS \
429  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
430  PCMK_XA_TYPE "='" PCMK_VALUE_NUMBER "' " \
431  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
432  PCMK_XA_ATTRIBUTE "='num' " \
433  PCMK_XA_VALUE "='10.1' />"
434 
435 static void
436 type_number_fails(void **state)
437 {
438  assert_attr_expression(EXPR_TYPE_NUMBER_FAILS, pcmk_rc_op_unsatisfied);
439 }
440 
441 #define EXPR_TYPE_VERSION_PASSES \
442  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
443  PCMK_XA_TYPE "='" PCMK_VALUE_VERSION "' " \
444  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
445  PCMK_XA_ATTRIBUTE "='ver' " \
446  PCMK_XA_VALUE "='3.4.9' />"
447 
448 static void
449 type_version_passes(void **state)
450 {
451  assert_attr_expression(EXPR_TYPE_VERSION_PASSES, pcmk_rc_ok);
452 }
453 
454 #define EXPR_TYPE_VERSION_EQUALITY \
455  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
456  PCMK_XA_TYPE "='" PCMK_VALUE_VERSION "' " \
457  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
458  PCMK_XA_ATTRIBUTE "='ver' " \
459  PCMK_XA_VALUE "='3.5' />"
460 
461 static void
462 type_version_equality(void **state)
463 {
464  assert_attr_expression(EXPR_TYPE_VERSION_EQUALITY, pcmk_rc_ok);
465 }
466 
467 #define EXPR_TYPE_VERSION_FAILS \
468  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
469  PCMK_XA_TYPE "='" PCMK_VALUE_VERSION "' " \
470  PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
471  PCMK_XA_ATTRIBUTE "='ver' " \
472  PCMK_XA_VALUE "='4.0' />"
473 
474 static void
475 type_version_fails(void **state)
476 {
477  assert_attr_expression(EXPR_TYPE_VERSION_FAILS, pcmk_rc_before_range);
478 }
479 
480 /*
481  * Test PCMK_XA_OPERATION
482  */
483 
484 #define EXPR_OP_MISSING \
485  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
486  PCMK_XA_ATTRIBUTE "='foo' " \
487  PCMK_XA_VALUE "='bar' />"
488 
489 static void
490 op_missing(void **state)
491 {
492  assert_attr_expression(EXPR_OP_MISSING, pcmk_rc_unpack_error);
493 }
494 
495 #define EXPR_OP_INVALID \
496  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
497  PCMK_XA_ATTRIBUTE "='foo' " \
498  PCMK_XA_OPERATION "='not-an-operation' " \
499  PCMK_XA_VALUE "='bar' />"
500 
501 static void
502 op_invalid(void **state)
503 {
504  assert_attr_expression(EXPR_OP_INVALID, pcmk_rc_unpack_error);
505 }
506 
507 #define EXPR_OP_LT_PASSES \
508  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
509  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
510  PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' " \
511  PCMK_XA_ATTRIBUTE "='num' " \
512  PCMK_XA_VALUE "='20' />"
513 
514 static void
515 op_lt_passes(void **state)
516 {
517  assert_attr_expression(EXPR_OP_LT_PASSES, pcmk_rc_ok);
518 }
519 
520 #define EXPR_OP_LT_FAILS \
521  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
522  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
523  PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' " \
524  PCMK_XA_ATTRIBUTE "='num' " \
525  PCMK_XA_VALUE "='2' />"
526 
527 static void
528 op_lt_fails(void **state)
529 {
530  assert_attr_expression(EXPR_OP_LT_FAILS, pcmk_rc_after_range);
531 }
532 
533 #define EXPR_OP_GT_PASSES \
534  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
535  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
536  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
537  PCMK_XA_ATTRIBUTE "='num' " \
538  PCMK_XA_VALUE "='2' />"
539 
540 static void
541 op_gt_passes(void **state)
542 {
543  assert_attr_expression(EXPR_OP_GT_PASSES, pcmk_rc_ok);
544 }
545 
546 #define EXPR_OP_GT_FAILS \
547  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
548  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
549  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
550  PCMK_XA_ATTRIBUTE "='num' " \
551  PCMK_XA_VALUE "='20' />"
552 
553 static void
554 op_gt_fails(void **state)
555 {
556  assert_attr_expression(EXPR_OP_GT_FAILS, pcmk_rc_before_range);
557 }
558 
559 #define EXPR_OP_LTE_LT_PASSES \
560  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
561  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
562  PCMK_XA_OPERATION "='" PCMK_VALUE_LTE "' " \
563  PCMK_XA_ATTRIBUTE "='num' " \
564  PCMK_XA_VALUE "='20' />"
565 
566 static void
567 op_lte_lt_passes(void **state)
568 {
569  assert_attr_expression(EXPR_OP_LTE_LT_PASSES, pcmk_rc_ok);
570 }
571 
572 #define EXPR_OP_LTE_EQ_PASSES \
573  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
574  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
575  PCMK_XA_OPERATION "='" PCMK_VALUE_LTE "' " \
576  PCMK_XA_ATTRIBUTE "='num' " \
577  PCMK_XA_VALUE "='10' />"
578 
579 static void
580 op_lte_eq_passes(void **state)
581 {
582  assert_attr_expression(EXPR_OP_LTE_EQ_PASSES, pcmk_rc_ok);
583 }
584 
585 #define EXPR_OP_LTE_FAILS \
586  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
587  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
588  PCMK_XA_OPERATION "='" PCMK_VALUE_LTE "' " \
589  PCMK_XA_ATTRIBUTE "='num' " \
590  PCMK_XA_VALUE "='9' />"
591 
592 static void
593 op_lte_fails(void **state)
594 {
595  assert_attr_expression(EXPR_OP_LTE_FAILS, pcmk_rc_after_range);
596 }
597 
598 #define EXPR_OP_GTE_GT_PASSES \
599  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
600  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
601  PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
602  PCMK_XA_ATTRIBUTE "='num' " \
603  PCMK_XA_VALUE "='1' />"
604 
605 static void
606 op_gte_gt_passes(void **state)
607 {
608  assert_attr_expression(EXPR_OP_GTE_GT_PASSES, pcmk_rc_ok);
609 }
610 
611 #define EXPR_OP_GTE_EQ_PASSES \
612  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
613  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
614  PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
615  PCMK_XA_ATTRIBUTE "='num' " \
616  PCMK_XA_VALUE "='10' />"
617 
618 static void
619 op_gte_eq_passes(void **state)
620 {
621  assert_attr_expression(EXPR_OP_GTE_EQ_PASSES, pcmk_rc_ok);
622 }
623 
624 #define EXPR_OP_GTE_FAILS \
625  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
626  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
627  PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
628  PCMK_XA_ATTRIBUTE "='num' " \
629  PCMK_XA_VALUE "='11' />"
630 
631 static void
632 op_gte_fails(void **state)
633 {
634  assert_attr_expression(EXPR_OP_GTE_FAILS, pcmk_rc_before_range);
635 }
636 
637 // This also tests that string is used if values aren't parseable as numbers
638 #define EXPR_OP_EQ_PASSES \
639  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
640  PCMK_XA_TYPE "='" PCMK_VALUE_NUMBER "' " \
641  PCMK_XA_ATTRIBUTE "='foo' " \
642  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
643  PCMK_XA_VALUE "='bar' " \
644  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
645 
646 static void
647 op_eq_passes(void **state)
648 {
649  assert_attr_expression(EXPR_OP_EQ_PASSES, pcmk_rc_ok);
650 }
651 
652 #define EXPR_OP_EQ_FAILS \
653  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
654  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
655  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
656  PCMK_XA_ATTRIBUTE "='num' " \
657  PCMK_XA_VALUE "='bar' />"
658 
659 static void
660 op_eq_fails(void **state)
661 {
662  assert_attr_expression(EXPR_OP_EQ_FAILS, pcmk_rc_op_unsatisfied);
663 }
664 
665 #define EXPR_OP_NE_PASSES \
666  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
667  PCMK_XA_TYPE "='" PCMK_VALUE_STRING "' " \
668  PCMK_XA_ATTRIBUTE "='foo' " \
669  PCMK_XA_OPERATION "='" PCMK_VALUE_NE "' " \
670  PCMK_XA_VALUE "='bat' " \
671  PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
672 
673 static void
674 op_ne_passes(void **state)
675 {
676  assert_attr_expression(EXPR_OP_NE_PASSES, pcmk_rc_ok);
677 }
678 
679 #define EXPR_OP_NE_FAILS \
680  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
681  PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
682  PCMK_XA_OPERATION "='" PCMK_VALUE_NE "' " \
683  PCMK_XA_ATTRIBUTE "='num' " \
684  PCMK_XA_VALUE "='10' />"
685 
686 static void
687 op_ne_fails(void **state)
688 {
689  assert_attr_expression(EXPR_OP_NE_FAILS, pcmk_rc_op_unsatisfied);
690 }
691 
692 #define EXPR_OP_DEFINED_PASSES \
693  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
694  PCMK_XA_ATTRIBUTE "='foo' " \
695  PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
696 
697 static void
698 op_defined_passes(void **state)
699 {
700  assert_attr_expression(EXPR_OP_DEFINED_PASSES, pcmk_rc_ok);
701 }
702 
703 #define EXPR_OP_DEFINED_FAILS \
704  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
705  PCMK_XA_ATTRIBUTE "='boo' " \
706  PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
707 
708 static void
709 op_defined_fails(void **state)
710 {
711  assert_attr_expression(EXPR_OP_DEFINED_FAILS, pcmk_rc_op_unsatisfied);
712 }
713 
714 #define EXPR_OP_DEFINED_WITH_VALUE \
715  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
716  PCMK_XA_ATTRIBUTE "='foo' " \
717  PCMK_XA_VALUE "='bar' " \
718  PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
719 
720 static void
721 op_defined_with_value(void **state)
722 {
723  // Ill-formed but currently accepted
724  assert_attr_expression(EXPR_OP_DEFINED_WITH_VALUE, pcmk_rc_ok);
725 }
726 
727 #define EXPR_OP_UNDEFINED_PASSES \
728  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
729  PCMK_XA_ATTRIBUTE "='boo' " \
730  PCMK_XA_OPERATION "='" PCMK_VALUE_NOT_DEFINED "' />"
731 
732 static void
733 op_undefined_passes(void **state)
734 {
735  assert_attr_expression(EXPR_OP_UNDEFINED_PASSES, pcmk_rc_ok);
736 }
737 
738 #define EXPR_OP_UNDEFINED_FAILS \
739  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
740  PCMK_XA_ATTRIBUTE "='foo' " \
741  PCMK_XA_OPERATION "='" PCMK_VALUE_NOT_DEFINED "' />"
742 
743 static void
744 op_undefined_fails(void **state)
745 {
746  assert_attr_expression(EXPR_OP_DEFINED_FAILS, pcmk_rc_op_unsatisfied);
747 }
748 
749 
750 /*
751  * Test PCMK_XA_VALUE
752  */
753 
754 #define EXPR_VALUE_MISSING_DEFINED_OK \
755  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
756  PCMK_XA_ATTRIBUTE "='num' " \
757  PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
758 
759 static void
760 value_missing_defined_ok(void **state)
761 {
762  assert_attr_expression(EXPR_VALUE_MISSING_DEFINED_OK, pcmk_rc_ok);
763 }
764 
765 #define EXPR_VALUE_MISSING_EQ_OK \
766  "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
767  PCMK_XA_ATTRIBUTE "='not-an-attr' " \
768  PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' />"
769 
770 static void
771 value_missing_eq_ok(void **state)
772 {
773  // Currently treated as NULL reference value
774  assert_attr_expression(EXPR_VALUE_MISSING_EQ_OK, pcmk_rc_ok);
775 }
776 
777 
778 #define expr_test(f) cmocka_unit_test_setup_teardown(f, setup, teardown)
779 
781  cmocka_unit_test(null_invalid),
782  expr_test(id_missing),
783  expr_test(attr_missing),
784  expr_test(attr_with_submatch_passes),
785  expr_test(attr_with_submatch_fails),
786  expr_test(source_missing),
787  expr_test(source_invalid),
788  expr_test(source_literal_passes),
789  expr_test(source_literal_value_fails),
790  expr_test(source_literal_attr_fails),
791  expr_test(source_params_missing),
792  expr_test(source_params_passes),
793  expr_test(source_params_fails),
794  expr_test(source_meta_missing),
795  expr_test(source_meta_passes),
796  expr_test(source_meta_fails),
797  expr_test(type_default_number),
798  expr_test(type_default_int),
799  expr_test(type_string_passes),
800  expr_test(type_string_fails),
801  expr_test(type_integer_passes),
802  expr_test(type_integer_fails),
803  expr_test(type_integer_truncation),
804  expr_test(type_number_passes),
805  expr_test(type_number_fails),
806  expr_test(type_version_passes),
807  expr_test(type_version_equality),
808  expr_test(type_version_fails),
809  expr_test(op_missing),
810  expr_test(op_invalid),
811  expr_test(op_lt_passes),
812  expr_test(op_lt_fails),
813  expr_test(op_gt_passes),
814  expr_test(op_gt_fails),
815  expr_test(op_lte_lt_passes),
816  expr_test(op_lte_eq_passes),
817  expr_test(op_lte_fails),
818  expr_test(op_gte_gt_passes),
819  expr_test(op_gte_eq_passes),
820  expr_test(op_gte_fails),
821  expr_test(op_eq_passes),
822  expr_test(op_eq_fails),
823  expr_test(op_ne_passes),
824  expr_test(op_ne_fails),
825  expr_test(op_defined_passes),
826  expr_test(op_defined_fails),
827  expr_test(op_defined_with_value),
828  expr_test(op_undefined_passes),
829  expr_test(op_undefined_fails),
830  expr_test(value_missing_defined_ok),
831  expr_test(value_missing_eq_ok))
#define EXPR_VALUE_MISSING_DEFINED_OK
GHashTable * rsc_meta
Definition: rules.h:93
#define EXPR_TYPE_VERSION_FAILS
Data used to evaluate a rule (any NULL items are ignored)
Definition: rules.h:57
#define EXPR_SOURCE_META_PASSES
#define EXPR_TYPE_INTEGER_TRUNCATION
GHashTable * rsc_params
Definition: rules.h:86
#define EXPR_OP_UNDEFINED_PASSES
G_GNUC_INTERNAL int pcmk__evaluate_attr_expression(const xmlNode *expression, const pcmk_rule_input_t *rule_input)
Definition: rules.c:1039
#define EXPR_SOURCE_PARAM_FAILS
#define EXPR_TYPE_DEFAULT_NUMBER
#define EXPR_TYPE_VERSION_PASSES
#define EXPR_TYPE_NUMBER_FAILS
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
#define EXPR_OP_DEFINED_WITH_VALUE
#define EXPR_SOURCE_PARAM_MISSING
#define EXPR_VALUE_MISSING_EQ_OK
#define EXPR_TYPE_STRING_PASSES
#define EXPR_SOURCE_LITERAL_VALUE_FAILS
#define EXPR_OP_DEFINED_PASSES
int pcmk__xml_test_setup_group(void **state)
Definition: unittest.c:85
Wrappers for and extensions to libxml2.
void free_xml(xmlNode *child)
Definition: xml.c:958
#define EXPR_SOURCE_LITERAL_ATTR_FAILS
#define EXPR_ATTR_SUBMATCH_PASSES
#define EXPR_SOURCE_LITERAL_PASSES
int pcmk__xml_test_teardown_group(void **state)
Definition: unittest.c:104
xmlNode * pcmk__xml_parse(const char *input)
Definition: xml_io.c:245
#define EXPR_TYPE_INTEGER_FAILS
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition: strings.c:695
#define EXPR_TYPE_STRING_FAILS
GHashTable * node_attrs
Operation interval that rule applies to.
Definition: rules.h:77
#define EXPR_TYPE_NUMBER_PASSES
#define EXPR_TYPE_INTEGER_PASSES
#define EXPR_SOURCE_META_MISSING
#define EXPR_TYPE_VERSION_EQUALITY
#define EXPR_ATTR_SUBMATCH_FAILS
const char * rsc_id
Resource ID to compare against a location constraint&#39;s resource pattern.
Definition: rules.h:96
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition: strings.c:713
#define EXPR_SOURCE_PARAM_PASSES
#define EXPR_SOURCE_META_FAILS