Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-05-09 22:37:41

0001 
0002 // Test code for the ParameterSetDescription and ParameterDescription
0003 // classes.
0004 
0005 #include "catch.hpp"
0006 
0007 #include "DataFormats/Provenance/interface/EventID.h"
0008 #include "DataFormats/Provenance/interface/LuminosityBlockID.h"
0009 #include "FWCore/ParameterSet/interface/AllowedLabelsDescription.h"
0010 #include "FWCore/ParameterSet/interface/IfExistsDescription.h"
0011 #include "FWCore/Utilities/interface/FileInPath.h"
0012 #include "FWCore/ParameterSet/interface/ParameterDescriptionBase.h"
0013 #include "FWCore/ParameterSet/interface/ParameterDescriptionNode.h"
0014 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0015 #include "FWCore/ParameterSet/interface/ParameterWildcardWithSpecifics.h"
0016 #include "FWCore/ParameterSet/interface/allowedValues.h"
0017 #include "FWCore/ParameterSet/interface/PluginDescription.h"
0018 #include "FWCore/ParameterSet/interface/ValidatedPluginMacros.h"
0019 #include "FWCore/ParameterSet/interface/ValidatedPluginFactoryMacros.h"
0020 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0021 #include "FWCore/PluginManager/interface/PluginManager.h"
0022 #include "FWCore/PluginManager/interface/standard.h"
0023 #include "FWCore/Utilities/interface/EDMException.h"
0024 #include "FWCore/Utilities/interface/Exception.h"
0025 #include "FWCore/Utilities/interface/InputTag.h"
0026 
0027 #include <cassert>
0028 #include <iostream>
0029 #include <string>
0030 #include <vector>
0031 
0032 namespace testParameterSetDescription {
0033 
0034   void testDesc(edm::ParameterDescriptionNode const& node,
0035                 edm::ParameterSetDescription const& psetDesc,
0036                 edm::ParameterSet& pset,
0037                 bool exists,
0038                 bool validates) {
0039     CHECK(node.exists(pset) == exists);
0040     CHECK(node.partiallyExists(pset) == exists);
0041     CHECK(node.howManyXORSubNodesExist(pset) == (exists ? 1 : 0));
0042     if (validates) {
0043       psetDesc.validate(pset);
0044     } else {
0045       REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
0046     }
0047   }
0048 
0049   struct TestPluginBase {
0050     virtual ~TestPluginBase() = default;
0051   };
0052 
0053   struct ATestPlugin : public TestPluginBase {
0054     static void fillPSetDescription(edm::ParameterSetDescription& iPS) { iPS.add<int>("anInt", 5); }
0055   };
0056 
0057   struct BTestPlugin : public TestPluginBase {
0058     static void fillPSetDescription(edm::ParameterSetDescription& iPS) { iPS.add<double>("aDouble", 0.5); }
0059   };
0060 
0061   struct CTestPlugin : public TestPluginBase {
0062     static void fillPSetDescription(edm::ParameterSetDescription& iPS) { iPS.addUntracked<int>("anInt", 42); }
0063   };
0064 
0065   using TestPluginFactory = edmplugin::PluginFactory<testParameterSetDescription::TestPluginBase*()>;
0066 
0067 }  // namespace testParameterSetDescription
0068 
0069 using TestPluginFactory = testParameterSetDescription::TestPluginFactory;
0070 
0071 using testParameterSetDescription::testDesc;
0072 
0073 TEST_CASE("test ParameterSetDescription", "[ParameterSetDescription]") {
0074   static std::once_flag flag;
0075   std::call_once(flag, []() { edmplugin::PluginManager::configure(edmplugin::standard::config()); });
0076 
0077   SECTION("testWildcards") {
0078     using Catch::Matchers::Equals;
0079     {
0080       edm::ParameterSetDescription set;
0081       edm::ParameterWildcard<int> w("*", edm::RequireZeroOrMore, true);
0082       set.addNode(w);
0083       edm::ParameterSet pset;
0084       testDesc(w, set, pset, true, true);
0085       pset.addParameter<int>("x", 1);
0086       testDesc(w, set, pset, true, true);
0087       pset.addParameter<int>("y", 1);
0088       testDesc(w, set, pset, true, true);
0089       pset.addParameter<unsigned>("z", 1);
0090       testDesc(w, set, pset, true, false);
0091 
0092       SECTION("cfi generation") {
0093         std::ostringstream os;
0094         bool startWithComma = false;
0095         bool wroteSomething = false;
0096         edm::CfiOptions ops = edm::cfi::Typed{};
0097         w.writeCfi(os, edm::ParameterModifier::kNone, startWithComma, 0, ops, wroteSomething);
0098 
0099         REQUIRE_THAT(os.str(), Equals("\nallowAnyLabel_ = cms.required.int32"));
0100       }
0101     }
0102 
0103     {
0104       edm::ParameterSetDescription set;
0105       edm::ParameterWildcard<unsigned> w("*", edm::RequireExactlyOne, false);
0106       set.addNode(w);
0107       edm::ParameterSet pset;
0108       testDesc(w, set, pset, false, false);
0109       pset.addUntrackedParameter<unsigned>("x", 1);
0110       testDesc(w, set, pset, true, true);
0111       pset.addUntrackedParameter<unsigned>("y", 1);
0112       testDesc(w, set, pset, false, false);
0113 
0114       SECTION("cfi generation") {
0115         std::ostringstream os;
0116         bool startWithComma = false;
0117         bool wroteSomething = false;
0118         edm::CfiOptions ops = edm::cfi::Typed{};
0119 
0120         w.writeCfi(os, edm::ParameterModifier::kNone, startWithComma, 0, ops, wroteSomething);
0121 
0122         REQUIRE_THAT(os.str(), Equals("\nallowAnyLabel_ = cms.required.untracked.uint32"));
0123       }
0124     }
0125 
0126     {
0127       edm::ParameterSetDescription set;
0128       edm::ParameterWildcard<unsigned> w("*", edm::RequireExactlyOne, false);
0129       set.addOptionalNode(w, false);
0130       edm::ParameterSet pset;
0131       testDesc(w, set, pset, false, true);
0132       pset.addUntrackedParameter<unsigned>("x", 1);
0133       testDesc(w, set, pset, true, true);
0134       pset.addUntrackedParameter<unsigned>("y", 1);
0135       testDesc(w, set, pset, false, false);
0136     }
0137 
0138     {
0139       edm::ParameterSetDescription set;
0140       edm::ParameterWildcard<unsigned> w("*", edm::RequireAtLeastOne, false);
0141       set.addOptionalNode(w, false);
0142       edm::ParameterSet pset;
0143       testDesc(w, set, pset, false, true);
0144       pset.addUntrackedParameter<unsigned>("x", 1);
0145       testDesc(w, set, pset, true, true);
0146       pset.addUntrackedParameter<unsigned>("y", 1);
0147       testDesc(w, set, pset, true, true);
0148     }
0149 
0150     {
0151       edm::ParameterSetDescription set;
0152       edm::ParameterWildcard<double> w("*", edm::RequireAtLeastOne, true);
0153       set.addNode(w);
0154       edm::ParameterSet pset;
0155       testDesc(w, set, pset, false, false);
0156       pset.addParameter<double>("x", 1);
0157       testDesc(w, set, pset, true, true);
0158       pset.addParameter<double>("y", 1);
0159       testDesc(w, set, pset, true, true);
0160 
0161       SECTION("cfi generation") {
0162         std::ostringstream os;
0163         bool startWithComma = false;
0164         bool wroteSomething = false;
0165         edm::CfiOptions ops = edm::cfi::Typed{};
0166 
0167         w.writeCfi(os, edm::ParameterModifier::kNone, startWithComma, 0, ops, wroteSomething);
0168 
0169         REQUIRE_THAT(os.str(), Equals("\nallowAnyLabel_ = cms.required.double"));
0170       }
0171     }
0172 
0173     {
0174       edm::ParameterSetDescription set;
0175       edm::ParameterWildcard<double> w("*", edm::RequireAtLeastOne, true);
0176       set.addNode(w);
0177       set.add<int>("testTypeChecking1", 11);
0178       REQUIRE_THROWS_AS(set.add<double>("testTypeChecking2", 11.0), edm::Exception);
0179     }
0180 
0181     REQUIRE_THROWS_AS(edm::ParameterWildcard<int>("a*", edm::RequireZeroOrMore, true), edm::Exception);
0182 
0183     edm::ParameterSet nestedPset;
0184     nestedPset.addUntrackedParameter<unsigned>("n1", 1);
0185 
0186     {
0187       edm::ParameterSetDescription set;
0188       edm::ParameterWildcard<edm::ParameterSetDescription> w("*", edm::RequireZeroOrMore, true);
0189       set.addNode(w);
0190       edm::ParameterSet pset;
0191       testDesc(w, set, pset, true, true);
0192       pset.addParameter<edm::ParameterSet>("nested1", nestedPset);
0193       testDesc(w, set, pset, true, true);
0194       pset.addParameter<edm::ParameterSet>("nested2", nestedPset);
0195       testDesc(w, set, pset, true, true);
0196 
0197       SECTION("cfi generation") {
0198         std::ostringstream os;
0199         bool startWithComma = false;
0200         bool wroteSomething = false;
0201         edm::CfiOptions ops = edm::cfi::Typed{};
0202         w.writeCfi(os, edm::ParameterModifier::kNone, startWithComma, 0, ops, wroteSomething);
0203 
0204         REQUIRE_THAT(os.str(), Equals("\nallowAnyLabel_ = cms.required.PSetTemplate()"));
0205       }
0206     }
0207 
0208     {
0209       edm::ParameterSetDescription set;
0210       edm::ParameterWildcard<edm::ParameterSetDescription> w(std::string("*"), edm::RequireZeroOrMore, true);
0211       set.addNode(w);
0212       edm::ParameterSet pset;
0213       testDesc(w, set, pset, true, true);
0214       pset.addParameter<edm::ParameterSet>("nested1", nestedPset);
0215       testDesc(w, set, pset, true, true);
0216       pset.addParameter<edm::ParameterSet>("nested2", nestedPset);
0217       testDesc(w, set, pset, true, true);
0218     }
0219 
0220     {
0221       edm::ParameterSetDescription set;
0222       edm::ParameterWildcard<edm::ParameterSetDescription> w(
0223           "*", edm::RequireZeroOrMore, true, edm::ParameterSetDescription());
0224       set.addNode(w);
0225       edm::ParameterSet pset;
0226       testDesc(w, set, pset, true, true);
0227       pset.addParameter<edm::ParameterSet>("nested1", nestedPset);
0228       testDesc(w, set, pset, true, false);
0229       pset.addParameter<edm::ParameterSet>("nested2", nestedPset);
0230       testDesc(w, set, pset, true, false);
0231     }
0232 
0233     edm::ParameterSetDescription nestedDesc;
0234     nestedDesc.addUntracked<unsigned>("n1", 1);
0235 
0236     {
0237       edm::ParameterSetDescription set;
0238       edm::ParameterWildcard<edm::ParameterSetDescription> w("*", edm::RequireZeroOrMore, true, nestedDesc);
0239       set.addNode(w);
0240       edm::ParameterSet pset;
0241       testDesc(w, set, pset, true, true);
0242       pset.addParameter<edm::ParameterSet>("nested1", nestedPset);
0243       testDesc(w, set, pset, true, true);
0244       pset.addParameter<edm::ParameterSet>("nested2", nestedPset);
0245       testDesc(w, set, pset, true, true);
0246 
0247       SECTION("cfi generation") {
0248         std::ostringstream os;
0249         bool startWithComma = false;
0250         bool wroteSomething = false;
0251         edm::CfiOptions ops = edm::cfi::Typed{};
0252         w.writeCfi(os, edm::ParameterModifier::kNone, startWithComma, 0, ops, wroteSomething);
0253 
0254         REQUIRE_THAT(os.str(),
0255                      Equals("\nallowAnyLabel_ = cms.required.PSetTemplate(\n  n1 = cms.untracked.uint32(1)\n)"));
0256       }
0257     }
0258 
0259     {
0260       edm::ParameterSetDescription set;
0261       edm::ParameterWildcard<edm::ParameterSetDescription> w(
0262           std::string("*"), edm::RequireExactlyOne, true, nestedDesc);
0263       set.addNode(w);
0264       edm::ParameterSet pset;
0265       testDesc(w, set, pset, false, false);
0266       pset.addParameter<edm::ParameterSet>("nested1", nestedPset);
0267       testDesc(w, set, pset, true, true);
0268       pset.addParameter<edm::ParameterSet>("nested2", nestedPset);
0269       testDesc(w, set, pset, false, false);
0270     }
0271 
0272     {
0273       edm::ParameterSetDescription set;
0274       edm::ParameterWildcard<edm::ParameterSetDescription> w("*", edm::RequireAtLeastOne, true, nestedDesc);
0275       set.addNode(w);
0276       edm::ParameterSet pset;
0277       testDesc(w, set, pset, false, false);
0278       pset.addParameter<edm::ParameterSet>("nested1", nestedPset);
0279       testDesc(w, set, pset, true, true);
0280       pset.addParameter<edm::ParameterSet>("nested2", nestedPset);
0281       testDesc(w, set, pset, true, true);
0282     }
0283 
0284     std::vector<edm::ParameterSet> nestedVPset;
0285     edm::ParameterSet vectorElement;
0286     vectorElement.addUntrackedParameter<unsigned>("n11", 1);
0287     nestedVPset.push_back(vectorElement);
0288     nestedVPset.push_back(vectorElement);
0289 
0290     {
0291       edm::ParameterSetDescription set;
0292       edm::ParameterWildcard<std::vector<edm::ParameterSet>> w("*", edm::RequireZeroOrMore, true);
0293       set.addNode(w);
0294       edm::ParameterSet pset;
0295       testDesc(w, set, pset, true, true);
0296       pset.addParameter<std::vector<edm::ParameterSet>>("nested1", nestedVPset);
0297       testDesc(w, set, pset, true, true);
0298       pset.addParameter<std::vector<edm::ParameterSet>>("nested2", nestedVPset);
0299       testDesc(w, set, pset, true, true);
0300       SECTION("cfi generation") {
0301         std::ostringstream os;
0302         bool startWithComma = false;
0303         bool wroteSomething = false;
0304         edm::CfiOptions ops = edm::cfi::Typed{};
0305         w.writeCfi(os, edm::ParameterModifier::kNone, startWithComma, 0, ops, wroteSomething);
0306 
0307         REQUIRE_THAT(os.str(), Equals("\nallowAnyLabel_ = cms.required.VPSet"));
0308       }
0309     }
0310 
0311     {
0312       edm::ParameterSetDescription set;
0313       edm::ParameterWildcard<std::vector<edm::ParameterSet>> w(std::string("*"), edm::RequireZeroOrMore, true);
0314       set.addNode(w);
0315       edm::ParameterSet pset;
0316       testDesc(w, set, pset, true, true);
0317       pset.addParameter<std::vector<edm::ParameterSet>>("nested1", nestedVPset);
0318       testDesc(w, set, pset, true, true);
0319       pset.addParameter<std::vector<edm::ParameterSet>>("nested2", nestedVPset);
0320       testDesc(w, set, pset, true, true);
0321     }
0322 
0323     {
0324       edm::ParameterSetDescription set;
0325       edm::ParameterWildcard<std::vector<edm::ParameterSet>> w(
0326           "*", edm::RequireZeroOrMore, true, edm::ParameterSetDescription());
0327       set.addNode(w);
0328       edm::ParameterSet pset;
0329       testDesc(w, set, pset, true, true);
0330       pset.addParameter<std::vector<edm::ParameterSet>>("nested1", nestedVPset);
0331       testDesc(w, set, pset, true, false);
0332       pset.addParameter<std::vector<edm::ParameterSet>>("nested2", nestedVPset);
0333       testDesc(w, set, pset, true, false);
0334     }
0335 
0336     edm::ParameterSetDescription descElement;
0337     descElement.addUntracked<unsigned>("n11", 1);
0338     {
0339       edm::ParameterSetDescription set;
0340       edm::ParameterWildcard<std::vector<edm::ParameterSet>> w("*", edm::RequireZeroOrMore, true, descElement);
0341       set.addNode(w);
0342       edm::ParameterSet pset;
0343       testDesc(w, set, pset, true, true);
0344       pset.addParameter<std::vector<edm::ParameterSet>>("nested1", nestedVPset);
0345       testDesc(w, set, pset, true, true);
0346       pset.addParameter<std::vector<edm::ParameterSet>>("nested2", nestedVPset);
0347       testDesc(w, set, pset, true, true);
0348     }
0349 
0350     {
0351       edm::ParameterSetDescription set;
0352       edm::ParameterWildcard<std::vector<edm::ParameterSet>> w(
0353           std::string("*"), edm::RequireExactlyOne, true, descElement);
0354       set.addNode(w);
0355       edm::ParameterSet pset;
0356       testDesc(w, set, pset, false, false);
0357       pset.addParameter<std::vector<edm::ParameterSet>>("nested1", nestedVPset);
0358       testDesc(w, set, pset, true, true);
0359       pset.addParameter<std::vector<edm::ParameterSet>>("nested2", nestedVPset);
0360       testDesc(w, set, pset, false, false);
0361     }
0362 
0363     {
0364       edm::ParameterSetDescription set;
0365       edm::ParameterWildcard<std::vector<edm::ParameterSet>> w("*", edm::RequireAtLeastOne, true, descElement);
0366       set.addNode(w);
0367       edm::ParameterSet pset;
0368       testDesc(w, set, pset, false, false);
0369       pset.addParameter<std::vector<edm::ParameterSet>>("nested1", nestedVPset);
0370       testDesc(w, set, pset, true, true);
0371       pset.addParameter<std::vector<edm::ParameterSet>>("nested2", nestedVPset);
0372       testDesc(w, set, pset, true, true);
0373     }
0374   }
0375 
0376   SECTION("testWildcardWithExceptions") {
0377     {
0378       edm::ParameterSetDescription set;
0379 
0380       edm::ParameterSetDescription wild;
0381       wild.addUntracked<unsigned>("n11", 1);
0382 
0383       edm::ParameterSetDescription except_;
0384       except_.addUntracked<double>("f", 3.14);
0385       std::map<std::string, edm::ParameterSetDescription> excptions = {{"special", except_}};
0386       edm::ParameterWildcardWithSpecifics w("*", edm::RequireZeroOrMore, true, wild, std::move(excptions));
0387       set.addNode(w);
0388       edm::ParameterSet pset;
0389       testDesc(w, set, pset, true, true);
0390       edm::ParameterSet nested1;
0391       nested1.addUntrackedParameter<unsigned>("n11", 3);
0392       pset.addParameter<edm::ParameterSet>("nested1", nested1);
0393       testDesc(w, set, pset, true, true);
0394       edm::ParameterSet special;
0395       special.addUntrackedParameter<double>("f", 5);
0396       pset.addParameter<edm::ParameterSet>("special", special);
0397       testDesc(w, set, pset, true, true);
0398     }
0399 
0400     {
0401       edm::ParameterSetDescription set;
0402 
0403       edm::ParameterSetDescription wild;
0404       wild.add<unsigned>("n11", 1);
0405 
0406       edm::ParameterSetDescription except_;
0407       except_.add<double>("f", 3.14);
0408       std::map<std::string, edm::ParameterSetDescription> excptions = {{"special", except_}};
0409       edm::ParameterWildcardWithSpecifics w("*", edm::RequireZeroOrMore, true, wild, std::move(excptions));
0410       set.addNode(w);
0411       edm::ParameterSet pset;
0412       testDesc(w, set, pset, true, true);
0413       edm::ParameterSet nested1;
0414       nested1.addParameter<unsigned>("n11", 3);
0415       pset.addParameter<edm::ParameterSet>("nested1", nested1);
0416       testDesc(w, set, pset, true, true);
0417       edm::ParameterSet special;
0418       special.addParameter<double>("f", 5);
0419       pset.addParameter<edm::ParameterSet>("special", special);
0420       testDesc(w, set, pset, true, true);
0421     }
0422   }
0423 
0424   // ---------------------------------------------------------------------------------
0425 
0426   SECTION("testAllowedValues") {
0427     // Duplicate case values not allowed
0428     edm::ParameterSetDescription psetDesc;
0429     psetDesc.ifValue(edm::ParameterDescription<std::string>("sswitch", "a", true),
0430                      edm::allowedValues<std::string>("a", "h", "z"));
0431   }
0432 
0433   SECTION("testSwitch") {
0434     // Duplicate case values not allowed
0435     edm::ParameterSetDescription psetDesc;
0436     REQUIRE_THROWS_AS(psetDesc.ifValue(edm::ParameterDescription<int>("oiswitch", 1, true),
0437                                        0 >> edm::ParameterDescription<int>("oivalue", 100, true) or
0438                                            1 >> (edm::ParameterDescription<double>("oivalue1", 101.0, true) and
0439                                                  edm::ParameterDescription<double>("oivalue2", 101.0, true)) or
0440                                            1 >> edm::ParameterDescription<std::string>("oivalue", "102", true)),
0441                       edm::Exception);
0442 
0443     // Types used in case parameters cannot duplicate type already used in a wildcard
0444     edm::ParameterSetDescription psetDesc1;
0445     edm::ParameterWildcard<double> w("*", edm::RequireAtLeastOne, true);
0446     psetDesc1.addNode(w);
0447 
0448     REQUIRE_THROWS_AS(psetDesc1.ifValue(edm::ParameterDescription<int>("oiswitch", 1, true),
0449                                         0 >> edm::ParameterDescription<int>("oivalue", 100, true) or
0450                                             1 >> (edm::ParameterDescription<double>("oivalue1", 101.0, true) and
0451                                                   edm::ParameterDescription<double>("oivalue2", 101.0, true)) or
0452                                             2 >> edm::ParameterDescription<std::string>("oivalue", "102", true)),
0453                       edm::Exception);
0454 
0455     // Types used in the switch parameter cannot duplicate type already used in a wildcard
0456     edm::ParameterSetDescription psetDesc2;
0457     edm::ParameterWildcard<int> w1("*", edm::RequireAtLeastOne, true);
0458     psetDesc2.addNode(w1);
0459 
0460     REQUIRE_THROWS_AS(psetDesc2.ifValue(edm::ParameterDescription<int>("aswitch", 1, true),
0461                                         1 >> (edm::ParameterDescription<unsigned>("avalue1", 101, true) and
0462                                               edm::ParameterDescription<unsigned>("avalue2", 101, true)) or
0463                                             2 >> edm::ParameterDescription<std::string>("avalue", "102", true)),
0464                       edm::Exception);
0465 
0466     // Type used in the switch parameter cannot duplicate type in a case wildcard
0467     edm::ParameterSetDescription psetDesc3;
0468     REQUIRE_THROWS_AS(psetDesc3.ifValue(edm::ParameterDescription<int>("xswitch", 1, true),
0469                                         0 >> edm::ParameterWildcard<int>("*", edm::RequireAtLeastOne, true) or
0470                                             1 >> (edm::ParameterDescription<double>("xvalue1", 101.0, true) and
0471                                                   edm::ParameterDescription<double>("xvalue2", 101.0, true))),
0472                       edm::Exception);
0473 
0474     // Type used in a parameter cannot duplicate type in a case wildcard
0475     edm::ParameterSetDescription psetDesc4;
0476     psetDesc4.add<unsigned>("testunsigned", 1U);
0477     REQUIRE_THROWS_AS(psetDesc4.ifValue(edm::ParameterDescription<int>("xswitch", 1, true),
0478                                         0 >> edm::ParameterWildcard<unsigned>("*", edm::RequireAtLeastOne, true) or
0479                                             1 >> (edm::ParameterDescription<double>("xvalue1", 101.0, true) and
0480                                                   edm::ParameterDescription<double>("xvalue2", 101.0, true))),
0481                       edm::Exception);
0482 
0483     // No problem is wildcard type and parameter type are the same for different cases.
0484     edm::ParameterSetDescription psetDesc5;
0485     psetDesc5.ifValue(edm::ParameterDescription<int>("uswitch", 1, true),
0486                       0 >> edm::ParameterWildcard<unsigned>("*", edm::RequireAtLeastOne, true) or
0487                           1 >> (edm::ParameterDescription<unsigned>("uvalue1", 101, true) and
0488                                 edm::ParameterDescription<unsigned>("uvalue2", 101, true)));
0489 
0490     // The switch parameter label cannot be the same as a label that already exists
0491     edm::ParameterSetDescription psetDesc6;
0492     psetDesc6.add<unsigned>("xswitch", 1U);
0493     REQUIRE_THROWS_AS(psetDesc6.ifValue(edm::ParameterDescription<int>("xswitch", 1, true),
0494                                         0 >> edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) or
0495                                             1 >> (edm::ParameterDescription<double>("xvalue1", 101.0, true) and
0496                                                   edm::ParameterDescription<double>("xvalue2", 101.0, true))),
0497                       edm::Exception);
0498 
0499     // Case labels cannot be the same as a label that already exists
0500     edm::ParameterSetDescription psetDesc7;
0501     psetDesc7.add<unsigned>("xvalue1", 1U);
0502     REQUIRE_THROWS_AS(psetDesc7.ifValue(edm::ParameterDescription<int>("xswitch", 1, true),
0503                                         0 >> edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) or
0504                                             1 >> (edm::ParameterDescription<double>("xvalue1", 101.0, true) and
0505                                                   edm::ParameterDescription<double>("xvalue2", 101.0, true))),
0506                       edm::Exception);
0507 
0508     // Case labels cannot be the same as a switch label
0509     edm::ParameterSetDescription psetDesc8;
0510     REQUIRE_THROWS_AS(psetDesc8.ifValue(edm::ParameterDescription<int>("xswitch", 1, true),
0511                                         0 >> edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) or
0512                                             1 >> (edm::ParameterDescription<double>("xswitch", 101.0, true) and
0513                                                   edm::ParameterDescription<double>("xvalue2", 101.0, true))),
0514                       edm::Exception);
0515 
0516     // Parameter set switch value must be one of the defined cases
0517     edm::ParameterSetDescription psetDesc9;
0518 
0519     psetDesc9.ifValue(edm::ParameterDescription<int>("xswitch", 1, true),
0520                       0 >> edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) or
0521                           1 >> (edm::ParameterDescription<double>("xvalue1", 101.0, true) and
0522                                 edm::ParameterDescription<double>("xvalue2", 101.0, true)));
0523     edm::ParameterSet pset;
0524     pset.addParameter<int>("xswitch", 5);
0525     REQUIRE_THROWS_AS(psetDesc9.validate(pset), edm::Exception);
0526 
0527     edm::ParameterSwitch<int> pswitch(edm::ParameterDescription<int>("xswitch", 1, true),
0528                                       0 >> edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) or
0529                                           1 >> (edm::ParameterDescription<double>("xvalue1", 101.0, true) and
0530                                                 edm::ParameterDescription<double>("xvalue2", 101.0, true)));
0531     edm::ParameterSetDescription psetDesc10;
0532     psetDesc10.addNode(pswitch);
0533     edm::ParameterSet pset10;
0534     testDesc(pswitch, psetDesc10, pset10, false, true);
0535     pset10.addParameter<int>("xswitch", 1);
0536     testDesc(pswitch, psetDesc10, pset10, true, true);
0537   }
0538 
0539   // ---------------------------------------------------------------------------------
0540 
0541   SECTION("testXor") {
0542     edm::ParameterSetDescription psetDesc1;
0543     std::unique_ptr<edm::ParameterDescriptionNode> node1(
0544         edm::ParameterDescription<double>("x1", 101.0, true) xor
0545         (edm::ParameterDescription<double>("x1", 101.0, true) and
0546          edm::ParameterDescription<double>("x2", 101.0, true)) xor
0547         edm::ParameterDescription<double>("x1", 101.0, true) xor
0548         (edm::ParameterDescription<double>("x1", 101.0, true) or edm::ParameterDescription<double>("x2", 101.0, true)));
0549 
0550     edm::ParameterSet pset1;
0551 
0552     edm::ParameterSet pset2;
0553     pset2.addParameter("x1", 11.0);
0554     pset2.addParameter("x2", 12.0);
0555 
0556     CHECK(node1->exists(pset1) == false);
0557     CHECK(node1->partiallyExists(pset1) == false);
0558     CHECK(node1->howManyXORSubNodesExist(pset1) == 0);
0559 
0560     CHECK(node1->exists(pset2) == false);
0561     CHECK(node1->partiallyExists(pset2) == false);
0562     CHECK(node1->howManyXORSubNodesExist(pset2) == 4);
0563 
0564     // 0 of the options existing should fail validation
0565     psetDesc1.addNode(std::move(node1));
0566     REQUIRE_THROWS_AS(psetDesc1.validate(pset1), edm::Exception);
0567 
0568     // More than one of the options existing should also fail
0569     REQUIRE_THROWS_AS(psetDesc1.validate(pset2), edm::Exception);
0570 
0571     // One of the labels cannot already exist in the description
0572     edm::ParameterSetDescription psetDesc2;
0573     psetDesc2.add<unsigned>("xvalue1", 1U);
0574     std::unique_ptr<edm::ParameterDescriptionNode> node2(edm::ParameterDescription<double>("x1", 101.0, true) xor
0575                                                          (edm::ParameterDescription<double>("x1", 101.0, true) and
0576                                                           edm::ParameterDescription<double>("x2", 101.0, true)) xor
0577                                                          edm::ParameterDescription<double>("x1", 101.0, true) xor
0578                                                          (edm::ParameterDescription<double>("xvalue1", 101.0, true) or
0579                                                           edm::ParameterDescription<double>("x2", 101.0, true)));
0580     REQUIRE_THROWS_AS(psetDesc2.addNode(std::move(node2)), edm::Exception);
0581 
0582     // One of the labels cannot already exist in the description, other order
0583     edm::ParameterSetDescription psetDesc3;
0584     std::unique_ptr<edm::ParameterDescriptionNode> node3(edm::ParameterDescription<double>("x1", 101.0, true) xor
0585                                                          (edm::ParameterDescription<double>("x1", 101.0, true) and
0586                                                           edm::ParameterDescription<double>("x2", 101.0, true)) xor
0587                                                          edm::ParameterDescription<double>("x1", 101.0, true) xor
0588                                                          (edm::ParameterDescription<double>("xvalue1", 101.0, true) or
0589                                                           edm::ParameterDescription<double>("x2", 101.0, true)));
0590     psetDesc3.addNode(std::move(node3));
0591     REQUIRE_THROWS_AS(psetDesc3.add<unsigned>("xvalue1", 1U), edm::Exception);
0592 
0593     // A parameter cannot use the same type as a wildcard
0594     edm::ParameterSetDescription psetDesc4;
0595     std::unique_ptr<edm::ParameterDescriptionNode> node4(
0596         edm::ParameterDescription<double>("x1", 101.0, true) xor
0597         (edm::ParameterDescription<double>("x1", 101.0, true) and
0598          edm::ParameterDescription<unsigned>("x2", 101, true)) xor
0599         edm::ParameterDescription<double>("x1", 101.0, true) xor
0600         (edm::ParameterDescription<double>("x1", 101.0, true) or edm::ParameterDescription<double>("x2", 101.0, true)));
0601     psetDesc4.addNode(std::move(node4));
0602 
0603     edm::ParameterWildcard<unsigned> w4("*", edm::RequireAtLeastOne, true);
0604     REQUIRE_THROWS_AS(psetDesc4.addNode(w4), edm::Exception);
0605 
0606     // A parameter cannot use the same type as a wildcard
0607     edm::ParameterSetDescription psetDesc5;
0608     std::unique_ptr<edm::ParameterDescriptionNode> node5(
0609         edm::ParameterDescription<double>("x1", 101.0, true) xor
0610         (edm::ParameterDescription<double>("x1", 101.0, true) and
0611          edm::ParameterWildcard<unsigned>("*", edm::RequireAtLeastOne, true)) xor
0612         edm::ParameterDescription<double>("x1", 101.0, true) xor
0613         (edm::ParameterDescription<double>("x1", 101.0, true) or
0614          edm::ParameterWildcard<unsigned>("*", edm::RequireAtLeastOne, true)));
0615     psetDesc5.addNode(std::move(node5));
0616 
0617     edm::ParameterDescription<unsigned> n5("z5", edm::RequireAtLeastOne, true);
0618     REQUIRE_THROWS_AS(psetDesc5.addNode(n5), edm::Exception);
0619   }
0620 
0621   // ---------------------------------------------------------------------------------
0622 
0623   SECTION("testOr") {
0624     edm::ParameterSetDescription psetDesc1;
0625     std::unique_ptr<edm::ParameterDescriptionNode> node1(edm::ParameterDescription<double>("x1", 101.0, true) or
0626                                                          (edm::ParameterDescription<double>("x2", 101.0, true) and
0627                                                           edm::ParameterDescription<double>("x3", 101.0, true)) or
0628                                                          edm::ParameterDescription<double>("x4", 101.0, true) or
0629                                                          (edm::ParameterDescription<double>("x5", 101.0, true) xor
0630                                                           edm::ParameterDescription<double>("x6", 101.0, true)));
0631 
0632     edm::ParameterSet pset1;
0633 
0634     edm::ParameterSet pset2;
0635     pset2.addParameter("x1", 11.0);
0636     pset2.addParameter("x2", 12.0);
0637     pset2.addParameter("x3", 13.0);
0638     pset2.addParameter("x4", 14.0);
0639     pset2.addParameter("x5", 15.0);
0640 
0641     CHECK(node1->exists(pset1) == false);
0642     CHECK(node1->partiallyExists(pset1) == false);
0643     CHECK(node1->howManyXORSubNodesExist(pset1) == 0);
0644 
0645     CHECK(node1->exists(pset2) == true);
0646     CHECK(node1->partiallyExists(pset2) == true);
0647     CHECK(node1->howManyXORSubNodesExist(pset2) == 1);
0648 
0649     // 0 of the options existing should fail validation
0650     psetDesc1.addNode(std::move(node1));
0651     psetDesc1.validate(pset1);
0652 
0653     // More than one of the options existing should succeed
0654     psetDesc1.validate(pset2);
0655 
0656     // One of the labels cannot already exist in the description
0657     edm::ParameterSetDescription psetDesc2;
0658     psetDesc2.add<unsigned>("x1", 1U);
0659     std::unique_ptr<edm::ParameterDescriptionNode> node2(edm::ParameterDescription<double>("x1", 101.0, true) or
0660                                                          (edm::ParameterDescription<double>("x2", 101.0, true) and
0661                                                           edm::ParameterDescription<double>("x3", 101.0, true)) or
0662                                                          edm::ParameterDescription<double>("x4", 101.0, true));
0663     REQUIRE_THROWS_AS(psetDesc2.addNode(std::move(node2)), edm::Exception);
0664 
0665     // One of the labels cannot already exist in the description, other order
0666     edm::ParameterSetDescription psetDesc3;
0667     std::unique_ptr<edm::ParameterDescriptionNode> node3(edm::ParameterDescription<double>("x1", 101.0, true) or
0668                                                          (edm::ParameterDescription<double>("x2", 101.0, true) and
0669                                                           edm::ParameterDescription<double>("x3", 101.0, true)) or
0670                                                          edm::ParameterDescription<double>("x4", 101.0, true));
0671     psetDesc3.addNode(std::move(node3));
0672 
0673     REQUIRE_THROWS_AS(psetDesc3.add<unsigned>("x1", 1U), edm::Exception);
0674 
0675     // Put the duplicate labels in different nodes of the "or" expression
0676     edm::ParameterSetDescription psetDesc4;
0677     std::unique_ptr<edm::ParameterDescriptionNode> node4(edm::ParameterDescription<double>("x1", 101.0, true) or
0678                                                          (edm::ParameterDescription<double>("x2", 101.0, true) and
0679                                                           edm::ParameterDescription<double>("x3", 101.0, true)) or
0680                                                          edm::ParameterDescription<double>("x1", 101.0, true));
0681     REQUIRE_THROWS_AS(psetDesc4.addNode(std::move(node4)), edm::Exception);
0682 
0683     // A type used in a wildcard should not be the same as a type
0684     // used for another parameter
0685     edm::ParameterSetDescription psetDesc5;
0686     std::unique_ptr<edm::ParameterDescriptionNode> node5(
0687         edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) or
0688         (edm::ParameterDescription<double>("x2", 101.0, true) and
0689          edm::ParameterDescription<unsigned>("x3", 101U, true)) or
0690         edm::ParameterDescription<unsigned>("x1", 101U, true));
0691     REQUIRE_THROWS_AS(psetDesc5.addNode(std::move(node5)), edm::Exception);
0692 
0693     // A type used in a wildcard should not be the same as a type
0694     // used for another parameter node
0695     edm::ParameterSetDescription psetDesc6;
0696     psetDesc6.add<double>("x0", 1.0);
0697     std::unique_ptr<edm::ParameterDescriptionNode> node6(
0698         edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) or
0699         (edm::ParameterDescription<unsigned>("x2", 101U, true) and
0700          edm::ParameterDescription<unsigned>("x3", 101U, true)) or
0701         edm::ParameterDescription<unsigned>("x1", 101U, true));
0702     REQUIRE_THROWS_AS(psetDesc6.addNode(std::move(node6)), edm::Exception);
0703 
0704     // A type used in a wildcard should not be the same as a type
0705     // used for another parameter node
0706     edm::ParameterSetDescription psetDesc7;
0707     psetDesc7.addWildcard<double>("*");
0708     std::unique_ptr<edm::ParameterDescriptionNode> node7(edm::ParameterDescription<double>("x0", 1.0, true) or
0709                                                          (edm::ParameterDescription<unsigned>("x2", 101U, true) and
0710                                                           edm::ParameterDescription<unsigned>("x3", 101U, true)) or
0711                                                          edm::ParameterDescription<unsigned>("x1", 101U, true));
0712     REQUIRE_THROWS_AS(psetDesc7.addNode(std::move(node7)), edm::Exception);
0713   }
0714 
0715   // ---------------------------------------------------------------------------------
0716 
0717   SECTION("testAnd") {
0718     edm::ParameterSetDescription psetDesc1;
0719     std::unique_ptr<edm::ParameterDescriptionNode> node1(edm::ParameterDescription<double>("x1", 101.0, true) and
0720                                                          (edm::ParameterDescription<double>("x2", 101.0, true) or
0721                                                           edm::ParameterDescription<double>("x3", 101.0, true)) and
0722                                                          edm::ParameterDescription<double>("x4", 101.0, true) and
0723                                                          (edm::ParameterDescription<double>("x5", 101.0, true) xor
0724                                                           edm::ParameterDescription<double>("x6", 101.0, true)));
0725 
0726     edm::ParameterSet pset1;
0727 
0728     edm::ParameterSet pset2;
0729     pset2.addParameter("x1", 11.0);
0730     pset2.addParameter("x2", 12.0);
0731     pset2.addParameter("x3", 13.0);
0732     pset2.addParameter("x4", 14.0);
0733     pset2.addParameter("x5", 15.0);
0734 
0735     edm::ParameterSet pset3;
0736     pset3.addParameter("x3", 13.0);
0737 
0738     CHECK(node1->exists(pset1) == false);
0739     CHECK(node1->partiallyExists(pset1) == false);
0740     CHECK(node1->howManyXORSubNodesExist(pset1) == 0);
0741 
0742     CHECK(node1->exists(pset2) == true);
0743     CHECK(node1->partiallyExists(pset2) == true);
0744     CHECK(node1->howManyXORSubNodesExist(pset2) == 1);
0745 
0746     CHECK(node1->exists(pset3) == false);
0747     CHECK(node1->partiallyExists(pset3) == true);
0748     CHECK(node1->howManyXORSubNodesExist(pset3) == 0);
0749 
0750     psetDesc1.addNode(std::move(node1));
0751     psetDesc1.validate(pset1);
0752     psetDesc1.validate(pset2);
0753     psetDesc1.validate(pset3);
0754 
0755     // One of the labels cannot already exist in the description
0756     edm::ParameterSetDescription psetDesc2;
0757     psetDesc2.add<unsigned>("x1", 1U);
0758     std::unique_ptr<edm::ParameterDescriptionNode> node2(edm::ParameterDescription<double>("x1", 101.0, true) and
0759                                                          (edm::ParameterDescription<double>("x2", 101.0, true) or
0760                                                           edm::ParameterDescription<double>("x3", 101.0, true)) and
0761                                                          edm::ParameterDescription<double>("x4", 101.0, true));
0762     REQUIRE_THROWS_AS(psetDesc2.addNode(std::move(node2)), edm::Exception);
0763 
0764     // One of the labels cannot already exist in the description, other order
0765     edm::ParameterSetDescription psetDesc3;
0766     std::unique_ptr<edm::ParameterDescriptionNode> node3(edm::ParameterDescription<double>("x1", 101.0, true) and
0767                                                          (edm::ParameterDescription<double>("x2", 101.0, true) or
0768                                                           edm::ParameterDescription<double>("x3", 101.0, true)) and
0769                                                          edm::ParameterDescription<double>("x4", 101.0, true));
0770     psetDesc3.addNode(std::move(node3));
0771 
0772     REQUIRE_THROWS_AS(psetDesc3.add<unsigned>("x1", 1U), edm::Exception);
0773 
0774     // Put the duplicate labels in different nodes of the "and" expression
0775     edm::ParameterSetDescription psetDesc4;
0776     std::unique_ptr<edm::ParameterDescriptionNode> node4(edm::ParameterDescription<double>("x1", 101.0, true) and
0777                                                          (edm::ParameterDescription<double>("x2", 101.0, true) or
0778                                                           edm::ParameterDescription<double>("x3", 101.0, true)) and
0779                                                          edm::ParameterDescription<double>("x1", 101.0, true));
0780     REQUIRE_THROWS_AS(psetDesc4.addNode(std::move(node4)), edm::Exception);
0781 
0782     // A type used in a wildcard should not be the same as a type
0783     // used for another parameter
0784     edm::ParameterSetDescription psetDesc5;
0785     std::unique_ptr<edm::ParameterDescriptionNode> node5(
0786         edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) and
0787         (edm::ParameterDescription<double>("x2", 101.0, true) or
0788          edm::ParameterDescription<unsigned>("x3", 101U, true)) and
0789         edm::ParameterDescription<unsigned>("x1", 101U, true));
0790     REQUIRE_THROWS_AS(psetDesc5.addNode(std::move(node5)), edm::Exception);
0791 
0792     // A type used in a wildcard should not be the same as a type
0793     // used for another parameter node
0794     edm::ParameterSetDescription psetDesc6;
0795     psetDesc6.add<double>("x0", 1.0);
0796     std::unique_ptr<edm::ParameterDescriptionNode> node6(
0797         edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true) and
0798         (edm::ParameterDescription<unsigned>("x2", 101U, true) or
0799          edm::ParameterDescription<unsigned>("x3", 101U, true)) and
0800         edm::ParameterDescription<unsigned>("x1", 101U, true));
0801     REQUIRE_THROWS_AS(psetDesc6.addNode(std::move(node6)), edm::Exception);
0802 
0803     // A type used in a wildcard should not be the same as a type
0804     // used for another parameter node
0805     edm::ParameterSetDescription psetDesc7;
0806     psetDesc7.addWildcard<double>("*");
0807     std::unique_ptr<edm::ParameterDescriptionNode> node7(edm::ParameterDescription<double>("x0", 1.0, true) and
0808                                                          (edm::ParameterDescription<unsigned>("x2", 101U, true) or
0809                                                           edm::ParameterDescription<unsigned>("x3", 101U, true)) and
0810                                                          edm::ParameterDescription<unsigned>("x1", 101U, true));
0811     REQUIRE_THROWS_AS(psetDesc7.addNode(std::move(node7)), edm::Exception);
0812   }
0813 
0814   // ---------------------------------------------------------------------------------
0815 
0816   SECTION("testIfExists") {
0817     edm::ParameterSetDescription psetDesc1;
0818     std::unique_ptr<edm::ParameterDescriptionNode> node1(
0819         std::make_unique<edm::IfExistsDescription>(edm::ParameterDescription<double>("x1", 101.0, true),
0820                                                    (edm::ParameterDescription<double>("x2", 101.0, true) and
0821                                                     edm::ParameterDescription<double>("x3", 101.0, true))));
0822 
0823     std::unique_ptr<edm::ParameterDescriptionNode> node1a(std::make_unique<edm::IfExistsDescription>(
0824         (edm::ParameterDescription<double>("x2", 101.0, true) and edm::ParameterDescription<double>("x3", 101.0, true)),
0825         edm::ParameterDescription<double>("x1", 101.0, true)));
0826 
0827     std::unique_ptr<edm::ParameterDescriptionNode> node1b(std::make_unique<edm::IfExistsDescription>(
0828         (edm::ParameterDescription<double>("x1", 101.0, true) xor edm::ParameterDescription<int>("x1", 101, true)),
0829         (edm::ParameterDescription<double>("x2", 101.0, true) and
0830          edm::ParameterDescription<double>("x3", 101.0, true))));
0831 
0832     edm::ParameterSet pset1;
0833 
0834     edm::ParameterSet pset2;
0835     pset2.addParameter("x1", 11.0);
0836     pset2.addParameter("x2", 12.0);
0837     pset2.addParameter("x3", 13.0);
0838 
0839     edm::ParameterSet pset3;
0840     pset3.addParameter("x1", 14.0);
0841 
0842     edm::ParameterSet pset4;
0843     pset4.addParameter("x2", 15.0);
0844     pset4.addParameter("x3", 16.0);
0845 
0846     CHECK(node1->exists(pset1) == true);
0847     CHECK(node1->partiallyExists(pset1) == true);
0848     CHECK(node1->howManyXORSubNodesExist(pset1) == 1);
0849     CHECK(node1a->exists(pset1) == true);
0850     CHECK(node1b->exists(pset1) == true);
0851 
0852     CHECK(node1->exists(pset2) == true);
0853     CHECK(node1->partiallyExists(pset2) == true);
0854     CHECK(node1->howManyXORSubNodesExist(pset2) == 1);
0855     CHECK(node1a->exists(pset2) == true);
0856     CHECK(node1b->exists(pset2) == true);
0857 
0858     CHECK(node1->exists(pset3) == false);
0859     CHECK(node1->partiallyExists(pset3) == false);
0860     CHECK(node1->howManyXORSubNodesExist(pset3) == 0);
0861     CHECK(node1a->exists(pset3) == false);
0862     CHECK(node1b->exists(pset3) == false);
0863 
0864     CHECK(node1->exists(pset4) == false);
0865     CHECK(node1->partiallyExists(pset4) == false);
0866     CHECK(node1->howManyXORSubNodesExist(pset4) == 0);
0867     CHECK(node1a->exists(pset4) == false);
0868     CHECK(node1b->exists(pset4) == false);
0869 
0870     psetDesc1.addNode(std::move(node1));
0871     psetDesc1.validate(pset1);
0872     psetDesc1.validate(pset2);
0873     psetDesc1.validate(pset3);
0874     psetDesc1.validate(pset3);
0875 
0876     // One of the labels cannot already exist in the description
0877     edm::ParameterSetDescription psetDesc2;
0878     psetDesc2.add<unsigned>("x1", 1U);
0879     std::unique_ptr<edm::ParameterDescriptionNode> node2(
0880         std::make_unique<edm::IfExistsDescription>(edm::ParameterDescription<double>("x1", 101.0, true),
0881                                                    (edm::ParameterDescription<double>("x2", 101.0, true) and
0882                                                     edm::ParameterDescription<double>("x3", 101.0, true))));
0883 
0884     REQUIRE_THROWS_AS(psetDesc2.addNode(std::move(node2)), edm::Exception);
0885 
0886     // One of the labels cannot already exist in the description, other order
0887     edm::ParameterSetDescription psetDesc3;
0888     std::unique_ptr<edm::ParameterDescriptionNode> node3(
0889         std::make_unique<edm::IfExistsDescription>(edm::ParameterDescription<double>("x1", 101.0, true),
0890                                                    (edm::ParameterDescription<double>("x2", 101.0, true) and
0891                                                     edm::ParameterDescription<double>("x3", 101.0, true))));
0892     psetDesc3.addNode(std::move(node3));
0893 
0894     REQUIRE_THROWS_AS(psetDesc3.add<unsigned>("x1", 1U), edm::Exception);
0895 
0896     // Put the duplicate labels in different nodes of the "and" expression
0897     edm::ParameterSetDescription psetDesc4;
0898     std::unique_ptr<edm::ParameterDescriptionNode> node4(
0899         std::make_unique<edm::IfExistsDescription>(edm::ParameterDescription<double>("x1", 101.0, true),
0900                                                    (edm::ParameterDescription<double>("x2", 101.0, true) and
0901                                                     edm::ParameterDescription<double>("x1", 101.0, true))));
0902     REQUIRE_THROWS_AS(psetDesc4.addNode(std::move(node4)), edm::Exception);
0903 
0904     // A type used in a wildcard should not be the same as a type
0905     // used for another parameter
0906     edm::ParameterSetDescription psetDesc5;
0907     std::unique_ptr<edm::ParameterDescriptionNode> node5(std::make_unique<edm::IfExistsDescription>(
0908         edm::ParameterDescription<double>("x1", 101.0, true),
0909         (edm::ParameterDescription<unsigned>("x2", 101U, true) and
0910          edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true))));
0911     REQUIRE_THROWS_AS(psetDesc5.addNode(std::move(node5)), edm::Exception);
0912 
0913     // A type used in a wildcard should not be the same as a type
0914     // used for another parameter node
0915     edm::ParameterSetDescription psetDesc6;
0916     psetDesc6.add<double>("x0", 1.0);
0917     std::unique_ptr<edm::ParameterDescriptionNode> node6(
0918         std::make_unique<edm::IfExistsDescription>(edm::ParameterWildcard<double>("*", edm::RequireAtLeastOne, true),
0919                                                    (edm::ParameterDescription<unsigned>("x2", 101U, true) and
0920                                                     edm::ParameterDescription<unsigned>("x3", 102U, true))));
0921     REQUIRE_THROWS_AS(psetDesc6.addNode(std::move(node6)), edm::Exception);
0922 
0923     // A type used in a wildcard should not be the same as a type
0924     // used for another parameter node
0925     edm::ParameterSetDescription psetDesc7;
0926     psetDesc7.addWildcard<double>("*");
0927     std::unique_ptr<edm::ParameterDescriptionNode> node7(
0928         std::make_unique<edm::IfExistsDescription>(edm::ParameterDescription<double>("x1", 11.0, true),
0929                                                    (edm::ParameterDescription<unsigned>("x2", 101U, true) and
0930                                                     edm::ParameterDescription<unsigned>("x3", 102U, true))));
0931     REQUIRE_THROWS_AS(psetDesc7.addNode(std::move(node7)), edm::Exception);
0932   }
0933 
0934   // ---------------------------------------------------------------------------------
0935 
0936   SECTION("testAllowedLabels") {
0937     {
0938       std::unique_ptr<edm::ParameterDescriptionNode> node(
0939           std::make_unique<edm::AllowedLabelsDescription<int>>("allowedLabels", true));
0940 
0941       const edm::ParameterSet emptyPset;
0942 
0943       edm::ParameterSet pset;
0944       std::vector<std::string> labels;
0945       pset.addParameter<std::vector<std::string>>("allowedLabels", labels);
0946 
0947       CHECK(node->exists(emptyPset) == false);
0948       CHECK(node->partiallyExists(emptyPset) == false);
0949       CHECK(node->howManyXORSubNodesExist(emptyPset) == 0);
0950 
0951       CHECK(node->exists(pset) == true);
0952       CHECK(node->partiallyExists(pset) == true);
0953       CHECK(node->howManyXORSubNodesExist(pset) == 1);
0954     }
0955 
0956     {
0957       // One of the labels cannot already exist in the description
0958       edm::ParameterSetDescription psetDesc;
0959       psetDesc.add<unsigned>("x1", 1U);
0960       std::unique_ptr<edm::ParameterDescriptionNode> node(
0961           std::make_unique<edm::AllowedLabelsDescription<int>>("x1", true));
0962 
0963       REQUIRE_THROWS_AS(psetDesc.addNode(std::move(node)), edm::Exception);
0964     }
0965 
0966     {
0967       // A type used in a wildcard should not be the same as a type
0968       // used for another parameter node
0969       edm::ParameterSetDescription psetDesc;
0970       psetDesc.addWildcard<std::vector<std::string>>("*");
0971       std::unique_ptr<edm::ParameterDescriptionNode> node(
0972           std::make_unique<edm::AllowedLabelsDescription<int>>("x1", true));
0973       REQUIRE_THROWS_AS(psetDesc.addNode(std::move(node)), edm::Exception);
0974     }
0975     {
0976       edm::ParameterSet pset;
0977       edm::ParameterSet nestedPset;
0978       nestedPset.addParameter<int>("x", 1);
0979       pset.addParameter<edm::ParameterSet>("nestedPset", nestedPset);
0980 
0981       {
0982         edm::ParameterSetDescription psetDesc;
0983         psetDesc.labelsFrom<edm::ParameterSetDescription>("allowedLabelsA");
0984 
0985         // nestedPset is an illegal parameter
0986         REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
0987 
0988         std::vector<std::string> labels;
0989         labels.push_back(std::string("nestedPset"));
0990         pset.addParameter<std::vector<std::string>>("allowedLabelsA", labels);
0991 
0992         // Now nestedPset should be an allowed parameter
0993         psetDesc.validate(pset);
0994       }
0995 
0996       // Above it did not validate the contents of the nested ParameterSet
0997       // because a description was not passed to the labelsFrom function.
0998 
0999       {
1000         edm::ParameterSetDescription psetDesc;
1001         psetDesc.labelsFrom<edm::ParameterSetDescription>("allowedLabelsA", edm::ParameterSetDescription());
1002         // Now it should fail because the description says the nested ParameterSet
1003         // should be empty, but it has parameter "x"
1004         REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
1005       }
1006 
1007       // Now include "x" in the description and it should once again pass validation
1008       edm::ParameterSetDescription nestedPsetDesc;
1009       nestedPsetDesc.add<int>("x", 1);
1010 
1011       {
1012         edm::ParameterSetDescription psetDesc;
1013         psetDesc.labelsFrom<edm::ParameterSetDescription>("allowedLabelsA", nestedPsetDesc);
1014         psetDesc.validate(pset);
1015       }
1016       // Minor variations, repeat with a string argument
1017       {
1018         edm::ParameterSetDescription psetDesc;
1019         psetDesc.labelsFrom<edm::ParameterSetDescription>(std::string("allowedLabelsA"));
1020         psetDesc.validate(pset);
1021       }
1022       {
1023         edm::ParameterSetDescription psetDesc;
1024         psetDesc.labelsFrom<edm::ParameterSetDescription>(std::string("allowedLabelsA"),
1025                                                           edm::ParameterSetDescription());
1026         REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
1027       }
1028       {
1029         edm::ParameterSetDescription psetDesc;
1030         psetDesc.labelsFrom<edm::ParameterSetDescription>(std::string("allowedLabelsA"), nestedPsetDesc);
1031         psetDesc.validate(pset);
1032       }
1033     }
1034     // Now repeat what was done above with the variations
1035     // necessary to test the vector<ParameterSet> case
1036     {
1037       edm::ParameterSet pset;
1038 
1039       edm::ParameterSet elementOfVPset;
1040       elementOfVPset.addParameter<int>("y", 1);
1041       std::vector<edm::ParameterSet> vpset;
1042       vpset.push_back(elementOfVPset);
1043       vpset.push_back(elementOfVPset);
1044 
1045       pset.addParameter<std::vector<edm::ParameterSet>>("nestedVPSet", vpset);
1046 
1047       {
1048         edm::ParameterSetDescription psetDesc;
1049         psetDesc.labelsFrom<std::vector<edm::ParameterSet>>("allowedLabelsC");
1050 
1051         // nestedVPSet is an illegal parameter
1052         REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
1053 
1054         std::vector<std::string> labels;
1055         labels.push_back(std::string("nestedVPSet"));
1056         pset.addParameter<std::vector<std::string>>("allowedLabelsC", labels);
1057 
1058         // Now nestedVPSet should be an allowed parameter
1059         psetDesc.validate(pset);
1060       }
1061       // Above it did not validate the contents of the nested vector<ParameterSet>
1062       // because a description was not passed to the labelsFrom function.
1063 
1064       {
1065         edm::ParameterSetDescription psetDesc;
1066         psetDesc.labelsFrom<std::vector<edm::ParameterSet>>("allowedLabelsC", edm::ParameterSetDescription());
1067         // Now it should fail because the description says the contained vector<ParameterSet>
1068         // should have empty ParameterSets, but the ParameterSets have parameter "y"
1069         REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
1070       }
1071 
1072       // Now include "y" in the description and it should once again pass validation
1073       edm::ParameterSetDescription nestedPSetDesc;
1074       nestedPSetDesc.add<int>("y", 1);
1075 
1076       {
1077         edm::ParameterSetDescription psetDesc;
1078         psetDesc.labelsFrom<std::vector<edm::ParameterSet>>("allowedLabelsC", nestedPSetDesc);
1079         psetDesc.validate(pset);
1080       }
1081 
1082       // Minor variations, repeat with a string argument
1083       {
1084         edm::ParameterSetDescription psetDesc;
1085         psetDesc.labelsFrom<std::vector<edm::ParameterSet>>(std::string("allowedLabelsC"));
1086         psetDesc.validate(pset);
1087       }
1088       {
1089         edm::ParameterSetDescription psetDesc;
1090         psetDesc.labelsFrom<std::vector<edm::ParameterSet>>(std::string("allowedLabelsC"),
1091                                                             edm::ParameterSetDescription());
1092         REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
1093       }
1094       {
1095         edm::ParameterSetDescription psetDesc;
1096         psetDesc.labelsFrom<std::vector<edm::ParameterSet>>(std::string("allowedLabelsC"), nestedPSetDesc);
1097         psetDesc.validate(pset);
1098       }
1099     }
1100   }
1101   // ---------------------------------------------------------------------------------
1102 
1103   SECTION("testNoDefault") {
1104     edm::ParameterSetDescription psetDesc;
1105     psetDesc.add<int>("x");
1106     edm::ParameterSet pset;
1107 
1108     REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
1109 
1110     pset.addParameter<int>("x", 1);
1111     psetDesc.validate(pset);
1112 
1113     psetDesc.addVPSet("y", edm::ParameterSetDescription());
1114     REQUIRE_THROWS_AS(psetDesc.validate(pset), edm::Exception);
1115   }
1116 
1117   // ---------------------------------------------------------------------------------
1118 
1119   SECTION("testWrongTrackiness") {
1120     edm::ParameterSet pset1;
1121     pset1.addParameter<int>("test1", 1);
1122 
1123     edm::ParameterSetDescription psetDesc1;
1124     psetDesc1.addUntracked<int>("test1", 1);
1125     REQUIRE_THROWS_AS(psetDesc1.validate(pset1), edm::Exception);
1126 
1127     edm::ParameterSet pset2;
1128     pset2.addParameter<edm::ParameterSet>("test2", edm::ParameterSet());
1129 
1130     edm::ParameterSetDescription psetDesc2;
1131     psetDesc2.addUntracked<edm::ParameterSetDescription>("test2", edm::ParameterSetDescription());
1132     REQUIRE_THROWS_AS(psetDesc2.validate(pset2), edm::Exception);
1133 
1134     edm::ParameterSet pset3;
1135     pset3.addParameter<std::vector<edm::ParameterSet>>("test3", std::vector<edm::ParameterSet>());
1136 
1137     edm::ParameterSetDescription psetDesc3;
1138     psetDesc3.addVPSetUntracked("test3", edm::ParameterSetDescription());
1139     REQUIRE_THROWS_AS(psetDesc3.validate(pset3), edm::Exception);
1140   }
1141 
1142   // ---------------------------------------------------------------------------------
1143 
1144   SECTION("testWrongType") {
1145     edm::ParameterSet pset1;
1146     pset1.addParameter<unsigned int>("test1", 1);
1147 
1148     edm::ParameterSetDescription psetDesc1;
1149     psetDesc1.add<int>("test1", 1);
1150     REQUIRE_THROWS_AS(psetDesc1.validate(pset1), edm::Exception);
1151 
1152     edm::ParameterSet pset2;
1153     pset2.addParameter<int>("test2", 1);
1154 
1155     edm::ParameterSetDescription psetDesc2;
1156     psetDesc2.add<edm::ParameterSetDescription>("test2", edm::ParameterSetDescription());
1157     REQUIRE_THROWS_AS(psetDesc2.validate(pset2), edm::Exception);
1158 
1159     edm::ParameterSet pset3;
1160     pset3.addParameter<int>("test3", 1);
1161 
1162     edm::ParameterSetDescription psetDesc3;
1163     psetDesc3.addVPSetUntracked("test3", edm::ParameterSetDescription());
1164     REQUIRE_THROWS_AS(psetDesc3.validate(pset3), edm::Exception);
1165   }
1166 
1167   // ---------------------------------------------------------------------------------
1168 
1169   SECTION("testPlugin") {
1170     SECTION("Plugin A") {
1171       edm::ParameterSetDescription desc;
1172       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1173 
1174       edm::ParameterSet pset1;
1175       pset1.addParameter<std::string>("type", "ATestPlugin");
1176       pset1.addParameter<int>("anInt", 3);
1177 
1178       desc.validate(pset1);
1179     }
1180 
1181     SECTION("Plugin B") {
1182       edm::ParameterSetDescription desc;
1183       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1184 
1185       edm::ParameterSet pset1;
1186       pset1.addParameter<std::string>("type", "BTestPlugin");
1187       pset1.addParameter<double>("aDouble", 0.2);
1188 
1189       desc.validate(pset1);
1190     }
1191 
1192     SECTION("Plugin C") {
1193       edm::ParameterSetDescription desc;
1194       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1195 
1196       edm::ParameterSet pset1;
1197       pset1.addParameter<std::string>("type", "CTestPlugin");
1198       pset1.addUntrackedParameter<int>("anInt", 4);
1199 
1200       desc.validate(pset1);
1201     }
1202 
1203     SECTION("Let validation to inject parameter") {
1204       edm::ParameterSetDescription desc;
1205       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1206 
1207       edm::ParameterSet pset1;
1208       pset1.addParameter<std::string>("type", "ATestPlugin");
1209       desc.validate(pset1);
1210       CHECK(pset1.getParameter<int>("anInt") == 5);
1211     }
1212 
1213     SECTION("Let validation to inject untracked parameter") {
1214       edm::ParameterSetDescription desc;
1215       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1216 
1217       edm::ParameterSet pset1;
1218       pset1.addParameter<std::string>("type", "CTestPlugin");
1219       desc.validate(pset1);
1220       CHECK(pset1.getUntrackedParameter<int>("anInt") == 42);
1221     }
1222 
1223     SECTION("Let validation to inject also 'type'") {
1224       edm::ParameterSetDescription desc;
1225       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", "ATestPlugin", true));
1226 
1227       edm::ParameterSet pset1;
1228       desc.validate(pset1);
1229       CHECK(pset1.getParameter<int>("anInt") == 5);
1230       CHECK(pset1.getParameter<std::string>("type") == "ATestPlugin");
1231     }
1232 
1233     SECTION("Add additional parameter") {
1234       edm::ParameterSetDescription desc;
1235       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1236 
1237       edm::ParameterSet pset1;
1238       pset1.addParameter<std::string>("type", "ATestPlugin");
1239       pset1.addParameter<int>("anInt", 3);
1240       pset1.addParameter<int>("NotRight", 3);
1241 
1242       REQUIRE_THROWS_AS(desc.validate(pset1), edm::Exception);
1243     }
1244 
1245     SECTION("wildcard") {
1246       //embedded with wildcard
1247       edm::ParameterSetDescription desc;
1248       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1249       edm::ParameterWildcard<edm::ParameterSetDescription> w("*", edm::RequireExactlyOne, true, desc);
1250 
1251       edm::ParameterSetDescription top;
1252       top.addNode(w);
1253 
1254       edm::ParameterSet pset1;
1255       pset1.addParameter<std::string>("type", "ATestPlugin");
1256 
1257       edm::ParameterSet psetTop;
1258       psetTop.addParameter<edm::ParameterSet>("foo", pset1);
1259 
1260       top.validate(psetTop);
1261     }
1262 
1263     SECTION("Missing 'type'") {
1264       edm::ParameterSetDescription desc;
1265       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1266 
1267       edm::ParameterSet pset1;
1268       pset1.addParameter<int>("anInt", 3);
1269 
1270       REQUIRE_THROWS_AS(desc.validate(pset1), edm::Exception);
1271     }
1272 
1273     SECTION("Non-existent type") {
1274       edm::ParameterSetDescription desc;
1275       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1276 
1277       edm::ParameterSet pset1;
1278       pset1.addParameter<std::string>("type", "ZTestPlugin");
1279 
1280       REQUIRE_THROWS_AS(desc.validate(pset1), cms::Exception);
1281     }
1282 
1283     SECTION("Untracked 'type'") {
1284       edm::ParameterSetDescription desc;
1285       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", false));
1286 
1287       edm::ParameterSet pset1;
1288       pset1.addUntrackedParameter<std::string>("type", "ATestPlugin");
1289       pset1.addParameter<int>("anInt", 3);
1290 
1291       desc.validate(pset1);
1292     }
1293 
1294     SECTION("Untracked 'type' and other parameters") {
1295       edm::ParameterSetDescription desc;
1296       desc.addNode(edm::PluginDescription<TestPluginFactory>("type", false));
1297 
1298       edm::ParameterSet pset1;
1299       pset1.addUntrackedParameter<std::string>("type", "CTestPlugin");
1300       pset1.addUntrackedParameter<int>("anInt", 3);
1301 
1302       desc.validate(pset1);
1303     }
1304   }
1305 
1306   SECTION("VPSet with defaults") {
1307     edm::ParameterSetDescription psetDesc;
1308 
1309     std::vector<edm::ParameterSet> defaults{1};
1310     {
1311       auto& d = defaults.front();
1312       edm::ParameterSetDescription templte;
1313 
1314       templte.add<int>("i");
1315       d.addParameter<int>("i", 1);
1316 
1317       templte.add<std::vector<int>>("vi");
1318       d.addParameter<std::vector<int>>("vi", std::vector<int>({1}));
1319 
1320       templte.add<unsigned int>("ui");
1321       d.addParameter<unsigned int>("ui", 1);
1322 
1323       templte.add<std::vector<unsigned int>>("vui");
1324       d.addParameter<std::vector<unsigned int>>("vui", std::vector<unsigned int>({1}));
1325 
1326       templte.add<long long>("l");
1327       d.addParameter<long long>("l", 1);
1328 
1329       templte.add<std::vector<long long>>("vl");
1330       d.addParameter<std::vector<long long>>("vl", std::vector<long long>({1}));
1331 
1332       templte.add<unsigned long long>("ul");
1333       d.addParameter<unsigned long long>("ul", 1);
1334 
1335       templte.add<std::vector<unsigned long long>>("vul");
1336       d.addParameter<std::vector<unsigned long long>>("vul", std::vector<unsigned long long>({1}));
1337 
1338       templte.add<bool>("b");
1339       d.addParameter<bool>("b", true);
1340 
1341       templte.add<double>("d");
1342       d.addParameter<double>("d", 1.0);
1343 
1344       templte.add<std::vector<double>>("vd");
1345       d.addParameter<std::vector<double>>("vd", std::vector<double>({1.0}));
1346 
1347       templte.add<std::string>("s");
1348       d.addParameter<std::string>("s", "a");
1349 
1350       templte.add<std::vector<std::string>>("vs");
1351       d.addParameter<std::vector<std::string>>("vs", std::vector<std::string>({"a"}));
1352 
1353       templte.add<edm::InputTag>("t");
1354       d.addParameter<edm::InputTag>("t", edm::InputTag("foo"));
1355 
1356       templte.add<std::vector<edm::InputTag>>("vt");
1357       d.addParameter<std::vector<edm::InputTag>>("vt", std::vector<edm::InputTag>({edm::InputTag("foo")}));
1358 
1359       templte.add<edm::ESInputTag>("et");
1360       d.addParameter<edm::ESInputTag>("et", edm::ESInputTag(":foo"));
1361 
1362       templte.add<std::vector<edm::ESInputTag>>("vet");
1363       d.addParameter<std::vector<edm::ESInputTag>>("vet", std::vector<edm::ESInputTag>({edm::ESInputTag(":foo")}));
1364 
1365       edm::FileInPath::disableFileLookup();
1366       templte.add<edm::FileInPath>("f");
1367       d.addParameter<edm::FileInPath>("f", edm::FileInPath());
1368 
1369       templte.add<edm::EventID>("e");
1370       d.addParameter<edm::EventID>("e", edm::EventID(1, 2, 3));
1371 
1372       templte.add<std::vector<edm::EventID>>("ve");
1373       d.addParameter<std::vector<edm::EventID>>("ve", std::vector<edm::EventID>({edm::EventID(1, 2, 3)}));
1374 
1375       templte.add<edm::LuminosityBlockID>("L");
1376       d.addParameter<edm::LuminosityBlockID>("L", edm::LuminosityBlockID(1, 2));
1377 
1378       templte.add<std::vector<edm::LuminosityBlockID>>("vL");
1379       d.addParameter<std::vector<edm::LuminosityBlockID>>(
1380           "vL", std::vector<edm::LuminosityBlockID>({edm::LuminosityBlockID(1, 2)}));
1381 
1382       templte.add<edm::EventRange>("er");
1383       d.addParameter<edm::EventRange>("er", edm::EventRange(1, 2, 3, 4, 5, 6));
1384 
1385       templte.add<std::vector<edm::EventRange>>("ver");
1386       d.addParameter<std::vector<edm::EventRange>>("ver",
1387                                                    std::vector<edm::EventRange>({edm::EventRange(1, 2, 3, 4, 5, 6)}));
1388 
1389       templte.add<edm::LuminosityBlockRange>("Lr");
1390       d.addParameter<edm::LuminosityBlockRange>("Lr", edm::LuminosityBlockRange(1, 2, 3, 4));
1391 
1392       templte.add<std::vector<edm::LuminosityBlockRange>>("vLr");
1393       d.addParameter<std::vector<edm::LuminosityBlockRange>>(
1394           "vLr", std::vector<edm::LuminosityBlockRange>({edm::LuminosityBlockRange(1, 2, 3, 4)}));
1395 
1396       templte.add<edm::ParameterSetDescription>("p", edm::ParameterSetDescription());
1397       d.addParameter<edm::ParameterSet>("p", edm::ParameterSet());
1398 
1399       templte.addVPSet("vp", edm::ParameterSetDescription());
1400       d.addParameter<std::vector<edm::ParameterSet>>("vp", std::vector<edm::ParameterSet>());
1401 
1402       psetDesc.addVPSet("vp", templte, defaults);
1403     }
1404 
1405     SECTION("VPSet with plugin") {
1406       SECTION("Tracked 'type' and parameters") {
1407         edm::ParameterSetDescription pluginDesc;
1408         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1409         std::vector<edm::ParameterSet> defaults;
1410         edm::ParameterSetDescription desc;
1411         desc.addVPSet("plugins", pluginDesc, defaults);
1412 
1413         SECTION("Empty") {
1414           edm::ParameterSet pset;
1415           desc.validate(pset);
1416           CHECK(pset.getParameter<std::vector<edm::ParameterSet>>("plugins").empty());
1417         }
1418 
1419         SECTION("One plugin") {
1420           edm::ParameterSet pset;
1421           {
1422             edm::ParameterSet pluginPSet;
1423             pluginPSet.addParameter<std::string>("type", "ATestPlugin");
1424             pset.addParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1425           }
1426           desc.validate(pset);
1427 
1428           auto const& vpset = pset.getParameter<std::vector<edm::ParameterSet>>("plugins");
1429           REQUIRE(vpset.size() == 1);
1430           CHECK(vpset[0].getParameter<int>("anInt") == 5);
1431         }
1432       }
1433 
1434       SECTION("Untracked 'type' with tracked parameters") {
1435         edm::ParameterSetDescription pluginDesc;
1436         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", false));
1437         std::vector<edm::ParameterSet> defaults;
1438         edm::ParameterSetDescription desc;
1439         desc.addVPSet("plugins", pluginDesc, defaults);
1440 
1441         edm::ParameterSet pset;
1442         {
1443           edm::ParameterSet pluginPSet;
1444           pluginPSet.addUntrackedParameter<std::string>("type", "ATestPlugin");
1445           pset.addParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1446         }
1447         desc.validate(pset);
1448 
1449         auto const& vpset = pset.getParameter<std::vector<edm::ParameterSet>>("plugins");
1450         REQUIRE(vpset.size() == 1);
1451         CHECK(vpset[0].getParameter<int>("anInt") == 5);
1452       }
1453 
1454       SECTION("Tracked 'type' with untracked parameters") {
1455         edm::ParameterSetDescription pluginDesc;
1456         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1457         std::vector<edm::ParameterSet> defaults;
1458         edm::ParameterSetDescription desc;
1459         desc.addVPSet("plugins", pluginDesc, defaults);
1460 
1461         edm::ParameterSet pset;
1462         {
1463           edm::ParameterSet pluginPSet;
1464           pluginPSet.addParameter<std::string>("type", "CTestPlugin");
1465           pset.addParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1466         }
1467         desc.validate(pset);
1468 
1469         auto const& vpset = pset.getParameter<std::vector<edm::ParameterSet>>("plugins");
1470         REQUIRE(vpset.size() == 1);
1471         CHECK(vpset[0].getUntrackedParameter<int>("anInt") == 42);
1472       }
1473 
1474       SECTION("Untracked 'type' with untracked parameters") {
1475         edm::ParameterSetDescription pluginDesc;
1476         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", false));
1477         std::vector<edm::ParameterSet> defaults;
1478         edm::ParameterSetDescription desc;
1479         desc.addVPSet("plugins", pluginDesc, defaults);
1480 
1481         edm::ParameterSet pset;
1482         {
1483           edm::ParameterSet pluginPSet;
1484           pluginPSet.addUntrackedParameter<std::string>("type", "CTestPlugin");
1485           pset.addParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1486         }
1487         desc.validate(pset);
1488 
1489         auto const& vpset = pset.getParameter<std::vector<edm::ParameterSet>>("plugins");
1490         REQUIRE(vpset.size() == 1);
1491         CHECK(vpset[0].getUntrackedParameter<int>("anInt") == 42);
1492       }
1493     }
1494 
1495     SECTION("Untracked VPSet with plugin") {
1496       SECTION("Tracked 'type' and parameters") {
1497         edm::ParameterSetDescription pluginDesc;
1498         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1499         std::vector<edm::ParameterSet> defaults;
1500         edm::ParameterSetDescription desc;
1501         desc.addVPSetUntracked("plugins", pluginDesc, defaults);
1502 
1503         SECTION("Empty") {
1504           edm::ParameterSet pset;
1505           desc.validate(pset);
1506           CHECK(pset.getUntrackedParameter<std::vector<edm::ParameterSet>>("plugins").empty());
1507         }
1508 
1509         SECTION("One plugin") {
1510           edm::ParameterSet pset;
1511           {
1512             edm::ParameterSet pluginPSet;
1513             pluginPSet.addParameter<std::string>("type", "ATestPlugin");
1514             pset.addUntrackedParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1515           }
1516           desc.validate(pset);
1517 
1518           auto const& vpset = pset.getUntrackedParameter<std::vector<edm::ParameterSet>>("plugins");
1519           REQUIRE(vpset.size() == 1);
1520           CHECK(vpset[0].getParameter<int>("anInt") == 5);
1521         }
1522       }
1523 
1524       SECTION("Untracked 'type' with tracked parameters") {
1525         edm::ParameterSetDescription pluginDesc;
1526         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", false));
1527         std::vector<edm::ParameterSet> defaults;
1528         edm::ParameterSetDescription desc;
1529         desc.addVPSetUntracked("plugins", pluginDesc, defaults);
1530 
1531         edm::ParameterSet pset;
1532         {
1533           edm::ParameterSet pluginPSet;
1534           pluginPSet.addUntrackedParameter<std::string>("type", "ATestPlugin");
1535           pset.addUntrackedParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1536         }
1537         desc.validate(pset);
1538 
1539         auto const& vpset = pset.getUntrackedParameter<std::vector<edm::ParameterSet>>("plugins");
1540         REQUIRE(vpset.size() == 1);
1541         CHECK(vpset[0].getParameter<int>("anInt") == 5);
1542       }
1543 
1544       SECTION("Tracked 'type' with untracked parameters") {
1545         edm::ParameterSetDescription pluginDesc;
1546         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", true));
1547         std::vector<edm::ParameterSet> defaults;
1548         edm::ParameterSetDescription desc;
1549         desc.addVPSetUntracked("plugins", pluginDesc, defaults);
1550 
1551         edm::ParameterSet pset;
1552         {
1553           edm::ParameterSet pluginPSet;
1554           pluginPSet.addParameter<std::string>("type", "CTestPlugin");
1555           pset.addUntrackedParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1556         }
1557         desc.validate(pset);
1558 
1559         auto const& vpset = pset.getUntrackedParameter<std::vector<edm::ParameterSet>>("plugins");
1560         REQUIRE(vpset.size() == 1);
1561         CHECK(vpset[0].getUntrackedParameter<int>("anInt") == 42);
1562       }
1563 
1564       SECTION("Untracked 'type' with untracked parameters") {
1565         edm::ParameterSetDescription pluginDesc;
1566         pluginDesc.addNode(edm::PluginDescription<TestPluginFactory>("type", false));
1567         std::vector<edm::ParameterSet> defaults;
1568         edm::ParameterSetDescription desc;
1569         desc.addVPSetUntracked("plugins", pluginDesc, defaults);
1570 
1571         edm::ParameterSet pset;
1572         {
1573           edm::ParameterSet pluginPSet;
1574           pluginPSet.addUntrackedParameter<std::string>("type", "CTestPlugin");
1575           pset.addUntrackedParameter<std::vector<edm::ParameterSet>>("plugins", {pluginPSet});
1576         }
1577         desc.validate(pset);
1578 
1579         auto const& vpset = pset.getUntrackedParameter<std::vector<edm::ParameterSet>>("plugins");
1580         REQUIRE(vpset.size() == 1);
1581         CHECK(vpset[0].getUntrackedParameter<int>("anInt") == 42);
1582       }
1583     }
1584 
1585     SECTION("writeCfi full") {
1586       edm::ParameterSet test;
1587       test.addParameter("vp", defaults);
1588       psetDesc.validate(test);
1589 
1590       std::ostringstream s;
1591       edm::CfiOptions fullOps = edm::cfi::Typed{};
1592       psetDesc.writeCfi(s, false, 0, fullOps);
1593       std::string expected = R"-(
1594 vp = cms.VPSet(
1595   cms.PSet(
1596     L = cms.LuminosityBlockID(1, 2),
1597     Lr = cms.LuminosityBlockRange('1:2-3:4'),
1598     b = cms.bool(True),
1599     d = cms.double(1),
1600     e = cms.EventID(1, 2, 3),
1601     er = cms.EventRange('1:2:3-4:5:6'),
1602     et = cms.ESInputTag('', 'foo'),
1603     f = cms.FileInPath(''),
1604     i = cms.int32(1),
1605     l = cms.int64(1),
1606     s = cms.string('a'),
1607     t = cms.InputTag('foo'),
1608     ui = cms.uint32(1),
1609     ul = cms.uint64(1),
1610     vL = cms.VLuminosityBlockID('1:2'),
1611     vLr = cms.VLuminosityBlockRange('1:2-3:4'),
1612     vd = cms.vdouble(1),
1613     ve = cms.VEventID('1:2:3'),
1614     ver = cms.VEventRange('1:2:3-4:5:6'),
1615     vet = cms.VESInputTag(':foo'),
1616     vi = cms.vint32(1),
1617     vl = cms.vint64(1),
1618     vs = cms.vstring('a'),
1619     vt = cms.VInputTag('foo'),
1620     vui = cms.vuint32(1),
1621     vul = cms.vuint64(1),
1622     p = cms.PSet(),
1623     vp = cms.VPSet(
1624     )
1625   ),
1626   template = cms.PSetTemplate(
1627     i = cms.required.int32,
1628     vi = cms.required.vint32,
1629     ui = cms.required.uint32,
1630     vui = cms.required.vuint32,
1631     l = cms.required.int64,
1632     vl = cms.required.vint64,
1633     ul = cms.required.uint64,
1634     vul = cms.required.vuint64,
1635     b = cms.required.bool,
1636     d = cms.required.double,
1637     vd = cms.required.vdouble,
1638     s = cms.required.string,
1639     vs = cms.required.vstring,
1640     t = cms.required.InputTag,
1641     vt = cms.required.VInputTag,
1642     et = cms.required.ESInputTag,
1643     vet = cms.required.VESInputTag,
1644     f = cms.required.FileInPath,
1645     e = cms.required.EventID,
1646     ve = cms.required.VEventID,
1647     L = cms.required.LuminosityBlockID,
1648     vL = cms.required.VLuminosityBlockID,
1649     er = cms.required.EventRange,
1650     ver = cms.required.VEventRange,
1651     Lr = cms.required.LuminosityBlockRange,
1652     vLr = cms.required.VLuminosityBlockRange,
1653     p = cms.PSet(),
1654     vp = cms.required.VPSet
1655   )
1656 )
1657 )-";
1658 
1659       CHECK(expected == s.str());
1660     }
1661     SECTION("writeCfi Untyped") {
1662       edm::ParameterSet test;
1663       test.addParameter("vp", defaults);
1664       psetDesc.validate(test);
1665 
1666       std::ostringstream s;
1667       edm::CfiOptions fullOps = edm::cfi::Untyped{edm::cfi::Paths{}};
1668       psetDesc.writeCfi(s, false, 0, fullOps);
1669       std::string expected = R"-(
1670 vp = [
1671   cms.PSet(
1672     L = cms.LuminosityBlockID(1, 2),
1673     Lr = cms.LuminosityBlockRange('1:2-3:4'),
1674     b = cms.bool(True),
1675     d = cms.double(1),
1676     e = cms.EventID(1, 2, 3),
1677     er = cms.EventRange('1:2:3-4:5:6'),
1678     et = cms.ESInputTag('', 'foo'),
1679     f = cms.FileInPath(''),
1680     i = cms.int32(1),
1681     l = cms.int64(1),
1682     s = cms.string('a'),
1683     t = cms.InputTag('foo'),
1684     ui = cms.uint32(1),
1685     ul = cms.uint64(1),
1686     vL = cms.VLuminosityBlockID('1:2'),
1687     vLr = cms.VLuminosityBlockRange('1:2-3:4'),
1688     vd = cms.vdouble(1),
1689     ve = cms.VEventID('1:2:3'),
1690     ver = cms.VEventRange('1:2:3-4:5:6'),
1691     vet = cms.VESInputTag(':foo'),
1692     vi = cms.vint32(1),
1693     vl = cms.vint64(1),
1694     vs = cms.vstring('a'),
1695     vt = cms.VInputTag('foo'),
1696     vui = cms.vuint32(1),
1697     vul = cms.vuint64(1),
1698     p = cms.PSet(),
1699     vp = cms.VPSet(
1700     )
1701   )
1702 ]
1703 )-";
1704 
1705       CHECK(expected == s.str());
1706     }
1707   }
1708 
1709   SECTION("PSet with default") {
1710     edm::ParameterSetDescription psetDesc;
1711 
1712     {
1713       edm::ParameterSetDescription templte;
1714 
1715       templte.add<int>("i", 1);
1716       templte.add<std::vector<int>>("vi", std::vector<int>({1}));
1717       templte.add<unsigned int>("ui", 1);
1718       templte.add<std::vector<unsigned int>>("vui", std::vector<unsigned int>({1}));
1719       templte.add<long long>("l", 1);
1720       templte.add<std::vector<long long>>("vl", std::vector<long long>({1}));
1721       templte.add<unsigned long long>("ul", 1);
1722       templte.add<std::vector<unsigned long long>>("vul", std::vector<unsigned long long>({1}));
1723       templte.add<bool>("b", true);
1724       templte.add<double>("d", 1.0);
1725       templte.add<std::vector<double>>("vd", std::vector<double>({1.0}));
1726       templte.add<std::string>("s", "a");
1727       templte.add<std::vector<std::string>>("vs", std::vector<std::string>({"a"}));
1728       templte.add<edm::InputTag>("t", edm::InputTag("foo"));
1729       templte.add<std::vector<edm::InputTag>>("vt", std::vector<edm::InputTag>({edm::InputTag("foo")}));
1730       templte.add<edm::ESInputTag>("et", edm::ESInputTag(":foo"));
1731       templte.add<std::vector<edm::ESInputTag>>("vet", std::vector<edm::ESInputTag>({edm::ESInputTag(":foo")}));
1732       edm::FileInPath::disableFileLookup();
1733       templte.add<edm::FileInPath>("f", edm::FileInPath());
1734       templte.add<edm::EventID>("e", edm::EventID(1, 2, 3));
1735       templte.add<std::vector<edm::EventID>>("ve", std::vector<edm::EventID>({edm::EventID(1, 2, 3)}));
1736       templte.add<edm::LuminosityBlockID>("L", edm::LuminosityBlockID(1, 2));
1737       templte.add<std::vector<edm::LuminosityBlockID>>(
1738           "vL", std::vector<edm::LuminosityBlockID>({edm::LuminosityBlockID(1, 2)}));
1739       templte.add<edm::EventRange>("er", edm::EventRange(1, 2, 3, 4, 5, 6));
1740       templte.add<std::vector<edm::EventRange>>("ver",
1741                                                 std::vector<edm::EventRange>({edm::EventRange(1, 2, 3, 4, 5, 6)}));
1742       templte.add<edm::LuminosityBlockRange>("Lr", edm::LuminosityBlockRange(1, 2, 3, 4));
1743       templte.add<std::vector<edm::LuminosityBlockRange>>(
1744           "vLr", std::vector<edm::LuminosityBlockRange>({edm::LuminosityBlockRange(1, 2, 3, 4)}));
1745       templte.add<edm::ParameterSetDescription>("p", edm::ParameterSetDescription());
1746       templte.addVPSet("vp", edm::ParameterSetDescription(), std::vector<edm::ParameterSet>());
1747       psetDesc.add<edm::ParameterSetDescription>("p", templte);
1748     }
1749     SECTION("writeCfi full") {
1750       edm::ParameterSet test;
1751       test.addParameter("p", edm::ParameterSet());
1752       psetDesc.validate(test);
1753 
1754       std::ostringstream s;
1755       edm::CfiOptions fullOps = edm::cfi::Typed{};
1756       psetDesc.writeCfi(s, false, 0, fullOps);
1757       std::string expected = R"-(
1758 p = cms.PSet(
1759   i = cms.int32(1),
1760   vi = cms.vint32(1),
1761   ui = cms.uint32(1),
1762   vui = cms.vuint32(1),
1763   l = cms.int64(1),
1764   vl = cms.vint64(1),
1765   ul = cms.uint64(1),
1766   vul = cms.vuint64(1),
1767   b = cms.bool(True),
1768   d = cms.double(1),
1769   vd = cms.vdouble(1),
1770   s = cms.string('a'),
1771   vs = cms.vstring('a'),
1772   t = cms.InputTag('foo'),
1773   vt = cms.VInputTag('foo'),
1774   et = cms.ESInputTag('', 'foo'),
1775   vet = cms.VESInputTag(':foo'),
1776   f = cms.FileInPath(''),
1777   e = cms.EventID(1, 2, 3),
1778   ve = cms.VEventID('1:2:3'),
1779   L = cms.LuminosityBlockID(1, 2),
1780   vL = cms.VLuminosityBlockID('1:2'),
1781   er = cms.EventRange('1:2:3-4:5:6'),
1782   ver = cms.VEventRange('1:2:3-4:5:6'),
1783   Lr = cms.LuminosityBlockRange('1:2-3:4'),
1784   vLr = cms.VLuminosityBlockRange('1:2-3:4'),
1785   p = cms.PSet(),
1786   vp = cms.VPSet(
1787   )
1788 )
1789 )-";
1790 
1791       CHECK(expected == s.str());
1792     }
1793     SECTION("writeCfi Untyped") {
1794       std::ostringstream s;
1795       edm::CfiOptions fullOps = edm::cfi::Untyped{edm::cfi::Paths{}};
1796       psetDesc.writeCfi(s, false, 0, fullOps);
1797       std::string expected = R"-(
1798 p = dict(
1799   i = 1,
1800   vi = [1],
1801   ui = 1,
1802   vui = [1],
1803   l = 1,
1804   vl = [1],
1805   ul = 1,
1806   vul = [1],
1807   b = True,
1808   d = 1,
1809   vd = [1],
1810   s = 'a',
1811   vs = ['a'],
1812   t = ('foo'),
1813   vt = ['foo'],
1814   et = ('', 'foo'),
1815   vet = [':foo'],
1816   f = '',
1817   e = (1, 2, 3),
1818   ve = ['1:2:3'],
1819   L = (1, 2),
1820   vL = ['1:2'],
1821   er = ('1:2:3-4:5:6'),
1822   ver = ['1:2:3-4:5:6'],
1823   Lr = ('1:2-3:4'),
1824   vLr = ['1:2-3:4'],
1825   p = dict(),
1826   vp = [
1827   ]
1828 )
1829 )-";
1830 
1831       CHECK(expected == s.str());
1832     }
1833   }
1834 
1835   SECTION("setAllowAnything") {
1836     edm::ParameterSetDescription psetDesc;
1837     CHECK(!psetDesc.anythingAllowed());
1838     CHECK(!psetDesc.isUnknown());
1839     CHECK(psetDesc.begin() == psetDesc.end());
1840 
1841     edm::ParameterSet params;
1842     psetDesc.validate(params);
1843 
1844     params.addParameter<std::string>("testname", std::string("testvalue"));
1845 
1846     // Expect this to throw, parameter not in description
1847     REQUIRE_THROWS_AS(psetDesc.validate(params), edm::Exception);
1848 
1849     psetDesc.setAllowAnything();
1850     CHECK(psetDesc.anythingAllowed());
1851 
1852     psetDesc.validate(params);
1853 
1854     psetDesc.add<int>("testInt", 11);
1855     psetDesc.validate(params);
1856     CHECK(params.exists("testInt"));
1857   }
1858 
1859   SECTION("unknown") {
1860     edm::ParameterSetDescription psetDesc;
1861 
1862     edm::ParameterSet params;
1863     params.addParameter<std::string>("testname", std::string("testvalue"));
1864     psetDesc.setUnknown();
1865     CHECK(psetDesc.isUnknown());
1866 
1867     psetDesc.validate(params);
1868   }
1869 
1870   SECTION("obsolete") {
1871     SECTION("string") {
1872       edm::ParameterSetDescription psetDesc;
1873 
1874       psetDesc.add<std::string>("testname");
1875       psetDesc.add<std::string>("hadDefault", "default");
1876       psetDesc.addObsolete<std::string>("noLongerUsed");
1877       SECTION("with obsolete") {
1878         edm::ParameterSet params;
1879         params.addParameter<std::string>("testname", std::string("testvalue"));
1880         params.addParameter<std::string>("noLongerUsed", std::string("testvalue"));
1881 
1882         psetDesc.validate(params);
1883       }
1884       SECTION("without obsolete") {
1885         edm::ParameterSet params;
1886         params.addParameter<std::string>("testname", std::string("testvalue"));
1887         psetDesc.validate(params);
1888         CHECK(not params.existsAs<std::string>("noLongerUsed"));
1889       }
1890       SECTION("writeCfi full") {
1891         std::ostringstream s;
1892         edm::CfiOptions fullOps = edm::cfi::Typed{};
1893         psetDesc.writeCfi(s, false, 0, fullOps);
1894         std::string expected = R"-(
1895 testname = cms.required.string,
1896 hadDefault = cms.string('default'),
1897 noLongerUsed = cms.obsolete.string
1898 )-";
1899 
1900         CHECK(expected == s.str());
1901       }
1902       SECTION("writeCfi Untyped") {
1903         std::ostringstream s;
1904         edm::CfiOptions fullOps = edm::cfi::Untyped{edm::cfi::Paths{}};
1905         psetDesc.writeCfi(s, false, 0, fullOps);
1906         std::string expected = R"-(
1907 hadDefault = 'default'
1908 )-";
1909         CHECK(expected == s.str());
1910       }
1911     }
1912     SECTION("PSet") {
1913       edm::ParameterSetDescription psetDesc;
1914 
1915       psetDesc.add<std::string>("testname");
1916       psetDesc.add<std::string>("hadDefault", "default");
1917       psetDesc.addObsolete<edm::ParameterSetDescription>("noLongerUsed");
1918       SECTION("with obsolete") {
1919         edm::ParameterSet params;
1920         params.addParameter<std::string>("testname", std::string("testvalue"));
1921         edm::ParameterSet obs;
1922         obs.addParameter<int>("something", 1);
1923         params.addParameter<edm::ParameterSet>("noLongerUsed", obs);
1924 
1925         psetDesc.validate(params);
1926       }
1927       SECTION("without obsolete") {
1928         edm::ParameterSet params;
1929         params.addParameter<std::string>("testname", std::string("testvalue"));
1930         psetDesc.validate(params);
1931       }
1932       SECTION("writeCfi full") {
1933         std::ostringstream s;
1934         edm::CfiOptions fullOps = edm::cfi::Typed{};
1935         psetDesc.writeCfi(s, false, 0, fullOps);
1936         std::string expected = R"-(
1937 testname = cms.required.string,
1938 hadDefault = cms.string('default'),
1939 noLongerUsed = cms.obsolete.PSet
1940 )-";
1941 
1942         CHECK(expected == s.str());
1943       }
1944       SECTION("writeCfi Untyped") {
1945         std::ostringstream s;
1946         edm::CfiOptions fullOps = edm::cfi::Untyped{edm::cfi::Paths{}};
1947         psetDesc.writeCfi(s, false, 0, fullOps);
1948         std::string expected = R"-(
1949 hadDefault = 'default'
1950 )-";
1951         CHECK(expected == s.str());
1952       }
1953     }
1954   }
1955 
1956   SECTION("VPSet") {
1957     edm::ParameterSetDescription psetDesc;
1958 
1959     psetDesc.add<std::string>("testname");
1960     psetDesc.add<std::string>("hadDefault", "default");
1961     psetDesc.addVPSetObsolete("noLongerUsed");
1962     SECTION("with obsolete") {
1963       edm::ParameterSet params;
1964       params.addParameter<std::string>("testname", std::string("testvalue"));
1965 
1966       edm::ParameterSet obs;
1967       obs.addParameter<int>("something", 1);
1968       std::vector<edm::ParameterSet> vobs{1, obs};
1969       params.addParameter<std::vector<edm::ParameterSet>>("noLongerUsed", vobs);
1970 
1971       psetDesc.validate(params);
1972     }
1973     SECTION("without obsolete") {
1974       edm::ParameterSet params;
1975       params.addParameter<std::string>("testname", std::string("testvalue"));
1976       psetDesc.validate(params);
1977     }
1978     SECTION("writeCfi full") {
1979       std::ostringstream s;
1980       edm::CfiOptions fullOps = edm::cfi::Typed{};
1981       psetDesc.writeCfi(s, false, 0, fullOps);
1982       std::string expected = R"-(
1983 testname = cms.required.string,
1984 hadDefault = cms.string('default'),
1985 noLongerUsed = cms.obsolete.VPSet
1986 )-";
1987 
1988       CHECK(expected == s.str());
1989     }
1990     SECTION("writeCfi Untyped") {
1991       std::ostringstream s;
1992       edm::CfiOptions fullOps = edm::cfi::Untyped{edm::cfi::Paths{}};
1993       psetDesc.writeCfi(s, false, 0, fullOps);
1994       std::string expected = R"-(
1995 hadDefault = 'default'
1996 )-";
1997       CHECK(expected == s.str());
1998     }
1999   }
2000 
2001   SECTION("FileInPath") {
2002     // Test this type separately because I do not know how to
2003     // add an entry into a ParameterSet without FileInPath pointing
2004     // at a real file.
2005     edm::ParameterSetDescription psetDesc;
2006     edm::ParameterDescriptionBase* par = psetDesc.add<edm::FileInPath>("fileInPath", edm::FileInPath());
2007     CHECK(par->type() == edm::k_FileInPath);
2008     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("FileInPath"));
2009   }
2010 
2011   SECTION("main") {
2012     edm::ParameterSetDescription psetDesc;
2013     edm::ParameterSet pset;
2014 
2015     psetDesc.reserve(2);
2016 
2017     int a = 1;
2018     edm::ParameterDescriptionBase* par = psetDesc.add<int>(std::string("ivalue"), a);
2019     CHECK(par->exists(pset) == false);
2020     CHECK(par->partiallyExists(pset) == false);
2021     CHECK(par->howManyXORSubNodesExist(pset) == 0);
2022     pset.addParameter<int>("ivalue", a);
2023     CHECK(par != 0);
2024     CHECK(par->label() == std::string("ivalue"));
2025     CHECK(par->type() == edm::k_int32);
2026     CHECK(par->isTracked() == true);
2027     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("int32"));
2028     CHECK(par->exists(pset) == true);
2029     CHECK(par->partiallyExists(pset) == true);
2030     CHECK(par->howManyXORSubNodesExist(pset) == 1);
2031 
2032     edm::ParameterSet psetWrongTrackiness;
2033     psetWrongTrackiness.addUntrackedParameter("ivalue", a);
2034     REQUIRE_THROWS_AS(psetDesc.validate(psetWrongTrackiness), edm::Exception);
2035 
2036     edm::ParameterSet psetWrongType;
2037     psetWrongType.addUntrackedParameter("ivalue", 1U);
2038     REQUIRE_THROWS_AS(psetDesc.validate(psetWrongType), edm::Exception);
2039 
2040     edm::ParameterSetDescription::const_iterator parIter = psetDesc.begin();
2041     CHECK(parIter->node().operator->() == par);
2042 
2043     unsigned b = 2;
2044     par = psetDesc.add<unsigned>("uvalue", b);
2045     pset.addParameter<unsigned>("uvalue", b);
2046     CHECK(par != 0);
2047     CHECK(par->label() == std::string("uvalue"));
2048     CHECK(par->type() == edm::k_uint32);
2049     CHECK(par->isTracked() == true);
2050     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("uint32"));
2051 
2052     parIter = psetDesc.begin();
2053     ++parIter;
2054     CHECK(parIter->node().operator->() == par);
2055 
2056     long long c = 3;
2057     par = psetDesc.addUntracked<long long>(std::string("i64value"), c);
2058     pset.addUntrackedParameter<long long>("i64value", c);
2059     CHECK(par != 0);
2060     CHECK(par->label() == std::string("i64value"));
2061     CHECK(par->type() == edm::k_int64);
2062     CHECK(par->isTracked() == false);
2063     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("int64"));
2064 
2065     unsigned long long d = 4;
2066     par = psetDesc.addUntracked<unsigned long long>("u64value", d);
2067     pset.addUntrackedParameter<unsigned long long>("u64value", d);
2068     CHECK(par != 0);
2069     CHECK(par->label() == std::string("u64value"));
2070     CHECK(par->type() == edm::k_uint64);
2071     CHECK(par->isTracked() == false);
2072     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("uint64"));
2073 
2074     double e = 5;
2075     par = psetDesc.addOptional<double>(std::string("dvalue"), e);
2076     pset.addParameter<double>("dvalue", e);
2077     CHECK(par != 0);
2078     CHECK(par->label() == std::string("dvalue"));
2079     CHECK(par->type() == edm::k_double);
2080     CHECK(par->isTracked() == true);
2081     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("double"));
2082 
2083     bool f = true;
2084     par = psetDesc.addOptional<bool>("bvalue", f);
2085     pset.addParameter<bool>("bvalue", f);
2086     CHECK(par != 0);
2087     CHECK(par->label() == std::string("bvalue"));
2088     CHECK(par->type() == edm::k_bool);
2089     CHECK(par->isTracked() == true);
2090     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("bool"));
2091 
2092     std::string g;
2093     par = psetDesc.addOptionalUntracked<std::string>(std::string("svalue"), g);
2094     pset.addUntrackedParameter<std::string>("svalue", g);
2095     CHECK(par != 0);
2096     CHECK(par->label() == std::string("svalue"));
2097     CHECK(par->type() == edm::k_stringRaw);
2098     CHECK(par->isTracked() == false);
2099     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("string"));
2100 
2101     edm::EventID h;
2102     par = psetDesc.addOptionalUntracked<edm::EventID>("evalue", h);
2103     pset.addUntrackedParameter<edm::EventID>("evalue", h);
2104     CHECK(par != 0);
2105     CHECK(par->label() == std::string("evalue"));
2106     CHECK(par->type() == edm::k_EventID);
2107     CHECK(par->isTracked() == false);
2108     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("EventID"));
2109 
2110     edm::LuminosityBlockID i;
2111     par = psetDesc.add<edm::LuminosityBlockID>("lvalue", i);
2112     pset.addParameter<edm::LuminosityBlockID>("lvalue", i);
2113     CHECK(par->type() == edm::k_LuminosityBlockID);
2114     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("LuminosityBlockID"));
2115 
2116     edm::InputTag j;
2117     par = psetDesc.add<edm::InputTag>("input", j);
2118     pset.addParameter<edm::InputTag>("input", j);
2119     CHECK(par->type() == edm::k_InputTag);
2120     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("InputTag"));
2121 
2122     edm::ESInputTag k;
2123     par = psetDesc.add<edm::ESInputTag>("esinput", k);
2124     pset.addParameter<edm::ESInputTag>("esinput", k);
2125     CHECK(par->type() == edm::k_ESInputTag);
2126     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("ESInputTag"));
2127 
2128     std::vector<int> v1;
2129     par = psetDesc.add<std::vector<int>>("v1", v1);
2130     pset.addParameter<std::vector<int>>("v1", v1);
2131     CHECK(par->type() == edm::k_vint32);
2132     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("vint32"));
2133 
2134     std::vector<unsigned> v2;
2135     par = psetDesc.add<std::vector<unsigned>>("v2", v2);
2136     pset.addParameter<std::vector<unsigned>>("v2", v2);
2137     CHECK(par->type() == edm::k_vuint32);
2138     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("vuint32"));
2139 
2140     std::vector<long long> v3;
2141     par = psetDesc.add<std::vector<long long>>("v3", v3);
2142     pset.addParameter<std::vector<long long>>("v3", v3);
2143     CHECK(par->type() == edm::k_vint64);
2144     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("vint64"));
2145 
2146     std::vector<unsigned long long> v4;
2147     par = psetDesc.add<std::vector<unsigned long long>>("v4", v4);
2148     pset.addParameter<std::vector<unsigned long long>>("v4", v4);
2149     CHECK(par->type() == edm::k_vuint64);
2150     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("vuint64"));
2151 
2152     std::vector<double> v5;
2153     par = psetDesc.add<std::vector<double>>("v5", v5);
2154     pset.addParameter<std::vector<double>>("v5", v5);
2155     CHECK(par->type() == edm::k_vdouble);
2156     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("vdouble"));
2157 
2158     std::vector<std::string> v6;
2159     par = psetDesc.add<std::vector<std::string>>("v6", v6);
2160     pset.addParameter<std::vector<std::string>>("v6", v6);
2161     CHECK(par->type() == edm::k_vstringRaw);
2162     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("vstring"));
2163 
2164     std::vector<edm::EventID> v7;
2165     par = psetDesc.add<std::vector<edm::EventID>>("v7", v7);
2166     pset.addParameter<std::vector<edm::EventID>>("v7", v7);
2167     CHECK(par->type() == edm::k_VEventID);
2168     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("VEventID"));
2169 
2170     std::vector<edm::LuminosityBlockID> v8;
2171     par = psetDesc.add<std::vector<edm::LuminosityBlockID>>("v8", v8);
2172     pset.addParameter<std::vector<edm::LuminosityBlockID>>("v8", v8);
2173     CHECK(par->type() == edm::k_VLuminosityBlockID);
2174     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("VLuminosityBlockID"));
2175 
2176     std::vector<edm::InputTag> v9;
2177     par = psetDesc.add<std::vector<edm::InputTag>>("v9", v9);
2178     pset.addParameter<std::vector<edm::InputTag>>("v9", v9);
2179     CHECK(par->type() == edm::k_VInputTag);
2180     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("VInputTag"));
2181 
2182     std::vector<edm::ESInputTag> v11;
2183     par = psetDesc.add<std::vector<edm::ESInputTag>>("v11", v11);
2184     pset.addParameter<std::vector<edm::ESInputTag>>("v11", v11);
2185     CHECK(par->type() == edm::k_VESInputTag);
2186     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("VESInputTag"));
2187 
2188     edm::ParameterSetDescription m;
2189     par = psetDesc.add<edm::ParameterSetDescription>("psetDesc", m);
2190     CHECK(par->exists(pset) == false);
2191     CHECK(par->partiallyExists(pset) == false);
2192     CHECK(par->howManyXORSubNodesExist(pset) == 0);
2193     edm::ParameterSet p1;
2194     pset.addParameter<edm::ParameterSet>("psetDesc", p1);
2195     CHECK(par->type() == edm::k_PSet);
2196     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("PSet"));
2197     CHECK(par->exists(pset) == true);
2198     CHECK(par->partiallyExists(pset) == true);
2199     CHECK(par->howManyXORSubNodesExist(pset) == 1);
2200 
2201     edm::ParameterSetDescription v10;
2202     par = psetDesc.addVPSet("psetVectorDesc", v10);
2203     CHECK(par->exists(pset) == false);
2204     CHECK(par->partiallyExists(pset) == false);
2205     CHECK(par->howManyXORSubNodesExist(pset) == 0);
2206     std::vector<edm::ParameterSet> vp1;
2207     pset.addParameter<std::vector<edm::ParameterSet>>("psetVectorDesc", vp1);
2208     CHECK(par->type() == edm::k_VPSet);
2209     CHECK(edm::parameterTypeEnumToString(par->type()) == std::string("VPSet"));
2210     CHECK(par->exists(pset) == true);
2211     CHECK(par->partiallyExists(pset) == true);
2212     CHECK(par->howManyXORSubNodesExist(pset) == 1);
2213 
2214     psetDesc.validate(pset);
2215 
2216     // Add a ParameterSetDescription nested in a ParameterSetDescription nested in
2217     // a vector in the top level ParameterSetDescription to see if the nesting is
2218     // working properly.
2219 
2220     edm::ParameterSet nest2;
2221     nest2.addParameter<int>("intLevel2a", 1);
2222     nest2.addUntrackedParameter<int>("intLevel2b", 1);
2223     nest2.addParameter<int>("intLevel2e", 1);
2224     nest2.addUntrackedParameter<int>("intLevel2f", 1);
2225 
2226     edm::ParameterSet nest1;
2227     nest1.addParameter<int>("intLevel1a", 1);
2228     nest1.addParameter<edm::ParameterSet>("nestLevel1b", nest2);
2229 
2230     std::vector<edm::ParameterSet> vPset;
2231     vPset.push_back(edm::ParameterSet());
2232     vPset.push_back(nest1);
2233 
2234     pset.addUntrackedParameter<std::vector<edm::ParameterSet>>("nestLevel0", vPset);
2235 
2236     std::vector<edm::ParameterSetDescription> testDescriptions;
2237     testDescriptions.push_back(psetDesc);
2238     testDescriptions.push_back(psetDesc);
2239     testDescriptions.push_back(psetDesc);
2240 
2241     for (int ii = 0; ii < 3; ++ii) {
2242       edm::ParameterSetDescription nestLevel2;
2243 
2244       // for the first test do not put a parameter in the description
2245       // so there will be an extra parameter in the ParameterSet and
2246       // validation should fail.
2247       if (ii > 0)
2248         nestLevel2.add<int>("intLevel2a", 1);
2249 
2250       // for the next test validation should pass
2251 
2252       // For the last test add an extra required parameter in the
2253       // description that is not in the ParameterSet.
2254       if (ii == 2)
2255         nestLevel2.add<int>("intLevel2extra", 11);
2256 
2257       nestLevel2.addUntracked<int>("intLevel2b", 1);
2258       nestLevel2.addOptional<int>("intLevel2c", 1);
2259       nestLevel2.addOptionalUntracked<int>("intLevel2d", 1);
2260       nestLevel2.addOptional<int>("intLevel2e", 1);
2261       nestLevel2.addOptionalUntracked<int>("intLevel2f", 1);
2262 
2263       edm::ParameterSetDescription nestLevel1;
2264       nestLevel1.add<int>("intLevel1a", 1);
2265       nestLevel1.add<edm::ParameterSetDescription>("nestLevel1b", nestLevel2);
2266 
2267       testDescriptions[ii].addVPSetUntracked("nestLevel0", nestLevel1);
2268     }
2269 
2270     // Now run the validation and make sure we get the expected results
2271     REQUIRE_THROWS_AS(testDescriptions[0].validate(pset), edm::Exception);
2272 
2273     // This one should pass validation with no exception
2274     testDescriptions[1].validate(pset);
2275 
2276     // This validation should also pass and it should insert
2277     // the missing parameter into the ParameterSet
2278     testDescriptions[2].validate(pset);
2279 
2280     std::vector<edm::ParameterSet> const& vpset = pset.getUntrackedParameterSetVector("nestLevel0");
2281     edm::ParameterSet const& psetInPset = vpset[1].getParameterSet("nestLevel1b");
2282     CHECK(psetInPset.getParameter<int>("intLevel2extra") == 11);
2283 
2284     // One more iteration, this time the purpose is to
2285     // test the parameterSetDescription accessors.
2286     edm::ParameterSetDescription nestLevel2;
2287     par = nestLevel2.add<int>("intLevel2a", 1);
2288     par->setComment("testComment");
2289     CHECK(par->parameterSetDescription() == 0);
2290     edm::ParameterDescriptionBase const& constParRef = *par;
2291     CHECK(constParRef.parameterSetDescription() == 0);
2292 
2293     nestLevel2.addUntracked<int>("intLevel2b", 1);
2294     nestLevel2.addOptional<int>("intLevel2c", 1);
2295     nestLevel2.addOptionalUntracked<int>("intLevel2d", 1);
2296     nestLevel2.addOptional<int>("intLevel2e", 1);
2297     nestLevel2.addOptionalUntracked<int>("intLevel2f", 1);
2298     nestLevel2.setAllowAnything();
2299 
2300     edm::ParameterSetDescription nestLevel1;
2301     par = nestLevel1.add<int>("intLevel1a", 1);
2302     par->setComment("testComment1");
2303     par = nestLevel1.add<edm::ParameterSetDescription>("nestLevel1b", nestLevel2);
2304     CHECK(par->parameterSetDescription() != 0);
2305     CHECK(par->parameterSetDescription()->begin()->node()->comment() == std::string("testComment"));
2306     edm::ParameterDescriptionBase const& constParRef2 = *par;
2307     CHECK(constParRef2.parameterSetDescription() != 0);
2308     CHECK(constParRef2.parameterSetDescription()->begin()->node()->comment() == std::string("testComment"));
2309 
2310     CHECK(par->parameterSetDescription()->anythingAllowed() == true);
2311     CHECK(constParRef2.parameterSetDescription()->anythingAllowed() == true);
2312 
2313     par = psetDesc.addVPSetUntracked("nestLevel0", nestLevel1);
2314     CHECK(par->parameterSetDescription() != 0);
2315     CHECK(par->parameterSetDescription()->begin()->node()->comment() == std::string("testComment1"));
2316     edm::ParameterDescriptionBase const& constParRef3 = *par;
2317     CHECK(constParRef3.parameterSetDescription() != 0);
2318     CHECK(constParRef3.parameterSetDescription()->begin()->node()->comment() == std::string("testComment1"));
2319 
2320     psetDesc.validate(pset);
2321   }
2322 }  // namespace testParameterSetDescription
2323 
2324 EDM_REGISTER_VALIDATED_PLUGINFACTORY(TestPluginFactory, "TestPluginFWCoreParameterSet");
2325 
2326 DEFINE_EDM_VALIDATED_PLUGIN(TestPluginFactory, testParameterSetDescription::ATestPlugin, "ATestPlugin");
2327 DEFINE_EDM_VALIDATED_PLUGIN(TestPluginFactory, testParameterSetDescription::BTestPlugin, "BTestPlugin");
2328 DEFINE_EDM_VALIDATED_PLUGIN(TestPluginFactory, testParameterSetDescription::CTestPlugin, "CTestPlugin");