pacemaker 2.1.8-2.1.8
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
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
66 return 0;
67}
68
69static int
70teardown(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
85static void
86assert_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
107static void
108null_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
130static void
131id_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
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 // Currently treated as literal
204 assert_attr_expression(EXPR_SOURCE_INVALID, pcmk_rc_ok);
205}
206
207static void
208source_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
220static void
221source_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
234static void
235source_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
248static void
249source_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
261static void
262source_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
274static void
275source_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
287static void
288source_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
300static void
301source_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
313static void
314source_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
330static void
331type_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
343static void
344type_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
357static void
358type_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
370static void
371type_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
383static void
384type_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
396static void
397type_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
409static void
410type_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
422static void
423type_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
435static void
436type_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
448static void
449type_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
461static void
462type_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
474static void
475type_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
489static void
490op_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
501static void
502op_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
514static void
515op_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
527static void
528op_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
540static void
541op_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
553static void
554op_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
566static void
567op_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
579static void
580op_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
592static void
593op_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
605static void
606op_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
618static void
619op_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
631static void
632op_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
646static void
647op_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
659static void
660op_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
673static void
674op_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
686static void
687op_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
697static void
698op_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
708static void
709op_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
720static void
721op_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
732static void
733op_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
743static void
744op_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
759static void
760value_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
770static void
771value_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))
G_GNUC_INTERNAL int pcmk__evaluate_attr_expression(const xmlNode *expression, const pcmk_rule_input_t *rule_input)
Definition rules.c:1038
#define EXPR_ATTR_SUBMATCH_PASSES
#define EXPR_SOURCE_LITERAL_VALUE_FAILS
#define EXPR_SOURCE_PARAM_MISSING
#define EXPR_VALUE_MISSING_DEFINED_OK
#define EXPR_TYPE_INTEGER_TRUNCATION
#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:134
@ pcmk_rc_op_unsatisfied
Definition results.h:136
@ pcmk_rc_ok
Definition results.h:162
@ pcmk_rc_after_range
Definition results.h:132
@ pcmk_rc_unpack_error
Definition results.h:125
void pcmk__insert_dup(GHashTable *table, const char *name, const char *value)
Definition strings.c:701
GHashTable * pcmk__strkey_table(GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func)
Definition strings.c:683
Data used to evaluate a rule (any NULL items are ignored)
Definition rules.h:57
GHashTable * node_attrs
Operation interval that rule applies to.
Definition rules.h:77
GHashTable * rsc_meta
Definition rules.h:93
const char * rsc_id
Resource ID to compare against a location constraint's resource pattern.
Definition rules.h:96
GHashTable * rsc_params
Definition rules.h:86
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
int pcmk__xml_test_setup_group(void **state)
Definition unittest.c:74
Wrappers for and extensions to libxml2.
void free_xml(xmlNode *child)
Definition xml.c:867
xmlNode * pcmk__xml_parse(const char *input)
Definition xml_io.c:244