Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:25

0001 #include "catch.hpp"
0002 
0003 #include "FWCore/Framework/interface/EventSelector.h"
0004 #include "DataFormats/Common/interface/TriggerResults.h"
0005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0006 #include "FWCore/Framework/interface/TriggerNamesService.h"
0007 #include "FWCore/ServiceRegistry/interface/ServiceWrapper.h"
0008 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
0009 #include "FWCore/ServiceRegistry/interface/ServiceToken.h"
0010 #include "FWCore/Utilities/interface/Exception.h"
0011 
0012 #include <array>
0013 #include <vector>
0014 #include <string>
0015 #include <iostream>
0016 #include <memory>
0017 
0018 using namespace edm;
0019 
0020 const size_t numBits = 5;
0021 const int numPatterns = 11;
0022 const int numMasks = 9;
0023 
0024 typedef bool Answers[numPatterns][numMasks];
0025 typedef std::vector<std::string> Strings;
0026 typedef std::vector<Strings> VStrings;
0027 typedef std::vector<bool> Bools;
0028 typedef std::vector<Bools> VBools;
0029 
0030 namespace {
0031   std::ostream& operator<<(std::ostream& ost, const Strings& s) {
0032     for (Strings::const_iterator i(s.begin()), e(s.end()); i != e; ++i) {
0033       ost << *i << " ";
0034     }
0035     return ost;
0036   }
0037 
0038   std::ostream& operator<<(std::ostream& ost, const Bools& b) {
0039     for (unsigned int i = 0; i < b.size(); ++i) {
0040       ost << b[i] << " ";
0041     }
0042     return ost;
0043   }
0044 }  // namespace
0045 void testone(const Strings& paths, const Strings& pattern, const Bools& mask, bool answer, int jmask) {
0046   // There are 2 different ways to build the EventSelector.
0047   // Both should give the same result.  We exercise both here.
0048   EventSelector select1(pattern, paths);
0049   EventSelector select2(pattern);
0050 
0051   int number_of_trigger_paths = 0;
0052   std::vector<unsigned char> bitArray;
0053 
0054   HLTGlobalStatus bm(mask.size());
0055   const HLTPathStatus pass = HLTPathStatus(edm::hlt::Pass);
0056   const HLTPathStatus fail = HLTPathStatus(edm::hlt::Fail);
0057   const HLTPathStatus ex = HLTPathStatus(edm::hlt::Exception);
0058   const HLTPathStatus ready = HLTPathStatus(edm::hlt::Ready);
0059   for (unsigned int b = 0; b < mask.size(); ++b) {
0060     bm[b] = (mask[b] ? pass : fail);
0061 
0062     // There is an alternate version of the function acceptEvent
0063     // that takes an array of characters as an argument instead
0064     // of a TriggerResults object.  These next few lines build
0065     // that array so we can test that also.
0066     if ((number_of_trigger_paths % 4) == 0)
0067       bitArray.push_back(0);
0068     int byteIndex = number_of_trigger_paths / 4;
0069     int subIndex = number_of_trigger_paths % 4;
0070     bitArray[byteIndex] |= (mask[b] ? edm::hlt::Pass : edm::hlt::Fail) << (subIndex * 2);
0071     ++number_of_trigger_paths;
0072   }
0073 
0074   if (jmask == 8 && mask.size() > 4) {
0075     bm[0] = ready;
0076     bm[4] = ex;
0077     bitArray[0] = (bitArray[0] & 0xfc) | edm::hlt::Ready;
0078     bitArray[1] = (bitArray[1] & 0xfc) | edm::hlt::Exception;
0079   }
0080 
0081   TriggerResults results(bm, paths);
0082 
0083   //        std::cerr << "pattern=" << pattern
0084   //          << "mask=" << mask << "\n";  // DBG
0085 
0086   //    std:: cerr << "a1 \n";
0087   bool a1 = select1.acceptEvent(results);
0088   //    std:: cerr << "a2 \n";
0089   bool a2 = select2.acceptEvent(results);
0090   //    std:: cerr << "b2 \n";
0091   bool b2 = select2.acceptEvent(results);
0092   //    std:: cerr << "c1 \n";
0093   bool c1 = select1.acceptEvent(&(bitArray[0]), number_of_trigger_paths);
0094 
0095   std::ostringstream s;
0096   if (a1 != answer || a2 != answer || b2 != answer || c1 != answer) {
0097     s << "failed to compare pattern with mask: "
0098       << "correct=" << answer << " "
0099       << "results=" << a1 << "  " << a2 << "  " << b2 << "  " << c1 << "\n"
0100       << "pattern=" << pattern << "\n"
0101       << "mask=" << mask << "\n"
0102       << "jmask = " << jmask << "\n";
0103   }
0104   REQUIRE_THAT(
0105       answer,
0106       Catch::Predicate<bool>(
0107           [a1, a2, b2, c1](auto answer) { return a1 == answer and a2 == answer and b2 == answer and c1 == answer; },
0108           s.str()));
0109 
0110   // Repeat putting the list of trigger names in the pset
0111   // registry
0112 
0113   ParameterSet trigger_pset;
0114   trigger_pset.addParameter<Strings>("@trigger_paths", paths);
0115   trigger_pset.registerIt();
0116 
0117   TriggerResults results_id(bm, trigger_pset.id());
0118 
0119   //    std:: cerr << "a11 \n";
0120   bool a11 = select1.acceptEvent(results_id);
0121   //    std:: cerr << "a12 \n";
0122   bool a12 = select2.acceptEvent(results_id);
0123   //    std:: cerr << "a13 \n";
0124   bool a13 = select2.acceptEvent(results_id);
0125 
0126   if (a11 != answer || a12 != answer || a13 != answer) {
0127     s << "failed to compare pattern with mask using pset ID: "
0128       << "correct=" << answer << " "
0129       << "results=" << a11 << "  " << a12 << "  " << a13 << "\n"
0130       << "pattern=" << pattern << "\n"
0131       << "mask=" << mask << "\n"
0132       << "jmask = " << jmask << "\n";
0133   }
0134   REQUIRE_THAT(
0135       answer,
0136       Catch::Predicate<bool>([a11, a12, a13](auto answer) { return a11 == answer and a12 == answer and a13 == answer; },
0137                              s.str()));
0138 }
0139 
0140 void testall(const Strings& paths, const VStrings& patterns, const VBools& masks, const Answers& answers) {
0141   for (unsigned int i = 0; i < patterns.size(); ++i) {
0142     for (unsigned int j = 0; j < masks.size(); ++j) {
0143       testone(paths, patterns[i], masks[j], answers[i][j], j);
0144     }
0145   }
0146 }
0147 
0148 TEST_CASE("test EventSelector", "[EventSelector]") {
0149   // Name all our paths. We have as many paths as there are trigger
0150   // bits.
0151   std::array<char const*, numBits> cpaths = {{"a1", "a2", "a3", "a4", "a5"}};
0152   Strings paths(cpaths.begin(), cpaths.end());
0153 
0154   //
0155 
0156   std::array<char const*, 2> cw1 = {{"a1", "a2"}};
0157   std::array<char const*, 2> cw2 = {{"!a1", "!a2"}};
0158   std::array<char const*, 2> cw3 = {{"a1", "!a2"}};
0159   std::array<char const*, 1> cw4 = {{"*"}};
0160   std::array<char const*, 1> cw5 = {{"!*"}};
0161   std::array<char const*, 2> cw6 = {{"*", "!*"}};
0162   std::array<char const*, 2> cw7 = {{"*", "!a2"}};
0163   std::array<char const*, 2> cw8 = {{"!*", "a2"}};
0164   std::array<char const*, 3> cw9 = {{"a1", "a2", "a5"}};
0165   std::array<char const*, 2> cwA = {{"a3", "a4"}};
0166   std::array<char const*, 1> cwB = {{"!a5"}};
0167 
0168   VStrings patterns(numPatterns);
0169   patterns[0].insert(patterns[0].end(), cw1.begin(), cw1.end());
0170   patterns[1].insert(patterns[1].end(), cw2.begin(), cw2.end());
0171   patterns[2].insert(patterns[2].end(), cw3.begin(), cw3.end());
0172   patterns[3].insert(patterns[3].end(), cw4.begin(), cw4.end());
0173   patterns[4].insert(patterns[4].end(), cw5.begin(), cw5.end());
0174   patterns[5].insert(patterns[5].end(), cw6.begin(), cw6.end());
0175   patterns[6].insert(patterns[6].end(), cw7.begin(), cw7.end());
0176   patterns[7].insert(patterns[7].end(), cw8.begin(), cw8.end());
0177   patterns[8].insert(patterns[8].end(), cw9.begin(), cw9.end());
0178   patterns[9].insert(patterns[9].end(), cwA.begin(), cwA.end());
0179   patterns[10].insert(patterns[10].end(), cwB.begin(), cwB.end());
0180 
0181   std::array<bool, numBits> t1 = {{true, false, true, false, true}};
0182   std::array<bool, numBits> t2 = {{false, true, true, false, true}};
0183   std::array<bool, numBits> t3 = {{true, true, true, false, true}};
0184   std::array<bool, numBits> t4 = {{false, false, true, false, true}};
0185   std::array<bool, numBits> t5 = {{false, false, false, false, false}};
0186   std::array<bool, numBits> t6 = {{true, true, true, true, true}};
0187   std::array<bool, numBits> t7 = {{true, true, true, true, false}};
0188   std::array<bool, numBits> t8 = {{false, false, false, false, true}};
0189   std::array<bool, numBits> t9 = {{false, false, false, false, false}};  // for t9 only, above the
0190                                                                          // first is reset to ready
0191                                                                          // last is reset to exception
0192 
0193   VBools testmasks(numMasks);
0194   testmasks[0].insert(testmasks[0].end(), t1.begin(), t1.end());
0195   testmasks[1].insert(testmasks[1].end(), t2.begin(), t2.end());
0196   testmasks[2].insert(testmasks[2].end(), t3.begin(), t3.end());
0197   testmasks[3].insert(testmasks[3].end(), t4.begin(), t4.end());
0198   testmasks[4].insert(testmasks[4].end(), t5.begin(), t5.end());
0199   testmasks[5].insert(testmasks[5].end(), t6.begin(), t6.end());
0200   testmasks[6].insert(testmasks[6].end(), t7.begin(), t7.end());
0201   testmasks[7].insert(testmasks[7].end(), t8.begin(), t8.end());
0202   testmasks[8].insert(testmasks[8].end(), t9.begin(), t9.end());
0203 
0204   Answers ans = {
0205       {true, true, true, false, false, true, true, false, false},
0206       {true, true, false, true, true, false, false, true, true},
0207       {true, false, true, true, true, true, true, true, true},
0208       {true, true, true, true, false, true, true, true, false},  // last column changed due to treatment of excp
0209       {false, false, false, false, true, false, false, false, false},
0210       {true, true, true, true, true, true, true, true, false},  // last column changed due to treatment of excp
0211       {true, true, true, true, true, true, true, true, true},
0212       {false, true, true, false, true, true, true, false, false},
0213       {true, true, true, true, false, true, true, true, false},  // last column changed due to treatment of excp
0214       {true, true, true, true, false, true, true, false, false},
0215       {false, false, false, false, true, false, true, false, false}  // last column changed due to treatment of excp
0216   };
0217 
0218   // We want to create the TriggerNamesService because it is used in
0219   // the tests.  We do that here, but first we need to build a minimal
0220   // parameter set to pass to its constructor.  Then we build the
0221   // service and setup the service system.
0222   ParameterSet proc_pset;
0223 
0224   std::string processName("HLT");
0225   proc_pset.addParameter<std::string>("@process_name", processName);
0226 
0227   ParameterSet trigPaths;
0228   trigPaths.addParameter<Strings>("@trigger_paths", paths);
0229   proc_pset.addParameter<ParameterSet>("@trigger_paths", trigPaths);
0230 
0231   Strings endPaths;
0232   proc_pset.addParameter<Strings>("@end_paths", endPaths);
0233 
0234   // We do not care what is in these parameters for the test, they
0235   // just need to exist.
0236   Strings dummy;
0237   for (size_t i = 0; i < numBits; ++i) {
0238     proc_pset.addParameter<Strings>(paths[i], dummy);
0239   }
0240   proc_pset.registerIt();
0241 
0242   // Now create and setup the service
0243   typedef edm::service::TriggerNamesService TNS;
0244   typedef serviceregistry::ServiceWrapper<TNS> w_TNS;
0245 
0246   auto tnsptr = std::make_shared<w_TNS>(std::make_unique<TNS>(proc_pset));
0247 
0248   ServiceToken serviceToken_ = ServiceRegistry::createContaining(tnsptr);
0249 
0250   //make the services available
0251   ServiceRegistry::Operate operate(serviceToken_);
0252 
0253   // We are ready to run some tests
0254 
0255   testall(paths, patterns, testmasks, ans);
0256 }