diff --git a/HLTrigger/HLTcore/interface/TriggerExpressionParser.h b/HLTrigger/HLTcore/interface/TriggerExpressionParser.h index ac81d2d21d7ad..38e17809b52ed 100644 --- a/HLTrigger/HLTcore/interface/TriggerExpressionParser.h +++ b/HLTrigger/HLTcore/interface/TriggerExpressionParser.h @@ -28,6 +28,7 @@ namespace triggerExpression { operand_not = qi::lexeme[qi::lit("NOT") >> delimiter]; operand_and = qi::lexeme[qi::lit("AND") >> delimiter]; operand_or = qi::lexeme[qi::lit("OR") >> delimiter]; + operand_xor = qi::lexeme[qi::lit("XOR") >> delimiter]; operand_masking = qi::lexeme[qi::lit("MASKING") >> delimiter]; // "TRUE": keyword to accept all events @@ -40,9 +41,9 @@ namespace triggerExpression { token_l1algo %= qi::raw[qi::lexeme["L1_" >> +(qi::char_("a-zA-Z0-9_*?"))]]; // Decisions of Paths in the CMSSW configuration (e.g. high-level triggers): - // any alphanumeric pattern except for "TRUE", "FALSE", "NOT", "AND", "OR", and "MASKING" + // any alphanumeric pattern except for "TRUE", "FALSE", "NOT", "AND", "OR", "XOR" and "MASKING" token_path %= qi::raw[qi::lexeme[+(qi::char_("a-zA-Z0-9_*?"))] - token_true - token_false - operand_not - - operand_and - operand_or - operand_masking]; + operand_and - operand_or - operand_xor - operand_masking]; token = (token_true[qi::_val = new_(true)] | token_false[qi::_val = new_(false)] | token_l1algo[qi::_val = new_(qi::_1)] | token_path[qi::_val = new_(qi::_1)]); @@ -68,6 +69,7 @@ namespace triggerExpression { expression = unary[qi::_val = qi::_1] >> *((operand_and >> unary)[qi::_val = new_(qi::_val, qi::_1)] | (operand_or >> unary)[qi::_val = new_(qi::_val, qi::_1)] | + (operand_xor >> unary)[qi::_val = new_(qi::_val, qi::_1)] | (operand_masking >> argument_masking)[qi::_val = new_(qi::_val, qi::_1)]); } @@ -82,6 +84,7 @@ namespace triggerExpression { terminal_rule operand_not; terminal_rule operand_and; terminal_rule operand_or; + terminal_rule operand_xor; terminal_rule operand_masking; name_rule token_l1algo; diff --git a/HLTrigger/HLTcore/test/test_catch2_TriggerExpressionParser.cc b/HLTrigger/HLTcore/test/test_catch2_TriggerExpressionParser.cc index 0b7d5c5d666b9..c1d1b9ae2b76f 100644 --- a/HLTrigger/HLTcore/test/test_catch2_TriggerExpressionParser.cc +++ b/HLTrigger/HLTcore/test/test_catch2_TriggerExpressionParser.cc @@ -52,6 +52,11 @@ TEST_CASE("Test TriggerExpressionParser", "[TriggerExpressionParser]") { "((Uninitialised_Path_Expression AND TRUE) AND (NOT Uninitialised_L1_Expression))")); REQUIRE(testExpression("NOT NOTThisHLTPath", // "(NOT Uninitialised_Path_Expression)")); + REQUIRE(testExpression("XYZ XOR TRUE", // + "(Uninitialised_Path_Expression XOR TRUE)")); + REQUIRE(testExpression("XYZ XOR ABC AND L1_* OR DEF/10", // + "(((Uninitialised_Path_Expression XOR Uninitialised_Path_Expression) AND " + "Uninitialised_L1_Expression) OR (Uninitialised_Path_Expression / 10))")); REQUIRE(testExpression("ThisHLTANDNOTThatORTheOther", // "Uninitialised_Path_Expression")); REQUIRE(testExpression("TRUEPath AND NOTPath", // @@ -86,8 +91,8 @@ TEST_CASE("Test TriggerExpressionParser", "[TriggerExpressionParser]") { "L1_*copy* MASKING L1_*copy MASKING ((L1_*copy2))", // "((Uninitialised_L1_Expression MASKING Uninitialised_L1_Expression) MASKING Uninitialised_L1_Expression)")); REQUIRE(testExpression( - "(A AND B OR C) MASKING D OR E", // - "((((Uninitialised_Path_Expression AND Uninitialised_Path_Expression) OR Uninitialised_Path_Expression)" + "(A AND B XOR C) MASKING D OR E", // + "((((Uninitialised_Path_Expression AND Uninitialised_Path_Expression) XOR Uninitialised_Path_Expression)" " MASKING Uninitialised_Path_Expression) OR Uninitialised_Path_Expression)")); REQUIRE(testExpression("EXPR_A MASKING FALSE", "(Uninitialised_Path_Expression MASKING FALSE)")); } @@ -96,6 +101,11 @@ TEST_CASE("Test TriggerExpressionParser", "[TriggerExpressionParser]") { SECTION("IncorrectExpressions") { REQUIRE(not testExpression("A | B")); REQUIRE(not testExpression("A && B")); + REQUIRE(not testExpression("NOT")); + REQUIRE(not testExpression("AND")); + REQUIRE(not testExpression("OR")); + REQUIRE(not testExpression("XOR")); + REQUIRE(not testExpression("MASKING")); REQUIRE(not testExpression("NOT L1_SEED1 ANDD L1_SEED2*")); REQUIRE(not testExpression("NOT (NOTHLT_Path OR HLT_Path2))")); REQUIRE(not testExpression("HLT_Path* NOT TRUE")); diff --git a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.py b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.py index 569b1ba7b317d..045c858435141 100644 --- a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.py +++ b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.py @@ -123,6 +123,16 @@ triggerConditions = ( 'NOT(Path_1/15)AND(NOT Path_2/10)AND(NOT Path_3/6)', ) ) +# accept if Path_1 and Path_2 have different results (XOR) without using XOR operator +process.filter_1xor2_withoutXOR = _triggerResultsFilter.clone( + triggerConditions = ( 'Path_1 AND NOT Path_2', 'NOT Path_1 AND Path_2', ) +) + +# accept if Path_1 and Path_2 have different results (XOR) using XOR operator +process.filter_1xor2_withXOR = _triggerResultsFilter.clone( + triggerConditions = ( 'Path_1 XOR Path_2', ) +) + # accept if any path succeeds (wildcard, '*') process.filter_any_star = _triggerResultsFilter.clone( triggerConditions = ( 'Path_*', ) @@ -204,25 +214,27 @@ process.Check_Any_Or = cms.Path( process.filter_any_or ) process.Check_Any_Star = cms.Path( process.filter_any_star ) -process.Check_1_Pre = cms.Path( process.filter_1_pre ) +process.Check_1_Pre = cms.Path( process.filter_1_pre ) process.Check_1_Pre_With_Masks1 = cms.Path( process.filter_1_pre_with_masks1 ) process.Check_1_Pre_With_Masks2 = cms.Path( process.filter_1_pre_with_masks2 ) -process.Check_NOT_1_Pre = cms.Path( process.filter_not_1_pre ) -process.Check_2_Pre = cms.Path( process.filter_2_pre ) -process.Check_Any_Pre = cms.Path( process.filter_any_pre ) +process.Check_NOT_1_Pre = cms.Path( process.filter_not_1_pre ) +process.Check_2_Pre = cms.Path( process.filter_2_pre ) +process.Check_Any_Pre = cms.Path( process.filter_any_pre ) process.Check_Any_Pre_DoubleNOT = cms.Path( process.filter_any_pre_doubleNOT ) -process.Check_Not_Any_Pre = cms.Path( process.filter_not_any_pre ) - -process.Check_Any_Question = cms.Path( process.filter_any_question ) -process.Check_Any_StarQuestion = cms.Path( process.filter_any_starquestion ) -process.Check_Wrong_Name = cms.Path( process.filter_wrong_name ) -process.Check_Wrong_Pattern = cms.Path( process.filter_wrong_pattern ) -process.Check_Not_Wrong_Pattern = cms.Path( ~ process.filter_wrong_pattern ) -process.Check_Empty_Pattern = cms.Path( process.filter_empty_pattern ) -process.Check_L1Path_Pattern = cms.Path( process.filter_l1path_pattern ) +process.Check_Not_Any_Pre = cms.Path( process.filter_not_any_pre ) +process.Check_1xor2_withoutXOR = cms.Path( process.filter_1xor2_withoutXOR ) +process.Check_1xor2_withXOR = cms.Path( process.filter_1xor2_withXOR ) + +process.Check_Any_Question = cms.Path( process.filter_any_question ) +process.Check_Any_StarQuestion = cms.Path( process.filter_any_starquestion ) +process.Check_Wrong_Name = cms.Path( process.filter_wrong_name ) +process.Check_Wrong_Pattern = cms.Path( process.filter_wrong_pattern ) +process.Check_Not_Wrong_Pattern = cms.Path( ~ process.filter_wrong_pattern ) +process.Check_Empty_Pattern = cms.Path( process.filter_empty_pattern ) +process.Check_L1Path_Pattern = cms.Path( process.filter_l1path_pattern ) process.Check_L1Singlemuopen_Pattern = cms.Path( process.filter_l1singlemuopen_pattern ) -process.Check_True_Pattern = cms.Path( process.filter_true_pattern ) -process.Check_False_Pattern = cms.Path( process.filter_false_pattern ) +process.Check_True_Pattern = cms.Path( process.filter_true_pattern ) +process.Check_False_Pattern = cms.Path( process.filter_false_pattern ) process.Check_AlwaysNOTFalse_Pattern = cms.Path( process.filter_AlwaysNOTFalse_pattern ) process.Check_NOTAlwaysFALSE_Pattern = cms.Path( process.filter_NOTAlwaysFALSE_pattern ) diff --git a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.sh b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.sh index 52ca6e8d947ab..2c9a5cf31f582 100755 --- a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.sh +++ b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_PathStatus.sh @@ -41,18 +41,20 @@ TrigReport 1 16 1000 33 967 0 Check_2_Pre TrigReport 1 17 1000 99 901 0 Check_Any_Pre TrigReport 1 18 1000 99 901 0 Check_Any_Pre_DoubleNOT TrigReport 1 19 1000 901 99 0 Check_Not_Any_Pre -TrigReport 1 20 1000 733 267 0 Check_Any_Question -TrigReport 1 21 1000 733 267 0 Check_Any_StarQuestion -TrigReport 1 22 1000 0 1000 0 Check_Wrong_Name -TrigReport 1 23 1000 0 1000 0 Check_Wrong_Pattern -TrigReport 1 24 1000 1000 0 0 Check_Not_Wrong_Pattern -TrigReport 1 25 1000 0 1000 0 Check_Empty_Pattern -TrigReport 1 26 1000 0 1000 0 Check_L1Path_Pattern -TrigReport 1 27 1000 0 1000 0 Check_L1Singlemuopen_Pattern -TrigReport 1 28 1000 1000 0 0 Check_True_Pattern -TrigReport 1 29 1000 0 1000 0 Check_False_Pattern -TrigReport 1 30 1000 1000 0 0 Check_AlwaysNOTFalse_Pattern -TrigReport 1 31 1000 1000 0 0 Check_NOTAlwaysFALSE_Pattern +TrigReport 1 20 1000 499 501 0 Check_1xor2_withoutXOR +TrigReport 1 21 1000 499 501 0 Check_1xor2_withXOR +TrigReport 1 22 1000 733 267 0 Check_Any_Question +TrigReport 1 23 1000 733 267 0 Check_Any_StarQuestion +TrigReport 1 24 1000 0 1000 0 Check_Wrong_Name +TrigReport 1 25 1000 0 1000 0 Check_Wrong_Pattern +TrigReport 1 26 1000 1000 0 0 Check_Not_Wrong_Pattern +TrigReport 1 27 1000 0 1000 0 Check_Empty_Pattern +TrigReport 1 28 1000 0 1000 0 Check_L1Path_Pattern +TrigReport 1 29 1000 0 1000 0 Check_L1Singlemuopen_Pattern +TrigReport 1 30 1000 1000 0 0 Check_True_Pattern +TrigReport 1 31 1000 0 1000 0 Check_False_Pattern +TrigReport 1 32 1000 1000 0 0 Check_AlwaysNOTFalse_Pattern +TrigReport 1 33 1000 1000 0 0 Check_NOTAlwaysFALSE_Pattern @EOF # compare to expected output of test job diff --git a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.py b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.py index e89ad7d74f7fb..ce03e707bb8a9 100644 --- a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.py +++ b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.py @@ -84,6 +84,16 @@ triggerConditions = ( 'NOT(Path_1/15)AND(NOT Path_2/10)AND(NOT Path_3/6)', ) ) +# accept if Path_1 and Path_2 have different results (XOR) without using XOR operator +process.filter_1xor2_withoutXOR = _triggerResultsFilter.clone( + triggerConditions = ( 'Path_1 AND NOT Path_2', 'NOT Path_1 AND Path_2', ) +) + +# accept if Path_1 and Path_2 have different results (XOR) using XOR operator +process.filter_1xor2_withXOR = _triggerResultsFilter.clone( + triggerConditions = ( 'Path_1 XOR Path_2', ) +) + # accept if any path succeeds (wildcard, '*') process.filter_any_star = _triggerResultsFilter.clone( triggerConditions = ( '*', ) @@ -157,14 +167,16 @@ process.path_any_or = cms.Path( process.filter_any_or ) process.path_any_star = cms.Path( process.filter_any_star ) -process.path_1_pre = cms.Path( process.filter_1_pre ) +process.path_1_pre = cms.Path( process.filter_1_pre ) process.path_1_pre_with_masks1 = cms.Path( process.filter_1_pre_with_masks1 ) process.path_1_pre_with_masks2 = cms.Path( process.filter_1_pre_with_masks2 ) -process.path_not_1_pre = cms.Path( process.filter_not_1_pre ) -process.path_2_pre = cms.Path( process.filter_2_pre ) -process.path_any_pre = cms.Path( process.filter_any_pre ) +process.path_not_1_pre = cms.Path( process.filter_not_1_pre ) +process.path_2_pre = cms.Path( process.filter_2_pre ) +process.path_any_pre = cms.Path( process.filter_any_pre ) process.path_any_pre_doubleNOT = cms.Path( process.filter_any_pre_doubleNOT ) -process.path_not_any_pre = cms.Path( process.filter_not_any_pre ) +process.path_not_any_pre = cms.Path( process.filter_not_any_pre ) +process.Check_1xor2_withoutXOR = cms.Path( process.filter_1xor2_withoutXOR ) +process.Check_1xor2_withXOR = cms.Path( process.filter_1xor2_withXOR ) process.path_any_doublestar = cms.Path( process.filter_any_doublestar ) process.path_any_question = cms.Path( process.filter_any_question ) diff --git a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.sh b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.sh index 968a2d5e6cf16..3ee0e81c05676 100755 --- a/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.sh +++ b/HLTrigger/HLTfilters/test/triggerResultsFilter_by_TriggerResults.sh @@ -38,16 +38,18 @@ TrigReport 1 10 1000 33 967 0 path_2_pre TrigReport 1 11 1000 99 901 0 path_any_pre TrigReport 1 12 1000 99 901 0 path_any_pre_doubleNOT TrigReport 1 13 1000 901 99 0 path_not_any_pre -TrigReport 1 14 1000 1000 0 0 path_any_doublestar -TrigReport 1 15 1000 733 267 0 path_any_question -TrigReport 1 16 1000 0 1000 0 path_wrong_name -TrigReport 1 17 1000 0 1000 0 path_wrong_pattern -TrigReport 1 18 1000 1000 0 0 path_not_wrong_pattern -TrigReport 1 19 1000 0 1000 0 path_empty_pattern -TrigReport 1 20 1000 0 1000 0 path_l1path_pattern -TrigReport 1 21 1000 0 1000 0 path_l1singlemuopen_pattern -TrigReport 1 22 1000 1000 0 0 path_true_pattern -TrigReport 1 23 1000 0 1000 0 path_false_pattern +TrigReport 1 14 1000 499 501 0 Check_1xor2_withoutXOR +TrigReport 1 15 1000 499 501 0 Check_1xor2_withXOR +TrigReport 1 16 1000 1000 0 0 path_any_doublestar +TrigReport 1 17 1000 733 267 0 path_any_question +TrigReport 1 18 1000 0 1000 0 path_wrong_name +TrigReport 1 19 1000 0 1000 0 path_wrong_pattern +TrigReport 1 20 1000 1000 0 0 path_not_wrong_pattern +TrigReport 1 21 1000 0 1000 0 path_empty_pattern +TrigReport 1 22 1000 0 1000 0 path_l1path_pattern +TrigReport 1 23 1000 0 1000 0 path_l1singlemuopen_pattern +TrigReport 1 24 1000 1000 0 0 path_true_pattern +TrigReport 1 25 1000 0 1000 0 path_false_pattern @EOF # compare to expected output of test job