Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 /*
0002  *  interval_t.cc
0003  *  EDMProto
0004  *
0005  *  Created by Chris Jones on 3/30/05.
0006  *  Changed by Viji Sundararajan on 29-Jun-05.
0007  *
0008  */
0009 
0010 #include <unordered_map>
0011 #include <unordered_set>
0012 #include <algorithm>
0013 #include <cassert>
0014 
0015 #include "FWCore/Framework/interface/PathsAndConsumesOfModules.h"
0016 #include "FWCore/Utilities/interface/Exception.h"
0017 #include "DataFormats/Provenance/interface/ParameterSetID.h"
0018 #include "DataFormats/Provenance/interface/ModuleDescription.h"
0019 #include "DataFormats/Provenance/interface/ProcessConfiguration.h"
0020 #include "cppunit/extensions/HelperMacros.h"
0021 
0022 using ModuleDependsOnMap = std::map<std::string, std::vector<std::string>>;
0023 using PathToModules = std::unordered_map<std::string, std::vector<std::string>>;
0024 
0025 namespace {
0026   class PathsAndConsumesOfModulesForTest : public edm::PathsAndConsumesOfModulesBase {
0027   public:
0028     PathsAndConsumesOfModulesForTest(ModuleDependsOnMap const&, PathToModules const&);
0029 
0030   private:
0031     std::vector<std::string> const& doPaths() const final { return m_paths; }
0032     std::vector<std::string> const& doEndPaths() const final { return m_endPaths; }
0033     std::vector<edm::ModuleDescription const*> const& doAllModules() const final { return m_modules; }
0034     edm::ModuleDescription const* doModuleDescription(unsigned int moduleID) const final { return m_modules[moduleID]; }
0035     std::vector<edm::ModuleDescription const*> const& doModulesOnPath(unsigned int pathIndex) const final {
0036       return m_modulesOnPath[pathIndex];
0037     }
0038     std::vector<edm::ModuleDescription const*> const& doModulesOnEndPath(unsigned int endPathIndex) const final {
0039       return m_modulesOnEndPath[endPathIndex];
0040     }
0041     std::vector<edm::ModuleDescription const*> const& doModulesWhoseProductsAreConsumedBy(
0042         unsigned int moduleID, edm::BranchType branchType) const final {
0043       return m_modulesWhoseProductsAreConsumedBy[moduleID];
0044     }
0045     std::vector<edm::ConsumesInfo> doConsumesInfo(unsigned int moduleID) const final {
0046       return m_moduleConsumesInfo[moduleID];
0047     }
0048     unsigned int doLargestModuleID() const final {
0049       if (m_modules.empty()) {
0050         return 0;
0051       }
0052       return m_modules.size() - 1;
0053     }
0054 
0055     std::vector<std::string> m_paths;
0056     std::vector<std::string> m_endPaths;
0057     std::vector<edm::ModuleDescription const*> m_modules;
0058     std::vector<std::vector<edm::ConsumesInfo>> m_moduleConsumesInfo;
0059     std::vector<std::vector<edm::ModuleDescription const*>> m_modulesOnPath;
0060     std::vector<std::vector<edm::ModuleDescription const*>> m_modulesOnEndPath;
0061     std::vector<std::vector<edm::ModuleDescription const*>> m_modulesWhoseProductsAreConsumedBy;
0062     std::vector<edm::ModuleDescription> m_cache;
0063 
0064     static unsigned int indexForModule(std::string const& iName,
0065                                        std::unordered_map<std::string, unsigned int>& modsToIndex,
0066                                        std::unordered_map<unsigned int, std::string>& indexToMods) {
0067       auto found = modsToIndex.find(iName);
0068       unsigned int fromIndex;
0069       if (found == modsToIndex.end()) {
0070         fromIndex = modsToIndex.size();
0071         modsToIndex.emplace(iName, fromIndex);
0072         indexToMods.emplace(fromIndex, iName);
0073       } else {
0074         fromIndex = found->second;
0075       }
0076       return fromIndex;
0077     }
0078   };
0079   PathsAndConsumesOfModulesForTest::PathsAndConsumesOfModulesForTest(ModuleDependsOnMap const& iModDeps,
0080                                                                      PathToModules const& iPaths) {
0081     //setup module indicies
0082     std::unordered_map<std::string, unsigned int> modsToIndex;
0083     std::unordered_map<unsigned int, std::string> indexToMods;
0084 
0085     const edm::ProcessConfiguration pc("TEST", edm::ParameterSetID{}, "CMSSW_x_y_z", "??");
0086 
0087     //In actual configuration building, the source is always assigned id==0
0088     m_cache.emplace_back(
0089         edm::ParameterSetID{}, "source", "source", &pc, indexForModule("source", modsToIndex, indexToMods));
0090 
0091     for (auto const& md : iModDeps) {
0092       auto const lastSize = modsToIndex.size();
0093       auto index = indexForModule(md.first, modsToIndex, indexToMods);
0094       if (index == lastSize) {
0095         m_cache.emplace_back(edm::ParameterSetID{}, md.first, md.first, &pc, index);
0096       }
0097     }
0098     m_paths.reserve(iPaths.size());
0099     for (auto const& pToM : iPaths) {
0100       m_paths.push_back(pToM.first);
0101 
0102       for (auto const& mod : pToM.second) {
0103         auto const lastSize = modsToIndex.size();
0104         unsigned int index = indexForModule(mod, modsToIndex, indexToMods);
0105         if (index == lastSize) {
0106           m_cache.emplace_back(edm::ParameterSetID{}, mod, mod, &pc, index);
0107         }
0108       }
0109     }
0110     for (auto const& md : iModDeps) {
0111       for (auto const& dep : md.second) {
0112         auto const lastSize = modsToIndex.size();
0113         auto index = indexForModule(dep, modsToIndex, indexToMods);
0114         if (index == lastSize) {
0115           m_cache.emplace_back(edm::ParameterSetID{}, dep, dep, &pc, index);
0116         }
0117       }
0118     }
0119 
0120     if (not iPaths.empty()) {
0121       auto indexForTriggerResults = indexForModule("TriggerResults", modsToIndex, indexToMods);
0122       for (auto const& pToM : iPaths) {
0123         auto index = indexForModule(pToM.first, modsToIndex, indexToMods);
0124         m_cache.emplace_back(edm::ParameterSetID{}, "PathStatusInserter", pToM.first, &pc, index);
0125       }
0126       m_cache.emplace_back(
0127           edm::ParameterSetID{}, "TriggerResultInserter", "TriggerResults", &pc, indexForTriggerResults);
0128     }
0129 
0130     m_modules.reserve(m_cache.size());
0131     for (auto const& desc : m_cache) {
0132       m_modules.push_back(&desc);
0133     }
0134 
0135     //do consumes
0136     edm::TypeID dummy;
0137     m_moduleConsumesInfo.resize(m_modules.size());
0138     m_modulesWhoseProductsAreConsumedBy.resize(m_modules.size());
0139     for (auto const& md : iModDeps) {
0140       auto moduleID = modsToIndex[md.first];
0141       auto& consumes = m_moduleConsumesInfo[moduleID];
0142       consumes.reserve(md.second.size());
0143       for (auto const& dep : md.second) {
0144         consumes.emplace_back(dummy, dep.c_str(), "", "TEST", edm::InEvent, edm::PRODUCT_TYPE, true, false);
0145         m_modulesWhoseProductsAreConsumedBy[moduleID].push_back(m_modules[modsToIndex[dep]]);
0146         //m_modulesWhoseProductsAreConsumedBy[modsToIndex[dep]].push_back(m_modules[moduleID]);
0147       }
0148     }
0149 
0150     m_modulesOnPath.reserve(m_paths.size());
0151     for (auto const& pToM : iPaths) {
0152       m_modulesOnPath.emplace_back();
0153       auto& newPath = m_modulesOnPath.back();
0154       newPath.reserve(pToM.second.size());
0155       for (auto const& mod : pToM.second) {
0156         newPath.push_back(m_modules[modsToIndex[mod]]);
0157       }
0158     }
0159   }
0160 }  // namespace
0161 
0162 class test_checkForModuleDependencyCorrectness : public CppUnit::TestFixture {
0163   CPPUNIT_TEST_SUITE(test_checkForModuleDependencyCorrectness);
0164 
0165   CPPUNIT_TEST(onePathNoCycleTest);
0166   CPPUNIT_TEST(onePathHasCycleTest);
0167   CPPUNIT_TEST(twoPathsNoCycleTest);
0168   CPPUNIT_TEST(twoPathsWithCycleTest);
0169   CPPUNIT_TEST(duplicateModuleOnPathTest);
0170   CPPUNIT_TEST(selfCycleTest);
0171 
0172   CPPUNIT_TEST_SUITE_END();
0173 
0174 public:
0175   void setUp() {}
0176   void tearDown() {}
0177 
0178   void onePathNoCycleTest();
0179   void onePathHasCycleTest();
0180 
0181   void twoPathsNoCycleTest();
0182   void twoPathsWithCycleTest();
0183 
0184   void selfCycleTest();
0185 
0186   void duplicateModuleOnPathTest();
0187 
0188 private:
0189   bool testCase(ModuleDependsOnMap const& iModDeps, PathToModules const& iPaths) const {
0190     PathsAndConsumesOfModulesForTest pAndC(iModDeps, iPaths);
0191 
0192     checkForModuleDependencyCorrectness(pAndC, false);
0193     return true;
0194   }
0195 };
0196 
0197 ///registration of the test so that the runner can find it
0198 CPPUNIT_TEST_SUITE_REGISTRATION(test_checkForModuleDependencyCorrectness);
0199 
0200 void test_checkForModuleDependencyCorrectness::onePathNoCycleTest() {
0201   {
0202     ModuleDependsOnMap md = {{"C", {"B"}}, {"B", {"A"}}};
0203     PathToModules paths = {{"p", {"A", "B", "C"}}};
0204 
0205     CPPUNIT_ASSERT(testCase(md, paths));
0206   }
0207 
0208   {
0209     ModuleDependsOnMap md = {};
0210     PathToModules paths = {{"p", {"A", "B", "C"}}};
0211 
0212     CPPUNIT_ASSERT(testCase(md, paths));
0213   }
0214 
0215   {
0216     //Circular dependency but not connected to any path
0217     // NOTE: "A" is on the list since the ROOT of the
0218     // tree in the job is actually TriggerResults which
0219     // always connects to paths and end paths
0220     ModuleDependsOnMap md = {{"E", {"F"}}, {"F", {"G"}}, {"G", {"E"}}, {"A", {}}};
0221     PathToModules paths = {{"p", {"A", "B", "C"}}};
0222 
0223     CPPUNIT_ASSERT(testCase(md, paths));
0224   }
0225 }
0226 
0227 void test_checkForModuleDependencyCorrectness::onePathHasCycleTest() {
0228   {
0229     ModuleDependsOnMap md = {{"C", {"B"}}, {"B", {"A"}}};
0230     {
0231       PathToModules paths = {{"p", {"B", "A", "C"}}};
0232 
0233       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0234     }
0235     {
0236       PathToModules paths = {{"p", {"B", "A"}}};
0237 
0238       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0239     }
0240     {
0241       PathToModules paths = {{"p", {"C", "A"}}};
0242 
0243       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0244     }
0245     {
0246       PathToModules paths = {{"p", {"C", "B"}}};
0247 
0248       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0249     }
0250   }
0251 
0252   {
0253     ModuleDependsOnMap md = {{"C", {"B"}}};
0254     {
0255       PathToModules paths = {{"p", {"C", "A", "B"}}};
0256 
0257       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0258     }
0259     {
0260       PathToModules paths = {{"p", {"A", "C", "B"}}};
0261 
0262       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0263     }
0264     {
0265       PathToModules paths = {{"p", {"C", "B", "A"}}};
0266 
0267       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0268     }
0269   }
0270   {
0271     ModuleDependsOnMap md = {{"A", {"p"}}};
0272     {
0273       PathToModules paths = {{"p", {"A"}}};
0274 
0275       CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0276     }
0277   }
0278 }
0279 
0280 void test_checkForModuleDependencyCorrectness::twoPathsNoCycleTest() {
0281   {
0282     ModuleDependsOnMap md = {{"C", {"B"}}};
0283 
0284     {
0285       PathToModules paths = {{"p1", {"A", "B", "C"}}, {"p2", {"A", "B", "C"}}};
0286 
0287       CPPUNIT_ASSERT(testCase(md, paths));
0288     }
0289 
0290     {
0291       //CDJ DEBUG THIS IS NOW FAILING
0292       PathToModules paths = {{"p1", {"A", "B", "C"}}, {"p2", {"B", "A", "C"}}};
0293 
0294       CPPUNIT_ASSERT(testCase(md, paths));
0295     }
0296     {
0297       PathToModules paths = {{"p1", {"A", "B", "C"}}, {"p2", {"B", "C", "A"}}};
0298 
0299       CPPUNIT_ASSERT(testCase(md, paths));
0300     }
0301     {
0302       PathToModules paths = {{"p1", {"B", "A", "C"}}, {"p2", {"A", "B", "C"}}};
0303 
0304       CPPUNIT_ASSERT(testCase(md, paths));
0305     }
0306     {
0307       PathToModules paths = {{"p1", {"B", "A", "C"}}, {"p2", {"B", "A", "C"}}};
0308 
0309       CPPUNIT_ASSERT(testCase(md, paths));
0310     }
0311     {
0312       PathToModules paths = {{"p1", {"B", "A", "C"}}, {"p2", {"B", "C", "A"}}};
0313 
0314       CPPUNIT_ASSERT(testCase(md, paths));
0315     }
0316     {
0317       PathToModules paths = {{"p1", {"B", "C", "A"}}, {"p2", {"A", "B", "C"}}};
0318 
0319       CPPUNIT_ASSERT(testCase(md, paths));
0320     }
0321     {
0322       PathToModules paths = {{"p1", {"B", "C", "A"}}, {"p2", {"B", "A", "C"}}};
0323 
0324       CPPUNIT_ASSERT(testCase(md, paths));
0325     }
0326     {
0327       PathToModules paths = {{"p1", {"B", "C", "A"}}, {"p2", {"B", "C", "A"}}};
0328 
0329       CPPUNIT_ASSERT(testCase(md, paths));
0330     }
0331   }
0332 
0333   {
0334     //Test all possible 3 module combinations
0335     ModuleDependsOnMap md = {};
0336     std::vector<std::string> moduleName = {"A", "B", "C"};
0337     std::vector<std::string> pathModules;
0338     for (unsigned int i = 0; i < 3; ++i) {
0339       pathModules.push_back(moduleName[i]);
0340       for (unsigned int j = 0; j < 3; ++j) {
0341         if (j == i) {
0342           continue;
0343         }
0344         pathModules.push_back(moduleName[j]);
0345         for (unsigned int k = 0; k < 3; ++k) {
0346           if (j == k or i == k) {
0347             continue;
0348           }
0349           pathModules.push_back(moduleName[k]);
0350 
0351           std::vector<std::string> path2Modules;
0352           for (unsigned int ii = 0; ii < 3; ++ii) {
0353             path2Modules.push_back(moduleName[ii]);
0354             for (unsigned int jj = 0; jj < 3; ++jj) {
0355               if (jj == ii) {
0356                 continue;
0357               }
0358               path2Modules.push_back(moduleName[jj]);
0359               for (unsigned int kk = 0; kk < 3; ++kk) {
0360                 if (jj == kk or ii == kk) {
0361                   continue;
0362                 }
0363                 path2Modules.push_back(moduleName[kk]);
0364                 PathToModules paths;
0365                 paths["p1"] = pathModules;
0366                 paths["p2"] = path2Modules;
0367                 CPPUNIT_ASSERT(testCase(md, paths));
0368                 path2Modules.pop_back();
0369               }
0370               path2Modules.pop_back();
0371             }
0372             path2Modules.pop_back();
0373           }
0374 
0375           pathModules.pop_back();
0376         }
0377         pathModules.pop_back();
0378       }
0379       pathModules.pop_back();
0380     }
0381   }
0382 
0383   {
0384     ModuleDependsOnMap md = {{"C", {"B"}}, {"B", {"A"}}, {"D", {"C"}}};
0385 
0386     {
0387       PathToModules paths = {{"p1", {"A", "C"}}, {"p2", {"B", "D"}}};
0388 
0389       CPPUNIT_ASSERT(testCase(md, paths));
0390     }
0391 
0392     {
0393       PathToModules paths = {{"p1", {"A", "D"}}, {"p2", {"B", "C"}}};
0394 
0395       CPPUNIT_ASSERT(testCase(md, paths));
0396     }
0397     {
0398       PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0399 
0400       CPPUNIT_ASSERT(testCase(md, paths));
0401     }
0402 
0403     {
0404       PathToModules paths = {{"p1", {"A"}}, {"p2", {"C", "D"}}};
0405 
0406       CPPUNIT_ASSERT(testCase(md, paths));
0407     }
0408     {
0409       PathToModules paths = {{"p1", {"A"}}, {"p2", {"D"}}};
0410 
0411       CPPUNIT_ASSERT(testCase(md, paths));
0412     }
0413     {
0414       PathToModules paths = {{"p1", {"A"}}, {"p2", {"C"}}};
0415 
0416       CPPUNIT_ASSERT(testCase(md, paths));
0417     }
0418 
0419     {
0420       PathToModules paths = {{"p1", {"B"}}, {"p2", {"D"}}};
0421 
0422       CPPUNIT_ASSERT(testCase(md, paths));
0423     }
0424 
0425     {
0426       PathToModules paths = {{"p1", {"B"}}, {"p2", {"C"}}};
0427 
0428       CPPUNIT_ASSERT(testCase(md, paths));
0429     }
0430     {
0431       PathToModules paths = {{"p1", {"C"}}, {"p2", {"D"}}};
0432 
0433       CPPUNIT_ASSERT(testCase(md, paths));
0434     }
0435 
0436     {
0437       PathToModules paths = {{"p1", {"A", "C"}}, {"p2", {"A", "D"}}};
0438 
0439       CPPUNIT_ASSERT(testCase(md, paths));
0440     }
0441     {
0442       PathToModules paths = {{"p1", {"A", "C"}}, {"p2", {"A", "D"}}};
0443 
0444       CPPUNIT_ASSERT(testCase(md, paths));
0445     }
0446   }
0447 
0448   {
0449     ModuleDependsOnMap md = {{"B", {"C"}}, {"D", {"A"}}};
0450     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0451 
0452     CPPUNIT_ASSERT(testCase(md, paths));
0453   }
0454 
0455   {
0456     ModuleDependsOnMap md = {{"B", {"E"}}, {"E", {"C"}}, {"D", {"F"}}, {"F", {"A"}}};
0457     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0458 
0459     CPPUNIT_ASSERT(testCase(md, paths));
0460   }
0461 
0462   {
0463     ModuleDependsOnMap md = {{"B", {"E"}}, {"E", {"C"}}, {"D", {"E"}}, {"E", {"A"}}};
0464     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0465 
0466     CPPUNIT_ASSERT(testCase(md, paths));
0467   }
0468 
0469   {
0470     ModuleDependsOnMap md = {{"B", {"E"}}, {"C", {"E"}}, {"D", {"E"}}, {"A", {"E"}}};
0471     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0472 
0473     CPPUNIT_ASSERT(testCase(md, paths));
0474   }
0475 
0476   {
0477     //Simplified schedule which was failing
0478     ModuleDependsOnMap md = {{"H", {"A"}}};
0479     PathToModules paths = {{"reco", {"I", "A", "H", "G", "F", "E"}}, {"val", {"E", "D", "C", "B", "A"}}};
0480 
0481     CPPUNIT_ASSERT(testCase(md, paths));
0482   }
0483 
0484   {
0485     //Simplified schedule which was failing
0486     ModuleDependsOnMap md = {{"B", {"X"}}, {"Y", {"Z"}}, {"Z", {"A"}}};
0487     PathToModules paths = {{"p1", {"X", "B", "A"}}, {"p2", {"A", "Z", "?", "Y", "X"}}};
0488 
0489     CPPUNIT_ASSERT(testCase(md, paths));
0490   }
0491   {
0492     //Simplified schedule which was failing
0493     ModuleDependsOnMap md = {{"B", {"X"}}, {"Y", {"Z"}}, {"Z", {"A"}}, {"?", {}}, {"A", {}}, {"X", {}}};
0494     PathToModules paths = {{"p1", {"X", "B", "A"}}, {"p2", {"A", "Z", "?", "Y", "X"}}};
0495     CPPUNIT_ASSERT(testCase(md, paths));
0496   }
0497 
0498   {
0499     //Simplified schedule which was failing
0500     // The data dependency for 'D" can be met
0501     // by the order of modules on path p2
0502     ModuleDependsOnMap md = {{"A_TR", {"zEP1", "zEP2"}}, {"D", {"B"}}, {"E", {"D"}}, {"zSEP3", {"A_TR"}}};
0503     PathToModules paths = {{"p1", {"E", "F", "zEP1"}}, {"p2", {"B", "C", "D", "zEP2"}}, {"p3", {"zSEP3", "B", "zEP3"}}};
0504 
0505     CPPUNIT_ASSERT(testCase(md, paths));
0506   }
0507 
0508   {
0509     //The same sequence of modules appear on a Path and EndPath
0510     // Check that the framework does not get confused when jumping
0511     // from one path to the other path just because of the
0512     // TriggerResults connection.
0513 
0514     ModuleDependsOnMap md = {{"A_TR", {"zEP1"}},
0515                              {"A", {"B"}},
0516                              {"B", {"H"}},
0517                              {"C", {}},
0518                              {"D", {}},
0519                              {"E", {}},
0520                              {"G", {"D"}},
0521                              {"H", {"D"}},
0522                              {"zEP1", {}},
0523                              {"zSEP2", {"A_TR"}}};
0524     PathToModules paths = {{"p2", {"D", "G", "H", "B", "C", "zEP1"}},
0525                            {"p3", {"A"}},  //Needed to make graph search start here
0526                            {"p1", {"zSEP2", "E", "D", "G", "H", "B", "C"}}};
0527 
0528     CPPUNIT_ASSERT(testCase(md, paths));
0529   }
0530 
0531   {
0532     //Have a module which can not be run initially be needed by two other modules
0533     ModuleDependsOnMap md = {{"out", {"A", "B"}}, {"A", {"D"}}, {"B", {"D"}}};
0534     PathToModules paths = {{"p1", {"filter", "D"}}, {"p2", {"out"}}};
0535     CPPUNIT_ASSERT(testCase(md, paths));
0536   }
0537   {
0538     //like above, but with path names reversed
0539     ModuleDependsOnMap md = {{"out", {"A", "B"}}, {"A", {"D"}}, {"B", {"D"}}};
0540     PathToModules paths = {{"p1", {"out"}}, {"p2", {"filter", "D"}}};
0541     CPPUNIT_ASSERT(testCase(md, paths));
0542   }
0543 
0544   {
0545     //Have a module which can not be run initially be needed by two other modules
0546     ModuleDependsOnMap md = {{"out", {"A", "B"}}, {"A", {"D"}}, {"B", {"D"}}, {"D", {"E"}}};
0547     PathToModules paths = {{"p1", {"filter", "E"}}, {"p2", {"out"}}};
0548     CPPUNIT_ASSERT(testCase(md, paths));
0549   }
0550   {
0551     //like above, but with path names reversed
0552     ModuleDependsOnMap md = {{"out", {"A", "B"}}, {"A", {"D"}}, {"B", {"D"}}, {"D", {"E"}}};
0553     PathToModules paths = {{"p1", {"out"}}, {"p2", {"filter", "E"}}};
0554     CPPUNIT_ASSERT(testCase(md, paths));
0555   }
0556 }
0557 
0558 void test_checkForModuleDependencyCorrectness::twoPathsWithCycleTest() {
0559   {
0560     ModuleDependsOnMap md = {{"C", {"B"}}, {"A", {"D"}}};
0561     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0562 
0563     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0564   }
0565 
0566   {
0567     //Add additional dependencies to test that they are ignored
0568     ModuleDependsOnMap md = {{"C", {"E", "F", "G", "B"}}, {"A", {"D"}}};
0569     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0570 
0571     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0572   }
0573 
0574   {
0575     ModuleDependsOnMap md = {{"C", {"B"}}, {"A", {"D"}}};
0576     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D", "A"}}};
0577 
0578     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0579   }
0580 
0581   {
0582     ModuleDependsOnMap md = {{"C", {"B"}}, {"A", {"D"}}, {"B", {"A"}}, {"D", {"C"}}};
0583     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0584 
0585     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0586   }
0587 
0588   {
0589     ModuleDependsOnMap md = {{"E", {"B"}}, {"C", {"E"}}, {"A", {"D"}}};
0590     PathToModules paths = {{"p1", {"A", "B"}}, {"p2", {"C", "D"}}};
0591 
0592     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0593   }
0594 
0595   {
0596     ModuleDependsOnMap md = {{"A", {"B"}}, {"B", {"C"}}, {"C", {"D"}}, {"D", {"B"}}};
0597     PathToModules paths = {{"p1", {"A", "EP"}}};
0598 
0599     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0600   }
0601 
0602   {
0603     //Simplified schedule which was failing
0604     ModuleDependsOnMap md = {{"B", {"X"}}, {"Y", {"Z"}}, {"Z", {"A"}}, {"?", {}}, {"A", {}}, {"X", {}}};
0605     //NOTE: p1 is inconsistent but with p2 it would be runnable.
0606     PathToModules paths = {{"p1", {"B", "A", "X"}}, {"p2", {"A", "Z", "?", "Y", "X"}}};
0607     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0608   }
0609 
0610   {
0611     ModuleDependsOnMap md = {{"A_TR", {"EP1", "EP2"}},  //assigned aTR==0, EP1==1, EP2==2
0612                              {"C", {"A"}},
0613                              {"D", {"A"}},
0614                              {"E", {"D"}},
0615                              {"BP", {"A_TR"}}};
0616 
0617     PathToModules paths = {{"p1", {"A", "B", "C", "EP1"}}, {"p2", {"E", "EP2"}}, {"ep", {"BP", "A", "D"}}};
0618     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0619   }
0620 
0621   {
0622     // The data dependency for 'D" can be met
0623     // by the order of modules on path p2
0624     // but NOT by path3
0625     ModuleDependsOnMap md = {{"A_TR", {"zEP1", "zEP2", "zEP3"}}, {"D", {"B"}}, {"E", {"D"}}, {"zSEP4", {"A_TR"}}};
0626     PathToModules paths = {{"p1", {"E", "F", "zEP1"}},
0627                            {"p2", {"Filter", "B", "C", "D", "zEP2"}},
0628                            {"p3", {"C", "D", "zEP3"}},
0629                            {"p4", {"zSEP4", "B", "zEP4"}}};
0630 
0631     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0632   }
0633 
0634   {
0635     // The data dependency for 'D" can be met
0636     // by the order of modules on path p2
0637     // but NOT by path3
0638     ModuleDependsOnMap md = {{"A_TR", {"zEP1", "zEP2", "zEP3"}}, {"D", {"B"}}, {"E", {"D"}}, {"zSEP4", {"A_TR"}}};
0639     PathToModules paths = {{"p1", {"E", "F", "zEP1"}},
0640                            {"p2", {"Filter", "B", "D", "zEP2"}},
0641                            {"p3", {"C", "D", "zEP3"}},
0642                            {"p4", {"zSEP4", "B", "zEP4"}}};
0643 
0644     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0645   }
0646 
0647   {
0648     // The data dependency for 'D" can be met
0649     // by the order of modules on path p2
0650     // but NOT by path3
0651     ModuleDependsOnMap md = {{"A_TR", {"zEP1", "zEP2"}}, {"B", {}}, {"zFilter", {"A_TR"}}};
0652     PathToModules paths = {{"p1", {"zFilter", "B", "zEP1"}}, {"p2", {"zFilter", "B", "zEP2"}}};
0653 
0654     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0655   }
0656 
0657   {
0658     ModuleDependsOnMap md = {{"B", {"A"}}, {"C", {"B"}}, {"cFilter", {"C"}}};
0659     PathToModules paths = {{"p1", {"C", "cFilter", "D", "E", "F", "A", "B"}}, {"p2", {"oFilter", "D", "F", "B"}}};
0660 
0661     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0662   }
0663 }
0664 
0665 void test_checkForModuleDependencyCorrectness::selfCycleTest() {
0666   {
0667     ModuleDependsOnMap md = {{"A", {"A"}}};
0668     PathToModules paths = {{"p", {"A"}}};
0669 
0670     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0671   }
0672   {
0673     ModuleDependsOnMap md = {{"A", {"A"}}, {"B", {"A"}}};
0674     PathToModules paths = {{"p", {"B"}}};
0675 
0676     CPPUNIT_ASSERT_THROW(testCase(md, paths), cms::Exception);
0677   }
0678 }
0679 
0680 void test_checkForModuleDependencyCorrectness::duplicateModuleOnPathTest() {
0681   {
0682     ModuleDependsOnMap md = {{"C", {"B"}}, {"B", {"A"}}};
0683     PathToModules paths = {{"p", {"A", "B", "C", "A"}}};
0684 
0685     CPPUNIT_ASSERT(testCase(md, paths));
0686   }
0687 }