]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/trigger/test/testTriggerDomain.C
Adding the trigger menu for the HLT global trigger.
[u/mrichter/AliRoot.git] / HLT / trigger / test / testTriggerDomain.C
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * ALICE Experiment at CERN, All rights reserved.                         *
4  *                                                                        *
5  * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
6  *                  for The ALICE HLT Project.                            *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /**
18  * @file   testGlobalTriggerComponent.C
19  * @author Artur Szostak <artursz@iafrica.com>
20  * @date   4 Dec 2008
21  *
22  * This macro is used to test the behaviour of the AliHLTTriggerDomain class.
23  * We specifically check that the AliHLTTriggerDomain operators behave correctly
24  * as set operations.
25  */
26
27 #if defined(__CINT__) && (! defined(__MAKECINT__))
28 #error This macro must be compiled. Try running as testTriggerDomain.C++
29 #endif
30
31 #include "Riostream.h"
32 #include "TSystem.h"
33 #include "TClassTable.h"
34 #include "TRandom3.h"
35 #include "TObjArray.h"
36 #include "AliHLTTriggerDomain.h"
37 #include "AliHLTDomainEntry.h"
38
39 const int N = 6;
40 const char* datatype[N] = {"*******", "AAAAAAAA", "BBBBBBBB", "CCCCCCCC", "DDDDDDDD", "EEEEEEEE"};
41 const char* origin[N] = {"***", "xxxx", "yyyy", "zzzz", "wwww", "uuuu"};
42 int spec[N] = {0, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555};
43
44 /**
45  * Randomly builds a trigger domain from the various data types, origins and specifications.
46  * \param domain <i>[out]</i> The new constructed domain is filled into this output variable.
47  * \param opcount <i>[in]</i> The number of Add / Remove operations to apply to the domain.
48  */
49 void BuildTriggerDomain(AliHLTTriggerDomain& domain, int opcount = 100)
50 {
51         domain.Clear();
52         for (int i = 0; i < opcount; i++)
53         {
54                 // Make sure not to use the last data type, origin or specification in
55                 // the respective lists because we want to use them later to test the
56                 // matching against wild card values.
57                 int itype = gRandom->Integer(N-1);
58                 int iorigin = gRandom->Integer(N-1);
59                 int ispec = gRandom->Integer(N-1);
60                 if (gRandom->Integer(2) == 0)
61                 {
62                         if (spec[ispec] == 0)
63                                 domain.Add(datatype[itype], origin[iorigin]);
64                         else
65                                 domain.Add(datatype[itype], origin[iorigin], spec[ispec]);
66                 }
67                 else
68                 {
69                         if (spec[ispec] == 0)
70                                 domain.Remove(datatype[itype], origin[iorigin]);
71                         else
72                                 domain.Remove(datatype[itype], origin[iorigin], spec[ispec]);
73                 }
74         }
75 }
76
77 /**
78  * Returns the string representation of the data type.
79  */
80 const char* TypeToString(const AliHLTComponentDataType& type)
81 {
82         static char str[kAliHLTComponentDataTypefIDsize+1];
83         for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
84         {
85                 str[i] = type.fID[i];
86         }
87         return str;
88 }
89
90 /**
91  * Returns the string representation of the data origin.
92  */
93 const char* OriginToString(const AliHLTComponentDataType& type)
94 {
95         static char str[kAliHLTComponentDataTypefOriginSize+1];
96         for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
97         {
98                 str[i] = type.fOrigin[i];
99         }
100         return str;
101 }
102
103 /**
104  * Checks to see if the domain is correctly constructed compared to the list of entries
105  * that were applied to the domain.
106  * \param entryList <i>[out]</i> The list of entries that were used to construct the domain.
107  * \param domain <i>[in]</i> The trigger domain to check.
108  */
109 bool DomainOK(const TObjArray& entryList, const AliHLTTriggerDomain& domain)
110 {
111         for (int i = 1; i < N; i++)
112         for (int j = 1; j < N; j++)
113         for (int k = 1; k < N; k++)
114         {
115                 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
116                 AliHLTComponentBlockData block;
117                 block.fDataType = entry;
118                 block.fSpecification = spec[k];
119                 
120                 bool result = false;
121                 bool result2 = false;
122                 for (int n = 0; n < entryList.GetEntriesFast(); n++)
123                 {
124                         const AliHLTDomainEntry* rule = static_cast<const AliHLTDomainEntry*>( entryList[n] );
125                         if (*rule == entry) result = rule->Inclusive();
126                         if (*rule == &block) result2 = rule->Inclusive();
127                 }
128                 
129                 bool containsResult = domain.Contains(entry);
130                 bool includeResult = domain.IncludeInReadout(&block);
131                 if (containsResult != result or includeResult != result2)
132                 {
133                         cout << "FAILED DomainOK test!" << endl;
134                         cout << "==============================================================================" << endl;
135                         cout << "Dump of how AliHLTTriggerDomain was built:" << endl;
136                         cout << "  AliHLTTriggerDomain domain;" << endl;
137                         for (int n = 0; n < entryList.GetEntriesFast(); n++)
138                         {
139                                 const AliHLTDomainEntry* rule = static_cast<const AliHLTDomainEntry*>( entryList[n] );
140                                 const char* opstr = (rule->Exclusive() ? "Remove" : "Add");
141                                 if (rule->IsValidSpecification())
142                                 {
143                                         cout << "  domain." << opstr << "(\"" << TypeToString(rule->DataType())
144                                                 << "\", \"" << OriginToString(rule->DataType())
145                                                 << "\", 0x" << hex << rule->Specification() << dec
146                                                 << ");" << endl;
147                                 }
148                                 else
149                                 {
150                                         cout << "  domain." << opstr << "(\"" << TypeToString(rule->DataType())
151                                                 << "\", \"" << OriginToString(rule->DataType())
152                                                 << "\");" << endl;
153                                 }
154                         }
155                         cout << "==============================================================================" << endl;
156                         cout << "Dump of the trigger domain contents:" << endl;
157                         domain.Print();
158                         cout << "==============================================================================" << endl;
159                 }
160                 if (containsResult != result)
161                 {
162                         cout << "Failed for entry = ";
163                         entry.Print();
164                         cout << "Result of domain.Contains(entry) == " << containsResult << endl;
165                         cout << " Expected domain.Contains(entry) == " << result << endl;
166                         return false;
167                 }
168                 if (includeResult != result2)
169                 {
170                         cout << "Failed for block: type = " << TypeToString(block.fDataType)
171                                 << ", origin = " << OriginToString(block.fDataType)
172                                 << ", specification = " << hex << block.fSpecification << dec;
173                         cout << "Result of domain.IncludeInReadout(&block) == " << includeResult << endl;
174                         cout << " Expected domain.IncludeInReadout(&block) == " << result2 << endl;
175                         return false;
176                 }
177         }
178         
179         return true;
180 }
181
182 /**
183  * Randomly builds a trigger domain and tests the Add / Remove operations of the
184  * AliHLTTriggerDomain class.
185  * \param opcount <i>[in]</i> The number of Add / Remove operations to use to
186  *     build the domain.
187  */
188 bool AddRemoveOK(int opcount = 100)
189 {
190         TObjArray entryList;
191         entryList.SetOwner(kTRUE);
192         AliHLTTriggerDomain domain;
193         
194         for (int i = 0; i < opcount; i++)
195         {
196                 // Make sure not to use the last data type, origin or specification in
197                 // the respective lists because we want to use them later to test the
198                 // matching against wild card values.
199                 int itype = gRandom->Integer(N-1);
200                 int iorigin = gRandom->Integer(N-1);
201                 int ispec = gRandom->Integer(N-1);
202                 if (gRandom->Integer(2) == 0)
203                 {
204                         if (spec[ispec] == 0)
205                         {
206                                 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin]));
207                                 domain.Add(datatype[itype], origin[iorigin]);
208                         }
209                         else
210                         {
211                                 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin], spec[ispec]));
212                                 domain.Add(datatype[itype], origin[iorigin], spec[ispec]);
213                         }
214                 }
215                 else
216                 {
217                         if (spec[ispec] == 0)
218                         {
219                                 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin]));
220                                 domain.Remove(datatype[itype], origin[iorigin]);
221                         }
222                         else
223                         {
224                                 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin], spec[ispec]));
225                                 domain.Remove(datatype[itype], origin[iorigin], spec[ispec]);
226                         }
227                 }
228         }
229         
230         if (not DomainOK(entryList, domain)) return false;
231         
232         return true;
233 }
234
235
236 #define DefOperation(name, expr, logicExpr) \
237         class name \
238         { \
239         public: \
240                 static const char* Name() \
241                 { \
242                         return #name; \
243                 } \
244                 static const char* Expression() \
245                 { \
246                         return #expr; \
247                 } \
248                 static AliHLTTriggerDomain Apply(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
249                 { \
250                         return expr; \
251                 } \
252                 static bool ExpectedResult(bool a, const bool b) \
253                 { \
254                         return logicExpr; \
255                 } \
256         };
257
258
259 DefOperation( OpComplement, ~a,    !a       );
260 DefOperation( OpUnion,      a | b, a | b    );
261 DefOperation( OpIntersect,  a & b, a & b    );
262 DefOperation( OpXor,        a ^ b, a ^ b    );
263 DefOperation( OpPlus,       a + b, a | b    );
264 DefOperation( OpMinus,      a - b, a & (!b) );
265
266 /**
267  * Randomly builds two trigger domains and tests a overloaded operator of the
268  * AliHLTTriggerDomain class.
269  * \param opcount <i>[in]</i> The number of Add / Remove operations to use to
270  *     build the domains.
271  */
272 template <class Op>
273 bool OperatorOK(int opcount = 100)
274 {
275         AliHLTTriggerDomain d1;
276         BuildTriggerDomain(d1, opcount);
277         AliHLTTriggerDomain d2;
278         BuildTriggerDomain(d2, opcount);
279         AliHLTTriggerDomain d3 = Op::Apply(d1, d2);
280         
281         for (int i = 1; i < N; i++)
282         for (int j = 1; j < N; j++)
283         for (int k = 1; k < N; k++)
284         {
285                 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
286                 bool d1Result = d1.Contains(entry);
287                 bool d2Result = d2.Contains(entry);
288                 bool d3Result = d3.Contains(entry);
289                 bool d3ExpectedResult = Op::ExpectedResult(d1Result, d2Result);
290                 if (d3Result != d3ExpectedResult)
291                 {
292                         cout << "FAILED OperatorOK<" << Op::Name() << "> test!" << endl;
293                         cout << "==============================================================================" << endl;
294                         cout << "Dump of the trigger domain a contents:" << endl;
295                         d1.Print();
296                         cout << "==============================================================================" << endl;
297                         cout << "Dump of the trigger domain b contents:" << endl;
298                         d2.Print();
299                         cout << "==============================================================================" << endl;
300                         cout << "Dump of the trigger domain c = " << Op::Expression() << " contents:" << endl;
301                         d3.Print();
302                         cout << "==============================================================================" << endl;
303                         cout << "Failed for entry = ";
304                         entry.Print();
305                         cout << "Result of c.Contains(entry) == " << d3Result << endl;
306                         cout << " Expected c.Contains(entry) == " << d3ExpectedResult << endl;
307                         return false;
308                 }
309         }
310         
311         return true;
312 }
313
314
315 #define DefEqualExprCheck(name, expr1, expr2) \
316         class name \
317         { \
318         public: \
319                 static const char* Name() \
320                 { \
321                         return #name; \
322                 } \
323                 static const char* Expr1() \
324                 { \
325                         return #expr1; \
326                 } \
327                 static const char* Expr2() \
328                 { \
329                         return #expr2; \
330                 } \
331                 static AliHLTTriggerDomain Apply1(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
332                 { \
333                         return expr1; \
334                 } \
335                 static AliHLTTriggerDomain Apply2(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
336                 { \
337                         return expr2; \
338                 } \
339         };
340
341
342 DefEqualExprCheck( XorExprCheck1,  a ^ b, (a | b) - (a & b)             );
343 DefEqualExprCheck( XorExprCheck2,  a ^ b, (a - (a & b)) | (b - (a & b)) );
344 DefEqualExprCheck( MinusExprCheck1, a - b, a & (a ^ b)                  );
345 DefEqualExprCheck( MinusExprCheck2, a - b, a & ~(a & b)                 );
346
347 /**
348  * Randomly builds two trigger domains and tests two expressions applied to the
349  * domains that should be equivalent.
350  * \param opcount <i>[in]</i> The number of Add / Remove operations to use to
351  *     build the domains.
352  */
353 template <class Expr>
354 bool EquivalentExpressionsOK(int opcount = 100)
355 {
356         AliHLTTriggerDomain d1;
357         BuildTriggerDomain(d1, opcount);
358         AliHLTTriggerDomain d2;
359         BuildTriggerDomain(d2, opcount);
360         AliHLTTriggerDomain d3 = Expr::Apply1(d1, d2);
361         AliHLTTriggerDomain d4 = Expr::Apply2(d1, d2);
362         
363         for (int i = 1; i < N; i++)
364         for (int j = 1; j < N; j++)
365         for (int k = 1; k < N; k++)
366         {
367                 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
368                 bool d3Result = d3.Contains(entry);
369                 bool d4Result = d4.Contains(entry);
370                 if (d3Result != d4Result)
371                 {
372                         cout << "FAILED EquivalentExpressionsOK<" << Expr::Name() << "> test!" << endl;
373                         cout << "==============================================================================" << endl;
374                         cout << "Dump of the trigger domain a contents:" << endl;
375                         d1.Print();
376                         cout << "==============================================================================" << endl;
377                         cout << "Dump of the trigger domain b contents:" << endl;
378                         d2.Print();
379                         cout << "==============================================================================" << endl;
380                         cout << "Dump of the trigger domain c = " << Expr::Expr1() << " contents:" << endl;
381                         d3.Print();
382                         cout << "==============================================================================" << endl;
383                         cout << "Dump of the trigger domain d = " << Expr::Expr2() << " contents:" << endl;
384                         d3.Print();
385                         cout << "==============================================================================" << endl;
386                         cout << "Failed for entry = ";
387                         entry.Print();
388                         cout << "Result of c.Contains(entry) == " << d3Result << endl;
389                         cout << "Result of d.Contains(entry) == " << d4Result << endl;
390                         cout << "But the results should be the same." << endl;
391                         return false;
392                 }
393         }
394         
395         return true;
396 }
397
398
399 #define DefTest(name, routine, description) \
400         class name \
401         { \
402         public: \
403                 static bool Run(int opcount) \
404                 { \
405                         return routine(opcount); \
406                 } \
407                 static const char* Description() \
408                 { \
409                         return description; \
410                 } \
411         }
412
413 // Declarations of the different tests.
414 DefTest(AddRemoveTest,           AddRemoveOK,              "AliHLTTriggerDomain::Add and AliHLTTriggerDomain::Remove");
415 DefTest(ComplementOperationTest, OperatorOK<OpComplement>, "operator ~a");
416 DefTest(UnionOperationTest,      OperatorOK<OpUnion>,      "operator a | b");
417 DefTest(IntersectOperationTest,  OperatorOK<OpIntersect>,  "operator a & b");
418 DefTest(XorOperationTest,        OperatorOK<OpXor>,        "operator a ^ b");
419 DefTest(PlusOperationTest,       OperatorOK<OpPlus>,       "operator a + b");
420 DefTest(MinusOperationTest,      OperatorOK<OpMinus>,      "operator a - b");
421 DefTest(XorExpressionTest1,   EquivalentExpressionsOK<XorExprCheck1>,   "expression a ^ b == (a | b) - (a & b)");
422 DefTest(XorExpressionTest2,   EquivalentExpressionsOK<XorExprCheck2>,   "expression a ^ b == (a - (a & b)) | (b - (a & b))");
423 DefTest(MinusExpressionTest1, EquivalentExpressionsOK<MinusExprCheck1>, "expression a - b == a & (a ^ b)");
424 DefTest(MinusExpressionTest2, EquivalentExpressionsOK<MinusExprCheck2>, "expression a - b == a & ~(a & b)");
425
426 /**
427  * Routine to run an individual test.
428  * \param print  Should information be printed showing the progress of testing.
429  * \param numOfTests  The number of test iterations to run.
430  */
431 template <class Test>
432 bool Run(bool print = true, int numOfTests = 100)
433 {
434         if (print) cout << "Testing " << Test::Description() << " ..." << endl;
435         for (int i = 0; i < numOfTests; i++)
436         {
437                 if (not Test::Run(10)) return false;
438                 if (not Test::Run(100)) return false;
439                 if (not Test::Run(1000)) return false;
440                 if (print and ((i+1) % (numOfTests / 10) == 0))
441                 {
442                         cout << "  Completed " << ((i+1) * 100 / numOfTests) << "%" << endl;
443                 }
444         }
445         return true;
446 }
447
448 /**
449  * This is the top level testing method which calls individual tests.
450  * \param print  Should information be printed showing the progress of testing.
451  * \param numOfTests  The number of test iterations to run.
452  * \param seed  The random number seed to use.
453  */
454 bool testTriggerDomain(bool print = true, int numOfTests = 100, int seed = 0)
455 {
456         if (gClassTable->GetID("AliHLTDomainEntry") < 0)
457         {
458                 gSystem->Load("libAliHLTTrigger.so");
459         }
460         
461         gRandom->SetSeed(seed);
462         
463         if (not Run<AddRemoveTest>(print, numOfTests)) return false;
464         if (not Run<ComplementOperationTest>(print, numOfTests)) return false;
465         if (not Run<UnionOperationTest>(print, numOfTests)) return false;
466         if (not Run<IntersectOperationTest>(print, numOfTests)) return false;
467         if (not Run<XorOperationTest>(print, numOfTests)) return false;
468         if (not Run<PlusOperationTest>(print, numOfTests)) return false;
469         if (not Run<MinusOperationTest>(print, numOfTests)) return false;
470         if (not Run<XorExpressionTest1>(print, numOfTests)) return false;
471         if (not Run<XorExpressionTest2>(print, numOfTests)) return false;
472         if (not Run<MinusExpressionTest1>(print, numOfTests)) return false;
473         if (not Run<MinusExpressionTest2>(print, numOfTests)) return false;
474         
475         return true;
476 }
477
478 #ifndef __MAKECINT__
479
480 int main(int /*argc*/, const char** /*argv*/)
481 {
482         bool resultOk = testTriggerDomain();
483         if (not resultOk) return 1;
484         return 0;
485 }
486
487 #endif // __MAKECINT__
488