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 * This macro is used to test the behaviour of the AliHLTTriggerDomain class.
19 * We specifically check that the AliHLTTriggerDomain operators behave correctly
23 #if defined(__CINT__) && (! defined(__MAKECINT__))
24 #error This macro must be compiled. Try running as testTriggerDomain.C++
27 #include "Riostream.h"
29 #include "TClassTable.h"
31 #include "TObjArray.h"
32 #include "AliHLTTriggerDomain.h"
33 #include "AliHLTDomainEntry.h"
36 const char* datatype[N] = {"*******", "AAAAAAAA", "BBBBBBBB", "CCCCCCCC", "DDDDDDDD", "EEEEEEEE"};
37 const char* origin[N] = {"***", "xxxx", "yyyy", "zzzz", "wwww", "uuuu"};
38 int spec[N] = {0, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555};
41 * Randomly builds a trigger domain from the various data types, origins and specifications.
42 * \param domain <i>[out]</i> The new constructed domain is filled into this output variable.
43 * \param opcount <i>[in]</i> The number of Add / Remove operations to apply to the domain.
45 void BuildTriggerDomain(AliHLTTriggerDomain& domain, int opcount = 100)
48 for (int i = 0; i < opcount; i++)
50 // Make sure not to use the last data type, origin or specification in
51 // the respective lists because we want to use them later to test the
52 // matching against wild card values.
53 int itype = gRandom->Integer(N-1);
54 int iorigin = gRandom->Integer(N-1);
55 int ispec = gRandom->Integer(N-1);
56 if (gRandom->Integer(2) == 0)
59 domain.Add(datatype[itype], origin[iorigin]);
61 domain.Add(datatype[itype], origin[iorigin], spec[ispec]);
66 domain.Remove(datatype[itype], origin[iorigin]);
68 domain.Remove(datatype[itype], origin[iorigin], spec[ispec]);
74 * Returns the string representation of the data type.
76 const char* TypeToString(const AliHLTComponentDataType& type)
78 static char str[kAliHLTComponentDataTypefIDsize+1];
79 for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
87 * Returns the string representation of the data origin.
89 const char* OriginToString(const AliHLTComponentDataType& type)
91 static char str[kAliHLTComponentDataTypefOriginSize+1];
92 for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
94 str[i] = type.fOrigin[i];
100 * Checks to see if the domain is correctly constructed compared to the list of entries
101 * that were applied to the domain.
102 * \param entryList <i>[out]</i> The list of entries that were used to construct the domain.
103 * \param domain <i>[in]</i> The trigger domain to check.
105 bool DomainOK(const TObjArray& entryList, const AliHLTTriggerDomain& domain)
107 for (int i = 1; i < N; i++)
108 for (int j = 1; j < N; j++)
109 for (int k = 1; k < N; k++)
111 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
112 AliHLTComponentBlockData block;
113 block.fDataType = entry;
114 block.fSpecification = spec[k];
117 bool result2 = false;
118 for (int n = 0; n < entryList.GetEntriesFast(); n++)
120 const AliHLTDomainEntry* rule = static_cast<const AliHLTDomainEntry*>( entryList[n] );
121 if (*rule == entry) result = rule->Inclusive();
122 if (*rule == &block) result2 = rule->Inclusive();
125 bool containsResult = domain.Contains(entry);
126 bool includeResult = domain.IncludeInReadout(&block);
127 if (containsResult != result or includeResult != result2)
129 cout << "FAILED DomainOK test!" << endl;
130 cout << "==============================================================================" << endl;
131 cout << "Dump of how AliHLTTriggerDomain was built:" << endl;
132 cout << " AliHLTTriggerDomain domain;" << endl;
133 for (int n = 0; n < entryList.GetEntriesFast(); n++)
135 const AliHLTDomainEntry* rule = static_cast<const AliHLTDomainEntry*>( entryList[n] );
136 const char* opstr = (rule->Exclusive() ? "Remove" : "Add");
137 if (rule->IsValidSpecification())
139 cout << " domain." << opstr << "(\"" << TypeToString(rule->DataType())
140 << "\", \"" << OriginToString(rule->DataType())
141 << "\", 0x" << hex << rule->Specification() << dec
146 cout << " domain." << opstr << "(\"" << TypeToString(rule->DataType())
147 << "\", \"" << OriginToString(rule->DataType())
151 cout << "==============================================================================" << endl;
152 cout << "Dump of the trigger domain contents:" << endl;
154 cout << "==============================================================================" << endl;
156 if (containsResult != result)
158 cout << "Failed for entry = ";
160 cout << "Result of domain.Contains(entry) == " << containsResult << endl;
161 cout << " Expected domain.Contains(entry) == " << result << endl;
164 if (includeResult != result2)
166 cout << "Failed for block: type = " << TypeToString(block.fDataType)
167 << ", origin = " << OriginToString(block.fDataType)
168 << ", specification = " << hex << block.fSpecification << dec;
169 cout << "Result of domain.IncludeInReadout(&block) == " << includeResult << endl;
170 cout << " Expected domain.IncludeInReadout(&block) == " << result2 << endl;
179 * Randomly builds a trigger domain and tests the Add / Remove operations of the
180 * AliHLTTriggerDomain class.
181 * \param opcount <i>[in]</i> The number of Add / Remove operations to use to
184 bool AddRemoveOK(int opcount = 100)
187 entryList.SetOwner(kTRUE);
188 AliHLTTriggerDomain domain;
190 for (int i = 0; i < opcount; i++)
192 // Make sure not to use the last data type, origin or specification in
193 // the respective lists because we want to use them later to test the
194 // matching against wild card values.
195 int itype = gRandom->Integer(N-1);
196 int iorigin = gRandom->Integer(N-1);
197 int ispec = gRandom->Integer(N-1);
198 if (gRandom->Integer(2) == 0)
200 if (spec[ispec] == 0)
202 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin]));
203 domain.Add(datatype[itype], origin[iorigin]);
207 entryList.Add(new AliHLTDomainEntry(kFALSE, datatype[itype], origin[iorigin], spec[ispec]));
208 domain.Add(datatype[itype], origin[iorigin], spec[ispec]);
213 if (spec[ispec] == 0)
215 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin]));
216 domain.Remove(datatype[itype], origin[iorigin]);
220 entryList.Add(new AliHLTDomainEntry(kTRUE, datatype[itype], origin[iorigin], spec[ispec]));
221 domain.Remove(datatype[itype], origin[iorigin], spec[ispec]);
226 if (not DomainOK(entryList, domain)) return false;
232 #define DefOperation(name, expr, logicExpr) \
236 static const char* Name() \
240 static const char* Expression() \
244 static AliHLTTriggerDomain Apply(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
248 static bool ExpectedResult(bool a, const bool b) \
255 DefOperation( OpComplement, ~a, !a );
256 DefOperation( OpUnion, a | b, a | b );
257 DefOperation( OpIntersect, a & b, a & b );
258 DefOperation( OpXor, a ^ b, a ^ b );
259 DefOperation( OpPlus, a + b, a | b );
260 DefOperation( OpMinus, a - b, a & (!b) );
263 * Randomly builds two trigger domains and tests a overloaded operator of the
264 * AliHLTTriggerDomain class.
265 * \param opcount <i>[in]</i> The number of Add / Remove operations to use to
269 bool OperatorOK(int opcount = 100)
271 AliHLTTriggerDomain d1;
272 BuildTriggerDomain(d1, opcount);
273 AliHLTTriggerDomain d2;
274 BuildTriggerDomain(d2, opcount);
275 AliHLTTriggerDomain d3 = Op::Apply(d1, d2);
277 for (int i = 1; i < N; i++)
278 for (int j = 1; j < N; j++)
279 for (int k = 1; k < N; k++)
281 AliHLTDomainEntry entry(datatype[i], origin[j], spec[k]);
282 bool d1Result = d1.Contains(entry);
283 bool d2Result = d2.Contains(entry);
284 bool d3Result = d3.Contains(entry);
285 bool d3ExpectedResult = Op::ExpectedResult(d1Result, d2Result);
286 if (d3Result != d3ExpectedResult)
288 cout << "FAILED OperatorOK<" << Op::Name() << "> test!" << endl;
289 cout << "==============================================================================" << endl;
290 cout << "Dump of the trigger domain a contents:" << endl;
292 cout << "==============================================================================" << endl;
293 cout << "Dump of the trigger domain b contents:" << endl;
295 cout << "==============================================================================" << endl;
296 cout << "Dump of the trigger domain c = " << Op::Expression() << " contents:" << endl;
298 cout << "==============================================================================" << endl;
299 cout << "Failed for entry = ";
301 cout << "Result of c.Contains(entry) == " << d3Result << endl;
302 cout << " Expected c.Contains(entry) == " << d3ExpectedResult << endl;
311 #define DefEqualExprCheck(name, expr1, expr2) \
315 static const char* Name() \
319 static const char* Expr1() \
323 static const char* Expr2() \
327 static AliHLTTriggerDomain Apply1(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
331 static AliHLTTriggerDomain Apply2(const AliHLTTriggerDomain& a, const AliHLTTriggerDomain& b) \
338 DefEqualExprCheck( XorExprCheck1, a ^ b, (a | b) - (a & b) );
339 DefEqualExprCheck( XorExprCheck2, a ^ b, (a - (a & b)) | (b - (a & b)) );
340 DefEqualExprCheck( MinusExprCheck1, a - b, a & (a ^ b) );
341 DefEqualExprCheck( MinusExprCheck2, a - b, a & ~(a & b) );
344 * Randomly builds two trigger domains and tests two expressions applied to the
345 * domains that should be equivalent.
346 * \param opcount <i>[in]</i> The number of Add / Remove operations to use to
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(PlusOperationTest, OperatorOK<OpPlus>, "operator a + b");
416 DefTest(MinusOperationTest, OperatorOK<OpMinus>, "operator a - b");
417 DefTest(XorExpressionTest1, EquivalentExpressionsOK<XorExprCheck1>, "expression a ^ b == (a | b) - (a & b)");
418 DefTest(XorExpressionTest2, EquivalentExpressionsOK<XorExprCheck2>, "expression a ^ b == (a - (a & b)) | (b - (a & b))");
419 DefTest(MinusExpressionTest1, EquivalentExpressionsOK<MinusExprCheck1>, "expression a - b == a & (a ^ b)");
420 DefTest(MinusExpressionTest2, EquivalentExpressionsOK<MinusExprCheck2>, "expression a - b == a & ~(a & b)");
423 * Routine to run an individual test.
424 * \param print Should information be printed showing the progress of testing.
425 * \param numOfTests The number of test iterations to run.
427 template <class Test>
428 bool Run(bool print = true, int numOfTests = 100)
430 if (print) cout << "Testing " << Test::Description() << " ..." << endl;
431 for (int i = 0; i < numOfTests; i++)
433 if (not Test::Run(10)) return false;
434 if (not Test::Run(100)) return false;
435 if (not Test::Run(1000)) return false;
436 if (print and ((i+1) % (numOfTests / 10) == 0))
438 cout << " Completed " << ((i+1) * 100 / numOfTests) << "%" << endl;
445 * This is the top level testing method which calls individual tests.
446 * \param print Should information be printed showing the progress of testing.
447 * \param numOfTests The number of test iterations to run.
448 * \param seed The random number seed to use.
450 bool testTriggerDomain(bool print = true, int numOfTests = 100, int seed = 0)
452 if (gClassTable->GetID("AliHLTDomainEntry") < 0)
454 gSystem->Load("libAliHLTTrigger.so");
457 gRandom->SetSeed(seed);
459 if (not Run<AddRemoveTest>(print, numOfTests)) return false;
460 if (not Run<ComplementOperationTest>(print, numOfTests)) return false;
461 if (not Run<UnionOperationTest>(print, numOfTests)) return false;
462 if (not Run<IntersectOperationTest>(print, numOfTests)) return false;
463 if (not Run<XorOperationTest>(print, numOfTests)) return false;
464 if (not Run<PlusOperationTest>(print, numOfTests)) return false;
465 if (not Run<MinusOperationTest>(print, numOfTests)) return false;
466 if (not Run<XorExpressionTest1>(print, numOfTests)) return false;
467 if (not Run<XorExpressionTest2>(print, numOfTests)) return false;
468 if (not Run<MinusExpressionTest1>(print, numOfTests)) return false;
469 if (not Run<MinusExpressionTest2>(print, numOfTests)) return false;
476 int main(int /*argc*/, const char** /*argv*/)
478 bool resultOk = testTriggerDomain();
479 if (not resultOk) return 1;
483 #endif // __MAKECINT__