]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/test/testAliHLTCTPData.C
Adding the new detector MFT (Antonio Uras)
[u/mrichter/AliRoot.git] / HLT / BASE / test / testAliHLTCTPData.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   testAliHLTCTPData.C
20     @author Matthias Richter
21     @date   
22     @brief  Test program for the AliHLTCTPData class
23  */
24
25 #ifndef __CINT__
26 #include "TDatime.h"
27 #include "TRandom.h"
28 #include "AliHLTDataTypes.h"
29 #include "algorithm"
30 #include "TObjArray.h"
31 #include "TObjString.h"
32 #include "TString.h"
33 #include "AliHLTDAQ.h"
34 #include <cstdio>
35 #include <cstring>
36 #include <iostream>
37 #include <cerrno>
38 #include "AliHLTCTPData.h"
39 #include "AliHLTReadoutList.h"
40 #endif
41
42 using namespace std;
43
44 class AliHLTCTPDataTest {
45 public:
46   AliHLTCTPDataTest() {}
47   ~AliHLTCTPDataTest() {}
48
49   class AliHLTCTPTriggerClass {
50   public:
51     AliHLTCTPTriggerClass() : fBit(~(unsigned)0), fClassName(""), fTrigger(false), fDetectorParam(), fDetectors() {}
52     ~AliHLTCTPTriggerClass() {}
53
54     bool        Valid() {return fBit!=~(unsigned)0;}
55     unsigned    Bit() {return fBit;}
56     void        Bit(unsigned bit) {fBit=bit;}
57     bool        Trigger() {return fTrigger;}
58     void        Trigger(bool trigger) {fTrigger=trigger;}
59     const char* ClassName() {return fClassName.c_str();}
60     void        ClassName(const char* classname) {fClassName=classname;}
61     const char* DetectorParam() {
62       if (fDetectorParam.IsNull() && fDetectors.size()>0) {
63         for (unsigned  i=0; i<fDetectors.size(); i++) {
64           if (!fDetectorParam.IsNull()) fDetectorParam+="-";
65           if (fDetectors[i]<10) fDetectorParam+="0";
66           fDetectorParam+=fDetectors[i];
67         }
68       }
69       return fDetectorParam.Data();
70     }
71     void        DetectorParam(const char* detectorparam) {fDetectorParam=detectorparam;}
72     int         AddDetector(unsigned short detector) {
73       fDetectorParam.Clear();
74       for (vector<unsigned short>::iterator element=fDetectors.begin();
75            element!=fDetectors.end(); element++) {
76         if (detector<*element) {
77           fDetectors.insert(element, detector);
78           return 0;
79         }
80       }
81       fDetectors.push_back(detector);
82       return 0;
83     }
84     bool        HasDetector(int detector) const {
85       for (unsigned i=0; i<fDetectors.size(); i++) {
86         if (fDetectors[i]==detector) {
87           return true;
88         }
89       }
90       return false;
91     }
92     bool        HasDetector(const char* id) const {
93       TString detectorid=id;
94       for (unsigned i=0; i<fDetectors.size(); i++) {
95         if (detectorid.CompareTo(AliHLTDAQ::OnlineName(fDetectors[i]))==0) {
96           return true;
97         }
98       }
99       return false;
100     }
101
102   private:
103     unsigned fBit;
104     string   fClassName;
105     bool     fTrigger;
106     TString  fDetectorParam;
107     vector<unsigned short> fDetectors;
108   };
109
110 protected:
111 private:
112 };
113
114 class AliHLTTriggerDataAccess
115 {
116 public:
117   AliHLTTriggerDataAccess()
118     : fData(NULL)
119     , fEventData(NULL)
120     , fCDH(NULL)
121     , fMine(NULL)
122   {
123     unsigned size=sizeof(AliHLTComponentTriggerData) + sizeof(AliHLTEventTriggerData);
124     fMine=new Byte_t[size];
125     memset(fMine, 0, size);
126     AliHLTComponentTriggerData* data=reinterpret_cast<AliHLTComponentTriggerData*>(fMine);
127     data->fStructSize=sizeof(AliHLTComponentTriggerData);
128     data->fData=fMine+sizeof(AliHLTComponentTriggerData);
129     Set(data);
130   }
131
132   AliHLTTriggerDataAccess(AliHLTComponentTriggerData* pData)
133     : fData(NULL)
134     , fEventData(NULL)
135     , fCDH(NULL)
136     , fMine(NULL)
137   {
138     if (fMine) delete [] fMine;
139     fMine=NULL;
140     Set(pData);
141   }
142
143   ~AliHLTTriggerDataAccess(){
144     if (fMine) delete [] fMine;
145     fMine=NULL;
146     fData=NULL;
147     fEventData=NULL;
148     fCDH=NULL;
149   }
150
151   AliHLTComponentTriggerData* Data() {return fData;}
152
153   Long64_t              TriggerMask() {
154     Long64_t mask=0;
155     if (fCDH) {
156       mask=fCDH[6];
157       mask<<=32;
158       mask|=fCDH[5];
159     }
160     return mask;
161   }
162
163   int Set(AliHLTComponentTriggerData* data) {
164     fData=data;
165     fData->fDataSize=sizeof(AliHLTEventTriggerData);
166     fEventData=reinterpret_cast<AliHLTEventTriggerData*>(fData->fData);
167     fEventData->fCommonHeaderWordCnt=gkAliHLTCommonHeaderCount;
168     fCDH=fEventData->fCommonHeader;
169     return 0;
170   }
171
172   int ResetCDH() {
173     if (fCDH) {
174       memset(fCDH, 0, 32);
175     }
176     return 0;
177   }
178
179   int TriggerBit(unsigned bit, bool set) {
180     if ((int)bit>=gkNCTPTriggerClasses) return -EINVAL;
181     if (!fCDH) return -ENODATA;
182
183     int word=5;
184     if (bit>=32) {
185       word++;
186       bit-=32;
187     }
188     if (set)
189       fCDH[word]|=(UInt_t)0x1<<bit;
190     else
191       fCDH[word]&=~((UInt_t)0x1<<bit);
192       
193     return bit;
194   }
195
196 private:
197   AliHLTTriggerDataAccess(const AliHLTTriggerDataAccess&);
198   AliHLTTriggerDataAccess& operator=(const AliHLTTriggerDataAccess&);
199
200   AliHLTComponentTriggerData* fData;
201   AliHLTEventTriggerData*     fEventData;
202   AliHLTUInt32_t*             fCDH;
203   Byte_t*                     fMine;
204 };
205
206 /////////////////////////////////////////////////////////////////////////
207 /////////////////////////////////////////////////////////////////////////
208 //
209 // setup of the CTP test
210
211 /**
212  * Get a random number in the given range.
213  */
214 int GetRandom(int min, int max)
215 {
216   if (max-min<2) return min;
217   static TRandom rand;
218   static bool seedSet=false;
219   if (!seedSet) {
220     TDatime dt;
221     rand.SetSeed(dt.Get());
222     seedSet=true;
223   }
224   return min+rand.Integer(max-min);
225 }
226
227 /**
228  * Generate a random name of given length
229  */
230 string GenerateTriggerClassName(int length)
231 {
232   string tcn;
233   bool toggle=false;
234   for (int i=0; i<length; i++) {
235     // add random number of '-' characters, but not at beginning or end
236     if (i>0 && i<length-1 && GetRandom(5,10)==7 && (toggle=(!toggle))) {
237       tcn+='-';
238       continue;
239     }
240     unsigned char c=GetRandom(48, 83);
241     if (c>57) c+=7;
242     tcn+=c;
243   }
244   return tcn;
245 }
246
247 /**
248  * Generate an array of trigger classes.
249  * The array has the specified size but the number antries which are actually
250  * filled is randomized.
251  */
252 int GenerateTriggerClasses(int size, vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass>& classes)
253 {
254   classes.clear();
255   classes.resize(size);
256   unsigned count=GetRandom(4, size>16?size/2:size);
257   int last=-1;
258   for (unsigned i=0; i<count; i++) {
259     int bit=0;
260     do {
261       bit=GetRandom(0, size);
262     } while (classes[bit].Valid());
263     classes[bit].Bit(bit);
264     if (last>=0 && GetRandom(5,10)==7) {
265       // generate similar class names by just adding or truncating characters
266       string name=classes[last].ClassName();
267       if (GetRandom(0,100)%2) {
268         name+=GenerateTriggerClassName(GetRandom(3,7)).c_str();
269         cout << "using appended name " << name << " (" << classes[last].ClassName() << ")" << endl;
270       } else {
271         int num=GetRandom(1,name.length()/2);
272         name.erase(name.length()-num, num);
273         cout << "using truncated name " << name << " (" << classes[last].ClassName() << ")" << endl;
274       }
275       classes[bit].ClassName(name.c_str());
276     } else {
277     classes[bit].ClassName((GenerateTriggerClassName(GetRandom(5,15))).c_str());
278     }
279     last=bit;
280     unsigned nofdetectors=GetRandom(1, 10);
281     unsigned short detector=17;
282     for (unsigned k=0; k<nofdetectors; k++) {
283       detector=GetRandom(nofdetectors-k-1, detector-1);
284       classes[bit].AddDetector(detector);
285     }
286   }
287   return classes.size();
288 }
289
290 /**
291  * Test the CTP trigger tools
292  * The base class is initialized with an ECS string of randomly defined trigger
293  * classes consisting of random bits and names. Than a couple of expressions is
294  * test for various random bit patterns.
295  */
296 int testAliHLTCTPData()
297 {
298   cout << "checking AliHLTCTPData class" << endl;
299   int iResult=0;
300   vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass> triggerClasses;
301   if (GenerateTriggerClasses(GetRandom(5,gkNCTPTriggerClasses), triggerClasses)<=0) {
302     return -1;
303   }
304
305   TString ecs_parameter="CONFIGURE";
306   TString ctp_parameter="CTP_TRIGGER_CLASS=";
307   vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass>::iterator element=triggerClasses.begin();
308   while (element!=triggerClasses.end()) {
309     if (!element->Valid()) {
310       element=triggerClasses.erase(element);
311       continue;
312     }
313     if (!ctp_parameter.EndsWith("=")) ctp_parameter+=",";
314     if (element->Bit()<10) ctp_parameter+="0";
315     ctp_parameter+=element->Bit(); 
316     ctp_parameter+=":";
317     ctp_parameter+=element->ClassName(); ctp_parameter+=":";
318     ctp_parameter+=element->DetectorParam();
319     element++;
320   }
321
322   vector<const char*> parameters;
323   parameters.push_back("HLT_MODE=B");
324   parameters.push_back("RUN_NO=0");
325   parameters.push_back(ctp_parameter.Data());
326   random_shuffle(parameters.begin(), parameters.end());
327   for (vector<const char*>::iterator par=parameters.begin();
328        par!=parameters.end(); par++) {
329     ecs_parameter+=";";
330     ecs_parameter+=*par;
331   }
332
333   AliHLTCTPData ctpdata;
334   ctpdata.SetGlobalLoggingLevel(kHLTLogDefault);
335   if ((iResult=ctpdata.InitCTPTriggerClasses(ctp_parameter.Data()))<0) {
336     cerr << "InitCTPTriggerClasses failed :" << iResult << endl;
337     return iResult;
338   }
339
340   for (element=triggerClasses.begin();
341        element!=triggerClasses.end();
342        element++) {
343     int index=ctpdata.Index(element->ClassName());
344     if (index<0) {
345       cerr << "error: can not find CTP trigger class name " << element->ClassName() << endl;
346       return -1;
347     }
348     if (element->Bit()!=(unsigned)index) {
349       cerr << "error: wrong index for CTP trigger class " << element->ClassName() << ": expected " << element->Bit() << " - got " << index << endl;
350       return -1;      
351     }
352   }
353
354   AliHLTTriggerDataAccess trigData;
355
356   // check the readout lists for the different trigger classes
357   for (element=triggerClasses.begin();
358        element!=triggerClasses.end(); element++) {
359     trigData.ResetCDH();
360     trigData.TriggerBit(element->Bit(), 1);
361     AliHLTReadoutList detectorReadout(ctpdata.ReadoutList(*trigData.Data()));
362     for (int detectorid=0; detectorid<17; detectorid++) {
363         if ((detectorReadout.DetectorEnabled(0x1<<detectorid) && !element->HasDetector(detectorid)) ||
364             (!detectorReadout.DetectorEnabled(0x1<<detectorid) && element->HasDetector(detectorid))) {
365           cerr << "readout list does not match trigger class " << element->Bit() << ":" << element->ClassName() << ":" << element->DetectorParam() << endl;
366           detectorReadout.Print();
367           return -1;
368         }
369      }
370   }
371
372   const int nofCycles=500;
373   for (int cycle=0; cycle<nofCycles && iResult>=0; cycle++) {
374     bool bHaveTrigger=false;
375     for (element=triggerClasses.begin();
376          element!=triggerClasses.end(); element++) {
377       element->Trigger(GetRandom(0,100)>50);
378       bHaveTrigger|=element->Trigger();
379     }
380     if (!bHaveTrigger) {
381       // trigger at least one class
382       (triggerClasses.begin())->Trigger(1);
383     }
384
385     vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass> shuffle;
386     shuffle.assign(triggerClasses.begin(), triggerClasses.end());
387     for (unsigned int trial=0; trial<2*triggerClasses.size() && iResult>=0; trial++) {
388       random_shuffle(shuffle.begin(), shuffle.end());
389
390       bool result=0;
391       bool trigger=0;
392       TString expression;
393       trigData.ResetCDH();
394       for (element=shuffle.begin();
395            element!=shuffle.end(); element++) {
396         trigData.TriggerBit(element->Bit(), element->Trigger());
397         //cout << " " << element->Bit() << ":" << element->Trigger();
398       }
399       //cout << endl;
400       ctpdata.SetTriggers(*(trigData.Data()));
401
402       // single class
403       for (element=shuffle.begin();
404            element!=shuffle.end() && iResult>=0 && trial<3;
405            element++) {
406         int check=ctpdata.CheckTrigger(element->ClassName());
407         if (check<0) {
408           cerr << "error avaluating CheckTrigger: class name " << element->ClassName() << " not found" << endl;
409           iResult=-1;
410           break;          
411         }
412         if (check!=element->Trigger()) {
413           cerr << "error avaluating CheckTrigger, class name " << element->ClassName() << ": expecting " << element->Trigger() << " - got " << check << endl;
414           ctpdata.Print();
415           iResult=-1;
416           break;          
417         }
418
419         // is
420         result=element->Trigger();
421         expression=element->ClassName();
422         trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
423         if (trigger!=result) {
424           cout << expression << ": " << element->Trigger()
425                << "->" << trigger 
426                << std::hex << "   (" << trigData.TriggerMask() << ")"
427                << endl;
428           cerr << "trigger does not match, expected " << result << endl;
429           iResult=-1;
430           break;
431         }
432
433         // is not
434         expression="!";
435         expression+=element->ClassName();
436         result=!result;
437         trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
438         if (trigger!=result) {
439           cout << expression << ": " << element->Trigger()
440                << "->" << trigger 
441                << std::hex << "   (" << trigData.TriggerMask() << ")"
442                << endl;
443           cerr << "trigger does not match, expected " << result << endl;
444           iResult=-1;
445           break;
446         }
447       }
448
449       // OR
450       result=shuffle[0].Trigger() || shuffle[1].Trigger() || shuffle[2].Trigger();
451       expression.Form("%s || %s || %s",
452                       shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
453       trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
454       if (trigger!=result) {
455         cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
456              << "->" << trigger 
457              << std::hex << "   (" << trigData.TriggerMask() << ")"
458              << endl;
459         cerr << "trigger does not match, expected " << result << endl;
460         iResult=-1;
461         break;
462       }
463
464       // AND
465       result=shuffle[0].Trigger() && shuffle[1].Trigger() && shuffle[2].Trigger();
466       expression.Form("%s && %s && %s",
467                       shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
468
469       trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
470       if (trigger!=result) {
471         cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
472              << "->" << trigger 
473              << std::hex << "   (" << trigData.TriggerMask() << ")"
474              << endl;
475         cerr << "trigger does not match, expected " << result << endl;
476         iResult=-1;
477         break;
478       }
479
480       // mixed OR/AND
481       result=shuffle[0].Trigger() && (shuffle[1].Trigger() || shuffle[2].Trigger());
482       expression.Form("%s && (%s || %s)",
483                       shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
484
485       trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
486       if (trigger!=result) {
487         cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger() 
488              << "->" << trigger 
489              << std::hex << "   (" << trigData.TriggerMask() << ")"
490              << endl;
491         cerr << "trigger does not match, expected " << result << endl;
492         iResult=-1;
493         break;
494       }
495     }
496     // readout list
497     AliHLTReadoutList detectorReadout(ctpdata.ReadoutList(*trigData.Data()));
498     for (int detectorid=0; detectorid<17 && iResult>=0; detectorid++) {
499         if (detectorReadout.DetectorEnabled(0x1<<detectorid)) {
500         // detector is included in the readout, find at least one active trigger
501         // class with this detector
502         for (element=triggerClasses.begin();
503              element!=triggerClasses.end(); element++) {
504           if (element->Trigger() && element->HasDetector(detectorid)) break;
505         }
506         if (element==triggerClasses.end()) {
507           cerr << "can not find any active trigger class for detector " << detectorid << " enabled in the readout" << endl;
508           iResult=-1;
509         }
510       } else {
511         // check that this detector is not part of any of the active trigger classes
512         for (element=triggerClasses.begin();
513              element!=triggerClasses.end(); element++) {
514           if (element->Trigger() && element->HasDetector(detectorid)) {
515             cerr << "detector " << detectorid << " not enabled in the readout but enabled in active trigger class " << element->ClassName() << endl;
516             iResult=-1;
517           }
518         }
519       }
520       if (iResult<0) {
521         detectorReadout.Print();
522       }
523     }
524     if ((cycle+1)%(nofCycles/5)==0) cout << " " << (100*(cycle+1))/nofCycles << " % done" << endl;
525   }
526
527   if (iResult<0) {
528     cerr << "check failed, dumping info" << endl;
529     cerr << "CTP param: " << ctp_parameter << endl;
530     for (element=triggerClasses.begin();
531          element!=triggerClasses.end(); element++) {
532       cerr << element->Trigger() << " " << element->Bit() << ": " << element->ClassName() << endl;
533     }
534   }
535   return iResult;
536 }
537
538 /////////////////////////////////////////////////////////////////////////
539 /////////////////////////////////////////////////////////////////////////
540 //
541 // main functions
542
543 int main(int /*argc*/, const char** /*argv*/)
544 {
545   int iResult=0;
546   iResult=testAliHLTCTPData();
547   return iResult;
548 }