pacemaker 3.0.1-16e74fc4da
Scalable High-Availability cluster resource manager
Loading...
Searching...
No Matches
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
26static 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
31static 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
35 .rsc_id = MATCHED_STRING,
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
49static int
50setup(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 pcmk__insert_dup(rule_input.node_attrs, "empty", "");
66
67 return 0;
68}
69
70static int
71teardown(void **state)
72{
73 g_hash_table_destroy(rule_input.rsc_params);
74 g_hash_table_destroy(rule_input.rsc_meta);
75 g_hash_table_destroy(rule_input.node_attrs);
76 return 0;
77}
78
86static void
87assert_attr_expression(const char *xml_string, int reference_rc)
88{
89 xmlNode *xml = pcmk__xml_parse(xml_string);
90
91 assert_int_equal(pcmk__evaluate_attr_expression(xml, &rule_input),
92 reference_rc);
93 pcmk__xml_free(xml);
94}
95
96
97/*
98 * Invalid arguments
99 */
100
101#define EXPR_SOURCE_LITERAL_PASSES \
102 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
103 PCMK_XA_ATTRIBUTE "='foo' " \
104 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
105 PCMK_XA_VALUE "='bar' " \
106 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
107
108static void
109null_invalid(void **state)
110{
112
113 assert_int_equal(pcmk__evaluate_attr_expression(NULL, NULL), EINVAL);
114 assert_int_equal(pcmk__evaluate_attr_expression(xml, NULL), EINVAL);
115 assert_int_equal(pcmk__evaluate_attr_expression(NULL, &rule_input), EINVAL);
116
117 pcmk__xml_free(xml);
118}
119
120
121/*
122 * Test PCMK_XA_ID
123 */
124
125#define EXPR_ID_MISSING \
126 "<" PCMK_XE_EXPRESSION " " \
127 PCMK_XA_ATTRIBUTE "='foo' " \
128 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
129 PCMK_XA_VALUE "='bar' />"
130
131static void
132id_missing(void **state)
133{
134 assert_attr_expression(EXPR_ID_MISSING, pcmk_rc_unpack_error);
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
147static void
148attr_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
158static void
159attr_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
169static void
170attr_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
186static void
187source_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
200static void
201source_invalid(void **state)
202{
203 assert_attr_expression(EXPR_SOURCE_INVALID, pcmk_rc_unpack_error);
204}
205
206static void
207source_literal_passes(void **state)
208{
209 assert_attr_expression(EXPR_SOURCE_LITERAL_PASSES, pcmk_rc_ok);
210}
211
212#define EXPR_SOURCE_LITERAL_VALUE_FAILS \
213 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
214 PCMK_XA_ATTRIBUTE "='foo' " \
215 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
216 PCMK_XA_VALUE "='wrong-value' " \
217 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
218
219static void
220source_literal_value_fails(void **state)
221{
222 assert_attr_expression(EXPR_SOURCE_LITERAL_VALUE_FAILS,
224}
225
226#define EXPR_SOURCE_LITERAL_ATTR_FAILS \
227 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
228 PCMK_XA_ATTRIBUTE "='not-an-attribute' " \
229 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
230 PCMK_XA_VALUE "='bar' " \
231 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
232
233static void
234source_literal_attr_fails(void **state)
235{
236 assert_attr_expression(EXPR_SOURCE_LITERAL_ATTR_FAILS,
238}
239
240#define EXPR_SOURCE_PARAM_MISSING \
241 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
242 PCMK_XA_ATTRIBUTE "='foo' " \
243 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
244 PCMK_XA_VALUE "='not-a-param' " \
245 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_PARAM "' />"
246
247static void
248source_params_missing(void **state)
249{
250 assert_attr_expression(EXPR_SOURCE_PARAM_MISSING, pcmk_rc_op_unsatisfied);
251}
252
253#define EXPR_SOURCE_PARAM_PASSES \
254 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
255 PCMK_XA_ATTRIBUTE "='foo' " \
256 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
257 PCMK_XA_VALUE "='foo-param' " \
258 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_PARAM "' />"
259
260static void
261source_params_passes(void **state)
262{
263 assert_attr_expression(EXPR_SOURCE_PARAM_PASSES, pcmk_rc_ok);
264}
265
266#define EXPR_SOURCE_PARAM_FAILS \
267 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
268 PCMK_XA_ATTRIBUTE "='foo' " \
269 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
270 PCMK_XA_VALUE "='myparam' " \
271 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_PARAM "' />"
272
273static void
274source_params_fails(void **state)
275{
276 assert_attr_expression(EXPR_SOURCE_PARAM_FAILS, pcmk_rc_op_unsatisfied);
277}
278
279#define EXPR_SOURCE_META_MISSING \
280 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
281 PCMK_XA_ATTRIBUTE "='foo' " \
282 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
283 PCMK_XA_VALUE "='not-a-meta' " \
284 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_META "' />"
285
286static void
287source_meta_missing(void **state)
288{
289 assert_attr_expression(EXPR_SOURCE_META_MISSING, pcmk_rc_op_unsatisfied);
290}
291
292#define EXPR_SOURCE_META_PASSES \
293 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
294 PCMK_XA_ATTRIBUTE "='foo' " \
295 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
296 PCMK_XA_VALUE "='foo-meta' " \
297 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_META "' />"
298
299static void
300source_meta_passes(void **state)
301{
302 assert_attr_expression(EXPR_SOURCE_META_PASSES, pcmk_rc_ok);
303}
304
305#define EXPR_SOURCE_META_FAILS \
306 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
307 PCMK_XA_ATTRIBUTE "='foo' " \
308 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
309 PCMK_XA_VALUE "='mymeta' " \
310 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_META "' />"
311
312static void
313source_meta_fails(void **state)
314{
315 assert_attr_expression(EXPR_SOURCE_META_FAILS, pcmk_rc_op_unsatisfied);
316}
317
318
319/*
320 * Test PCMK_XA_TYPE
321 */
322
323#define EXPR_TYPE_DEFAULT_NUMBER \
324 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
325 PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
326 PCMK_XA_ATTRIBUTE "='num' " \
327 PCMK_XA_VALUE "='2.5' />"
328
329static void
330type_default_number(void **state)
331{
332 // Defaults to number for "gt" if either value contains a decimal point
333 assert_attr_expression(EXPR_TYPE_DEFAULT_NUMBER, pcmk_rc_ok);
334}
335
336#define EXPR_TYPE_DEFAULT_INT \
337 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
338 PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
339 PCMK_XA_ATTRIBUTE "='num' " \
340 PCMK_XA_VALUE "='2' />"
341
342static void
343type_default_int(void **state)
344{
345 // Defaults to integer for "gt" if neither value contains a decimal point
346 assert_attr_expression(EXPR_TYPE_DEFAULT_INT, pcmk_rc_ok);
347}
348
349#define EXPR_TYPE_INVALID \
350 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
351 PCMK_XA_TYPE "='not-a-value' " \
352 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
353 PCMK_XA_ATTRIBUTE "='foo' " \
354 PCMK_XA_VALUE "='bar' />"
355
356static void
357type_invalid(void **state)
358{
359 assert_attr_expression(EXPR_TYPE_INVALID, pcmk_rc_unpack_error);
360}
361
362#define EXPR_TYPE_STRING_PASSES \
363 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
364 PCMK_XA_TYPE "='" PCMK_VALUE_STRING "' " \
365 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
366 PCMK_XA_ATTRIBUTE "='foo' " \
367 PCMK_XA_VALUE "='bar' />"
368
369static void
370type_string_passes(void **state)
371{
372 assert_attr_expression(EXPR_TYPE_STRING_PASSES, pcmk_rc_ok);
373}
374
375#define EXPR_TYPE_STRING_FAILS \
376 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
377 PCMK_XA_TYPE "='" PCMK_VALUE_STRING "' " \
378 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
379 PCMK_XA_ATTRIBUTE "='foo' " \
380 PCMK_XA_VALUE "='bat' />"
381
382static void
383type_string_fails(void **state)
384{
385 assert_attr_expression(EXPR_TYPE_STRING_FAILS, pcmk_rc_op_unsatisfied);
386}
387
388#define EXPR_TYPE_INTEGER_PASSES \
389 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
390 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
391 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
392 PCMK_XA_ATTRIBUTE "='num' " \
393 PCMK_XA_VALUE "='10' />"
394
395static void
396type_integer_passes(void **state)
397{
398 assert_attr_expression(EXPR_TYPE_INTEGER_PASSES, pcmk_rc_ok);
399}
400
401#define EXPR_TYPE_INTEGER_FAILS \
402 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
403 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
404 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
405 PCMK_XA_ATTRIBUTE "='num' " \
406 PCMK_XA_VALUE "='11' />"
407
408static void
409type_integer_fails(void **state)
410{
411 assert_attr_expression(EXPR_TYPE_INTEGER_FAILS, pcmk_rc_op_unsatisfied);
412}
413
414#define EXPR_TYPE_INTEGER_TRUNCATION \
415 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
416 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
417 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
418 PCMK_XA_ATTRIBUTE "='num' " \
419 PCMK_XA_VALUE "='10.5' />"
420
421static void
422type_integer_truncation(void **state)
423{
424 assert_attr_expression(EXPR_TYPE_INTEGER_TRUNCATION, pcmk_rc_ok);
425}
426
427#define EXPR_TYPE_NUMBER_PASSES \
428 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
429 PCMK_XA_TYPE "='" PCMK_VALUE_NUMBER "' " \
430 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
431 PCMK_XA_ATTRIBUTE "='num' " \
432 PCMK_XA_VALUE "='10.0' />"
433
434static void
435type_number_passes(void **state)
436{
437 assert_attr_expression(EXPR_TYPE_NUMBER_PASSES, pcmk_rc_ok);
438}
439
440#define EXPR_TYPE_NUMBER_FAILS \
441 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
442 PCMK_XA_TYPE "='" PCMK_VALUE_NUMBER "' " \
443 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
444 PCMK_XA_ATTRIBUTE "='num' " \
445 PCMK_XA_VALUE "='10.1' />"
446
447static void
448type_number_fails(void **state)
449{
450 assert_attr_expression(EXPR_TYPE_NUMBER_FAILS, pcmk_rc_op_unsatisfied);
451}
452
453#define EXPR_TYPE_VERSION_PASSES \
454 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
455 PCMK_XA_TYPE "='" PCMK_VALUE_VERSION "' " \
456 PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
457 PCMK_XA_ATTRIBUTE "='ver' " \
458 PCMK_XA_VALUE "='3.4.9' />"
459
460static void
461type_version_passes(void **state)
462{
463 assert_attr_expression(EXPR_TYPE_VERSION_PASSES, pcmk_rc_ok);
464}
465
466#define EXPR_TYPE_VERSION_EQUALITY \
467 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
468 PCMK_XA_TYPE "='" PCMK_VALUE_VERSION "' " \
469 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
470 PCMK_XA_ATTRIBUTE "='ver' " \
471 PCMK_XA_VALUE "='3.5' />"
472
473static void
474type_version_equality(void **state)
475{
476 assert_attr_expression(EXPR_TYPE_VERSION_EQUALITY, pcmk_rc_ok);
477}
478
479#define EXPR_TYPE_VERSION_FAILS \
480 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
481 PCMK_XA_TYPE "='" PCMK_VALUE_VERSION "' " \
482 PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
483 PCMK_XA_ATTRIBUTE "='ver' " \
484 PCMK_XA_VALUE "='4.0' />"
485
486static void
487type_version_fails(void **state)
488{
489 assert_attr_expression(EXPR_TYPE_VERSION_FAILS, pcmk_rc_before_range);
490}
491
492/*
493 * Test PCMK_XA_OPERATION
494 */
495
496#define EXPR_OP_MISSING \
497 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
498 PCMK_XA_ATTRIBUTE "='foo' " \
499 PCMK_XA_VALUE "='bar' />"
500
501static void
502op_missing(void **state)
503{
504 assert_attr_expression(EXPR_OP_MISSING, pcmk_rc_unpack_error);
505}
506
507#define EXPR_OP_INVALID \
508 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
509 PCMK_XA_ATTRIBUTE "='foo' " \
510 PCMK_XA_OPERATION "='not-an-operation' " \
511 PCMK_XA_VALUE "='bar' />"
512
513static void
514op_invalid(void **state)
515{
516 assert_attr_expression(EXPR_OP_INVALID, pcmk_rc_unpack_error);
517}
518
519#define EXPR_OP_LT_PASSES \
520 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
521 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
522 PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' " \
523 PCMK_XA_ATTRIBUTE "='num' " \
524 PCMK_XA_VALUE "='20' />"
525
526static void
527op_lt_passes(void **state)
528{
529 assert_attr_expression(EXPR_OP_LT_PASSES, pcmk_rc_ok);
530}
531
532#define EXPR_OP_LT_FAILS \
533 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
534 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
535 PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' " \
536 PCMK_XA_ATTRIBUTE "='num' " \
537 PCMK_XA_VALUE "='2' />"
538
539static void
540op_lt_fails(void **state)
541{
542 assert_attr_expression(EXPR_OP_LT_FAILS, pcmk_rc_after_range);
543}
544
545#define EXPR_OP_GT_PASSES \
546 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
547 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
548 PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
549 PCMK_XA_ATTRIBUTE "='num' " \
550 PCMK_XA_VALUE "='2' />"
551
552static void
553op_gt_passes(void **state)
554{
555 assert_attr_expression(EXPR_OP_GT_PASSES, pcmk_rc_ok);
556}
557
558#define EXPR_OP_GT_FAILS \
559 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
560 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
561 PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
562 PCMK_XA_ATTRIBUTE "='num' " \
563 PCMK_XA_VALUE "='20' />"
564
565static void
566op_gt_fails(void **state)
567{
568 assert_attr_expression(EXPR_OP_GT_FAILS, pcmk_rc_before_range);
569}
570
571#define EXPR_OP_LTE_LT_PASSES \
572 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
573 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
574 PCMK_XA_OPERATION "='" PCMK_VALUE_LTE "' " \
575 PCMK_XA_ATTRIBUTE "='num' " \
576 PCMK_XA_VALUE "='20' />"
577
578static void
579op_lte_lt_passes(void **state)
580{
581 assert_attr_expression(EXPR_OP_LTE_LT_PASSES, pcmk_rc_ok);
582}
583
584#define EXPR_OP_LTE_EQ_PASSES \
585 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
586 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
587 PCMK_XA_OPERATION "='" PCMK_VALUE_LTE "' " \
588 PCMK_XA_ATTRIBUTE "='num' " \
589 PCMK_XA_VALUE "='10' />"
590
591static void
592op_lte_eq_passes(void **state)
593{
594 assert_attr_expression(EXPR_OP_LTE_EQ_PASSES, pcmk_rc_ok);
595}
596
597#define EXPR_OP_LTE_FAILS \
598 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
599 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
600 PCMK_XA_OPERATION "='" PCMK_VALUE_LTE "' " \
601 PCMK_XA_ATTRIBUTE "='num' " \
602 PCMK_XA_VALUE "='9' />"
603
604static void
605op_lte_fails(void **state)
606{
607 assert_attr_expression(EXPR_OP_LTE_FAILS, pcmk_rc_after_range);
608}
609
610#define EXPR_OP_GTE_GT_PASSES \
611 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
612 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
613 PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
614 PCMK_XA_ATTRIBUTE "='num' " \
615 PCMK_XA_VALUE "='1' />"
616
617static void
618op_gte_gt_passes(void **state)
619{
620 assert_attr_expression(EXPR_OP_GTE_GT_PASSES, pcmk_rc_ok);
621}
622
623#define EXPR_OP_GTE_EQ_PASSES \
624 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
625 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
626 PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
627 PCMK_XA_ATTRIBUTE "='num' " \
628 PCMK_XA_VALUE "='10' />"
629
630static void
631op_gte_eq_passes(void **state)
632{
633 assert_attr_expression(EXPR_OP_GTE_EQ_PASSES, pcmk_rc_ok);
634}
635
636#define EXPR_OP_GTE_FAILS \
637 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
638 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
639 PCMK_XA_OPERATION "='" PCMK_VALUE_GTE "' " \
640 PCMK_XA_ATTRIBUTE "='num' " \
641 PCMK_XA_VALUE "='11' />"
642
643static void
644op_gte_fails(void **state)
645{
646 assert_attr_expression(EXPR_OP_GTE_FAILS, pcmk_rc_before_range);
647}
648
649// This also tests that string is used if values aren't parseable as numbers
650#define EXPR_OP_EQ_PASSES \
651 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
652 PCMK_XA_TYPE "='" PCMK_VALUE_NUMBER "' " \
653 PCMK_XA_ATTRIBUTE "='foo' " \
654 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
655 PCMK_XA_VALUE "='bar' " \
656 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
657
658static void
659op_eq_passes(void **state)
660{
661 assert_attr_expression(EXPR_OP_EQ_PASSES, pcmk_rc_ok);
662}
663
664#define EXPR_EQ_EMPTY_VS_EMPTY_PASSES \
665 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
666 PCMK_XA_ATTRIBUTE "='empty' " \
667 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
668 PCMK_XA_VALUE "='' />"
669
670static void
671op_eq_empty_vs_empty_passes(void **state)
672{
673 assert_attr_expression(EXPR_EQ_EMPTY_VS_EMPTY_PASSES, pcmk_rc_ok);
674}
675
676#define EXPR_OP_EQ_FAILS \
677 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
678 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
679 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
680 PCMK_XA_ATTRIBUTE "='num' " \
681 PCMK_XA_VALUE "='bar' />"
682
683static void
684op_eq_fails(void **state)
685{
686 assert_attr_expression(EXPR_OP_EQ_FAILS, pcmk_rc_op_unsatisfied);
687}
688
689#define EXPR_EQ_UNDEFINED_VS_EMPTY_FAILS \
690 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
691 PCMK_XA_ATTRIBUTE "='boo' " \
692 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' " \
693 PCMK_XA_VALUE "='' />"
694
695static void
696op_eq_undefined_vs_empty_fails(void **state)
697{
698 assert_attr_expression(EXPR_EQ_UNDEFINED_VS_EMPTY_FAILS,
700}
701
702#define EXPR_OP_NE_PASSES \
703 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
704 PCMK_XA_TYPE "='" PCMK_VALUE_STRING "' " \
705 PCMK_XA_ATTRIBUTE "='foo' " \
706 PCMK_XA_OPERATION "='" PCMK_VALUE_NE "' " \
707 PCMK_XA_VALUE "='bat' " \
708 PCMK_XA_VALUE_SOURCE "='" PCMK_VALUE_LITERAL "' />"
709
710static void
711op_ne_passes(void **state)
712{
713 assert_attr_expression(EXPR_OP_NE_PASSES, pcmk_rc_ok);
714}
715
716#define EXPR_OP_NE_FAILS \
717 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
718 PCMK_XA_TYPE "='" PCMK_VALUE_INTEGER "' " \
719 PCMK_XA_OPERATION "='" PCMK_VALUE_NE "' " \
720 PCMK_XA_ATTRIBUTE "='num' " \
721 PCMK_XA_VALUE "='10' />"
722
723static void
724op_ne_fails(void **state)
725{
726 assert_attr_expression(EXPR_OP_NE_FAILS, pcmk_rc_op_unsatisfied);
727}
728
729#define EXPR_OP_DEFINED_PASSES \
730 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
731 PCMK_XA_ATTRIBUTE "='foo' " \
732 PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
733
734static void
735op_defined_passes(void **state)
736{
737 assert_attr_expression(EXPR_OP_DEFINED_PASSES, pcmk_rc_ok);
738}
739
740#define EXPR_OP_DEFINED_EMPTY_PASSES \
741 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
742 PCMK_XA_ATTRIBUTE "='empty' " \
743 PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
744
745static void
746op_defined_empty_passes(void **state)
747{
748 assert_attr_expression(EXPR_OP_DEFINED_EMPTY_PASSES, pcmk_rc_ok);
749}
750
751#define EXPR_OP_DEFINED_FAILS \
752 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
753 PCMK_XA_ATTRIBUTE "='boo' " \
754 PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
755
756static void
757op_defined_fails(void **state)
758{
759 assert_attr_expression(EXPR_OP_DEFINED_FAILS, pcmk_rc_op_unsatisfied);
760}
761
762#define EXPR_OP_DEFINED_WITH_VALUE \
763 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
764 PCMK_XA_ATTRIBUTE "='foo' " \
765 PCMK_XA_VALUE "='bar' " \
766 PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
767
768static void
769op_defined_with_value(void **state)
770{
771 assert_attr_expression(EXPR_OP_DEFINED_WITH_VALUE, pcmk_rc_unpack_error);
772}
773
774#define EXPR_OP_UNDEFINED_PASSES \
775 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
776 PCMK_XA_ATTRIBUTE "='boo' " \
777 PCMK_XA_OPERATION "='" PCMK_VALUE_NOT_DEFINED "' />"
778
779static void
780op_undefined_passes(void **state)
781{
782 assert_attr_expression(EXPR_OP_UNDEFINED_PASSES, pcmk_rc_ok);
783}
784
785#define EXPR_OP_UNDEFINED_FAILS \
786 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
787 PCMK_XA_ATTRIBUTE "='foo' " \
788 PCMK_XA_OPERATION "='" PCMK_VALUE_NOT_DEFINED "' />"
789
790static void
791op_undefined_fails(void **state)
792{
793 assert_attr_expression(EXPR_OP_UNDEFINED_FAILS, pcmk_rc_op_unsatisfied);
794}
795
796#define EXPR_OP_UNDEFINED_EMPTY_FAILS \
797 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
798 PCMK_XA_ATTRIBUTE "='empty' " \
799 PCMK_XA_OPERATION "='" PCMK_VALUE_NOT_DEFINED "' />"
800
801static void
802op_undefined_empty_fails(void **state)
803{
804 assert_attr_expression(EXPR_OP_UNDEFINED_EMPTY_FAILS,
806}
807
808
809/*
810 * Test PCMK_XA_VALUE
811 */
812
813#define EXPR_VALUE_MISSING_DEFINED_OK \
814 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
815 PCMK_XA_ATTRIBUTE "='num' " \
816 PCMK_XA_OPERATION "='" PCMK_VALUE_DEFINED "' />"
817
818static void
819value_missing_defined_ok(void **state)
820{
821 assert_attr_expression(EXPR_VALUE_MISSING_DEFINED_OK, pcmk_rc_ok);
822}
823
824#define EXPR_VALUE_MISSING_EQ_FAILS \
825 "<" PCMK_XE_EXPRESSION " " PCMK_XA_ID "='e' " \
826 PCMK_XA_ATTRIBUTE "='not-an-attr' " \
827 PCMK_XA_OPERATION "='" PCMK_VALUE_EQ "' />"
828
829static void
830value_missing_eq_fails(void **state)
831{
832 assert_attr_expression(EXPR_VALUE_MISSING_EQ_FAILS, pcmk_rc_unpack_error);
833}
834
835
836#define expr_test(f) cmocka_unit_test_setup_teardown(f, setup, teardown)
837
839 cmocka_unit_test(null_invalid),
840 expr_test(id_missing),
841 expr_test(attr_missing),
842 expr_test(attr_with_submatch_passes),
843 expr_test(attr_with_submatch_fails),
844 expr_test(source_missing),
845 expr_test(source_invalid),
846 expr_test(source_literal_passes),
847 expr_test(source_literal_value_fails),
848 expr_test(source_literal_attr_fails),
849 expr_test(source_params_missing),
850 expr_test(source_params_passes),
851 expr_test(source_params_fails),
852 expr_test(source_meta_missing),
853 expr_test(source_meta_passes),
854 expr_test(source_meta_fails),
855 expr_test(type_default_number),
856 expr_test(type_default_int),
857 expr_test(type_invalid),
858 expr_test(type_string_passes),
859 expr_test(type_string_fails),
860 expr_test(type_integer_passes),
861 expr_test(type_integer_fails),
862 expr_test(type_integer_truncation),
863 expr_test(type_number_passes),
864 expr_test(type_number_fails),
865 expr_test(type_version_passes),
866 expr_test(type_version_equality),
867 expr_test(type_version_fails),
868 expr_test(op_missing),
869 expr_test(op_invalid),
870 expr_test(op_lt_passes),
871 expr_test(op_lt_fails),
872 expr_test(op_gt_passes),
873 expr_test(op_gt_fails),
874 expr_test(op_lte_lt_passes),
875 expr_test(op_lte_eq_passes),
876 expr_test(op_lte_fails),
877 expr_test(op_gte_gt_passes),
878 expr_test(op_gte_eq_passes),
879 expr_test(op_gte_fails),
880 expr_test(op_eq_passes),
881 expr_test(op_eq_empty_vs_empty_passes),
882 expr_test(op_eq_fails),
883 expr_test(op_eq_undefined_vs_empty_fails),
884 expr_test(op_ne_passes),
885 expr_test(op_ne_fails),
886 expr_test(op_defined_passes),
887 expr_test(op_defined_empty_passes),
888 expr_test(op_defined_fails),
889 expr_test(op_defined_with_value),
890 expr_test(op_undefined_passes),
891 expr_test(op_undefined_fails),
892 expr_test(op_undefined_empty_fails),
893 expr_test(value_missing_defined_ok),
894 expr_test(value_missing_eq_fails))
G_GNUC_INTERNAL int pcmk__evaluate_attr_expression(const xmlNode *expression, const pcmk_rule_input_t *rule_input)
Definition rules.c:958
#define EXPR_ATTR_SUBMATCH_PASSES
#define EXPR_SOURCE_LITERAL_VALUE_FAILS
#define EXPR_OP_UNDEFINED_EMPTY_FAILS
#define EXPR_SOURCE_PARAM_MISSING
#define EXPR_OP_DEFINED_EMPTY_PASSES
#define EXPR_VALUE_MISSING_EQ_FAILS
#define EXPR_VALUE_MISSING_DEFINED_OK
#define EXPR_EQ_EMPTY_VS_EMPTY_PASSES
#define EXPR_TYPE_INTEGER_TRUNCATION
#define EXPR_EQ_UNDEFINED_VS_EMPTY_FAILS
#define EXPR_SOURCE_LITERAL_ATTR_FAILS
#define EXPR_OP_DEFINED_WITH_VALUE
#define EXPR_SOURCE_LITERAL_PASSES
#define EXPR_TYPE_VERSION_EQUALITY
@ pcmk_rc_before_range
Definition results.h:131
@ pcmk_rc_op_unsatisfied
Definition results.h:133
@ pcmk_rc_ok
Definition results.h:159
@ pcmk_rc_after_range
Definition results.h:129
@ pcmk_rc_unpack_error
Definition results.h:122
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:703
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
GHashTable * node_attrs
Definition rules.h:77
GHashTable * rsc_meta
Definition rules.h:93
GHashTable * rsc_params
Definition rules.h:86
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