Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:54:59

0001 #include <cppunit/extensions/HelperMacros.h>
0002 #include <ext/alloc_traits.h>
0003 #include <regex.h>
0004 #include <algorithm>
0005 #include <iostream>
0006 #include <iterator>
0007 #include <map>
0008 #include <memory>
0009 #include <string>
0010 #include <utility>
0011 #include <vector>
0012 
0013 #include "DetectorDescription/Core/interface/Singleton.h"
0014 #include "DetectorDescription/Core/interface/DDLogicalPart.h"
0015 #include "DetectorDescription/Core/interface/DDName.h"
0016 #include "FWCore/ParameterSet/interface/FileInPath.h"
0017 #include "cppunit/TestAssert.h"
0018 #include "cppunit/TestFixture.h"
0019 
0020 namespace {
0021 
0022   std::pair<bool, std::string> oldDDIsValid(const std::string& ns,
0023                                             const std::string& nm,
0024                                             std::vector<DDLogicalPart>& result,
0025                                             bool doRegex) {
0026     //return std::make_pair(true,"");
0027     std::string status, aName, aNs;
0028     bool emptyNs = false;
0029     if (ns.empty())
0030       emptyNs = true;
0031 
0032     aName = "^" + nm + "$";
0033     aNs = "^" + ns + "$";
0034     //bool flag(true);
0035     regex_t aRegex, aNsRegex;
0036     const char* aRegexCStr = aName.c_str();
0037     const char* aNsRegexCStr = aNs.c_str();
0038     if (doRegex) {
0039       //    std:: cout << "Regex " << nm << " " << ns << std::endl;
0040       if (regcomp(&aRegex, aRegexCStr, 0)) {
0041         regfree(&aRegex);
0042         return std::make_pair(false, "Error in the regexp for the name: " + nm);
0043       }
0044 
0045       if (regcomp(&aNsRegex, aNsRegexCStr, 0)) {
0046         regfree(&aRegex);
0047         regfree(&aNsRegex);
0048         return std::make_pair(false, "Error in the regexp for the namespace: " + ns);
0049       }
0050     } else {
0051       DDName ddnm(nm, ns);
0052       result.emplace_back(DDLogicalPart(ddnm));
0053       return std::make_pair(true, "");
0054     }
0055     //edm::LogInfo("DDLogicalPart") << " . emptyNs=" << emptyNs << std::endl;
0056     //edm::LogInfo("DDLogicalPart") << " . qname=[" << ns << ":" << nm << "]" << std::endl;
0057 
0058     // THIS IS THE SLOW PART: I have to compare every namespace & name of every
0059     // logical part with a regex-comparison .... a linear search always through the
0060     // full range of logical parts!!!!
0061     /*
0062       Algorithm description:
0063       x. empty nm and ns argument of method means: use all matching regex ^.*$
0064       a. iterate over all logical part names, match against regex for names
0065       b. iterate over all namespaces of names found in a & match against regex for namespaces   
0066     */
0067     LPNAMES::value_type::const_iterator it(LPNAMES::instance().begin()), ed(LPNAMES::instance().end());
0068     for (; it != ed; ++it) {
0069       bool doit = false;
0070       doit = !regexec(&aRegex, it->first.c_str(), 0, nullptr, 0);
0071       //if (doit)  edm::LogInfo("DDLogicalPart") << "rgx: " << aName << ' ' << it->first << ' ' << doit << std::endl;
0072       if (doit) {
0073         std::vector<DDName>::size_type sz = it->second.size();  // no of 'compatible' namespaces
0074         if (emptyNs && (sz == 1)) {                             // accept all logical parts in all the namespaces
0075           result.emplace_back(it->second[0]);
0076           //std::vector<DDName>::const_iterator nsIt(it->second.begin()), nsEd(it->second.end());
0077           //for(; nsIt != nsEd; ++nsIt) {
0078           //   result.emplace_back(DDLogicalPart(*nsIt));
0079           //   edm::LogInfo("DDLogicalPart") << "DDD-WARNING: multiple namespaces match (in SpecPars PartSelector): " << *nsIt << std::endl;
0080           //}
0081         } else if (!emptyNs) {  // only accept matching namespaces
0082           std::vector<DDName>::const_iterator nsit(it->second.begin()), nsed(it->second.end());
0083           for (; nsit != nsed; ++nsit) {
0084             //edm::LogInfo("DDLogicalPart") << "comparing " << aNs << " with " << *nsit << std::endl;
0085             bool another_doit = !regexec(&aNsRegex, nsit->ns().c_str(), 0, nullptr, 0);
0086             if (another_doit) {
0087               //temp.emplace_back(std::make_pair(it->first,*nsit));
0088               result.emplace_back(DDLogicalPart(*nsit));
0089             }
0090           }
0091         } else {  // emtpyNs and sz>1 -> error, too ambigous
0092           std::string message = "DDLogicalPart-name \"" + it->first + "\" matching regex \"" + nm +
0093                                 "\" has been found at least in following namespaces:\n";
0094           std::vector<DDName>::const_iterator vit = it->second.begin();
0095           for (; vit != it->second.end(); ++vit) {
0096             message += vit->ns();
0097             message += " ";
0098           }
0099           message += "\nQualify the name with a regexp for the namespace, i.e \".*:name-regexp\" !";
0100 
0101           regfree(&aRegex);
0102           regfree(&aNsRegex);
0103 
0104           return std::make_pair(false, message);
0105         }
0106       }
0107     }
0108     bool flag = true;
0109     std::string message;
0110 
0111     // check whether the found logical-parts are also defined (i.e. have material, solid ...)
0112     // std::cout << "IsValid-Result " << nm << " :";
0113     if (!result.empty()) {
0114       std::vector<DDLogicalPart>::const_iterator lpit(result.begin()), lped(result.end());
0115       for (; lpit != lped; ++lpit) {
0116         // std::cout << " " << std::string(lpit->name());
0117         if (!lpit->isDefined().second) {
0118           message = message + "LogicalPart " + lpit->name().fullname() + " not (yet) defined!\n";
0119           flag = false;
0120         }
0121       }
0122     } else {
0123       flag = false;
0124       message = "No regex-match for namespace=" + ns + "  name=" + nm + "\n";
0125     }
0126     regfree(&aRegex);
0127     regfree(&aNsRegex);
0128     // std::cout << std::endl;
0129 
0130     return std::make_pair(flag, message);
0131   }
0132 }  // namespace
0133 
0134 namespace {
0135   // the static dumper
0136   // to be used in the real application
0137   struct BHA {
0138     ~BHA() {
0139       LPNAMES::value_type::const_iterator it(LPNAMES::instance().begin()), ed(LPNAMES::instance().end());
0140       std::cout << "LPNAMES begin" << std::endl;
0141       for (; it != ed; ++it) {
0142         std::cout << it->first;
0143         std::vector<DDName>::const_iterator nsit(it->second.begin()), nsed(it->second.end());
0144         for (; nsit != nsed; ++nsit)
0145           std::cout << " " << nsit->ns();
0146         std::cout << std::endl;
0147       }
0148       std::cout << "LPNAMES end" << std::endl;
0149     }
0150   };
0151   //  BHA bah;
0152 }  // namespace
0153 
0154 class testDDIsValid : public CppUnit::TestFixture {
0155   CPPUNIT_TEST_SUITE(testDDIsValid);
0156   CPPUNIT_TEST(checkAgaistOld);
0157   CPPUNIT_TEST_SUITE_END();
0158 
0159 public:
0160   void setUp() override {}
0161   void tearDown() override {}
0162   void buildIt();
0163   void testloading();
0164   void checkAgaistOld();
0165 };
0166 
0167 CPPUNIT_TEST_SUITE_REGISTRATION(testDDIsValid);
0168 
0169 void testDDIsValid::testloading() {
0170   std::cerr << "test Loading" << std::endl;
0171   // get name using FileInPath.
0172   edm::FileInPath fp("DetectorDescription/Core/test/lpnames.out");
0173   // test that we load LPNAMES correclty
0174   //  std::ifstream in("lpnames.out");
0175   std::ifstream in(fp.fullPath().c_str());
0176   //  std::cout << "FILE : " << fp << " absolute path " << fp.fullPath().c_str() << std::endl;
0177   in.unsetf(std::ios::skipws);
0178   std::istream_iterator<char> sbegin(in), send;
0179   std::string str;
0180   std::copy(sbegin, send, std::inserter(str, str.begin()));
0181 
0182   std::ostringstream os;
0183 
0184   LPNAMES::value_type::const_iterator it(LPNAMES::instance().begin()), ed(LPNAMES::instance().end());
0185   for (; it != ed; ++it) {
0186     os << it->first;
0187     std::vector<DDName>::const_iterator nsit(it->second.begin()), nsed(it->second.end());
0188     for (; nsit != nsed; ++nsit)
0189       os << " " << nsit->ns();
0190     os << std::endl;
0191   }
0192 
0193   if (os.str() != str)
0194     std::cerr << "not the same!" << std::endl;
0195   CPPUNIT_ASSERT(os.str() == str);
0196 }
0197 
0198 void testDDIsValid::buildIt() {
0199   // get name using FileInPath.
0200   edm::FileInPath fp("DetectorDescription/Core/test/lpnames.out");
0201   // fill LPNAMES
0202   //  std::ifstream in("lpnames.out");
0203   std::ifstream in(fp.fullPath().c_str());
0204   std::string line;
0205   while (std::getline(in, line)) {
0206     std::string::size_type p;
0207     p = line.find(" ");
0208     std::string nm(line, 0, p);
0209     std::vector<DDName>& v = LPNAMES::instance()[nm];
0210     while (p != std::string::npos) {
0211       ++p;
0212       std::string::size_type e = line.find(" ", p);
0213       std::string::size_type s = e - p;
0214       if (e == std::string::npos)
0215         s = e;
0216       v.emplace_back(DDName(nm, line.substr(p, s)));
0217       p = e;
0218     }
0219   }
0220   std::cerr << "read " << LPNAMES::instance().size() << std::endl;
0221   CPPUNIT_ASSERT(LPNAMES::instance().size() == 3819);
0222 }
0223 
0224 void testDDIsValid::checkAgaistOld() {
0225   buildIt();
0226   testloading();
0227   // get name using FileInPath.
0228   edm::FileInPath fp("DetectorDescription/Core/test/regex.queries");
0229 
0230   //  std::ifstream in("regex.queries");
0231   std::ifstream in(fp.fullPath().c_str());
0232 
0233   std::string line;
0234   const std::string ns;
0235   int bad = 0;
0236   while (std::getline(in, line)) {
0237     std::string::size_type p = line.find(" ");
0238     ++p;
0239     std::string::size_type e = line.find(" ", p);
0240     // ns, we know, is always ""
0241     std::vector<DDLogicalPart> oldResult;
0242     std::vector<DDLogicalPart> result;
0243     std::pair<bool, std::string> oldRes = oldDDIsValid(ns, line.substr(p, e - p), oldResult, true);
0244     std::pair<bool, std::string> res = DDIsValid(ns, line.substr(p, e - p), result, true);
0245     if (oldRes.first != res.first || oldRes.second != res.second || oldResult.size() != result.size()) {
0246       ++bad;
0247       continue;
0248     }
0249     for (int i = 0; i != int(result.size()); ++i) {
0250       if (result[i].name() == oldResult[i].name())
0251         continue;
0252       ++bad;
0253       break;
0254     }
0255   }
0256 
0257   if (bad)
0258     std::cerr << bad << " queries not the same!" << std::endl;
0259   CPPUNIT_ASSERT(bad == 0);
0260 }