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 testAliHLTCTPData.C
20 @author Matthias Richter
22 @brief Test program for the AliHLTCTPData class
28 #include "AliHLTDataTypes.h"
30 #include "TObjArray.h"
31 #include "TObjString.h"
33 #include "AliHLTDAQ.h"
38 #include "AliHLTCTPData.h"
39 #include "AliHLTReadoutList.h"
44 class AliHLTCTPDataTest {
46 AliHLTCTPDataTest() {}
47 ~AliHLTCTPDataTest() {}
49 class AliHLTCTPTriggerClass {
51 AliHLTCTPTriggerClass() : fBit(~(unsigned)0), fClassName(""), fTrigger(false), fDetectorParam(), fDetectors() {}
52 ~AliHLTCTPTriggerClass() {}
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];
69 return fDetectorParam.Data();
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);
81 fDetectors.push_back(detector);
84 bool HasDetector(int detector) const {
85 for (unsigned i=0; i<fDetectors.size(); i++) {
86 if (fDetectors[i]==detector) {
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) {
106 TString fDetectorParam;
107 vector<unsigned short> fDetectors;
114 class AliHLTTriggerDataAccess
117 AliHLTTriggerDataAccess()
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);
132 AliHLTTriggerDataAccess(AliHLTComponentTriggerData* pData)
138 if (fMine) delete [] fMine;
143 ~AliHLTTriggerDataAccess(){
144 if (fMine) delete [] fMine;
151 AliHLTComponentTriggerData* Data() {return fData;}
153 Long64_t TriggerMask() {
163 int Set(AliHLTComponentTriggerData* data) {
165 fData->fDataSize=sizeof(AliHLTEventTriggerData);
166 fEventData=reinterpret_cast<AliHLTEventTriggerData*>(fData->fData);
167 fEventData->fCommonHeaderWordCnt=gkAliHLTCommonHeaderCount;
168 fCDH=fEventData->fCommonHeader;
179 int TriggerBit(unsigned bit, bool set) {
180 if ((int)bit>=gkNCTPTriggerClasses) return -EINVAL;
181 if (!fCDH) return -ENODATA;
189 fCDH[word]|=(UInt_t)0x1<<bit;
191 fCDH[word]&=~((UInt_t)0x1<<bit);
197 AliHLTTriggerDataAccess(const AliHLTTriggerDataAccess&);
198 AliHLTTriggerDataAccess& operator=(const AliHLTTriggerDataAccess&);
200 AliHLTComponentTriggerData* fData;
201 AliHLTEventTriggerData* fEventData;
202 AliHLTUInt32_t* fCDH;
206 /////////////////////////////////////////////////////////////////////////
207 /////////////////////////////////////////////////////////////////////////
209 // setup of the CTP test
212 * Get a random number in the given range.
214 int GetRandom(int min, int max)
216 if (max-min<2) return min;
218 static bool seedSet=false;
221 rand.SetSeed(dt.Get());
224 return min+rand.Integer(max-min);
228 * Generate a random name of given length
230 string GenerateTriggerClassName(int length)
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))) {
240 unsigned char c=GetRandom(48, 83);
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.
252 int GenerateTriggerClasses(int size, vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass>& classes)
255 classes.resize(size);
256 unsigned count=GetRandom(4, size>16?size/2:size);
258 for (unsigned i=0; i<count; i++) {
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;
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;
275 classes[bit].ClassName(name.c_str());
277 classes[bit].ClassName((GenerateTriggerClassName(GetRandom(5,15))).c_str());
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);
287 return classes.size();
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.
296 int testAliHLTCTPData()
298 cout << "checking AliHLTCTPData class" << endl;
300 vector<AliHLTCTPDataTest::AliHLTCTPTriggerClass> triggerClasses;
301 if (GenerateTriggerClasses(GetRandom(5,gkNCTPTriggerClasses), triggerClasses)<=0) {
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);
313 if (!ctp_parameter.EndsWith("=")) ctp_parameter+=",";
314 if (element->Bit()<10) ctp_parameter+="0";
315 ctp_parameter+=element->Bit();
317 ctp_parameter+=element->ClassName(); ctp_parameter+=":";
318 ctp_parameter+=element->DetectorParam();
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++) {
333 AliHLTCTPData ctpdata;
334 ctpdata.SetGlobalLoggingLevel(kHLTLogDefault);
335 if ((iResult=ctpdata.InitCTPTriggerClasses(ctp_parameter.Data()))<0) {
336 cerr << "InitCTPTriggerClasses failed :" << iResult << endl;
340 for (element=triggerClasses.begin();
341 element!=triggerClasses.end();
343 int index=ctpdata.Index(element->ClassName());
345 cerr << "error: can not find CTP trigger class name " << element->ClassName() << endl;
348 if (element->Bit()!=(unsigned)index) {
349 cerr << "error: wrong index for CTP trigger class " << element->ClassName() << ": expected " << element->Bit() << " - got " << index << endl;
354 AliHLTTriggerDataAccess trigData;
356 // check the readout lists for the different trigger classes
357 for (element=triggerClasses.begin();
358 element!=triggerClasses.end(); element++) {
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();
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();
381 // trigger at least one class
382 (triggerClasses.begin())->Trigger(1);
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());
394 for (element=shuffle.begin();
395 element!=shuffle.end(); element++) {
396 trigData.TriggerBit(element->Bit(), element->Trigger());
397 //cout << " " << element->Bit() << ":" << element->Trigger();
400 ctpdata.SetTriggers(*(trigData.Data()));
403 for (element=shuffle.begin();
404 element!=shuffle.end() && iResult>=0 && trial<3;
406 int check=ctpdata.CheckTrigger(element->ClassName());
408 cerr << "error avaluating CheckTrigger: class name " << element->ClassName() << " not found" << endl;
412 if (check!=element->Trigger()) {
413 cerr << "error avaluating CheckTrigger, class name " << element->ClassName() << ": expecting " << element->Trigger() << " - got " << check << endl;
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()
426 << std::hex << " (" << trigData.TriggerMask() << ")"
428 cerr << "trigger does not match, expected " << result << endl;
435 expression+=element->ClassName();
437 trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
438 if (trigger!=result) {
439 cout << expression << ": " << element->Trigger()
441 << std::hex << " (" << trigData.TriggerMask() << ")"
443 cerr << "trigger does not match, expected " << result << endl;
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()
457 << std::hex << " (" << trigData.TriggerMask() << ")"
459 cerr << "trigger does not match, expected " << result << endl;
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());
469 trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
470 if (trigger!=result) {
471 cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
473 << std::hex << " (" << trigData.TriggerMask() << ")"
475 cerr << "trigger does not match, expected " << result << endl;
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());
485 trigger=ctpdata.EvaluateCTPTriggerClass(expression.Data(), *trigData.Data());
486 if (trigger!=result) {
487 cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].Trigger()
489 << std::hex << " (" << trigData.TriggerMask() << ")"
491 cerr << "trigger does not match, expected " << result << endl;
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;
506 if (element==triggerClasses.end()) {
507 cerr << "can not find any active trigger class for detector " << detectorid << " enabled in the readout" << endl;
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;
521 detectorReadout.Print();
524 if ((cycle+1)%(nofCycles/5)==0) cout << " " << (100*(cycle+1))/nofCycles << " % done" << endl;
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;
538 /////////////////////////////////////////////////////////////////////////
539 /////////////////////////////////////////////////////////////////////////
543 int main(int /*argc*/, const char** /*argv*/)
546 iResult=testAliHLTCTPData();