]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/test/testAliHLTComponent.C
Adding the new detector MFT (Antonio Uras)
[u/mrichter/AliRoot.git] / HLT / BASE / test / testAliHLTComponent.C
1 // $Id$
2
3 /**************************************************************************
4  * This file is property of and copyright by the ALICE HLT Project        * 
5  * ALICE Experiment at CERN, All rights reserved.                         *
6  *                                                                        *
7  * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8  *                  for The ALICE HLT Project.                            *
9  *                                                                        *
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  **************************************************************************/
18
19 // @file   testAliHLTComponent.C
20 // @author Matthias Richter
21 // @date   
22 // @brief  Test program for the AliHLTComponent base class
23 // 
24
25 #ifndef __CINT__
26 #include "TDatime.h"
27 #include "TRandom.h"
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"
35 #include "algorithm"
36 #include "TObjArray.h"
37 #include "TObjString.h"
38 #include "TString.h"
39 #endif
40
41 using namespace std;
42
43 class AliHLTTestComponent : public AliHLTProcessor
44 {
45 public:
46   AliHLTTestComponent() :
47     fArguments(),
48     fCurrentArgument(fArguments.begin())
49   {}
50
51   ~AliHLTTestComponent() {}
52
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;}
58
59   class AliHLTConfigurationArgument {
60   public:
61     AliHLTConfigurationArgument(const char* argument) :
62       fElements(NULL)
63     {
64       TString work=argument;
65       fElements=work.Tokenize(" ");
66     }
67
68     AliHLTConfigurationArgument(const AliHLTConfigurationArgument& src) :
69       fElements(NULL)
70     {
71       if (src.fElements) {
72         fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
73       }
74     }
75
76     ~AliHLTConfigurationArgument() {
77       if (fElements) delete fElements;
78     }
79
80     AliHLTConfigurationArgument& operator=(const AliHLTConfigurationArgument& src) {
81       delete fElements;
82       if (src.fElements) {
83         fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
84       }
85       return *this;
86     }
87
88     const char* Argument() {
89       if (!fElements) return NULL;
90       return ((TObjString*)fElements->At(0))->GetString().Data();
91     }
92
93     int NofParameters() {
94       if (!fElements) return 0;
95       return fElements->GetEntriesFast()-1;
96     }
97
98     const char* Parameter(int i) {
99       if (!fElements ||
100           fElements->GetEntriesFast()<=i+1) return NULL;
101       return ((TObjString*)fElements->At(i+1))->GetString().Data();      
102     }
103
104     bool operator==(const char* string) {
105       if (!fElements) return 0;
106       return (((TObjString*)fElements->At(0))->GetString().CompareTo(string))==0;
107     }
108
109     bool operator!=(const char* string) {
110       return !operator==(string);
111     }
112
113     void Print() {
114       if (!fElements) {
115         cout << "#############  empty ############" << endl;
116         return;
117       }
118       cout << "   Print: " << Argument() << " with " << NofParameters() << " parameter(s)";
119       for (int n=0; n<NofParameters(); n++) cout << " " << Parameter(n);
120       cout << endl;
121     }
122
123   private:
124     TObjArray* fElements;
125   };
126
127   int ScanConfigurationArgument(int argc, const char** argv) {
128     if (fCurrentArgument==fArguments.end()) return 0;
129     int count=0;
130
131     // check whether it is an argument at all
132     if (*(argv[count])!='-') {
133       cerr << "not a recognized argument: " << argv[count] << endl;
134       return -EINVAL;
135     }
136
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;
141       return -EINVAL;
142     }
143
144     count++;
145     // read parameters
146     if (fCurrentArgument->NofParameters()>0) {
147       if (argc<=count) {
148         cerr << "missing parameter" << endl;
149         return -EPROTO;
150       }
151
152       // implement more checks here
153       count+=fCurrentArgument->NofParameters();
154     }
155     fCurrentArgument++;
156     return count;
157   }
158
159   int FillArgumentVector(const char** arguments, vector<AliHLTConfigurationArgument>& list) {
160     list.clear();
161     for (const char** iter=arguments; *iter!=NULL; iter++) {
162       list.push_back(AliHLTConfigurationArgument(*iter));
163     }
164     return list.size();
165   }
166
167   int FillArgv(vector<AliHLTConfigurationArgument>& list, vector<const char*>& argv) {
168     argv.clear();
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));
174       }
175     }
176     return argv.size();
177   }
178
179   void PrintArgv(int argc, const char** argv) {
180     for (int n=0; n<argc; n++) {
181       cout << "   " << n << " : " << argv[n] << endl;
182     }
183   }
184
185   int CheckSequence(const char* sequence[], int mode=0) {
186     int iResult=0;
187     if ((iResult=FillArgumentVector(sequence, fArguments))<0) {
188       cerr << "failed to fill argument vector" << endl;
189       return iResult;
190     }
191     vector<const char*> argv;
192     if (mode==0) {
193       if ((iResult=FillArgv(fArguments, argv))<0) {
194         cerr << "failed to fill argument array" << endl;
195         return iResult;
196       }
197     } else {
198       for (const char** element=sequence; *element!=NULL; element++)
199         argv.push_back(*element);
200     }
201     fCurrentArgument=fArguments.begin();
202     //PrintArgv(argv.size(), &argv[0]);
203     if ((iResult=ConfigureFromArgumentString(argv.size(), &argv[0]))<0) {
204       cerr << "ConfigureFromArgumentString failed " << endl;
205       return iResult;
206     }
207
208     return iResult;
209   }
210
211   int CheckConfigure() {
212     int iResult=0;
213     const char* sequence1[]={"-sequence1","-argument2 5", NULL};
214     if ((iResult=CheckSequence(sequence1))<0) {
215       cerr << "failed checking sequence " << sequence1[0] << endl;
216       return iResult;
217     }
218
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;
222       return iResult;
223     }
224
225     if ((iResult=CheckSequence(sequence2, 1))<0) {
226       cerr << "failed checking sequence in mode 1: " << sequence2[0] << endl;
227       return iResult;
228     }
229
230     const char* sequence3[]={"-solenoidBz 5", NULL};
231     if ((iResult=CheckSequence(sequence3))<0) {
232       cerr << "failed checking sequence " << sequence3[0] << endl;
233       return iResult;
234     }
235     return iResult;
236   }
237
238   int InitCTPTest(const char* param) {
239     // this quick test needs to be the functions of the base class to be
240     // defined 'protected'
241     SetupCTPData();
242     //return ScanECSParam(param);
243     //return InitCTPTriggerClasses(param);
244     return -ENOSYS;
245   }
246
247   bool CheckCTP(const char* expression, AliHLTComponentTriggerData* data) {
248     return EvaluateCTPTriggerClass(expression, *data);
249   }
250
251   class AliHLTCTPTriggerClass {
252   public:
253     AliHLTCTPTriggerClass() : fBit(~(unsigned)0), fClassName(""), fTrigger(false) {}
254     ~AliHLTCTPTriggerClass() {}
255
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;}    
263   private:
264     unsigned fBit;
265     string   fClassName;
266     bool     fTrigger;
267   };
268 protected:
269   int DoInit(int /*argc*/, const char** /*argv*/) {
270     SetupCTPData();
271     return 0;
272   }
273
274   int DoDeinit() {
275     return 0;
276   }
277
278   int DoEvent( const AliHLTComponentEventData& /*evtData*/,
279                AliHLTComponentTriggerData& /*trigData*/) {
280     if (!IsDataEvent()) return 0;
281
282     cout << "DoEvent: run no " << GetRunNo() << endl;
283     if ((int)GetRunNo()!=AliHLTMisc::Instance().GetCDBRunNo()) {
284       return -1;
285     }
286     return 0;
287   }
288 private:
289   vector<AliHLTConfigurationArgument> fArguments;
290   vector<AliHLTConfigurationArgument>::iterator fCurrentArgument;
291 };
292
293 class AliHLTTriggerDataAccess
294 {
295 public:
296   AliHLTTriggerDataAccess()
297     : fData(NULL)
298     , fEventData(NULL)
299     , fCDH(NULL)
300     , fMine(NULL)
301   {
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);
307     Set(data);
308   }
309
310   AliHLTTriggerDataAccess(AliHLTComponentTriggerData* pData)
311     : fData(NULL)
312     , fEventData(NULL)
313     , fCDH(NULL)
314     , fMine(NULL)
315   {
316     if (fMine) delete [] fMine;
317     fMine=NULL;
318     Set(pData);
319   }
320
321   ~AliHLTTriggerDataAccess(){
322     if (fMine) delete [] fMine;
323     fMine=NULL;
324     fData=NULL;
325     fEventData=NULL;
326     fCDH=NULL;
327   }
328
329   AliHLTComponentTriggerData* Data() {return fData;}
330
331   Long64_t              TriggerMask() {
332     Long64_t mask=0;
333     if (fCDH) {
334       mask=fCDH[6];
335       mask<<=32;
336       mask|=fCDH[5];
337     }
338     return mask;
339   }
340
341   int Set(AliHLTComponentTriggerData* data) {
342     fData=data;
343     fData->fDataSize=sizeof(AliHLTEventTriggerData);
344     fEventData=reinterpret_cast<AliHLTEventTriggerData*>(fData->fData);
345     fCDH=fEventData->fCommonHeader;
346     return 0;
347   }
348
349   int ResetCDH() {
350     if (fCDH) {
351       memset(fCDH, 0, 32);
352     }
353     return 0;
354   }
355
356   int TriggerBit(unsigned bit, bool set) {
357     if ((int)bit>=gkNCTPTriggerClasses) return -EINVAL;
358     if (!fCDH) return -ENODATA;
359
360     int word=5;
361     if (bit>=32) {
362       word++;
363       bit-=32;
364     }
365     if (set)
366       fCDH[word]|=(UInt_t)0x1<<bit;
367     else
368       fCDH[word]&=~((UInt_t)0x1<<bit);
369       
370     return bit;
371   }
372
373 private:
374   AliHLTTriggerDataAccess(const AliHLTTriggerDataAccess&);
375   AliHLTTriggerDataAccess& operator=(const AliHLTTriggerDataAccess&);
376
377   AliHLTComponentTriggerData* fData;
378   AliHLTEventTriggerData*     fEventData;
379   AliHLTUInt32_t*             fCDH;
380   Byte_t*                     fMine;
381 };
382
383 /////////////////////////////////////////////////////////////////////////
384 /////////////////////////////////////////////////////////////////////////
385 //
386 // setup of the CTP test
387
388 /**
389  * Get a random number in the given range.
390  */
391 int GetRandom(int min, int max)
392 {
393   if (max-min<2) return min;
394   static TRandom rand;
395   static bool seedSet=false;
396   if (!seedSet) {
397     TDatime dt;
398     rand.SetSeed(dt.Get());
399     seedSet=true;
400   }
401   return min+rand.Integer(max-min);
402 }
403
404 /**
405  * Generate a random name of given length
406  */
407 string GenerateTriggerClassName(int length)
408 {
409   string tcn;
410   for (int i=0; i<length; i++) {
411     unsigned char c=GetRandom(48, 83);
412     if (c>57) c+=7;
413     tcn+=c;
414   }
415   return tcn;
416 }
417
418 /**
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.
422  */
423 int GenerateTriggerClasses(int size, vector<AliHLTTestComponent::AliHLTCTPTriggerClass>& classes)
424 {
425   classes.clear();
426   classes.resize(size);
427   unsigned count=GetRandom(4, size>16?size/2:size);
428   for (unsigned i=0; i<count; i++) {
429     int bit=0;
430     do {
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());
435   }
436   return classes.size();
437 }
438
439 /**
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.
444  */
445 int testCTPTrigger()
446 {
447   cout << "checking CTP functionality of the base class" << endl;
448   int iResult=0;
449   vector<AliHLTTestComponent::AliHLTCTPTriggerClass> triggerClasses;
450   if (GenerateTriggerClasses(GetRandom(5,gkNCTPTriggerClasses), triggerClasses)<=0) {
451     return -1;
452   }
453
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);
459       continue;
460     }
461     if (!parameter.EndsWith("=")) parameter+=",";
462     if (element->Bit()<10) parameter+="0";
463     parameter+=element->Bit(); 
464     parameter+=":";
465     parameter+=element->ClassName(); parameter+=":";
466     parameter+="05-01-06"; // just a test pattern for the detector ids, ignored for the moment
467     element++;
468   }
469   parameter+=";HLT_MODE=A;RUN_NO=0";
470
471   AliHLTTestComponent component;
472   component.SetGlobalLoggingLevel(kHLTLogDefault);
473   if ((iResult=component.InitCTPTest(parameter.Data()))<0) {
474     cerr << "InitCTPTest failed :" << iResult << endl;
475     return iResult;
476   }
477   cout << "init ECS parameter: " << parameter << endl;
478
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);
484     }
485
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());
490
491       bool result=0;
492       bool trigger=0;
493       TString expression;
494       trigData.ResetCDH();
495       for (element=shuffle.begin();
496            element!=shuffle.end(); element++) {
497         trigData.TriggerBit(element->Bit(), element->Trigger());
498       }
499
500       // single class
501       for (element=shuffle.begin();
502            element!=shuffle.end() && iResult>=0 && trial<3;
503            element++) {
504         // is
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()
510                << "->" << trigger 
511                << std::hex << "   (" << trigData.TriggerMask() << ")"
512                << endl;
513           cerr << "trigger does not match, expected " << result << endl;
514           iResult=-1;
515           break;
516         }
517
518         // is not
519         expression="!";
520         expression+=element->ClassName();
521         result=!result;
522         trigger=component.CheckCTP(expression.Data(), trigData.Data());
523         if (trigger!=result) {
524           cout << expression << ": " << element->Trigger()
525                << "->" << trigger 
526                << std::hex << "   (" << trigData.TriggerMask() << ")"
527                << endl;
528           cerr << "trigger does not match, expected " << result << endl;
529           iResult=-1;
530           break;
531         }
532       }
533
534       // OR
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() 
541              << "->" << trigger 
542              << std::hex << "   (" << trigData.TriggerMask() << ")"
543              << endl;
544         cerr << "trigger does not match, expected " << result << endl;
545         iResult=-1;
546         break;
547       }
548
549       // AND
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());
553
554       trigger=component.CheckCTP(expression.Data(), trigData.Data());
555       if (trigger!=result) {
556         cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
557              << "->" << trigger 
558              << std::hex << "   (" << trigData.TriggerMask() << ")"
559              << endl;
560         cerr << "trigger does not match, expected " << result << endl;
561         iResult=-1;
562         break;
563       }
564
565       // mixed OR/AND
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());
569
570       trigger=component.CheckCTP(expression.Data(), trigData.Data());
571       if (trigger!=result) {
572         cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
573              << "->" << trigger 
574              << std::hex << "   (" << trigData.TriggerMask() << ")"
575              << endl;
576         cerr << "trigger does not match, expected " << result << endl;
577         iResult=-1;
578         break;
579       }
580     }
581   }
582   if (iResult<0) {
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;
588     }
589   }
590   return iResult;
591 }
592
593 /////////////////////////////////////////////////////////////////////////
594 /////////////////////////////////////////////////////////////////////////
595 //
596 // setup of the Configure test
597 int testConfigure() 
598 {
599   cout << "checking common configuration tools of the base class" << endl;
600   AliHLTTestComponent component;
601   return component.CheckConfigure();
602 }
603
604 /////////////////////////////////////////////////////////////////////////
605 /////////////////////////////////////////////////////////////////////////
606 //
607 // test event precessing sequence
608 int testEventProcessing()
609 {
610   int iResult=0;
611   cout << "checking AliHLTComponent processing sequence" << endl;
612   AliHLTSystem* pHLT=AliHLTPluginBase::GetInstance();
613   if (!pHLT) {
614     cerr << "error: failed to create HLTSystem" << endl;
615     return -1;
616   }
617
618   // add the test component to the handler
619   pHLT->GetComponentHandler()->AddComponent(new AliHLTTestComponent);
620
621   // configurattion with just the TestComponent
622   AliHLTConfiguration testcomponent("testcomponent", "TestComponent", "", "");
623   pHLT->BuildTaskList("testcomponent");
624
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);
629
630   // run one event
631   if ((iResult=pHLT->Run(1))<0) {
632     cerr << "error: event processing failed" << endl;
633     return iResult;
634   }
635
636   return 0;
637 }
638
639 /////////////////////////////////////////////////////////////////////////
640 /////////////////////////////////////////////////////////////////////////
641 //
642 // main functions
643
644 int testAliHLTComponent()
645 {
646   int iResult=0;
647   //if ((iResult=testCTPTrigger())<0) return iResult;
648   if ((iResult=testConfigure())<0) return iResult;
649   if ((iResult=testEventProcessing())<0) return iResult;
650   return iResult;
651 }
652
653 int main(int /*argc*/, const char** /*argv*/)
654 {
655   int iResult=0;
656   iResult=testAliHLTComponent();
657   return iResult;
658 }