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 [out] domain The new constructed domain is filled into this output variable.
47 * \param [in] opcount 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 [out] entryList The list of entries that were used to construct the domain.
107 * \param [in] domain 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 [in] opcount The number of Add / Remove operations to use to build the domain.
187 bool AddRemoveOK(int opcount = 100)
190 entryList.SetOwner(kTRUE);
191 AliHLTTriggerDomain domain;
193 for (int i = 0; i < opcount; i++)
195 // Make sure not to use the last data type, origin or specification in
196 // the respective lists because we want to use them later to test the
197 // matching against wild card values.
198 int itype = gRandom->Integer(N-1);
199 int iorigin = gRandom->Integer(N-1);
200 int ispec = gRandom->Integer(N-1);
201 if (gRandom->Integer(2) == 0)
203 if (spec[ispec] == 0)
205 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin]));
206 domain.Add(datatype[itype], origin[iorigin]);
210 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin], spec[ispec]));
211 domain.Add(datatype[itype], origin[iorigin], spec[ispec]);
216 if (spec[ispec] == 0)
218 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin]));
219 domain.Remove(datatype[itype], origin[iorigin]);
223 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin], spec[ispec]));
224 domain.Remove(datatype[itype], origin[iorigin], spec[ispec]);
229 if (not DomainOK(entryList, domain)) return false;
235 #define DefOperation(name, expr, logicExpr) \
239 static const char* Name() \
243 static const char* Expression() \
247 static AliHLTTriggerDomain Apply(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
251 static bool ExpectedResult(bool a, const bool b) \
258 DefOperation( OpComplement, ~a, !a );
259 DefOperation( OpUnion, a | b, a | b );
260 DefOperation( OpIntersect, a & b, a & b );
261 DefOperation( OpXor, a ^ b, a ^ b );
262 DefOperation( OpDifference, a - b, a & (!b) );
265 * Randomly builds two trigger domains and tests a overloaded operator of the
266 * AliHLTTriggerDomain class.
267 * \param [in] opcount The number of Add / Remove operations to use to build the domains.
270 bool OperatorOK(int opcount = 100)
272 AliHLTTriggerDomain d1;
273 BuildTriggerDomain(d1, opcount);
274 AliHLTTriggerDomain d2;
275 BuildTriggerDomain(d2, opcount);
276 AliHLTTriggerDomain d3 = Op::Apply(d1, d2);
278 for (int i = 1; i < N; i++)
279 for (int j = 1; j < N; j++)
280 for (int k = 1; k < N; k++)
282 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
283 bool d1Result = d1.Contains(entry);
284 bool d2Result = d2.Contains(entry);
285 bool d3Result = d3.Contains(entry);
286 bool d3ExpectedResult = Op::ExpectedResult(d1Result, d2Result);
287 if (d3Result != d3ExpectedResult)
289 cout << "FAILED OperatorOK<" << Op::Name() << "> test!" << endl;
290 cout << "==============================================================================" << endl;
291 cout << "Dump of the trigger domain a contents:" << endl;
293 cout << "==============================================================================" << endl;
294 cout << "Dump of the trigger domain b contents:" << endl;
296 cout << "==============================================================================" << endl;
297 cout << "Dump of the trigger domain c = " << Op::Expression() << " contents:" << endl;
299 cout << "==============================================================================" << endl;
300 cout << "Failed for entry = ";
302 cout << "Result of c.Contains(entry) == " << d3Result << endl;
303 cout << " Expected c.Contains(entry) == " << d3ExpectedResult << endl;
312 #define DefEqualExprCheck(name, expr1, expr2) \
316 static const char* Name() \
320 static const char* Expr1() \
324 static const char* Expr2() \
328 static AliHLTTriggerDomain Apply1(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
332 static AliHLTTriggerDomain Apply2(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
339 DefEqualExprCheck( XorExprCheck1, a ^ b, (a | b) - (a & b) );
340 DefEqualExprCheck( XorExprCheck2, a ^ b, (a - (a & b)) | (b - (a & b)) );
341 DefEqualExprCheck( MinusExprCheck1, a - b, a & (a ^ b) );
342 DefEqualExprCheck( MinusExprCheck2, a - b, a & ~(a & b) );
345 * Randomly builds two trigger domains and tests two expressions applied to the
346 * domains that should be equivalent.
347 * \param [in] opcount The number of Add / Remove operations to use to build the domains.
349 template <class Expr>
350 bool EquivalentExpressionsOK(int opcount = 100)
352 AliHLTTriggerDomain d1;
353 BuildTriggerDomain(d1, opcount);
354 AliHLTTriggerDomain d2;
355 BuildTriggerDomain(d2, opcount);
356 AliHLTTriggerDomain d3 = Expr::Apply1(d1, d2);
357 AliHLTTriggerDomain d4 = Expr::Apply2(d1, d2);
359 for (int i = 1; i < N; i++)
360 for (int j = 1; j < N; j++)
361 for (int k = 1; k < N; k++)
363 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
364 bool d3Result = d3.Contains(entry);
365 bool d4Result = d4.Contains(entry);
366 if (d3Result != d4Result)
368 cout << "FAILED EquivalentExpressionsOK<" << Expr::Name() << "> test!" << endl;
369 cout << "==============================================================================" << endl;
370 cout << "Dump of the trigger domain a contents:" << endl;
372 cout << "==============================================================================" << endl;
373 cout << "Dump of the trigger domain b contents:" << endl;
375 cout << "==============================================================================" << endl;
376 cout << "Dump of the trigger domain c = " << Expr::Expr1() << " contents:" << endl;
378 cout << "==============================================================================" << endl;
379 cout << "Dump of the trigger domain d = " << Expr::Expr2() << " contents:" << endl;
381 cout << "==============================================================================" << endl;
382 cout << "Failed for entry = ";
384 cout << "Result of c.Contains(entry) == " << d3Result << endl;
385 cout << "Result of d.Contains(entry) == " << d4Result << endl;
386 cout << "But the results should be the same." << endl;
395 #define DefTest(name, routine, description) \
399 static bool Run(int opcount) \
401 return routine(opcount); \
403 static const char* Description() \
405 return description; \
409 // Declarations of the different tests.
410 DefTest(AddRemoveTest, AddRemoveOK, "AliHLTTriggerDomain::Add and AliHLTTriggerDomain::Remove");
411 DefTest(ComplementOperationTest, OperatorOK<OpComplement>, "operator ~a");
412 DefTest(UnionOperationTest, OperatorOK<OpUnion>, "operator a | b");
413 DefTest(IntersectOperationTest, OperatorOK<OpIntersect>, "operator a & b");
414 DefTest(XorOperationTest, OperatorOK<OpXor>, "operator a ^ b");
415 DefTest(DifferenceOperationTest, OperatorOK<OpDifference>, "operator a - b");
416 DefTest(XorExpressionTest1, EquivalentExpressionsOK<XorExprCheck1>, "expression a ^ b == (a | b) - (a & b)");
417 DefTest(XorExpressionTest2, EquivalentExpressionsOK<XorExprCheck2>, "expression a ^ b == (a - (a & b)) | (b - (a & b))");
418 DefTest(MinusExpressionTest1, EquivalentExpressionsOK<MinusExprCheck1>, "expression a - b == a & (a ^ b)");
419 DefTest(MinusExpressionTest2, EquivalentExpressionsOK<MinusExprCheck2>, "expression a - b == a & ~(a & b)");
422 * Routine to run an individual test.
423 * \param print Should information be printed showing the progress of testing.
424 * \param numOfTests The number of test iterations to run.
426 template <class Test>
427 bool Run(bool print = true, int numOfTests = 100)
429 if (print) cout << "Testing " << Test::Description() << " ..." << endl;
430 for (int i = 0; i < numOfTests; i++)
432 if (not Test::Run(10)) return false;
433 if (not Test::Run(100)) return false;
434 if (not Test::Run(1000)) return false;
435 if (print and ((i+1) % (numOfTests / 10) == 0))
437 cout << " Completed " << ((i+1) * 100 / numOfTests) << "%" << endl;
444 * This is the top level testing method which calls individual tests.
445 * \param print Should information be printed showing the progress of testing.
446 * \param numOfTests The number of test iterations to run.
447 * \param seed The random number seed to use.
449 bool testTriggerDomain(bool print = true, int numOfTests = 100, int seed = 0)
451 if (gClassTable->GetID("AliHLTDomainEntry") < 0)
453 gSystem->Load("libAliHLTTrigger.so");
456 gRandom->SetSeed(seed);
458 if (not Run<AddRemoveTest>(print, numOfTests)) return false;
459 if (not Run<ComplementOperationTest>(print, numOfTests)) return false;
460 if (not Run<UnionOperationTest>(print, numOfTests)) return false;
461 if (not Run<IntersectOperationTest>(print, numOfTests)) return false;
462 if (not Run<XorOperationTest>(print, numOfTests)) return false;
463 if (not Run<DifferenceOperationTest>(print, numOfTests)) return false;
464 if (not Run<XorExpressionTest1>(print, numOfTests)) return false;
465 if (not Run<XorExpressionTest2>(print, numOfTests)) return false;
466 if (not Run<MinusExpressionTest1>(print, numOfTests)) return false;
467 if (not Run<MinusExpressionTest2>(print, numOfTests)) return false;
474 int main(int /*argc*/, const char** /*argv*/)
476 bool resultOk = testTriggerDomain();
477 if (not resultOk) return 1;
481 #endif // __MAKECINT__