Major update required to handle old and new AliHLTEventDDL structures within HLT...
[u/mrichter/AliRoot.git] / HLT / BASE / test / testAliHLTReadoutList.C
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: Artur Szostak <artursz@iafrica.com>                   *
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   testAliHLTReadoutList.C
20 /// @author Artur Szostak <artursz@iafrica.com>
21 /// @date   8 June 2010
22 /// @brief  Test program for the AliHLTReadoutList class.
23 ///
24
25 #if defined(__CINT__) && (! defined(__MAKECINT__))
26 #error This macro must be compiled. Try running as testAliHLTReadoutList.C++.
27 #endif
28
29 #if !defined(__CINT__) || defined(__MAKECINT__)
30 #include "AliHLTDataTypes.h"
31 #include "AliHLTReadoutList.h"
32 #include "AliHLTDAQ.h"
33 #include "TRandom3.h"
34 #include "TString.h"
35 #include "Riostream.h"
36 #include <vector>
37 #include <algorithm>
38 #endif
39
40 // The detector codes as used by AliHLTReadoutList.
41 const int kgNumberOfCodes = 21;
42 const int kgDetCodes[kgNumberOfCodes] = {
43         AliHLTReadoutList::kITSSPD,
44         AliHLTReadoutList::kITSSDD,
45         AliHLTReadoutList::kITSSSD,
46         AliHLTReadoutList::kTPC,
47         AliHLTReadoutList::kTRD,
48         AliHLTReadoutList::kTOF,
49         AliHLTReadoutList::kHMPID,
50         AliHLTReadoutList::kPHOS,
51         AliHLTReadoutList::kCPV,
52         AliHLTReadoutList::kPMD,
53         AliHLTReadoutList::kMUONTRK,
54         AliHLTReadoutList::kMUONTRG,
55         AliHLTReadoutList::kFMD,
56         AliHLTReadoutList::kT0,
57         AliHLTReadoutList::kV0,
58         AliHLTReadoutList::kZDC,
59         AliHLTReadoutList::kACORDE,
60         AliHLTReadoutList::kTRG,
61         AliHLTReadoutList::kEMCAL,
62         AliHLTReadoutList::kDAQTEST,
63         AliHLTReadoutList::kHLT
64 };
65 const char* kgDetCodeName[kgNumberOfCodes] = {
66         "AliHLTReadoutList::kITSSPD",
67         "AliHLTReadoutList::kITSSDD",
68         "AliHLTReadoutList::kITSSSD",
69         "AliHLTReadoutList::kTPC",
70         "AliHLTReadoutList::kTRD",
71         "AliHLTReadoutList::kTOF",
72         "AliHLTReadoutList::kHMPID",
73         "AliHLTReadoutList::kPHOS",
74         "AliHLTReadoutList::kCPV",
75         "AliHLTReadoutList::kPMD",
76         "AliHLTReadoutList::kMUONTRK",
77         "AliHLTReadoutList::kMUONTRG",
78         "AliHLTReadoutList::kFMD",
79         "AliHLTReadoutList::kT0",
80         "AliHLTReadoutList::kV0",
81         "AliHLTReadoutList::kZDC",
82         "AliHLTReadoutList::kACORDE",
83         "AliHLTReadoutList::kTRG",
84         "AliHLTReadoutList::kEMCAL",
85         "AliHLTReadoutList::kDAQTEST",
86         "AliHLTReadoutList::kHLT"
87 };
88
89 /**
90  * Converts a code to string.
91  * \param code  The ID code of the detector. One of AliHLTReadoutList::EDetectorId
92  * \returns the code name as a string given a the detector code.
93  */
94 const char* CodeToString(int code)
95 {
96         for (int i = 0; i < kgNumberOfCodes; ++i)
97         {
98                 if (kgDetCodes[i] == code) return kgDetCodeName[i];
99         }
100         return "UNKNOWN";
101 }
102
103 /**
104  * Checks if the basic empty and clear methods work.
105  */
106 bool CheckEmptyAndClear()
107 {
108         AliHLTReadoutList rl;
109         if (rl.Empty() != true)
110         {
111                 cerr << "ERROR: AliHLTReadoutList::Empty returns false for an empty readout list." << endl;
112                 return false;
113         }
114         
115         // Enable all the detectors and check this operation.
116         rl.Enable(AliHLTReadoutList::kALLDET);
117         for (int i = 0; i < kgNumberOfCodes; ++i)
118         {
119                 if (i == 19) continue; // This is the test DDL. off by default.
120                 if (not rl.DetectorEnabled(kgDetCodes[i]))
121                 {
122                         cerr << "ERROR: AliHLTReadoutList::Enable(AliHLTReadoutList::kALLDET) did not enable for "
123                                 << CodeToString(kgDetCodes[i]) << "." << endl;
124                         return false;
125                 }
126         }
127         if (rl.DetectorEnabled(AliHLTReadoutList::kDAQTEST))
128         {
129                 cerr << "ERROR: AliHLTReadoutList::Enable(AliHLTReadoutList::kALLDET) enabled bits"
130                         " for AliHLTReadoutList::kDAQTEST but should not have." << endl;
131                 return false;
132         }
133         
134         rl.Clear();
135         // Fetch the raw bits for the readout list structure and check that they
136         // are all zero, since we should have disabled everything in the loop above.
137         AliHLTEventDDL bits = rl;
138         if (bits.fCount != (unsigned int)gkAliHLTDDLListSize)
139         {
140                 cerr << "ERROR: Typecast operator AliHLTEventDDL () is not"
141                         " setting the fCount of the structure correctly." << endl;
142                 return false;
143         }
144         for (int j = 0; j < gkAliHLTDDLListSize; ++j)
145         {
146                 if (bits.fList[j] != 0x0)
147                 {
148                         cerr << "ERROR: Word " << j << " in internal AliHLTReadoutList"
149                                 " bitfield structure is not zero as expected after a"
150                                 " call to AliHLTReadoutList::Clear." << endl;
151                         return false;
152                 }
153         }
154         
155         return true;
156 }
157
158 /**
159  * Tests enabling and disabling of different detectors.
160  */
161 bool CheckEnablingDisabling()
162 {
163         for (int i = 0; i < 10000; ++i)
164         {
165                 // Get 3 random detector codes.
166                 int detNum[3] = {
167                         gRandom->Integer(kgNumberOfCodes),
168                         gRandom->Integer(kgNumberOfCodes),
169                         gRandom->Integer(kgNumberOfCodes)
170                 };
171                 int code[3] = {
172                         kgDetCodes[detNum[0]],
173                         kgDetCodes[detNum[1]],
174                         kgDetCodes[detNum[2]]
175                 };
176                 // make sure the codes are not duplicated.
177                 while (code[1] == code[0])
178                 {
179                         detNum[1] = gRandom->Integer(kgNumberOfCodes);
180                         code[1] = kgDetCodes[detNum[1]];
181                 }
182                 while (code[2] == code[1] or code[2] == code[0])
183                 {
184                         detNum[2] = gRandom->Integer(kgNumberOfCodes);
185                         code[2] = kgDetCodes[detNum[2]];
186                 }
187                 
188                 // Choose the number of codes to use, from 1 to max 3.
189                 int codeCount = gRandom->Integer(3) + 1;
190                 
191                 // Build up the detector code list for the AliHLTReadoutList constructor.
192                 int totalCode = 0;
193                 for (int j = 0; j < codeCount; ++j) totalCode |= code[j];
194                 
195                 AliHLTReadoutList rl(totalCode);
196                 if (rl.Empty() == true)
197                 {
198                         cerr << "ERROR: AliHLTReadoutList::Empty returns true for a non empty readout list." << endl;
199                         return false;
200                 }
201                 
202                 // Check that the correct detectors have been enabled and
203                 // that we can disable a detector correctly.
204                 for (int j = 0; j < codeCount; ++j)
205                 {
206                         if (rl.DetectorEnabled(code[j]) == false)
207                         {
208                                 cerr << "ERROR: Detector was not enabled for "
209                                         << CodeToString(code[j]) << " by constructor." << endl;
210                                 return false;
211                         }
212                         if (rl.DetectorDisabled(code[j]) == true)
213                         {
214                                 cerr << "ERROR: DetectorDisabled returned and incorrect result"
215                                         " when detectors enabled for "
216                                         << CodeToString(code[j]) << " by constructor." << endl;
217                                 return false;
218                         }
219                         
220                         // Also check each bit individualy according to AliHLTDAQ values.
221                         int det = detNum[j];
222                         int maxddls = AliHLTDAQ::NumberOfDdls(det);
223                         for (int ddlindex = 0; ddlindex < maxddls; ++ddlindex)
224                         {
225                                 int ddlid = AliHLTDAQ::DdlIDOffset(det) | (ddlindex & 0xFF);
226                                 if (rl.IsDDLDisabled(ddlid))
227                                 {
228                                         cerr << "ERROR: Bit not set for DDL " << ddlid
229                                                 << ", even though detector "
230                                                 << AliHLTDAQ::OnlineName(det)
231                                                 << " was enabled." << endl;
232                                         return false;
233                                 }
234                         }
235                         
236                         rl.Disable(code[j]);
237                         if (rl.DetectorEnabled(code[j]) == true)
238                         {
239                                 cerr << "ERROR: AliHLTReadoutList::Disable(x) is not working for x = "
240                                         << CodeToString(code[j]) << "." << endl;
241                                 return false;
242                         }
243                         if (rl.DetectorDisabled(code[j]) == false)
244                         {
245                                 cerr << "ERROR: DetectorDisabled returned and incorrect result"
246                                         " when calling AliHLTReadoutList::Disable(x) for "
247                                         << CodeToString(code[j]) << "." << endl;
248                                 return false;
249                         }
250                 }
251                 
252                 // Fetch the raw bits for the readout list structure and check that they
253                 // are all zero, since we should have disabled everything in the loop above.
254                 AliHLTEventDDL bits = rl;
255                 for (int j = 0; j < gkAliHLTDDLListSize; ++j)
256                 {
257                         if (bits.fList[j] != 0x0)
258                         {
259                                 cerr << "ERROR: Word " << j << " in internal AliHLTReadoutList"
260                                         " bitfield structure is not zero as expected." << endl;
261                                 return false;
262                         }
263                 }
264         }
265         return true;
266 }
267
268 /**
269  * Tests enabling and disabling of different DDLs.
270  */
271 bool CheckEnablingDisablingDDLs()
272 {
273         for (int i = 0; i < 10000; ++i)
274         {
275                 // Get random DDL IDs that are each unique.
276                 std::vector<int> ddls;
277                 int ddlCount = gRandom->Integer(100) + 1;
278                 for (int j = 0; j < ddlCount; ++j)
279                 {
280                         int ddlid = -1;
281                         do
282                         {
283                                 int det = gRandom->Integer(AliHLTDAQ::NumberOfDetectors());
284                                 int maxddls = AliHLTDAQ::NumberOfDdls(det);
285                                 // The following is a special check since AliDAQ could be the newer version.
286                                 // det = 18 is for EMCAL and gkAliHLTDDLListSize = 30 indicates old version
287                                 // of AliHLTEventDDL before EMCAL expantion with DCAL.
288                                 if (det == 18 and gkAliHLTDDLListSize == 30 and maxddls > 24) maxddls = 24;
289                                 int ddlindex = gRandom->Integer(maxddls);
290                                 ddlid = AliHLTDAQ::DdlID(det, ddlindex);
291                                 if (std::find(ddls.begin(), ddls.end(), ddlid) != ddls.end()) ddlid = -1;
292                         }
293                         while (ddlid == -1);
294                         ddls.push_back(ddlid);
295                 }
296                 
297                 // Build up the enable list for the AliHLTReadoutList constructor.
298                 TString enableList;
299                 for (size_t j = 0; j < ddls.size(); ++j)
300                 {
301                         char num[32];
302                         sprintf(num, "%d", ddls[j]);
303                         enableList += " ";
304                         enableList += num;
305                 }
306                 
307                 AliHLTReadoutList rl(enableList.Data());
308                 if (rl.Empty() == true)
309                 {
310                         cerr << "ERROR: AliHLTReadoutList::Empty returns true for a non empty readout list." << endl;
311                         return false;
312                 }
313                 
314                 // Check that the correct DDLs have been enabled and
315                 // that we can disable a DDL correctly.
316                 for (size_t j = 0; j < ddls.size(); ++j)
317                 {
318                         if (rl.IsDDLEnabled(ddls[j]) == false)
319                         {
320                                 cerr << "ERROR: DDL " << ddls[j] << " was not enabled by constructor." << endl;
321                                 return false;
322                         }
323                         rl.DisableDDLBit(ddls[j]);
324                         if (rl.IsDDLDisabled(ddls[j]) == false)
325                         {
326                                 cerr << "ERROR: AliHLTReadoutList::DisableDDLBit(x) is not working for x = "
327                                         << ddls[j] << "." << endl;
328                                 return false;
329                         }
330                 }
331                 
332                 // Fetch the raw bits for the readout list structure and check that they
333                 // are all zero, since we should have disabled everything in the loop above.
334                 AliHLTEventDDL bits = rl;
335                 for (int j = 0; j < gkAliHLTDDLListSize; ++j)
336                 {
337                         if (bits.fList[j] != 0x0)
338                         {
339                                 cerr << "ERROR: Word " << j << " in internal AliHLTReadoutList"
340                                         " bitfield structure is not zero as expected." << endl;
341                                 return false;
342                         }
343                 }
344         }
345         return true;
346 }
347
348 /**
349  * Tests if using incorrect DDL IDs returns zero or is ignored as expected.
350  */
351 bool CheckIncorrectIDs()
352 {
353         for (int i = 0; i < 1000000; ++i)
354         {
355                 // Get random DDL ID outside the valid range.
356                 int ddlid = -1;
357                 int det = gRandom->Integer(AliHLTDAQ::NumberOfDetectors()+1);
358                 if (det != AliHLTDAQ::NumberOfDetectors())
359                 {
360                         int maxddls = AliHLTDAQ::NumberOfDdls(det);
361                         int ddlindex = gRandom->Integer(0xFF - maxddls) + maxddls;
362                         ddlid = AliHLTDAQ::DdlIDOffset(det) | (ddlindex & 0xFF);
363                 }
364                 else
365                 {
366                         det = gRandom->Integer(11) + 20;
367                         if (det == 30) det = 31;
368                         int ddlindex = gRandom->Integer(0xFF);
369                         ddlid = (det << 8) | (ddlindex & 0xFF);
370                 }
371                 
372                 AliHLTReadoutList rl;
373                 if (rl.GetDDLBit(ddlid) != kFALSE)
374                 {
375                         cerr << "ERROR: Received a non zero result for invalid DDL " << ddlid << "." << endl;
376                         return false;
377                 }
378                 AliHLTEventDDL before = rl;
379                 rl.EnableDDLBit(ddlid);
380                 AliHLTEventDDL after = rl;
381                 if (memcmp(&before, &after, sizeof(AliHLTEventDDL)) != 0)
382                 {
383                         cerr << "ERROR: Modified AliHLTReadoutList structure using an invalid DDL "
384                                 << ddlid << "." << endl;
385                         cerr << "========== Dump of bits before modification ==========" << endl;
386                         for (unsigned int j = 0; j < before.fCount; ++j)
387                         {
388                                 cerr << "[word " << dec << j << "] = " << hex << before.fList[j] << dec << endl;
389                         }
390                         cerr << "========== Dump of bits after modification ==========" << endl;
391                         for (unsigned int j = 0; j < after.fCount; ++j)
392                         {
393                                 cerr << "[word " << dec << j << "] = " << hex << after.fList[j] << dec << endl;
394                         }
395                         return false;
396                 }
397         }
398         return true;
399 }
400
401 /**
402  * Tests if using incorrect DDL IDs returns zero or is ignored as expected.
403  */
404 bool CheckWordIndexAndCount()
405 {
406         int wordCovered[gkAliHLTDDLListSize];
407         for (int j = 0; j < gkAliHLTDDLListSize; ++j) wordCovered[j] = 0;
408         
409         for (int i = 0; i < kgNumberOfCodes; ++i)
410         {
411                 AliHLTReadoutList rl;
412                 Int_t firstword = rl.GetFirstWord((AliHLTReadoutList::EDetectorId)kgDetCodes[i]);
413                 if (firstword < 0 or gkAliHLTDDLListSize-1 < firstword)
414                 {
415                         cerr << "ERROR: AliHLTReadoutList::GetFirstWord(" << kgDetCodeName[i]
416                                 << ") returns " << firstword
417                                 << ", which is outside the valid range of [0.." << gkAliHLTDDLListSize-1
418                                 << "]." << endl;
419                         return false;
420                 }
421                 
422                 Int_t lastword = firstword + rl.GetWordCount((AliHLTReadoutList::EDetectorId)kgDetCodes[i]);
423                 if (lastword < 1 or gkAliHLTDDLListSize < lastword)
424                 {
425                         cerr << "ERROR: The sum AliHLTReadoutList::GetFirstWord(" << kgDetCodeName[i]
426                                 << ") + AliHLTReadoutList::GetWordCount(" << kgDetCodeName[i]
427                                 << ") gives " << lastword
428                                 << ", which is outside the valid range of [1.." << gkAliHLTDDLListSize
429                                 << "]." << endl;
430                         return false;
431                 }
432                 
433                 for (int j = firstword; j < lastword; ++j)
434                 {
435                         if (wordCovered[j] == 1)
436                         {
437                                 cerr << "ERROR: The combination of AliHLTReadoutList::GetWordCount(" << kgDetCodeName[i]
438                                         << ") and AliHLTReadoutList::GetWordCount(" << kgDetCodeName[i]
439                                         << ") overlaps with previous detectors. Check the mapping in these functions."
440                                         << endl;
441                                 return false;
442                         }
443                         wordCovered[j] = 1;
444                 }
445                 
446                 Int_t maxddls = AliHLTDAQ::NumberOfDdls(i);
447                 Int_t ddlid = AliHLTDAQ::DdlIDOffset(i) | (gRandom->Integer(maxddls) & 0xFF);
448                 rl.EnableDDLBit(ddlid);
449                 if (rl.GetFirstUsedDetector() != kgDetCodes[i])
450                 {
451                         cerr << "ERROR: AliHLTReadoutList::GetFirstUsedDetector() did not return the correct value of"
452                                 << kgDetCodeName[i] << " after calling AliHLTReadoutList::EnableDDLBit("
453                                 << ddlid << ")." << endl;
454                         return false;
455                 }
456                 if (rl.GetFirstUsedDetector((AliHLTReadoutList::EDetectorId)kgDetCodes[i]) != AliHLTReadoutList::kNoDetector)
457                 {
458                         cerr << "ERROR: AliHLTReadoutList::GetFirstUsedDetector(" << kgDetCodeName[i]
459                                 << "+1) did not return the correct value of AliHLTReadoutList::kNoDetector"
460                                    " after calling AliHLTReadoutList::EnableDDLBit("
461                                 << ddlid << ")." << endl;
462                         return false;
463                 }
464         }
465         
466         for (int j = 0; j < gkAliHLTDDLListSize; ++j)
467         {
468                 if (wordCovered[j] == 0)
469                 {
470                         cerr << "ERROR: The functions AliHLTReadoutList::GetWordCount"
471                                 " and AliHLTReadoutList::GetWordCount do not fully cover"
472                                 " all DDL readout list words." << endl;
473                         return false;
474                 }
475         }
476         
477         return true;
478 }
479
480 /**
481  * Runs the unit test for the AliHLTReadoutList class.
482  * \returns true if the class passed the test and false otherwise.
483  */
484 bool testAliHLTReadoutList()
485 {
486         gRandom->SetSeed(123);
487         
488         if (AliHLTDAQ::NumberOfDetectors() != kgNumberOfCodes)
489         {
490                 cerr << "ERROR: The testAliHLTReadoutList.C macro needs to be updated"
491                         " or something went really wrong."
492                         " The number of detectors reported by AliHLTDAQ is not "
493                         << kgNumberOfCodes << ", as expected, but "
494                         << AliHLTDAQ::NumberOfDetectors() << "." << endl;
495                 return false;
496         }
497         
498         if (not CheckEmptyAndClear()) return false;
499         if (not CheckEnablingDisabling()) return false;
500         if (not CheckEnablingDisablingDDLs()) return false;
501         if (not CheckIncorrectIDs()) return false;
502         if (not CheckWordIndexAndCount()) return false;
503         
504         return true;
505 }
506
507 #ifndef __MAKECINT__
508
509 int main(int /*argc*/, const char** /*argv*/)
510 {
511         bool resultOk = testAliHLTReadoutList();
512         if (not resultOk) return 1;
513         return 0;
514 }
515
516 #endif // __MAKECINT__