dfddbeec3a446dc2fad7e4b55e3363cb9ed9cb2e
[u/mrichter/AliRoot.git] / HLT / trigger / test / testGlobalTriggerComponent.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   19 Dec 2008
21  *
22  * This macro is used to test the AliHLTGlobalTriggerComponent class.
23  * A number of tests are run with the AliHLTSystem framework to check that
24  * the automatically generated global trigger logic is generated correctly.
25  *
26  * This macro can also be used to debug the configuration that fails.
27  * If a configuration test fails then the global trigger logic implementation
28  * is left in a generated file with a name of the form \<AliHLTGlobalTriggerImpl_*.cxx\>.
29  * For example a file named like: AliHLTGlobalTriggerImpl_08869e64_c54b_11de_9717_0101007fbeef.cxx
30  * One can make manual modifications to this file and then rerun the test with
31  * these manual modifications with the following command in aliroot:
32  *  .x testGlobalTriggerComponent.C+(\<configVersion\>,"\<AliHLTGlobalTriggerImpl_*\>")
33  * where \<configVersion\> is the appropriate config version number as passed to the
34  * TriggerConfig.C file to initialise the configuration we want to test. Also take note
35  * that we only specify the root of the file name without the .cxx file name extention.
36  * For our example file name the command to execute in aliroot would be:
37  *  .x testGlobalTriggerComponent.C+(2,"AliHLTGlobalTriggerImpl_08869e64_c54b_11de_9717_0101007fbeef")
38  * where we are testing the 2nd trigger configuration in TriggerConfig.C.
39  */
40
41 #if defined(__CINT__) && (! defined(__MAKECINT__))
42 #error This macro must be compiled. Try running as testGlobalTriggerComponent.C++, but remember to load the libAliHLTTrigger.so library first.
43 #endif
44
45 #if !defined(__CINT__) || defined(__MAKECINT__)
46 #include "TSystem.h"
47 #include "TClassTable.h"
48 #include "TFile.h"
49 #include "AliLog.h"
50 #include "AliHLTReadoutList.h"
51 #include "AliHLTTriggerDomain.h"
52 #include "AliHLTTriggerDecision.h"
53 #include "AliHLTGlobalTriggerDecision.h"
54 #include "AliHLTEventSummary.h"
55 #include "AliHLTSystem.h"
56 #include "AliHLTConfiguration.h"
57 #include "Riostream.h"
58 #endif
59
60 /**
61  * Generates some sample input data and writes it into 8 files named
62  * testInputFile1.root ... testInputFile8.root
63  */
64 void GenerateInputData()
65 {
66         bool loadedLibs = false;
67         if (gClassTable->GetID("AliHLTGlobalTriggerComponent") < 0)
68         {
69                 gSystem->Load("libAliHLTUtil.so");
70                 gSystem->Load("libAliHLTTRD.so");
71                 gSystem->Load("libAliHLTMUON.so");
72                 gSystem->Load("libAliHLTTrigger.so");
73                 loadedLibs = true;
74         }
75
76         AliHLTReadoutList readoutList1("TPC");
77         AliHLTTriggerDomain triggerDomain1;
78         triggerDomain1.Add("CLUSTERS", "TPC ");
79         triggerDomain1.Add("TRACKS", "TPC ");
80         triggerDomain1.Add(readoutList1);
81         AliHLTTriggerDecision decision1(true, "triggerTPC", triggerDomain1, "TPC has data");
82         
83         AliHLTReadoutList readoutList2a("MUONTRK");
84         AliHLTReadoutList readoutList2b("MUONTRG");
85         AliHLTTriggerDomain triggerDomain2;
86         triggerDomain2.Add("TRACKS", "MUON");
87         triggerDomain2.Add(readoutList2a);
88         triggerDomain2.Add(readoutList2b);
89         AliHLTTriggerDecision decision2(true, "triggerMUON", triggerDomain2, "MUON has data");
90         
91         AliHLTReadoutList readoutList3("ITSSSD");
92         AliHLTTriggerDomain triggerDomain3;
93         triggerDomain3.Add("*******", "SSD ");
94         triggerDomain3.Add(readoutList3);
95         AliHLTTriggerDecision decision3(true, "triggerSSD", triggerDomain3, "SSD has data");
96         
97         AliHLTEventSummary summary1;
98         summary1.SetTriggerClass(0x1);
99         
100         AliHLTEventSummary summary2;
101         summary2.SetTriggerClass(0x2);
102         
103         TFile* file = new TFile("testInputFile1.root", "RECREATE");
104         decision1.Write("triggerTPC");
105         decision2.Write("triggerMUON");
106         decision3.Write("triggerSSD");
107         summary2.Write("summary");
108         delete file;
109         
110         file = new TFile("testInputFile2.root", "RECREATE");
111         decision1.Write("triggerTPC");
112         summary2.Write("summary");
113         delete file;
114         
115         file = new TFile("testInputFile3.root", "RECREATE");
116         decision2.Write("triggerMUON");
117         summary1.Write("summary");
118         delete file;
119         
120         file = new TFile("testInputFile4.root", "RECREATE");
121         decision3.Write("triggerSSD");
122         summary2.Write("summary");
123         delete file;
124         
125         file = new TFile("testInputFile5.root", "RECREATE");
126         decision1.Write("triggerTPC");
127         decision2.Write("triggerMUON");
128         summary1.Write("summary");
129         delete file;
130         
131         file = new TFile("testInputFile6.root", "RECREATE");
132         decision1.Write("triggerTPC");
133         decision3.Write("triggerSSD");
134         summary2.Write("summary");
135         delete file;
136         
137         file = new TFile("testInputFile7.root", "RECREATE");
138         decision2.Write("triggerMUON");
139         decision3.Write("triggerSSD");
140         summary1.Write("summary");
141         delete file;
142         
143         file = new TFile("testInputFile8.root", "RECREATE");
144         delete file;
145         
146         if (loadedLibs)
147         {
148                 gSystem->Unload("libAliHLTTrigger.so");
149                 gSystem->Unload("libAliHLTMUON.so");
150                 gSystem->Unload("libAliHLTTRD.so");
151                 gSystem->Unload("libAliHLTUtil.so");
152         }
153 }
154
155 /**
156  * Runs a small global trigger test chain with the different configuration as specified
157  * in TriggerConfig.C.
158  * \param config  The configuration version to pass to TriggerConfig.C
159  * \param usecint  If true then the global trigger component uses CINT to interpret
160  *     the code rather than compiling it.
161  * \param debug  If true then the global trigger component generates extra debug
162  *     statements in the on the fly AliHLTGlobalTriggerImp_*.cxx file.
163  * \param numOfEvents  The number of events to run the chain for.
164  * \param customClass  Names the custom class that should be loaded from the file
165  *     <i>\<customClass\>.cxx</i>. This is useful for debugging only. i.e. you can
166  *     edit a generated logic file and test it by hand.
167  */
168 void RunTrigger(int config = 0, bool usecint = false, bool debug = false, int numOfEvents = 8, const char* customClass = NULL)
169 {
170         AliHLTSystem sys;
171         sys.ScanOptions("ECS=CTP_TRIGGER_CLASS=00:TRIGGER-ALL:00-01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17");
172         sys.LoadComponentLibraries("libAliHLTUtil.so");
173         sys.LoadComponentLibraries("libAliHLTTRD.so");
174         sys.LoadComponentLibraries("libAliHLTMUON.so");
175         sys.LoadComponentLibraries("libAliHLTTrigger.so");
176         if (debug)
177         {
178                 AliLog::SetGlobalLogLevel(AliLog::kMaxType);
179                 sys.SetGlobalLoggingLevel(kHLTLogAll);
180         }
181         
182         TString cmdline = "-datatype ROOTTOBJ 'HLT ' ";
183         for (int i = 1; i <= 8; i++)
184         {
185                 if (i > 1) cmdline += " -nextevent";
186                 cmdline += Form(" -datafile testInputFile%d.root", i);
187         }
188         AliHLTConfiguration pub("pub", "ROOTFilePublisher", NULL, cmdline.Data());
189         
190         cmdline = Form("-config $ALICE_ROOT/HLT/trigger/test/TriggerConfig.C(%d)"
191                 " -includepath $ALICE_ROOT/include -includepath $ALICE_ROOT/HLT/BASE"
192                 " -includepath $ALICE_ROOT/HLT/trigger -include AliHLTEventSummary.h",
193                 config
194                 );
195         if (customClass != NULL) cmdline += Form(" -usecode %s.cxx %s", customClass, customClass);
196         if (usecint) cmdline += " -cint";
197         if (debug) cmdline += " -debug";
198         AliHLTConfiguration proc("proc", "HLTGlobalTrigger", "pub", cmdline.Data());
199         
200         AliHLTConfiguration sink("sink", "ROOTFileWriter", "proc", "-datafile testOutputFile.root -concatenate-events");
201         
202         sys.BuildTaskList("sink");
203         sys.Run(
204                 numOfEvents,
205                 1,   // Stop chain at end of run.
206                 0x1, // Active CTP trigger mask.
207                 0,   // Time stamp.
208                 0    // Event type.
209         );
210 }
211
212 /**
213  * This method calls the RunTrigger method in an independant aliroot process.
214  * This is necessary since we get memory corruption if we run too many instances of
215  * AliHLTSystem in the same process.
216  */
217 void CallRunTrigger(
218                 int config = 0, bool usecint = false, bool debug = false,
219                 int numOfEvents = 8, const char* customClass = NULL,
220                 bool showOutput = false
221         )
222 {
223         const char* redirection = "> /dev/null";
224         const char* classNameString = "NULL";
225         if (showOutput) redirection = "";
226         if (customClass != NULL) classNameString = Form("\"%s\"", customClass);
227         const char* command = Form(
228                         "aliroot %s <<EOF\n"
229                         "gSystem->Load(\"libAliHLTUtil.so\");\n"
230                         "gSystem->Load(\"libAliHLTTRD.so\");\n"
231                         "gSystem->Load(\"libAliHLTMUON.so\");\n"
232                         "gSystem->Load(\"libAliHLTTrigger.so\");\n"
233                         "gSystem->SetIncludePath(\"-I${ALICE_ROOT}/include"
234                         " -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger\");\n"
235                         ".L $ALICE_ROOT/HLT/trigger/test/testGlobalTriggerComponent.C+\n"
236                         "RunTrigger(%d,%d,%d,%d,%s);\n"
237                         "EOF\n",
238                         redirection,
239                         config,
240                         usecint,
241                         debug,
242                         numOfEvents,
243                         classNameString
244                 );
245         gSystem->Exec(command);
246 }
247
248 /**
249  * Runs a global trigger test chain to test L0 software triggers.
250  * \param config  The configuration version to pass to TriggerConfig.C
251  * \param usecint  If true then the global trigger component uses CINT to interpret
252  *     the code rather than compiling it.
253  * \param debug  If true then the global trigger component generates extra debug
254  *     statements in the on the fly AliHLTGlobalTriggerImp_*.cxx file.
255  * \param customClass  Names the custom class that should be loaded from the file
256  *     <i>\<customClass\>.cxx</i>. This is useful for debugging only. i.e. you can
257  *     edit a generated logic file and test it by hand.
258  */
259 void RunTriggerSW(int config = 0, bool usecint = false, bool debug = false, const char* customClass = NULL)
260 {
261         AliHLTSystem sys;
262         sys.ScanOptions("ECS=CTP_TRIGGER_CLASS=00:TRIGGER-ALL:00-01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17");
263         sys.LoadComponentLibraries("libAliHLTUtil.so");
264         sys.LoadComponentLibraries("libAliHLTTRD.so");
265         sys.LoadComponentLibraries("libAliHLTMUON.so");
266         sys.LoadComponentLibraries("libAliHLTTrigger.so");
267         if (debug)
268         {
269                 AliLog::SetGlobalLogLevel(AliLog::kMaxType);
270                 sys.SetGlobalLoggingLevel(kHLTLogAll);
271         }
272         
273         TString cmdline = "-datatype ROOTTOBJ 'HLT ' ";
274         for (int i = 1; i <= 8; i++)
275         {
276                 if (i > 1) cmdline += " -nextevent";
277                 cmdline += Form(" -datafile testInputFile%d.root", i);
278         }
279         AliHLTConfiguration pub("pub", "ROOTFilePublisher", NULL, cmdline.Data());
280         
281         cmdline = Form("-config $ALICE_ROOT/HLT/trigger/test/TriggerConfig.C(%d)"
282                 " -includepath $ALICE_ROOT/include -includepath $ALICE_ROOT/HLT/BASE"
283                 " -includepath $ALICE_ROOT/HLT/trigger -include AliHLTEventSummary.h"
284                 " -process-all-events",
285                 config
286                 );
287         if (customClass != NULL) cmdline += Form(" -usecode %s.cxx %s", customClass, customClass);
288         if (usecint) cmdline += " -cint";
289         if (debug) cmdline += " -debug";
290         AliHLTConfiguration proc("proc", "HLTGlobalTrigger", "pub", cmdline.Data());
291         
292         AliHLTConfiguration sink("sink", "ROOTFileWriter", "proc", "-datafile testOutputFile.root -concatenate-events");
293         
294         sys.BuildTaskList("sink");
295         sys.Run(
296                 1,   // Number of events to process.
297                 0,   // Stop chain at end of run.
298                 0x1, // Active CTP trigger mask.
299                 0,   // Time stamp.
300                 gkAliEventTypeSoftware  // Event type.
301         );
302         sys.Run(
303                 1,   // Number of events to process.
304                 0,   // Stop chain at end of run.
305                 0x1, // Active CTP trigger mask.
306                 0,   // Time stamp.
307                 gkAliEventTypeCalibration  // Event type.
308         );
309         sys.Run(
310                 1,   // Number of events to process.
311                 1,   // Stop chain at end of run.
312                 0x1, // Active CTP trigger mask.
313                 0,   // Time stamp.
314                 0    // Event type.
315         );
316 }
317
318 /**
319  * This method calls the RunTriggerSW method in an independant aliroot process.
320  * This is necessary since we get memory corruption if we run too many instances of
321  * AliHLTSystem in the same process.
322  */
323 void CallRunTriggerSW(
324                 int config = 0, bool usecint = false, bool debug = false,
325                 const char* customClass = NULL, bool showOutput = false
326         )
327 {
328         const char* redirection = "> /dev/null";
329         const char* classNameString = "NULL";
330         if (showOutput) redirection = "";
331         if (customClass != NULL) classNameString = Form("\"%s\"", customClass);
332         const char* command = Form(
333                         "aliroot %s <<EOF\n"
334                         "gSystem->Load(\"libAliHLTUtil.so\");\n"
335                         "gSystem->Load(\"libAliHLTTRD.so\");\n"
336                         "gSystem->Load(\"libAliHLTMUON.so\");\n"
337                         "gSystem->Load(\"libAliHLTTrigger.so\");\n"
338                         "gSystem->SetIncludePath(\"-I${ALICE_ROOT}/include"
339                         " -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger\");\n"
340                         ".L $ALICE_ROOT/HLT/trigger/test/testGlobalTriggerComponent.C+\n"
341                         "RunTriggerSW(%d,%d,%d,%s);\n"
342                         "EOF\n",
343                         redirection,
344                         config,
345                         usecint,
346                         debug,
347                         classNameString
348                 );
349         gSystem->Exec(command);
350 }
351
352 /**
353  * Checks that a particular decision is as expected and prints error messages
354  * if it is not.
355  * \param testName  The name of the test being run.
356  * \param eventNum  The number of the event being checked.
357  * \param decision  The global trigger decision being checked.
358  * \param expectedResult  The expected global trigger result.
359  * \param expectedDomain  The expected resulting global trigger domain.
360  * \param expectedDescription  The expected resulting trigger description.
361  * \returns true if the decision is as expected.
362  */
363 bool Check(
364                 const char* testName,
365                 int eventNum,
366                 AliHLTGlobalTriggerDecision* decision,
367                 bool expectedResult,
368                 AliHLTTriggerDomain expectedDomain,
369                 TString expectedDescription
370         )
371 {
372         if (decision == NULL)
373         {
374                 cerr << "ERROR (Test: " << testName
375                      << "): No decision found where expected for event "
376                      << eventNum << "." << endl;
377                 return false;
378         }
379         if (decision->Result() != expectedResult)
380         {
381                 cerr << "ERROR (Test: " << testName
382                      << "): The result does not match the expected value for event "
383                      << eventNum << ". Got " << decision->Result() << " but expected "
384                      << expectedResult << "." << endl;
385                 return false;
386         }
387         if (decision->TriggerDomain() != expectedDomain)
388         {
389                 cerr << "ERROR (Test: " << testName
390                      << "): The domain does not match the expected value for event "
391                      << eventNum << ". Got:" << endl;
392                 decision->TriggerDomain().Print();
393                 cerr << "but expected:" << endl;
394                 expectedDomain.Print();
395                 return false;
396         }
397         if (decision->Description() != expectedDescription)
398         {
399                 cerr << "ERROR (Test: " << testName
400                      << "): The description does not match the expected value for event "
401                      << eventNum << ". Got '" << decision->Description() << "' but expected '"
402                      << expectedDescription << "'." << endl;
403                 return false;
404         }
405         return true;
406 }
407
408
409 /// Routine for checking the result of the PriorityGroupTestConfig() config in TriggerConfig.C
410 bool CheckPriorityGroupTestConfig(const char* testName = "Priority group config")
411 {
412         AliHLTGlobalTriggerDecision* decision = NULL;
413         bool result = false;
414         
415         AliHLTTriggerDomain domainTPC("CLUSTERS:TPC ,TRACKS:TPC ");
416         domainTPC.Add(AliHLTReadoutList("TPC"));
417         AliHLTTriggerDomain domainMUON("TRACKS:MUON");
418         domainMUON.Add(AliHLTReadoutList("MUONTRK"));
419         domainMUON.Add(AliHLTReadoutList("MUONTRG"));
420         AliHLTTriggerDomain domainSSD("*******:SSD ");
421         domainSSD.Add(AliHLTReadoutList("ITSSSD"));
422
423         TFile* file = new TFile("testOutputFile.root", "READ");
424         
425         // Triggers in events (i.e. input triggers):
426         // event 1: TPC MUON SSD
427         // event 2: TPC
428         // event 3: MUON
429         // event 4: SSD
430         // event 5: TPC MUON
431         // event 6: TPC SSD
432         // event 7: MUON SSD
433         // event 8: (empty)
434         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;1"));
435         result = Check(testName, 1, decision, true, domainSSD, "Fast SSD trigger");
436         if (! result) goto cleanup;
437         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;2"));
438         result = Check(testName, 2, decision, true, domainTPC, "TPC trigger");
439         if (! result) goto cleanup;
440         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;3"));
441         result = Check(testName, 3, decision, true, domainMUON, "MUON trigger");
442         if (! result) goto cleanup;
443         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;4"));
444         result = Check(testName, 4, decision, true, domainSSD, "MUON trigger");
445         if (! result) goto cleanup;
446         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;5"));
447         result = Check(testName, 5, decision, true, domainMUON, "MUON trigger");
448         if (! result) goto cleanup;
449         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;6"));
450         result = Check(testName, 6, decision, true, domainSSD, "Fast SSD trigger");
451         if (! result) goto cleanup;
452         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;7"));
453         result = Check(testName, 7, decision, true, domainMUON | domainSSD, "MUON trigger");
454         if (! result) goto cleanup;
455         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;8"));
456         result = Check(testName, 8, decision, false, AliHLTTriggerDomain(), "No trigger");
457         if (! result) goto cleanup;
458         
459         delete file;
460         return true;
461         
462 cleanup:
463         if (decision != NULL)
464         {
465                 cout << "========== Dumping incorrect decision ========== " << endl;
466                 decision->Print();
467         }
468         delete file;
469         return false;
470 }
471
472
473 /// Routine for checking the result of the SingleGroupTestConfig() config in TriggerConfig.C
474 bool CheckSingleGroupTestConfig(const char* testName = "Single group config")
475 {
476         AliHLTGlobalTriggerDecision* decision = NULL;
477         bool result = false;
478         
479         AliHLTTriggerDomain domainTPC("CLUSTERS:TPC ,TRACKS:TPC ");
480         domainTPC.Add(AliHLTReadoutList("TPC"));
481         AliHLTTriggerDomain domainMUON("TRACKS:MUON");
482         domainMUON.Add(AliHLTReadoutList("MUONTRK"));
483         domainMUON.Add(AliHLTReadoutList("MUONTRG"));
484         AliHLTTriggerDomain domainSSD("*******:SSD ");
485         domainSSD.Add(AliHLTReadoutList("ITSSSD"));
486
487         TFile* file = new TFile("testOutputFile.root", "READ");
488         
489         // Triggers in events (i.e. input triggers):
490         // event 1: TPC MUON SSD
491         // event 2: TPC
492         // event 3: MUON
493         // event 4: SSD
494         // event 5: TPC MUON
495         // event 6: TPC SSD
496         // event 7: MUON SSD
497         // event 8: (empty)
498         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;1"));
499         result = Check(testName, 1, decision, true, domainTPC | domainMUON | domainSSD, "TPC trigger,MUON trigger,SSD trigger");
500         if (! result) goto cleanup;
501         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;2"));
502         result = Check(testName, 2, decision, true, domainTPC, "TPC trigger");
503         if (! result) goto cleanup;
504         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;3"));
505         result = Check(testName, 3, decision, true, domainMUON, "MUON trigger");
506         if (! result) goto cleanup;
507         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;4"));
508         result = Check(testName, 4, decision, true, domainSSD, "SSD trigger");
509         if (! result) goto cleanup;
510         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;5"));
511         result = Check(testName, 5, decision, true, domainTPC | domainMUON, "TPC trigger,MUON trigger");
512         if (! result) goto cleanup;
513         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;6"));
514         result = Check(testName, 6, decision, true, domainTPC | domainSSD, "TPC trigger,SSD trigger");
515         if (! result) goto cleanup;
516         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;7"));
517         result = Check(testName, 7, decision, true, domainMUON | domainSSD, "MUON trigger,SSD trigger");
518         if (! result) goto cleanup;
519         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;8"));
520         result = Check(testName, 8, decision, false, AliHLTTriggerDomain(), "");
521         if (! result) goto cleanup;
522         
523         delete file;
524         return true;
525         
526 cleanup:
527         if (decision != NULL)
528         {
529                 cout << "========== Dumping incorrect decision ========== " << endl;
530                 decision->Print();
531         }
532         delete file;
533         return false;
534 }
535
536
537 /// Routine for checking the result of the PrescalarTestConfig() config in TriggerConfig.C
538 bool CheckPrescalarTestConfig(const char* testName = "Prescalar config")
539 {
540         AliHLTGlobalTriggerDecision* decision = NULL;
541         bool result = false;
542         
543         AliHLTTriggerDomain domainTPC("CLUSTERS:TPC ,TRACKS:TPC ");
544         domainTPC.Add(AliHLTReadoutList("TPC"));
545         AliHLTTriggerDomain domainMUON("TRACKS:MUON");
546         domainMUON.Add(AliHLTReadoutList("MUONTRK"));
547         domainMUON.Add(AliHLTReadoutList("MUONTRG"));
548         AliHLTTriggerDomain domainSSD("*******:SSD ");
549         domainSSD.Add(AliHLTReadoutList("ITSSSD"));
550         AliHLTTriggerDomain defaultDomain("*******:HLT ");
551
552         TFile* file = new TFile("testOutputFile.root", "READ");
553         
554         // Triggers in events (i.e. input triggers):
555         // event 1: TPC MUON SSD
556         // event 2: TPC
557         // event 3: MUON
558         // event 4: SSD
559         // event 5: TPC MUON
560         // event 6: TPC SSD
561         // event 7: MUON SSD
562         // event 8: (empty)
563         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;1"));
564         result = Check(testName, 1, decision, true, domainTPC, "TPC trigger");
565         if (! result) goto cleanup;
566         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;2"));
567         result = Check(testName, 2, decision, false, defaultDomain, "No trigger");
568         if (! result) goto cleanup;
569         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;3"));
570         result = Check(testName, 3, decision, true, domainMUON, "MUON trigger");
571         if (! result) goto cleanup;
572         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;4"));
573         result = Check(testName, 4, decision, false, defaultDomain, "No trigger");
574         if (! result) goto cleanup;
575         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;5"));
576         result = Check(testName, 5, decision, true, domainMUON, "MUON trigger");
577         if (! result) goto cleanup;
578         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;6"));
579         result = Check(testName, 6, decision, true, domainTPC, "TPC trigger");
580         if (! result) goto cleanup;
581         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;7"));
582         result = Check(testName, 7, decision, true, domainMUON, "MUON trigger");
583         if (! result) goto cleanup;
584         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;8"));
585         result = Check(testName, 8, decision, false, defaultDomain, "No trigger");
586         if (! result) goto cleanup;
587         
588         delete file;
589         return true;
590         
591 cleanup:
592         if (decision != NULL)
593         {
594                 cout << "========== Dumping incorrect decision ========== " << endl;
595                 decision->Print();
596         }
597         delete file;
598         return false;
599 }
600
601
602 /// Routine for checking the result of the SymbolTestConfig() config in TriggerConfig.C
603 bool CheckSymbolTestConfig(const char* testName = "Symbol config")
604 {
605         AliHLTGlobalTriggerDecision* decision = NULL;
606         bool result = false;
607         
608         AliHLTTriggerDomain domainAll("*******:***,-DAQRDOUT:TST");
609         AliHLTTriggerDomain domainPHOS("CLUSTERS:PHOS,TRACKS:PHOS");
610         AliHLTTriggerDomain domainTPC("CLUSTERS:TPC ,TRACKS:TPC ");
611         domainTPC.Add(AliHLTReadoutList("TPC"));
612         AliHLTTriggerDomain domainMUON("TRACKS:MUON");
613         domainMUON.Add(AliHLTReadoutList("MUONTRK"));
614         domainMUON.Add(AliHLTReadoutList("MUONTRG"));
615         AliHLTTriggerDomain domainSSD("*******:SSD ");
616         domainSSD.Add(AliHLTReadoutList("ITSSSD"));
617
618         TFile* file = new TFile("testOutputFile.root", "READ");
619         
620         // Triggers in events (i.e. input triggers) and trigger classes in AliHLTEventSummary:
621         // event 1: TPC MUON SSD, 0x2
622         // event 2: TPC         , 0x2
623         // event 3: MUON        , 0x1
624         // event 4: SSD         , 0x2
625         // event 5: TPC MUON    , 0x1
626         // event 6: TPC SSD     , 0x2
627         // event 7: MUON SSD    , 0x1
628         // event 8: (empty)     , 0x0
629         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;1"));
630         result = Check(testName, 1, decision, true, domainAll - AliHLTTriggerDomain("DAQRDOUT:EMC"), "Pass through");
631         if (! result) goto cleanup;
632         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;2"));
633         result = Check(testName, 2, decision, true, domainTPC | domainPHOS, "Trigger class 2");
634         if (! result) goto cleanup;
635         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;3"));
636         result = Check(testName, 3, decision, false, AliHLTTriggerDomain(), "");
637         if (! result) goto cleanup;
638         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;4"));
639         result = Check(testName, 4, decision, true, domainPHOS, "Trigger class 2");
640         if (! result) goto cleanup;
641         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;5"));
642         result = Check(testName, 5, decision, true, domainAll - AliHLTTriggerDomain("DAQRDOUT:EMC"), "Pass through");
643         if (! result) goto cleanup;
644         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;6"));
645         result = Check(testName, 6, decision, true, domainTPC | domainPHOS, "Trigger class 2");
646         if (! result) goto cleanup;
647         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;7"));
648         result = Check(testName, 7, decision, false, AliHLTTriggerDomain(), "");
649         if (! result) goto cleanup;
650         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;8"));
651         result = Check(testName, 8, decision, false, AliHLTTriggerDomain(), "");
652         if (! result) goto cleanup;
653         
654         delete file;
655         return true;
656         
657 cleanup:
658         if (decision != NULL)
659         {
660                 cout << "========== Dumping incorrect decision ========== " << endl;
661                 decision->Print();
662         }
663         delete file;
664         return false;
665 }
666
667
668 /// Routine for checking the result of the ComplexTestConfig() config in TriggerConfig.C
669 bool CheckComplexTestConfig(const char* testName = "Complex config")
670 {
671         AliHLTGlobalTriggerDecision* decision = NULL;
672         bool result = false;
673         
674         AliHLTTriggerDomain domainAll("*******:***,-DAQRDOUT:TST,-DAQRDOUT:EMC");
675         AliHLTTriggerDomain domainPHOS("CLUSTERS:PHOS,TRACKS:PHOS");
676         AliHLTTriggerDomain domainTPC("CLUSTERS:TPC ,TRACKS:TPC ");
677         domainTPC.Add(AliHLTReadoutList("TPC"));
678         AliHLTTriggerDomain domainMUON("TRACKS:MUON");
679         domainMUON.Add(AliHLTReadoutList("MUONTRK"));
680         domainMUON.Add(AliHLTReadoutList("MUONTRG"));
681         AliHLTTriggerDomain domainSSD("*******:SSD ");
682         domainSSD.Add(AliHLTReadoutList("ITSSSD"));
683
684         TFile* file = new TFile("testOutputFile.root", "READ");
685         
686         // Triggers in events (i.e. input triggers) and trigger classes in AliHLTEventSummary:
687         // event 1: TPC MUON SSD, 0x2
688         // event 2: TPC         , 0x2
689         // event 3: MUON        , 0x1
690         // event 4: SSD         , 0x2
691         // event 5: TPC MUON    , 0x1
692         // event 6: TPC SSD     , 0x2
693         // event 7: MUON SSD    , 0x1
694         // event 8: (empty)     , 0x0
695         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;1"));
696         result = Check(testName, 1, decision, true, domainAll, "Pass through");
697         if (! result) goto cleanup;
698         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;2"));
699         result = Check(testName, 2, decision, true, domainTPC, "Slow trigger");
700         if (! result) goto cleanup;
701         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;3"));
702         result = Check(testName, 3, decision, true, domainMUON, "MUON trigger 2");
703         if (! result) goto cleanup;
704         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;4"));
705         result = Check(testName, 4, decision, true, domainSSD | domainPHOS, "SSD trigger 2");
706         if (! result) goto cleanup;
707         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;5"));
708         result = Check(testName, 5, decision, true, domainMUON, "MUON trigger 2");
709         if (! result) goto cleanup;
710         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;6"));
711         result = Check(testName, 6, decision, true, domainSSD | domainPHOS, "SSD trigger 2");
712         if (! result) goto cleanup;
713         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;7"));
714         result = Check(testName, 7, decision, true, domainSSD | domainMUON, "SSD trigger 1,MUON trigger 1");
715         if (! result) goto cleanup;
716         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;8"));
717         result = Check(testName, 8, decision, true, domainAll, "Pass through");
718         if (! result) goto cleanup;
719         
720         delete file;
721         return true;
722         
723 cleanup:
724         if (decision != NULL)
725         {
726                 cout << "========== Dumping incorrect decision ========== " << endl;
727                 decision->Print();
728         }
729         delete file;
730         return false;
731 }
732
733
734 typedef bool (*CheckFunctionType)(const char* testName);
735
736 /**
737  * This will check the results of a global trigger run with a particular checking
738  * routine and for different combinations of -cint and -debug flags passed to the
739  * global trigger component.
740  * It is important to check these flag combinations to make sure that everything
741  * is functioning the same under all the different combinations as it should.
742  * \param function  The checking routine to use.
743  * \param version  The trigger menu configuration version to use in <i>RunTrigger</i>.
744  * \param testName  The name of the test being run.
745  * \param numOfEvents  The number of events to run the chain for.
746  * \param customClass  Name of the custom class as passed to <i>RunTrigger</i>.
747  * \param showOutput  If true then the output from the RunTrigger method is not suppressed.
748  * \returns true if the different checks succeeded and false otherwise.
749  */
750 bool CheckDifferentModes(
751                 CheckFunctionType function, int version, const char* testName,
752                 int numOfEvents = 8, const char* customClass = NULL,
753                 bool showOutput = false
754         )
755 {
756         TString name = testName;
757         name += " in debug mode";
758         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
759         CallRunTrigger(version, false, true, numOfEvents, customClass, showOutput);
760         if (! function(testName)) return false;
761         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
762         
763         name = testName;
764         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
765         CallRunTrigger(version, false, false, numOfEvents, customClass, showOutput);
766         if (! function(testName)) return false;
767         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
768         
769         name = testName;
770         name += " interpreted with CINT in debug mode";
771         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
772         CallRunTrigger(version, true, true, numOfEvents, customClass, showOutput);
773         if (! function(testName)) return false;
774         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
775         
776         name = testName;
777         name += " interpreted with CINT";
778         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
779         CallRunTrigger(version, true, false, numOfEvents, customClass, showOutput);
780         if (! function(testName)) return false;
781         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
782         
783         return true;
784 }
785
786 /**
787  * This routine is used to check if the global Trigger counters are correct.
788  * \param testName  The name of the test being run.
789  * \param eventNum  The number of the event being checked.
790  * \param decision  The global trigger decision being checked.
791  * \param expectedCounters  The expected counters.
792  * \returns true if the decision is as expected.
793  */
794 bool CheckCounters(
795                 const char* testName,
796                 int eventNum,
797                 AliHLTGlobalTriggerDecision* decision,
798                 const TArrayL64& expectedCounters
799         )
800 {
801         if (decision->Counters().GetSize() != expectedCounters.GetSize())
802         {
803                 cerr << "ERROR (Test: " << testName
804                      << "): The result does not have the required number of counters for event "
805                      << eventNum << ". Got " << decision->Counters().GetSize() << " but expected "
806                      << expectedCounters.GetSize() << "." << endl;
807                 return false;
808         }
809         for (Int_t i = 0; i < expectedCounters.GetSize(); ++i)
810         {
811                 if (decision->Counters()[i] != expectedCounters[i])
812                 {
813                         cerr << "ERROR (Test: " << testName
814                              << "): The result does not have the correct counter value for event "
815                              << eventNum << ". Got a value " << decision->Counters()[i]
816                              << " for counter " << i << ", but expected a value of "
817                              << expectedCounters[i] << "." << endl;
818                         return false;
819                 }
820         }
821         return true;
822 }
823
824 /// Routine for checking the result of the SoftwareTriggersTestConfig() config in TriggerConfig.C
825 bool CheckSoftwareTriggerTestConfig(const char* testName = "Software trigger config")
826 {
827         AliHLTGlobalTriggerDecision* decision = NULL;
828         bool result = false;
829         
830         AliHLTTriggerDomain domainPHOS("*******:PHOS");
831         domainPHOS.Remove(AliHLTReadoutList("PHOS"));
832         AliHLTTriggerDomain domainSPD("*******:SPD");
833         domainSPD.Remove(AliHLTReadoutList("ITSSPD"));
834         AliHLTTriggerDomain domainMUON("TRACKS:MUON");
835         domainMUON.Add(AliHLTReadoutList("MUONTRK MUONTRG"));
836
837         TFile* file = new TFile("testOutputFile.root", "READ");
838         TArrayL64 expectedCounters;
839         expectedCounters.Set(6);
840         
841         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;1"));
842         result = Check(testName, 1, decision, true, AliHLTTriggerDomain(), "Start of data");
843         if (! result) goto cleanup;
844         expectedCounters[0] = 1; expectedCounters[5] = 1;
845         result = CheckCounters(testName, 1, decision, expectedCounters);
846         if (! result) goto cleanup;
847         
848         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;2"));
849         result = Check(testName, 2, decision, true, domainSPD, "Software trigger");
850         if (! result) goto cleanup;
851         expectedCounters[2] = 1; expectedCounters[5] = 2;
852         result = CheckCounters(testName, 2, decision, expectedCounters);
853         if (! result) goto cleanup;
854         
855         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;3"));
856         result = Check(testName, 3, decision, true, domainPHOS, "Calibration trigger");
857         if (! result) goto cleanup;
858         expectedCounters[3] = 1; expectedCounters[5] = 3;
859         result = CheckCounters(testName, 3, decision, expectedCounters);
860         if (! result) goto cleanup;
861         
862         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;4"));
863         result = Check(testName, 4, decision, true, domainMUON, "MUON trigger");
864         if (! result) goto cleanup;
865         expectedCounters[4] = 1; expectedCounters[5] = 4;
866         result = CheckCounters(testName, 4, decision, expectedCounters);
867         if (! result) goto cleanup;
868         
869         decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;5"));
870         result = Check(testName, 5, decision, true, AliHLTTriggerDomain(), "End of data");
871         if (! result) goto cleanup;
872         expectedCounters[1] = 1; expectedCounters[5] = 5;
873         result = CheckCounters(testName, 5, decision, expectedCounters);
874         if (! result) goto cleanup;
875         
876         delete file;
877         return true;
878         
879 cleanup:
880         if (decision != NULL)
881         {
882                 cout << "========== Dumping incorrect decision ========== " << endl;
883                 decision->Print();
884         }
885         delete file;
886         return false;
887 }
888
889 /**
890  * This method performs the same task as for CheckDifferentModes, but trying to
891  * test the behaviour of the global HLT trigger component with L0 software triggers.
892  * \param version  The trigger menu configuration version to use in <i>RunTrigger</i>.
893  * \param testName  The name of the test being run.
894  * \param customClass  Name of the custom class as passed to <i>RunTrigger</i>.
895  * \param showOutput  If true then the output from the RunTriggerSW method is not suppressed.
896  * \returns true if the different checks succeeded and false otherwise.
897  */
898 bool CheckDifferentSWTestModes(
899                 int version, const char* testName,
900                 const char* customClass = NULL, bool showOutput = false
901         )
902 {
903         TString name = testName;
904         name += " in debug mode";
905         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
906         CallRunTriggerSW(version, false, true, customClass, showOutput);
907         if (! CheckSoftwareTriggerTestConfig(testName)) return false;
908         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
909         
910         name = testName;
911         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
912         CallRunTriggerSW(version, false, false, customClass, showOutput);
913         if (! CheckSoftwareTriggerTestConfig(testName)) return false;
914         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
915         
916         name = testName;
917         name += " interpreted with CINT in debug mode";
918         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
919         CallRunTriggerSW(version, true, true, customClass, showOutput);
920         if (! CheckSoftwareTriggerTestConfig(testName)) return false;
921         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
922         
923         name = testName;
924         name += " interpreted with CINT";
925         cout << "#################### Running test: " << name.Data() << " ####################" << endl;
926         CallRunTriggerSW(version, true, false, customClass, showOutput);
927         if (! CheckSoftwareTriggerTestConfig(testName)) return false;
928         gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
929         
930         return true;
931 }
932
933 /**
934  * Runs several tests for the AliHLTGlobalTriggerComponent class.
935  * We specifically test if the global trigger menu configuration is interpreted
936  * correctly and the trigger logic generated correctly on the fly.
937  * \param configVersion  The appropriate version number of the config being tested
938  *     which is passed to TriggerConfig.C.
939  * \param customClass  Name of the custom class as passed to <i>CheckDifferentModes</i>.
940  * \returns true if the different checks succeeded and false otherwise.
941  * \param numOfEvents  The number of events to run the chain for.
942  * \returns true if all the tests succeeded and false otherwise.
943  */
944 bool testGlobalTriggerComponent(int configVersion = -1, const char* customClass = NULL, int numOfEvents = 8)
945 {
946         GenerateInputData();
947         
948         if (configVersion != -1)
949         {
950                 CheckFunctionType function = NULL;
951                 switch (configVersion)
952                 {
953                 case 0: function = CheckPriorityGroupTestConfig; break;
954                 case 1: function = CheckSingleGroupTestConfig; break;
955                 case 2: function = CheckPrescalarTestConfig; break;
956                 case 3: function = CheckSymbolTestConfig; break;
957                 case 4: function = CheckComplexTestConfig; break;
958                 case 5: break;
959                 default:
960                         cerr << "ERROR: Invalid value for configVersion specified." << endl;
961                         return false;
962                 }
963                 bool result = false;
964                 if (configVersion != 5)
965                 {
966                         result = CheckDifferentModes(
967                                         function,
968                                         configVersion,
969                                         Form("Config version %d", configVersion),
970                                         numOfEvents,
971                                         customClass,
972                                         true
973                                 );
974                 }
975                 else
976                 {
977                         result = CheckDifferentSWTestModes(
978                                         configVersion,
979                                         Form("Config version %d", configVersion),
980                                         customClass,
981                                         true
982                                 );
983                 }
984                 return result;
985         }
986         
987         if (! CheckDifferentModes(CheckPriorityGroupTestConfig, 0, "Priority group config", numOfEvents, customClass)) return false;
988         if (! CheckDifferentModes(CheckSingleGroupTestConfig, 1, "Single group config", numOfEvents, customClass)) return false;
989         if (! CheckDifferentModes(CheckPrescalarTestConfig, 2, "Prescalar config", numOfEvents, customClass)) return false;
990         if (! CheckDifferentModes(CheckSymbolTestConfig, 3, "Symbol config", numOfEvents, customClass)) return false;
991         if (! CheckDifferentModes(CheckComplexTestConfig, 4, "Complex config", numOfEvents, customClass)) return false;
992         if (! CheckDifferentSWTestModes(5, "Software trigger config", customClass)) return false;
993         
994         // Cleanup all temporary files generated.
995         gSystem->Exec("rm -f testOutputFile.root testInputFile*.root AliHLTGlobalTriggerImpl*");
996         return true;
997 }
998
999
1000 #ifndef __MAKECINT__
1001
1002 int main(int /*argc*/, const char** /*argv*/)
1003 {
1004         bool resultOk = testGlobalTriggerComponent();
1005         if (not resultOk) return 1;
1006         return 0;
1007 }
1008
1009 #endif // __MAKECINT__