<commit_before>//===- Pass.cpp - LLVM Pass Infrastructure Implementation -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LLVM Pass infrastructure.  It is primarily
// responsible with ensuring that passes are executed and batched together
// optimally.
//
//===----------------------------------------------------------------------===//

#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Module.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Atomic.h"
#include "llvm/System/Mutex.h"
#include "llvm/System/Threading.h"
#include <algorithm>
#include <map>
#include <set>
using namespace llvm;

//===----------------------------------------------------------------------===//
// Pass Implementation
//

// Force out-of-line virtual method.
Pass::~Pass() {
  delete Resolver;
}

// Force out-of-line virtual method.
ModulePass::~ModulePass() { }

Pass *ModulePass::createPrinterPass(raw_ostream &O,
                                    const std::string &Banner) const {
  return createPrintModulePass(&O, false, Banner);
}

PassManagerType ModulePass::getPotentialPassManagerType() const {
  return PMT_ModulePassManager;
}

bool Pass::mustPreserveAnalysisID(const PassInfo *AnalysisID) const {
  return Resolver->getAnalysisIfAvailable(AnalysisID, true) != 0;
}

// dumpPassStructure - Implement the -debug-passes=Structure option
void Pass::dumpPassStructure(unsigned Offset) {
  dbgs().indent(Offset*2) << getPassName() << "\n";
}

/// getPassName - Return a nice clean name for a pass.  This usually
/// implemented in terms of the name that is registered by one of the
/// Registration templates, but can be overloaded directly.
///
const char *Pass::getPassName() const {
  if (const PassInfo *PI = getPassInfo())
    return PI->getPassName();
  return "Unnamed pass: implement Pass::getPassName()";
}

void Pass::preparePassManager(PMStack &) {
  // By default, don't do anything.
}

PassManagerType Pass::getPotentialPassManagerType() const {
  // Default implementation.
  return PMT_Unknown;
}

void Pass::getAnalysisUsage(AnalysisUsage &) const {
  // By default, no analysis results are used, all are invalidated.
}

void Pass::releaseMemory() {
  // By default, don't do anything.
}

void Pass::verifyAnalysis() const {
  // By default, don't do anything.
}

// print - Print out the internal state of the pass.  This is called by Analyze
// to print out the contents of an analysis.  Otherwise it is not necessary to
// implement this method.
//
void Pass::print(raw_ostream &O,const Module*) const {
  O << "Pass::print not implemented for pass: '" << getPassName() << "'!\n";
}

// dump - call print(cerr);
void Pass::dump() const {
  print(dbgs(), 0);
}

//===----------------------------------------------------------------------===//
// ImmutablePass Implementation
//
// Force out-of-line virtual method.
ImmutablePass::~ImmutablePass() { }

void ImmutablePass::initializePass() {
  // By default, don't do anything.
}

//===----------------------------------------------------------------------===//
// FunctionPass Implementation
//

Pass *FunctionPass::createPrinterPass(raw_ostream &O,
                                      const std::string &Banner) const {
  return createPrintFunctionPass(Banner, &O);
}

// run - On a module, we run this pass by initializing, runOnFunction'ing once
// for every function in the module, then by finalizing.
//
bool FunctionPass::runOnModule(Module &M) {
  bool Changed = doInitialization(M);

  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration())      // Passes are not run on external functions!
    Changed |= runOnFunction(*I);

  return Changed | doFinalization(M);
}

// run - On a function, we simply initialize, run the function, then finalize.
//
bool FunctionPass::run(Function &F) {
  // Passes are not run on external functions!
  if (F.isDeclaration()) return false;

  bool Changed = doInitialization(*F.getParent());
  Changed |= runOnFunction(F);
  return Changed | doFinalization(*F.getParent());
}

bool FunctionPass::doInitialization(Module &) {
  // By default, don't do anything.
  return false;
}

bool FunctionPass::doFinalization(Module &) {
  // By default, don't do anything.
  return false;
}

PassManagerType FunctionPass::getPotentialPassManagerType() const {
  return PMT_FunctionPassManager;
}

//===----------------------------------------------------------------------===//
// BasicBlockPass Implementation
//

Pass *BasicBlockPass::createPrinterPass(raw_ostream &O,
                                        const std::string &Banner) const {

  llvm_unreachable("BasicBlockPass printing unsupported.");
  return 0;
}

// To run this pass on a function, we simply call runOnBasicBlock once for each
// function.
//
bool BasicBlockPass::runOnFunction(Function &F) {
  bool Changed = doInitialization(F);
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
    Changed |= runOnBasicBlock(*I);
  return Changed | doFinalization(F);
}

bool BasicBlockPass::doInitialization(Module &) {
  // By default, don't do anything.
  return false;
}

bool BasicBlockPass::doInitialization(Function &) {
  // By default, don't do anything.
  return false;
}

bool BasicBlockPass::doFinalization(Function &) {
  // By default, don't do anything.
  return false;
}

bool BasicBlockPass::doFinalization(Module &) {
  // By default, don't do anything.
  return false;
}

PassManagerType BasicBlockPass::getPotentialPassManagerType() const {
  return PMT_BasicBlockPassManager;
}

//===----------------------------------------------------------------------===//
// Pass Registration mechanism
//
namespace {
class PassRegistrar {
  /// Guards the contents of this class.
  mutable sys::SmartMutex<true> Lock;

  /// PassInfoMap - Keep track of the passinfo object for each registered llvm
  /// pass.
  typedef std::map<intptr_t, const PassInfo*> MapType;
  MapType PassInfoMap;

  typedef StringMap<const PassInfo*> StringMapType;
  StringMapType PassInfoStringMap;

  /// AnalysisGroupInfo - Keep track of information for each analysis group.
  struct AnalysisGroupInfo {
    std::set<const PassInfo *> Implementations;
  };

  /// AnalysisGroupInfoMap - Information for each analysis group.
  std::map<const PassInfo *, AnalysisGroupInfo> AnalysisGroupInfoMap;

public:

  const PassInfo *GetPassInfo(intptr_t TI) const {
    sys::SmartScopedLock<true> Guard(Lock);
    MapType::const_iterator I = PassInfoMap.find(TI);
    return I != PassInfoMap.end() ? I->second : 0;
  }

  const PassInfo *GetPassInfo(StringRef Arg) const {
    sys::SmartScopedLock<true> Guard(Lock);
    StringMapType::const_iterator I = PassInfoStringMap.find(Arg);
    return I != PassInfoStringMap.end() ? I->second : 0;
  }

  void RegisterPass(const PassInfo &PI) {
    sys::SmartScopedLock<true> Guard(Lock);
    bool Inserted =
      PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second;
    assert(Inserted && "Pass registered multiple times!"); Inserted=Inserted;
    PassInfoStringMap[PI.getPassArgument()] = &PI;
  }

  void UnregisterPass(const PassInfo &PI) {
    sys::SmartScopedLock<true> Guard(Lock);
    MapType::iterator I = PassInfoMap.find(PI.getTypeInfo());
    assert(I != PassInfoMap.end() && "Pass registered but not in map!");

    // Remove pass from the map.
    PassInfoMap.erase(I);
    PassInfoStringMap.erase(PI.getPassArgument());
  }

  void EnumerateWith(PassRegistrationListener *L) {
    sys::SmartScopedLock<true> Guard(Lock);
    for (MapType::const_iterator I = PassInfoMap.begin(),
         E = PassInfoMap.end(); I != E; ++I)
      L->passEnumerate(I->second);
  }

  /// Analysis Group Mechanisms.
  void RegisterAnalysisGroup(PassInfo *InterfaceInfo,
                             const PassInfo *ImplementationInfo,
                             bool isDefault) {
    sys::SmartScopedLock<true> Guard(Lock);
    AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo];
    assert(AGI.Implementations.count(ImplementationInfo) == 0 &&
           "Cannot add a pass to the same analysis group more than once!");
    AGI.Implementations.insert(ImplementationInfo);
    if (isDefault) {
      assert(InterfaceInfo->getNormalCtor() == 0 &&
             "Default implementation for analysis group already specified!");
      assert(ImplementationInfo->getNormalCtor() &&
           "Cannot specify pass as default if it does not have a default ctor");
      InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
    }
  }
};
}

static std::vector<PassRegistrationListener*> *Listeners = 0;
static sys::SmartMutex<true> ListenersLock;

static PassRegistrar *PassRegistrarObj = 0;
static PassRegistrar *getPassRegistrar() {
  // Use double-checked locking to safely initialize the registrar when
  // we're running in multithreaded mode.
  PassRegistrar* tmp = PassRegistrarObj;
  if (llvm_is_multithreaded()) {
    sys::MemoryFence();
    if (!tmp) {
      llvm_acquire_global_lock();
      tmp = PassRegistrarObj;
      if (!tmp) {
        tmp = new PassRegistrar();
        sys::MemoryFence();
        PassRegistrarObj = tmp;
      }
      llvm_release_global_lock();
    }
  } else if (!tmp) {
    PassRegistrarObj = new PassRegistrar();
  }

  return PassRegistrarObj;
}

// FIXME: We use ManagedCleanup to erase the pass registrar on shutdown.
// Unfortunately, passes are registered with static ctors, and having
// llvm_shutdown clear this map prevents successful ressurection after
// llvm_shutdown is run.  Ideally we should find a solution so that we don't
// leak the map, AND can still resurrect after shutdown.
void cleanupPassRegistrar(void*) {
  if (PassRegistrarObj) {
    delete PassRegistrarObj;
    PassRegistrarObj = 0;
  }
}
ManagedCleanup<&cleanupPassRegistrar> registrarCleanup;

// getPassInfo - Return the PassInfo data structure that corresponds to this
// pass...
const PassInfo *Pass::getPassInfo() const {
  return lookupPassInfo(PassID);
}

const PassInfo *Pass::lookupPassInfo(intptr_t TI) {
  return getPassRegistrar()->GetPassInfo(TI);
}

const PassInfo *Pass::lookupPassInfo(StringRef Arg) {
  return getPassRegistrar()->GetPassInfo(Arg);
}

void PassInfo::registerPass() {
  getPassRegistrar()->RegisterPass(*this);

  // Notify any listeners.
  sys::SmartScopedLock<true> Lock(ListenersLock);
  if (Listeners)
    for (std::vector<PassRegistrationListener*>::iterator
           I = Listeners->begin(), E = Listeners->end(); I != E; ++I)
      (*I)->passRegistered(this);
}

void PassInfo::unregisterPass() {
  getPassRegistrar()->UnregisterPass(*this);
}

//===----------------------------------------------------------------------===//
//                  Analysis Group Implementation Code
//===----------------------------------------------------------------------===//

// RegisterAGBase implementation
//
RegisterAGBase::RegisterAGBase(const char *Name, intptr_t InterfaceID,
                               intptr_t PassID, bool isDefault)
  : PassInfo(Name, InterfaceID) {

  PassInfo *InterfaceInfo =
    const_cast<PassInfo*>(Pass::lookupPassInfo(InterfaceID));
  if (InterfaceInfo == 0) {
    // First reference to Interface, register it now.
    registerPass();
    InterfaceInfo = this;
  }
  assert(isAnalysisGroup() &&
         "Trying to join an analysis group that is a normal pass!");

  if (PassID) {
    const PassInfo *ImplementationInfo = Pass::lookupPassInfo(PassID);
    assert(ImplementationInfo &&
           "Must register pass before adding to AnalysisGroup!");

    // Make sure we keep track of the fact that the implementation implements
    // the interface.
    PassInfo *IIPI = const_cast<PassInfo*>(ImplementationInfo);
    IIPI->addInterfaceImplemented(InterfaceInfo);

    getPassRegistrar()->RegisterAnalysisGroup(InterfaceInfo, IIPI, isDefault);
  }
}

//===----------------------------------------------------------------------===//
// PassRegistrationListener implementation
//

// PassRegistrationListener ctor - Add the current object to the list of
// PassRegistrationListeners...
PassRegistrationListener::PassRegistrationListener() {
  sys::SmartScopedLock<true> Lock(ListenersLock);
  if (!Listeners) Listeners = new std::vector<PassRegistrationListener*>();
  Listeners->push_back(this);
}

// dtor - Remove object from list of listeners...
PassRegistrationListener::~PassRegistrationListener() {
  sys::SmartScopedLock<true> Lock(ListenersLock);
  std::vector<PassRegistrationListener*>::iterator I =
    std::find(Listeners->begin(), Listeners->end(), this);
  assert(Listeners && I != Listeners->end() &&
         "PassRegistrationListener not registered!");
  Listeners->erase(I);

  if (Listeners->empty()) {
    delete Listeners;
    Listeners = 0;
  }
}

// enumeratePasses - Iterate over the registered passes, calling the
// passEnumerate callback on each PassInfo object.
//
void PassRegistrationListener::enumeratePasses() {
  getPassRegistrar()->EnumerateWith(this);
}

PassNameParser::~PassNameParser() {}

//===----------------------------------------------------------------------===//
//   AnalysisUsage Class Implementation
//

namespace {
  struct GetCFGOnlyPasses : public PassRegistrationListener {
    typedef AnalysisUsage::VectorType VectorType;
    VectorType &CFGOnlyList;
    GetCFGOnlyPasses(VectorType &L) : CFGOnlyList(L) {}

    void passEnumerate(const PassInfo *P) {
      if (P->isCFGOnlyPass())
        CFGOnlyList.push_back(P);
    }
  };
}

// setPreservesCFG - This function should be called to by the pass, iff they do
// not:
//
//  1. Add or remove basic blocks from the function
//  2. Modify terminator instructions in any way.
//
// This function annotates the AnalysisUsage info object to say that analyses
// that only depend on the CFG are preserved by this pass.
//
void AnalysisUsage::setPreservesCFG() {
  // Since this transformation doesn't modify the CFG, it preserves all analyses
  // that only depend on the CFG (like dominators, loop info, etc...)
  GetCFGOnlyPasses(Preserved).enumeratePasses();
}

<commit_msg>Fix namespace polution.<commit_after>//===- Pass.cpp - LLVM Pass Infrastructure Implementation -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LLVM Pass infrastructure.  It is primarily
// responsible with ensuring that passes are executed and batched together
// optimally.
//
//===----------------------------------------------------------------------===//

#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Module.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Atomic.h"
#include "llvm/System/Mutex.h"
#include "llvm/System/Threading.h"
#include <algorithm>
#include <map>
#include <set>
using namespace llvm;

//===----------------------------------------------------------------------===//
// Pass Implementation
//

// Force out-of-line virtual method.
Pass::~Pass() {
  delete Resolver;
}

// Force out-of-line virtual method.
ModulePass::~ModulePass() { }

Pass *ModulePass::createPrinterPass(raw_ostream &O,
                                    const std::string &Banner) const {
  return createPrintModulePass(&O, false, Banner);
}

PassManagerType ModulePass::getPotentialPassManagerType() const {
  return PMT_ModulePassManager;
}

bool Pass::mustPreserveAnalysisID(const PassInfo *AnalysisID) const {
  return Resolver->getAnalysisIfAvailable(AnalysisID, true) != 0;
}

// dumpPassStructure - Implement the -debug-passes=Structure option
void Pass::dumpPassStructure(unsigned Offset) {
  dbgs().indent(Offset*2) << getPassName() << "\n";
}

/// getPassName - Return a nice clean name for a pass.  This usually
/// implemented in terms of the name that is registered by one of the
/// Registration templates, but can be overloaded directly.
///
const char *Pass::getPassName() const {
  if (const PassInfo *PI = getPassInfo())
    return PI->getPassName();
  return "Unnamed pass: implement Pass::getPassName()";
}

void Pass::preparePassManager(PMStack &) {
  // By default, don't do anything.
}

PassManagerType Pass::getPotentialPassManagerType() const {
  // Default implementation.
  return PMT_Unknown;
}

void Pass::getAnalysisUsage(AnalysisUsage &) const {
  // By default, no analysis results are used, all are invalidated.
}

void Pass::releaseMemory() {
  // By default, don't do anything.
}

void Pass::verifyAnalysis() const {
  // By default, don't do anything.
}

// print - Print out the internal state of the pass.  This is called by Analyze
// to print out the contents of an analysis.  Otherwise it is not necessary to
// implement this method.
//
void Pass::print(raw_ostream &O,const Module*) const {
  O << "Pass::print not implemented for pass: '" << getPassName() << "'!\n";
}

// dump - call print(cerr);
void Pass::dump() const {
  print(dbgs(), 0);
}

//===----------------------------------------------------------------------===//
// ImmutablePass Implementation
//
// Force out-of-line virtual method.
ImmutablePass::~ImmutablePass() { }

void ImmutablePass::initializePass() {
  // By default, don't do anything.
}

//===----------------------------------------------------------------------===//
// FunctionPass Implementation
//

Pass *FunctionPass::createPrinterPass(raw_ostream &O,
                                      const std::string &Banner) const {
  return createPrintFunctionPass(Banner, &O);
}

// run - On a module, we run this pass by initializing, runOnFunction'ing once
// for every function in the module, then by finalizing.
//
bool FunctionPass::runOnModule(Module &M) {
  bool Changed = doInitialization(M);

  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration())      // Passes are not run on external functions!
    Changed |= runOnFunction(*I);

  return Changed | doFinalization(M);
}

// run - On a function, we simply initialize, run the function, then finalize.
//
bool FunctionPass::run(Function &F) {
  // Passes are not run on external functions!
  if (F.isDeclaration()) return false;

  bool Changed = doInitialization(*F.getParent());
  Changed |= runOnFunction(F);
  return Changed | doFinalization(*F.getParent());
}

bool FunctionPass::doInitialization(Module &) {
  // By default, don't do anything.
  return false;
}

bool FunctionPass::doFinalization(Module &) {
  // By default, don't do anything.
  return false;
}

PassManagerType FunctionPass::getPotentialPassManagerType() const {
  return PMT_FunctionPassManager;
}

//===----------------------------------------------------------------------===//
// BasicBlockPass Implementation
//

Pass *BasicBlockPass::createPrinterPass(raw_ostream &O,
                                        const std::string &Banner) const {

  llvm_unreachable("BasicBlockPass printing unsupported.");
  return 0;
}

// To run this pass on a function, we simply call runOnBasicBlock once for each
// function.
//
bool BasicBlockPass::runOnFunction(Function &F) {
  bool Changed = doInitialization(F);
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
    Changed |= runOnBasicBlock(*I);
  return Changed | doFinalization(F);
}

bool BasicBlockPass::doInitialization(Module &) {
  // By default, don't do anything.
  return false;
}

bool BasicBlockPass::doInitialization(Function &) {
  // By default, don't do anything.
  return false;
}

bool BasicBlockPass::doFinalization(Function &) {
  // By default, don't do anything.
  return false;
}

bool BasicBlockPass::doFinalization(Module &) {
  // By default, don't do anything.
  return false;
}

PassManagerType BasicBlockPass::getPotentialPassManagerType() const {
  return PMT_BasicBlockPassManager;
}

//===----------------------------------------------------------------------===//
// Pass Registration mechanism
//
namespace {
class PassRegistrar {
  /// Guards the contents of this class.
  mutable sys::SmartMutex<true> Lock;

  /// PassInfoMap - Keep track of the passinfo object for each registered llvm
  /// pass.
  typedef std::map<intptr_t, const PassInfo*> MapType;
  MapType PassInfoMap;

  typedef StringMap<const PassInfo*> StringMapType;
  StringMapType PassInfoStringMap;

  /// AnalysisGroupInfo - Keep track of information for each analysis group.
  struct AnalysisGroupInfo {
    std::set<const PassInfo *> Implementations;
  };

  /// AnalysisGroupInfoMap - Information for each analysis group.
  std::map<const PassInfo *, AnalysisGroupInfo> AnalysisGroupInfoMap;

public:

  const PassInfo *GetPassInfo(intptr_t TI) const {
    sys::SmartScopedLock<true> Guard(Lock);
    MapType::const_iterator I = PassInfoMap.find(TI);
    return I != PassInfoMap.end() ? I->second : 0;
  }

  const PassInfo *GetPassInfo(StringRef Arg) const {
    sys::SmartScopedLock<true> Guard(Lock);
    StringMapType::const_iterator I = PassInfoStringMap.find(Arg);
    return I != PassInfoStringMap.end() ? I->second : 0;
  }

  void RegisterPass(const PassInfo &PI) {
    sys::SmartScopedLock<true> Guard(Lock);
    bool Inserted =
      PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second;
    assert(Inserted && "Pass registered multiple times!"); Inserted=Inserted;
    PassInfoStringMap[PI.getPassArgument()] = &PI;
  }

  void UnregisterPass(const PassInfo &PI) {
    sys::SmartScopedLock<true> Guard(Lock);
    MapType::iterator I = PassInfoMap.find(PI.getTypeInfo());
    assert(I != PassInfoMap.end() && "Pass registered but not in map!");

    // Remove pass from the map.
    PassInfoMap.erase(I);
    PassInfoStringMap.erase(PI.getPassArgument());
  }

  void EnumerateWith(PassRegistrationListener *L) {
    sys::SmartScopedLock<true> Guard(Lock);
    for (MapType::const_iterator I = PassInfoMap.begin(),
         E = PassInfoMap.end(); I != E; ++I)
      L->passEnumerate(I->second);
  }

  /// Analysis Group Mechanisms.
  void RegisterAnalysisGroup(PassInfo *InterfaceInfo,
                             const PassInfo *ImplementationInfo,
                             bool isDefault) {
    sys::SmartScopedLock<true> Guard(Lock);
    AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo];
    assert(AGI.Implementations.count(ImplementationInfo) == 0 &&
           "Cannot add a pass to the same analysis group more than once!");
    AGI.Implementations.insert(ImplementationInfo);
    if (isDefault) {
      assert(InterfaceInfo->getNormalCtor() == 0 &&
             "Default implementation for analysis group already specified!");
      assert(ImplementationInfo->getNormalCtor() &&
           "Cannot specify pass as default if it does not have a default ctor");
      InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
    }
  }
};
}

static std::vector<PassRegistrationListener*> *Listeners = 0;
static sys::SmartMutex<true> ListenersLock;

static PassRegistrar *PassRegistrarObj = 0;
static PassRegistrar *getPassRegistrar() {
  // Use double-checked locking to safely initialize the registrar when
  // we're running in multithreaded mode.
  PassRegistrar* tmp = PassRegistrarObj;
  if (llvm_is_multithreaded()) {
    sys::MemoryFence();
    if (!tmp) {
      llvm_acquire_global_lock();
      tmp = PassRegistrarObj;
      if (!tmp) {
        tmp = new PassRegistrar();
        sys::MemoryFence();
        PassRegistrarObj = tmp;
      }
      llvm_release_global_lock();
    }
  } else if (!tmp) {
    PassRegistrarObj = new PassRegistrar();
  }

  return PassRegistrarObj;
}

namespace {

// FIXME: We use ManagedCleanup to erase the pass registrar on shutdown.
// Unfortunately, passes are registered with static ctors, and having
// llvm_shutdown clear this map prevents successful ressurection after
// llvm_shutdown is run.  Ideally we should find a solution so that we don't
// leak the map, AND can still resurrect after shutdown.
void cleanupPassRegistrar(void*) {
  if (PassRegistrarObj) {
    delete PassRegistrarObj;
    PassRegistrarObj = 0;
  }
}
ManagedCleanup<&cleanupPassRegistrar> registrarCleanup;

}

// getPassInfo - Return the PassInfo data structure that corresponds to this
// pass...
const PassInfo *Pass::getPassInfo() const {
  return lookupPassInfo(PassID);
}

const PassInfo *Pass::lookupPassInfo(intptr_t TI) {
  return getPassRegistrar()->GetPassInfo(TI);
}

const PassInfo *Pass::lookupPassInfo(StringRef Arg) {
  return getPassRegistrar()->GetPassInfo(Arg);
}

void PassInfo::registerPass() {
  getPassRegistrar()->RegisterPass(*this);

  // Notify any listeners.
  sys::SmartScopedLock<true> Lock(ListenersLock);
  if (Listeners)
    for (std::vector<PassRegistrationListener*>::iterator
           I = Listeners->begin(), E = Listeners->end(); I != E; ++I)
      (*I)->passRegistered(this);
}

void PassInfo::unregisterPass() {
  getPassRegistrar()->UnregisterPass(*this);
}

//===----------------------------------------------------------------------===//
//                  Analysis Group Implementation Code
//===----------------------------------------------------------------------===//

// RegisterAGBase implementation
//
RegisterAGBase::RegisterAGBase(const char *Name, intptr_t InterfaceID,
                               intptr_t PassID, bool isDefault)
  : PassInfo(Name, InterfaceID) {

  PassInfo *InterfaceInfo =
    const_cast<PassInfo*>(Pass::lookupPassInfo(InterfaceID));
  if (InterfaceInfo == 0) {
    // First reference to Interface, register it now.
    registerPass();
    InterfaceInfo = this;
  }
  assert(isAnalysisGroup() &&
         "Trying to join an analysis group that is a normal pass!");

  if (PassID) {
    const PassInfo *ImplementationInfo = Pass::lookupPassInfo(PassID);
    assert(ImplementationInfo &&
           "Must register pass before adding to AnalysisGroup!");

    // Make sure we keep track of the fact that the implementation implements
    // the interface.
    PassInfo *IIPI = const_cast<PassInfo*>(ImplementationInfo);
    IIPI->addInterfaceImplemented(InterfaceInfo);

    getPassRegistrar()->RegisterAnalysisGroup(InterfaceInfo, IIPI, isDefault);
  }
}

//===----------------------------------------------------------------------===//
// PassRegistrationListener implementation
//

// PassRegistrationListener ctor - Add the current object to the list of
// PassRegistrationListeners...
PassRegistrationListener::PassRegistrationListener() {
  sys::SmartScopedLock<true> Lock(ListenersLock);
  if (!Listeners) Listeners = new std::vector<PassRegistrationListener*>();
  Listeners->push_back(this);
}

// dtor - Remove object from list of listeners...
PassRegistrationListener::~PassRegistrationListener() {
  sys::SmartScopedLock<true> Lock(ListenersLock);
  std::vector<PassRegistrationListener*>::iterator I =
    std::find(Listeners->begin(), Listeners->end(), this);
  assert(Listeners && I != Listeners->end() &&
         "PassRegistrationListener not registered!");
  Listeners->erase(I);

  if (Listeners->empty()) {
    delete Listeners;
    Listeners = 0;
  }
}

// enumeratePasses - Iterate over the registered passes, calling the
// passEnumerate callback on each PassInfo object.
//
void PassRegistrationListener::enumeratePasses() {
  getPassRegistrar()->EnumerateWith(this);
}

PassNameParser::~PassNameParser() {}

//===----------------------------------------------------------------------===//
//   AnalysisUsage Class Implementation
//

namespace {
  struct GetCFGOnlyPasses : public PassRegistrationListener {
    typedef AnalysisUsage::VectorType VectorType;
    VectorType &CFGOnlyList;
    GetCFGOnlyPasses(VectorType &L) : CFGOnlyList(L) {}

    void passEnumerate(const PassInfo *P) {
      if (P->isCFGOnlyPass())
        CFGOnlyList.push_back(P);
    }
  };
}

// setPreservesCFG - This function should be called to by the pass, iff they do
// not:
//
//  1. Add or remove basic blocks from the function
//  2. Modify terminator instructions in any way.
//
// This function annotates the AnalysisUsage info object to say that analyses
// that only depend on the CFG are preserved by this pass.
//
void AnalysisUsage::setPreservesCFG() {
  // Since this transformation doesn't modify the CFG, it preserves all analyses
  // that only depend on the CFG (like dominators, loop info, etc...)
  GetCFGOnlyPasses(Preserved).enumeratePasses();
}

<|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

/**
 * @internal
 *
 * @def LIBBIRCH_BASE
 *
 * Declare the base type for a class.
 */
#define LIBBIRCH_BASE(Base...) \
  using base_type_ = Base; \
  \
  auto shared_from_base_() { \
    return libbirch::Shared<base_type_>(static_cast<base_type_*>(this)); \
  }

/**
 * @internal
 *
 * @def LIBBIRCH_THIS
 *
 * Declare this type for a class.
 */
#define LIBBIRCH_THIS(Name...) \
  using this_type_ = Name; \
  \
  auto shared_from_this_() { \
    return libbirch::Shared<this_type_>(this); \
  }

/**
 * @internal
 *
 * @def LIBBIRCH_VIRTUAL
 *
 * Declare virtual functions for concrete classes.
 */
#define LIBBIRCH_VIRTUAL(Name, Base...) \
  virtual const char* getClassName() const { \
    return #Name; \
  } \
  \
  virtual int size_() const override { \
    return sizeof(*this); \
  } \
  \
  virtual Name* copy_() const override { \
    return new Name(*this); \
  }

/**
 * @def LIBBIRCH_CLASS
 *
 * Boilerplate macro for classes to support lazy deep copy. The first
 * argument is the name of the class; this should exclude any generic type
 * arguments. The second argument is the base class; this should include any
 * generic type arguments. It is recommended that the macro is used at the
 * very end of the class definition.
 *
 * LIBBIRCH_CLASS must be followed by LIBBIRCH_MEMBERS, and should be in a
 * public section, e.g.:
 *
 *     class A : public B {
 *     private:
 *       int x, y, z;
 *
 *     public:
 *       LIBBIRCH_CLASS(A, B)
 *       LIBBIRCH_MEMBERS(x, y, z)
 *     };
 *
 * The use of a variadic macro here supports base classes that contain
 * commas without special treatment, e.g.
 *
 *     LIBBIRCH_CLASS(A, B<T,U>)
 */
#define LIBBIRCH_CLASS(Name, Base...) public: \
  LIBBIRCH_THIS(Name) \
  LIBBIRCH_BASE(Base) \
  LIBBIRCH_VIRTUAL(Name, Base)

/**
 * @def LIBBIRCH_ABSTRACT_CLASS
 *
 * Use in place of LIBBIRCH_CLASS when the containing class is abstract.
 */
#define LIBBIRCH_ABSTRACT_CLASS(Name, Base...) public: \
  LIBBIRCH_THIS(Name) \
  LIBBIRCH_BASE(Base)

/**
 * @def LIBBIRCH_MEMBERS
 *
 * Boilerplate macro for classes to support lazy deep copy. The arguments
 * list all member variables of the class (but not those of a base class,
 * which should be listed in its own use of LIBBIRCH_MEMBERS).
 *
 * LIBBIRCH_MEMBERS must be preceded by LIBBIRCH_CLASS, and should be in a
 * public section, e.g.:
 *
 *     class A : public B {
 *     private:
 *       int x, y, z;
 *
 *     public:
 *       LIBBIRCH_CLASS(A, B)
 *       LIBBIRCH_MEMBERS(x, y, z)
 *     };
 */
#define LIBBIRCH_MEMBERS(...) \
  void accept_(libbirch::Marker& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  void accept_(libbirch::Scanner& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  void accept_(libbirch::Reacher& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  void accept_(libbirch::Collector& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  std::tuple<int,int,int> accept_(libbirch::Spanner& visitor_, const int i_, const int j_) override { \
    int l_, h_, m_, l1_, h1_, m1_; \
    std::tie(l_, h_, m_) = base_type_::accept_(visitor_, i_, j_); \
    std::tie(l1_, h1_, m1_) = visitor_.visit(i_, j_ + m_ __VA_OPT__(,) __VA_ARGS__); \
    l_ = std::min(l_, l1_); \
    h_ = std::max(h_, h1_); \
    m_ += m1_; \
    return std::make_tuple(l_, h_, m_); \
  } \
  \
  std::tuple<int,int,int,int> accept_(libbirch::Bridger& visitor_, const int j_, const int k_) override { \
    int l_, h_, m_, n_, l1_, h1_, m1_, n1_; \
    std::tie(l_, h_, m_, n_) = base_type_::accept_(visitor_, j_, k_); \
    std::tie(l1_, h1_, m1_, n1_) = visitor_.visit(j_ + m_, k_ + n_ __VA_OPT__(,) __VA_ARGS__); \
    l_ = std::min(l_, l1_); \
    h_ = std::max(h_, h1_); \
    m_ += m1_; \
    n_ += n1_; \
    return std::make_tuple(l_, h_, m_, n_); \
  } \
  \
  void accept_(libbirch::Copier& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  }

#include "libbirch/Marker.hpp"
#include "libbirch/Scanner.hpp"
#include "libbirch/Reacher.hpp"
#include "libbirch/Collector.hpp"
#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
<commit_msg>Replaced __VA_OPT__(,) with ## GNU extension.<commit_after>/**
 * @file
 */
#pragma once

/**
 * @internal
 *
 * @def LIBBIRCH_BASE
 *
 * Declare the base type for a class.
 */
#define LIBBIRCH_BASE(Base...) \
  using base_type_ = Base; \
  \
  auto shared_from_base_() { \
    return libbirch::Shared<base_type_>(static_cast<base_type_*>(this)); \
  }

/**
 * @internal
 *
 * @def LIBBIRCH_THIS
 *
 * Declare this type for a class.
 */
#define LIBBIRCH_THIS(Name...) \
  using this_type_ = Name; \
  \
  auto shared_from_this_() { \
    return libbirch::Shared<this_type_>(this); \
  }

/**
 * @internal
 *
 * @def LIBBIRCH_VIRTUAL
 *
 * Declare virtual functions for concrete classes.
 */
#define LIBBIRCH_VIRTUAL(Name, Base...) \
  virtual const char* getClassName() const { \
    return #Name; \
  } \
  \
  virtual int size_() const override { \
    return sizeof(*this); \
  } \
  \
  virtual Name* copy_() const override { \
    return new Name(*this); \
  }

/**
 * @def LIBBIRCH_CLASS
 *
 * Boilerplate macro for classes to support lazy deep copy. The first
 * argument is the name of the class; this should exclude any generic type
 * arguments. The second argument is the base class; this should include any
 * generic type arguments. It is recommended that the macro is used at the
 * very end of the class definition.
 *
 * LIBBIRCH_CLASS must be followed by LIBBIRCH_MEMBERS, and should be in a
 * public section, e.g.:
 *
 *     class A : public B {
 *     private:
 *       int x, y, z;
 *
 *     public:
 *       LIBBIRCH_CLASS(A, B)
 *       LIBBIRCH_MEMBERS(x, y, z)
 *     };
 *
 * The use of a variadic macro here supports base classes that contain
 * commas without special treatment, e.g.
 *
 *     LIBBIRCH_CLASS(A, B<T,U>)
 */
#define LIBBIRCH_CLASS(Name, Base...) public: \
  LIBBIRCH_THIS(Name) \
  LIBBIRCH_BASE(Base) \
  LIBBIRCH_VIRTUAL(Name, Base)

/**
 * @def LIBBIRCH_ABSTRACT_CLASS
 *
 * Use in place of LIBBIRCH_CLASS when the containing class is abstract.
 */
#define LIBBIRCH_ABSTRACT_CLASS(Name, Base...) public: \
  LIBBIRCH_THIS(Name) \
  LIBBIRCH_BASE(Base)

/**
 * @def LIBBIRCH_MEMBERS
 *
 * Boilerplate macro for classes to support lazy deep copy. The arguments
 * list all member variables of the class (but not those of a base class,
 * which should be listed in its own use of LIBBIRCH_MEMBERS).
 *
 * LIBBIRCH_MEMBERS must be preceded by LIBBIRCH_CLASS, and should be in a
 * public section, e.g.:
 *
 *     class A : public B {
 *     private:
 *       int x, y, z;
 *
 *     public:
 *       LIBBIRCH_CLASS(A, B)
 *       LIBBIRCH_MEMBERS(x, y, z)
 *     };
 */
#define LIBBIRCH_MEMBERS(...) \
  void accept_(libbirch::Marker& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  void accept_(libbirch::Scanner& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  void accept_(libbirch::Reacher& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  void accept_(libbirch::Collector& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  } \
  \
  std::tuple<int,int,int> accept_(libbirch::Spanner& visitor_, const int i_, const int j_) override { \
    int l_, h_, m_, l1_, h1_, m1_; \
    std::tie(l_, h_, m_) = base_type_::accept_(visitor_, i_, j_); \
    std::tie(l1_, h1_, m1_) = visitor_.visit(i_, j_ + m_, ##__VA_ARGS__); \
    l_ = std::min(l_, l1_); \
    h_ = std::max(h_, h1_); \
    m_ += m1_; \
    return std::make_tuple(l_, h_, m_); \
  } \
  \
  std::tuple<int,int,int,int> accept_(libbirch::Bridger& visitor_, const int j_, const int k_) override { \
    int l_, h_, m_, n_, l1_, h1_, m1_, n1_; \
    std::tie(l_, h_, m_, n_) = base_type_::accept_(visitor_, j_, k_); \
    std::tie(l1_, h1_, m1_, n1_) = visitor_.visit(j_ + m_, k_ + n_, ##__VA_ARGS__); \
    l_ = std::min(l_, l1_); \
    h_ = std::max(h_, h1_); \
    m_ += m1_; \
    n_ += n1_; \
    return std::make_tuple(l_, h_, m_, n_); \
  } \
  \
  void accept_(libbirch::Copier& visitor_) override { \
    base_type_::accept_(visitor_); \
    visitor_.visit(__VA_ARGS__); \
  }

#include "libbirch/Marker.hpp"
#include "libbirch/Scanner.hpp"
#include "libbirch/Reacher.hpp"
#include "libbirch/Collector.hpp"
#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
<|endoftext|>


<commit_before>#include <cucumber-cpp/internal/connectors/wire/WireServer.hpp>

#include <gmock/gmock.h>

#include <boost/filesystem/operations.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/timer.hpp>

#include <stdlib.h>
#include <sstream>

using namespace cucumber::internal;
using namespace boost::posix_time;
using namespace boost::asio::ip;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
using namespace boost::asio::local;
#endif
using namespace std;
using namespace testing;
using boost::bind;
using boost::thread;
namespace fs = boost::filesystem;

static const time_duration THREAD_TEST_TIMEOUT = milliseconds(4000);

MATCHER(IsConnected, string(negation ? "is not" : "is") +
        " connected") { return arg.good(); }

MATCHER(HasTerminated, "") {
    return !arg.joinable();
}

MATCHER(EventuallyTerminates, "") {
    return arg->timed_join(THREAD_TEST_TIMEOUT);
}

MATCHER_P(EventuallyReceives, value, "") {
    std::basic_iostream<char> *stream = const_cast<std::basic_iostream<char> *>(
            static_cast<const std::basic_iostream<char> *>(&arg));
    std::string output;
// FIXME It should not block
    (*stream) >> output;
//    boost::timer timer;
//    double timeout = THREAD_TEST_TIMEOUT.total_milliseconds() / 1000.0;
//    while (timer.elapsed() < timeout) {
//        if (stream->rdbuf()->available() > 0) { // it is zero even if it doesn't block!
//            (*stream) >> output;
//            break;
//        }
//        boost::this_thread::yield();
//    }
    return (output == value);
}

class MockProtocolHandler : public ProtocolHandler {
public:
    MOCK_CONST_METHOD1(handle, string(const string &request));
};

class SocketServerTest : public Test {

protected:
    StrictMock<MockProtocolHandler> protocolHandler;
    boost::scoped_ptr<thread> serverThread;

    virtual void SetUp() {
        SocketServer* server = createListeningServer();
        serverThread.reset(new thread(&SocketServer::acceptOnce, server));
    }

    virtual void TearDown() {
        if (serverThread) {
            serverThread->timed_join(THREAD_TEST_TIMEOUT);
            serverThread.reset();
        }
        destroyListeningServer();
    }

    virtual SocketServer* createListeningServer() = 0;
    virtual void destroyListeningServer() = 0;
};

class TCPSocketServerTest : public SocketServerTest {
protected:
    boost::scoped_ptr<TCPSocketServer> server;

    virtual SocketServer* createListeningServer() {
        server.reset(new TCPSocketServer(&protocolHandler));
        server->listen(0);
        return server.get();
    }

    virtual void destroyListeningServer() {
        server.reset();
    }
};

TEST_F(TCPSocketServerTest, exitsOnFirstConnectionClosed) {
    // given
    tcp::iostream client(server->listenEndpoint());
    ASSERT_THAT(client, IsConnected());
    ASSERT_THAT(server->listenEndpoint().address().to_string(), std::string("0.0.0.0"));

    // when
    client.close();

    // then
    EXPECT_THAT(serverThread, EventuallyTerminates());
}

TEST_F(TCPSocketServerTest, moreThanOneClientCanConnect) {
    // given
    tcp::iostream client1(server->listenEndpoint());
    ASSERT_THAT(client1, IsConnected());

    // when
    tcp::iostream client2(server->listenEndpoint());

    //then
    ASSERT_THAT(client2, IsConnected());
}

TEST_F(TCPSocketServerTest, receiveAndSendsSingleLineMassages) {
    {
        InSequence s;
        EXPECT_CALL(protocolHandler, handle("12")).WillRepeatedly(Return("A"));
        EXPECT_CALL(protocolHandler, handle("3")).WillRepeatedly(Return("B"));
        EXPECT_CALL(protocolHandler, handle("4")).WillRepeatedly(Return("C"));
    }

    // given
    tcp::iostream client(server->listenEndpoint());
    ASSERT_THAT(client, IsConnected());

    // when
    client << "1" << flush << "2" << endl << flush;
    client << "3" << endl << "4" << endl << flush;

    // then
    EXPECT_THAT(client, EventuallyReceives("A"));
    EXPECT_THAT(client, EventuallyReceives("B"));
    EXPECT_THAT(client, EventuallyReceives("C"));
}

class TCPSocketServerLocalhostTest : public SocketServerTest {
protected:
  boost::scoped_ptr<TCPSocketServer> server;

  virtual SocketServer* createListeningServer() {
      server.reset(new TCPSocketServer(&protocolHandler));
      server->listen(tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 0));
      return server.get();
  }

  virtual void destroyListeningServer() {
      server.reset();
  }
};

TEST_F(TCPSocketServerLocalhostTest, listensOnLocalhost) {
    // given
    tcp::iostream client(server->listenEndpoint());
    ASSERT_THAT(client, IsConnected());
    ASSERT_THAT(server->listenEndpoint().address().to_string(), std::string("127.0.0.1"));

    // when
    client.close();

    // then
    EXPECT_THAT(serverThread, EventuallyTerminates());
}

#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
class UnixSocketServerTest : public SocketServerTest {
protected:
    boost::scoped_ptr<UnixSocketServer> server;

    virtual SocketServer* createListeningServer() {
        fs::path socket = fs::temp_directory_path() / fs::unique_path();
        server.reset(new UnixSocketServer(&protocolHandler));
        server->listen(socket.string());
        return server.get();
    }

    virtual void destroyListeningServer() {
        server.reset();
    }
};

/*
 * Tests are flickering on OSX when testing without traffic flowing.
 *
 * This full lifecycle test is not optimal but it should be enough
 * given that the main difference between Unix and TCP is the socket
 * created at startup and removed on shutdown.
 */
TEST_F(UnixSocketServerTest, fullLifecycle) {
    stream_protocol::endpoint socketName = server->listenEndpoint();
    EXPECT_CALL(protocolHandler, handle("X")).WillRepeatedly(Return("Y"));

    // socket created at startup
    ASSERT_TRUE(fs::exists(socketName.path()));

    // traffic flows
    stream_protocol::iostream client(socketName);
    client << "X" << endl << flush;
    EXPECT_THAT(client, EventuallyReceives("Y"));

    // client disconnection terminates server
    client.close();
    EXPECT_THAT(serverThread, EventuallyTerminates());

    // socket removed by destructor
    TearDown();
    EXPECT_FALSE(fs::exists(socketName.path()));
}
#endif
<commit_msg>fix conflicting "using std" declaration with "using boost::thread"<commit_after>#include <cucumber-cpp/internal/connectors/wire/WireServer.hpp>

#include <gmock/gmock.h>

#include <boost/filesystem/operations.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/timer.hpp>

#include <stdlib.h>
#include <sstream>

using namespace cucumber::internal;
using namespace boost::posix_time;
using namespace boost::asio::ip;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
using namespace boost::asio::local;
#endif
using namespace testing;
using boost::bind;
using boost::thread;
namespace fs = boost::filesystem;

static const time_duration THREAD_TEST_TIMEOUT = milliseconds(4000);

MATCHER(IsConnected, std::string(negation ? "is not" : "is") + " connected") {
    return arg.good();
}

MATCHER(HasTerminated, "") {
    return !arg.joinable();
}

MATCHER(EventuallyTerminates, "") {
    return arg->timed_join(THREAD_TEST_TIMEOUT);
}

MATCHER_P(EventuallyReceives, value, "") {
    std::basic_iostream<char> *stream = const_cast<std::basic_iostream<char> *>(
            static_cast<const std::basic_iostream<char> *>(&arg));
    std::string output;
// FIXME It should not block
    (*stream) >> output;
//    boost::timer timer;
//    double timeout = THREAD_TEST_TIMEOUT.total_milliseconds() / 1000.0;
//    while (timer.elapsed() < timeout) {
//        if (stream->rdbuf()->available() > 0) { // it is zero even if it doesn't block!
//            (*stream) >> output;
//            break;
//        }
//        boost::this_thread::yield();
//    }
    return (output == value);
}

class MockProtocolHandler : public ProtocolHandler {
public:
    MOCK_CONST_METHOD1(handle, std::string(const std::string& request));
};

class SocketServerTest : public Test {

protected:
    StrictMock<MockProtocolHandler> protocolHandler;
    boost::scoped_ptr<thread> serverThread;

    virtual void SetUp() {
        SocketServer* server = createListeningServer();
        serverThread.reset(new thread(&SocketServer::acceptOnce, server));
    }

    virtual void TearDown() {
        if (serverThread) {
            serverThread->timed_join(THREAD_TEST_TIMEOUT);
            serverThread.reset();
        }
        destroyListeningServer();
    }

    virtual SocketServer* createListeningServer() = 0;
    virtual void destroyListeningServer() = 0;
};

class TCPSocketServerTest : public SocketServerTest {
protected:
    boost::scoped_ptr<TCPSocketServer> server;

    virtual SocketServer* createListeningServer() {
        server.reset(new TCPSocketServer(&protocolHandler));
        server->listen(0);
        return server.get();
    }

    virtual void destroyListeningServer() {
        server.reset();
    }
};

TEST_F(TCPSocketServerTest, exitsOnFirstConnectionClosed) {
    // given
    tcp::iostream client(server->listenEndpoint());
    ASSERT_THAT(client, IsConnected());
    ASSERT_THAT(server->listenEndpoint().address().to_string(), std::string("0.0.0.0"));

    // when
    client.close();

    // then
    EXPECT_THAT(serverThread, EventuallyTerminates());
}

TEST_F(TCPSocketServerTest, moreThanOneClientCanConnect) {
    // given
    tcp::iostream client1(server->listenEndpoint());
    ASSERT_THAT(client1, IsConnected());

    // when
    tcp::iostream client2(server->listenEndpoint());

    //then
    ASSERT_THAT(client2, IsConnected());
}

TEST_F(TCPSocketServerTest, receiveAndSendsSingleLineMassages) {
    {
        InSequence s;
        EXPECT_CALL(protocolHandler, handle("12")).WillRepeatedly(Return("A"));
        EXPECT_CALL(protocolHandler, handle("3")).WillRepeatedly(Return("B"));
        EXPECT_CALL(protocolHandler, handle("4")).WillRepeatedly(Return("C"));
    }

    // given
    tcp::iostream client(server->listenEndpoint());
    ASSERT_THAT(client, IsConnected());

    // when
    client << "1" << std::flush << "2" << std::endl << std::flush;
    client << "3" << std::endl << "4" << std::endl << std::flush;

    // then
    EXPECT_THAT(client, EventuallyReceives("A"));
    EXPECT_THAT(client, EventuallyReceives("B"));
    EXPECT_THAT(client, EventuallyReceives("C"));
}

class TCPSocketServerLocalhostTest : public SocketServerTest {
protected:
  boost::scoped_ptr<TCPSocketServer> server;

  virtual SocketServer* createListeningServer() {
      server.reset(new TCPSocketServer(&protocolHandler));
      server->listen(tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 0));
      return server.get();
  }

  virtual void destroyListeningServer() {
      server.reset();
  }
};

TEST_F(TCPSocketServerLocalhostTest, listensOnLocalhost) {
    // given
    tcp::iostream client(server->listenEndpoint());
    ASSERT_THAT(client, IsConnected());
    ASSERT_THAT(server->listenEndpoint().address().to_string(), std::string("127.0.0.1"));

    // when
    client.close();

    // then
    EXPECT_THAT(serverThread, EventuallyTerminates());
}

#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
class UnixSocketServerTest : public SocketServerTest {
protected:
    boost::scoped_ptr<UnixSocketServer> server;

    virtual SocketServer* createListeningServer() {
        fs::path socket = fs::temp_directory_path() / fs::unique_path();
        server.reset(new UnixSocketServer(&protocolHandler));
        server->listen(socket.string());
        return server.get();
    }

    virtual void destroyListeningServer() {
        server.reset();
    }
};

/*
 * Tests are flickering on OSX when testing without traffic flowing.
 *
 * This full lifecycle test is not optimal but it should be enough
 * given that the main difference between Unix and TCP is the socket
 * created at startup and removed on shutdown.
 */
TEST_F(UnixSocketServerTest, fullLifecycle) {
    stream_protocol::endpoint socketName = server->listenEndpoint();
    EXPECT_CALL(protocolHandler, handle("X")).WillRepeatedly(Return("Y"));

    // socket created at startup
    ASSERT_TRUE(fs::exists(socketName.path()));

    // traffic flows
    stream_protocol::iostream client(socketName);
    client << "X" << std::endl << std::flush;
    EXPECT_THAT(client, EventuallyReceives("Y"));

    // client disconnection terminates server
    client.close();
    EXPECT_THAT(serverThread, EventuallyTerminates());

    // socket removed by destructor
    TearDown();
    EXPECT_FALSE(fs::exists(socketName.path()));
}
#endif
<|endoftext|>


<commit_before>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "collectionselectjob.h"

#include <QDebug>

using namespace PIM;

class PIM::CollectionSelectJobPrivate
{
  public:
    QByteArray path;
    QByteArray tag;
    int unseen;
};

PIM::CollectionSelectJob::CollectionSelectJob( const QByteArray & path, QObject *parent ) :
    Job( parent ),
    d( new CollectionSelectJobPrivate )
{
  d->path = path;
  d->unseen = -1;
}

PIM::CollectionSelectJob::~ CollectionSelectJob( )
{
  delete d;
}

void PIM::CollectionSelectJob::doStart( )
{
  d->tag = newTag();
  writeData( d->tag + " SELECT \"" + d->path + "\"" );
}

void PIM::CollectionSelectJob::handleResponse( const QByteArray & tag, const QByteArray & data )
{
  if ( tag == d->tag ) {
    if ( !data.startsWith( "OK" ) )
      setError( Unknown );
    emit done( this );
    return;
  }
  if ( tag == "*" ) {
    if ( data.startsWith( "OK [UNSEEN" ) ) {
      int begin = data.indexOf( ' ', 4 );
      int end = data.indexOf( ']' );
      QByteArray number = data.mid( begin + 1, end - begin - 1 );
      d->unseen = number.toInt();
      qDebug() << "unseen items " << d->unseen << " in folder " << d->path;
      return;
    }
  }
  qDebug() << "Unhandled response in collection selection job: " << tag << data;
}

int PIM::CollectionSelectJob::unseen( ) const
{
  return d->unseen;
}

#include "collectionselectjob.moc"
<commit_msg>Allow leading slash in path for messagefetchjob.<commit_after>/*
    Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "collectionselectjob.h"

#include <QDebug>

using namespace PIM;

class PIM::CollectionSelectJobPrivate
{
  public:
    QByteArray path;
    QByteArray tag;
    int unseen;
};

PIM::CollectionSelectJob::CollectionSelectJob( const QByteArray & path, QObject *parent ) :
    Job( parent ),
    d( new CollectionSelectJobPrivate )
{
  d->path = path;
  d->unseen = -1;
}

PIM::CollectionSelectJob::~ CollectionSelectJob( )
{
  delete d;
}

void PIM::CollectionSelectJob::doStart( )
{
  QByteArray path = d->path;
  if ( path.startsWith( "/" ) ) path.remove( 0, 1 );

  d->tag = newTag();
  writeData( d->tag + " SELECT \"" + path + "\"" );
}

void PIM::CollectionSelectJob::handleResponse( const QByteArray & tag, const QByteArray & data )
{
  if ( tag == d->tag ) {
    if ( !data.startsWith( "OK" ) )
      setError( Unknown );
    emit done( this );
    return;
  }
  if ( tag == "*" ) {
    if ( data.startsWith( "OK [UNSEEN" ) ) {
      int begin = data.indexOf( ' ', 4 );
      int end = data.indexOf( ']' );
      QByteArray number = data.mid( begin + 1, end - begin - 1 );
      d->unseen = number.toInt();
      qDebug() << "unseen items " << d->unseen << " in folder " << d->path;
      return;
    }
  }
  qDebug() << "Unhandled response in collection selection job: " << tag << data;
}

int PIM::CollectionSelectJob::unseen( ) const
{
  return d->unseen;
}

#include "collectionselectjob.moc"
<|endoftext|>


<commit_before>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QtTest/QtTest>

#include "ui_archivestabwidget.h"
#include "ui_helpwidget.h"
#include "ui_jobstabwidget.h"
#include "ui_jobwidget.h"
#include "ui_mainwindow.h"
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include "helpwidget.h"
#include "jobstabwidget.h"
#include "mainwindow.h"

#include "archivewidget.h"
#include "persistentmodel/archive.h"

#include <ConsoleLog.h>
#include <TSettings.h>

class TestMainWindow : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void about_window_menubar();
    void quit_simple();
    void quit_tasks();
    void tab_navigation();
    void other_navigation();
};

void TestMainWindow::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    HANDLE_IGNORING_XDG_HOME;

    ConsoleLog::initializeConsoleLog();
    Translator::initializeTranslator();

    IF_NOT_VISUAL
    {
        // Use a custom message handler to filter out unwanted messages
        orig_message_handler = qInstallMessageHandler(offscreenMessageOutput);
    }

    // Initialization normally done in init_shared.cpp's init_no_app()
    qRegisterMetaType<QVector<File>>("QVector<File>");

    // Deal with PersistentStore
    PersistentStore::initializePersistentStore();
    PersistentStore &store = PersistentStore::instance();
    int              ok    = store.init();
    QVERIFY(ok);
}

void TestMainWindow::cleanupTestCase()
{
    PersistentStore::destroy();
    Translator::destroy();
    TSettings::destroy();
    ConsoleLog::destroy();

    // Wait for everything to finish
    QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
}

static QAction *get_menubar_about(QMenuBar *menubar)
{
    for(QAction *action : menubar->actions())
    {
        if(action->menu())
        {
            for(QAction *subaction : action->menu()->actions())
            {
                if(subaction->menuRole() == QAction::AboutRole)
                {
                    return subaction;
                }
            }
        }
    }
    return (nullptr);
}

void TestMainWindow::about_window_menubar()
{
    MainWindow *    mainwindow = new MainWindow();
    HelpWidget *    help       = &mainwindow->_helpWidget;
    Ui::HelpWidget *ui         = help->_ui;

    VISUAL_INIT(mainwindow);

    // Test the "About Tarsnap" menubar item, if applicable.
    if(mainwindow->_menuBar != nullptr)
    {
        // find "About Tarsnap" menu item
        QAction *menuAction = get_menubar_about(mainwindow->_menuBar);
        QVERIFY(menuAction != nullptr);
        VISUAL_WAIT;

        // Becomes visible using the menu bar action
        menuAction->trigger();
        QVERIFY(help->_aboutWindow.isVisible() == true);
        QVERIFY(ui->aboutButton->isChecked() == true);
        VISUAL_WAIT;

        // Stay visible even when clicking the menu bar action again
        menuAction->trigger();
        QVERIFY(help->_aboutWindow.isVisible() == true);
        QVERIFY(ui->aboutButton->isChecked() == true);
        VISUAL_WAIT;

        // Becomes invisible by clicking the Help->About button
        ui->aboutButton->click();
        QVERIFY(help->_aboutWindow.isVisible() == false);
        QVERIFY(ui->aboutButton->isChecked() == false);
        VISUAL_WAIT;
    }

    delete mainwindow;
}

void TestMainWindow::quit_simple()
{
    MainWindow *mainwindow = new MainWindow();
    QSignalSpy  sig_getTaskInfo(mainwindow, SIGNAL(getTaskInfo()));

    VISUAL_INIT(mainwindow);

    // If we try to close the window, we emit a getTaskInfo instead
    QCloseEvent *close_event = new QCloseEvent();
    mainwindow->closeEvent(close_event);
    QVERIFY(sig_getTaskInfo.count() == 1);
    sig_getTaskInfo.clear();

    // Fake getting a reply which says there's no tasks.
    mainwindow->closeWithTaskInfo(false, 0, 0);

    // After quitting, we don't respond to more events.
    QCloseEvent *close_event_another = new QCloseEvent();
    mainwindow->closeEvent(close_event_another);
    QVERIFY(sig_getTaskInfo.count() == 0);

    delete mainwindow;
    delete close_event;
    delete close_event_another;
}

void TestMainWindow::quit_tasks()
{
    MainWindow *mainwindow = new MainWindow();
    QSignalSpy  sig_getTaskInfo(mainwindow, SIGNAL(getTaskInfo()));

    VISUAL_INIT(mainwindow);

    // Fake getting a response to a closeEvent (not sent in this test) which
    // says that there's running tasks, but cancel the quitting.
    QMetaObject::invokeMethod(mainwindow, "closeWithTaskInfo",
                              Qt::QueuedConnection, Q_ARG(bool, true),
                              Q_ARG(int, 1), Q_ARG(int, 1));
    QMetaObject::invokeMethod(&mainwindow->_stopTasksDialog, "close",
                              Qt::QueuedConnection);
    VISUAL_WAIT;

    // After cancelling the quit, we still respond to events
    QCloseEvent *close_event = new QCloseEvent();
    mainwindow->closeEvent(close_event);
    QVERIFY(sig_getTaskInfo.count() == 1);
    sig_getTaskInfo.clear();
    VISUAL_WAIT;

    // Quit the app
    // FIXME: sending an "accept" is a hack because the task-specific choices
    // (e.g., stop tasks, run in background) are only added to the dialog box
    // after MainWindow receives the closeWithTaskInfo, so we can't
    // "queue up" sending a message to one of those objects.
    QMetaObject::invokeMethod(mainwindow, "closeWithTaskInfo",
                              Qt::QueuedConnection, Q_ARG(bool, true),
                              Q_ARG(int, 1), Q_ARG(int, 1));
    QMetaObject::invokeMethod(&mainwindow->_stopTasksDialog, "accept",
                              Qt::QueuedConnection);
    VISUAL_WAIT;

    // After quitting, we don't respond to more events
    QCloseEvent *close_event_another = new QCloseEvent();
    mainwindow->closeEvent(close_event_another);
    QVERIFY(sig_getTaskInfo.count() == 0);
    VISUAL_WAIT;

    delete mainwindow;
    delete close_event;
    delete close_event_another;
}

void TestMainWindow::tab_navigation()
{
    MainWindow *    mainwindow = new MainWindow();
    Ui::MainWindow *ui         = mainwindow->_ui;

    VISUAL_INIT(mainwindow);

    // Start in the Backup tab
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->backupTab);

    // Switch between tabs
    // Unfortunately we can't test the Ctrl+X keyboard shortcuts, because
    // QTest::keyClick() doesn't work with -platform offscreen.
    mainwindow->displayTab(ui->archivesTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->archivesTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->jobsTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->settingsTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->settingsTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->helpTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->helpTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->backupTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->backupTab);
    VISUAL_WAIT;

    delete mainwindow;
}

void TestMainWindow::other_navigation()
{
    MainWindow *       mainwindow    = new MainWindow();
    Ui::MainWindow *   ui            = mainwindow->_ui;
    JobsTabWidget *    jobsTabWidget = &mainwindow->_jobsTabWidget;
    Ui::JobsTabWidget *jui           = jobsTabWidget->_ui;

    BackupTabWidget *backupTabWidget = &mainwindow->_backupTabWidget;

    ArchiveWidget *archiveDetailsWidget =
        mainwindow->_archivesTabWidget._ui->archiveDetailsWidget;

    VISUAL_INIT(mainwindow);

#if defined(Q_OS_OSX)
    // HACK: Load directory that we'll want for creating a Job.  This is
    // slow to load on OSX (relative to the -platform offscreen test), so we
    // add an extra delay.
    jobsTabWidget->_ui->jobDetailsWidget->_ui->jobTreeWidget->_model
        .setRootPath(TEST_DIR);
    QTest::qWait(1000);
#endif

    QList<QUrl> testdir_urls({QUrl("file://" TEST_DIR)});

    // Switch to a different tab.
    mainwindow->displayTab(ui->helpTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->helpTab);
    VISUAL_WAIT;

    // Switch back to Backup tab
    QMetaObject::invokeMethod(mainwindow, "browseForBackupItems",
                              Qt::QueuedConnection);
    QMetaObject::invokeMethod(&backupTabWidget->_filePickerDialog, "close",
                              Qt::QueuedConnection);
    QTest::qWait(100);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->backupTab);
    VISUAL_WAIT;

    // Add a Job
    mainwindow->displayTab(ui->jobsTab);
    jobsTabWidget->createNewJob(testdir_urls, QString("test-job"));
    jobsTabWidget->addJobClicked();

    // Make sure that MainWindow has a job, then get a pointer to it.
    QVERIFY(jui->jobListWidget->count() == 1);
    QVERIFY(jui->jobListWidget->currentItem() != nullptr);
    JobPtr job =
        static_cast<JobListWidgetItem *>(jui->jobListWidget->currentItem())
            ->job();
    QVERIFY(job != nullptr);
    VISUAL_WAIT;

    // Add an Archive
    mainwindow->displayTab(ui->archivesTab);
    ArchivePtr archive(new Archive);
    archive->setName("Job_test-job_archive1");
    mainwindow->addArchive(archive);
    archive->setJobRef("test-job");
    VISUAL_WAIT;

    // Link them
    job->setArchives(QList<ArchivePtr>() << archive);

    // Create a second job, this time via morphBackupIntoJob
    mainwindow->displayTab(ui->backupTab);
    VISUAL_WAIT;

    backupTabWidget->morphBackupIntoJob(testdir_urls, "test-job2");
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    jobsTabWidget->addJobClicked();
    QVERIFY(jui->jobListWidget->count() == 2);
    VISUAL_WAIT;

    // Switch back and forth between the job and archive.
    mainwindow->displayInspectArchive(archive);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->archivesTab);
    VISUAL_WAIT;

    mainwindow->displayJobDetails(job);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    // Click on the Job name in the archive tab.
    mainwindow->displayInspectArchive(archive);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->archivesTab);
    VISUAL_WAIT;

    archiveDetailsWidget->jobClicked("test-job");
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    delete mainwindow;
}

QTEST_MAIN(TestMainWindow)
#include "test-mainwindow.moc"
<commit_msg>tests/mainwindow: increate cleanup wait-time<commit_after>#include "warnings-disable.h"

WARNINGS_DISABLE
#include <QtTest/QtTest>

#include "ui_archivestabwidget.h"
#include "ui_helpwidget.h"
#include "ui_jobstabwidget.h"
#include "ui_jobwidget.h"
#include "ui_mainwindow.h"
WARNINGS_ENABLE

#include "../qtest-platform.h"

#include "helpwidget.h"
#include "jobstabwidget.h"
#include "mainwindow.h"

#include "archivewidget.h"
#include "persistentmodel/archive.h"

#include <ConsoleLog.h>
#include <TSettings.h>

class TestMainWindow : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void about_window_menubar();
    void quit_simple();
    void quit_tasks();
    void tab_navigation();
    void other_navigation();
};

void TestMainWindow::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    HANDLE_IGNORING_XDG_HOME;

    ConsoleLog::initializeConsoleLog();
    Translator::initializeTranslator();

    IF_NOT_VISUAL
    {
        // Use a custom message handler to filter out unwanted messages
        orig_message_handler = qInstallMessageHandler(offscreenMessageOutput);
    }

    // Initialization normally done in init_shared.cpp's init_no_app()
    qRegisterMetaType<QVector<File>>("QVector<File>");

    // Deal with PersistentStore
    PersistentStore::initializePersistentStore();
    PersistentStore &store = PersistentStore::instance();
    int              ok    = store.init();
    QVERIFY(ok);
}

void TestMainWindow::cleanupTestCase()
{
    PersistentStore::destroy();
    Translator::destroy();
    TSettings::destroy();
    ConsoleLog::destroy();

    // Wait for everything to finish
    QCoreApplication::processEvents(QEventLoop::AllEvents, 5000);
}

static QAction *get_menubar_about(QMenuBar *menubar)
{
    for(QAction *action : menubar->actions())
    {
        if(action->menu())
        {
            for(QAction *subaction : action->menu()->actions())
            {
                if(subaction->menuRole() == QAction::AboutRole)
                {
                    return subaction;
                }
            }
        }
    }
    return (nullptr);
}

void TestMainWindow::about_window_menubar()
{
    MainWindow *    mainwindow = new MainWindow();
    HelpWidget *    help       = &mainwindow->_helpWidget;
    Ui::HelpWidget *ui         = help->_ui;

    VISUAL_INIT(mainwindow);

    // Test the "About Tarsnap" menubar item, if applicable.
    if(mainwindow->_menuBar != nullptr)
    {
        // find "About Tarsnap" menu item
        QAction *menuAction = get_menubar_about(mainwindow->_menuBar);
        QVERIFY(menuAction != nullptr);
        VISUAL_WAIT;

        // Becomes visible using the menu bar action
        menuAction->trigger();
        QVERIFY(help->_aboutWindow.isVisible() == true);
        QVERIFY(ui->aboutButton->isChecked() == true);
        VISUAL_WAIT;

        // Stay visible even when clicking the menu bar action again
        menuAction->trigger();
        QVERIFY(help->_aboutWindow.isVisible() == true);
        QVERIFY(ui->aboutButton->isChecked() == true);
        VISUAL_WAIT;

        // Becomes invisible by clicking the Help->About button
        ui->aboutButton->click();
        QVERIFY(help->_aboutWindow.isVisible() == false);
        QVERIFY(ui->aboutButton->isChecked() == false);
        VISUAL_WAIT;
    }

    delete mainwindow;
}

void TestMainWindow::quit_simple()
{
    MainWindow *mainwindow = new MainWindow();
    QSignalSpy  sig_getTaskInfo(mainwindow, SIGNAL(getTaskInfo()));

    VISUAL_INIT(mainwindow);

    // If we try to close the window, we emit a getTaskInfo instead
    QCloseEvent *close_event = new QCloseEvent();
    mainwindow->closeEvent(close_event);
    QVERIFY(sig_getTaskInfo.count() == 1);
    sig_getTaskInfo.clear();

    // Fake getting a reply which says there's no tasks.
    mainwindow->closeWithTaskInfo(false, 0, 0);

    // After quitting, we don't respond to more events.
    QCloseEvent *close_event_another = new QCloseEvent();
    mainwindow->closeEvent(close_event_another);
    QVERIFY(sig_getTaskInfo.count() == 0);

    delete mainwindow;
    delete close_event;
    delete close_event_another;
}

void TestMainWindow::quit_tasks()
{
    MainWindow *mainwindow = new MainWindow();
    QSignalSpy  sig_getTaskInfo(mainwindow, SIGNAL(getTaskInfo()));

    VISUAL_INIT(mainwindow);

    // Fake getting a response to a closeEvent (not sent in this test) which
    // says that there's running tasks, but cancel the quitting.
    QMetaObject::invokeMethod(mainwindow, "closeWithTaskInfo",
                              Qt::QueuedConnection, Q_ARG(bool, true),
                              Q_ARG(int, 1), Q_ARG(int, 1));
    QMetaObject::invokeMethod(&mainwindow->_stopTasksDialog, "close",
                              Qt::QueuedConnection);
    VISUAL_WAIT;

    // After cancelling the quit, we still respond to events
    QCloseEvent *close_event = new QCloseEvent();
    mainwindow->closeEvent(close_event);
    QVERIFY(sig_getTaskInfo.count() == 1);
    sig_getTaskInfo.clear();
    VISUAL_WAIT;

    // Quit the app
    // FIXME: sending an "accept" is a hack because the task-specific choices
    // (e.g., stop tasks, run in background) are only added to the dialog box
    // after MainWindow receives the closeWithTaskInfo, so we can't
    // "queue up" sending a message to one of those objects.
    QMetaObject::invokeMethod(mainwindow, "closeWithTaskInfo",
                              Qt::QueuedConnection, Q_ARG(bool, true),
                              Q_ARG(int, 1), Q_ARG(int, 1));
    QMetaObject::invokeMethod(&mainwindow->_stopTasksDialog, "accept",
                              Qt::QueuedConnection);
    VISUAL_WAIT;

    // After quitting, we don't respond to more events
    QCloseEvent *close_event_another = new QCloseEvent();
    mainwindow->closeEvent(close_event_another);
    QVERIFY(sig_getTaskInfo.count() == 0);
    VISUAL_WAIT;

    delete mainwindow;
    delete close_event;
    delete close_event_another;
}

void TestMainWindow::tab_navigation()
{
    MainWindow *    mainwindow = new MainWindow();
    Ui::MainWindow *ui         = mainwindow->_ui;

    VISUAL_INIT(mainwindow);

    // Start in the Backup tab
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->backupTab);

    // Switch between tabs
    // Unfortunately we can't test the Ctrl+X keyboard shortcuts, because
    // QTest::keyClick() doesn't work with -platform offscreen.
    mainwindow->displayTab(ui->archivesTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->archivesTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->jobsTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->settingsTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->settingsTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->helpTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->helpTab);
    VISUAL_WAIT;

    mainwindow->displayTab(ui->backupTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->backupTab);
    VISUAL_WAIT;

    delete mainwindow;
}

void TestMainWindow::other_navigation()
{
    MainWindow *       mainwindow    = new MainWindow();
    Ui::MainWindow *   ui            = mainwindow->_ui;
    JobsTabWidget *    jobsTabWidget = &mainwindow->_jobsTabWidget;
    Ui::JobsTabWidget *jui           = jobsTabWidget->_ui;

    BackupTabWidget *backupTabWidget = &mainwindow->_backupTabWidget;

    ArchiveWidget *archiveDetailsWidget =
        mainwindow->_archivesTabWidget._ui->archiveDetailsWidget;

    VISUAL_INIT(mainwindow);

#if defined(Q_OS_OSX)
    // HACK: Load directory that we'll want for creating a Job.  This is
    // slow to load on OSX (relative to the -platform offscreen test), so we
    // add an extra delay.
    jobsTabWidget->_ui->jobDetailsWidget->_ui->jobTreeWidget->_model
        .setRootPath(TEST_DIR);
    QTest::qWait(1000);
#endif

    QList<QUrl> testdir_urls({QUrl("file://" TEST_DIR)});

    // Switch to a different tab.
    mainwindow->displayTab(ui->helpTab);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->helpTab);
    VISUAL_WAIT;

    // Switch back to Backup tab
    QMetaObject::invokeMethod(mainwindow, "browseForBackupItems",
                              Qt::QueuedConnection);
    QMetaObject::invokeMethod(&backupTabWidget->_filePickerDialog, "close",
                              Qt::QueuedConnection);
    QTest::qWait(100);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->backupTab);
    VISUAL_WAIT;

    // Add a Job
    mainwindow->displayTab(ui->jobsTab);
    jobsTabWidget->createNewJob(testdir_urls, QString("test-job"));
    jobsTabWidget->addJobClicked();

    // Make sure that MainWindow has a job, then get a pointer to it.
    QVERIFY(jui->jobListWidget->count() == 1);
    QVERIFY(jui->jobListWidget->currentItem() != nullptr);
    JobPtr job =
        static_cast<JobListWidgetItem *>(jui->jobListWidget->currentItem())
            ->job();
    QVERIFY(job != nullptr);
    VISUAL_WAIT;

    // Add an Archive
    mainwindow->displayTab(ui->archivesTab);
    ArchivePtr archive(new Archive);
    archive->setName("Job_test-job_archive1");
    mainwindow->addArchive(archive);
    archive->setJobRef("test-job");
    VISUAL_WAIT;

    // Link them
    job->setArchives(QList<ArchivePtr>() << archive);

    // Create a second job, this time via morphBackupIntoJob
    mainwindow->displayTab(ui->backupTab);
    VISUAL_WAIT;

    backupTabWidget->morphBackupIntoJob(testdir_urls, "test-job2");
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    jobsTabWidget->addJobClicked();
    QVERIFY(jui->jobListWidget->count() == 2);
    VISUAL_WAIT;

    // Switch back and forth between the job and archive.
    mainwindow->displayInspectArchive(archive);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->archivesTab);
    VISUAL_WAIT;

    mainwindow->displayJobDetails(job);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    // Click on the Job name in the archive tab.
    mainwindow->displayInspectArchive(archive);
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->archivesTab);
    VISUAL_WAIT;

    archiveDetailsWidget->jobClicked("test-job");
    QVERIFY(ui->mainTabWidget->currentWidget() == ui->jobsTab);
    VISUAL_WAIT;

    delete mainwindow;
}

QTEST_MAIN(TestMainWindow)
#include "test-mainwindow.moc"
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	配列クラス（ヘッダー）
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include <vector>
#include <boost/unordered_map.hpp>

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	配列クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class dim {

		uint32_t				unit_size_;
		std::vector<uint8_t>	array_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		dim() : unit_size_(1) { }

		void set_unit_size(uint32_t us) { unit_size_ = us; }

		uint32_t get_unit_size() const { return unit_size_; }

		void create(uint32_t size) { array_.resize(size); }

		void* get_ptr(uint32_t idx) { return &array_[idx * unit_size_]; }

		uint32_t get(uint32_t idx) {
			if(unit_size_ == 2) {
				uint16_t* p = reinterpret_cast<uint16_t*>(&array_[0]);
				return p[idx];
			} else if(unit_size_ == 4) {
				uint32_t* p = reinterpret_cast<uint32_t*>(&array_[0]);
				return p[idx];
			} else {
				return array_[idx];
			}
		}

		void put(uint32_t idx, uint32_t data) {
			if(unit_size_ == 2) {
				uint16_t* p = reinterpret_cast<uint16_t*>(&array_[0]);
				p[idx] = data;
			} else if(unit_size_ == 4) {
				uint32_t* p = reinterpret_cast<uint32_t*>(&array_[0]);
				p[idx] = data;
			} else {
				array_[idx] = data;
			}
		}
	};
}
<commit_msg>dim クラス、全面改修<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	配列クラス（ヘッダー）
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <vector>

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	配列クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class dim {
		struct i_dim {
			virtual ~i_dim() { }
			virtual void resize(uint32_t s) = 0;
			virtual uint32_t size() const = 0;
			virtual uint32_t unit_size() const = 0;
			virtual uint32_t get(uint32_t idx) const = 0;
			virtual void put(uint32_t idx, uint32_t val) = 0;
			virtual void* ptr(uint32_t idx) = 0;
		};

		template <typename T>
		class dimx : public i_dim {
			std::vector<T>	array_;
		public:
			typedef T	value_type;
			virtual ~dimx() { }
			void resize(uint32_t s) { array_.resize(s); }
			uint32_t size() const { return array_.size(); }
			uint32_t unit_size() const { return sizeof(T); }
			uint32_t get(uint32_t idx) const { return array_[idx]; }
			void put(uint32_t idx, uint32_t val) { array_[idx] = val; }
			void* ptr(uint32_t idx) { return &array_[idx]; }
		};

		i_dim*		array_;
	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		dim() : array_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-----------------------------------------------------------------//
		~dim() { delete array_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	ユニットサイズを選択
			@param[in]	n	ユニットサイズ（１、２，４）
		*/
		//-----------------------------------------------------------------//
		void select(uint32_t n) {
			delete array_;
			array_ = 0;
			if(n == 1) {
				array_ = new dimx<uint8_t>;
			} else if(n == 2) {
				array_ = new dimx<uint16_t>;
			} else if(n == 4) {
				array_ = new dimx<uint32_t>;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	リサイズ
			@param[in]	s	サイズ
		*/
		//-----------------------------------------------------------------//
		void resize(uint32_t s) { array_->resize(s); }

		//-----------------------------------------------------------------//
		/*!
			@brief	要素サイズを返す
			@return 要素サイズ
		*/
		//-----------------------------------------------------------------//
		uint32_t size() const { return array_->size(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	要素が空か？
			@return 要素が空の場合「true」
		*/
		//-----------------------------------------------------------------//
		bool empty() const { return array_->size() == 0; }

		//-----------------------------------------------------------------//
		/*!
			@brief	ユニットサイズを返す
			@return ユニットサイズ
		*/
		//-----------------------------------------------------------------//
		uint32_t unit_size() const { return array_->unit_size(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	要素を取得
			@param[in]	idx	要素位置
			@return 要素
		*/
		//-----------------------------------------------------------------//
		uint32_t get(uint32_t idx) const { return array_->get(idx); }

		//-----------------------------------------------------------------//
		/*!
			@brief	要素を設定
			@param[in]	idx	要素位置
			@param[in]	val	値
		*/
		//-----------------------------------------------------------------//
		void put(uint32_t idx, uint32_t val) { array_->put(idx, val); }

		//-----------------------------------------------------------------//
		/*!
			@brief	要素をポインターを取得
			@param[in]	idx	要素位置
			@return 要素ポインター
		*/
		//-----------------------------------------------------------------//
		void* ptr(uint32_t idx = 0) { return array_->ptr(idx); }
	};
}
<|endoftext|>


<commit_before>///
/// EMCal Tender configuration macro
///
AliAnalysisTaskSE *AddTaskEMCALTender(
  Bool_t distBC             = kTRUE,    // distance to bad channel
  Bool_t recalibClus        = kTRUE,    // recalibrate cluster energy
  Bool_t recalcClusPos      = kTRUE,    // recalculate cluster position
  Bool_t nonLinearCorr      = kTRUE,    // apply non-linearity
  Bool_t remExoticCell      = kTRUE,    // remove exotic cells
  Bool_t remExoticClus      = kTRUE,    // remove exotic clusters
  Bool_t fidRegion          = kFALSE,   // apply fiducial cuts
  Bool_t calibEnergy        = kTRUE,    // calibrate energy
  Bool_t calibTime          = kTRUE,    // calibrate timing
  Bool_t remBC              = kTRUE,    // remove bad channels
  UInt_t nonLinFunct        = AliEMCALRecoUtils::kBeamTestCorrected,
  Bool_t reclusterize       = kTRUE,    // reclusterize
  Float_t seedthresh        = 0.100,    // seed threshold
  Float_t cellthresh        = 0.050,    // cell threshold
  UInt_t clusterizer        = AliEMCALRecParam::kClusterizerv2,
  Bool_t trackMatch         = kTRUE,    // track matching
  Bool_t updateCellOnly     = kFALSE,   // only change if you run your own clusterizer task
  Float_t timeMin           = 100e-9,   // minimum time of physical signal in a cell/digit (s)
  Float_t timeMax           = 900e-9,   // maximum time of physical signal in a cell/digit (s)
  Float_t timeCut           = 900e-9,   // maximum time difference between the digits inside EMC cluster (s)
  const char *pass          = 0,        // string defining pass (use none if figured out from path)
  Bool_t  remapMcAod        = kFALSE,   // switch on the remaping for the MC labels in AOD productions,
  TString cdbStorage        = "raw://", // "local://"
  Float_t diffEAggregation  = 0.        // difference E in aggregation of cells (i.e. stop aggregation if E_{new} > E_{prev} + diffEAggregation)
)
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskEMCALTender", "No analysis manager to connect to.");
    return NULL;
  }

  AliVEventHandler *evhand = mgr->GetInputEventHandler();

  // Create the task and configure it.
  //===========================================================================

  AliAnalysisTaskSE *ana = 0;
  AliAnalysisDataContainer *coutput1 = 0;

  #ifdef __CLING__
    // ROOT6 version of the Config macro. JIT cannot handle load and execute macro (compiler error) - need to call via gROOT->ProcessLine(...)
    std::stringstream configbuilder;
    configbuilder << ".x " << gSystem->Getenv("ALICE_PHYSICS") << "/PWG/EMCAL/macros/ConfigEmcalTenderSupply.C(";
    configbuilder << (distBC ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (recalibClus ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (recalcClusPos ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (nonLinearCorr ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (remExoticCell ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (remExoticClus ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (fidRegion ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (calibEnergy ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (calibTime ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (remBC ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << nonLinFunct << ", ";
    configbuilder << (reclusterize ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << seedthresh << ", ";
    configbuilder << cellthresh << ", ";
    configbuilder << clusterizer << ", ";
    configbuilder << trackMatch << ", ";
    configbuilder << (updateCellOnly ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << timeMin << ", ";
    configbuilder << timeMax << ", ";
    configbuilder << timeCut;
    configbuilder << ")";
    std::string configbuilderstring = configbuilder.str();
    std::cout << "Running config macro " << configbuilderstring << std::endl;
    AliEMCALTenderSupply *EMCALSupply = (AliEMCALTenderSupply *)gROOT->ProcessLine(configbuilderstring.c_str());
  #else
    // ROOT5 version, allows loading a macro
    gROOT->LoadMacro("$ALICE_PHYSICS/PWG/EMCAL/macros/ConfigEmcalTenderSupply.C");

    AliEMCALTenderSupply *EMCALSupply = ConfigEmcalTenderSupply(distBC, recalibClus, recalcClusPos, nonLinearCorr, remExoticCell, remExoticClus,
                      fidRegion, calibEnergy, calibTime, remBC, nonLinFunct, reclusterize, seedthresh,
                      cellthresh, clusterizer, trackMatch, updateCellOnly, timeMin, timeMax, timeCut, diffEAggregation);
  #endif

  if (pass)
    EMCALSupply->SetPass(pass);

  if (evhand->InheritsFrom("AliESDInputHandler")) {
    #ifdef __CLING__
        AliTender* alitender = dynamic_cast<AliTender *>(mgr->GetTopTasks()->FindObject("AliTender"));
    #else
        AliTender* alitender = (AliTender *)mgr->GetTopTasks()->FindObject("AliTender");
    #endif
    if (!alitender)
      alitender = new  AliTender("AliTender");

    alitender->AddSupply(EMCALSupply);
    alitender->SetDefaultCDBStorage(cdbStorage);

    ana = alitender;

    coutput1 = mgr->CreateContainer("emcal_tender_event",
                                      AliESDEvent::Class(),
                                      AliAnalysisManager::kExchangeContainer,
                                      "default_tender");
  } else if (evhand->InheritsFrom("AliAODInputHandler")) {
    #ifdef __CLING__
        AliEmcalTenderTask* emcaltender = dynamic_cast<AliEmcalTenderTask *>(mgr->GetTopTasks()->FindObject("AliEmcalTenderTask"));
    #else
        AliEmcalTenderTask* emcaltender = (AliEmcalTenderTask *)mgr->GetTopTasks()->FindObject("AliEmcalTenderTask");
    #endif

    if (!emcaltender)
        emcaltender = new  AliEmcalTenderTask("AliEmcalTenderTask");

    if (remapMcAod)
        EMCALSupply->SwitchOnRemapMCLabelForAODs();

    emcaltender->SetEMCALTenderSupply(EMCALSupply);

    ana = emcaltender;

    coutput1 = mgr->CreateContainer(  "emcal_tender_event",
                                      AliAODEvent::Class(),
                                      AliAnalysisManager::kExchangeContainer,
                                      "default_tender");
  } else {
    ::Error("AddTaskEMCALTender", "Input event handler not recognized, AOD/ESD expected. Returning...");
    return NULL;
  }

  mgr->AddTask(ana);

  // Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================

  mgr->ConnectInput(ana, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(ana, 1, coutput1 );

  ::Info("AddTaskEMCALTender", "Tender configured");

  return ana;
}
<commit_msg>open default parameters to avoid confusions; also update the recommended non linearity correction function<commit_after>///
/// EMCal Tender configuration macro
///
AliAnalysisTaskSE *AddTaskEMCALTender(
  Bool_t distBC             = kTRUE,    // distance to bad channel
  Bool_t recalibClus        = kTRUE,    // recalibrate cluster energy
  Bool_t recalcClusPos      = kTRUE,    // recalculate cluster position
  Bool_t nonLinearCorr      = kTRUE,    // apply non-linearity
  Bool_t remExoticCell      = kTRUE,    // remove exotic cells
  Bool_t remExoticClus      = kTRUE,    // remove exotic clusters
  Bool_t fidRegion          = kFALSE,   // apply fiducial cuts
  Bool_t calibEnergy        = kTRUE,    // calibrate energy
  Bool_t calibTime          = kTRUE,    // calibrate timing
  Bool_t remBC              = kTRUE,    // remove bad channels
  UInt_t nonLinFunct        = AliEMCALRecoUtils::kBeamTestCorrectedv3, // For MC use kPi0MCv3
  Bool_t reclusterize       = kTRUE,    // reclusterize
  Float_t seedthresh        = 0.100,    // seed threshold
  Float_t cellthresh        = 0.050,    // cell threshold
  UInt_t clusterizer        = AliEMCALRecParam::kClusterizerv2,
  Bool_t trackMatch         = kTRUE,    // track matching
  Bool_t updateCellOnly     = kFALSE,   // only change if you run your own clusterizer task
  Float_t timeMin           =-1000e-9,  // minimum time of physical signal in a cell/digit (s)
  Float_t timeMax           = 1000e-9,  // maximum time of physical signal in a cell/digit (s)
  Float_t timeCut           = 1000e-9,  // maximum time difference between the digits inside EMC cluster (s)
  const char *pass          = 0,        // string defining pass (use none if figured out from path)
  Bool_t  remapMcAod        = kFALSE,   // switch on the remaping for the MC labels in AOD productions,
  TString cdbStorage        = "raw://", // "local://"
  Float_t diffEAggregation  = 0.        // difference E in aggregation of cells (i.e. stop aggregation if E_{new} > E_{prev} + diffEAggregation)
)
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskEMCALTender", "No analysis manager to connect to.");
    return NULL;
  }

  AliVEventHandler *evhand = mgr->GetInputEventHandler();

  // Create the task and configure it.
  //===========================================================================

  AliAnalysisTaskSE *ana = 0;
  AliAnalysisDataContainer *coutput1 = 0;

  #ifdef __CLING__
    // ROOT6 version of the Config macro. JIT cannot handle load and execute macro (compiler error) - need to call via gROOT->ProcessLine(...)
    std::stringstream configbuilder;
    configbuilder << ".x " << gSystem->Getenv("ALICE_PHYSICS") << "/PWG/EMCAL/macros/ConfigEmcalTenderSupply.C(";
    configbuilder << (distBC ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (recalibClus ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (recalcClusPos ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (nonLinearCorr ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (remExoticCell ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (remExoticClus ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (fidRegion ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (calibEnergy ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (calibTime ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << (remBC ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << nonLinFunct << ", ";
    configbuilder << (reclusterize ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << seedthresh << ", ";
    configbuilder << cellthresh << ", ";
    configbuilder << clusterizer << ", ";
    configbuilder << trackMatch << ", ";
    configbuilder << (updateCellOnly ? "kTRUE" : "kFALSE") << ", ";
    configbuilder << timeMin << ", ";
    configbuilder << timeMax << ", ";
    configbuilder << timeCut;
    configbuilder << ")";
    std::string configbuilderstring = configbuilder.str();
    std::cout << "Running config macro " << configbuilderstring << std::endl;
    AliEMCALTenderSupply *EMCALSupply = (AliEMCALTenderSupply *)gROOT->ProcessLine(configbuilderstring.c_str());
  #else
    // ROOT5 version, allows loading a macro
    gROOT->LoadMacro("$ALICE_PHYSICS/PWG/EMCAL/macros/ConfigEmcalTenderSupply.C");

    AliEMCALTenderSupply *EMCALSupply = ConfigEmcalTenderSupply(distBC, recalibClus, recalcClusPos, nonLinearCorr, remExoticCell, remExoticClus,
                      fidRegion, calibEnergy, calibTime, remBC, nonLinFunct, reclusterize, seedthresh,
                      cellthresh, clusterizer, trackMatch, updateCellOnly, timeMin, timeMax, timeCut, diffEAggregation);
  #endif

  if (pass)
    EMCALSupply->SetPass(pass);

  if (evhand->InheritsFrom("AliESDInputHandler")) {
    #ifdef __CLING__
        AliTender* alitender = dynamic_cast<AliTender *>(mgr->GetTopTasks()->FindObject("AliTender"));
    #else
        AliTender* alitender = (AliTender *)mgr->GetTopTasks()->FindObject("AliTender");
    #endif
    if (!alitender)
      alitender = new  AliTender("AliTender");

    alitender->AddSupply(EMCALSupply);
    alitender->SetDefaultCDBStorage(cdbStorage);

    ana = alitender;

    coutput1 = mgr->CreateContainer("emcal_tender_event",
                                      AliESDEvent::Class(),
                                      AliAnalysisManager::kExchangeContainer,
                                      "default_tender");
  } else if (evhand->InheritsFrom("AliAODInputHandler")) {
    #ifdef __CLING__
        AliEmcalTenderTask* emcaltender = dynamic_cast<AliEmcalTenderTask *>(mgr->GetTopTasks()->FindObject("AliEmcalTenderTask"));
    #else
        AliEmcalTenderTask* emcaltender = (AliEmcalTenderTask *)mgr->GetTopTasks()->FindObject("AliEmcalTenderTask");
    #endif

    if (!emcaltender)
        emcaltender = new  AliEmcalTenderTask("AliEmcalTenderTask");

    if (remapMcAod)
        EMCALSupply->SwitchOnRemapMCLabelForAODs();

    emcaltender->SetEMCALTenderSupply(EMCALSupply);

    ana = emcaltender;

    coutput1 = mgr->CreateContainer(  "emcal_tender_event",
                                      AliAODEvent::Class(),
                                      AliAnalysisManager::kExchangeContainer,
                                      "default_tender");
  } else {
    ::Error("AddTaskEMCALTender", "Input event handler not recognized, AOD/ESD expected. Returning...");
    return NULL;
  }

  mgr->AddTask(ana);

  // Create ONLY the output containers for the data produced by the task.
  // Get and connect other common input/output containers via the manager as below
  //==============================================================================

  mgr->ConnectInput(ana, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(ana, 1, coutput1 );

  ::Info("AddTaskEMCALTender", "Tender configured");

  return ana;
}
<|endoftext|>