Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

DbiValidate.cc

Go to the documentation of this file.
00001 // $Id: DbiValidate.cc,v 1.102 2008/11/17 07:52:33 nwest Exp $
00002 
00003 #include <fstream>
00004 #include <iomanip>
00005 #include <list>
00006 #include <map>
00007 #include <memory>
00008 using std::auto_ptr;
00009 #include <sstream>
00010 #include <string>
00011 
00012 #include <math.h>
00013 #include <vector>
00014 
00015 #include "TObjectTable.h"
00016 #include "TStopwatch.h"
00017 #include "TSystem.h"
00018 #include "TSQLServer.h"
00019 #include "TSQLStatement.h"
00020 
00021 #include "Conventions/Detector.h"
00022 #include "Conventions/SimFlag.h"
00023 #include "DatabaseInterface/Dbi.h"
00024 #include "DatabaseInterface/DbiResultAgg.h"
00025 #include "DatabaseInterface/DbiCascader.h"
00026 #include "DatabaseInterface/DbiConfigSet.h"
00027 #include "DatabaseInterface/DbiConfigStream.h"
00028 #include "DatabaseInterface/test/DbiDemoData1.h"
00029 #include "DatabaseInterface/test/DbiDemoData2.h"
00030 #include "DatabaseInterface/test/DbiDemoData3.h"
00031 #include "DatabaseInterface/test/DbiDemoData4.h"
00032 #include "DatabaseInterface/DbiBinaryFile.h"
00033 #include "DatabaseInterface/DbiLogEntry.h"
00034 #include "DatabaseInterface/DbiRecord.h"
00035 #include "DatabaseInterface/DbiResultKey.h"
00036 #include "DatabaseInterface/DbiResultNonAgg.h"
00037 #include "DatabaseInterface/DbiResultPtr.h"
00038 #include "DatabaseInterface/DbiResultSet.h"
00039 #include "DatabaseInterface/DbiServices.h"
00040 #include "DatabaseInterface/DbiSimFlagAssociation.h"
00041 #include "DatabaseInterface/DbiSqlContext.h"
00042 #include "DatabaseInterface/DbiSqlValPacket.h"
00043 #include "DatabaseInterface/DbiStatement.h"
00044 #include "DatabaseInterface/DbiTableProxy.h"
00045 #include "DatabaseInterface/DbiValRecSet.h"
00046 #include "DatabaseInterface/test/DbiValidate.hh"
00047 #include "LeakChecker/Lea.h"
00048 #include "LeakChecker/LeaLeakChecker.h"
00049 #include "MessageService/MsgService.h"
00050 #include "Registry/Registry.h"
00051 
00052 
00053 #include "Util/UtilString.h"
00054 #include "Validity/VldTimeStamp.h"
00055 
00056 //ClassImp(DbiValidate)
00057 
00058 //   Definition of static data members
00059 //   *********************************
00060 #include "DatabaseInterface/DbiCache.h"
00061 
00062 CVSID("$Id: DbiValidate.cc,v 1.102 2008/11/17 07:52:33 nwest Exp $");
00063 
00064 // Definition of member functions (alphabetical order)
00065 // ***************************************************
00066 
00067 
00068 //.....................................................................
00069 
00070 DbiValidate::DbiValidate() :
00071   fNumFail(0),
00072   fNumPass(0),
00073   fGoodCascade(false),
00074   fSkipAsciiDbTest(false)
00075 {
00076 //
00077 //  Purpose:   Default constructor.
00078 //  Arguments: None.
00079 //  Return:    None.
00080 //
00081 //  Contact:   N. West
00082 //
00083 //  Specification:-
00084 //  =============
00085 //
00086 //  o  Create default object and prepares the database.
00087 
00088 
00089   MSG("Dbi",Msg::kVerbose) << "DbiValidate ctor 1 at " << this 
00090                              << "\n";
00091   MSG("Dbi",Msg::kInfo) << "DbiValidation: $Revision: 1.102 $" << endl;
00092 
00093   // Initiate leak checking before preparing the database as this creates DBI objects.
00094   LeaLeakChecker* lea = LeaLeakChecker::Instance();
00095   //Not really necessary, but keeps compiler from fretting about unused variables.
00096   lea->Reset();
00097   fSkipAsciiDbTest = gSystem->Getenv("ENV_SKIP_ASCII_DB_TEST") != 0;
00098   this->PrepareDatabases();
00099 
00100 }
00101 
00102 //.....................................................................
00103 
00104 DbiValidate::~DbiValidate() {
00105 //
00106 //
00107 //  Purpose:   Destructor.
00108 //  Arguments: None.
00109 //  Return:    None.
00110 //
00111 //  Contact:   N. West
00112 //
00113 //  Specification:-
00114 //  =============
00115 //
00116 //  o  Destroy object.
00117 
00118   MSG("Dbi",Msg::kVerbose) << "DbiValidate dtor at " << this << "\n";
00119   if ( gSystem->Getenv("ENV_NO_CLEAN_DB_TEST") ) {
00120     MSG("Dbi",Msg::kInfo) << "ENV_NO_CLEAN_DB_TEST set; not cleaning database" <<endl;
00121   }
00122   else this->CleanDatabases();
00123 
00124 }
00125 
00126 //.....................................................................
00127 
00128 void DbiValidate::CleanDatabases(Bool_t printWarnings) {
00129 //
00130 //
00131 //  Purpose:   Cleanup Databases, removing unwanted test data.
00132 
00133 // Operate only if safe to do so!
00134   if ( ! fGoodCascade ) return;
00135 
00136   MSG("Dbi",Msg::kInfo)  << "Removing test tables from databases...\n" << endl;
00137 
00138   DbiCascader* cascader = DbiTableProxyRegistry::Instance().fCascader;
00139   for (int cascadeEntry = 0; cascadeEntry <= 1; ++cascadeEntry) {
00140     auto_ptr<DbiStatement> stmtDbn(cascader->CreateStatement(cascadeEntry));
00141     if ( ! stmtDbn.get() ) {
00142       MSG("Dbi",Msg::kError) << "Cannot get a statement for cascade entry " << cascadeEntry 
00143                              << "\n    Please check the ENV_TSQL_* environment.  Quitting ... " << endl;
00144       exit(1);
00145     }
00146 
00147     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA1");
00148     if (printWarnings) stmtDbn->PrintExceptions();
00149     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA1VLD");
00150     if (printWarnings) stmtDbn->PrintExceptions();
00151     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA2");
00152     if (printWarnings) stmtDbn->PrintExceptions();
00153     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA2VLD");
00154     if (printWarnings) stmtDbn->PrintExceptions();
00155     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA3");
00156     if (printWarnings) stmtDbn->PrintExceptions();
00157     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA3VLD");
00158     if (printWarnings) stmtDbn->PrintExceptions();
00159     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA3A");
00160     if (printWarnings) stmtDbn->PrintExceptions();
00161     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA3AVLD");
00162     if (printWarnings) stmtDbn->PrintExceptions();
00163     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA4");
00164     if (printWarnings) stmtDbn->PrintExceptions();
00165     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBIDEMODATA4VLD");
00166     if (printWarnings) stmtDbn->PrintExceptions();
00167     stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS LOCALSEQNO");
00168     if (printWarnings) stmtDbn->PrintExceptions();
00169 
00170     if ( cascadeEntry == 0 ) {
00171       stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBILOGENTRY");
00172       if (printWarnings) stmtDbn->PrintExceptions();
00173       stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS DBILOGENTRYVLD");
00174       if (printWarnings) stmtDbn->PrintExceptions();
00175       stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS GLOBALSEQNO");
00176       if (printWarnings) stmtDbn->PrintExceptions();
00177       stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS ALL_DATA_TYPES");
00178       if (printWarnings) stmtDbn->PrintExceptions();
00179       stmtDbn->ExecuteUpdate("DROP TABLE IF EXISTS ALL_DATA_TYPESVLD");
00180       if (printWarnings) stmtDbn->PrintExceptions();
00181    }
00182   }
00183 }
00184 //.....................................................................
00185 
00186 void DbiValidate::PrepareDatabases() {
00187 //
00188 //
00189 //  Purpose:   Prepare Databases, by creating required test data.
00190 
00191   bool fail = false;
00192   MSG("Dbi",Msg::kInfo) << "Preparing databases for DBI testing ..." << endl;
00193 
00194   string privateContext(gSystem->Getenv("SRT_PRIVATE_CONTEXT"));
00195   string  publicContext(gSystem->Getenv("SRT_PUBLIC_CONTEXT"));
00196 
00197 // Before opening the database append an ASCII DB to the cascade if there are
00198 // only 2 entries and not skipping test.
00199   string cascade(gSystem->Getenv("ENV_TSQL_URL"));
00200   vector<string>cascadeElements;
00201   UtilString::StringTok(cascadeElements,cascade,";");
00202   if ( cascadeElements.size() == 2 && ! fSkipAsciiDbTest ) {
00203     string asciiDb = cascadeElements[1] + "#";
00204     asciiDb  += ( privateContext.size() > 2 ) ? privateContext : publicContext;
00205     asciiDb  += "/DatabaseInterface/test/DemoASCIICatalogue.db";
00206     MSG("Dbi",Msg::kInfo) << "Appending ASCII DB: " << asciiDb << endl;
00207     cascade += ";" + asciiDb;
00208     gSystem->Setenv("ENV_TSQL_URL",cascade.c_str());
00209   }
00210 
00211 
00212 // Before proceeding make sure that the cascade looks O.K. and that we
00213 // are not going to do damage by recreating the GLOBALSEQNO table on cascade entry 0
00214 // or wiping DBILOGENTRY.
00215 
00216   DbiCascader* cascader = DbiTableProxyRegistry::Instance().fCascader;
00217 
00218   auto_ptr<DbiStatement> stmtDb(cascader->CreateStatement(0));
00219   if ( ! stmtDb.get() ) {
00220     MSG("Dbi",Msg::kError) << "Cannot get a statement for cascade entry 0.  \n"
00221                            << "Please check the ENV_TSQL_* environment.  Quitting ... " << endl;
00222     exit(1);
00223   }
00224   TSQLStatement* stmtTSQL = stmtDb->ExecuteQuery("select * from GLOBALSEQNO;");
00225 
00226   if ( stmtTSQL ) {
00227     while ( stmtTSQL->NextResultRow() ) {
00228       TString tableName = stmtTSQL->GetString(0);
00229       int lastUsedSeqNo = stmtTSQL->GetInt(1);
00230       if ( tableName == "*" && lastUsedSeqNo != 900000000 )  {
00231         MSG("Dbi",Msg::kError) << "GLOBALSEQNO table error. Entry * = " <<   lastUsedSeqNo
00232                                << " but should be 900000000" << endl;
00233         fail = true;
00234       }
00235       else if  ( tableName != "*" ) {
00236         string tn3(tableName.Data(),3);
00237         if ( tn3 != "DBI"  || lastUsedSeqNo < 900000000 || lastUsedSeqNo > 999999999 ) {
00238           MSG("Dbi",Msg::kError) << "GLOBALSEQNO table error. Entry " <<  tableName 
00239                                  << " but should start DBI \n"
00240                                  << "     and last used SEQNO: " << lastUsedSeqNo
00241                                  << " should be in range 900000000..999999999" << endl;
00242           fail = true;
00243         }
00244       }
00245     }
00246   }
00247 
00248   if ( fail ) {
00249     MSG("Dbi",Msg::kError) << "The GLOBALSEQNO table at entry 0 of the cascade doesn't look\n"
00250                            << "     like a dummy and as the test suite erases it the job will"
00251                                 << " quit rather than risk damage to this table\n" << endl;
00252     exit(1);
00253   }
00254 
00255   // See that DBILOGENTRY has not got too many entries.
00256 
00257   stmtTSQL = stmtDb->ExecuteQuery("select count(*) from DBILOGENTRY;");
00258   if ( stmtTSQL ) {
00259     stmtTSQL->NextResultRow();
00260     int numEntries = stmtTSQL->GetInt(0);
00261     if ( numEntries > 8)  {
00262     MSG("Dbi",Msg::kError) << "DBILOGENTRY at entry 0 has " <<  numEntries 
00263                            << " entries but should have no more than 8 \n"
00264                            << "    will quit rather than risk damage to this table\n" << endl;
00265     exit(1);
00266    }
00267   }
00268 
00269   // O.K. the cascade looks good.
00270   fGoodCascade = true;
00271 
00272   // Just in case the previous job didn't end cleanly.
00273   // Suppress errors at this stage - the database should be clean!
00274   this->CleanDatabases(false);
00275 
00276   // Now prime the first two cascade entries.
00277 
00278   MSG("Dbi",Msg::kInfo) << "Adding test tables to databases ..." << endl;
00279 
00280   for (int cascadeEntry = 0; cascadeEntry <= 1; ++cascadeEntry) {
00281 
00282   // Locate the commands to recreate the databases.
00283     ostringstream os;
00284     os << "/DatabaseInterface/test/prepare_db_" << cascadeEntry << ".sql";
00285     string fileName = privateContext + os.str();
00286     // AccessPathName returns true if cannot access!
00287     if ( gSystem->AccessPathName(fileName.c_str()) ) 
00288        fileName = publicContext + os.str();
00289 
00290     ifstream inp(fileName.c_str());
00291     if ( ! inp.is_open() ) {
00292       MSG("Dbi",Msg::kError) << "Cannot read DB priming file " << fileName << endl;
00293       exit(1);
00294     }
00295 
00296     // Get a statement through which to pass the commands.
00297     auto_ptr<DbiStatement> stmtDbn(cascader->CreateStatement(cascadeEntry));
00298     if ( ! stmtDbn.get() ) {
00299       MSG("Dbi",Msg::kError) << "Cannot get a statement for cascade entry " << cascadeEntry 
00300                              << "\n    Please check the ENV_TSQL_* environment.  Quitting ... " << endl;
00301       exit(1);
00302     }
00303 
00304     std::vector<std::string> sql_cmds;
00305 
00306     // The definition of DBIDEMODATA3 is centralised in the DbiDemoData3 class.
00307     sql_cmds.push_back(Dbi::GetVldDescr("DBIDEMODATA3"));
00308     sql_cmds.push_back(DbiDemoData3::GetTableDescr());
00309     if ( cascadeEntry == 0 ) {
00310       sql_cmds.push_back(Dbi::GetVldDescr("DBIDEMODATA3A"));
00311       sql_cmds.push_back(DbiDemoData3::GetTableDescr("DBIDEMODATA3A"));
00312     }
00313 
00314    // Loop over lines assembling SQL commands terminated by ;
00315     
00316     string sql; 
00317     while ( ! inp.eof() ) {
00318       string line;
00319       getline(inp,line);
00320 
00321       // Remove trailing spaces.
00322       while ( line.size() > 0 && *(line.rbegin()) == ' ' ) line.erase(line.size()-1);
00323 
00324       // Ignore empty lines and comments
00325       if ( line.size() == 0 || line[0] == '#' ) continue;
00326 
00327       sql += line;
00328 
00329       // If terminating semicolon found execute command.
00330       if ( *(line.rbegin()) == ';' ) {
00331         sql_cmds.push_back(sql);
00332         sql = "";
00333       }
00334     }
00335     
00336     // Now execute the assemble list of SQL commands.
00337 
00338     std::vector<std::string>::iterator itr(sql_cmds.begin()), itrEnd(sql_cmds.end());
00339     while( itr != itrEnd ) {
00340       std::string& sql_cmd(*itr++);
00341       // For DbiDemoData3 data, ignore SQL command and instead generate the data from
00342       // a reference object.  Do this for 2 reasons:-
00343       // a)  For self consistency: checks are always w.r.t. to the reference object
00344       // b)  For ORACLE metadata is always signed (unsigned not supported) but 
00345       //     for MySQL want to test support for unsigned so require either
00346       //     signed or unsigned data and by using DbiWriter to write the data
00347       //     ensures that it gets written in the right form.
00348       if ( sql_cmd.find("insert into DBIDEMODATA3 values") != std::string::npos) {
00349         MSG("Dbi",Msg::kDebug) << "Priming DB " << cascadeEntry << " using DbiDemoData3 to create data" << endl;
00350         DbiDemoData3 refDd3;
00351         DbiWriter<DbiDemoData3> w_Dd3(DbiDemoData3::GetRangeDTF(),refDd3.GetAggregateNo());
00352         w_Dd3.SetDbNo(cascadeEntry);
00353         w_Dd3.SetLogComment("test data");
00354         w_Dd3 << refDd3;
00355         if ( ! w_Dd3.Close() ) fail = true;
00356       }
00357       else {
00358         MSG("Dbi",Msg::kDebug) << "Priming DB " << cascadeEntry << "  SQL:" << sql_cmd << endl;
00359         stmtDbn->ExecuteUpdate(sql_cmd.c_str());
00360         if ( stmtDbn->PrintExceptions() ) fail = true;
00361       }
00362     }
00363 
00364     // Refresh list of tables in connected database
00365     cascader->GetConnection(cascadeEntry)->SetTableExists();
00366   }
00367   if ( fail ) {
00368     MSG("Dbi",Msg::kError) << "Quiting due to errors preparing database\n" << endl;
00369     if ( gSystem->Getenv("ENV_NO_CLEAN_DB_TEST") ) {
00370       MSG("Dbi",Msg::kInfo) << "ENV_NO_CLEAN_DB_TEST set; not cleaning database" <<endl;
00371     }
00372     else this->CleanDatabases();
00373     exit(1);
00374   }
00375 
00376   // Force cascader to use entry 0 as the authorising DB - it probably came
00377   // up without one.
00378   cascader->SetAuthorisingEntry(0);
00379 
00380   MSG("Dbi",Msg::kInfo) << "Database preparation complete." << endl;
00381 
00382   MSG("Dbi",Msg::kDebug) << "Load ALL_DATA_TYPES table to check meta-data" << endl;
00383   DbiTableProxyRegistry& tbp = DbiTableProxyRegistry::Instance();
00384   DbiConfigSet cfs;
00385   tbp.GetTableProxy("ALL_DATA_TYPES",&cfs);
00386 }
00387 
00388 
00389 //.....................................................................
00390 
00391 Bool_t DbiValidate::RunAllTests() {
00392 //
00393 //
00394 //  Purpose:   Run all tests.
00395 //  Arguments: None.
00396 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.
00397 //
00398 //  Contact:   N. West
00399 //
00400 //
00401 //  Specification:-
00402 //  =============
00403 //
00404 //  o  Run all tests
00405 //
00406 //  o  Check for leaks.
00407 
00408 
00409   LeaLeakChecker* lea = LeaLeakChecker::Instance();
00410 
00411 //  Run all tests.
00412 
00413   Bool_t ok = kTRUE;
00414 
00415   Int_t numOK = 0;
00416   for ( Int_t testNum = 1; testNum <= kNUMTESTS; testNum++  ) {
00417     if ( ! RunTest(testNum) ) ok = kFALSE;
00418     else ++numOK;
00419   }
00420 
00421 // Delete any residual objects and check for leaks.
00422 
00423   DbiTableProxyRegistry::Instance().Set("Shutdown = 1");
00424   DbiTableProxyRegistry::Instance().ShowStatistics();
00425   delete &(DbiTableProxyRegistry::Instance());
00426   DbiTableProxyRegistry::fgInstance = 0;
00427 
00428 //   extern TObjectTable* gObjectTable;
00429 //   if (gObjectTable) gObjectTable->Print();
00430 
00431   if ( lea->GetNumCreated() == 0 ) {
00432     MSG("Dbi",Msg::kInfo) << "Warning: Leak checking disabled!!"
00433                           << endl;
00434   }
00435   else if ( lea->GetNumActive() ) {
00436     MSG("Dbi",Msg::kInfo) << "Error, leaks detected! " << endl <<lea;
00437     ok = kFALSE;
00438   }
00439   else {
00440     MSG("Dbi",Msg::kInfo) << "O.K., no leaks detected " << endl << lea;
00441   }
00442 
00443   MSG("Dbi",Msg::kInfo) << "\nOverall test status for " << (int) kNUMTESTS << " tests : "
00444                         << ( ok ? "O.K." : "failed!") 
00445                         << "  (" << numOK << " passed) " << endl;
00446   if ( fSkipAsciiDbTest ) MSG("Dbi",Msg::kInfo) 
00447       << "Warning: ASCII DB tests skipped due to "
00448       << "setting of environmental variable ENV_SKIP_ASCII_DB_TEST !! \n" << endl;
00449   return ok;
00450 }
00451 
00452 //.....................................................................
00453 
00454 Bool_t DbiValidate::RunTest(Int_t testNum) {
00455 //
00456 //
00457 //  Purpose:   Run a specific test.
00458 //  Arguments: 
00459 //    testNum      in  Test to be run.
00460 //
00461 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
00462 //
00463 //  Contact:   N. West
00464 //
00465 //  Specification:-
00466 //  =============
00467 
00468 //  Program Notes
00469 //  =============
00470 
00471 //  Banner printing not yet implemented.
00472 
00473 //  Dispatch to appropriate test.
00474 
00475   switch ( testNum ) {
00476   case  0: return Test_0();
00477   case  1: return Test_1();
00478   case  2: return Test_2();
00479   case  3: return Test_3();
00480   case  4: return Test_4();
00481   case  5: return Test_5();
00482   case  6: return Test_6();
00483   case  7: return Test_7();
00484   case  8: return Test_8();
00485   case  9: return Test_9();
00486   case 10: return Test_10();
00487   case 11: return Test_11();
00488   case 12: return Test_12();
00489   case 13: return Test_13();
00490     }
00491   MSG("Dbi",Msg::kError) << "Undefined test: " << testNum << "\n";
00492   return kFALSE;
00493 
00494 }
00495 
00496 //.....................................................................
00497 
00498 void DbiValidate::RunTimeTest() {
00499 //
00500 //
00501 //  Purpose:   Run time test.
00502 //  Arguments: None.
00503 //
00504 //  Return:    n/a
00505 //
00506 //  Contact:   N. West
00507 //
00508 //  Specification:-
00509 //  =============
00510 //
00511 //  o  Run time test loading UgliDbiStrip.
00512 
00513 //  Program Notes
00514 //  =============
00515   TStopwatch tim;
00516 
00517   cout << "RunTimeTest has been dummied out.  It's no longer needed and using \n"
00518        << "UGLI pulls in most of loon and makes testing of API changes tedious\n"
00519        << "as many libraries have to be rebuilt"  << endl;
00520 
00521 }
00522 
00523 //.....................................................................
00524 
00525 Bool_t DbiValidate::Test_0() {
00526 //
00527 //
00528 //  Purpose:   Dummy test.
00529 //  Arguments: None.
00530 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
00531 //
00532 //  Contact:   N. West
00533 //
00534 //  Specification:-
00535 //  =============
00536 //
00537 //  o 
00538 //
00539  
00540   Bool_t ok = kTRUE;
00541 
00542   MSG("Dbi",Msg::kInfo) 
00543        << "Test 0: Dummy                                   ...... ";
00544   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
00545   MSG("Dbi",Msg::kInfo) << "\n";
00546 
00547 
00548   if ( ok ) fNumPass++; else fNumFail++;
00549 
00550   return ok;
00551   
00552 }
00553 
00554 //.....................................................................
00555 
00556 Bool_t DbiValidate::Test_1() {
00557 //
00558 //
00559 //  Purpose:  DateTime conversion utilities.
00560 //  Arguments: None.
00561 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
00562 //
00563 //  Contact:   N. West
00564 //
00565 //  Specification:-
00566 //  =============
00567 //
00568 //  o Test conversion between VldTimeStamp and SQL DATETIME string.
00569 //
00570  
00571   Bool_t ok = kTRUE;
00572 
00573   string ref("2001-09-27 01:02:03");
00574   VldTimeStamp dt1(2001,9,27,1,2,3);
00575 
00576   string s1 = Dbi::MakeDateTimeString(dt1);
00577   VldTimeStamp dt2(Dbi::MakeTimeStamp(s1));
00578   string s2 = Dbi::MakeDateTimeString(dt2);
00579 
00580   if ( ref.compare(s1) || ref.compare(s2) ) {
00581   
00582     MSG("Dbi",Msg::kError) << "Conversion test failed: strings: ("
00583                            << s1 << "," << s2 << ") do not match:" 
00584                            << ref << endl;
00585     ok = kFALSE;
00586   }
00587 
00588   // Check for incomplete and illegal dates.
00589 
00590   Bool_t convertOK;
00591   dt1 = Dbi::MakeTimeStamp("2000-1-",&convertOK);
00592   if ( ! convertOK )  {
00593     MSG("Dbi",Msg::kError) 
00594       << "Conversion: \"2000-1-\" failed but should not have." << endl;
00595     ok = kFALSE;
00596   }
00597 
00598   dt2 = Dbi::MakeTimeStamp("1960-1",&convertOK);
00599   if ( convertOK )  {
00600     MSG("Dbi",Msg::kError) 
00601       << "Conversion: \"1960-1\" should have failed but did not."<< endl;
00602     ok = kFALSE;
00603   }
00604 
00605   MSG("Dbi",Msg::kInfo) 
00606        << "Test 1: DateTime conversion utilities          ...... "
00607        << ( ok ? "O.K." : "Failed") << endl;
00608 
00609   if ( ok ) fNumPass++; else fNumFail++;
00610 
00611   return ok;
00612   
00613 }
00614 //.....................................................................
00615 
00616 Bool_t DbiValidate::Test_2() {
00617 //
00618 //
00619 //  Purpose:   Retrieval of non-aggregated data from database table.
00620 //  Arguments: None.
00621 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
00622 //
00623 //  Contact:   N. West
00624 //
00625 //  Specification:-
00626 //  =============
00627 //
00628 //  o Get data from DbiDataDemo1 and DbiDemoData3 tables.
00629 //
00630  
00631   Bool_t ok = kTRUE;
00632 
00633   struct Test_t {
00634     Int_t    dateCntx;
00635     Int_t    timeCntx;
00636     Int_t    dateResStart;
00637     Int_t    timeResStart;
00638     Int_t    dateResEnd;
00639     Int_t    timeResEnd;
00640     UInt_t   numRows;
00641     Float_t  firstGain1;
00642     Float_t  lastGain1;
00643   };
00644 
00645   Test_t tests[] = {
00646     {20001230,120000, 20000106,110000, 20010101,  10203,  0,  0.,  0.},
00647     {20010130,110000, 20010120, 40506, 20380119,  31407,  0,  0.,  0.},
00648     {20010113,100000, 20010110, 40506, 20010116,  10203,  0,  0.,  0.},
00649     {20010103, 90000, 20010103, 10203, 20010104,  10203,  4, 30., 33.},
00650     {20010105,120000, 20010105,110000, 20010105, 130000,  4, 1.0, 1.3},
00651   };
00652 
00653   for (int itest=0; itest<5; ++itest ) {
00654     Test_t& test = tests[itest];
00655     Int_t date = test.dateCntx;
00656     Int_t time = test.timeCntx;
00657     VldTimeStamp tstamp(date/10000, date/100%100, date%100,
00658                         time/10000, time/100%100, time%100);
00659     VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
00660 
00661     DbiResultPtr<DbiDemoData1> pr(vc,0);
00662 
00663 // Check validity range of result set.
00664     VldTimeStamp tsstart = pr.GetValidityRec()
00665                                          ->GetVldRange().GetTimeStart();
00666     VldTimeStamp tsend   = pr.GetValidityRec()
00667                                            ->GetVldRange().GetTimeEnd();
00668     if (    tsstart.GetDate() != test.dateResStart
00669          || tsstart.GetTime() != test.timeResStart
00670          || tsend.GetDate()   != test.dateResEnd
00671          || tsend.GetTime()   != test.timeResEnd ) {
00672 
00673       MSG("Dbi",Msg::kError) 
00674         << "Query date: " << tstamp.AsString() << endl
00675         << " has validity " << pr.GetValidityRec()
00676                                  ->GetVldRange().AsString() << endl
00677         << " but should have "
00678         << test.dateResStart << " " << test.timeResStart << " - "
00679         << test.dateResEnd   << " " << test.timeResEnd << endl;
00680 
00681       ok = kFALSE;
00682     }
00683 
00684 // Check number of entries in result set.
00685     unsigned int numRows = pr.GetNumRows();
00686     if ( numRows != test.numRows ) {
00687       MSG("Dbi",Msg::kError) 
00688         << "Query date: " << tstamp.AsString() << endl
00689         << " gave num rows  " << numRows
00690         << " but should have given " << test.numRows << endl;
00691       ok = kFALSE;
00692     }
00693 
00694     if ( numRows > 0 ) {
00695       Float_t  firstGain1 = pr.GetRow(0)->GetGain1();
00696       Float_t  lastGain1  = pr.GetRow(numRows-1)->GetGain1();
00697       if (     firstGain1 != test.firstGain1 
00698            ||  lastGain1  != test.lastGain1  ) {
00699         MSG("Dbi",Msg::kError) 
00700           << "Query date: " << tstamp.AsString() << endl
00701           << " gave first,last gains  " << firstGain1
00702           << "," << lastGain1
00703           << " but should have given " << test.firstGain1
00704           << "," << test.lastGain1 << endl;
00705         ok = kFALSE;
00706 
00707      }
00708  
00709       const DbiDemoData1* ddd3 = pr.GetRowByIndex(3000000003U);
00710       if ( ! ddd3 ) {
00711         MSG("Dbi",Msg::kError) 
00712           << "Query date: " << tstamp.AsString() << endl
00713           << " found no entry at index 3 " << endl;
00714         ok = kFALSE;
00715       }
00716       else if (  ddd3->GetGain1() != test.lastGain1 ) {
00717         MSG("Dbi",Msg::kError) 
00718           << "Query date: " << tstamp.AsString() << endl
00719           << " index 3 gain  " <<  lastGain1
00720           << " but should have given " << test.lastGain1 << endl;
00721         ok = kFALSE;
00722       }
00723 
00724       // On first non-empty test try out SEQNO query.
00725       if ( itest == 3 ) {
00726         const DbiValidityRec* vrec = pr.GetValidityRec();
00727         UInt_t dbNo  = vrec->GetDbNo();
00728         UInt_t seqNo = vrec->GetSeqNo();
00729         DbiResultPtr<DbiDemoData1> prSeqno("DbiDemoData1",seqNo,dbNo);
00730         numRows = prSeqno.GetNumRows();
00731         if ( numRows != test.numRows ) {
00732           MSG("Dbi",Msg::kError) 
00733             << "Query SEQNO " << seqNo << " on database " << dbNo << endl
00734             << " gave num rows  " << numRows
00735             << " but should have given " << test.numRows << endl;
00736           ok = kFALSE;
00737         }
00738       }
00739     }
00740 
00741   }
00742 
00743   // Test moving to adjacent validity range.
00744   Test_t& test = tests[0];
00745   Int_t date = test.dateCntx;
00746   Int_t time = test.timeCntx;
00747   VldTimeStamp tstamp2(date/10000, date/100%100, date%100,
00748                       time/10000, time/100%100, time%100);
00749   VldContext vc2(Detector::kCalib,SimFlag::kData,tstamp2);
00750   DbiResultPtr<DbiDemoData1> pr(vc2,0);
00751   for (int step = 0; step < 5; ++step) {
00752     pr.NextQuery();
00753   }
00754 
00755   Int_t nextDateGot = pr.GetValidityRec()->GetVldRange()
00756                         .GetTimeStart().GetDate();
00757   Int_t nextDateReq = 20010105;
00758   if ( nextDateGot != nextDateReq ) {
00759     MSG("Dbi",Msg::kInfo)
00760       << " Stepping forward expected date: " << nextDateReq
00761       << " but found " << nextDateGot << endl;
00762       ok = kFALSE;
00763     }
00764 
00765   for (int step = 0; step < 5; ++step) {
00766     pr.NextQuery(kFALSE);
00767   }
00768 
00769   nextDateGot = pr.GetValidityRec()->GetVldRange()
00770                   .GetTimeStart().GetDate();
00771   nextDateReq = 20000106;
00772   if ( nextDateGot != nextDateReq ) {
00773     MSG("Dbi",Msg::kInfo)
00774       << " Stepping backward expected date: " << nextDateReq
00775       << " but found " << nextDateGot << endl;
00776       ok = kFALSE;
00777   }
00778 
00779 
00780 // Test of DbiDemoData3 data.
00781 
00782   DbiDemoData3 refdd3;
00783   VldContext vc(refdd3.GetContextDTF());
00784   DbiResultPtr<DbiDemoData3> pr3(vc,0);
00785   DbiResultPtr<DbiDemoData3> pr3_copy(pr3);
00786   const DbiDemoData3* pdd3 = pr3_copy.GetRow(0);
00787   if ( ! pdd3 ) {
00788     MSG("Dbi",Msg::kInfo)
00789       << " Cannot find  DbiDemoData3:-" << endl;
00790       ok = kFALSE;
00791     }
00792   else if ( ! refdd3.Compare(pdd3) ) {
00793     MSG("Dbi",Msg::kInfo)
00794       << " Comparison failed comparing reference v. database (initial primed value)." << endl;
00795     ok = kFALSE;
00796   }
00797 
00798 // Test DbiResultKey coping.
00799 
00800   const DbiResultKey* original_key(pr3.GetKey());
00801   DbiResultKey copied_key(original_key);
00802   if ( not copied_key.IsEqualTo(original_key) ) {
00803   MSG("Dbi",Msg::kInfo)
00804       << " Copied DbiResultKey of DbiDemoData3 doesn't match:-\n" 
00805       <<  "Original:   " << *original_key << endl
00806       <<  "Copy:       " << copied_key << endl;
00807       ok = kFALSE;
00808     }
00809 
00810   MSG("Dbi",Msg::kInfo) 
00811        << "Test 2: Retrieval of non-aggregated data       ...... ";
00812   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
00813   MSG("Dbi",Msg::kInfo) << "\n";
00814 
00815 
00816   if ( ok ) fNumPass++; else fNumFail++;
00817 
00818   return ok;
00819   
00820 }
00821 //.....................................................................
00822 
00823 Bool_t DbiValidate::Test_3() {
00824 //
00825 //
00826 //  Purpose:   Test cache
00827 //  Arguments: None.
00828 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
00829 //
00830 //  Contact:   N. West
00831 //
00832 //  Specification:-
00833 //  =============
00834 //
00835 //  o Check caching of DemoData1.
00836 //
00837  
00838   Bool_t ok = kTRUE;
00839 
00840   struct Test_t {
00841     Int_t    dateCntx;
00842     Int_t    timeCntx;
00843   };
00844 
00845   Test_t tests[] = {
00846     {20001230,120000},
00847     {20010130,110000},
00848     {20010113,100000},
00849     {20010103, 90000},
00850   };
00851 
00852 // Initially the cache should have not have any DbiResults with clients
00853 // so we can force a purge that will empty it.
00854 
00855   DbiCache* cache = const_cast<DbiTableProxy&>
00856                         ( DbiResultPtr<DbiDemoData1>::GetTableProxy() )
00857                         .GetCache();
00858   cache->Purge();
00859 
00860    if ( cache->GetCurSize() != 0 ) {
00861      MSG("Dbi",Msg::kError) 
00862        << "Initial cache size is  " <<  cache->GetCurSize()
00863        << " but should be 0 " << endl;
00864      ok = kFALSE;
00865    }
00866    unsigned int numResused = cache->GetNumReused();
00867 
00868 // Force cache to be overfull by requesting multiple different
00869 // validities simultaneously.
00870   list<DbiResultPtr<DbiDemoData1>*> pResPtrs;
00871   for (int itest=0; itest<4; ++itest ) {
00872     Test_t& test = tests[itest];
00873     Int_t date = test.dateCntx;
00874     Int_t time = test.timeCntx;
00875     VldTimeStamp tstamp(date/10000, date/100%100, date%100,
00876                         time/10000, time/100%100, time%100);
00877     VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
00878 
00879 // Create multiple requests to test cache sharing
00880     pResPtrs.push_back( new DbiResultPtr<DbiDemoData1>(vc,0) );
00881     pResPtrs.push_back( new DbiResultPtr<DbiDemoData1>(vc,0) );
00882     pResPtrs.push_back( new DbiResultPtr<DbiDemoData1>(vc,0) );
00883   }
00884 
00885 // There should now be 4 in the cache, each reused twice.
00886    
00887   numResused = cache->GetNumReused() - numResused;
00888   if (    cache->GetCurSize() != 4  
00889        || numResused != 8 ) {
00890      MSG("Dbi",Msg::kError) 
00891        << "Final cache size is  " <<  cache->GetCurSize()
00892        << " but should be 4 " 
00893        << ", resuse count is "<< numResused
00894        << " but should be 8 " << endl;
00895      ok = kFALSE;
00896   }
00897 
00898 
00899   const DbiRecord* rec = DbiServices::GetRecord();
00900   if ( rec ) cout << *rec << endl;
00901 
00902 // Now delete all the DbiResultPtrs, purge  and the cache should drop
00903 // back to zero.
00904 
00905   for ( list<DbiResultPtr<DbiDemoData1>*>::iterator itr
00906              = pResPtrs.begin();
00907         itr != pResPtrs.end();
00908         ++itr ) delete *itr;
00909 
00910   cache->Purge();
00911 
00912    if ( cache->GetCurSize() != 0 ) {
00913      MSG("Dbi",Msg::kError) 
00914        << "Emptied cache size is  " <<  cache->GetCurSize()
00915        << " but should be 0 " << endl;
00916      ok = kFALSE;
00917    }
00918    
00919 // Test marking of cache as stale to force reloading.
00920    for (Int_t itry =1; itry <= 10; ++itry ) {
00921      Test_t& test = tests[0];
00922      Int_t date = test.dateCntx;
00923      Int_t time = test.timeCntx;
00924      VldTimeStamp tstamp(date/10000, date/100%100, date%100,
00925                          time/10000, time/100%100, time%100);
00926      VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
00927      cache->SetStale();
00928      DbiResultPtr<DbiDemoData1> pr1(vc,0);
00929    }
00930 
00931   numResused = cache->GetNumReused() - numResused;
00932   if (    cache->GetCurSize() != 1  
00933        || numResused != 0 ) {
00934      MSG("Dbi",Msg::kError) 
00935        << " SetStale test: Final cache size is  " <<  cache->GetCurSize()
00936        << " but should be 1 " 
00937        << ", resuse count is "<< numResused
00938        << " but should be 0 " << endl;
00939      ok = kFALSE;
00940   }
00941 
00942   MSG("Dbi",Msg::kInfo) 
00943        << "Test 3: Caching of DbiResults                  ...... ";
00944   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
00945   MSG("Dbi",Msg::kInfo) << "\n";
00946 
00947 
00948   if ( ok ) fNumPass++; else fNumFail++;
00949 
00950   return ok;
00951   
00952 }
00953 
00954 //.....................................................................
00955 
00956 Bool_t DbiValidate::Test_4() {
00957 //
00958 //
00959 //  Purpose:  Cache Save to/Restore from disk
00960 //  Arguments: None.
00961 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
00962 //
00963 //  Contact:   N. West
00964 //
00965 //  Specification:-
00966 //  =============
00967 //
00968 //  o Perform binary I/O on all the basic types.
00969 //
00970 //  o Test caching of unaggregated and aggregated queries.
00971 
00972   Bool_t ok = kTRUE;
00973 
00974   CfgConfigurable& dbiCfg = DbiTableProxyRegistry::Instance();
00975   dbiCfg.Set("Level2Cache = './'");
00976   dbiCfg.Update();
00977    
00978 //  Test I/O for builtin, string, simple and compound objects.
00979 
00980   int    i = 999;
00981   double f = 3.1415;
00982   string s1("A non-empty string");
00983   string s2;
00984   VldTimeStamp ts;
00985   VldTimeStamp ts2(2001,4,07,12,00,00);
00986   VldRange     vr(7,3,ts,ts2,"Test11");
00987   DbiValidityRec vrec(vr,123,456,789);
00988   DbiBinaryFile out("dbicache.dat",kFALSE);
00989   out << i << f << s1  << s2 << ts << vr;
00990   vrec.Streamer(out);
00991   out.Close();
00992 
00993   i = 0;
00994   f = 0.;
00995   s1 = "dummy";
00996   s2 = "dummy";
00997   string tsAsString = ts.AsString();
00998   string vrAsString = vr.AsString();
00999 
01000   // Destroy ts, vr
01001   memcpy(&ts," ",sizeof(ts));
01002   vr = VldRange();
01003 
01004   DbiValidityRec vrec2;
01005   DbiBinaryFile in("dbicache.dat");
01006   in >> i >> f >> s1  >> s2 >> ts >> vr;
01007   vrec2.Streamer(in);
01008   in.Close();
01009   if (     vrec.GetAggregateNo()  !=  vrec2.GetAggregateNo() 
01010        ||  vrec.GetDbNo()         !=  vrec2.GetDbNo()
01011        ||  vrec.GetTask()         !=  vrec2.GetTask()
01012        ||  vrec.GetSeqNo()        !=  vrec2.GetSeqNo()
01013        ||  vrec.GetInsertDate()   !=  vrec2.GetInsertDate()
01014        ||  vrec.GetCreationDate() !=  vrec2.GetCreationDate()
01015        ||  vrec.IsGap()           !=  vrec2.IsGap()
01016      ) {
01017     MSG("Dbi",Msg::kError) 
01018         << "Binary I/O has failed:-\n"
01019         <<   "  DbiValidityRec was " << vrec 
01020         << "\n          but now is " << vrec << endl;
01021     ok = kFALSE;
01022   }
01023   if (    i  != 999 
01024        || f  != 3.1415 
01025        || s1 != "A non-empty string" 
01026        || s2 != "" 
01027        || tsAsString != ts.AsString() 
01028        || vrAsString != vr.AsString() ) {
01029     MSG("Dbi",Msg::kError) 
01030         << "Binary I/O has failed:-\n"
01031         << "    int   = " << i << " but should be 999\n"
01032         << "    float = " << f << " but should be 3.1415\n"
01033         << "    str1  = \"" << s1 << "\" but should be \"A non-empty string\"\n"
01034         << "    str2  = \"" << s2 << "\" but should be \"\"\n"
01035         << "    ts    = \"" << ts.AsString() << "\n          but should be \"" 
01036         << tsAsString << "\"\n"
01037         << "    vr    = \"" << vr.AsString() << "\n          but should be \"" 
01038         << vrAsString << "\"\n"
01039         << endl;
01040     ok = kFALSE;
01041   }
01042 
01043 
01044 //  Test I/O for vector<DbiTableRow*>.
01045 
01046   DbiDemoData4 pet;
01047   void* vt;
01048   memcpy(&vt,&pet,4);
01049   MSG("Dbi",Msg::kVerbose) << "VT for DbiDemoData4 " << hex << vt << dec << endl;
01050 
01051   unsigned int  numRows  = 20;
01052   unsigned int  numTries = 5;
01053 
01054   for (unsigned int itry = 1; itry <= numTries; ++itry ) {
01055     vector<DbiTableRow*> arr;
01056 
01057     MSG("Dbi",Msg::kVerbose) << "Creating data ..." << endl;
01058     for (unsigned int row =0; row < numRows; ++row ) 
01059         arr.push_back(new DbiDemoData4(row));
01060 
01061     MSG("Dbi",Msg::kVerbose) << "Checking data ..." << endl;
01062     for (unsigned int row =0; row < numRows; ++row ) {
01063       if ( ! dynamic_cast<DbiDemoData4*>(arr[row])->IsValid() 
01064          ) {
01065          MSG("Dbi",Msg::kError) << row << " is not valid " << endl;
01066          ok = kFALSE;
01067       }
01068     }
01069 
01070     MSG("Dbi",Msg::kVerbose) << "Writing data ..." << endl;
01071     DbiBinaryFile out2("dbicache2.dat",kFALSE);
01072     out2 << arr;
01073     out2.Close();
01074 
01075     MSG("Dbi",Msg::kVerbose) << "Destroying data ..." << endl;
01076     for (unsigned int row =0; row < numRows; ++row ) delete arr[row];
01077     arr.clear();
01078   
01079     MSG("Dbi",Msg::kVerbose) << "Reading data ..." << endl;
01080     DbiBinaryFile in2("dbicache2.dat");
01081     in2 >> arr;
01082     in2.Close();
01083     char* buffer = in2.ReleaseArrayBuffer();
01084   
01085     MSG("Dbi",Msg::kVerbose) << "Checking data ..." << endl;
01086     for (unsigned int row =0; row < numRows; ++row ) {
01087       if ( ! dynamic_cast<DbiDemoData4*>(arr[row])->IsValid() 
01088          ) {
01089          MSG("Dbi",Msg::kError) << row << " is not valid " << endl;
01090          ok = kFALSE;
01091       }
01092 
01093     }
01094     delete[] buffer;
01095     buffer = 0;
01096   }
01097 
01098 // Test saving to Level 2 when caching enabled.
01099 
01100 
01101   DbiCache* cache1 = const_cast<DbiTableProxy&>
01102                         ( DbiResultPtr<DbiDemoData1>::GetTableProxy() )
01103                         .GetCache();
01104   DbiCache* cache2 = const_cast<DbiTableProxy&>
01105                         ( DbiResultPtr<DbiDemoData2>::GetTableProxy() )
01106                         .GetCache();
01107 
01108   VldTimeStamp ts3(2001,1,10,0,0,0);
01109   VldContext vc3(Detector::kCalib,SimFlag::kData,ts3);
01110 
01111   cache1->Purge();
01112   cache2->Purge();
01113 
01114 // First make L2 cache write-only, to refresh it.
01115   DbiBinaryFile::SetReadAccess(kFALSE);
01116 
01117   IndexToRow_t dd1Table;
01118   IndexToRow_t dd2Table;
01119 
01120 // Perform query within a scope to release resultset automatically
01121 // but take a copy of the results.
01122   {
01123     DbiResultPtr<DbiDemoData1> dd1pr3(vc3,0);
01124     DbiResultPtr<DbiDemoData2> dd2pr3(vc3,0);
01125 
01126     if ( ! dd1pr3.ResultsFromDb() || ! dd2pr3.ResultsFromDb() ) {
01127       MSG("Dbi",Msg::kError) << "First query isn't from database but should be " << endl;
01128       ok = kFALSE;
01129     }
01130 
01131     for (unsigned row=0; row < dd1pr3.GetNumRows(); ++row) {
01132       const DbiDemoData1* dd1 = dd1pr3.GetRow(row);
01133       const DbiTableRow* dd1Copy = new DbiDemoData1(*dd1);
01134       dd1Table[dd1->GetIndex(row)] = dd1Copy;
01135     }
01136     for (unsigned row=0; row < dd2pr3.GetNumRows(); ++row) {
01137       const DbiDemoData2* dd2 = dd2pr3.GetRow(row);
01138       const DbiTableRow* dd2Copy = new DbiDemoData2(*dd2);
01139       dd2Table[dd2->GetIndex(row)] = dd2Copy;
01140     }
01141 
01142   }
01143 
01144   cache1->Purge();
01145   cache2->Purge();
01146 
01147 // Now enable read access, read again, and compare.
01148 
01149   DbiBinaryFile::SetReadAccess();
01150   DbiResultPtr<DbiDemoData1> dd1pr3(vc3,0);
01151   DbiResultPtr<DbiDemoData2> dd2pr3(vc3,0);
01152   if ( dd1pr3.ResultsFromDb() || dd2pr3.ResultsFromDb() ) {
01153     MSG("Dbi",Msg::kError) << "Second query is from database but should not be " << endl;
01154     ok = kFALSE;
01155   }
01156   for (unsigned row=0; row < dd1pr3.GetNumRows(); ++row) {
01157     const DbiDemoData1* dd1 = dd1pr3.GetRow(row);
01158     const DbiDemoData1* dd1Copy = dynamic_cast<const DbiDemoData1*>(dd1Table[dd1->GetIndex(row)]);
01159     if ( ! dd1Copy || ! dd1Copy->Compare(*dd1) ) {
01160       MSG("Dbi",Msg::kError) << "Results for DbiDemoData1 from L2 cache differs on row  " 
01161                              << row << endl;
01162     ok = kFALSE;
01163     }
01164   }
01165   for (unsigned row=0; row < dd2pr3.GetNumRows(); ++row) {
01166     const DbiDemoData2* dd2 = dd2pr3.GetRow(row);
01167     const DbiDemoData2* dd2Copy = dynamic_cast<const DbiDemoData2*>(dd2Table[dd2->GetIndex(row)]);
01168     if ( ! dd2Copy || ! dd2Copy->Compare(*dd2) ) {
01169       MSG("Dbi",Msg::kError) << "Results for DbiDemoData2 from L2 cache differs on row  " 
01170                              << row << endl;
01171     ok = kFALSE;
01172     }
01173   }
01174 
01175 // Destroy copy so it doesn't show up as a leak.
01176   IndexToRow_t::iterator itr    =  dd1Table.begin();
01177   IndexToRow_t::iterator itrEnd =  dd1Table.end();
01178   for (; itr != itrEnd; ++itr) delete itr->second;
01179   itr    =  dd2Table.begin();
01180   itrEnd =  dd2Table.end();
01181   for (; itr != itrEnd; ++itr) delete itr->second;
01182 
01183   dbiCfg.Set("Level2Cache = ''");
01184   dbiCfg.Update();
01185 
01186 
01187   MSG("Dbi",Msg::kInfo) 
01188        << "Test 4: Level 2 Caching of DbiResults          ...... ";
01189   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
01190   MSG("Dbi",Msg::kInfo) << "\n";
01191 
01192 
01193   if ( ok ) fNumPass++; else fNumFail++;
01194 
01195   return ok;
01196   
01197 }
01198 //.....................................................................
01199 
01200 Bool_t DbiValidate::Test_5() {
01201 //
01202 //
01203 //  Purpose:   Test of aggregated data.  Further cache tests
01204 //  Arguments: None.
01205 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
01206 //
01207 //  Contact:   N. West
01208 //
01209 //  Specification:-
01210 //  =============
01211 //
01212 //  o Step through a set of validity range boundaries and ensure
01213 //    that the correct aggregates get refreshed and that all data 
01214 //    is valid.
01215 // 
01216 // o  Check on task selection and show that each task remains in
01217 //    cache
01218 // 
01219 // 
01220   Bool_t ok = kTRUE;
01221   struct Test_t {
01222     Int_t    dateCntx;
01223     Int_t    timeCntx;
01224     Int_t    dateResStart;
01225     Int_t    timeResStart;
01226     Int_t    dateResEnd;
01227     Int_t    timeResEnd;
01228     UInt_t   numRows;
01229     Float_t  datai[4];
01230     Float_t  datar[4];
01231   };
01232 
01233   enum { NUM_TESTS = 5 }; // Number of tests. 
01234   Test_t tests[] = {
01235     {20010101,120000, 20010101, 000000, 20010103, 000000, 15,
01236                               { 100.,  104.,  109.,  114.},
01237                               { 102.,  108.,  100.,  107.} },
01238     {20010102,120000, 20010101, 000000, 20010103, 000000, 15,
01239                               { 100.,  104.,  109.,  114.},
01240                               { 102.,  108.,  100.,  107.} },
01241     {20010103,120000, 20010103, 000000, 20010104, 000000, 15,
01242                               { 100.,  204.,  209.,  114. },
01243                               { 202.,  108.,  100.,  207. } },
01244     {20010104,120000, 20010104, 101112, 20010105, 000000, 12,
01245                               { 300., -999.,  309.,  314. },
01246                               { 202.,  308.,  300., -999. } },
01247     {20010105,120000, 20010105, 000000, 20010131, 000000, 15,
01248                               { 400.,  404.,  409.,  414. },
01249                               { 402.,  408.,  400.,  407. } },
01250   };
01251 
01252 
01253 // Sweep over all validity range boundaries.
01254 
01255   for (int itest=0; itest<NUM_TESTS; ++itest ) {
01256     Test_t& test = tests[itest];
01257     Int_t date = test.dateCntx;
01258     Int_t time = test.timeCntx;
01259     VldTimeStamp tstamp(date/10000, date/100%100, date%100,
01260                         time/10000, time/100%100, time%100);
01261     VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
01262 
01263     DbiResultPtr<DbiDemoData2> rp(vc,0);
01264 
01265 // Check validity range of result set.
01266     VldTimeStamp tsstart = rp.GetValidityRec()
01267                                          ->GetVldRange().GetTimeStart();
01268     VldTimeStamp tsend   = rp.GetValidityRec()
01269                                            ->GetVldRange().GetTimeEnd();
01270     if (    tsstart.GetDate() != test.dateResStart
01271          || tsstart.GetTime() != test.timeResStart
01272          || tsend.GetDate()   != test.dateResEnd
01273          || tsend.GetTime()   != test.timeResEnd ) {
01274 
01275       MSG("Dbi",Msg::kError) 
01276         << "Query date: " << tstamp.AsString() << endl
01277         << " has validity " << rp.GetValidityRec()
01278                                  ->GetVldRange().AsString() << endl
01279         << " but should have "
01280         << test.dateResStart << " " << test.timeResStart << " - "
01281         << test.dateResEnd   << " " << test.timeResEnd << endl;
01282 
01283       ok = kFALSE;
01284     }
01285 
01286 // Check number of entries in result set.
01287     unsigned int numRows = rp.GetNumRows();
01288     if ( numRows != test.numRows ) {
01289       MSG("Dbi",Msg::kError) 
01290         << "Query date: " << tstamp.AsString() << endl
01291         << " gave num rows  " << numRows
01292         << " but should have given " << test.numRows << endl;
01293       ok = kFALSE;
01294     }
01295 
01296 // Check the data from subsystems with indeces 0, 4, 9, 14.
01297     UInt_t indeces[] = { 0, 4, 9, 14};
01298     for (UInt_t idata = 0; idata<4; ++idata) {
01299       UInt_t index = indeces[idata];
01300       const DbiDemoData2* pdd2i = rp.GetRowByIndex(index);
01301       if ( pdd2i  == 0 ) {
01302         if ( test.datai[idata] != -999. ) {
01303           MSG("Dbi",Msg::kError) 
01304             << "Query date: " << tstamp.AsString() << endl
01305             << " gave data for index " << index
01306             << " but should have been missing " 
01307             << endl;
01308           ok = kFALSE;
01309         }
01310       }
01311       else {
01312         if ( pdd2i->GetData() != test.datai[idata] ) {
01313           MSG("Dbi",Msg::kError) 
01314             << "Query date: " << tstamp.AsString() << endl
01315             << " gave gave data  " <<  pdd2i->GetData()
01316             << " for index " << index
01317             << " but should have given " << test.datai[idata] << endl;
01318         ok = kFALSE;
01319         }
01320       }
01321     }
01322 
01323   }
01324   
01325 //  Repeat last validity context multiple times for multiple tasks
01326 
01327   DbiCache* cache = const_cast<DbiTableProxy&>
01328                     ( DbiResultPtr<DbiDemoData2>::GetTableProxy() )
01329                     .GetCache();
01330   int itest= NUM_TESTS-1;
01331   Test_t& test = tests[itest];
01332   Int_t date = test.dateCntx;
01333   Int_t time = test.timeCntx;
01334   VldTimeStamp tstamp(date/10000, date/100%100, date%100,
01335                       time/10000, time/100%100, time%100);
01336   VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
01337 
01338   UInt_t numAdopted = cache->GetNumAdopted();
01339   UInt_t setSize = 0;
01340   for ( int trial=0; trial<3; ++trial) {
01341     for (Dbi::Task task=1; task < 4; ++task ) { 
01342       DbiResultPtr<DbiDemoData2> rp(vc,task);
01343       setSize = rp.GetNumRows();
01344     }
01345   }
01346   numAdopted = cache->GetNumAdopted() - numAdopted;
01347 
01348   if (    setSize != 5 ||  numAdopted != 9 ) {
01349      MSG("Dbi",Msg::kError) 
01350        << "Non-zero task test:" << endl
01351        << "      Set size is  " << setSize
01352        << " but should be 5 " 
01353        << ", number adopted is "<< numAdopted
01354        << " but should be 9 " << endl;
01355      ok = kFALSE;
01356   }
01357 
01358 // Test getting a DbiValidityRec for a row.
01359 
01360   VldTimeStamp tstamp2(2001, 01, 03, 12, 0, 0);
01361   VldContext vc2(Detector::kCalib,SimFlag::kData,tstamp2);
01362   Int_t startDateReq = 20010103;
01363   Int_t endDateReq   = 20010104;
01364 
01365   DbiResultPtr<DbiDemoData2> rp(vc2);
01366   const VldRange& rng = rp.GetValidityRec()->GetVldRange(); 
01367   Int_t startDateGot = rng.GetTimeStart().GetDate();
01368   Int_t endDateGot   = rng.GetTimeEnd().GetDate();
01369 
01370   if ( startDateGot != startDateReq || endDateGot != endDateReq ) {
01371      MSG("Dbi",Msg::kError) 
01372        << "Failed row validity test" << endl
01373        << "           got  " << startDateGot << "-" << endDateGot <<endl
01374        << " but should be  "  << startDateReq << "-" << endDateReq <<endl;
01375      ok = kFALSE;
01376   }
01377 
01378 
01379   MSG("Dbi",Msg::kInfo) 
01380        << "Test 5: Retrieval of aggregated data           ...... ";
01381   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
01382   MSG("Dbi",Msg::kInfo) << "\n";
01383 
01384 
01385   if ( ok ) fNumPass++; else fNumFail++;
01386 
01387   return ok;
01388   
01389 }
01390 
01391 //.....................................................................
01392 
01393 Bool_t DbiValidate::Test_6() {
01394 //
01395 //
01396 //  Purpose:   Test of configuration data..
01397 //  Arguments: None.
01398 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
01399 //
01400 //  Contact:   N. West
01401 //
01402 //  Specification:-
01403 //  =============
01404 //
01405 //  o Build DbiConfigStream and use it to fill a Registry.
01406  
01407   Bool_t ok = kTRUE;
01408 
01409 
01410 
01411 // Test of DbiConfigSet/Stream  reading of DbiDemoData4 
01412 // and DEMOASCIICONFIG data.
01413 // This tests configuration loading from a configuration table i.e.
01414 // one in which there is a single column holding a string with
01415 // attribute name=value pairs.
01416 
01417   for (int tryNum = 0; tryNum < 2; ++tryNum) {
01418 
01419     string tableName = tryNum == 0 ? "DbiDemoData4" : "DEMOASCIICONFIG";
01420 
01421     if ( tableName == "DEMOASCIICONFIG" && fSkipAsciiDbTest ) {
01422       MSG("Dbi",Msg::kInfo) << "Skipping test on ASCII DB" << endl;
01423       continue;
01424     }
01425     DbiConfigStream cfStream2(tableName,"default",DbiConfigStream::fgDefaultContext,0,tableName);
01426   
01427     if ( cfStream2.GetConfigSet() == 0 ) {
01428       MSG("Dbi",Msg::kError)
01429         << "Error: ConfigStream2 is empty for table  " << tableName << endl;
01430         ok = kFALSE;
01431     }
01432     else {
01433   
01434       Registry reg(kFALSE);
01435       cfStream2 >> &reg;
01436 
01437       bool  testBool      = 1;
01438       Double_t testDouble = 1.23456789012345678e+100;
01439       string testString   = "This is a string";
01440       int    testInt      = 12345;
01441   
01442       if (    testBool != reg.GetInt("mybool") 
01443            || fabs( testDouble - reg.GetDouble("mydouble") ) > 1.0e86
01444            || testString != reg.GetCharString("mystring") 
01445            || testInt  != reg.GetInt("myint") ) {
01446         MSG("Dbi",Msg::kInfo)
01447           << "Mismatch reading contents of " << tableName << ":-" << endl
01448           <<  "  Bool   " << reg.GetInt("mybool") 
01449           << " should be: " << testBool   << endl
01450           <<  "  Double " << reg.GetDouble("mydouble") 
01451           << " should be: " << testDouble 
01452           << " - diff = " << testDouble - reg.GetDouble("mydouble") << endl
01453           <<  "  String \"" << reg.GetCharString("mystring") 
01454           << "\" should be: \"" << testString << "\"" << endl
01455           <<  " testInt  " << reg.GetInt("myint") 
01456           << " should be: " << testInt<< endl;
01457           ok = kFALSE;
01458       }
01459   
01460     }
01461   }
01462 
01463   MSG("Dbi",Msg::kInfo) 
01464        << "Test 6: Retrieval of configuration data        ...... ";
01465   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
01466   MSG("Dbi",Msg::kInfo) << "\n";
01467 
01468 
01469   if ( ok ) fNumPass++; else fNumFail++;
01470 
01471   return ok;
01472   
01473 }
01474 
01475 
01476 //.....................................................................
01477 
01478 Bool_t DbiValidate::Test_7() {
01479 //
01480 //
01481 //  Purpose:   Test of DbiWriter and DbiLogEntry.
01482 //  Arguments: None.
01483 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
01484 //
01485 //  Contact:   N. West
01486 //
01487 //  Specification:-
01488 //  =============
01489 //
01490 //  o Duplicate and write an aggregated set, then read back and compare.
01491 //
01492 
01493   typedef vector<DbiWriter<DbiDemoData2>*> vector_writer_t;
01494   typedef vector_writer_t::iterator        vector_writer_itr_t;
01495  
01496   Bool_t ok = kTRUE;
01497   
01498 // Remove any existing data from the database.
01499 
01500   DbiCascader* cascader = DbiTableProxyRegistry::Instance().fCascader;
01501   auto_ptr<DbiStatement> stmtDb(cascader->CreateStatement(0));
01502 // To avoid those "Unable to close ...still active statements.
01503   cascader->SetPermanent(0);
01504 
01505 // Check out local and global SeqNo allocation.
01506 
01507   Int_t lsqn1 = cascader->AllocateSeqNo("DBIDEMODATA1",-1,0);
01508   Int_t lsqn2 = cascader->AllocateSeqNo("DBIDEMODATA1",-1,0);
01509   Int_t gsqn1 = cascader->AllocateSeqNo("DBIDEMODATA1",1,0);
01510   Int_t gsqn2 = cascader->AllocateSeqNo("DBIDEMODATA1",1,0);
01511   if ( lsqn1 != 4 || lsqn2 != 5 ) {
01512     MSG("Dbi",Msg::kError) 
01513      << "Bad local sequence numbers. Got " << lsqn1
01514      << "," << lsqn2 << " but should be 4,5" << endl;
01515      ok = kFALSE;
01516   }
01517   if ( gsqn1 != 900000001 || gsqn2 != 900000002 ) {
01518     MSG("Dbi",Msg::kError) 
01519      << "Bad global sequence numbers. Got " << gsqn1
01520      << "," << gsqn2 << " but should be 900000001,900000002" << endl;
01521      ok = kFALSE;
01522   }
01523 
01524   
01525   
01526 //  Unagregated data test
01527 //  *********************
01528 
01529 
01530 // Read in reference set,
01531 
01532   DbiDemoData3 refdd3;
01533   VldContext vc_dd3(refdd3.GetContextDTF());
01534   DbiResultPtr<DbiDemoData3> refRP3(vc_dd3,0);
01535   const DbiDemoData3* row3 = refRP3.GetRow(0);
01536 
01537 // Define a validity range for the output set.
01538 
01539   VldTimeStamp  start(2001,4,07,12,00,00);
01540 // Add 173 days to get end date.
01541   time_t vcSec = start.GetSec() + 173*24*60*60;
01542   VldTimeStamp    end(vcSec,0);
01543   VldTimeStamp create(2001,5,7,12,00,00);
01544   VldRange      range(7,3,start,end,"Test6");
01545   
01546 // Create a writer and store the data and close writer.
01547 
01548   DbiWriter<DbiDemoData3> writer3(range,-1,0,create,0);  
01549   DbiValidityRec vrec3(range,0,-1,0);
01550   string ovlayTsGot1 = writer3.TableProxy()
01551                        .QueryOverlayCreationDate(vrec3,0).AsString("s");
01552   string ovlayTsReq1 = "2001-04-07 12:00:00";
01553   writer3 << *row3;
01554 
01555 // Give it a log comment from a file.
01556   ofstream log_comment("dbi_test_7.tmp");
01557   log_comment << "First comment" << endl;
01558   log_comment << "FIXUP-FILE:  (should be ignored)" << endl;
01559   log_comment << "Second comment" << endl;
01560   log_comment << "BROADCAST:  (should be ignored)" << endl;
01561   log_comment << "Last comment" << endl;
01562   log_comment.close();
01563   writer3.SetLogComment("@dbi_test_7.tmp");
01564 
01565   if ( ! writer3.Close() ) {
01566     MSG("Dbi",Msg::kError) 
01567          << "Output error writing data" << endl;
01568      ok = kFALSE;
01569   }
01570   string ovlayTsGot2 = writer3.TableProxy()
01571                        .QueryOverlayCreationDate(vrec3,0).AsString("s");
01572   string ovlayTsReq2 = "2001-05-07 12:01:00";
01573 
01574   if ( ovlayTsGot1 != ovlayTsReq1 || ovlayTsGot2 != ovlayTsReq2 ) {
01575     MSG("Dbi",Msg::kError) 
01576          << "Bad overlay creation dates:-" 
01577          << "\n  No overlay: got " << ovlayTsGot1 << " but expected " << ovlayTsReq1 
01578          << "\n  Overlay:    got " << ovlayTsGot2 << " but expected " << ovlayTsReq2
01579          << endl;
01580      ok = kFALSE;
01581   }
01582 
01583 //  Read back the data just written and compare to the orginal.
01584 
01585   VldContext copyVC(Detector::kCalib,SimFlag::kData,create);
01586   DbiResultPtr<DbiDemoData3> copyRP3(copyVC,0);
01587 
01588   UInt_t copyNumRows = copyRP3.GetNumRows();
01589   if ( copyNumRows != 1 ) {
01590     MSG("Dbi",Msg::kError) 
01591      << "Reference size " << 1
01592      << "  does not match copy size  " << copyNumRows << endl;
01593      ok = kFALSE;
01594   }
01595 
01596   else {
01597     const DbiDemoData3* copyRow3 = copyRP3.GetRow(0);
01598     if ( ! refdd3.Compare(copyRow3) ) {
01599     MSG("Dbi",Msg::kError) 
01600      << "Comparison failed reference v. Database (written & read back)" << endl;
01601      ok = kFALSE;
01602     }
01603   }
01604 
01605 //  Try writing to an alternative table.
01606 
01607   DbiWriter<DbiDemoData3> writer3A(range,-1,0,create,0,"@dbi_test_7.tmp","DBIDEMODATA3A");  
01608   writer3A << *row3;
01609   if ( ! writer3A.Close() ) {
01610     MSG("Dbi",Msg::kError) 
01611          << "Output error writing data to DBIDEMODATA3A" << endl;
01612      ok = kFALSE;
01613   }
01614 
01615   DbiResultPtr<DbiDemoData3> copyRP3A("DBIDEMODATA3A",copyVC,0);
01616   UInt_t copyNumRowsA = copyRP3A.GetNumRows();
01617   if ( copyNumRowsA != 1 ) {
01618     MSG("Dbi",Msg::kError) 
01619      << "Reference size " << 1
01620      << "  does not match copy size  " << copyNumRowsA << endl;
01621      ok = kFALSE;
01622   }
01623 
01624  
01625 
01626 //  Use extended context query to check the update record.
01627   time_t insSec = copyRP3A.GetValidityRec()->GetInsertDate().GetSec();
01628   VldTimeStamp lo(insSec-10,0);
01629   VldTimeStamp hi(insSec+10,0);
01630   DbiSqlContext sc(DbiSqlContext::kWithin,lo,hi,Detector::kCalib,SimFlag::kData);
01631   DbiResultPtr<DbiLogEntry>  logEntryPtr("DbiLogEntry",sc);
01632   if ( logEntryPtr.GetNumRows() != 2 ) {
01633     MSG("Dbi",Msg::kError) 
01634      << "Expected to find two update record but found " 
01635      << logEntryPtr.GetNumRows() << endl;
01636      ok = kFALSE;
01637   }
01638   else {
01639     const DbiLogEntry* logEntry = logEntryPtr.GetRow(0);
01640     string logMsgReq = "First comment\nSecond comment\nLast comment\n";
01641     string logMsgGot = logEntry->GetReason();
01642     if ( logMsgReq != logMsgGot ) {
01643       MSG("Dbi",Msg::kError) 
01644         << "Expected update record reason:-\n" << logMsgReq
01645         << "\n but got:- \n" << logMsgGot << endl;
01646      ok = kFALSE;
01647     }
01648     
01649   }
01650 
01651 //  Agregated data test
01652 //  *******************
01653 
01654 
01655 // Read in reference set,
01656 
01657   VldTimeStamp tstamp(2001,1,1,12,0,0);
01658   VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
01659   DbiResultPtr<DbiDemoData2> refRP(vc,0);
01660 
01661 // Loop over all data creating DbiWriters for each aggregate and 
01662 // storing the data.
01663 
01664   vector_writer_t writers;
01665   UInt_t numRows = refRP.GetNumRows();  
01666   for (UInt_t irow = 0; irow < numRows; ++irow) {
01667     const DbiDemoData2* row = refRP.GetRow(irow);
01668     if ( ! row ) continue;
01669     UInt_t aggNo = row->GetAggregateNo();
01670     while ( aggNo >= writers.size() ) writers.push_back(0);
01671     DbiWriter<DbiDemoData2>* writer = writers[aggNo];
01672     if ( ! writer ) {
01673       writer = new DbiWriter<DbiDemoData2>(range,aggNo,0,create,0,"Updating DbiDemoData2");
01674       writers[aggNo] = writer;
01675     }
01676     *writer << *row;
01677   }
01678   
01679 // Loop over all writers, closing and deleting them.
01680 
01681   for (vector_writer_itr_t itr = writers.begin(); 
01682        itr != writers.end();
01683        ++itr ) {
01684     DbiWriter<DbiDemoData2>* writer = *itr;
01685     if ( writer ) {
01686       if ( ! writer->Close() ) {
01687         MSG("Dbi",Msg::kError) 
01688          << "Output error writing data" << endl;
01689          ok = kFALSE;
01690       }
01691 
01692       delete writer;
01693     }
01694   }
01695   
01696 //  Read back the data just written and compare to the orginal.
01697 
01698   DbiResultPtr<DbiDemoData2> copyRP(copyVC,0);
01699 
01700   copyNumRows = copyRP.GetNumRows();
01701   if ( numRows != copyNumRows || numRows == 0 ) {
01702     MSG("Dbi",Msg::kError) 
01703      << "Reference size " << numRows
01704      << "  is zero, or does not match copy size  " << copyNumRows << endl;
01705      ok = kFALSE;
01706   }
01707 
01708   else {
01709     for (UInt_t irow = 0; irow < numRows; ++irow) {
01710       const DbiDemoData2* refRow  = refRP.GetRow(irow);
01711       const DbiDemoData2* copyRow = copyRP.GetRowByIndex(refRow->GetIndex(irow));
01712       Int_t refAggNo   = refRow->GetAggregateNo();
01713       Int_t copyAggNo  = copyRow->GetAggregateNo();
01714       Float_t refData  = refRow->GetData();
01715       Float_t copyData = copyRow->GetData();
01716       if ( refAggNo != copyAggNo || refData != copyData ) {
01717         MSG("Dbi",Msg::kError) 
01718           << "Mismatch between ref. and copy on row " << irow << endl
01719           << "    Agg. nos: " << refAggNo << "," << copyAggNo 
01720           << "   Data:" << refData  << "," << copyData << endl;
01721        ok = kFALSE;
01722       }
01723     }
01724   }
01725 
01726   // Try writing configuration data.
01727 
01728   DbiConfigStream cfs("DbiDemoData4","NewData",DbiConfigStream::fgDefaultContext,0,"DbiDemoData4");
01729   if ( ! cfs.IsEmpty() ) {
01730     MSG("Dbi",Msg::kError) << "New configuration data already exists." << endl;
01731    ok = kFALSE;
01732   }
01733 
01734   Registry reg(kFALSE);
01735   reg.Set("MyInt",123);
01736   reg.Set("MyFloat",456.0);
01737   reg.Set("MyString","A string");
01738   cfs << &reg;
01739 
01740   if ( cfs.IsEmpty() ) {
01741     MSG("Dbi",Msg::kError) << "Config stream still empty after adding config data." << endl;
01742    ok = kFALSE;
01743   }
01744   if ( ! cfs.Write(0,"Test writing config data") ) {
01745     MSG("Dbi",Msg::kError) << "Failed to write Config stream." << endl;
01746    ok = kFALSE;
01747   }
01748 
01749   // Try reading it back again.  Need to set cache as stale to force reloading.
01750   DbiConfigSet pet;
01751   DbiTableProxyRegistry::Instance().GetTableProxy("DbiDemoData4",&pet).GetCache()->SetStale();
01752   DbiConfigStream cfs2("DbiDemoData4","NewData",DbiConfigStream::fgDefaultContext,0,"DbiDemoData4");
01753   if ( cfs2.IsEmpty() ) {
01754     MSG("Dbi",Msg::kError) << "Cannot find new configuration data." << endl;
01755    ok = kFALSE;
01756   }
01757 
01758   Registry reg2(kFALSE);
01759   cfs >> &reg2;
01760   ostringstream os;
01761   ostringstream os2;
01762   reg.PrettyPrint(os);
01763   reg.PrettyPrint(os2);
01764   if ( os.str() != os2.str() ) {
01765     MSG("Dbi",Msg::kError) << "Configuration I/O failed."
01766                            << "\n Wrote:" << os.str() 
01767                            << "\n Read: " << os2.str() << endl;
01768    ok = kFALSE;
01769   }
01770   MSG("Dbi",Msg::kInfo) 
01771        << "Test 7: Writing data                           ...... ";
01772   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
01773   MSG("Dbi",Msg::kInfo) << "\n";
01774 
01775 
01776   if ( ok ) fNumPass++; else fNumFail++;
01777 
01778   return ok;
01779   
01780 }
01781 
01782 //.....................................................................
01783 
01784 Bool_t DbiValidate::Test_8() {
01785 //
01786 //
01787 //  Purpose:  ASCII catalogue and files.
01788 //  Arguments: None.
01789 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
01790 //
01791 //  Contact:   N. West
01792 //
01793 //  Specification:-
01794 //  =============
01795 //
01796 //  o Load ASCII catalogue that contains two table:-
01797 //     DEMOASCIIDATA and DEMOASCIIDATAVLD
01798 //    That are compatible with DbiDemoData1.
01799 //
01800 //  o Load DbiDemoData1 from this data and check its data.
01801 
01802   Bool_t ok = kTRUE;
01803   if ( fSkipAsciiDbTest ) {
01804     MSG("Dbi",Msg::kInfo) << "Skipping test on ASCII DB" << endl;
01805     return ok;
01806   }
01807 
01808   const Int_t dbNoCat = 2;  // Hardwired catalog DB as 3rd in cascade.
01809   DbiCascader* cascader = DbiTableProxyRegistry::Instance().fCascader;
01810   string url = cascader->GetURL(dbNoCat);
01811   if ( url == "" || url.find("DemoASCIICatalogue.db") > url.size() ) {
01812     MSG("Dbi",Msg::kError) 
01813         << "Database number " << dbNoCat << " does not have \n"
01814         << " name DemoASCIICatalogue.db; assumed not to be" 
01815         << " an ASCII catalogue.  Aborting test " << endl;
01816     ok = kFALSE;
01817   }
01818 
01819   else {
01820     string asciiName = "DemoASCIIData";
01821     if ( ! cascader->TableExists(asciiName) ) asciiName = "DEMOASCIIDATA";
01822     VldTimeStamp tstamp(2001,1, 3, 12, 0, 0);
01823     VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
01824     DbiResultPtr<DbiDemoData1> pr(asciiName,vc,0);
01825     const DbiDemoData1* ddd1 = pr.GetRow(0);
01826     if ( ! ddd1 ) {
01827       MSG("Dbi",Msg::kError) 
01828         << "No " << asciiName << " in catalogue " << endl;
01829       ok = kFALSE;
01830     }
01831     else {
01832       if (     ddd1->GetPedestal() != 1.0
01833             || ddd1->GetGain1()    != 10.
01834             || ddd1->GetGain2()    != 100. ){
01835         MSG("Dbi",Msg::kError) 
01836           << "Data of first row in catalogue "
01837           << ddd1->GetPedestal() << "," 
01838           << ddd1->GetGain1() << "," 
01839           << ddd1->GetGain2() << "," 
01840           << " but should have been 1.,10.,100." << endl;
01841         ok = kFALSE;
01842       }
01843     }
01844   }
01845 
01846   MSG("Dbi",Msg::kInfo) 
01847        << "Test 8: Flat file (ASCII) access               ...... ";
01848   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
01849   MSG("Dbi",Msg::kInfo) << "\n";
01850 
01851 
01852   if ( ok ) fNumPass++; else fNumFail++;
01853 
01854   return ok;
01855   
01856 }
01857 //.....................................................................
01858 
01859 Bool_t DbiValidate::Test_9() {
01860 //
01861 //
01862 //  Purpose:  Temporary tables
01863 //  Arguments: None.
01864 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
01865 //
01866 //  Contact:   N. West
01867 //
01868 //  Specification:-
01869 //  =============
01870 //
01871 //  o Create temporary table and then try to access it.
01872 //
01873  
01874   Bool_t ok = kTRUE;
01875 
01876 // Running this test with ORACLE in position 0 in the cascade fails.  It objects:-
01877 //
01878 //     Error executing " create global temporary table DBIDEMODATA1 ...
01879 //      ...  name is already used by an existing object"
01880 //
01881 // but the whole point of the test is to do just that - overlay existing data.
01882 // Still ORACLE won't be use to host temporary tables so I will skip 
01883 // this test when ORACLE is in position 0 of the cascade. 
01884 
01885   DbiCascader& cascader 
01886                       = DbiTableProxyRegistry::Instance().GetCascader();
01887   Dbi::DbTypes dbType = cascader.GetConnection(0)->GetDbType();
01888   if ( dbType == Dbi::kOracle ) {
01889     MSG("Dbi",Msg::kInfo) 
01890       << "Test 9: Temporary table creation & access      ...... Skipped (ORACLE in cascade entry 0)" << endl;
01891     return ok;
01892   }
01893 
01894      
01895 // First read DbiDemoData1 from a date found in primary database.
01896 
01897   VldTimeStamp tstamp(2001,01,05,10,30,0);
01898   VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
01899   DbiResultPtr<DbiDemoData1> pr(vc,0);
01900 
01901   unsigned int numRows = pr.GetNumRows();
01902   if ( numRows != 4 ) {    
01903     MSG("Dbi",Msg::kError) 
01904         << "Before writing temp table Query date: " 
01905         << tstamp.AsString() << endl
01906         << " gave num rows  " << numRows 
01907         << " but should have given 4" << endl;
01908     ok = kFALSE;
01909   }
01910 
01911 // Mark as stale so won't use cache again.
01912 
01913   pr.TableProxy().GetCache()->SetStale();
01914 
01915 // Now write new data into temporary table to replace it.
01916 
01917 
01918   string tableDescr = "(SEQNO int,"
01919                       " ROW_COUNTER int,"
01920                       " SUBSYSTEM  int,"
01921                       " PEDESTAL float,"
01922                       " GAIN1 float,"
01923                       " GAIN2 float )";
01924   string tableName = "DbiDemoData1";
01925   if ( ! cascader.TableExists(tableName) ) tableName = "DBIDEMODATA1";
01926   Int_t dbNo = cascader.CreateTemporaryTable(tableName,tableDescr);
01927 
01928   if ( dbNo < 0 ) {
01929     MSG("Dbi",Msg::kError) 
01930      << "Unable to find a database to accept temporary tables. "<< endl;
01931      ok = kFALSE;
01932   }
01933 
01934   else if ( dbNo > 0 ) {
01935     MSG("Dbi",Msg::kError) 
01936       << "Found database " <<  dbNo 
01937       << " to accept temporary tables, but should have been 0. "<< endl;
01938      ok = kFALSE;
01939   }
01940  
01941   else {
01942 
01943     VldTimeStamp  start(2001,1,1,12,00,00);
01944     VldTimeStamp    end(2001,9,27,12,00,00);
01945     VldRange      range(7,3,start,end,"Test8");
01946 
01947     DbiWriter<DbiDemoData1> wr(range,-1);
01948     DbiDemoData1 dd1(7,7.,7.,7.);
01949     wr << dd1;
01950     if ( ! wr.Close() ) {
01951       MSG("Dbi",Msg::kError) 
01952         << "Output to temporary table failed." << endl;
01953        ok = kFALSE;
01954     }
01955   }
01956 
01957 // Read again and confirm we get the new data.
01958 
01959   pr.NewQuery(vc,0);
01960 
01961   numRows = pr.GetNumRows();
01962   Float_t ped = -999.;
01963   if ( numRows > 0 ) ped = pr.GetRow(0)->GetPedestal();
01964 
01965   if ( numRows != 1 || ped != 7. ) {    
01966     MSG("Dbi",Msg::kError) 
01967         << "After writing temp table Query date: " 
01968         << tstamp.AsString() << endl
01969         << " gave num rows  " << numRows 
01970         << " but should have given 1" << endl
01971         << " First row pedesal was " << ped
01972         << " but should have been 7." << endl;
01973     ok = kFALSE;
01974   }
01975 
01976   MSG("Dbi",Msg::kInfo) 
01977        << "Test 9: Temporary table creation & access      ...... ";
01978   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
01979   MSG("Dbi",Msg::kInfo) << "\n";
01980 
01981 
01982   if ( ok ) fNumPass++; else fNumFail++;
01983 
01984   return ok;
01985   
01986 }
01987 
01988 //.....................................................................
01989 
01990 Bool_t DbiValidate::Test_10() {
01991 //
01992 //
01993 //  Purpose:  Database maintenance support
01994 //  Arguments: None.
01995 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
01996 //
01997 //  Contact:   N. West
01998 //
01999 //  Specification:-
02000 //  =============
02001 //
02002 //  o Test out sequence number replacement and loading of all 
02003 //    validity records.
02004 //
02005 //  Program Notes:-
02006 //  ============= 
02007 //
02008 //  Relies on data written by Test 7 (yes I know that's bad and that I 
02009 //  should make them all independent!)
02010 
02011   Bool_t ok = kTRUE;
02012   
02013 // Get Db proxy for DbiDemoData2 table.
02014   DbiDemoData1 pet;
02015   DbiTableProxy& tbProxy  = DbiTableProxyRegistry::Instance()
02016                            .GetTableProxy("DbiDemoData2",&pet);
02017   const DbiDBProxy& proxy = tbProxy.GetDBProxy(); 
02018 
02019 // Renumber a known SeqNo in Db 0
02020   ok = proxy.ReplaceSeqNo(900000002,710000002,0);
02021   if ( ! ok ) MSG("Dbi",Msg::kError) << " Replace SeqNo failed." << endl;
02022   
02023 // Check create table SQL generation.
02024 
02025   TString sqlMainExp;
02026   sqlMainExp += "CREATE TABLE DBIDEMODATA2(SEQNO INT NOT NULL, ";
02027   sqlMainExp += "ROW_COUNTER INT NOT NULL, ";
02028   sqlMainExp += "AGGREGATENO INT, ";
02029   sqlMainExp += "SUBSYSTEM INT, ";
02030   sqlMainExp += "DATA FLOAT, PRIMARY KEY (SEQNO,ROW_COUNTER))";
02031   TString sqlMainGot = tbProxy.GetMetaData().Sql();
02032   sqlMainGot.ToUpper();
02033   if ( sqlMainGot != sqlMainExp ) {
02034     MSG("Dbi",Msg::kError) 
02035       << " Creation SQL failed.  Got:-\n" << sqlMainGot
02036       << "\n but expected:-\n" << sqlMainExp << endl;
02037     ok = kFALSE;
02038   }
02039 
02040   TString sqlAuxGot = tbProxy.GetMetaValid().Sql();
02041   sqlAuxGot.ToUpper();
02042   TString sqlAuxExp;
02043   sqlAuxExp += "CREATE TABLE DBIDEMODATA2VLD(";
02044   sqlAuxExp += "SEQNO INT NOT NULL PRIMARY KEY, ";
02045   sqlAuxExp += "TIMESTART DATETIME NOT NULL, ";
02046   sqlAuxExp += "TIMEEND DATETIME NOT NULL, ";
02047   sqlAuxExp += "DETECTORMASK TINYINT, ";
02048   sqlAuxExp += "SIMMASK TINYINT, ";
02049   sqlAuxExp += "TASK INT, ";
02050   sqlAuxExp += "AGGREGATENO INT, ";
02051   sqlAuxExp += "CREATIONDATE DATETIME NOT NULL, ";
02052   sqlAuxExp += "INSERTDATE DATETIME NOT NULL, ";
02053   sqlAuxExp += "KEY TIMESTART (TIMESTART), KEY TIMEEND (TIMEEND))";
02054   TString sqlAuxExpOracle =  
02055                "CREATE TABLE DBIDEMODATA2VLD(SEQNO INTEGER NOT NULL PRIMARY KEY, "
02056                "TIMESTART DATE NOT NULL, TIMEEND DATE NOT NULL, "
02057                "DETECTORMASK INTEGER, SIMMASK INTEGER, TASK INTEGER, "
02058                "AGGREGATENO INTEGER, CREATIONDATE DATE NOT NULL, "
02059                "INSERTDATE DATE NOT NULL)";
02060   if ( sqlAuxGot != sqlAuxExp 
02061        && sqlAuxGot != sqlAuxExpOracle) {
02062     MSG("Dbi",Msg::kError) 
02063       << " Creation SQL failed.  Got:-\n" << sqlAuxGot
02064       << "\n but expected:-\n" << sqlAuxExp
02065       << "\n or (ORACLE):-\n" << sqlAuxExpOracle << endl;
02066     ok = kFALSE;
02067   }
02068   
02069 // Collect up all validity records.
02070   DbiValRecSet vrs("DbiDemoData2",0); 
02071   if ( vrs.GetNumRows() != 5 ) {    
02072     MSG("Dbi",Msg::kError) 
02073         << " No. of DbiDemoData2Validity records in cascade entry 0"
02074         << " was " << vrs.GetNumRows() 
02075         << " but should have been 5." << endl;
02076     ok = kFALSE;
02077   }
02078 
02079 // Fill up a DbiConfigSet query for each DbiValidityRec and export it
02080 // checking to see if replaced one is there.
02081   ofstream export_stream("dbi_test_10.tmp");
02082   int matchMask = 0;
02083   for (unsigned int irec = 0; irec < vrs.GetNumRows(); ++irec) {
02084     const DbiValidityRec* vrec = vrs.GetTableRow(irec);
02085     DbiResultPtr<DbiConfigSet> cfsPtr("DbiDemoData2",*vrec);
02086     int numRows = cfsPtr.GetNumRows();
02087     int seqno = vrec->GetSeqNo();
02088     if      ( seqno == 710000002 && numRows == 4 )   matchMask |= 1;
02089     else if ( seqno == 900000001 && numRows == 3 )   matchMask |= 2;
02090     else if ( seqno == 900000003 && numRows == 2 )   matchMask |= 4;
02091     else if ( seqno == 900000004 && numRows == 3 )   matchMask |= 8;
02092     else if ( seqno == 900000005 && numRows == 3 )   matchMask |= 16;
02093     else  {
02094       MSG("Dbi",Msg::kError) 
02095         << "ValidityRec Row " << irec 
02096         << " SEQNO = " << seqno << " No of members " << numRows
02097         << " does not match any of:\n "
02098         << " (710000002,4),(900000001,3),(900000003,2),(900000004,3),(900000005,3)" << endl;
02099       ok = kFALSE;
02100     }
02101 
02102     DbiSqlValPacket packet(*vrec);
02103     packet.Write(export_stream,irec==0);
02104   }
02105   if ( matchMask != 31 ) {
02106     MSG("Dbi",Msg::kError) 
02107       << "Didn't find all expected rows.  Match mask = " << matchMask
02108       << " but should have been 31" << endl;
02109     ok = kFALSE;
02110   }
02111   export_stream.close();
02112   
02113 // Import them again and check total numbers.
02114   ifstream import("dbi_test_10.tmp");
02115   DbiSqlValPacket packet(import);
02116 
02117   UInt_t numPackets = 0;
02118   UInt_t numStmts   = 0;
02119   while ( packet.CanBeStored() ) {
02120     ++ numPackets;
02121     numStmts += packet.GetNumSqlStmts();
02122     packet.Fill(import);
02123   }
02124 
02125   if ( numPackets != 5 || numStmts != 20 ) {
02126     MSG("Dbi",Msg::kError) 
02127         << "Packet and statements counts were (" << numPackets
02128         << "," <<  numStmts << ") but should have been (5,20)" << endl;
02129     ok = kFALSE;
02130   }
02131 
02132   VldTimeStamp aDate(2001,9,27,1,2,3);
02133   proxy.ReplaceInsertDate(aDate,900000005,0);
02134 
02135   MSG("Dbi",Msg::kInfo) 
02136        << "Test 10: Database maintenance support          ...... ";
02137   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
02138   MSG("Dbi",Msg::kInfo) << "\n";
02139 
02140 
02141   if ( ok ) fNumPass++; else fNumFail++;
02142 
02143   return ok;
02144   
02145 }
02146 
02147 //.....................................................................
02148 
02149 Bool_t DbiValidate::Test_11() {
02150 //
02151 //
02152 //  Purpose:  Test Rollback
02153 //  Arguments: None.
02154 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
02155 //
02156 //  Contact:   N. West
02157 //
02158 //  Specification:-
02159 //  =============
02160 //
02161 //  o Test Rollback
02162 //
02163  
02164   Bool_t ok = kTRUE;
02165 
02166   VldTimeStamp tstamp(2001,01,05,0,0,0,0);
02167   VldContext vc(Detector::kCalib,SimFlag::kData,tstamp);
02168 
02169   DbiResultPtr<DbiDemoData1> pr;
02170   DbiCache* cache =  pr.TableProxy().GetCache();
02171   cache->Purge();
02172 
02173   CfgConfigurable& dbiCfg = DbiTableProxyRegistry::Instance();
02174   dbiCfg.Set("Rollback:* = '2000-01-01'");
02175   dbiCfg.Set("Rollback:DBI* = '2000-01-01'");
02176   dbiCfg.Update();
02177 
02178   cache->Purge();
02179   pr.NewQuery(vc,0);
02180 
02181   float gain = pr.GetRow(0)->GetGain1();
02182   if ( gain != 9. ) {
02183     MSG("Dbi",Msg::kError) 
02184         << "Rollback gain should be 9. but was " << gain << endl;
02185     ok = kFALSE;
02186   }
02187 
02188   dbiCfg.Set("Rollback:DBI* = '2001-01-04'");
02189   dbiCfg.Set("RollbackType:DBI* = 'CREATIONDATE'");
02190   dbiCfg.Update();
02191 
02192   cache->SetStale();  // Cannot just purge, the client still exists.
02193   pr.NewQuery(vc,0);
02194 
02195   gain = pr.GetRow(0)->GetGain1();
02196   if ( gain != 7. ) {
02197     MSG("Dbi",Msg::kError) 
02198         << "Rollback gain should be 7. but was " << gain << endl;
02199     ok = kFALSE;
02200   }
02201   DbiTableProxyRegistry::Instance().ClearRollbackDates();
02202 
02203   MSG("Dbi",Msg::kInfo) 
02204        << "Test 11: Rollback                              ...... ";
02205   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
02206   MSG("Dbi",Msg::kInfo) << "\n";
02207 
02208 
02209   if ( ok ) fNumPass++; else fNumFail++;
02210 
02211   return ok;
02212   
02213 }
02214 //.....................................................................
02215 
02216 Bool_t DbiValidate::Test_12() {
02217 //
02218 //
02219 //  Purpose:   Extended context queries.
02220 //  Arguments: None.
02221 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
02222 //
02223 //  Contact:   N. West
02224 //
02225 //  Specification:-
02226 //  =============
02227 //
02228 //  o 
02229 //
02230  
02231   Bool_t ok = kTRUE;
02232 
02233   VldTimeStamp start(2002, 1, 1, 0, 0, 0);
02234   VldTimeStamp   end(2004, 1, 1, 0, 0, 0);
02235   DbiSqlContext   sc(DbiSqlContext::kStarts,start,end,Detector::kFar,SimFlag::kData);
02236   DbiResultPtr<DbiDemoData1>  rp("DbiDemoData1",sc,5,"SUBSYSTEM > 1");
02237   DbiResultPtr<DbiDemoData1> rp2("DbiDemoData1",sc,5,"SUBSYSTEM > 1");
02238 
02239   if ( rp.GetNumRows() != 4 ) {
02240     MSG("Dbi",Msg::kError) 
02241         << "First extended context query should give 4 rows but gave " 
02242         << rp.GetNumRows() << endl;
02243     ok = kFALSE;
02244   }
02245   if ( rp.GetResult() != rp2.GetResult() ) {
02246     MSG("Dbi",Msg::kError) 
02247         << "Repeat of first extended context query didn't use cache." << endl;
02248     ok = kFALSE;
02249   }
02250 
02251   rp.NewQuery(sc,5,"","Test Fill Options");
02252   if ( rp.GetNumRows() != 8 ) {
02253     MSG("Dbi",Msg::kError) 
02254         << "Second extended context query should give 8 rows but gave " 
02255         << rp.GetNumRows() << endl;
02256     ok = kFALSE;
02257   }
02258 
02259   MSG("Dbi",Msg::kInfo) 
02260        << "Test 12: Extended context queries              ...... ";
02261   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
02262   MSG("Dbi",Msg::kInfo) << "\n";
02263 
02264 
02265   if ( ok ) fNumPass++; else fNumFail++;
02266 
02267   return ok;
02268   
02269 }
02270 
02271 //.....................................................................
02272 
02273 Bool_t DbiValidate::Test_13() {
02274 //
02275 //
02276 //  Purpose:  
02277 //  Arguments: None.
02278 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
02279 //
02280 //  Contact:   N. West
02281 //
02282 //  Specification:-
02283 //  =============
02284 //
02285 //  o 
02286 //
02287  
02288   Bool_t ok = kTRUE;
02289 
02290   Int_t date = 20010103;
02291   Int_t time = 120000;
02292   VldTimeStamp tstamp(date/10000, date/100%100, date%100,
02293                         time/10000, time/100%100, time%100);
02294   VldContext vc_data(Detector::kCalib,SimFlag::kData,tstamp);
02295   VldContext vc_mc(Detector::kCalib,SimFlag::kMC,tstamp);
02296 
02297   // There isn't any data for MC but SimFlag association should allow it to
02298   // find data.  Have 2 tries:-
02299   //
02300   //  1)  Data then MC  - to test cache search
02301   //  2)  MC then data  - to test database query
02302 
02303 
02304   DbiTableProxyRegistry& tpr = DbiTableProxyRegistry::Instance();  
02305   tpr.Set("SimFlagAssociation:MC = 'Reroot,MC,Data'");
02306   tpr.Update();
02307 
02308   for ( int itry=1; itry <= 2; ++itry ) {
02309 
02310     tpr.PurgeCaches ();
02311 
02312     DbiResultPtr<DbiDemoData2> pr_data;
02313     DbiResultPtr<DbiDemoData2> pr_mc;
02314 
02315     if ( itry == 1 ) {
02316       pr_data.NewQuery(vc_data,0);
02317       pr_mc.NewQuery(vc_mc,0);
02318     }
02319     else {
02320       pr_mc.NewQuery(vc_mc,0);
02321       pr_data.NewQuery(vc_data,0);
02322     }
02323     int numRows_data = pr_data.GetNumRows();
02324     int numRows_mc   = pr_mc.GetNumRows();
02325 
02326     if ( numRows_data != 15 || numRows_mc != 15) {
02327       MSG("Dbi",Msg::kError) 
02328         << "SimFlag association failed on try " << itry
02329         << ". Both data and MC should give 15 rows but gave " << numRows_data
02330         << "," << numRows_mc << endl;
02331       ok = kFALSE;
02332     }
02333   }
02334 
02335   tpr.ClearSimFlagAssociation();
02336 
02337 
02338   MSG("Dbi",Msg::kInfo) 
02339        << "Test 13: SimFlag Association:                  ...... ";
02340   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
02341   MSG("Dbi",Msg::kInfo) << "\n";
02342 
02343 
02344   if ( ok ) fNumPass++; else fNumFail++;
02345 
02346   return ok;
02347 
02348   
02349 }
02350 
02351 // Template for further tests
02352 /*
02353 
02354 //.....................................................................
02355 
02356 Bool_t DbiValidate::Test_?() {
02357 //
02358 //
02359 //  Purpose:  
02360 //  Arguments: None.
02361 //  Return:    = kTRUE if all tests are O.K., kFALSE otherwise.  
02362 //
02363 //  Contact:   N. West
02364 //
02365 //  Specification:-
02366 //  =============
02367 //
02368 //  o 
02369 //
02370  
02371   Bool_t ok = kTRUE;
02372 
02373   MSG("Dbi",Msg::kInfo) 
02374 //     << "Test x:                                        ...... ";
02375        << "Test ?:                                        ...... ";
02376   MSG("Dbi",Msg::kInfo) << ( ok ? "O.K." : "Failed") ;
02377   MSG("Dbi",Msg::kInfo) << "\n";
02378 
02379 
02380   if ( ok ) fNumPass++; else fNumFail++;
02381 
02382   return ok;
02383   
02384 }
02385 
02386 */

Generated on Mon Feb 15 11:06:35 2010 for loon by  doxygen 1.3.9.1