AnalysisTestFramework.h

00001 #ifndef ANALYSISTESTFRAMEWORK_H
00002 #define ANALYSISTESTFRAMEWORK_H
00003 
00004 #include <vector>
00005 #include <string>
00006 #include <algorithm>
00007 #include <is/info.h>
00008 #include <is/infodictionary.h>
00009 #include <is/infoiterator.h>
00010 #include <boost/shared_ptr.hpp>
00011 #include <iostream>
00012 #include <TTree.h>
00013 #include <TApplication.h>
00014 #include <TFile.h>
00015 #include <TROOT.h>
00016 
00017 #include "Sct/IS/IOManagerIS.h"
00018 #include "Sct/Env.h"
00019 #include "Sct/SctNames.h"
00020 #include "Sct/OmniMarshalling.h"
00021 
00022 #include "../SCTTestAPI/ModuleData.h"
00023 #include "../SCTTestAPI/XmlSummaryFile.h"
00024 #include "../SCTTestAPI/SctTestApi.hh"
00025 
00026 using namespace Sct::IS;
00027 
00028 class TApplication;
00029 class TFile;
00030 class TTree;
00031 
00032 template<typename T>
00033 class AnalysisTestFramework {
00034 public:   
00040     AnalysisTestFramework(string isFilter=".*TestResult", string isServer="TestData");
00041     virtual ~AnalysisTestFramework(){}
00042     
00043     void analyzeAll(int argc, char** argv);
00044     
00048     void printHelp();
00049     
00053     int getExitCode() {return exitCode;}
00054     
00055 protected:
00061     virtual int handleArg(int argc, int i, char** argv);
00062     
00066     virtual void printAdditionalArgs() {}
00067     
00071     virtual void printHelpHeader();
00072     
00073     virtual void summaryOutput() {}
00074     
00080     virtual void doModule(string serialNumber);
00081     
00086     virtual vector<boost::shared_ptr<T> > readData(string serialNumber);
00087     
00091     virtual void publishData(/*SctTestApiStatus* status*/) {}
00092     
00096     virtual void downloadData(string serialNumber) {}
00097     
00098     virtual void compare(const T& t) {}
00099     
00100     virtual void setup() {}
00101         
00102     virtual void tearDown();
00103     
00104     int exitCode;   //The exit code
00105     bool readOnly;  //If true, only read and compare data, don't analyze
00106     bool debug;
00107     SctTestApi::HighLevelApi_var highLevelApi; //The high-level api
00108     unsigned int nModules;      //The number of modules in the list
00109     unsigned int nSkip;         //The number of modules to skip from the input file
00110     list<string> modules;             //The modules to do
00111     TFile* file;                    //Output file
00112     TTree* tree;                  //Output tree
00113     SctTest::ModuleData moduleData;              //Here we hold all the info about the tests
00114     unsigned int maxModules;        //Default Max number of modules to test
00115     unsigned int nData;         //The number of data objects to read
00116     string isFilter;            //To choose the wanted objects    
00117     string isServer;            //Holds the ISServer where we wait for object - default TestData
00118     list<string> ignoreModules;     //A list of modules to be ignored    
00119     string ignoreFile;          //The name of a file used for ignoring 'problem' modules
00120     
00121 private:    
00122     void loadIgnoreFile();
00123     void handleArgs(int argc, char** argv);
00124     static void getRootApp();
00125 };
00126 
00127 template<typename T>
00128 vector<shared_ptr<T> > AnalysisTestFramework<T>::readData(string serialNumber) {
00129     string filter = isFilter + ".*" + serialNumber;
00130     while (true) {
00131     ISInfoIterator it(SctNames::getPartition(), isServer.c_str(), filter.c_str() );
00132     ISInfoDictionary dict(SctNames::getPartition());
00133     //cout << it.entries() << " for isServer: " << isServer << " and filter: " << filter << " waiting for: " << nData << endl;
00134     if (it.entries() == nData) {
00135         vector<shared_ptr<T> > data;
00136         while (it()) {
00137         boost::shared_ptr<Serializable> ob = IOManagerIS::instance().read(it);
00138         boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(ob);
00139         if (!result)
00140             throw IllegalStateError(string("Failed to read test: ") + it.name(), __FILE__, __LINE__);
00141         data.push_back(result);
00142         }
00143         return data;
00144     }
00145     sleep(1);
00146     }
00147 }
00148 
00152 template<typename T>
00153 void AnalysisTestFramework<T>::tearDown() {
00154     file->Write();
00155     file->Close();
00156     delete file;
00157 }
00158 
00159 template<typename T>
00160 void AnalysisTestFramework<T>::doModule(string serialNumber) {
00161     highLevelApi->setModuleSerial(copyStringToCorba(serialNumber));
00162     try {
00163       if (!readOnly) publishData(/*&status*/);
00164     } catch (...) {
00165         std::cout << "LESTERDEBUGWARNING 9274 in " << __FILE__ << std::endl;
00166       cerr << "Error publishing data" <</* status.returnCode << */endl;
00167       return;
00168     }
00169     
00170 
00171     try {
00172     downloadData(serialNumber);    
00173     vector<shared_ptr<T> > ob = readData(serialNumber);
00174     for (unsigned int i=0; i<ob.size(); ++i) {
00175         compare(*ob[i]);
00176     }
00177     } catch(Throwable& e) {
00178     e.sendToMrs(MRS_ERROR);
00179     }
00180 }
00181 
00182 
00183 template<typename T>
00184 void AnalysisTestFramework<T>::printHelpHeader() {
00185     cout << "RetrieveAndCompare [-n <num>] [-r] [-s <serials>] [-h/--help]" << endl;
00186     cout << "Compares SCTDAQ and SctRodDaq analyses" << endl;
00187     cout << "Arguments: " << endl;
00188 }
00189 
00190 template<typename T>
00191 void AnalysisTestFramework<T>::printHelp() {
00192     printHelpHeader();
00193     cout << "-n <num>:     Do up to <num> modules only, otherwise do all" << endl;
00194     cout << "-r:           Read only - Useful for a re-run" << endl;
00195     cout << "-j <num>:     Skip the first <num> modules in the config files" << endl;
00196     cout << "-h/--help:    Print this help" << endl;
00197     cout << "-i <file>:    Ignore file - a file with serial numbers, 1 per line, that will be ignored - useful for 'problem' modules" << endl;
00198     cout << "-s <serials>: All arguments after -s are assumed to be module serial numbers" << endl;
00199     printAdditionalArgs();
00200     
00201     exit(0);
00202 }
00203 
00204 template<typename T>
00205 int AnalysisTestFramework<T>::handleArg(int argc, int i, char** argv) {
00206     printHelp();
00207     return i;
00208 }
00209 
00210 
00211 template<typename T>
00212 void AnalysisTestFramework<T>::handleArgs(int argc, char** argv) {
00213     for (int i=1; i<argc; ++i) {
00214     if (string(argv[i]) == "-s") {
00215         for (int j=i+1; j<argc; ++j) {
00216         modules.push_back(argv[j]);
00217         ++nModules;
00218         }
00219         return;
00220     }
00221     
00222     if (string(argv[i]) == "-n") {
00223         if (i+1 == argc) printHelp();
00224         istringstream iss(argv[++i]);
00225         iss >> maxModules;
00226     } else if (string(argv[i]) == "-r") {
00227         readOnly = true;
00228     } else if (string(argv[i]) == "-j") {
00229         if (i+1 == argc) printHelp();
00230         istringstream iss(argv[++i]);
00231         iss >> nSkip;
00232     } else if (string(argv[i]) == "-i") {
00233         if (i+1 == argc) printHelp();
00234         ignoreFile = argv[++i];
00235     } else {
00236         i = handleArg(argc, i, argv);
00237     }
00238     
00239     }
00240 }
00241 
00242 
00243 template<typename T>
00244 void AnalysisTestFramework<T>::getRootApp() {
00245     //Create TApplication - necessary to prevent batch mode and no graphics on later ROOT versions
00246     //static TApplication myapp("myapp", 0, 0);
00247     gROOT->SetBatch(false);
00248     //return myapp;
00249 }
00250 
00251 template<typename T>
00252 void AnalysisTestFramework<T>::loadIgnoreFile() {
00253     if (ignoreFile.length()==0) return;
00254     ifstream file(ignoreFile.c_str());
00255     if (!file.is_open() || !file.good()) {
00256     cerr << "Unable to open ignore file: " << ignoreFile << endl;
00257     return;
00258     }   
00259     string serial;
00260     while (file.good()) {
00261     file >> serial;
00262     if (serial[0] != '#' && serial.length() == 14 && count(ignoreModules.begin(), ignoreModules.end(), serial)==0) {
00263         ignoreModules.push_back(serial);
00264     }
00265     file.ignore(256, '\n');
00266     }
00267 }
00268 
00269 // For some strange reason this code likes it a lot better if it isn't in the template method below... BJG
00270 static inline SctTestApi::HighLevelApi_var getHighLevelApi() {
00271   //Get HighLevelApi:
00272   IPCPartition p = Sct::SctNames::getPartition();
00273   SctTestApi::HighLevelApi_var hla = p.lookup < ::SctTestApi::HighLevelApi > ( ::SctTestApi::HighLevelApi::instanceName );
00274   return hla;
00275 }
00276 
00277 template<typename T>
00278 void AnalysisTestFramework<T>::analyzeAll(int argc, char** argv) {
00279     Sct::setExceptionHandlers(argv[0]);
00280     getRootApp();
00281     
00282     try {
00283         handleArgs(argc, argv);
00284     
00285     //Get HighLevelApi:
00286         highLevelApi = getHighLevelApi();
00287     if (CORBA::is_nil(highLevelApi)) //Can't use !highLevelApi!
00288         throw IllegalStateError("Couldn't get HighLevelApi", __FILE__, __LINE__);
00289     
00290     //SctTestApiStatus status;
00291     string dataFile = highLevelApi->getDataFile();
00292     moduleData.load(Sct::Env::substituteVariables(dataFile));
00293     
00294     loadIgnoreFile();
00295         setup();
00296     
00297     //Make sure we have a list of modules  
00298     if (modules.size() == 0) {  
00299         string summaryFile = highLevelApi->getXmlSummaryFile();
00300         SctTest::XmlSummaryFile file(summaryFile);
00301         
00302         while (file.hasMoreRecords() && nModules < maxModules) {
00303         SctTest::XmlSummaryRecord xsr = file.getNextRecord();
00304         if (xsr.serialNumber.length() == 0)
00305             continue;
00306         if (count(ignoreModules.begin(), ignoreModules.end(), xsr.serialNumber) != 0) {
00307             cout << "Ignoring module: " << xsr.serialNumber << endl;
00308             continue;
00309         }
00310         modules.push_back(xsr.serialNumber);
00311         ++nModules;
00312         }
00313     } 
00314     
00315     //Loop over all modules and do them 
00316     for (list<string>::iterator it=modules.begin(); it!=modules.end(); ++it) {
00317         //Only do if not ignored
00318         if (count(ignoreModules.begin(), ignoreModules.end(), *it) == 0)
00319         doModule(*it);
00320         else 
00321         cout << "Ignoring module: " << *it << endl;
00322     }
00323     nModules = modules.size();
00324     
00325     file->cd(); //Make sure we are in the right directory
00326         summaryOutput();
00327     } catch (Throwable& e) {
00328         e.sendToMrs(MRS_FATAL);
00329         exitCode = -1;
00330     }
00331     tearDown();
00332 }
00333 
00334 template<typename T>
00335 AnalysisTestFramework<T>::AnalysisTestFramework(string isFilter, string isServer) : isFilter(isFilter), isServer(isServer) {  
00336     debug = false;
00337     maxModules = 1000;
00338     file = 0;
00339     tree = 0;
00340     readOnly = false;
00341     exitCode = 0;
00342     nModules = 0;
00343     nSkip = 0;
00344     nData = 1;
00345 }
00346 
00347 
00348 #endif //ANALYSISTESTFRAMEWORK_H

Generated on Mon Feb 6 14:01:16 2006 for SCT DAQ/DCS Software - C++ by  doxygen 1.4.6