pacemaker  2.1.8-3980678f03
Scalable High-Availability cluster resource manager
pcmk__evaluate_date_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 
34 static void
35 assert_date_expression(const xmlNode *xml, const char *now_s,
36  const char *next_change_s, const char *reference_s,
37  int reference_rc)
38 {
39  crm_time_t *now = NULL;
40  crm_time_t *next_change = NULL;
41  bool check_next_change = (next_change_s != NULL) && (reference_s != NULL);
42 
43  if (check_next_change) {
44  next_change = crm_time_new(next_change_s);
45  }
46 
47  now = crm_time_new(now_s);
48  assert_int_equal(pcmk__evaluate_date_expression(xml, now, next_change),
49  reference_rc);
50  crm_time_free(now);
51 
52  if (check_next_change) {
53  crm_time_t *reference = crm_time_new(reference_s);
54 
55  assert_int_equal(crm_time_compare(next_change, reference), 0);
56  crm_time_free(reference);
57  crm_time_free(next_change);
58  }
59 }
60 
61 #define EXPR_LT_VALID \
62  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
63  PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' " \
64  PCMK_XA_END "='2024-02-01 15:00:00' />"
65 
66 static void
67 null_invalid(void **state)
68 {
69  xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_VALID);
70  crm_time_t *t = crm_time_new("2024-02-01");
71 
72  assert_int_equal(pcmk__evaluate_date_expression(NULL, NULL, NULL), EINVAL);
73  assert_int_equal(pcmk__evaluate_date_expression(xml, NULL, NULL), EINVAL);
74  assert_int_equal(pcmk__evaluate_date_expression(NULL, t, NULL), EINVAL);
75 
76  crm_time_free(t);
77  free_xml(xml);
78 }
79 
80 static void
81 null_next_change_ok(void **state)
82 {
83  xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_VALID);
84 
85  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_within_range);
86  free_xml(xml);
87 }
88 
89 #define EXPR_ID_MISSING \
90  "<" PCMK_XE_DATE_EXPRESSION " " \
91  PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' " \
92  PCMK_XA_END "='2024-02-01 15:00:00' />"
93 
94 static void
95 id_missing(void **state)
96 {
97  // Currently acceptable
98  xmlNodePtr xml = pcmk__xml_parse(EXPR_ID_MISSING);
99 
100  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_within_range);
101  free_xml(xml);
102 }
103 
104 #define EXPR_OP_INVALID \
105  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
106  PCMK_XA_OPERATION "='not-a-choice' />"
107 
108 static void
109 op_invalid(void **state)
110 {
111  xmlNodePtr xml = pcmk__xml_parse(EXPR_OP_INVALID);
112 
113  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
114  free_xml(xml);
115 }
116 
117 #define EXPR_LT_MISSING_END \
118  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
119  PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' />"
120 
121 static void
122 lt_missing_end(void **state)
123 {
124  xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_MISSING_END);
125 
126  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
127  free_xml(xml);
128 }
129 
130 #define EXPR_LT_INVALID_END \
131  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
132  PCMK_XA_OPERATION "='" PCMK_VALUE_LT "' " \
133  PCMK_XA_END "='not-a-datetime' />"
134 
135 static void
136 lt_invalid_end(void **state)
137 {
138  xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_INVALID_END);
139 
140  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
141  free_xml(xml);
142 }
143 
144 static void
145 lt_valid(void **state)
146 {
147  xmlNodePtr xml = pcmk__xml_parse(EXPR_LT_VALID);
148 
149  // Now and next change are both before end
150  assert_date_expression(xml, "2023-01-01 05:00:00", "2024-02-01 10:00:00",
151  "2024-02-01 10:00:00", pcmk_rc_within_range);
152 
153  // Now is before end, next change is after end
154  assert_date_expression(xml, "2024-02-01 14:59:59", "2024-02-01 18:00:00",
155  "2024-02-01 15:00:00", pcmk_rc_within_range);
156 
157  // Now is equal to end, next change is after end
158  assert_date_expression(xml, "2024-02-01 15:00:00", "2024-02-01 20:00:00",
159  "2024-02-01 20:00:00", pcmk_rc_after_range);
160 
161  // Now and next change are both after end
162  assert_date_expression(xml, "2024-03-01 12:00:00", "2024-02-01 20:00:00",
163  "2024-02-01 20:00:00", pcmk_rc_after_range);
164 
165  free_xml(xml);
166 }
167 
168 #define EXPR_GT_MISSING_START \
169  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
170  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' />"
171 
172 static void
173 gt_missing_start(void **state)
174 {
175  xmlNodePtr xml = pcmk__xml_parse(EXPR_GT_MISSING_START);
176 
177  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
178  free_xml(xml);
179 }
180 
181 #define EXPR_GT_INVALID_START \
182  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
183  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
184  PCMK_XA_START "='not-a-datetime' />"
185 
186 static void
187 gt_invalid_start(void **state)
188 {
189  xmlNodePtr xml = pcmk__xml_parse(EXPR_GT_INVALID_START);
190 
191  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
192  free_xml(xml);
193 }
194 
195 #define EXPR_GT_VALID \
196  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
197  PCMK_XA_OPERATION "='" PCMK_VALUE_GT "' " \
198  PCMK_XA_START "='2024-02-01 12:00:00' />"
199 
200 static void
201 gt_valid(void **state)
202 {
203  xmlNodePtr xml = pcmk__xml_parse(EXPR_GT_VALID);
204 
205  // Now and next change are both before start
206  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
207  "2024-01-01 11:00:00", pcmk_rc_before_range);
208 
209  // Now is before start, next change is after start
210  assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00",
211  "2024-02-01 12:00:01", pcmk_rc_before_range);
212 
213  // Now is equal to start, next change is after start
214  assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 18:00:00",
215  "2024-02-01 12:00:01", pcmk_rc_before_range);
216 
217  // Now is one second after start, next change is after start
218  assert_date_expression(xml, "2024-02-01 12:00:01", "2024-02-01 18:00:00",
219  "2024-02-01 18:00:00", pcmk_rc_within_range);
220 
221  // t is after start, next change is after start
222  assert_date_expression(xml, "2024-03-01 05:03:11", "2024-04-04 04:04:04",
223  "2024-04-04 04:04:04", pcmk_rc_within_range);
224 
225  free_xml(xml);
226 }
227 
228 #define EXPR_RANGE_MISSING \
229  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
230  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' />"
231 
232 static void
233 range_missing(void **state)
234 {
235  xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_MISSING);
236  crm_time_t *t = crm_time_new("2024-01-01");
237 
238  assert_int_equal(pcmk__evaluate_date_expression(xml, t, NULL),
240 
241  crm_time_free(t);
242  free_xml(xml);
243 }
244 
245 #define EXPR_RANGE_INVALID_START_INVALID_END \
246  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
247  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
248  PCMK_XA_START "='not-a-date' " \
249  PCMK_XA_END "='not-a-date' />"
250 
251 static void
252 range_invalid_start_invalid_end(void **state)
253 {
255 
256  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
257  free_xml(xml);
258 }
259 
260 #define EXPR_RANGE_INVALID_START_ONLY \
261  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
262  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
263  PCMK_XA_START "='not-a-date' />"
264 
265 static void
266 range_invalid_start_only(void **state)
267 {
269 
270  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
271  free_xml(xml);
272 }
273 
274 #define EXPR_RANGE_VALID_START_ONLY \
275  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
276  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
277  PCMK_XA_START "='2024-02-01 12:00:00' />"
278 
279 static void
280 range_valid_start_only(void **state)
281 {
283 
284  // Now and next change are before start
285  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
286  "2024-01-01 11:00:00", pcmk_rc_before_range);
287 
288  // Now is before start, next change is after start
289  assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00",
290  "2024-02-01 12:00:00", pcmk_rc_before_range);
291 
292  // Now is equal to start, next change is after start
293  assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 18:00:00",
294  "2024-02-01 18:00:00", pcmk_rc_within_range);
295 
296  // Now and next change are after start
297  assert_date_expression(xml, "2024-03-01 05:03:11", "2024-04-04 04:04:04",
298  "2024-04-04 04:04:04", pcmk_rc_within_range);
299 
300  free_xml(xml);
301 }
302 
303 #define EXPR_RANGE_INVALID_END_ONLY \
304  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
305  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
306  PCMK_XA_END "='not-a-date' />"
307 
308 static void
309 range_invalid_end_only(void **state)
310 {
312 
313  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
314  free_xml(xml);
315 }
316 
317 #define EXPR_RANGE_VALID_END_ONLY \
318  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
319  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
320  PCMK_XA_END "='2024-02-01 15:00:00' />"
321 
322 static void
323 range_valid_end_only(void **state)
324 {
325  xmlNodePtr xml = pcmk__xml_parse(EXPR_RANGE_VALID_END_ONLY);
326 
327  // Now and next change are before end
328  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
329  "2024-01-01 11:00:00", pcmk_rc_within_range);
330 
331  // Now is before end, next change is after end
332  assert_date_expression(xml, "2024-02-01 14:59:59", "2024-02-01 18:00:00",
333  "2024-02-01 15:00:01", pcmk_rc_within_range);
334 
335  // Now is equal to end, next change is after end
336  assert_date_expression(xml, "2024-02-01 15:00:00", "2024-02-01 18:00:00",
337  "2024-02-01 15:00:01", pcmk_rc_within_range);
338 
339  // Now and next change are after end
340  assert_date_expression(xml, "2024-02-01 15:00:01", "2024-04-04 04:04:04",
341  "2024-04-04 04:04:04", pcmk_rc_after_range);
342 
343  free_xml(xml);
344 }
345 
346 #define EXPR_RANGE_VALID_START_INVALID_END \
347  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
348  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
349  PCMK_XA_START "='2024-02-01 12:00:00' " \
350  PCMK_XA_END "='not-a-date' />"
351 
352 static void
353 range_valid_start_invalid_end(void **state)
354 {
355  // Currently treated same as start without end
357 
358  // Now and next change are before start
359  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
360  "2024-01-01 11:00:00", pcmk_rc_before_range);
361 
362  // Now is before start, next change is after start
363  assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00",
364  "2024-02-01 12:00:00", pcmk_rc_before_range);
365 
366  // Now is equal to start, next change is after start
367  assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 18:00:00",
368  "2024-02-01 18:00:00", pcmk_rc_within_range);
369 
370  // Now and next change are after start
371  assert_date_expression(xml, "2024-03-01 05:03:11", "2024-04-04 04:04:04",
372  "2024-04-04 04:04:04", pcmk_rc_within_range);
373 
374  free_xml(xml);
375 }
376 
377 #define EXPR_RANGE_INVALID_START_VALID_END \
378  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
379  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
380  PCMK_XA_START "='not-a-date' " \
381  PCMK_XA_END "='2024-02-01 15:00:00' />"
382 
383 static void
384 range_invalid_start_valid_end(void **state)
385 {
386  // Currently treated same as end without start
388 
389  // Now and next change are before end
390  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
391  "2024-01-01 11:00:00", pcmk_rc_within_range);
392 
393  // Now is before end, next change is after end
394  assert_date_expression(xml, "2024-02-01 14:59:59", "2024-02-01 18:00:00",
395  "2024-02-01 15:00:01", pcmk_rc_within_range);
396 
397  // Now is equal to end, next change is after end
398  assert_date_expression(xml, "2024-02-01 15:00:00", "2024-02-01 18:00:00",
399  "2024-02-01 15:00:01", pcmk_rc_within_range);
400 
401  // Now and next change are after end
402  assert_date_expression(xml, "2024-02-01 15:00:01", "2024-04-04 04:04:04",
403  "2024-04-04 04:04:04", pcmk_rc_after_range);
404 
405  free_xml(xml);
406 }
407 
408 #define EXPR_RANGE_VALID_START_VALID_END \
409  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
410  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
411  PCMK_XA_START "='2024-02-01 12:00:00' " \
412  PCMK_XA_END "='2024-02-01 15:00:00' />"
413 
414 static void
415 range_valid_start_valid_end(void **state)
416 {
418 
419  // Now and next change are before start
420  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
421  "2024-01-01 11:00:00", pcmk_rc_before_range);
422 
423  // Now is before start, next change is between start and end
424  assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 14:00:00",
425  "2024-02-01 12:00:00", pcmk_rc_before_range);
426 
427  // Now is equal to start, next change is between start and end
428  assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00",
429  "2024-02-01 14:30:00", pcmk_rc_within_range);
430 
431  // Now is between start and end, next change is after end
432  assert_date_expression(xml, "2024-02-01 14:03:11", "2024-04-04 04:04:04",
433  "2024-02-01 15:00:01", pcmk_rc_within_range);
434 
435  // Now is equal to end, next change is after end
436  assert_date_expression(xml, "2024-02-01 15:00:00", "2028-04-04 04:04:04",
437  "2024-02-01 15:00:01", pcmk_rc_within_range);
438 
439  // Now and next change are after end
440  assert_date_expression(xml, "2024-02-01 15:00:01", "2028-04-04 04:04:04",
441  "2028-04-04 04:04:04", pcmk_rc_after_range);
442 
443  free_xml(xml);
444 }
445 
446 #define EXPR_RANGE_VALID_START_INVALID_DURATION \
447  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
448  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
449  PCMK_XA_START "='2024-02-01 12:00:00'>" \
450  "<" PCMK_XE_DURATION " " PCMK_XA_ID "='d' " \
451  PCMK_XA_HOURS "='not-a-number' />" \
452  "</" PCMK_XE_DATE_EXPRESSION ">"
453 
454 static void
455 range_valid_start_invalid_duration(void **state)
456 {
457  // Currently treated same as end equals start
459 
460  // Now and next change are before start
461  assert_date_expression(xml, "2024-02-01 04:30:05", "2024-01-01 11:00:00",
462  "2024-01-01 11:00:00", pcmk_rc_before_range);
463 
464  // Now is before start, next change is after start
465  assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 18:00:00",
466  "2024-02-01 12:00:00", pcmk_rc_before_range);
467 
468  // Now is equal to start, next change is after start
469  assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00",
470  "2024-02-01 12:00:01", pcmk_rc_within_range);
471 
472  // Now and next change are after start
473  assert_date_expression(xml, "2024-02-01 12:00:01", "2024-02-01 14:30:00",
474  "2024-02-01 14:30:00", pcmk_rc_after_range);
475 
476  free_xml(xml);
477 }
478 
479 #define EXPR_RANGE_VALID_START_VALID_DURATION \
480  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
481  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
482  PCMK_XA_START "='2024-02-01 12:00:00'>" \
483  "<" PCMK_XE_DURATION " " PCMK_XA_ID "='d' " \
484  PCMK_XA_HOURS "='3' />" \
485  "</" PCMK_XE_DATE_EXPRESSION ">"
486 
487 static void
488 range_valid_start_valid_duration(void **state)
489 {
491 
492  // Now and next change are before start
493  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
494  "2024-01-01 11:00:00", pcmk_rc_before_range);
495 
496  // Now is before start, next change is between start and end
497  assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 14:00:00",
498  "2024-02-01 12:00:00", pcmk_rc_before_range);
499 
500  // Now is equal to start, next change is between start and end
501  assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00",
502  "2024-02-01 14:30:00", pcmk_rc_within_range);
503 
504  // Now is between start and end, next change is after end
505  assert_date_expression(xml, "2024-02-01 14:03:11", "2024-04-04 04:04:04",
506  "2024-02-01 15:00:01", pcmk_rc_within_range);
507 
508  // Now is equal to end, next change is after end
509  assert_date_expression(xml, "2024-02-01 15:00:00", "2028-04-04 04:04:04",
510  "2024-02-01 15:00:01", pcmk_rc_within_range);
511 
512  // Now and next change are after end
513  assert_date_expression(xml, "2024-02-01 15:00:01", "2028-04-04 04:04:04",
514  "2028-04-04 04:04:04", pcmk_rc_after_range);
515 
516  free_xml(xml);
517 }
518 
519 #define EXPR_RANGE_VALID_START_DURATION_MISSING_ID \
520  "<" PCMK_XE_DATE_EXPRESSION " " \
521  PCMK_XA_OPERATION "='" PCMK_VALUE_IN_RANGE "' " \
522  PCMK_XA_START "='2024-02-01 12:00:00'>" \
523  "<" PCMK_XE_DURATION " " PCMK_XA_ID "='d' " \
524  PCMK_XA_HOURS "='3' />" \
525  "</" PCMK_XE_DATE_EXPRESSION ">"
526 
527 static void
528 range_valid_start_duration_missing_id(void **state)
529 {
530  // Currently acceptable
531  xmlNodePtr xml = NULL;
532 
534 
535  // Now and next change are before start
536  assert_date_expression(xml, "2024-01-01 04:30:05", "2024-01-01 11:00:00",
537  "2024-01-01 11:00:00", pcmk_rc_before_range);
538 
539  // Now is before start, next change is between start and end
540  assert_date_expression(xml, "2024-02-01 11:59:59", "2024-02-01 14:00:00",
541  "2024-02-01 12:00:00", pcmk_rc_before_range);
542 
543  // Now is equal to start, next change is between start and end
544  assert_date_expression(xml, "2024-02-01 12:00:00", "2024-02-01 14:30:00",
545  "2024-02-01 14:30:00", pcmk_rc_within_range);
546 
547  // Now is between start and end, next change is after end
548  assert_date_expression(xml, "2024-02-01 14:03:11", "2024-04-04 04:04:04",
549  "2024-02-01 15:00:01", pcmk_rc_within_range);
550 
551  // Now is equal to end, next change is after end
552  assert_date_expression(xml, "2024-02-01 15:00:00", "2028-04-04 04:04:04",
553  "2024-02-01 15:00:01", pcmk_rc_within_range);
554 
555  // Now and next change are after end
556  assert_date_expression(xml, "2024-02-01 15:00:01", "2028-04-04 04:04:04",
557  "2028-04-04 04:04:04", pcmk_rc_after_range);
558 
559  free_xml(xml);
560 }
561 
562 #define EXPR_SPEC_MISSING \
563  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
564  PCMK_XA_OPERATION "='" PCMK_VALUE_DATE_SPEC "' />"
565 
566 static void
567 spec_missing(void **state)
568 {
569  xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_MISSING);
570 
571  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_undetermined);
572  free_xml(xml);
573 }
574 
575 #define EXPR_SPEC_INVALID \
576  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
577  PCMK_XA_OPERATION "='" PCMK_VALUE_DATE_SPEC "'>" \
578  "<" PCMK_XE_DATE_SPEC " " PCMK_XA_ID "='s' " \
579  PCMK_XA_MONTHS "='not-a-number'/>" \
580  "</" PCMK_XE_DATE_EXPRESSION ">"
581 
582 static void
583 spec_invalid(void **state)
584 {
585  // Currently treated as date_spec with no ranges (which passes)
586  xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_INVALID);
587 
588  assert_date_expression(xml, "2024-01-01", NULL, NULL, pcmk_rc_ok);
589  free_xml(xml);
590 }
591 
592 #define EXPR_SPEC_VALID \
593  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
594  PCMK_XA_OPERATION "='" PCMK_VALUE_DATE_SPEC "'>" \
595  "<" PCMK_XE_DATE_SPEC " " PCMK_XA_ID "='s' " \
596  PCMK_XA_MONTHS "='2'/>" \
597  "</" PCMK_XE_DATE_EXPRESSION ">"
598 
599 static void
600 spec_valid(void **state)
601 {
602  // date_spec does not currently support next_change
603  xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_VALID);
604 
605  // Now is just before spec start
606  assert_date_expression(xml, "2024-01-01 23:59:59", NULL, NULL,
608 
609  // Now matches spec start
610  assert_date_expression(xml, "2024-02-01 00:00:00", NULL, NULL, pcmk_rc_ok);
611 
612  // Now is within spec range
613  assert_date_expression(xml, "2024-02-22 22:22:22", NULL, NULL, pcmk_rc_ok);
614 
615  // Now matches spec end
616  assert_date_expression(xml, "2024-02-29 23:59:59", NULL, NULL, pcmk_rc_ok);
617 
618  // Now is just past spec end
619  assert_date_expression(xml, "2024-03-01 00:00:00", NULL, NULL,
621 
622  free_xml(xml);
623 }
624 
625 #define EXPR_SPEC_MISSING_ID \
626  "<" PCMK_XE_DATE_EXPRESSION " " PCMK_XA_ID "='e' " \
627  PCMK_XA_OPERATION "='" PCMK_VALUE_DATE_SPEC "'>" \
628  "<" PCMK_XE_DATE_SPEC " " \
629  PCMK_XA_MONTHS "='2'/>" \
630  "</" PCMK_XE_DATE_EXPRESSION ">"
631 
632 static void
633 spec_missing_id(void **state)
634 {
635  // Currently acceptable; date_spec does not currently support next_change
636  xmlNodePtr xml = pcmk__xml_parse(EXPR_SPEC_MISSING_ID);
637 
638  // Now is just before spec start
639  assert_date_expression(xml, "2024-01-01 23:59:59", NULL, NULL,
641 
642  // Now matches spec start
643  assert_date_expression(xml, "2024-02-01 00:00:00", NULL, NULL, pcmk_rc_ok);
644 
645  // Now is within spec range
646  assert_date_expression(xml, "2024-02-22 22:22:22", NULL, NULL, pcmk_rc_ok);
647 
648  // Now matches spec end
649  assert_date_expression(xml, "2024-02-29 23:59:59", NULL, NULL, pcmk_rc_ok);
650 
651  // Now is just past spec end
652  assert_date_expression(xml, "2024-03-01 00:00:00", NULL, NULL,
654 
655  free_xml(xml);
656 }
657 
659  cmocka_unit_test(null_invalid),
660  cmocka_unit_test(null_next_change_ok),
661  cmocka_unit_test(id_missing),
662  cmocka_unit_test(op_invalid),
663  cmocka_unit_test(lt_missing_end),
664  cmocka_unit_test(lt_invalid_end),
665  cmocka_unit_test(lt_valid),
666  cmocka_unit_test(gt_missing_start),
667  cmocka_unit_test(gt_invalid_start),
668  cmocka_unit_test(gt_valid),
669  cmocka_unit_test(range_missing),
670  cmocka_unit_test(range_invalid_start_invalid_end),
671  cmocka_unit_test(range_invalid_start_only),
672  cmocka_unit_test(range_valid_start_only),
673  cmocka_unit_test(range_invalid_end_only),
674  cmocka_unit_test(range_valid_end_only),
675  cmocka_unit_test(range_valid_start_invalid_end),
676  cmocka_unit_test(range_invalid_start_valid_end),
677  cmocka_unit_test(range_valid_start_valid_end),
678  cmocka_unit_test(range_valid_start_invalid_duration),
679  cmocka_unit_test(range_valid_start_valid_duration),
680  cmocka_unit_test(range_valid_start_duration_missing_id),
681  cmocka_unit_test(spec_missing),
682  cmocka_unit_test(spec_invalid),
683  cmocka_unit_test(spec_valid),
684  cmocka_unit_test(spec_missing_id))
#define EXPR_RANGE_INVALID_START_VALID_END
struct crm_time_s crm_time_t
Definition: iso8601.h:32
#define PCMK__UNIT_TEST(group_setup, group_teardown,...)
#define EXPR_RANGE_VALID_START_DURATION_MISSING_ID
#define EXPR_RANGE_VALID_START_INVALID_END
int pcmk__xml_test_setup_group(void **state)
Definition: unittest.c:74
Wrappers for and extensions to libxml2.
#define EXPR_RANGE_VALID_START_VALID_DURATION
#define EXPR_RANGE_VALID_END_ONLY
void free_xml(xmlNode *child)
Definition: xml.c:867
xmlNode * pcmk__xml_parse(const char *input)
Definition: xml_io.c:244
int crm_time_compare(const crm_time_t *a, const crm_time_t *b)
Definition: iso8601.c:1689
#define EXPR_RANGE_VALID_START_VALID_END
#define EXPR_RANGE_VALID_START_INVALID_DURATION
#define EXPR_RANGE_INVALID_END_ONLY
#define EXPR_RANGE_INVALID_START_ONLY
#define EXPR_RANGE_VALID_START_ONLY
crm_time_t * crm_time_new(const char *string)
Definition: iso8601.c:112
int pcmk__evaluate_date_expression(const xmlNode *date_expression, const crm_time_t *now, crm_time_t *next_change)
Definition: rules.c:534
#define EXPR_RANGE_INVALID_START_INVALID_END
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:150