// @(#)root/test:$Id$ // Author: David Smith 20/10/14 ///////////////////////////////////////////////////////////////// // //___A test for I/O plugins by reading files___ // // The files used in this test have been generated by // stress.cxx and preplaced on some data servers. // stressIOPlugins reads the remote files via various data // access protocols to test ROOT IO plugins. The data read are // tested via tests based on some of stress.cxx tests. // // Can be run as: // stressIOPlugins // stressIOPlugins [name] // // The name parameter is a protocol name, as expected // in a url. The supported names are: xroot, root, http, https // If the name is omitted a selection of schemes are // tested based on feature availability: // // feature protocol // // xrootd root // davix http // // An example of output when all the tests run OK is shown below: // // **************************************************************************** // * Starting stressIOPlugins test for protocol http // * Test files will be read from: // * http://root.cern.ch/files/StressIOPluginsTestFiles/ // **************************************************************************** // Test 1 : Check size & compression factor of a Root file........ using stress_2.root // : opened file with plugin class......................... TDavixFile // : Check size & compression factor of a Root file........ OK // Test 2 : Test graphics & Postscript............................ using stress_5.root // : opened file with plugin class......................... TDavixFile // : Test graphics & Postscript............................ OK // Test 3 : Trees split and compression modes..................... using Event_8a.root // : opened file with plugin class......................... TDavixFile // : Trees split and compression modes..................... using Event_8b.root // : opened file with plugin class......................... TDavixFile // : Trees split and compression modes..................... OK // **************************************************************************** //_____________________________batch only_____________________ #ifndef __CINT__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Event.h" void stressIOPlugins(); void stressIOPluginsForProto(const char *protoName = 0); void stressIOPlugins1(); void stressIOPlugins2(); void stressIOPlugins3(); void cleanup(); int main(int argc, char **argv) { gROOT->SetBatch(); TApplication theApp("App", &argc, argv); const char *proto = 0; if (argc > 1) proto = argv[1]; stressIOPluginsForProto(proto); return 0; } #endif class TH1; class TTree; #if defined(__CINT__) || defined(__CLING__) struct ensureEventLoaded { public: ensureEventLoaded() { // if needed load the Event shard library, making sure it exists // This test dynamic linking when running in interpreted mode if (!TClassTable::GetDict("Event")) { Int_t st1 = -1; if (gSystem->DynamicPathName("$ROOTSYS/test/libEvent",kTRUE)) { st1 = gSystem->Load("$(ROOTSYS)/test/libEvent"); } if (st1 == -1) { if (gSystem->DynamicPathName("test/libEvent",kTRUE)) { st1 = gSystem->Load("test/libEvent"); } if (st1 == -1) { printf("===>stress8 will try to build the libEvent library\n"); Bool_t UNIX = strcmp(gSystem->GetName(), "Unix") == 0; if (UNIX) gSystem->Exec("(cd $ROOTSYS/test; make Event)"); else gSystem->Exec("(cd %ROOTSYS%\\test && nmake libEvent.dll)"); st1 = gSystem->Load("$(ROOTSYS)/test/libEvent"); } } } } ~ensureEventLoaded() { } } myStaticObject; #endif //_______________________ common part_________________________ Double_t ntotin=0, ntotout=0; TString gPfx; void Bprint(Int_t id, const char *title) { // Print test program number and its title const Int_t kMAX = 65; char header[80]; if (id > 0) { snprintf(header,80,"Test %2d : %s",id,title); } else { snprintf(header,80," : %s",title); } Int_t nch = strlen(header); for (Int_t i=nch;iClassName()); Bprint(0, title); return f; } Bool_t isFeatureAvailable(const char *name) { TString configfeatures = gROOT->GetConfigFeatures(); return configfeatures.Contains(name); } int setPath(const char *proto) { if (!proto) return -1; TString p(proto); if (p == "root" || p == "xroot") { gPfx = p + "://eospublic.cern.ch//eos/opstest/dhsmith/StressIOPluginsTestFiles/"; return 0; } if (p == "http" || p == "https") { gPfx = p + "://root.cern.ch/files/StressIOPluginsTestFiles/"; return 0; } return -1; } void stressIOPluginsForProto(const char *protoName /*=0*/) { //Main control function invoking all test programs if (!protoName) { if (isFeatureAvailable("xrootd")) { stressIOPluginsForProto("root"); } else { printf("* Skipping root protocol test because 'xrootd' feature not available\n"); } if (isFeatureAvailable("davix")) { stressIOPluginsForProto("http"); } else { printf("* Skipping http protocol test because 'davix' feature not available\n"); } return; } if (setPath(protoName)) { printf("No server and path available to test protocol %s\n", protoName); return; } printf("****************************************************************************\n"); printf("* Starting stressIOPlugins test for protocol %s\n", protoName); printf("* Test files will be read from:\n"); printf("* %s\n", gPfx.Data()); printf("****************************************************************************\n"); stressIOPlugins1(); stressIOPlugins2(); stressIOPlugins3(); cleanup(); printf("****************************************************************************\n"); } void stressIOPlugins() { stressIOPluginsForProto((const char*)0); } //_______________________________________________________________ void stressIOPlugins1() { //based on stress2() //check length and compression factor in stress.root const char *title = "Check size & compression factor of a Root file"; Bprint(1, title); TFile *f = openTestFile("stress_2.root", title); if (!f) { printf("FAILED\n"); return; } Long64_t last = f->GetEND(); Float_t comp = f->GetCompressionFactor(); Bool_t OK = kTRUE; Long64_t lastgood = 9428; if (last lastgood+200 || comp <2.0 || comp > 2.4) OK = kFALSE; if (OK) printf("OK\n"); else { printf("FAILED\n"); printf("%-8s last =%lld, comp=%f\n"," ",last,comp); } delete f; } //_______________________________________________________________ void stressIOPlugins2() { // based on stress5() // Test of Postscript. // Make a complex picture. Verify number of lines on ps file // Testing automatically the graphics package is a complex problem. // The best way we have found is to generate a Postscript image // of a complex canvas containing many objects. // The number of lines in the ps file is compared with a reference run. // A few lines (up to 2 or 3) of difference may be expected because // Postscript works with floats. The date and time of the run are also // different. // You can also inspect visually the ps file with a ps viewer. const char *title = "Test graphics & Postscript"; Bprint(2,title); TCanvas *c1 = new TCanvas("c1","stress canvas",800,600); gROOT->LoadClass("TPostScript","Postscript"); TString psfname = TString::Format("stressIOPlugins-%d.ps", gSystem->GetPid()); TPostScript ps(psfname,112); //Get objects generated in previous test TFile *f = openTestFile("stress_5.root",title); if (!f) { printf("FAILED\n"); return; } TF1 *f1form = (TF1*)f->Get("f1form"); TF2 *f2form = (TF2*)f->Get("f2form"); TH1F *h1form = (TH1F*)f->Get("h1form"); TH2F *h2form = (TH2F*)f->Get("h2form"); //Divide the canvas in subpads. Plot with different options c1->Divide(2,2); c1->cd(1); f1form->Draw(); c1->cd(2); h1form->Draw(); c1->cd(3); h2form->Draw("box"); f2form->Draw("cont1same"); c1->cd(4); f2form->Draw("surf"); ps.Close(); //count number of lines in ps file FILE *fp = fopen(psfname.Data(),"r"); if (!fp) { printf("FAILED\n"); printf("%-8s could not open %s\n"," ",psfname.Data()); delete c1; delete f; return; } char line[260]; Int_t nlines = 0; Int_t nlinesGood = 632; while (fgets(line,255,fp)) { nlines++; } fclose(fp); ntotin += f->GetBytesRead(); ntotout += f->GetBytesWritten(); Bool_t OK = kTRUE; if (nlines < nlinesGood-110 || nlines > nlinesGood+110) OK = kFALSE; if (OK) printf("OK\n"); else { printf("FAILED\n"); printf("%-8s nlines in %s file = %d\n"," ",psfname.Data(),nlines); } delete c1; delete f; } //_______________________________________________________________ Int_t test3read(const TString &fn, const char *title) { // Read the event file // Loop on all events in the file (reading everything). // Count number of bytes read Int_t nevent = 0; TFile *hfile = openTestFile(fn,title); if (!hfile) { return 0; } TTree *tree; hfile->GetObject("T",tree); Event *event = 0; tree->SetBranchAddress("event",&event); Int_t nentries = (Int_t)tree->GetEntries(); Int_t nev = TMath::Max(nevent,nentries); //activate the treeCache Int_t cachesize = 10000000; //this is the default value: 10 MBytes tree->SetCacheSize(cachesize); TTreeCache::SetLearnEntries(1); //one entry is sufficient to learn TTreeCache *tc = (TTreeCache*)hfile->GetCacheRead(); tc->SetEntryRange(0,nevent); Int_t nb = 0; for (Int_t ev = 0; ev < nev; ev++) { nb += tree->GetEntry(ev); //read complete event in memory } ntotin += hfile->GetBytesRead(); delete event; delete hfile; return nb; } //_______________________________________________________________ void stressIOPlugins3() { // based on stress8() const char *title = "Trees split and compression modes"; Bprint(3,title); Int_t nbr0 = test3read("Event_8a.root",title); Event::Reset(); Int_t nbr1 = test3read("Event_8b.root",title); Event::Reset(); Bool_t OK = kTRUE; if (nbr0 == 0 || nbr0 != nbr1) OK = kFALSE; if (OK) printf("OK\n"); else { printf("FAILED\n"); printf("%-8s nbr0=%d, nbr1=%d\n"," ",nbr0,nbr1); } } void cleanup() { TString psfname = TString::Format("stressIOPlugins-%d.ps", gSystem->GetPid()); gSystem->Unlink(psfname); }