diff --git a/crm/pengine/regression.sh b/crm/pengine/regression.sh index b5fadbdda2..d80c874691 100755 --- a/crm/pengine/regression.sh +++ b/crm/pengine/regression.sh @@ -1,179 +1,181 @@ #!/bin/bash # Copyright (C) 2004 Andrew Beekhof # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This software is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # . regression.core.sh create_mode="true" echo Generating test outputs for these tests... #do_test bad7 echo "" echo Done. echo "" echo Performing the following tests... create_mode="false" do_test 594 "Bugzilla 594" do_test 662 "Bugzilla 662" do_test 696 "Bugzilla 696" do_test 726 "Bugzilla 726" do_test 735 "Bugzilla 735" do_test 764 "Bugzilla 764" do_test 797 "Bugzilla 797" echo "" +do_test date-1 "Dates" +echo "" do_test simple1 "Offline " do_test simple2 "Start " do_test simple3 "Start 2 " do_test simple4 "Start Failed" do_test simple6 "Stop Start " do_test simple7 "Shutdown " #do_test simple8 "Stonith " #do_test simple9 "Lower version" #do_test simple10 "Higher version" do_test simple11 "Priority (ne)" do_test simple12 "Priority (eq)" echo "" do_test rsc_dep1 "Must not " do_test rsc_dep3 "Must " do_test rsc_dep5 "Must not 3 " do_test rsc_dep7 "Must 3 " do_test rsc_dep10 "Must (but cant)" do_test rsc_dep2 "Must (running) " do_test rsc_dep8 "Must (running : alt) " do_test rsc_dep4 "Must (running + move)" echo "" do_test order1 "Order start 1 " do_test order2 "Order start 2 " do_test order3 "Order stop " do_test order4 "Order (multiple) " do_test order5 "Order (move) " do_test order6 "Order (move w/ restart) " #echo "" #do_test agent1 "version: lt (empty)" #do_test agent2 "version: eq " #do_test agent3 "version: gt " echo "" do_test attrs1 "string: eq (and) " do_test attrs2 "string: lt / gt (and)" do_test attrs3 "string: ne (or) " do_test attrs4 "string: exists " do_test attrs5 "string: not_exists " do_test attrs6 "is_dc: true " do_test attrs7 "is_dc: false " echo "" do_test mon-rsc-1 "Schedule Monitor - start" do_test mon-rsc-2 "Schedule Monitor - move " do_test mon-rsc-3 "Schedule Monitor - pending start " do_test mon-rsc-4 "Schedule Monitor - move/pending start" echo "" do_test rec-rsc-0 "Resource Recover - no start " do_test rec-rsc-1 "Resource Recover - start " do_test rec-rsc-2 "Resource Recover - monitor " do_test rec-rsc-3 "Resource Recover - stop - ignore" do_test rec-rsc-4 "Resource Recover - stop - block " do_test rec-rsc-5 "Resource Recover - stop - fence " do_test rec-rsc-6 "Resource Recover - multiple - restart" do_test rec-rsc-7 "Resource Recover - multiple - stop " do_test rec-rsc-8 "Resource Recover - multiple - block " echo "" do_test quorum-1 "No quorum - ignore" do_test quorum-2 "No quorum - freeze" do_test quorum-3 "No quorum - stop " do_test quorum-4 "No quorum - start anyway" do_test quorum-5 "No quorum - start anyway (group)" do_test quorum-6 "No quorum - start anyway (clone)" echo "" do_test rec-node-1 "Node Recover - Startup - no fence" do_test rec-node-2 "Node Recover - Startup - fence " do_test rec-node-3 "Node Recover - HA down - no fence" do_test rec-node-4 "Node Recover - HA down - fence " do_test rec-node-5 "Node Recover - CRM down - no fence" do_test rec-node-6 "Node Recover - CRM down - fence " do_test rec-node-7 "Node Recover - no quorum - ignore " do_test rec-node-8 "Node Recover - no quorum - freeze " do_test rec-node-9 "Node Recover - no quorum - stop " do_test rec-node-10 "Node Recover - no quorum - stop w/fence" echo "" do_test multi1 "Multiple Active (stop/start)" #echo "" #do_test complex1 "Complex " echo "" do_test group1 "Group " do_test group2 "Group + Native " do_test group3 "Group + Group " do_test group4 "Group + Native (nothing)" do_test group5 "Group + Native (move) " do_test group6 "Group + Group (move) " echo "" do_test inc0 "Incarnation start " do_test inc1 "Incarnation start order " do_test inc2 "Incarnation silent restart, stop, move " do_test inc3 "Inter-incarnation ordering, silent restart, stop, move" do_test inc4 "Inter-incarnation ordering, silent restart, stop, move (ordered)" do_test inc5 "Inter-incarnation ordering, silent restart, stop, move (restart 1)" do_test inc6 "Inter-incarnation ordering, silent restart, stop, move (restart 2) *" #do_test inc7 "Inter-incarnation ordering, silent restart, stop, move (ordered subset)" echo "" do_test managed-0 "Managed (reference)" do_test managed-1 "Not managed - down " do_test managed-2 "Not managed - up " echo "" do_test interleave-0 "Interleave (reference)" do_test interleave-1 "coloc - not interleaved" do_test interleave-2 "coloc - interleaved " do_test interleave-3 "coloc - interleaved (2)" echo "" do_test notify-0 "Notify reference" do_test notify-1 "Notify simple" do_test notify-2 "Notify simple, confirm" do_test notify-3 "Notify move, confirm" #do_test notify-2 "Notify - 764" echo "" do_test bad1 "Bad node " do_test bad2 "Bad rsc " do_test bad3 "No rsc class " do_test bad4 "Bad data " do_test bad5 "Bad data " do_test bad6 "Bad lrm_rsc " echo "" test_results diff --git a/crm/pengine/rules.c b/crm/pengine/rules.c index 05a499026c..bf3c431eff 100644 --- a/crm/pengine/rules.c +++ b/crm/pengine/rules.c @@ -1,380 +1,384 @@ -/* $Id: rules.c,v 1.9 2005/08/07 08:15:10 andrew Exp $ */ +/* $Id: rules.c,v 1.10 2005/08/10 18:03:37 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include enum expression_type { not_expr, nested_rule, attr_expr, loc_expr, time_expr }; enum expression_type find_expression_type(crm_data_t *expr); ha_time_t *parse_xml_duration(ha_time_t *start, crm_data_t *duration_spec); gboolean test_date_expression(crm_data_t *time_expr); gboolean cron_range_satisfied(ha_time_t *now, crm_data_t *cron_spec); gboolean test_attr_expression(crm_data_t *expr, GHashTable *hash); gboolean test_ruleset(crm_data_t *ruleset, node_t *node) { gboolean ruleset_default = TRUE; xml_child_iter( ruleset, rule, XML_TAG_RULE, ruleset_default = FALSE; if(test_rule(rule, node)) { return TRUE; } ); return ruleset_default; } gboolean test_rule(crm_data_t *rule, node_t *node) { gboolean test = TRUE; gboolean passed = TRUE; gboolean do_and = TRUE; const char *value = crm_element_value(rule, "boolean_op"); if(safe_str_eq(value, "or")) { do_and = FALSE; passed = FALSE; } crm_debug_2("Testing rule %s", ID(rule)); xml_child_iter( rule, expr, NULL, test = test_expression(expr, node); if(test && do_and == FALSE) { - crm_err("Expression %s/%s passed", ID(rule), ID(expr)); + crm_debug_3("Expression %s/%s passed", + ID(rule), ID(expr)); return TRUE; } else if(test == FALSE && do_and) { - crm_err("Expression %s/%s failed", ID(rule), ID(expr)); + crm_debug_3("Expression %s/%s failed", + ID(rule), ID(expr)); return FALSE; } ); - if(passed == FALSE) { - crm_err("Rule %s failed", ID(rule)); - } + crm_debug_2("Rule %s %s", ID(rule), passed?"passed":"failed"); return passed; } gboolean test_expression(crm_data_t *expr, node_t *node) { gboolean accept = FALSE; switch(find_expression_type(expr)) { case nested_rule: accept = test_rule(expr, node); break; case attr_expr: case loc_expr: accept = test_attr_expression( expr, node?node->details->attrs:NULL); break; case time_expr: accept = test_date_expression(expr); break; default: CRM_DEV_ASSERT(FALSE /* bad type */); accept = FALSE; } + crm_debug_2("Expression %s %s", ID(expr), accept?"passed":"failed"); return accept; } enum expression_type find_expression_type(crm_data_t *expr) { const char *tag = NULL; const char *attr = NULL; attr = crm_element_value(expr, XML_EXPR_ATTR_ATTRIBUTE); tag = crm_element_name(expr); if(safe_str_eq(tag, "date_expression")) { return time_expr; } else if(safe_str_eq(tag, XML_TAG_RULE)) { return nested_rule; } else if(safe_str_neq(tag, "expression")) { return not_expr; } else if(safe_str_eq(attr, "#uname") || safe_str_eq(attr, "#id")) { return loc_expr; } return attr_expr; } gboolean test_attr_expression(crm_data_t *expr, GHashTable *hash) { gboolean accept = FALSE; int cmp = 0; const char *h_val = NULL; const char *op = NULL; const char *type = NULL; const char *attr = NULL; const char *value = NULL; attr = crm_element_value(expr, XML_EXPR_ATTR_ATTRIBUTE); op = crm_element_value(expr, XML_EXPR_ATTR_OPERATION); value = crm_element_value(expr, XML_EXPR_ATTR_VALUE); type = crm_element_value(expr, XML_EXPR_ATTR_TYPE); if(attr == NULL || op == NULL) { pe_err("Invlaid attribute or operation in expression" " (\'%s\' \'%s\' \'%s\')", crm_str(attr), crm_str(op), crm_str(value)); return FALSE; } if(hash != NULL) { h_val = (const char*)g_hash_table_lookup(hash, attr); } if(value != NULL && h_val != NULL) { if(type == NULL || (safe_str_eq(type, "string"))) { cmp = strcmp(h_val, value); } else if(safe_str_eq(type, "number")) { float h_val_f = atof(h_val); float value_f = atof(value); if(h_val_f < value_f) { cmp = -1; } else if(h_val_f > value_f) { cmp = 1; } else { cmp = 0; } } else if(safe_str_eq(type, "version")) { cmp = compare_version(h_val, value); } } else if(value == NULL && h_val == NULL) { cmp = 0; } else if(value == NULL) { cmp = 1; } else { cmp = -1; } if(safe_str_eq(op, "defined")) { if(h_val != NULL) { accept = TRUE; } } else if(safe_str_eq(op, "not_defined")) { if(h_val == NULL) { accept = TRUE; } } else if(safe_str_eq(op, "eq")) { if((h_val == value) || cmp == 0) { accept = TRUE; } } else if(safe_str_eq(op, "ne")) { if((h_val == NULL && value != NULL) || (h_val != NULL && value == NULL) || cmp != 0) { accept = TRUE; } } else if(value == NULL || h_val == NULL) { /* the comparision is meaningless from this point on */ accept = FALSE; } else if(safe_str_eq(op, "lt")) { if(cmp < 0) { accept = TRUE; } } else if(safe_str_eq(op, "lte")) { if(cmp <= 0) { accept = TRUE; } } else if(safe_str_eq(op, "gt")) { if(cmp > 0) { accept = TRUE; } } else if(safe_str_eq(op, "gte")) { if(cmp >= 0) { accept = TRUE; } } return accept; } #define cron_check(xml_field, time_field) \ value = crm_element_value(cron_spec, xml_field); \ if(value != NULL) { \ decodeNVpair(value, '-', &value_low, &value_high); \ CRM_DEV_ASSERT(value_low != NULL); \ value_low_i = crm_atoi(value_low, "0"); \ value_high_i = crm_atoi(value_high, "-1"); \ if(value_low_i > now->time_field) { \ return FALSE; \ } else if(value_high_i < 0) { \ } else if(value_high_i < now->time_field) { \ return FALSE; \ } \ } gboolean cron_range_satisfied(ha_time_t *now, crm_data_t *cron_spec) { const char *value = NULL; char *value_low = NULL; char *value_high = NULL; int value_low_i = 0; int value_high_i = 0; cron_check("seconds", seconds); cron_check("minutes", minutes); cron_check("hours", hours); cron_check("monthdays", days); cron_check("weekdays", weekdays); cron_check("yeardays", yeardays); cron_check("weeks", weeks); cron_check("months", months); cron_check("years", years); cron_check("weekyears", weekyears); - - free_ha_date(now); return TRUE; } #define update_field(xml_field, time_fn) \ value = crm_element_value(duration_spec, xml_field); \ if(value != NULL) { \ int value_i = crm_atoi(value, "0"); \ time_fn(end, value_i); \ } ha_time_t * parse_xml_duration(ha_time_t *start, crm_data_t *duration_spec) { ha_time_t *end = NULL; const char *value = NULL; end = new_ha_date(FALSE); ha_set_time(end, start, TRUE); update_field("years", add_years); update_field("months", add_months); update_field("weeks", add_weeks); update_field("days", add_days); update_field("hours", add_hours); update_field("minutes", add_minutes); update_field("seconds", add_seconds); return end; } gboolean test_date_expression(crm_data_t *time_expr) { ha_time_t *start = NULL; ha_time_t *end = NULL; const char *value = NULL; char *value_copy = NULL; char *value_copy_start = NULL; const char *op = crm_element_value(time_expr, "operation"); ha_time_t *now = new_ha_date(TRUE); crm_data_t *duration_spec = NULL; crm_data_t *date_spec = NULL; + gboolean passed = FALSE; + crm_debug_2("Testing expression: %s", ID(time_expr)); duration_spec = cl_get_struct(time_expr, "duration"); date_spec = cl_get_struct(time_expr, "date_spec"); value = crm_element_value(time_expr, "start"); if(value != NULL) { value_copy = crm_strdup(value); value_copy_start = value_copy; start = parse_date(&value_copy); crm_free(value_copy_start); } value = crm_element_value(time_expr, "end"); if(value != NULL) { value_copy = crm_strdup(value); value_copy_start = value_copy; end = parse_date(&value_copy); crm_free(value_copy_start); } if(start != NULL && end == NULL) { end = parse_xml_duration(start, duration_spec); } if(op == NULL) { op = "in_range"; } if(safe_str_eq(op, "date_spec") || safe_str_eq(op, "in_range")) { if(start != NULL && compare_date(start, now) > 0) { - return FALSE; - + passed = FALSE; } else if(end != NULL && compare_date(end, now) < 0) { - return FALSE; + passed = FALSE; + } else if(safe_str_eq(op, "in_range")) { + passed = TRUE; + } else { + passed = cron_range_satisfied(now, date_spec); } - if(safe_str_eq(op, "in_range")) { - return TRUE; - } - return cron_range_satisfied(now, date_spec); - + } else if(safe_str_eq(op, "gt") && compare_date(start, now) < 0) { - return TRUE; + passed = TRUE; + } else if(safe_str_eq(op, "lt") && compare_date(end, now) > 0) { - return TRUE; + passed = TRUE; } else if(safe_str_eq(op, "eq") && compare_date(start, now) == 0) { - return TRUE; + passed = TRUE; } else if(safe_str_eq(op, "neq") && compare_date(start, now) != 0) { - return TRUE; + passed = TRUE; } - return FALSE; + free_ha_date(start); + free_ha_date(end); + free_ha_date(now); + return passed; } diff --git a/crm/pengine/testcases/date-1.dot b/crm/pengine/testcases/date-1.dot new file mode 100644 index 0000000000..99ecf0f7e0 --- /dev/null +++ b/crm/pengine/testcases/date-1.dot @@ -0,0 +1,4 @@ +digraph "g" { + size = "30,30" +"rsc1_start_0" [ tooltip="node2" style=bold color="green" fontcolor="black" ] +} diff --git a/crm/pengine/testcases/date-1.exp b/crm/pengine/testcases/date-1.exp new file mode 100644 index 0000000000..0f4c7139fd --- /dev/null +++ b/crm/pengine/testcases/date-1.exp @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +