--- /dev/null
+// $Id$
+
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
+ * for The ALICE HLT Project. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/** @file testAliHLTCTPData.C
+ @author Matthias Richter
+ @date
+ @brief Test program for the AliHLTCTPData class
+ */
+
+#ifndef __CINT__
+#include "TDatime.h"
+#include "TRandom.h"
+#include "AliHLTDataTypes.h"
+#include "algorithm"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TString.h"
+#include "AliHLTDAQ.h"
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <cerrno>
+#include "AliHLTCTPData.h"
+#include "AliHLTReadoutList.h"
+#endif
+
+using namespace std;
+
+class AliHLTCTPDataTest {
+public:
+ AliHLTCTPDataTest() {}
+ ~AliHLTCTPDataTest() {}
+
+ class AliHLTCTPTriggerClass {
+ public:
+ AliHLTCTPTriggerClass() : fBit(~(unsigned)0), fClassName(""), fTrigger(false), fDetectorParam(), fDetectors() {}
+ ~AliHLTCTPTriggerClass() {}
+
+ bool Valid() {return fBit!=~(unsigned)0;}
+ unsigned Bit() {return fBit;}
+ void Bit(unsigned bit) {fBit=bit;}
+ bool Trigger() {return fTrigger;}
+ void Trigger(bool trigger) {fTrigger=trigger;}
+ const char* ClassName() {return fClassName.c_str();}
+ void ClassName(const char* classname) {fClassName=classname;}
+ const char* DetectorParam() {
+ if (fDetectorParam.IsNull() && fDetectors.size()>0) {
+ for (unsigned i=0; i<fDetectors.size(); i++) {
+ if (!fDetectorParam.IsNull()) fDetectorParam+="-";
+ if (fDetectors[i]<10) fDetectorParam+="0";
+ fDetectorParam+=fDetectors[i];
+ }
+ }
+ return fDetectorParam.Data();
+ }
+ void DetectorParam(const char* detectorparam) {fDetectorParam=detectorparam;}
+ int AddDetector(unsigned short detector) {
+ fDetectorParam.Clear();
+ for (vector<unsigned short>::iterator element=fDetectors.begin();
+ element!=fDetectors.end(); element++) {
+ if (detector<*element) {
+ fDetectors.insert(element, detector);
+ return 0;
+ }
+ }
+ fDetectors.push_back(detector);
+ return 0;
+ }
+ bool HasDetector(int detector) const {
+ for (unsigned i=0; i<fDetectors.size(); i++) {
+ if (fDetectors[i]==detector) {
+ return true;
+ }
+ }
+ return false;
+ }
+ bool HasDetector(const char* id) const {
+ TString detectorid=id;
+ for (unsigned i=0; i<fDetectors.size(); i++) {
+ if (detectorid.CompareTo(AliHLTDAQ::OnlineName(fDetectors[i]))==0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private:
+ unsigned fBit;
+ string fClassName;
+ bool fTrigger;
+ TString fDetectorParam;
+ vector<unsigned short> fDetectors;
+ };
+
+protected:
+private:
+};
+
+class AliHLTTriggerDataAccess
+{
+public:
+ AliHLTTriggerDataAccess()
+ : fData(NULL)
+ , fEventData(NULL)
+ , fCDH(NULL)
+ , fMine(NULL)
+ {
+ unsigned size=sizeof(AliHLTComponentTriggerData) + sizeof(AliHLTEventTriggerData);
+ fMine=new Byte_t[size];
+ memset(fMine, 0, size);
+ AliHLTComponentTriggerData* data=reinterpret_cast<AliHLTComponentTriggerData*>(fMine);
+ data->fData=fMine+sizeof(AliHLTComponentTriggerData);
+ Set(data);
+ }
+
+ AliHLTTriggerDataAccess(AliHLTComponentTriggerData* pData)
+ : fData(NULL)
+ , fEventData(NULL)
+ , fCDH(NULL)
+ , fMine(NULL)
+ {
+ if (fMine) delete [] fMine;
+ fMine=NULL;
+ Set(pData);
+ }
+
+ ~AliHLTTriggerDataAccess(){
+ if (fMine) delete [] fMine;
+ fMine=NULL;
+ fData=NULL;
+ fEventData=NULL;
+ fCDH=NULL;
+ }
+
+ AliHLTComponentTriggerData* Data() {return fData;}
+
+ Long64_t TriggerMask() {
+ Long64_t mask=0;
+ if (fCDH) {
+ mask=fCDH[6];
+ mask<<=32;
+ mask|=fCDH[5];
+ }
+ return mask;
+ }
+
+ int Set(AliHLTComponentTriggerData* data) {
+ fData=data;
+ fData->fDataSize=sizeof(AliHLTEventTriggerData);
+ fEventData=reinterpret_cast<AliHLTEventTriggerData*>(fData->fData);
+ fCDH=fEventData->fCommonHeader;
+ return 0;
+ }
+
+ int ResetCDH() {
+ if (fCDH) {
+ memset(fCDH, 0, 32);
+ }
+ return 0;
+ }
+
+ int TriggerBit(unsigned bit, bool set) {
+ if ((int)bit>=gkNCTPTriggerClasses) return -EINVAL;
+ if (!fCDH) return -ENODATA;
+
+ int word=5;
+ if (bit>=32) {
+ word++;
+ bit-=32;
+ }
+ if (set)
+ fCDH[word]|=(UInt_t)0x1<<bit;
+ else
+ fCDH[word]&=~((UInt_t)0x1<<bit);
+
+ return bit;
+ }
+
+private:
+ AliHLTTriggerDataAccess(const AliHLTTriggerDataAccess&);
+ AliHLTTriggerDataAccess& operator=(const AliHLTTriggerDataAccess&);
+
+ AliHLTComponentTriggerData* fData;
+ AliHLTEventTriggerData* fEventData;
+ AliHLTUInt32_t* fCDH;
+ Byte_t* fMine;
+};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+//
+// setup of the CTP test
+
+/**
+ * Get a random number in the given range.
+ */
+int GetRandom(int min, int max)
+{
+ if (max-min<2) return min;
+ static TRandom rand;
+ static bool seedSet=false;
+ if (!seedSet) {
+ TDatime dt;
+ rand.SetSeed(dt.Get());
+ seedSet=true;
+ }
+ return min+rand.Integer(max-min);
+}
+
+/**
+ * Generate a random name of given length
+ */
+string GenerateTriggerClassName(int length)
+{
+ string tcn;
+ for (int i=0; i<length; i++) {
+ unsigned char c=GetRandom(48, 83);
+ if (c>57) c+=7;
+ tcn+=c;
+ }
+ return tcn;
+}
+
+/**
+ * Generate an array of trigger classes.
+ * The array has the specified size but the number antries which are actually
+ * filled is randomized.
+ */
+int GenerateTriggerClasses(int size, vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass>& classes)
+{
+ classes.clear();
+ classes.resize(size);
+ unsigned count=GetRandom(4, size>16?size/2:size);
+ for (unsigned i=0; i<count; i++) {
+ int bit=0;
+ do {
+ bit=GetRandom(0, size);
+ } while (classes[bit].Valid());
+ classes[bit].Bit(bit);
+ classes[bit].ClassName((GenerateTriggerClassName(GetRandom(5,15))).c_str());
+ unsigned nofdetectors=GetRandom(1, 10);
+ unsigned short detector=17;
+ for (unsigned k=0; k<nofdetectors; k++) {
+ detector=GetRandom(nofdetectors-k-1, detector-1);
+ classes[bit].AddDetector(detector);
+ }
+ }
+ return classes.size();
+}
+
+/**
+ * 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 testAliHLTCTPData()
+{
+ cout << "checking AliHLTCTPData class" << endl;
+ int iResult=0;
+ vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass> triggerClasses;
+ if (GenerateTriggerClasses(GetRandom(5,gkNCTPTriggerClasses), triggerClasses)<=0) {
+ return -1;
+ }
+
+ TString ecs_parameter="CONFIGURE";
+ TString ctp_parameter="CTP_TRIGGER_CLASS=";
+ vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass>::iterator element=triggerClasses.begin();
+ while (element!=triggerClasses.end()) {
+ if (!element->Valid()) {
+ element=triggerClasses.erase(element);
+ continue;
+ }
+ if (!ctp_parameter.EndsWith("=")) ctp_parameter+=",";
+ if (element->Bit()<10) ctp_parameter+="0";
+ ctp_parameter+=element->Bit();
+ ctp_parameter+=":";
+ ctp_parameter+=element->ClassName(); ctp_parameter+=":";
+ ctp_parameter+=element->DetectorParam();
+ element++;
+ }
+
+ vector<const char*> parameters;
+ parameters.push_back("HLT_MODE=B");
+ parameters.push_back("RUN_NO=0");
+ parameters.push_back(ctp_parameter.Data());
+ random_shuffle(parameters.begin(), parameters.end());
+ for (vector<const char*>::iterator par=parameters.begin();
+ par!=parameters.end(); par++) {
+ ecs_parameter+=";";
+ ecs_parameter+=*par;
+ }
+
+ AliHLTCTPData ctpdata;
+ ctpdata.SetGlobalLoggingLevel(kHLTLogDefault);
+ if ((iResult=ctpdata.InitCTPTriggerClasses(ctp_parameter.Data()))<0) {
+ cerr << "InitCTPTriggerClasses failed :" << iResult << endl;
+ return iResult;
+ }
+
+ AliHLTTriggerDataAccess trigData;
+
+ // check the readout lists for the different trigger classes
+ for (element=triggerClasses.begin();
+ element!=triggerClasses.end(); element++) {
+ trigData.ResetCDH();
+ trigData.TriggerBit(element->Bit(), 1);
+ AliHLTReadoutList detectorReadout(ctpdata.ReadoutList(*trigData.Data()));
+ for (int detectorid=0; detectorid<17; detectorid++) {
+ if ((detectorReadout.DetectorEnabled(0x1<<detectorid) && !element->HasDetector(detectorid)) ||
+ (!detectorReadout.DetectorEnabled(0x1<<detectorid) && element->HasDetector(detectorid))) {
+ cerr << "readout list does not match trigger class " << element->Bit() << ":" << element->ClassName() << ":" << element->DetectorParam() << endl;
+ detectorReadout.Print();
+ return -1;
+ }
+ }
+ }
+
+ const int nofCycles=500;
+ for (int cycle=0; cycle<nofCycles && iResult>=0; cycle++) {
+ bool bHaveTrigger=false;
+ for (element=triggerClasses.begin();
+ element!=triggerClasses.end(); element++) {
+ element->Trigger(GetRandom(0,100)>50);
+ bHaveTrigger|=element->Trigger();
+ }
+ if (!bHaveTrigger) {
+ // trigger at least one class
+ (triggerClasses.begin())->Trigger(1);
+ }
+
+ vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass> shuffle;
+ shuffle.assign(triggerClasses.begin(), triggerClasses.end());
+ for (unsigned int trial=0; trial<2*triggerClasses.size() && iResult>=0; trial++) {
+ random_shuffle(shuffle.begin(), shuffle.end());
+
+ bool result=0;
+ bool trigger=0;
+ TString expression;
+ trigData.ResetCDH();
+ for (element=shuffle.begin();
+ element!=shuffle.end(); element++) {
+ trigData.TriggerBit(element->Bit(), element->Trigger());
+ //cout << " " << element->Bit() << ":" << element->Trigger();
+ }
+ //cout << endl;
+
+ // single class
+ for (element=shuffle.begin();
+ element!=shuffle.end() && iResult>=0 && trial<3;
+ element++) {
+ // is
+ result=element->Trigger();
+ expression=element->ClassName();
+ trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
+ if (trigger!=result) {
+ cout << expression << ": " << element->Trigger()
+ << "->" << trigger
+ << std::hex << " (" << trigData.TriggerMask() << ")"
+ << endl;
+ cerr << "trigger does not match, expected " << result << endl;
+ iResult=-1;
+ break;
+ }
+
+ // is not
+ expression="!";
+ expression+=element->ClassName();
+ result=!result;
+ trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
+ if (trigger!=result) {
+ cout << expression << ": " << element->Trigger()
+ << "->" << trigger
+ << std::hex << " (" << trigData.TriggerMask() << ")"
+ << endl;
+ cerr << "trigger does not match, expected " << result << endl;
+ iResult=-1;
+ break;
+ }
+ }
+
+ // OR
+ 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=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
+ if (trigger!=result) {
+ cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
+ << "->" << trigger
+ << std::hex << " (" << trigData.TriggerMask() << ")"
+ << endl;
+ cerr << "trigger does not match, expected " << result << endl;
+ iResult=-1;
+ break;
+ }
+
+ // AND
+ 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=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
+ if (trigger!=result) {
+ cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
+ << "->" << trigger
+ << std::hex << " (" << trigData.TriggerMask() << ")"
+ << endl;
+ cerr << "trigger does not match, expected " << result << endl;
+ iResult=-1;
+ break;
+ }
+
+ // mixed OR/AND
+ 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=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
+ if (trigger!=result) {
+ cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
+ << "->" << trigger
+ << std::hex << " (" << trigData.TriggerMask() << ")"
+ << endl;
+ cerr << "trigger does not match, expected " << result << endl;
+ iResult=-1;
+ break;
+ }
+ }
+ // readout list
+ AliHLTReadoutList detectorReadout(ctpdata.ReadoutList(*trigData.Data()));
+ for (int detectorid=0; detectorid<17 && iResult>=0; detectorid++) {
+ if (detectorReadout.DetectorEnabled(0x1<<detectorid)) {
+ // detector is included in the readout, find at least one active trigger
+ // class with this detector
+ for (element=triggerClasses.begin();
+ element!=triggerClasses.end(); element++) {
+ if (element->Trigger() && element->HasDetector(detectorid)) break;
+ }
+ if (element==triggerClasses.end()) {
+ cerr << "can not find any active trigger class for detector " << detectorid << " enabled in the readout" << endl;
+ iResult=-1;
+ }
+ } else {
+ // check that this detector is not part of any of the active trigger classes
+ for (element=triggerClasses.begin();
+ element!=triggerClasses.end(); element++) {
+ if (element->Trigger() && element->HasDetector(detectorid)) {
+ cerr << "detector " << detectorid << " not enabled in the readout but enabled in active trigger class " << element->ClassName() << endl;
+ iResult=-1;
+ }
+ }
+ }
+ if (iResult<0) {
+ detectorReadout.Print();
+ }
+ }
+ if ((cycle+1)%(nofCycles/5)==0) cout << " " << (100*(cycle+1))/nofCycles << " % done" << endl;
+ }
+
+ if (iResult<0) {
+ cerr << "check failed, dumping info" << endl;
+ cerr << "CTP param: " << ctp_parameter << endl;
+ for (element=triggerClasses.begin();
+ element!=triggerClasses.end(); element++) {
+ cerr << element->Trigger() << " " << element->Bit() << ": " << element->ClassName() << endl;
+ }
+ }
+ return iResult;
+}
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+//
+// main functions
+
+int main(int /*argc*/, const char** /*argv*/)
+{
+ int iResult=0;
+ iResult=testAliHLTCTPData();
+ return iResult;
+}