3 /**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * for The ALICE HLT Project. *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
19 // @file testAliHLTComponent.C
20 // @author Matthias Richter
22 // @brief Test program for the AliHLTComponent base class
28 #include "AliHLTDataTypes.h"
29 #include "AliHLTProcessor.h"
30 #include "AliHLTPluginBase.h"
31 #include "AliHLTSystem.h"
32 #include "AliHLTMisc.h"
33 #include "AliHLTComponentHandler.h"
34 #include "AliHLTConfiguration.h"
36 #include "TObjArray.h"
37 #include "TObjString.h"
43 class AliHLTTestComponent : public AliHLTProcessor
46 AliHLTTestComponent() :
48 fCurrentArgument(fArguments.begin())
51 ~AliHLTTestComponent() {}
53 const char* GetComponentID() {return "TestComponent";};
54 void GetInputDataTypes(AliHLTComponentDataTypeList& list) {list.clear();}
55 AliHLTComponentDataType GetOutputDataType() {return kAliHLTAnyDataType;}
56 void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier) {constBase=0; inputMultiplier=0;}
57 AliHLTComponent* Spawn() {return new AliHLTTestComponent;}
59 class AliHLTConfigurationArgument {
61 AliHLTConfigurationArgument(const char* argument) :
64 TString work=argument;
65 fElements=work.Tokenize(" ");
68 AliHLTConfigurationArgument(const AliHLTConfigurationArgument& src) :
72 fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
76 ~AliHLTConfigurationArgument() {
77 if (fElements) delete fElements;
80 AliHLTConfigurationArgument& operator=(const AliHLTConfigurationArgument& src) {
83 fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
88 const char* Argument() {
89 if (!fElements) return NULL;
90 return ((TObjString*)fElements->At(0))->GetString().Data();
94 if (!fElements) return 0;
95 return fElements->GetEntriesFast()-1;
98 const char* Parameter(int i) {
100 fElements->GetEntriesFast()<=i+1) return NULL;
101 return ((TObjString*)fElements->At(i+1))->GetString().Data();
104 bool operator==(const char* string) {
105 if (!fElements) return 0;
106 return (((TObjString*)fElements->At(0))->GetString().CompareTo(string))==0;
109 bool operator!=(const char* string) {
110 return !operator==(string);
115 cout << "############# empty ############" << endl;
118 cout << " Print: " << Argument() << " with " << NofParameters() << " parameter(s)";
119 for (int n=0; n<NofParameters(); n++) cout << " " << Parameter(n);
124 TObjArray* fElements;
127 int ScanConfigurationArgument(int argc, const char** argv) {
128 if (fCurrentArgument==fArguments.end()) return 0;
131 // check whether it is an argument at all
132 if (*(argv[count])!='-') {
133 cerr << "not a recognized argument: " << argv[count] << endl;
137 // check whether the argument matches
138 //fCurrentArgument->Print();
139 if (*fCurrentArgument!=argv[count]) {
140 cerr << "argument sequence does not match: got " << argv[count] << " expected " << fCurrentArgument->Argument() << endl;
146 if (fCurrentArgument->NofParameters()>0) {
148 cerr << "missing parameter" << endl;
152 // implement more checks here
153 count+=fCurrentArgument->NofParameters();
159 int FillArgumentVector(const char** arguments, vector<AliHLTConfigurationArgument>& list) {
161 for (const char** iter=arguments; *iter!=NULL; iter++) {
162 list.push_back(AliHLTConfigurationArgument(*iter));
167 int FillArgv(vector<AliHLTConfigurationArgument>& list, vector<const char*>& argv) {
169 for (vector<AliHLTConfigurationArgument>::iterator argument=list.begin();
170 argument!=list.end(); argument++) {
171 argv.push_back(argument->Argument());
172 for (int n=0; n<argument->NofParameters(); n++) {
173 argv.push_back(argument->Parameter(n));
179 void PrintArgv(int argc, const char** argv) {
180 for (int n=0; n<argc; n++) {
181 cout << " " << n << " : " << argv[n] << endl;
185 int CheckSequence(const char* sequence[], int mode=0) {
187 if ((iResult=FillArgumentVector(sequence, fArguments))<0) {
188 cerr << "failed to fill argument vector" << endl;
191 vector<const char*> argv;
193 if ((iResult=FillArgv(fArguments, argv))<0) {
194 cerr << "failed to fill argument array" << endl;
198 for (const char** element=sequence; *element!=NULL; element++)
199 argv.push_back(*element);
201 fCurrentArgument=fArguments.begin();
202 //PrintArgv(argv.size(), &argv[0]);
203 if ((iResult=ConfigureFromArgumentString(argv.size(), &argv[0]))<0) {
204 cerr << "ConfigureFromArgumentString failed " << endl;
211 int CheckConfigure() {
213 const char* sequence1[]={"-sequence1","-argument2 5", NULL};
214 if ((iResult=CheckSequence(sequence1))<0) {
215 cerr << "failed checking sequence " << sequence1[0] << endl;
219 const char* sequence2[]={"-sequence2","-argument2 5 8", "-argument3 test", NULL};
220 if ((iResult=CheckSequence(sequence2))<0) {
221 cerr << "failed checking sequence in mode 0: " << sequence2[0] << endl;
225 if ((iResult=CheckSequence(sequence2, 1))<0) {
226 cerr << "failed checking sequence in mode 1: " << sequence2[0] << endl;
230 const char* sequence3[]={"-solenoidBz 5", NULL};
231 if ((iResult=CheckSequence(sequence3))<0) {
232 cerr << "failed checking sequence " << sequence3[0] << endl;
238 int InitCTPTest(const char* param) {
239 // this quick test needs to be the functions of the base class to be
240 // defined 'protected'
242 //return ScanECSParam(param);
243 //return InitCTPTriggerClasses(param);
247 bool CheckCTP(const char* expression, AliHLTComponentTriggerData* data) {
248 return EvaluateCTPTriggerClass(expression, *data);
251 class AliHLTCTPTriggerClass {
253 AliHLTCTPTriggerClass() : fBit(~(unsigned)0), fClassName(""), fTrigger(false) {}
254 ~AliHLTCTPTriggerClass() {}
256 bool Valid() {return fBit!=~(unsigned)0;}
257 unsigned Bit() {return fBit;}
258 void Bit(unsigned bit) {fBit=bit;}
259 bool Trigger() {return fTrigger;}
260 void Trigger(bool trigger) {fTrigger=trigger;}
261 const char* ClassName() {return fClassName.c_str();}
262 void ClassName(const char* classname) {fClassName=classname;}
269 int DoInit(int /*argc*/, const char** /*argv*/) {
278 int DoEvent( const AliHLTComponentEventData& /*evtData*/,
279 AliHLTComponentTriggerData& /*trigData*/) {
280 if (!IsDataEvent()) return 0;
282 cout << "DoEvent: run no " << GetRunNo() << endl;
283 if ((int)GetRunNo()!=AliHLTMisc::Instance().GetCDBRunNo()) {
289 vector<AliHLTConfigurationArgument> fArguments;
290 vector<AliHLTConfigurationArgument>::iterator fCurrentArgument;
293 class AliHLTTriggerDataAccess
296 AliHLTTriggerDataAccess()
302 unsigned size=sizeof(AliHLTComponentTriggerData) + sizeof(AliHLTEventTriggerData);
303 fMine=new Byte_t[size];
304 memset(fMine, 0, size);
305 AliHLTComponentTriggerData* data=reinterpret_cast<AliHLTComponentTriggerData*>(fMine);
306 data->fData=fMine+sizeof(AliHLTComponentTriggerData);
310 AliHLTTriggerDataAccess(AliHLTComponentTriggerData* pData)
316 if (fMine) delete [] fMine;
321 ~AliHLTTriggerDataAccess(){
322 if (fMine) delete [] fMine;
329 AliHLTComponentTriggerData* Data() {return fData;}
331 Long64_t TriggerMask() {
341 int Set(AliHLTComponentTriggerData* data) {
343 fData->fDataSize=sizeof(AliHLTEventTriggerData);
344 fEventData=reinterpret_cast<AliHLTEventTriggerData*>(fData->fData);
345 fCDH=fEventData->fCommonHeader;
356 int TriggerBit(unsigned bit, bool set) {
357 if ((int)bit>=gkNCTPTriggerClasses) return -EINVAL;
358 if (!fCDH) return -ENODATA;
366 fCDH[word]|=(UInt_t)0x1<<bit;
368 fCDH[word]&=~((UInt_t)0x1<<bit);
374 AliHLTTriggerDataAccess(const AliHLTTriggerDataAccess&);
375 AliHLTTriggerDataAccess& operator=(const AliHLTTriggerDataAccess&);
377 AliHLTComponentTriggerData* fData;
378 AliHLTEventTriggerData* fEventData;
379 AliHLTUInt32_t* fCDH;
383 /////////////////////////////////////////////////////////////////////////
384 /////////////////////////////////////////////////////////////////////////
386 // setup of the CTP test
389 * Get a random number in the given range.
391 int GetRandom(int min, int max)
393 if (max-min<2) return min;
395 static bool seedSet=false;
398 rand.SetSeed(dt.Get());
401 return min+rand.Integer(max-min);
405 * Generate a random name of given length
407 string GenerateTriggerClassName(int length)
410 for (int i=0; i<length; i++) {
411 unsigned char c=GetRandom(48, 83);
419 * Generate an array of trigger classes.
420 * The array has the specified size but the number antries which are actually
421 * filled is randomized.
423 int GenerateTriggerClasses(int size, vector<AliHLTTestComponent::AliHLTCTPTriggerClass>& classes)
426 classes.resize(size);
427 unsigned count=GetRandom(4, size>16?size/2:size);
428 for (unsigned i=0; i<count; i++) {
431 bit=GetRandom(0, size);
432 } while (classes[bit].Valid());
433 classes[bit].Bit(bit);
434 classes[bit].ClassName((GenerateTriggerClassName(GetRandom(5,15))).c_str());
436 return classes.size();
440 * Test the CTP trigger tools
441 * The base class is initialized with an ECS string of randomly defined trigger
442 * classes consisting of random bits and names. Than a couple of expressions is
443 * test for various random bit patterns.
447 cout << "checking CTP functionality of the base class" << endl;
449 vector<AliHLTTestComponent::AliHLTCTPTriggerClass> triggerClasses;
450 if (GenerateTriggerClasses(GetRandom(5,gkNCTPTriggerClasses), triggerClasses)<=0) {
454 TString parameter="CONFIGURE;CTP_TRIGGER_CLASS=";
455 vector<AliHLTTestComponent::AliHLTCTPTriggerClass>::iterator element=triggerClasses.begin();
456 while (element!=triggerClasses.end()) {
457 if (!element->Valid()) {
458 element=triggerClasses.erase(element);
461 if (!parameter.EndsWith("=")) parameter+=",";
462 if (element->Bit()<10) parameter+="0";
463 parameter+=element->Bit();
465 parameter+=element->ClassName(); parameter+=":";
466 parameter+="05-01-06"; // just a test pattern for the detector ids, ignored for the moment
469 parameter+=";HLT_MODE=A;RUN_NO=0";
471 AliHLTTestComponent component;
472 component.SetGlobalLoggingLevel(kHLTLogDefault);
473 if ((iResult=component.InitCTPTest(parameter.Data()))<0) {
474 cerr << "InitCTPTest failed :" << iResult << endl;
477 cout << "init ECS parameter: " << parameter << endl;
479 AliHLTTriggerDataAccess trigData;
480 for (int cycle=0; cycle<500 && iResult>=0; cycle++) {
481 for (element=triggerClasses.begin();
482 element!=triggerClasses.end(); element++) {
483 element->Trigger(GetRandom(0,100)>50);
486 vector<AliHLTTestComponent::AliHLTCTPTriggerClass> shuffle;
487 shuffle.assign(triggerClasses.begin(), triggerClasses.end());
488 for (unsigned int trial=0; trial<2*triggerClasses.size() && iResult>=0; trial++) {
489 random_shuffle(shuffle.begin(), shuffle.end());
495 for (element=shuffle.begin();
496 element!=shuffle.end(); element++) {
497 trigData.TriggerBit(element->Bit(), element->Trigger());
501 for (element=shuffle.begin();
502 element!=shuffle.end() && iResult>=0 && trial<3;
505 result=element->Trigger();
506 expression=element->ClassName();
507 trigger=component.CheckCTP(expression.Data(), trigData.Data());
508 if (trigger!=result) {
509 cout << expression << ": " << element->Trigger()
511 << std::hex << " (" << trigData.TriggerMask() << ")"
513 cerr << "trigger does not match, expected " << result << endl;
520 expression+=element->ClassName();
522 trigger=component.CheckCTP(expression.Data(), trigData.Data());
523 if (trigger!=result) {
524 cout << expression << ": " << element->Trigger()
526 << std::hex << " (" << trigData.TriggerMask() << ")"
528 cerr << "trigger does not match, expected " << result << endl;
535 result=shuffle[0].Trigger() || shuffle[1].Trigger() || shuffle[2].Trigger();
536 expression.Form("%s || %s || %s",
537 shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
538 trigger=component.CheckCTP(expression.Data(), trigData.Data());
539 if (trigger!=result) {
540 cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
542 << std::hex << " (" << trigData.TriggerMask() << ")"
544 cerr << "trigger does not match, expected " << result << endl;
550 result=shuffle[0].Trigger() && shuffle[1].Trigger() && shuffle[2].Trigger();
551 expression.Form("%s && %s && %s",
552 shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
554 trigger=component.CheckCTP(expression.Data(), trigData.Data());
555 if (trigger!=result) {
556 cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
558 << std::hex << " (" << trigData.TriggerMask() << ")"
560 cerr << "trigger does not match, expected " << result << endl;
566 result=shuffle[0].Trigger() && (shuffle[1].Trigger() || shuffle[2].Trigger());
567 expression.Form("%s && (%s || %s)",
568 shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
570 trigger=component.CheckCTP(expression.Data(), trigData.Data());
571 if (trigger!=result) {
572 cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
574 << std::hex << " (" << trigData.TriggerMask() << ")"
576 cerr << "trigger does not match, expected " << result << endl;
583 cerr << "check failed, dumping info" << endl;
584 cerr << "ECS param: " << parameter << endl;
585 for (element=triggerClasses.begin();
586 element!=triggerClasses.end(); element++) {
587 cerr << element->Trigger() << " " << element->Bit() << ": " << element->ClassName() << endl;
593 /////////////////////////////////////////////////////////////////////////
594 /////////////////////////////////////////////////////////////////////////
596 // setup of the Configure test
599 cout << "checking common configuration tools of the base class" << endl;
600 AliHLTTestComponent component;
601 return component.CheckConfigure();
604 /////////////////////////////////////////////////////////////////////////
605 /////////////////////////////////////////////////////////////////////////
607 // test event precessing sequence
608 int testEventProcessing()
611 cout << "checking AliHLTComponent processing sequence" << endl;
612 AliHLTSystem* pHLT=AliHLTPluginBase::GetInstance();
614 cerr << "error: failed to create HLTSystem" << endl;
618 // add the test component to the handler
619 pHLT->GetComponentHandler()->AddComponent(new AliHLTTestComponent);
621 // configurattion with just the TestComponent
622 AliHLTConfiguration testcomponent("testcomponent", "TestComponent", "", "");
623 pHLT->BuildTaskList("testcomponent");
625 // setup the OCDB and init a random runno
626 AliHLTMisc::Instance().InitCDB("local:///tmp");
627 int runNo=GetRandom(0,1000);
628 AliHLTMisc::Instance().SetCDBRunNo(runNo);
631 if ((iResult=pHLT->Run(1))<0) {
632 cerr << "error: event processing failed" << endl;
639 /////////////////////////////////////////////////////////////////////////
640 /////////////////////////////////////////////////////////////////////////
644 int testAliHLTComponent()
647 //if ((iResult=testCTPTrigger())<0) return iResult;
648 if ((iResult=testConfigure())<0) return iResult;
649 if ((iResult=testEventProcessing())<0) return iResult;
653 int main(int /*argc*/, const char** /*argv*/)
656 iResult=testAliHLTComponent();