1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * ALICE Experiment at CERN, All rights reserved. *
5 * Primary Authors: Artur Szostak <artursz@iafrica.com> *
6 * for The ALICE HLT Project. *
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 **************************************************************************/
18 * @file testGlobalTriggerComponent.C
19 * @author Artur Szostak <artursz@iafrica.com>
22 * This macro is used to test the behaviour of the AliHLTTriggerDomain class.
23 * We specifically check that the AliHLTTriggerDomain operators behave correctly
27 #if defined(__CINT__) && (! defined(__MAKECINT__))
28 #error This macro must be compiled. Try running as testTriggerDomain.C++
31 #include "Riostream.h"
33 #include "TClassTable.h"
35 #include "TObjArray.h"
36 #include "AliHLTTriggerDomain.h"
37 #include "AliHLTDomainEntry.h"
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};
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.
49 void BuildTriggerDomain(AliHLTTriggerDomain& domain, int opcount = 100)
52 for (int i = 0; i < opcount; i++)
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)
63 domain.Add(datatype[itype], origin[iorigin]);
65 domain.Add(datatype[itype], origin[iorigin], spec[ispec]);
70 domain.Remove(datatype[itype], origin[iorigin]);
72 domain.Remove(datatype[itype], origin[iorigin], spec[ispec]);
78 * Returns the string representation of the data type.
80 const char* TypeToString(const AliHLTComponentDataType& type)
82 static char str[kAliHLTComponentDataTypefIDsize+1];
83 for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
91 * Returns the string representation of the data origin.
93 const char* OriginToString(const AliHLTComponentDataType& type)
95 static char str[kAliHLTComponentDataTypefOriginSize+1];
96 for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
98 str[i] = type.fOrigin[i];
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.
109 bool DomainOK(const TObjArray& entryList, const AliHLTTriggerDomain& domain)
111 for (int i = 1; i < N; i++)
112 for (int j = 1; j < N; j++)
113 for (int k = 1; k < N; k++)
115 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
116 AliHLTComponentBlockData block;
117 block.fDataType = entry;
118 block.fSpecification = spec[k];
121 bool result2 = false;
122 for (int n = 0; n < entryList.GetEntriesFast(); n++)
124 const AliHLTDomainEntry* rule = static_cast<const AliHLTDomainEntry*>( entryList[n] );
125 if (*rule == entry) result = rule->Inclusive();
126 if (*rule == &block) result2 = rule->Inclusive();
129 bool containsResult = domain.Contains(entry);
130 bool includeResult = domain.IncludeInReadout(&block);
131 if (containsResult != result or includeResult != result2)
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++)
139 const AliHLTDomainEntry* rule = static_cast<const AliHLTDomainEntry*>( entryList[n] );
140 const char* opstr = (rule->Exclusive() ? "Remove" : "Add");
141 if (rule->IsValidSpecification())
143 cout << " domain." << opstr << "(\"" << TypeToString(rule->DataType())
144 << "\", \"" << OriginToString(rule->DataType())
145 << "\", 0x" << hex << rule->Specification() << dec
150 cout << " domain." << opstr << "(\"" << TypeToString(rule->DataType())
151 << "\", \"" << OriginToString(rule->DataType())
155 cout << "==============================================================================" << endl;
156 cout << "Dump of the trigger domain contents:" << endl;
158 cout << "==============================================================================" << endl;
160 if (containsResult != result)
162 cout << "Failed for entry = ";
164 cout << "Result of domain.Contains(entry) == " << containsResult << endl;
165 cout << " Expected domain.Contains(entry) == " << result << endl;
168 if (includeResult != result2)
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;
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
188 bool AddRemoveOK(int opcount = 100)
191 entryList.SetOwner(kTRUE);
192 AliHLTTriggerDomain domain;
194 for (int i = 0; i < opcount; i++)
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)
204 if (spec[ispec] == 0)
206 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin]));
207 domain.Add(datatype[itype], origin[iorigin]);
211 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin], spec[ispec]));
212 domain.Add(datatype[itype], origin[iorigin], spec[ispec]);
217 if (spec[ispec] == 0)
219 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin]));
220 domain.Remove(datatype[itype], origin[iorigin]);
224 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin], spec[ispec]));
225 domain.Remove(datatype[itype], origin[iorigin], spec[ispec]);
230 if (not DomainOK(entryList, domain)) return false;
236 #define DefOperation(name, expr, logicExpr) \
240 static const char* Name() \
244 static const char* Expression() \
248 static AliHLTTriggerDomain Apply(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
252 static bool ExpectedResult(bool a, const bool b) \
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) );
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
273 bool OperatorOK(int opcount = 100)
275 AliHLTTriggerDomain d1;
276 BuildTriggerDomain(d1, opcount);
277 AliHLTTriggerDomain d2;
278 BuildTriggerDomain(d2, opcount);
279 AliHLTTriggerDomain d3 = Op::Apply(d1, d2);
281 for (int i = 1; i < N; i++)
282 for (int j = 1; j < N; j++)
283 for (int k = 1; k < N; k++)
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)
292 cout << "FAILED OperatorOK<" << Op::Name() << "> test!" << endl;
293 cout << "==============================================================================" << endl;
294 cout << "Dump of the trigger domain a contents:" << endl;
296 cout << "==============================================================================" << endl;
297 cout << "Dump of the trigger domain b contents:" << endl;
299 cout << "==============================================================================" << endl;
300 cout << "Dump of the trigger domain c = " << Op::Expression() << " contents:" << endl;
302 cout << "==============================================================================" << endl;
303 cout << "Failed for entry = ";
305 cout << "Result of c.Contains(entry) == " << d3Result << endl;
306 cout << " Expected c.Contains(entry) == " << d3ExpectedResult << endl;
315 #define DefEqualExprCheck(name, expr1, expr2) \
319 static const char* Name() \
323 static const char* Expr1() \
327 static const char* Expr2() \
331 static AliHLTTriggerDomain Apply1(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
335 static AliHLTTriggerDomain Apply2(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
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) );
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
353 template <class Expr>
354 bool EquivalentExpressionsOK(int opcount = 100)
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);
363 for (int i = 1; i < N; i++)
364 for (int j = 1; j < N; j++)
365 for (int k = 1; k < N; k++)
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)
372 cout << "FAILED EquivalentExpressionsOK<" << Expr::Name() << "> test!" << endl;
373 cout << "==============================================================================" << endl;
374 cout << "Dump of the trigger domain a contents:" << endl;
376 cout << "==============================================================================" << endl;
377 cout << "Dump of the trigger domain b contents:" << endl;
379 cout << "==============================================================================" << endl;
380 cout << "Dump of the trigger domain c = " << Expr::Expr1() << " contents:" << endl;
382 cout << "==============================================================================" << endl;
383 cout << "Dump of the trigger domain d = " << Expr::Expr2() << " contents:" << endl;
385 cout << "==============================================================================" << endl;
386 cout << "Failed for entry = ";
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;
399 #define DefTest(name, routine, description) \
403 static bool Run(int opcount) \
405 return routine(opcount); \
407 static const char* Description() \
409 return description; \
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)");
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.
431 template <class Test>
432 bool Run(bool print = true, int numOfTests = 100)
434 if (print) cout << "Testing " << Test::Description() << " ..." << endl;
435 for (int i = 0; i < numOfTests; i++)
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))
442 cout << " Completed " << ((i+1) * 100 / numOfTests) << "%" << endl;
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.
454 bool testTriggerDomain(bool print = true, int numOfTests = 100, int seed = 0)
456 if (gClassTable->GetID("AliHLTDomainEntry") < 0)
458 gSystem->Load("libAliHLTTrigger.so");
461 gRandom->SetSeed(seed);
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;
480 int main(int /*argc*/, const char** /*argv*/)
482 bool resultOk = testTriggerDomain();
483 if (not resultOk) return 1;
487 #endif // __MAKECINT__