]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
Implementing base class methods for easy component configuration:
authorrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 7 Jul 2009 17:05:57 +0000 (17:05 +0000)
committerrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 7 Jul 2009 17:05:57 +0000 (17:05 +0000)
- AliHLTComponent::ConfigureFromArgumentString implements the common
  parsing and loop over all arguments. Fits both for single strings
  containing several blank separated arguments as well as an array
  of arguments.
- AliHLTComponent::ConfigureFromCDBTObjString loads the specified
  OCDB object and calls the argument parsing for all objects of
  type TObjString
- AliHLTComponent::LoadAndExtractOCDBObject helper function to
  access OCDB objects from components
- AliHLTComponent::ScanConfigurationArgument is defined and needs to
  be implemented in order to support the argument scan

Updated component base class documentation

Added test to AliHLTComponent unit test

HLT/BASE/AliHLTComponent.cxx
HLT/BASE/AliHLTComponent.h
HLT/BASE/test/Makefile.am
HLT/BASE/test/testAliHLTBlockDataCollection.C
HLT/BASE/test/testAliHLTComponent.C [moved from HLT/BASE/test/testAliHLTComponent_CTPTrigger.C with 58% similarity]

index 5c14f07556019b332b8c193a0b4e0d2b44381b19..e3fc920a06b55195af97f6e2716ec4dd1a56ad62 100644 (file)
@@ -396,6 +396,99 @@ int AliHLTComponent::SetComponentDescription(const char* desc)
   return iResult;
 }
 
+int AliHLTComponent::ConfigureFromArgumentString(int argc, const char** argv)
+{
+  // see header file for function documentation
+  int iResult=0;
+  vector<const char*> array;
+  TObjArray choppedArguments;
+  TString argument="";
+  int i=0;
+  for (i=0; i<argc && iResult>=0; i++) {
+    argument=argv[i];
+    if (argument.IsNull()) continue;
+    TObjArray* pTokens=argument.Tokenize(" ");
+    if (pTokens) {
+      if (pTokens->GetEntriesFast()<2) {
+       array.push_back(argv[i]);
+      } else {
+       for (int n=0; n<pTokens->GetEntriesFast(); n++) {
+         choppedArguments.AddLast(pTokens->At(n));
+         array.push_back(((TObjString*)pTokens->At(n))->GetString().Data());
+       }
+       pTokens->SetOwner(kFALSE);
+      }
+      delete pTokens;
+    }
+  }
+
+  for (i=0; (unsigned)i<array.size() && iResult>=0;) {
+    int result=ScanConfigurationArgument(array.size()-i, &array[i]);
+    if (result==0) {
+      HLTWarning("unknown component argument %s", array[i]);
+      i++;
+    } else if (result>0) {
+      i+=result;
+    } else {
+      iResult=result;
+      if (iResult==-EINVAL) {
+       HLTError("unknown argument %s", array[i]);
+      } else if (iResult==-EPROTO) {
+       HLTError("missing/wrong parameter for argument %s (%s)", array[i], array.size()>(unsigned)i+1)?array[i+1]:"missing";
+      } else {
+       HLTError("scan of argument %s failed (%d)", array[i], iResult);
+      }
+    }
+  }
+
+  return iResult;
+}
+
+int AliHLTComponent::ConfigureFromCDBTObjString(const char* entries)
+{
+  // see header file for function documentation
+  int iResult=0;
+  TString arguments;
+  TString confEntries=entries;
+  TObjArray* pTokens=confEntries.Tokenize(" ");
+  if (pTokens) {
+    for (int n=0; n<pTokens->GetEntriesFast(); n++) {
+      const char* path=((TObjString*)pTokens->At(n))->GetString().Data();
+      const char* chainId=GetChainId();
+      HLTInfo("configure from entry %s, chain id %s", path, (chainId!=NULL && chainId[0]!=0)?chainId:"<none>");
+      TObject* pOCDBObject = LoadAndExtractOCDBObject(path);
+      if (pOCDBObject) {
+       TObjString* pString=dynamic_cast<TObjString*>(pOCDBObject);
+       if (pString) {
+         HLTInfo("received configuration object string: \'%s\'", pString->GetString().Data());
+         arguments+=pString->GetString().Data();
+         arguments+=" ";
+       } else {
+         HLTError("configuration object \"%s\" has wrong type, required TObjString", path);
+         iResult=-EINVAL;
+       }
+      } else {
+       HLTError("can not fetch object \"%s\" from OCDB", path);
+       iResult=-ENOENT;
+      }
+    }
+    delete pTokens;
+  }
+  if (iResult>=0 && !arguments.IsNull())  {
+    const char* array=arguments.Data();
+    iResult=ConfigureFromArgumentString(1, &array);
+  }
+  return iResult;
+}
+
+TObject* AliHLTComponent::LoadAndExtractOCDBObject(const char* path, int version, int subVersion)
+{
+  // see header file for function documentation
+  AliCDBEntry* pEntry=AliHLTMisc::Instance().LoadOCDBEntry(path, GetRunNo(), version, subVersion);
+  if (!pEntry) return NULL;
+  return AliHLTMisc::Instance().ExtractObject(pEntry);
+}
+
 int AliHLTComponent::DoInit( int /*argc*/, const char** /*argv*/)
 {
   // default implementation, childs can overload
@@ -424,6 +517,14 @@ int AliHLTComponent::ReadPreprocessorValues(const char* /*modules*/)
   return 0;
 }
 
+int AliHLTComponent::ScanConfigurationArgument(int /*argc*/, const char** /*argv*/)
+{
+  // default implementation, childs can overload
+  HLTLogKeyword("dummy");
+  HLTWarning("The function needs to be implemented by the component");
+  return 0;
+}
+
 int AliHLTComponent::StartOfRun()
 {
   // default implementation, childs can overload
index 5df88fa9aa50c3665ccb82d645fd4c980e864202..4cb391d26e0a86ba876ff1a0828a4fcfa904db6a 100644 (file)
@@ -121,6 +121,9 @@ typedef vector<AliHLTMemoryFile*>         AliHLTMemoryFilePList;
  *   If the component has multiple output data types @ref GetOutputDataType
  *   should return @ref kAliHLTMultipleDataType. The framework will invoke
  *   @ref GetOutputDataTypes, a list can be filled.
+ * - @ref Reconfigure
+ *   This function is invoked by the framework on a special event which
+ *   triggers the reconfiguration of the component.
  *
  * @subsection alihltcomponent-processing-mehods Data processing
  * 
@@ -180,7 +183,7 @@ typedef vector<AliHLTMemoryFile*>         AliHLTMemoryFilePList;
  * framework will allocate a buffer of appropriate size and call the processing
  * again.
  *
- * @subsection alihltcomponent-error-codes Data processing
+ * @subsection alihltcomponent-error-codes Return values/Error codes
  * For return codes, the following scheme applies:
  * - The data processing methods have to indicate error conditions by a negative
  * error/return code. Preferably the system error codes are used like
@@ -188,6 +191,8 @@ typedef vector<AliHLTMemoryFile*>         AliHLTMemoryFilePList;
  * <pre>
  * \#include \<cerrno\>
  * </pre>
+ * This schema aplies to all interface functions of the component base class.
+ * For data processing it is as follows:
  * - If no suitable input block could be found (e.g. no clusters for the TPC cluster
  * finder) set size to 0, block list is empty, return 0
  * - If no ususable or significant signal could be found in the input blocks
@@ -252,15 +257,91 @@ typedef vector<AliHLTMemoryFile*>         AliHLTMemoryFilePList;
  * - @ref AliHLTDataSource::GetEvent
  * - @ref AliHLTDataSink::DumpEvent
  * 
- * 
+ * The base class passes all relevant parameters for data access directly on to the
+ * component. Input blocks can be accessed by means of the array <tt> blocks </tt>.
+ * Output data are written directly to shared memory provided by the pointer
+ * <tt> outputPtr </tt> and output block descriptors are inserted directly to the
+ * list <tt> outputBlocks </tt>.
+ *
+ * \b NOTE: The high-level input data access methods can be used also from the low
+ * level interface. Also the PushBack functions can be used BUT ONLY if no data is
+ * written to the output buffer and no data block descriptors are inserted into the
+ * output block list.
+ *
+ * @section alihltcomponent-initialization Component initialization and configuration
+ * The component interface provides two optional methods for component initialization
+ * and configuration. The @ref DoInit function is called once before the processing.
+ * During the event processing, a special event can trigger a reconfiguration and the
+ * @ref Reconfigure method is called. There are three possible options of initialization
+ * and configuration:
+ * - default values: set directly in the source code
+ * - OCDB objects: all necessary information must be loaded from OCDB objects. The
+ *   Offline Conditions Data Base stores objects specifically valid for individual runs
+ *   or run ranges.
+ * - Component arguments: can be specified for every component in the chain
+ *   configuration. The arguments can be used to override specific parameters of the
+ *   component.
+ *
+ * As a general rule, the three options should be processed in that sequence, i.e
+ * default parameters might be overridden by OCDB configuration, and the latter one
+ * by component arguments.
+ *
+ * @subsection alihltcomponent-initialization-arguments Component arguments
+ * In normal operation, components are supposed to run without any additional argument,
+ * however such arguments can be useful for testing and debugging. The idea follows
+ * the format of command line arguments. A keyword is indicated by a dash and an
+ * optional argument might follow, e.g.:
+ * <pre>
+ * -argument1 0.5 -argument2
+ * </pre>
+ * In this case argument1 requires an additional parameter whereas argument2 does not.
+ * The arguments will be provided as an array of separated arguments.
+ *
+ * Component arguments can be classified into initialization arguments and configuration
+ * arguments. The latter are applicable for both the @ref DoInit and @ref Reconfigure
+ * method whereas initialization arguments are not applicable after DoInit.
+ *
+ * @subsection alihltcomponent-initialization-ocdb OCDB objects
+ * OCDB objects are ROOT <tt>TObjects</tt> and can be of any type. This is in particular
+ * useful for complex parameter sets. However in most cases, a simple approach of human
+ * readable command line arguments is appropriate. Such a string can be simply stored
+ * in a TObjString (take note that the TString does not derive from TObject). The
+ * same arguments as for the command line can be used. Take note that in the TObjString
+ * all arguments are separated by blanks, instead of being in an array of separate
+ * strings.
+ *
+ * The base class provides two functions regarding OCDB objects: 
+ * - LoadAndExtractOCDBObject() loads the OCDB entry for the specified path and extracts
+ *                              the TObject from it.
+ * - ConfigureFromCDBTObjString() can load a number of OCDB objects and calls the
+ *                              argument parsing ConfigureFromArgumentString
+ *
+ *
+ * @subsection alihltcomponent-initialization-sequence Initialization sequence
+ * Using the approach of <tt>TObjString</tt>-type configuration objects allows to treat
+ * configuration from both @ref DoInit and @ref Reconfigure in the same way.
+ *
+ * The base class provides the function ConfigureFromArgumentString() which loops over
+ * all arguments and calls the child's method ScanConfigurationArgument(). Here the
+ * actual treatment of the argument and its parameters needs to be implemented.
+ * ConfigureFromArgumentString() can treat both arrays of arguments and arguments in
+ * one single string separated by blanks. The two options can be mixed.
+ *
+ * A second bas class function ConfigureFromCDBTObjString() allows to configure
+ * directly from a number of OCDB objects. This requires the entries to be of
+ * type TObjString and the child implementation of ScanConfigurationArgument().
+ *
  * @section alihltcomponent-handling Component handling 
  * The handling of HLT analysis components is carried out by the AliHLTComponentHandler.
  * Component are registered automatically at load-time of the component shared library
  * under the following suppositions:
  * - the component library has to be loaded from the AliHLTComponentHandler using the
  *   @ref AliHLTComponentHandler::LoadLibrary method.
+ * - the library defines an AliHLTModuleAgent which registers all components.
+ *   See AliHLTModuleAgent::RegisterComponents                               <br>
+ *     or                                                                    <br>
  * - the component implementation defines one global object (which is generated
- *   when the library is loaded)
+ *   when the library is loaded)                                             <br>
  *
  * @subsection alihltcomponent-design-rules General design considerations
  * The analysis code should be implemented in one or more destict class(es). A 
@@ -278,6 +359,8 @@ typedef vector<AliHLTMemoryFile*>         AliHLTMemoryFilePList;
  *
  * Further rules:
  * - avoid big static arrays in the component, allocate the memory at runtime
+ * - allocate all kind of complex data members (like classes, ROOT TObjects of
+ *   any kind) dynamically in DoInit and clean up in DoDeinit
  *
  * @section alihlt_component_arguments Default arguments
  * The component base class provides some default arguments:
@@ -735,6 +818,11 @@ class AliHLTComponent : public AliHLTLogging {
    * leading absolute path of the CDB location. The framework might also
    * provide the id of the component in the analysis chain.
    *
+   * The actual sequence of configuration depends on the component. As a
+   * general rule, the component should load the specific OCDB object if
+   * provided as parameter, and load the default objects if the parameter
+   * is NULL. However, other schemes are possible. See @ref 
+   *
    * \b Note: The CDB will be initialized by the framework, either already set
    * from AliRoot or from the wrapper interface during initialization.
    *
@@ -760,6 +848,23 @@ class AliHLTComponent : public AliHLTLogging {
    */
   virtual int ReadPreprocessorValues(const char* modules);
 
+  /**
+   * Child implementation to scan a number of configuration arguments.
+   * The method is invoked by the framework in conjunction with the
+   * common framework functions ConfigureFromArgumentString and
+   * ConfigureFromCDBTObjString.
+   * Function needs to scan the argument and optional additional
+   * parameters and returns the number of elements in the array which
+   * have been treated.
+   * @param argc
+   * @param argv
+   * @return number of arguments which have been scanned or neg error
+   *         code if failed                                              <br>
+   *         \li -EINVAL      unknown argument
+   *         \li -EPROTO      protocol error, e.g. missing parameter
+   */
+  virtual int ScanConfigurationArgument(int argc, const char** argv);
+
   /**
    * Custom handler for the SOR event.
    * Is invoked from the base class if an SOR event is in the block list.
@@ -863,6 +968,34 @@ class AliHLTComponent : public AliHLTLogging {
    */
   void DataType2Text(const AliHLTComponentDataType& type, char output[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2]) const;
 
+  /**
+   * Loop through a list of component arguments.
+   * The list can be either an array of separated strings or one single
+   * string containing blank separated arguments, or both mixed.
+   * ScanConfigurationArgument() is called to allow the component to treat
+   * the individual arguments.
+   * @return neg. error code if failed
+   */
+  int ConfigureFromArgumentString(int argc, const char** argv);
+
+  /**
+   * Read configuration objects from OCDB and configure from
+   * the content of TObjString entries.
+   * @param entries   blank separated list of OCDB paths
+   * @return neg. error code if failed
+   */
+  int ConfigureFromCDBTObjString(const char* entries);
+
+  /**
+   * Load specified entry from the OCDB and extract the object.
+   * The entry is explicitely unloaded from the cache before it is loaded.
+   * @param path      path of the entry under to root of the OCDB
+   * @param version   version of the entry
+   * @param subVersion  subversion of the entry
+   */
+  TObject* LoadAndExtractOCDBObject(const char* path, int version = -1, int subVersion = -1);
+
+
   /**
    * Get event number.
    * @return value of the internal event counter
index 8a51fe0ea4a353a8af4e901f9dd97511fc7d2da4..8aa3f3ca4ad7e7dbaa675da0a6f15407567c8090 100644 (file)
@@ -6,10 +6,11 @@ AM_CPPFLAGS                   = -I$(top_srcdir)/BASE
 EXTRA_DIST     = 
 
 check_PROGRAMS = testAliHLTBlockDataCollection \
+                 testAliHLTComponent \
                  dtOperators \
                  testDefaultDataTypes
 
-#                testAliHLT_C_Component_WrapperInterface
+#                testAliHLT_C_Component_WrapperInterface
 
 testAliHLTBlockDataCollection_SOURCES = testAliHLTBlockDataCollection.cxx
 testAliHLTBlockDataCollection_LDADD = $(top_builddir)/BASE/libHLTbase.la
@@ -23,4 +24,7 @@ dtOperators_LDADD = $(top_builddir)/BASE/libHLTbase.la
 testDefaultDataTypes_SOURCES = testDefaultDataTypes.C
 testDefaultDataTypes_LDADD = $(top_builddir)/BASE/libHLTbase.la
 
+testAliHLTComponent_SOURCES = testAliHLTComponent.C
+testAliHLTComponent_LDADD = $(top_builddir)/BASE/libHLTbase.la
+
 TESTS          = $(check_PROGRAMS)
index 896525a458a8045fcec01ea07a4a966c12d4df55..ca5efae1e810b6d2474223abde57689b2655c201 100644 (file)
@@ -77,7 +77,7 @@ int InitCollection(AliHLTBlockDataCollection& collection, const char* init)
   int iStart=0;
   for (;arguments[i]!=0; i++) {
     if (arguments[i]=='\'') {
-      if (bQuote=!bQuote) {
+      if (bQuote=(!bQuote)) {
        // opening quote, set start
       } else {
        // closing quote, add argument
similarity index 58%
rename from HLT/BASE/test/testAliHLTComponent_CTPTrigger.C
rename to HLT/BASE/test/testAliHLTComponent.C
index 02fbe90c7bccee270a056f5dcb122fc01e24904f..c285af6dd8371f8485b8409c7feebee4e3304004 100644 (file)
@@ -19,7 +19,7 @@
 /** @file   testAliHLTComponent_CTPTrigger.C
     @author Matthias Richter
     @date   
-    @brief  Test program for default data types
+    @brief  Test program for the AliHLTComponent base class
  */
 
 #ifndef __CINT__
 #include "TRandom.h"
 #include "AliHLTDataTypes.h"
 #include "AliHLTProcessor.h"
+#include "algorithm"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TString.h"
 #endif
 
+using namespace std;
+
 class AliHLTTestComponent : public AliHLTProcessor
 {
 public:
-  AliHLTTestComponent() {}
+  AliHLTTestComponent() :
+    fArguments(),
+    fCurrentArgument(fArguments.begin())
+  {}
+
   ~AliHLTTestComponent() {}
 
   const char* GetComponentID() {return "TestComponent";};
@@ -41,12 +51,194 @@ public:
   void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier) {constBase=0; inputMultiplier=0;}
   AliHLTComponent* Spawn() {return new AliHLTTestComponent;}
 
-  int InitTest(const char* param) {
-    return ScanECSParam(param);
+  class AliHLTConfigurationArgument {
+  public:
+    AliHLTConfigurationArgument(const char* argument) :
+      fElements(NULL)
+    {
+      TString work=argument;
+      fElements=work.Tokenize(" ");
+    }
+
+    AliHLTConfigurationArgument(const AliHLTConfigurationArgument& src) :
+      fElements(NULL)
+    {
+      if (src.fElements) {
+       fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
+      }
+    }
+
+    ~AliHLTConfigurationArgument() {
+      if (fElements) delete fElements;
+    }
+
+    AliHLTConfigurationArgument& operator=(const AliHLTConfigurationArgument& src) {
+      delete fElements;
+      if (src.fElements) {
+       fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
+      }
+      return *this;
+    }
+
+    const char* Argument() {
+      if (!fElements) return NULL;
+      return ((TObjString*)fElements->At(0))->GetString().Data();
+    }
+
+    int NofParameters() {
+      if (!fElements) return 0;
+      return fElements->GetEntriesFast()-1;
+    }
+
+    const char* Parameter(int i) {
+      if (!fElements ||
+         fElements->GetEntriesFast()<=i+1) return NULL;
+      return ((TObjString*)fElements->At(i+1))->GetString().Data();      
+    }
+
+    bool operator==(const char* string) {
+      if (!fElements) return 0;
+      return (((TObjString*)fElements->At(0))->GetString().CompareTo(string))==0;
+    }
+
+    bool operator!=(const char* string) {
+      return !operator==(string);
+    }
+
+    void Print() {
+      if (!fElements) {
+       cout << "#############  empty ############" << endl;
+       return;
+      }
+      cout << "   Print: " << Argument() << " with " << NofParameters() << " parameter(s)";
+      for (int n=0; n<NofParameters(); n++) cout << " " << Parameter(n);
+      cout << endl;
+    }
+
+  private:
+    TObjArray* fElements;
+  };
+
+  int ScanConfigurationArgument(int argc, const char** argv) {
+    if (fCurrentArgument==fArguments.end()) return 0;
+    int count=0;
+
+    // check whether it is an argument at all
+    if (*(argv[count])!='-') {
+      cerr << "not a recognized argument: " << argv[count] << endl;
+      return -EINVAL;
+    }
+
+    // check whether the argument matches
+    //fCurrentArgument->Print();
+    if (*fCurrentArgument!=argv[count]) {
+      cerr << "argument sequence does not match: got " << argv[count] << "  expected " << fCurrentArgument->Argument() << endl;
+      return -EINVAL;
+    }
+
+    count++;
+    // read parameters
+    if (fCurrentArgument->NofParameters()>0) {
+      if (argc<=count) {
+       cerr << "missing parameter" << endl;
+       return -EPROTO;
+      }
+
+      // implement more checks here
+      count+=fCurrentArgument->NofParameters();
+    }
+    fCurrentArgument++;
+    return count;
+  }
+
+  int FillArgumentVector(const char** arguments, vector<AliHLTConfigurationArgument>& list) {
+    list.clear();
+    for (const char** iter=arguments; *iter!=NULL; iter++) {
+      list.push_back(AliHLTConfigurationArgument(*iter));
+    }
+    return list.size();
+  }
+
+  int FillArgv(vector<AliHLTConfigurationArgument>& list, vector<const char*>& argv) {
+    argv.clear();
+    for (vector<AliHLTConfigurationArgument>::iterator argument=list.begin();
+        argument!=list.end(); argument++) {
+      argv.push_back(argument->Argument());
+      for (int n=0; n<argument->NofParameters(); n++) {
+       argv.push_back(argument->Parameter(n));
+      }
+    }
+    return argv.size();
+  }
+
+  void PrintArgv(int argc, const char** argv) {
+    for (int n=0; n<argc; n++) {
+      cout << "   " << n << " : " << argv[n] << endl;
+    }
+  }
+
+  int CheckSequence(const char* sequence[], int mode=0) {
+    int iResult=0;
+    if ((iResult=FillArgumentVector(sequence, fArguments))<0) {
+      cerr << "failed to fill argument vector" << endl;
+      return iResult;
+    }
+    vector<const char*> argv;
+    if (mode==0) {
+      if ((iResult=FillArgv(fArguments, argv))<0) {
+       cerr << "failed to fill argument array" << endl;
+       return iResult;
+      }
+    } else {
+      for (const char** element=sequence; *element!=NULL; element++)
+       argv.push_back(*element);
+    }
+    fCurrentArgument=fArguments.begin();
+    //PrintArgv(argv.size(), &argv[0]);
+    if ((iResult=ConfigureFromArgumentString(argv.size(), &argv[0]))<0) {
+      cerr << "ConfigureFromArgumentString failed " << endl;
+      return iResult;
+    }
+
+    return iResult;
+  }
+
+  int CheckConfigure() {
+    int iResult=0;
+    const char* sequence1[]={"-sequence1","-argument2 5", NULL};
+    if ((iResult=CheckSequence(sequence1))<0) {
+      cerr << "failed checking sequence " << sequence1[0] << endl;
+      return iResult;
+    }
+
+    const char* sequence2[]={"-sequence2","-argument2 5 8", "-argument3 test", NULL};
+    if ((iResult=CheckSequence(sequence2))<0) {
+      cerr << "failed checking sequence in mode 0: " << sequence2[0] << endl;
+      return iResult;
+    }
+
+    if ((iResult=CheckSequence(sequence2, 1))<0) {
+      cerr << "failed checking sequence in mode 1: " << sequence2[0] << endl;
+      return iResult;
+    }
+
+    const char* sequence3[]={"-solenoidBz 5", NULL};
+    if ((iResult=CheckSequence(sequence3))<0) {
+      cerr << "failed checking sequence " << sequence3[0] << endl;
+      return iResult;
+    }
+    return iResult;
+  }
+
+  int InitCTPTest(const char* param) {
+    // this quick test needs to be the functions of the base class to be
+    // defined 'protected'
+    //return ScanECSParam(param);
     //return InitCTPTriggerClasses(param);
+    return -ENOSYS;
   }
 
-  bool Check(const char* expression, AliHLTComponentTriggerData* data) {
+  bool CheckCTP(const char* expression, AliHLTComponentTriggerData* data) {
     return EvaluateCTPTriggerClass(expression, *data);
   }
 
@@ -80,6 +272,9 @@ protected:
               AliHLTComponentTriggerData& /*trigData*/) {
     return 0;
   }
+private:
+  vector<AliHLTConfigurationArgument> fArguments;
+  vector<AliHLTConfigurationArgument>::iterator fCurrentArgument;
 };
 
 class AliHLTTriggerDataAccess
@@ -172,6 +367,11 @@ private:
   Byte_t*                     fMine;
 };
 
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+//
+// setup of the CTP test
+
 /**
  * Get a random number in the given range.
  */
@@ -223,8 +423,15 @@ int GenerateTriggerClasses(int size, vector<AliHLTTestComponent::AliHLTCTPTrigge
   return classes.size();
 }
 
-int testAliHLTComponent_CTPTrigger()
+/**
+ * Test the CTP trigger tools
+ * The base class is initialized with an ECS string of randomly defined trigger
+ * classes consisting of random bits and names. Than a couple of expressions is
+ * test for various random bit patterns.
+ */
+int testCTPTrigger()
 {
+  cout << "checking CTP functionality of the base class" << endl;
   int iResult=0;
   vector<AliHLTTestComponent::AliHLTCTPTriggerClass> triggerClasses;
   if (GenerateTriggerClasses(GetRandom(5,gkNCTPTriggerClasses), triggerClasses)<=0) {
@@ -248,7 +455,10 @@ int testAliHLTComponent_CTPTrigger()
 
   AliHLTTestComponent component;
   component.SetGlobalLoggingLevel(kHLTLogDefault);
-  if ((iResult=component.InitTest(parameter.Data()))<0) return iResult;
+  if ((iResult=component.InitCTPTest(parameter.Data()))<0) {
+    cerr << "InitCTPTest failed :" << iResult << endl;
+    return iResult;
+  }
 
   AliHLTTriggerDataAccess trigData;
   for (int cycle=0; cycle<500 && iResult>=0; cycle++) {
@@ -278,7 +488,7 @@ int testAliHLTComponent_CTPTrigger()
        // is
        result=element->Trigger();
        expression=element->ClassName();
-       trigger=component.Check(expression.Data(), trigData.Data());
+       trigger=component.CheckCTP(expression.Data(), trigData.Data());
        if (trigger!=result) {
          cout << expression << ": " << element->Trigger()
               << "->" << trigger 
@@ -293,7 +503,7 @@ int testAliHLTComponent_CTPTrigger()
        expression="!";
        expression+=element->ClassName();
        result=!result;
-       trigger=component.Check(expression.Data(), trigData.Data());
+       trigger=component.CheckCTP(expression.Data(), trigData.Data());
        if (trigger!=result) {
          cout << expression << ": " << element->Trigger()
               << "->" << trigger 
@@ -309,7 +519,7 @@ int testAliHLTComponent_CTPTrigger()
       result=shuffle[0].Trigger() || shuffle[1].Trigger() || shuffle[2].Trigger();
       expression.Form("%s || %s || %s",
                      shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
-      trigger=component.Check(expression.Data(), trigData.Data());
+      trigger=component.CheckCTP(expression.Data(), trigData.Data());
       if (trigger!=result) {
        cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
             << "->" << trigger 
@@ -325,7 +535,7 @@ int testAliHLTComponent_CTPTrigger()
       expression.Form("%s && %s && %s",
                      shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
 
-      trigger=component.Check(expression.Data(), trigData.Data());
+      trigger=component.CheckCTP(expression.Data(), trigData.Data());
       if (trigger!=result) {
        cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
             << "->" << trigger 
@@ -341,7 +551,7 @@ int testAliHLTComponent_CTPTrigger()
       expression.Form("%s && (%s || %s)",
                      shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
 
-      trigger=component.Check(expression.Data(), trigData.Data());
+      trigger=component.CheckCTP(expression.Data(), trigData.Data());
       if (trigger!=result) {
        cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
             << "->" << trigger 
@@ -364,9 +574,33 @@ int testAliHLTComponent_CTPTrigger()
   return iResult;
 }
 
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+//
+// setup of the Configure test
+int testConfigure() 
+{
+  cout << "checking common configuration tools of the base class" << endl;
+  AliHLTTestComponent component;
+  return component.CheckConfigure();
+}
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+//
+// main functions
+
+int testAliHLTComponent()
+{
+  int iResult=0;
+  //if ((iResult=testCTPTrigger())<0) return iResult;
+  if ((iResult=testConfigure())<0) return iResult;
+  return iResult;
+}
+
 int main(int /*argc*/, const char** /*argv*/)
 {
   int iResult=0;
-  iResult=testAliHLTComponent_CTPTrigger();
+  iResult=testAliHLTComponent();
   return iResult;
 }