]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/BASE/test/testAliHLTComponent.C
Implementing base class methods for easy component configuration:
[u/mrichter/AliRoot.git] / HLT / BASE / test / testAliHLTComponent.C
CommitLineData
cf9cf07e 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_CTPTrigger.C
20 @author Matthias Richter
21 @date
02bc7a5f 22 @brief Test program for the AliHLTComponent base class
cf9cf07e 23 */
24
25#ifndef __CINT__
26#include "TDatime.h"
27#include "TRandom.h"
28#include "AliHLTDataTypes.h"
29#include "AliHLTProcessor.h"
02bc7a5f 30#include "algorithm"
31#include "TObjArray.h"
32#include "TObjString.h"
33#include "TString.h"
cf9cf07e 34#endif
35
02bc7a5f 36using namespace std;
37
cf9cf07e 38class AliHLTTestComponent : public AliHLTProcessor
39{
40public:
02bc7a5f 41 AliHLTTestComponent() :
42 fArguments(),
43 fCurrentArgument(fArguments.begin())
44 {}
45
cf9cf07e 46 ~AliHLTTestComponent() {}
47
48 const char* GetComponentID() {return "TestComponent";};
49 void GetInputDataTypes(AliHLTComponentDataTypeList& list) {list.clear();}
50 AliHLTComponentDataType GetOutputDataType() {return kAliHLTAnyDataType;}
51 void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier) {constBase=0; inputMultiplier=0;}
52 AliHLTComponent* Spawn() {return new AliHLTTestComponent;}
53
02bc7a5f 54 class AliHLTConfigurationArgument {
55 public:
56 AliHLTConfigurationArgument(const char* argument) :
57 fElements(NULL)
58 {
59 TString work=argument;
60 fElements=work.Tokenize(" ");
61 }
62
63 AliHLTConfigurationArgument(const AliHLTConfigurationArgument& src) :
64 fElements(NULL)
65 {
66 if (src.fElements) {
67 fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
68 }
69 }
70
71 ~AliHLTConfigurationArgument() {
72 if (fElements) delete fElements;
73 }
74
75 AliHLTConfigurationArgument& operator=(const AliHLTConfigurationArgument& src) {
76 delete fElements;
77 if (src.fElements) {
78 fElements=dynamic_cast<TObjArray*>(src.fElements->Clone());
79 }
80 return *this;
81 }
82
83 const char* Argument() {
84 if (!fElements) return NULL;
85 return ((TObjString*)fElements->At(0))->GetString().Data();
86 }
87
88 int NofParameters() {
89 if (!fElements) return 0;
90 return fElements->GetEntriesFast()-1;
91 }
92
93 const char* Parameter(int i) {
94 if (!fElements ||
95 fElements->GetEntriesFast()<=i+1) return NULL;
96 return ((TObjString*)fElements->At(i+1))->GetString().Data();
97 }
98
99 bool operator==(const char* string) {
100 if (!fElements) return 0;
101 return (((TObjString*)fElements->At(0))->GetString().CompareTo(string))==0;
102 }
103
104 bool operator!=(const char* string) {
105 return !operator==(string);
106 }
107
108 void Print() {
109 if (!fElements) {
110 cout << "############# empty ############" << endl;
111 return;
112 }
113 cout << " Print: " << Argument() << " with " << NofParameters() << " parameter(s)";
114 for (int n=0; n<NofParameters(); n++) cout << " " << Parameter(n);
115 cout << endl;
116 }
117
118 private:
119 TObjArray* fElements;
120 };
121
122 int ScanConfigurationArgument(int argc, const char** argv) {
123 if (fCurrentArgument==fArguments.end()) return 0;
124 int count=0;
125
126 // check whether it is an argument at all
127 if (*(argv[count])!='-') {
128 cerr << "not a recognized argument: " << argv[count] << endl;
129 return -EINVAL;
130 }
131
132 // check whether the argument matches
133 //fCurrentArgument->Print();
134 if (*fCurrentArgument!=argv[count]) {
135 cerr << "argument sequence does not match: got " << argv[count] << " expected " << fCurrentArgument->Argument() << endl;
136 return -EINVAL;
137 }
138
139 count++;
140 // read parameters
141 if (fCurrentArgument->NofParameters()>0) {
142 if (argc<=count) {
143 cerr << "missing parameter" << endl;
144 return -EPROTO;
145 }
146
147 // implement more checks here
148 count+=fCurrentArgument->NofParameters();
149 }
150 fCurrentArgument++;
151 return count;
152 }
153
154 int FillArgumentVector(const char** arguments, vector<AliHLTConfigurationArgument>& list) {
155 list.clear();
156 for (const char** iter=arguments; *iter!=NULL; iter++) {
157 list.push_back(AliHLTConfigurationArgument(*iter));
158 }
159 return list.size();
160 }
161
162 int FillArgv(vector<AliHLTConfigurationArgument>& list, vector<const char*>& argv) {
163 argv.clear();
164 for (vector<AliHLTConfigurationArgument>::iterator argument=list.begin();
165 argument!=list.end(); argument++) {
166 argv.push_back(argument->Argument());
167 for (int n=0; n<argument->NofParameters(); n++) {
168 argv.push_back(argument->Parameter(n));
169 }
170 }
171 return argv.size();
172 }
173
174 void PrintArgv(int argc, const char** argv) {
175 for (int n=0; n<argc; n++) {
176 cout << " " << n << " : " << argv[n] << endl;
177 }
178 }
179
180 int CheckSequence(const char* sequence[], int mode=0) {
181 int iResult=0;
182 if ((iResult=FillArgumentVector(sequence, fArguments))<0) {
183 cerr << "failed to fill argument vector" << endl;
184 return iResult;
185 }
186 vector<const char*> argv;
187 if (mode==0) {
188 if ((iResult=FillArgv(fArguments, argv))<0) {
189 cerr << "failed to fill argument array" << endl;
190 return iResult;
191 }
192 } else {
193 for (const char** element=sequence; *element!=NULL; element++)
194 argv.push_back(*element);
195 }
196 fCurrentArgument=fArguments.begin();
197 //PrintArgv(argv.size(), &argv[0]);
198 if ((iResult=ConfigureFromArgumentString(argv.size(), &argv[0]))<0) {
199 cerr << "ConfigureFromArgumentString failed " << endl;
200 return iResult;
201 }
202
203 return iResult;
204 }
205
206 int CheckConfigure() {
207 int iResult=0;
208 const char* sequence1[]={"-sequence1","-argument2 5", NULL};
209 if ((iResult=CheckSequence(sequence1))<0) {
210 cerr << "failed checking sequence " << sequence1[0] << endl;
211 return iResult;
212 }
213
214 const char* sequence2[]={"-sequence2","-argument2 5 8", "-argument3 test", NULL};
215 if ((iResult=CheckSequence(sequence2))<0) {
216 cerr << "failed checking sequence in mode 0: " << sequence2[0] << endl;
217 return iResult;
218 }
219
220 if ((iResult=CheckSequence(sequence2, 1))<0) {
221 cerr << "failed checking sequence in mode 1: " << sequence2[0] << endl;
222 return iResult;
223 }
224
225 const char* sequence3[]={"-solenoidBz 5", NULL};
226 if ((iResult=CheckSequence(sequence3))<0) {
227 cerr << "failed checking sequence " << sequence3[0] << endl;
228 return iResult;
229 }
230 return iResult;
231 }
232
233 int InitCTPTest(const char* param) {
234 // this quick test needs to be the functions of the base class to be
235 // defined 'protected'
236 //return ScanECSParam(param);
cf9cf07e 237 //return InitCTPTriggerClasses(param);
02bc7a5f 238 return -ENOSYS;
cf9cf07e 239 }
240
02bc7a5f 241 bool CheckCTP(const char* expression, AliHLTComponentTriggerData* data) {
cf9cf07e 242 return EvaluateCTPTriggerClass(expression, *data);
243 }
244
245 class AliHLTCTPTriggerClass {
246 public:
247 AliHLTCTPTriggerClass() : fBit(~(unsigned)0), fClassName(""), fTrigger(false) {}
248 ~AliHLTCTPTriggerClass() {}
249
250 bool Valid() {return fBit!=~(unsigned)0;}
251 unsigned Bit() {return fBit;}
252 void Bit(unsigned bit) {fBit=bit;}
253 bool Trigger() {return fTrigger;}
254 void Trigger(bool trigger) {fTrigger=trigger;}
255 const char* ClassName() {return fClassName.c_str();}
256 void ClassName(const char* classname) {fClassName=classname;}
257 private:
258 unsigned fBit;
259 string fClassName;
260 bool fTrigger;
261 };
262protected:
263 int DoInit(int /*argc*/, const char** /*argv*/) {
264 return 0;
265 }
266
267 int DoDeinit() {
268 return 0;
269 }
270
271 int DoEvent( const AliHLTComponentEventData& /*evtData*/,
272 AliHLTComponentTriggerData& /*trigData*/) {
273 return 0;
274 }
02bc7a5f 275private:
276 vector<AliHLTConfigurationArgument> fArguments;
277 vector<AliHLTConfigurationArgument>::iterator fCurrentArgument;
cf9cf07e 278};
279
280class AliHLTTriggerDataAccess
281{
282public:
283 AliHLTTriggerDataAccess()
284 : fData(NULL)
285 , fEventData(NULL)
286 , fCDH(NULL)
287 , fMine(NULL)
288 {
289 unsigned size=sizeof(AliHLTComponentTriggerData) + sizeof(AliHLTEventTriggerData);
290 fMine=new Byte_t[size];
291 memset(fMine, 0, size);
292 AliHLTComponentTriggerData* data=reinterpret_cast<AliHLTComponentTriggerData*>(fMine);
293 data->fData=fMine+sizeof(AliHLTComponentTriggerData);
294 Set(data);
295 }
296
297 AliHLTTriggerDataAccess(AliHLTComponentTriggerData* pData)
298 : fData(NULL)
299 , fEventData(NULL)
300 , fCDH(NULL)
301 , fMine(NULL)
302 {
303 if (fMine) delete [] fMine;
304 fMine=NULL;
305 Set(pData);
306 }
307
308 ~AliHLTTriggerDataAccess(){
309 if (fMine) delete [] fMine;
310 fMine=NULL;
311 fData=NULL;
312 fEventData=NULL;
313 fCDH=NULL;
314 }
315
316 AliHLTComponentTriggerData* Data() {return fData;}
317
318 Long64_t TriggerMask() {
319 Long64_t mask=0;
320 if (fCDH) {
321 mask=fCDH[6];
322 mask<<=32;
323 mask|=fCDH[5];
324 }
325 return mask;
326 }
327
328 int Set(AliHLTComponentTriggerData* data) {
329 fData=data;
330 fData->fDataSize=sizeof(AliHLTEventTriggerData);
331 fEventData=reinterpret_cast<AliHLTEventTriggerData*>(fData->fData);
332 fCDH=fEventData->fCommonHeader;
333 return 0;
334 }
335
336 int ResetCDH() {
337 if (fCDH) {
338 memset(fCDH, 0, 32);
339 }
340 return 0;
341 }
342
343 int TriggerBit(unsigned bit, bool set) {
344 if ((int)bit>=gkNCTPTriggerClasses) return -EINVAL;
345 if (!fCDH) return -ENODATA;
346
347 int word=5;
348 if (bit>=32) {
349 word++;
350 bit-=32;
351 }
352 if (set)
353 fCDH[word]|=(UInt_t)0x1<<bit;
354 else
355 fCDH[word]&=~((UInt_t)0x1<<bit);
356
357 return bit;
358 }
359
360private:
361 AliHLTTriggerDataAccess(const AliHLTTriggerDataAccess&);
362 AliHLTTriggerDataAccess& operator=(const AliHLTTriggerDataAccess&);
363
364 AliHLTComponentTriggerData* fData;
365 AliHLTEventTriggerData* fEventData;
366 AliHLTUInt32_t* fCDH;
367 Byte_t* fMine;
368};
369
02bc7a5f 370/////////////////////////////////////////////////////////////////////////
371/////////////////////////////////////////////////////////////////////////
372//
373// setup of the CTP test
374
cf9cf07e 375/**
376 * Get a random number in the given range.
377 */
378int GetRandom(int min, int max)
379{
380 if (max-min<2) return min;
381 static TRandom rand;
382 static bool seedSet=false;
383 if (!seedSet) {
384 TDatime dt;
385 rand.SetSeed(dt.Get());
386 seedSet=true;
387 }
388 return min+rand.Integer(max-min);
389}
390
391/**
392 * Generate a random name of given length
393 */
394string GenerateTriggerClassName(int length)
395{
396 string tcn;
397 for (int i=0; i<length; i++) {
398 unsigned char c=GetRandom(48, 83);
399 if (c>57) c+=7;
400 tcn+=c;
401 }
402 return tcn;
403}
404
405/**
406 * Generate an array of trigger classes.
407 * The array has the specified size but the number antries which are actually
408 * filled is randomized.
409 */
410int GenerateTriggerClasses(int size, vector<AliHLTTestComponent::AliHLTCTPTriggerClass>& classes)
411{
412 classes.clear();
413 classes.resize(size);
414 unsigned count=GetRandom(4, size>16?size/2:size);
415 for (unsigned i=0; i<count; i++) {
416 int bit=0;
417 do {
418 bit=GetRandom(0, size);
419 } while (classes[bit].Valid());
420 classes[bit].Bit(bit);
421 classes[bit].ClassName((GenerateTriggerClassName(GetRandom(5,15))).c_str());
422 }
423 return classes.size();
424}
425
02bc7a5f 426/**
427 * Test the CTP trigger tools
428 * The base class is initialized with an ECS string of randomly defined trigger
429 * classes consisting of random bits and names. Than a couple of expressions is
430 * test for various random bit patterns.
431 */
432int testCTPTrigger()
cf9cf07e 433{
02bc7a5f 434 cout << "checking CTP functionality of the base class" << endl;
cf9cf07e 435 int iResult=0;
436 vector<AliHLTTestComponent::AliHLTCTPTriggerClass> triggerClasses;
437 if (GenerateTriggerClasses(GetRandom(5,gkNCTPTriggerClasses), triggerClasses)<=0) {
438 return -1;
439 }
440
441 TString parameter="CONFIGURE;CTP_TRIGGER_CLASS=";
442 vector<AliHLTTestComponent::AliHLTCTPTriggerClass>::iterator element=triggerClasses.begin();
443 while (element!=triggerClasses.end()) {
444 if (!element->Valid()) {
445 element=triggerClasses.erase(element);
446 continue;
447 }
448 if (!parameter.EndsWith("=")) parameter+=",";
449 parameter+=element->Bit(); parameter+=":";
450 parameter+=element->ClassName(); parameter+=":";
451 parameter+=0;
452 element++;
453 }
454 parameter+=";HLT_MODE=A;RUN_NO=0";
455
456 AliHLTTestComponent component;
457 component.SetGlobalLoggingLevel(kHLTLogDefault);
02bc7a5f 458 if ((iResult=component.InitCTPTest(parameter.Data()))<0) {
459 cerr << "InitCTPTest failed :" << iResult << endl;
460 return iResult;
461 }
cf9cf07e 462
463 AliHLTTriggerDataAccess trigData;
464 for (int cycle=0; cycle<500 && iResult>=0; cycle++) {
465 for (element=triggerClasses.begin();
466 element!=triggerClasses.end(); element++) {
467 element->Trigger(GetRandom(0,100)>50);
468 }
469
470 vector<AliHLTTestComponent::AliHLTCTPTriggerClass> shuffle;
471 shuffle.assign(triggerClasses.begin(), triggerClasses.end());
472 for (unsigned int trial=0; trial<2*triggerClasses.size() && iResult>=0; trial++) {
473 random_shuffle(shuffle.begin(), shuffle.end());
474
475 bool result=0;
476 bool trigger=0;
477 TString expression;
478 trigData.ResetCDH();
479 for (element=shuffle.begin();
480 element!=shuffle.end(); element++) {
481 trigData.TriggerBit(element->Bit(), element->Trigger());
482 }
483
484 // single class
485 for (element=shuffle.begin();
486 element!=shuffle.end() && iResult>=0 && trial<3;
487 element++) {
488 // is
489 result=element->Trigger();
490 expression=element->ClassName();
02bc7a5f 491 trigger=component.CheckCTP(expression.Data(), trigData.Data());
cf9cf07e 492 if (trigger!=result) {
493 cout << expression << ": " << element->Trigger()
494 << "->" << trigger
495 << std::hex << " (" << trigData.TriggerMask() << ")"
496 << endl;
497 cerr << "trigger does not match, expected " << result << endl;
498 iResult=-1;
499 break;
500 }
501
502 // is not
503 expression="!";
504 expression+=element->ClassName();
505 result=!result;
02bc7a5f 506 trigger=component.CheckCTP(expression.Data(), trigData.Data());
cf9cf07e 507 if (trigger!=result) {
508 cout << expression << ": " << element->Trigger()
509 << "->" << trigger
510 << std::hex << " (" << trigData.TriggerMask() << ")"
511 << endl;
512 cerr << "trigger does not match, expected " << result << endl;
513 iResult=-1;
514 break;
515 }
516 }
517
518 // OR
519 result=shuffle[0].Trigger() || shuffle[1].Trigger() || shuffle[2].Trigger();
520 expression.Form("%s || %s || %s",
521 shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
02bc7a5f 522 trigger=component.CheckCTP(expression.Data(), trigData.Data());
cf9cf07e 523 if (trigger!=result) {
524 cout << expression << ": " << shuffle[0].Trigger() << shuffle[1].Trigger() << shuffle[2].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 // AND
534 result=shuffle[0].Trigger() && shuffle[1].Trigger() && shuffle[2].Trigger();
535 expression.Form("%s && %s && %s",
536 shuffle[0].ClassName(), shuffle[1].ClassName(), shuffle[2].ClassName());
537
02bc7a5f 538 trigger=component.CheckCTP(expression.Data(), trigData.Data());
cf9cf07e 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 // mixed OR/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
02bc7a5f 554 trigger=component.CheckCTP(expression.Data(), trigData.Data());
cf9cf07e 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 }
566 if (iResult<0) {
567 cerr << "check failed, dumping info" << endl;
568 cerr << "ECS param: " << parameter << endl;
569 for (element=triggerClasses.begin();
570 element!=triggerClasses.end(); element++) {
571 cerr << element->Trigger() << " " << element->Bit() << ": " << element->ClassName() << endl;
572 }
573 }
574 return iResult;
575}
576
02bc7a5f 577/////////////////////////////////////////////////////////////////////////
578/////////////////////////////////////////////////////////////////////////
579//
580// setup of the Configure test
581int testConfigure()
582{
583 cout << "checking common configuration tools of the base class" << endl;
584 AliHLTTestComponent component;
585 return component.CheckConfigure();
586}
587
588/////////////////////////////////////////////////////////////////////////
589/////////////////////////////////////////////////////////////////////////
590//
591// main functions
592
593int testAliHLTComponent()
594{
595 int iResult=0;
596 //if ((iResult=testCTPTrigger())<0) return iResult;
597 if ((iResult=testConfigure())<0) return iResult;
598 return iResult;
599}
600
cf9cf07e 601int main(int /*argc*/, const char** /*argv*/)
602{
603 int iResult=0;
02bc7a5f 604 iResult=testAliHLTComponent();
cf9cf07e 605 return iResult;
606}