ProcessToken

ProduceEntry

TestProcessor

TestProcessorConfig

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
#ifndef FWCore_TestProcessor_TestProcessor_h
#define FWCore_TestProcessor_TestProcessor_h
// -*- C++ -*-
//
// Package:     FWCore/TestProcessor
// Class  :     TestProcessor
//
/**\class TestProcessor TestProcessor.h "TestProcessor.h"

 Description: [one line class summary]

 Usage:
    <usage>

*/
//
// Original Author:  Chris Jones
//         Created:  Mon, 30 Apr 2018 18:51:00 GMT
//

// system include files
#include <string>
#include <utility>
#include <memory>
#include "oneapi/tbb/global_control.h"
#include "oneapi/tbb/task_arena.h"
#include "oneapi/tbb/task_group.h"

// user include files
#include "FWCore/Common/interface/FWCoreCommonFwd.h"
#include "FWCore/Framework/interface/SharedResourcesAcquirer.h"
#include "FWCore/Framework/interface/PrincipalCache.h"
#include "FWCore/Framework/interface/SignallingProductRegistryFiller.h"
#include "FWCore/Framework/interface/PreallocationConfiguration.h"
#include "FWCore/Framework/interface/ModuleRegistry.h"
#include "FWCore/Framework/interface/Schedule.h"
#include "FWCore/Framework/interface/EventSetupRecordKey.h"
#include "FWCore/Framework/interface/DataKey.h"
#include "FWCore/Framework/interface/MergeableRunProductProcesses.h"

#include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
#include "FWCore/ServiceRegistry/interface/ProcessContext.h"
#include "FWCore/ServiceRegistry/interface/ServiceLegacy.h"
#include "FWCore/ServiceRegistry/interface/ServiceToken.h"

#include "DataFormats/Provenance/interface/RunLumiEventNumber.h"
#include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
#include "DataFormats/Common/interface/Wrapper.h"

#include "FWCore/TestProcessor/interface/Event.h"
#include "FWCore/TestProcessor/interface/LuminosityBlock.h"
#include "FWCore/TestProcessor/interface/ProcessBlock.h"
#include "FWCore/TestProcessor/interface/Run.h"
#include "FWCore/TestProcessor/interface/TestESProductResolver.h"
#include "FWCore/TestProcessor/interface/ESPutTokenT.h"
#include "FWCore/TestProcessor/interface/ESProduceEntry.h"
#include "FWCore/TestProcessor/interface/EventSetupTestHelper.h"

#include "FWCore/Utilities/interface/EDPutToken.h"

// forward declarations

namespace edm {
  class ThinnedAssociationsHelper;
  class ExceptionToActionTable;
  class HistoryAppender;
  class ModuleTypeResolverMaker;

  namespace eventsetup {
    class EventSetupProvider;
    class EventSetupsController;
  }  // namespace eventsetup

  namespace test {
    class TestProcessorConfig;
    class EventSetupTestHelper;

    class ProcessToken {
      friend TestProcessorConfig;

    public:
      ProcessToken() : index_{undefinedIndex()} {}

      int index() const { return index_; }

      static int undefinedIndex() { return -1; }

    private:
      explicit ProcessToken(int index) : index_{index} {}

      int index_;
    };

    class TestProcessorConfig {
    public:
      TestProcessorConfig(std::string const& iPythonConfiguration) : config_(iPythonConfiguration) {}
      std::string const& pythonConfiguration() const { return config_; }
      void setPythonConfiguration(std::string iConfig) { config_ = std::move(iConfig); }

      /** add a Process name to the Process history. If multiple calls are made to addProcess,
     then the call order will be the order of the Processes in the history.*/
      ProcessToken addExtraProcess(std::string const& iProcessName) {
        extraProcesses_.emplace_back(iProcessName);
        return ProcessToken(extraProcesses_.size() - 1);
      }

      std::vector<std::string> const& extraProcesses() const { return extraProcesses_; }

      /** A blank iProcessName means it produces in the primary process.
     The use of any other name requires that it is first added via `addExtraProcess`.
     */
      template <typename T>
      edm::EDPutTokenT<T> produces(std::string iModuleLabel,
                                   std::string iProductInstanceLabel = std::string(),
                                   ProcessToken iToken = ProcessToken()) {
        produceEntries_.emplace_back(
            edm::TypeID(typeid(T)), std::move(iModuleLabel), std::move(iProductInstanceLabel), processName(iToken));
        return edm::EDPutTokenT<T>(produceEntries_.size() - 1);
      }

      template <typename REC, typename T>
      edm::test::ESPutTokenT<T> esProduces(std::string iLabel = std::string()) {
        auto rk = eventsetup::EventSetupRecordKey::makeKey<REC>();
        eventsetup::DataKey dk(eventsetup::DataKey::makeTypeTag<T>(), iLabel.c_str());
        esProduceEntries_.emplace_back(rk, dk, std::make_shared<TestESProductResolver<T>>());
        return edm::test::ESPutTokenT<T>(esProduceEntries_.size() - 1);
      }

      struct ProduceEntry {
        ProduceEntry(edm::TypeID const& iType,
                     std::string moduleLabel,
                     std::string instanceLabel,
                     std::string processName)
            : type_{iType},
              moduleLabel_{std::move(moduleLabel)},
              instanceLabel_{std::move(instanceLabel)},
              processName_{std::move(processName)} {}
        edm::TypeID type_;
        std::string moduleLabel_;
        std::string instanceLabel_;
        std::string processName_;
      };

      std::vector<ProduceEntry> const& produceEntries() const { return produceEntries_; }

      std::vector<ESProduceEntry> const& esProduceEntries() const { return esProduceEntries_; }

    private:
      std::string config_;
      std::vector<std::string> extraProcesses_;
      std::vector<ProduceEntry> produceEntries_;
      std::vector<ESProduceEntry> esProduceEntries_;

      std::string processName(ProcessToken iToken) {
        if (iToken.index() == ProcessToken::undefinedIndex()) {
          return std::string();
        }
        return extraProcesses_[iToken.index()];
      }
    };

    class TestProcessor {
    public:
      using Config = TestProcessorConfig;

      TestProcessor(Config const& iConfig, ServiceToken iToken = ServiceToken());
      TestProcessor(const TestProcessor&) = delete;
      const TestProcessor& operator=(const TestProcessor&) = delete;
      ~TestProcessor() noexcept(false);

      /** Run the test. The function arguments are the data products to be added to the
     Event for this particular test.
     */
      template <typename... T>
      edm::test::Event test(T&&... iArgs) {
        return testImpl(std::forward<T>(iArgs)...);
      }

      template <typename... T>
      edm::test::LuminosityBlock testBeginLuminosityBlock(edm::LuminosityBlockNumber_t iNum, T&&... iArgs) {
        return testBeginLuminosityBlockImpl(iNum, std::forward<T>(iArgs)...);
      }
      template <typename... T>
      edm::test::LuminosityBlock testEndLuminosityBlock(T&&... iArgs) {
        return testEndLuminosityBlockImpl(std::forward<T>(iArgs)...);
      }

      template <typename... T>
      edm::test::Run testBeginRun(edm::RunNumber_t iNum, T&&... iArgs) {
        return testBeginRunImpl(iNum, std::forward<T>(iArgs)...);
      }
      template <typename... T>
      edm::test::Run testEndRun(T&&... iArgs) {
        return testEndRunImpl(std::forward<T>(iArgs)...);
      }

      // It makes no sense to pass EventSetup products and at least
      // for now Runs, Lumis, and ProcessBlocks don't allow passing
      // in other products. So for now these don't need to be templates
      // for ProcessBlock.
      edm::test::ProcessBlock testBeginProcessBlock() { return testBeginProcessBlockImpl(); }

      edm::test::ProcessBlock testEndProcessBlock() { return testEndProcessBlockImpl(); }

      /** Run only beginJob and endJob. Once this is used, you should not attempt to run any further tests.
This simulates a problem happening early in the job which causes processing not to proceed.
   */
      void testBeginAndEndJobOnly() {
        arena_.execute([this]() {
          beginJob();
          endJob();
        });
      }

      void testWithNoRuns() {
        arena_.execute([this]() {
          beginJob();
          beginProcessBlock();
          endProcessBlock();
          endJob();
        });
      }

      void testRunWithNoLuminosityBlocks() {
        arena_.execute([this]() {
          beginJob();
          beginProcessBlock();
          beginRun();
          endRun();
          endProcessBlock();
          endJob();
        });
      }

      void testLuminosityBlockWithNoEvents() {
        arena_.execute([this]() {
          beginJob();
          beginProcessBlock();
          beginRun();
          beginLuminosityBlock();
          endLuminosityBlock();
          endRun();
          endProcessBlock();
          endJob();
        });
      }
      void setRunNumber(edm::RunNumber_t);
      void setLuminosityBlockNumber(edm::LuminosityBlockNumber_t);
      void setEventNumber(edm::EventNumber_t);

      std::string const& labelOfTestModule() const { return labelOfTestModule_; }

    private:
      template <typename T, typename... U>
      edm::test::Event testImpl(std::pair<edm::EDPutTokenT<T>, std::unique_ptr<T>>&& iPut, U&&... iArgs) {
        put(std::move(iPut));
        return testImpl(std::forward<U>(iArgs)...);
      }

      template <typename T, typename... U>
      edm::test::Event testImpl(std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut, U&&... iArgs) {
        put(std::move(iPut));
        return testImpl(std::forward<U>(iArgs)...);
      }

      template <typename T>
      void put(std::pair<edm::EDPutTokenT<T>, std::unique_ptr<T>>&& iPut) {
        put(iPut.first.index(), std::make_unique<edm::Wrapper<T>>(std::move(iPut.second)));
      }

      template <typename T>
      void put(std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut) {
        dynamic_cast<TestESProductResolver<T>*>(esHelper_->getResolver(iPut.first.index()).get())
            ->setData(std::move(iPut.second));
      }

      void put(unsigned int, std::unique_ptr<WrapperBase>);

      edm::test::Event testImpl();

      template <typename T, typename... U>
      edm::test::LuminosityBlock testBeginLuminosityBlockImpl(
          edm::LuminosityBlockNumber_t iNum,
          std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
          U&&... iArgs) {
        put(std::move(iPut));
        return testBeginLuminosityBlockImpl(iNum, std::forward<U>(iArgs)...);
      }
      edm::test::LuminosityBlock testBeginLuminosityBlockImpl(edm::LuminosityBlockNumber_t);

      template <typename T, typename... U>
      edm::test::LuminosityBlock testEndLuminosityBlockImpl(
          std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut, U&&... iArgs) {
        put(std::move(iPut));
        return testEndLuminosityBlockImpl(std::forward<U>(iArgs)...);
      }
      edm::test::LuminosityBlock testEndLuminosityBlockImpl();

      template <typename T, typename... U>
      edm::test::Run testBeginRunImpl(edm::RunNumber_t iNum,
                                      std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
                                      U&&... iArgs) {
        put(std::move(iPut));
        return testBeginRunImpl(iNum, std::forward<U>(iArgs)...);
      }
      edm::test::Run testBeginRunImpl(edm::RunNumber_t);
      template <typename T, typename... U>
      edm::test::LuminosityBlock testEndRunImpl(std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
                                                U&&... iArgs) {
        put(std::move(iPut));
        return testEndRunImpl(std::forward<U>(iArgs)...);
      }
      edm::test::Run testEndRunImpl();

      edm::test::ProcessBlock testBeginProcessBlockImpl();
      edm::test::ProcessBlock testEndProcessBlockImpl();

      void setupProcessing();
      void teardownProcessing();

      void beginJob();
      void respondToOpenInputFile();
      void openOutputFiles();
      void beginProcessBlock();
      void beginRun();
      void beginLuminosityBlock();
      void event();
      std::shared_ptr<LuminosityBlockPrincipal> endLuminosityBlock();
      std::shared_ptr<RunPrincipal> endRun();
      void respondToCloseInputFile();
      ProcessBlockPrincipal const* endProcessBlock();
      void closeOutputFiles();
      void endJob();

      template <typename Traits>
      void processTransitionForAllStreams(typename Traits::TransitionInfoType& transitionInfo);

      template <typename Traits>
      void processGlobalTransition(typename Traits::TransitionInfoType& transitionInfo);

      // ---------- member data --------------------------------
      oneapi::tbb::global_control globalControl_;
      oneapi::tbb::task_group taskGroup_;
      oneapi::tbb::task_arena arena_;
      std::string labelOfTestModule_;
      std::shared_ptr<ActivityRegistry> actReg_;  // We do not use propagate_const because the registry itself is mutable.
      std::shared_ptr<ProductRegistry> preg_;
      std::shared_ptr<BranchIDListHelper> branchIDListHelper_;
      std::shared_ptr<ProcessBlockHelper> processBlockHelper_;
      std::shared_ptr<ThinnedAssociationsHelper> thinnedAssociationsHelper_;
      ServiceToken serviceToken_;
      std::unique_ptr<ModuleTypeResolverMaker const> moduleTypeResolverMaker_;
      std::unique_ptr<eventsetup::EventSetupsController> espController_;
      std::shared_ptr<eventsetup::EventSetupProvider> esp_;
      std::shared_ptr<EventSetupTestHelper> esHelper_;

      std::unique_ptr<ExceptionToActionTable const> act_table_;
      std::shared_ptr<ProcessConfiguration const> processConfiguration_;
      ProcessContext processContext_;

      MergeableRunProductProcesses mergeableRunProductProcesses_;

      ProcessHistoryRegistry processHistoryRegistry_;
      ProcessHistory processHistory_;
      std::unique_ptr<HistoryAppender> historyAppender_;

      PrincipalCache principalCache_;
      PreallocationConfiguration preallocations_;

      std::shared_ptr<ModuleRegistry> moduleRegistry_;
      std::unique_ptr<Schedule> schedule_;
      std::shared_ptr<RunPrincipal> runPrincipal_;
      std::shared_ptr<LuminosityBlockPrincipal> lumiPrincipal_;

      std::vector<std::pair<edm::ProductDescription, std::unique_ptr<WrapperBase>>> dataProducts_;

      RunNumber_t runNumber_ = 1;
      LuminosityBlockNumber_t lumiNumber_ = 1;
      EventNumber_t eventNumber_ = 1;
      bool beginJobCalled_ = false;
      bool respondToOpenInputFileCalled_ = false;
      bool beginProcessBlockCalled_ = false;
      bool beginRunCalled_ = false;
      bool beginLumiCalled_ = false;
      bool openOutputFilesCalled_ = false;
    };
  }  // namespace test
}  // namespace edm

#endif