https://github.com/root-project/root
Tip revision: 8483108b510b110a664c89af1e452e5547bdaa38 authored by Fons Rademakers on 31 October 2013, 15:46:31 UTC
make version v5-34-11.
make version v5-34-11.
Tip revision: 8483108
stressProof.cxx
// ************************************************************************* //
// * * //
// * s t r e s s P r o o f * //
// * * //
// * This file contains a set of test of PROOF related functionality. * //
// * The tests can be run as a standalone program or with the interpreter. * //
// * To run as a standalone program: * //
// * * //
// * $ cd $ROOTSYS/test * //
// * $ make stressProof * //
// * * //
// * Run stressProof with '-h' to get the list of supported options * //
// * $ ./stressProof -h * //
// * * //
// * To run interactively: * //
// * $ root * //
// * root[] .include $ROOTSYS/tutorials * //
// * root[] .L stressProof.cxx+ * //
// * root[] stressProof(master, tests, wrks, verbose, logfile, dyn, \ * //
// * dyn, skipds, h1src, eventsrc, dryrun) * //
// * * //
// * The arguments have the same meaning as above except for * //
// * verbose [Int_t] increasing verbosity (0 == minimal) * //
// * dyn [Bool_t] if kTRUE run in dynamic startup mode * //
// * skipds [Bool_t] if kTRUE the dataset related tests are skipped * //
// * * //
// * A certain number of swithces can also be controlled via environment * //
// * variables: check './stressProof -h' * //
// * * //
// * The stressProof function returns 0 on success, 1 on failure. * //
// * * //
// * The successful output looks like this: * //
// * * //
// * ****************************************************************** * //
// * * Starting P R O O F - S T R E S S suite * * //
// * ****************************************************************** * //
// * * Log file: /tmp/ProofStress_XrcwBe * //
// * ****************************************************************** * //
// * Test 1 : Open a session ................................... OK * * //
// * Test 2 : Get session logs ................................. OK * * //
// * Test 3 : Simple random number generation .................. OK * * //
// * Test 4 : Dataset handling with H1 files ................... OK * * //
// * Test 5 : H1: chain processing ............................. OK * * //
// * Test 6 : H1: file collection processing ................... OK * * //
// * Test 7 : H1: file collection, TPacketizer ................. OK * * //
// * Test 8 : H1: by-name processing ........................... OK * * //
// * Test 9 : H1: multi dataset processing ..................... OK * * //
// * Test 10 : H1: multi dataset and entry list ................. OK * * //
// * Test 11 : Package management with 'event' .................. OK * * //
// * Test 12 : Package argument passing ......................... OK * * //
// * Test 13 : Simple 'event' generation ........................ OK * * //
// * Test 14 : Input data propagation ........................... OK * * //
// * Test 15 : H1, Simple: async mode :.......................... OK * * //
// * Test 16 : Admin functionality .............................. OK * * //
// * Test 17 : Dynamic sub-mergers functionality ................ OK * * //
// * Test 18 : Event range processing ........................... OK * * //
// * Test 19 : Event range, TPacketizer ......................... OK * * //
// * Test 20 : File-resident output: merge ...................... OK * * //
// * Test 21 : File-resident output: merge w/ submergers ........ OK * * //
// * Test 22 : File-resident output: create dataset ............. OK * * //
// * Test 23 : File-resident output: multi trees ................ OK * * //
// * Test 24 : TTree friends (and TPacketizerFile) .............. OK * * //
// * Test 25 : TTree friends, same file ......................... OK * * //
// * Test 26 : Handling output via file ......................... OK * * //
// * Test 27 : Simple: selector by object ....................... OK * * //
// * Test 28 : H1 dataset: selector by object ................... OK * * //
// * * All registered tests have been passed :-) * * //
// * ****************************************************************** * //
// * * //
// * The application redirects the processing logs to a log file which is * //
// * normally deleted at the end of a successful run; if the test fails * //
// * the caller is asked if she/he wants to keep the log file; if the * //
// * specifies a log file path of her/his choice, the log file is never * //
// * deleted. * //
// * * //
// * SKIPPED means that the test cannot be run. * //
// * * //
// * New tests can be easily added by providing a function performing the * //
// * test and a name for the test; see examples below. * //
// * * //
// * It is also possible to trigger the automatic PROOF valgrind setup by * //
// * means of the env GETPROOF_VALGRIND. * //
// * E.g. to run the master in valgrind do * //
// * * //
// * $ export GETPROOF_VALGRIND="valgrind=master" * //
// * or * //
// * $ export GETPROOF_VALGRIND="valgrind=workers" * //
// * * //
// * before running stressProof. The syntax is the same as for standard * //
// * PROOF valgrind runs. See * //
// * http://root.cern.ch/drupal/content/running-proof-query-valgrind * //
// * * //
// ************************************************************************* //
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <io.h>
#endif
#include "Getline.h"
#include "TApplication.h"
#include "TChain.h"
#include "TDataMember.h"
#include "TDSet.h"
#include "TFile.h"
#include "TFileCollection.h"
#include "TFileInfo.h"
#include "TH1F.h"
#include "TH2F.h"
#include "THashList.h"
#include "TList.h"
#include "TMacro.h"
#include "TMap.h"
#include "TMath.h"
#include "TMethodCall.h"
#include "TNamed.h"
#include "TNtuple.h"
#include "TParameter.h"
#include "TProof.h"
#include "TProofLog.h"
#include "TProofMgr.h"
#include "TProofOutputFile.h"
#include "TQueryResult.h"
#include "TStopwatch.h"
#include "TString.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TSelector.h"
#include "proof/getProof.C"
#define PT_NUMTEST 28
static const char *urldef = "proof://localhost:40000";
static TString gtutdir;
static TString gsandbox;
static Int_t gverbose = 1;
static TString gverbproof("kAll");
static TString glogfile;
static Int_t gpoints = 0;
static Bool_t guseprogress = kTRUE;
static Int_t totpoints = 53;
static RedirectHandle_t gRH;
static RedirectHandle_t gRHAdmin;
static Double_t gH1Time = 0;
static Double_t gSimpleTime = 0;
static Double_t gEventTime = 0;
static Int_t gH1Cnt = 0;
static Int_t gSimpleCnt = 0;
static Int_t gEventCnt = 0;
static TStopwatch gTimer;
static Bool_t gTimedOut = kFALSE;
static Bool_t gDynamicStartup = kFALSE;
static Bool_t gLocalCluster = kTRUE;
static Bool_t gSkipDataSetTest = kTRUE;
static Bool_t gUseParallelUnzip = kFALSE;
static Bool_t gClearCache = kFALSE;
static TString gh1src("http://root.cern.ch/files/h1");
static Bool_t gh1ok = kTRUE;
static Bool_t gh1local = kFALSE;
static char gh1sep = '/';
static const char *gh1file[] = { "dstarmb.root", "dstarp1a.root", "dstarp1b.root", "dstarp2.root" };
static TString geventsrc("http://root.cern.ch/files/data");
static Bool_t geventok = kTRUE;
static Bool_t geventlocal = kFALSE;
static Int_t geventnf = 10;
static Long64_t gEventNum = 200000;
static Long64_t gEventFst = 65000;
static Long64_t gEventSiz = 100000;
static TStopwatch gStopwatch;
// The selectors
static TString gTutDir = "$ROOTSYS/tutorials"; // default path
static TList gSelectors;
static TString gH1Sel("/tree/h1analysis.C");
static TString gEventSel("/proof/ProofEvent.C");
static TString gEventProcSel("/proof/ProofEventProc.C");
static TString gSimpleSel("/proof/ProofSimple.C");
static TString gTestsSel("/proof/ProofTests.C");
static TString gNtupleSel("/proof/ProofNtuple.C");
static TString gFriendsSel("/proof/ProofFriends.C");
static TString gAuxSel("/proof/ProofAux.C");
// Special class
static TString gProcFileElem("/proof/ProcFileElements.C");
// Special files
static TString gEmptyInclude("/proof/EmptyInclude.h");
static TString gNtpRndm("/proof/ntprndm.root");
// Special packages
static TString gPackEvent("/proof/event.par");
static TString gPack1("/proof/packtest1.par");
static TString gPack2("/proof/packtest2.par");
int stressProof(const char *url = 0,
const char *tests = 0, Int_t nwrks = -1,
const char *verbose = "1", const char *logfile = 0,
Bool_t dyn = kFALSE, Bool_t skipds = kTRUE,
const char *h1src = 0, const char *eventsrc = 0,
Bool_t dryrun = kFALSE, Bool_t showcpu = kFALSE,
Bool_t clearcache = kFALSE, Bool_t useprogress = kTRUE,
const char *tutdir = 0, Bool_t cleanlog = kFALSE, Bool_t keeplog = kTRUE);
//_____________________________batch only_____________________
#ifndef __CINT__
int main(int argc,const char *argv[])
{
// Request for help?
if (argc > 1 && !strcmp(argv[1],"-h")) {
printf(" \n");
printf(" PROOF test suite\n");
printf(" \n");
printf(" Usage:\n");
printf(" \n");
printf(" $ ./stressProof [-h] [-n <wrks>] [-d [scope:]level] [-l logfile] [-dyn] [-ds]\n");
printf(" [-t tests] [-h1 h1src] [-event src] [-dryrun] [-g] [-cpu]\n");
printf(" [-clearcache] [-noprogress] [-tut tutdir] [master]\n");
printf(" \n");
printf(" Optional arguments:\n");
printf(" -h prints this menu\n");
printf(" master entry point of the cluster where to run the test\n");
printf(" in the form '[user@]host.domain[:port]'; default 'localhost:40000'\n");
printf(" or the env STRESSPROOF_URL\n");
printf(" -n wrks number of workers to be started when running on the local host;\n");
printf(" default is the nuber of local cores\n");
printf(" -d [scope:]level\n");
printf(" verbosity scope and level; default level is 1; scope refers to PROOF debug\n");
printf(" options (see TProofDebug.h) and is enabled only is level > 1 (default kAll).\n");
printf(" -l logfile file where to redirect the processing logs; must be writable;\n");
printf(" default is a temporary file deleted at the end of the test\n");
printf(" in case of success. Some format specifiers can be used in the file name:\n");
printf(" - %%p is replaced by the current process ID; \n");
printf(" - %%tmp is replaced by the temporary directory; \n");
printf(" - %%d is replaced by date and time at test startup in the form YYYYMMDD-HHMM, \n");
printf(" e.g. 20120904-1138. \n");
printf(" The log file path can be also passed via the env STRESSPROOF_LOGFILE.\n");
printf(" In case of failure, the log files of the nodes (master and workers) are saved into\n");
printf(" a file called <logfile>.nodes .\n");
printf(" -c,-cleanlog Delete the logfile specified via '-l' in case of a successful run; by default\n");
printf(" the file specified by '-l' is kept in all cases (default log files are deleted\n");
printf(" on success); adding this switch allows to keep a user-defined log file only\n");
printf(" in case of error.\n");
printf(" -k,-keeplog Keep all logfiles, including the ones fro the PROOF nodes (in one single file).\n");
printf(" The paths are printed on the screen.\n");
printf(" -dyn run the test in dynamicStartup mode\n");
printf(" -ds force the dataset test if skipped by default\n");
printf(" -t tests run only tests in the comma-separated list and those from which they\n");
printf(" depend; ranges can be given with 'first-last' syntax, e.g. '3,6-9,23'\n");
printf(" to run tests 3, 6, 7, 8, 9 and 23. Can be also given via the env STRESSPROOF_TESTS.\n");
printf(" -h1 h1src specify a location for the H1 files; use h1src=\"download\" to download\n");
printf(" to a temporary location (or h1src=\"download=/path/for/local/h1\" to download\n");
printf(" to /path/for/local/h1; by default the files are read directly from the\n");
printf(" ROOT http server; however this may give failures if the connection is slow.\n");
printf(" If h1src ends with '.zip' the program assumes that the 4 files are concatenated\n");
printf(" in a single zip archive and are accessible with the standard archive syntax.\n");
printf(" Can be also passed via the env STRESSPROOF_H1SRC.\n");
printf(" -event src\n");
printf(" specify a location for the 'event' files; use src=\"download\" to download\n");
printf(" to a temporary location (or eventsrc=\"download=/path/for/local/event\" to download\n");
printf(" to /path/for/local/event; by default the files are read directly from the\n");
printf(" ROOT http server; however this may give failures if the connection is slow\n");
printf(" Can be also passed via the env STRESSPROOF_EVENT.\n");
printf(" -punzip use parallel unzipping for data-driven processing.\n");
printf(" -dryrun only show which tests would be run.\n");
printf(" -g enable graphics; default is to run in text mode.\n");
printf(" -cpu show CPU times used by each successful test; used for calibration.\n");
printf(" -clearcache clear memory cache associated with the files processed when local.\n");
printf(" -noprogress do not show progress (escaped chars may confuse some wrapper applications)\n");
printf(" -tut tutdir specify alternative location for the ROOT tutorials; allows to run multiple\n");
printf(" concurrent instances of stressProof, for tests, for example.\n");
printf(" Can be also passed via the env STRESSPROOF_TUTORIALDIR.\n");
printf(" \n");
gSystem->Exit(0);
}
// Parse options
const char *url = 0;
Int_t nWrks = -1;
const char *verbose = "1";
Bool_t enablegraphics = kFALSE;
Bool_t dryrun = kFALSE;
Bool_t showcpu = kFALSE;
Bool_t clearcache = kFALSE;
Bool_t useprogress = kTRUE;
Bool_t cleanlog = kFALSE;
Bool_t keeplog = kFALSE;
const char *logfile = 0;
const char *h1src = 0;
const char *eventsrc = 0;
const char *tests = 0;
const char *tutdir = 0;
Int_t i = 1;
while (i < argc) {
if (!strcmp(argv[i],"-h")) {
// Ignore if not first argument
i++;
} else if (!strcmp(argv[i],"-n")) {
if (i+1 == argc || argv[i+1][0] == '-') {
printf(" -n should be followed by the number of workers: ignoring \n");
i++;
} else {
nWrks = atoi(argv[i+1]);
i += 2;
}
} else if (!strcmp(argv[i],"-d")) {
if (i+1 == argc || argv[i+1][0] == '-') {
printf(" -d should be followed by the debug '[scope:]level': ignoring \n");
i++;
} else {
verbose = argv[i+1];
i += 2;
}
} else if (!strcmp(argv[i],"-l")) {
if (i+1 == argc || argv[i+1][0] == '-') {
printf(" -l should be followed by a path: ignoring \n");
i++;
} else {
logfile = argv[i+1];
i += 2;
}
} else if (!strncmp(argv[i],"-c",2) || !strncmp(argv[i],"-cleanlog",11)) {
cleanlog = kTRUE;
i++;
} else if (!strncmp(argv[i],"-k",2) || !strncmp(argv[i],"-keeplog",10)) {
keeplog = kTRUE;
i++;
} else if (!strncmp(argv[i],"-v",2)) {
// For backward compatibility
if (!strncmp(argv[i],"-vv",3)) verbose = "2";
if (!strncmp(argv[i],"-vvv",4)) verbose = "3";
i++;
} else if (!strncmp(argv[i],"-dyn",4)) {
gDynamicStartup = kTRUE;
i++;
} else if (!strncmp(argv[i],"-ds",3)) {
gSkipDataSetTest = kFALSE;
i++;
} else if (!strncmp(argv[i],"-punzip",7)) {
gUseParallelUnzip = kTRUE;
i++;
} else if (!strcmp(argv[i],"-t")) {
if (i+1 == argc || argv[i+1][0] == '-') {
printf(" -t should be followed by a string or a number: ignoring \n");
i++;
} else {
tests = argv[i+1];
i += 2;
}
} else if (!strcmp(argv[i],"-h1")) {
if (i+1 == argc || argv[i+1][0] == '-') {
printf(" -h1 should be followed by a path: ignoring \n");
i++;
} else {
h1src = argv[i+1];
i += 2;
}
} else if (!strcmp(argv[i],"-event")) {
if (i+1 == argc || argv[i+1][0] == '-') {
printf(" -event should be followed by a path: ignoring \n");
i++;
} else {
eventsrc = argv[i+1];
i += 2;
}
} else if (!strncmp(argv[i],"-g",2)) {
enablegraphics = kTRUE;
i++;
} else if (!strncmp(argv[i],"-dryrun",7)) {
dryrun = kTRUE;
i++;
} else if (!strncmp(argv[i],"-cpu",4)) {
showcpu = kTRUE;
i++;
} else if (!strncmp(argv[i],"-clearcache",11)) {
clearcache = kTRUE;
i++;
} else if (!strncmp(argv[i],"-noprogress",11)) {
useprogress = kFALSE;
i++;
} else if (!strcmp(argv[i],"-tut")) {
if (i+1 == argc || argv[i+1][0] == '-') {
printf(" -tut should be followed by a path: ignoring \n");
i++;
} else {
tutdir = argv[i+1];
i += 2;
}
} else {
url = argv[i];
i++;
}
}
// Enable graphics if required
if (enablegraphics) {
new TApplication("stressProof", 0, 0);
} else {
gROOT->SetBatch(kTRUE);
}
int rc = stressProof(url, tests, nWrks, verbose, logfile, gDynamicStartup, gSkipDataSetTest,
h1src, eventsrc, dryrun, showcpu, clearcache, useprogress, tutdir, cleanlog, keeplog);
gSystem->Exit(rc);
}
#endif
//_____________________________________________________________________________
Int_t PutPoint()
{
// Print one '.' and count it
printf(".");
return ++gpoints;
}
//______________________________________________________________________________
void PrintStressProgress(Long64_t total, Long64_t processed, Float_t, Long64_t)
{
// Print some progress information
gSystem->RedirectOutput(0, 0, &gRH);
char pc[2] = { '.', ':'};
static int lstpc = 1;
int ns = 0;
if (processed < total) {
ns += 6;
fprintf(stderr, "%c %2.0f %%", pc[(lstpc++)%2],
(total ? ((100.0*processed)/total) : 100.0));
}
while (ns--) fprintf(stderr, "\b");
gSystem->RedirectOutput(glogfile, "a", &gRH);
}
//______________________________________________________________________________
void PrintEmptyProgress(Long64_t, Long64_t, Float_t, Long64_t)
{
// Dummy PrintProgress
return;
}
// Guard class
class SwitchProgressGuard {
public:
SwitchProgressGuard(Bool_t force = kFALSE) {
if (guseprogress || force) {
gProof->SetPrintProgress(&PrintStressProgress);
} else {
gProof->SetPrintProgress(&PrintEmptyProgress);
}
}
~SwitchProgressGuard() { gProof->SetPrintProgress(0); }
};
//______________________________________________________________________________
void CleanupSelector(const char *selpath)
{
// Remove all non source files associated with seletor at path 'selpath'
if (!selpath) return;
TString dirpath(gSystem->DirName(selpath));
if (gSystem->AccessPathName(dirpath)) return;
TString selname(gSystem->BaseName(selpath));
selname.ReplaceAll(".C", "_C");
void *dirp = gSystem->OpenDirectory(dirpath);
if (!dirp) return;
TString fn;
const char *e = 0;
while ((e = gSystem->GetDirEntry(dirp))) {
if (!strncmp(e, selname.Data(), selname.Length())) {
// Cleanup this entry
fn.Form("%s/%s", dirpath.Data(), e);
gSystem->Unlink(fn);
}
}
}
//_____________________________________________________________________________
void AssertParallelUnzip()
{
// Set the parallel unzip option
if (gUseParallelUnzip) {
gProof->SetParameter("PROOF_UseParallelUnzip", (Int_t)1);
} else {
gProof->SetParameter("PROOF_UseParallelUnzip", (Int_t)0);
}
}
//______________________________________________________________________________
void ReleaseCache(const char *fn)
{
// Release the memory cache associated with file 'fn'.
#if defined(R__LINUX)
TString filename(fn);
Int_t fd;
fd = open(filename.Data(), O_RDONLY);
if (fd > -1) {
fdatasync(fd);
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
close(fd);
} else {
fprintf(stderr, "cannot open file '%s' for cache clean up; errno=%d \n",
filename.Data(), errno);
}
#else
fprintf(stderr, "ReleaseCache: dummy function: file '%s' untouched ...\n", fn);
#endif
// Done
return;
}
//
// Auxilliary classes for testing
//
class RunTimes {
public:
Double_t fCpu;
Double_t fReal;
RunTimes(Double_t c = -1., Double_t r = -1.) : fCpu(c), fReal(r) { }
RunTimes &operator=(const RunTimes &rt) { fCpu = rt.fCpu; fReal = rt.fReal; return *this; }
void Set(Double_t c = -1., Double_t r = -1.) { if (c > -1.) fCpu = c; if (r > -1.) fReal = r; }
void Print(const char *tag = "") { printf("%s real: %f s, cpu: %f s\n", tag, fReal, fCpu); }
};
RunTimes operator-(const RunTimes &rt1, const RunTimes &rt2) {
RunTimes rt(rt1.fCpu - rt2.fCpu, rt1.fReal - rt2.fReal);
return rt;
}
static RunTimes gProofTimesZero(0.,0.);
typedef Int_t (*ProofTestFun_t)(void *, RunTimes &);
class ProofTest : public TNamed {
private:
Int_t fSeq; // Sequential number for the test
ProofTestFun_t fFun; // Function to be executed for the test
void *fArgs; // Arguments to be passed to the function
TString fDeps; // Test dependencies, e.g. "1,3"
TString fSels; // Selectors used, e.g. "h1analysis,ProofSimple"
Int_t fDepFrom; // Index for looping over deps
Int_t fSelFrom; // Index for looping over selectors
Bool_t fEnabled; // kTRUE if this test is enabled
Double_t fCpuTime; // CPU time used by the test
Double_t fRealTime; // Real time used by the test
Double_t fRefReal; // Ref Real time used for PROOF marks
Double_t fProofMarks; // PROOF marks
Bool_t fUseForMarks; // Use in the calculation of the average PROOF marks
static Double_t gRefReal[PT_NUMTEST]; // Reference Cpu times
public:
ProofTest(const char *n, Int_t seq, ProofTestFun_t f, void *a = 0,
const char *d = "", const char *sel = "", Bool_t useForMarks = kFALSE)
: TNamed(n,""), fSeq(seq), fFun(f), fArgs(a),
fDeps(d), fSels(sel), fDepFrom(0), fSelFrom(0), fEnabled(kTRUE),
fCpuTime(-1.), fRealTime(-1.), fProofMarks(-1.), fUseForMarks(useForMarks)
{ fRefReal = gRefReal[fSeq-1]; }
virtual ~ProofTest() { }
void Disable() { fEnabled = kFALSE; }
void Enable() { fEnabled = kTRUE; }
Bool_t IsEnabled() const { return fEnabled; }
Int_t NextDep(Bool_t reset = kFALSE);
Int_t NextSel(TString &sel, Bool_t reset = kFALSE);
Int_t Num() const { return fSeq; }
Int_t Run(Bool_t dryrun = kFALSE, Bool_t showcpu = kFALSE);
Double_t ProofMarks() const { return fProofMarks; }
Bool_t UseForMarks() const { return fUseForMarks; }
};
// Reference time measured on a HP DL580 24 core (4 x Intel(R) Xeon(R) CPU X7460
// @ 2.132 GHz, 48GB RAM, 1 Gb/s NIC) with 4 workers.
Double_t ProofTest::gRefReal[PT_NUMTEST] = {
3.047808, // #1: Open a session
0.021979, // #2: Get session logs
4.779971, // #3: Simple random number generation
0.276155, // #4: Dataset handling with H1 files
5.355514, // #5: H1: chain processing
2.414207, // #6: H1: file collection processing
3.381990, // #7: H1: file collection, TPacketizer
3.227942, // #8: H1: by-name processing
3.944204, // #9: H1: multi dataset processing
9.146988, // #10: H1: multi dataset and entry list
2.703881, // #11: Package management with 'event'
3.814625, // #12: Package argument passing
9.028315, // #13: Simple 'event' generation
0.123514, // #14: Input data propagation
0.129757, // #15: H1, Simple: async mode
0.349625, // #16: Admin functionality
0.989456, // #17: Dynamic sub-mergers functionality
11.23798, // #18: Event range processing
6.087582, // #19: Event range, TPacketizer
2.489555, // #20: File-resident output: merge
0.180897, // #21: File-resident output: merge w/ submergers
1.417233, // #22: File-resident output: create dataset
0.000000, // #23: File-resident output: multi trees
7.452465, // #24: TTree friends (and TPacketizerFile)
0.259239, // #25: TTree friends, same file
6.868858, // #26: Simple generation: merge-via-file
6.362017, // #27: Simple random number generation by TSelector object
5.519631 // #28: H1: by-object processing
};
//
// Timer to stop asynchronous actions
//
class TTimeOutTimer : public TTimer {
public:
TTimeOutTimer(Long_t ms);
Bool_t Notify();
};
TTimeOutTimer::TTimeOutTimer(Long_t ms)
: TTimer(ms, kTRUE)
{
//constructor
gSystem->AddTimer(this);
}
Bool_t TTimeOutTimer::Notify()
{
//notifier
gTimedOut = kTRUE;
Remove(); // one shot only
return kTRUE;
}
//------------------------------------------------------------------------------
//_____________________________________________________________________________
Int_t ProofTest::NextDep(Bool_t reset)
{
// Return index of next dependency or -1 if none (or no more)
// If reset is kTRUE, reset the internal counter before acting.
if (reset) fDepFrom = 0;
TString tkn;
if (fDeps.Tokenize(tkn, fDepFrom, ",")) {
if (tkn.IsDigit()) return tkn.Atoi();
}
// Not found
return -1;
}
//_____________________________________________________________________________
Int_t ProofTest::NextSel(TString &sel, Bool_t reset)
{
// Return index of next dependency or -1 if none (or no more)
// If reset is kTRUE, reset the internal counter before acting.
if (reset) fSelFrom = 0;
if (fSels.Tokenize(sel, fSelFrom, ",")) {
if (!sel.IsNull()) return 0;
}
// Not found
return -1;
}
//_____________________________________________________________________________
Int_t ProofTest::Run(Bool_t dryrun, Bool_t showcpu)
{
// Generic stress steering function; returns 0 on success, -1 on error
gpoints = 0;
printf(" Test %2d : %s ", fSeq, GetName());
PutPoint();
Int_t rc = 0;
if (!dryrun) {
gSystem->RedirectOutput(glogfile, "a", &gRH);
RunTimes tt;
gStopwatch.Start();
rc = (*fFun)(fArgs, tt);
gStopwatch.Stop();
fCpuTime = tt.fCpu;
fRealTime = tt.fReal;
// Proof marks
if (fRefReal > 0)
fProofMarks = (fRealTime > 0) ? 1000 * fRefReal / fRealTime : -1;
gSystem->RedirectOutput(0, 0, &gRH);
if (rc == 0) {
Int_t np = totpoints - strlen(GetName()) - strlen(" OK *");
while (np--) { printf("."); }
if (showcpu) {
printf(" OK * (rt: %f s, cpu: %f s, marks: %.2f)\n",
fRealTime, fCpuTime, fProofMarks);
} else {
printf(" OK *\n");
}
} else if (rc == 1) {
Int_t np = totpoints - strlen(GetName()) - strlen(" SKIPPED *");
while (np--) { printf("."); }
printf(" SKIPPED *\n");
} else {
Int_t np = totpoints - strlen(GetName()) - strlen(" FAILED *");
while (np--) { printf("."); }
printf(" FAILED *\n");
gSystem->ShowOutput(&gRH);
}
} else {
if (fEnabled) {
Int_t np = totpoints - strlen(GetName()) - strlen(" ENABLED *");
while (np--) { printf("."); }
printf(" ENABLED *\n");
} else {
Int_t np = totpoints - strlen(GetName()) - strlen(" DISABLED *");
while (np--) { printf("."); }
printf(" DISABLED *\n");
}
}
// Done
return rc;
}
// Test functions
Int_t PT_Open(void *, RunTimes &);
Int_t PT_GetLogs(void *, RunTimes &);
Int_t PT_Simple(void *, RunTimes &);
Int_t PT_H1Http(void *, RunTimes &);
Int_t PT_H1FileCollection(void *, RunTimes &);
Int_t PT_H1DataSet(void *, RunTimes &);
Int_t PT_H1MultiDataSet(void *, RunTimes &);
Int_t PT_H1MultiDSetEntryList(void *, RunTimes &);
Int_t PT_DataSets(void *, RunTimes &);
Int_t PT_Packages(void *, RunTimes &);
Int_t PT_Event(void *, RunTimes &);
Int_t PT_InputData(void *, RunTimes &);
Int_t PT_H1SimpleAsync(void *arg, RunTimes &);
Int_t PT_AdminFunc(void *arg, RunTimes &);
Int_t PT_PackageArguments(void *, RunTimes &);
Int_t PT_EventRange(void *, RunTimes &);
Int_t PT_POFNtuple(void *, RunTimes &);
Int_t PT_POFDataset(void *, RunTimes &);
Int_t PT_Friends(void *, RunTimes &);
Int_t PT_SimpleByObj(void *, RunTimes &);
Int_t PT_H1ChainByObj(void *, RunTimes &);
Int_t PT_AssertTutorialDir(const char *tutdir);
Int_t PT_MultiTrees(void *, RunTimes &);
Int_t PT_OutputHandlingViaFile(void *, RunTimes &);
// Auxilliary functions
void PT_GetLastTimes(RunTimes &tt)
{
// Get in tt the Cpu and Real times used during the run
// The runtimes
gStopwatch.Stop();
tt.fCpu = gStopwatch.CpuTime();
tt.fReal = gStopwatch.RealTime();
}
void PT_GetLastProofTimes(RunTimes &tt)
{
// Get in tt the Cpu and Real times used by PROOF since last call
if (gProof->IsLite()) {
PT_GetLastTimes(tt);
return;
}
// Update the statistics
gProof->GetStatistics(kFALSE);
// The runtimes
RunTimes proofTimesCurrent(gProof->GetCpuTime(), gProof->GetRealTime());
tt = proofTimesCurrent - gProofTimesZero;
gProofTimesZero = proofTimesCurrent;
}
// Arguments structures
typedef struct ptopenargs { // Open
const char *url;
Int_t nwrks;
} PT_Open_Args_t;
// Packetizer parameters
typedef struct ptpacketizer {
const char *fName;
Int_t fType;
} PT_Packetizer_t;
// Options
typedef struct ptoption {
Int_t fOne;
Int_t fTwo;
} PT_Option_t;
static PT_Packetizer_t gStd_Old = { "TPacketizer", 0 };
//_____________________________________________________________________________
int stressProof(const char *url, const char *tests, Int_t nwrks,
const char *verbose, const char *logfile, Bool_t dyn, Bool_t skipds,
const char *h1src, const char *eventsrc,
Bool_t dryrun, Bool_t showcpu, Bool_t clearcache, Bool_t useprogress,
const char *tutdir, Bool_t cleanlog, Bool_t keeplog)
{
printf("******************************************************************\n");
printf("* Starting P R O O F - S T R E S S suite *\n");
printf("******************************************************************\n");
// Use defaults or environment settings where required
if (!url) {
url = getenv("STRESSPROOF_URL");
if (!url) url = urldef;
}
// Set dynamic mode
gDynamicStartup = (!strcmp(url,"lite://")) ? kFALSE : dyn;
// Set verbosity
TString vv(verbose);
Ssiz_t icol = kNPOS;
if ((icol = vv.Index(":")) != kNPOS) {
TString sv = vv(icol+1, vv.Length() - icol -1);
gverbose = sv.Atoi();
vv.Remove(icol);
gverbproof = vv;
} else {
gverbose = vv.Atoi();
}
// No progress bar if not tty or explicitly not requested (i.e. for ctest)
guseprogress = useprogress;
if (isatty(0) == 0 || isatty(1) == 0) guseprogress = kFALSE;
if (!guseprogress) {
if (!useprogress) {
printf("* Progress not shown (explicit request) *\n");
} else {
printf("* Progress not shown (not tty) *\n");
}
printf("******************************************************************\n");
}
// Notify/warn about the dynamic startup option, if any
TUrl uu(url), udef(urldef);
Bool_t extcluster = ((strcmp(uu.GetHost(), udef.GetHost()) ||
(uu.GetPort() != udef.GetPort())) && strcmp(url,"lite://"))? kTRUE : kFALSE;
if (gDynamicStartup && gverbose > 0) {
// Check url
if (extcluster) {
printf("* WARNING: request to run a test with per-job scheduling on *\n");
printf("* an external cluster: %s .\n", url);
printf("* Make sure the dynamic option is set. *\n");
printf("* *\n");
gDynamicStartup = kFALSE;
} else {
printf("* Runnning in dynamic mode (per-job scheduling) *\n");
}
printf("* Tests #15, #22, #23, #26 skipped in dynamic mode **\n");
printf("******************************************************************\n");
}
if (dryrun) {
printf("* Dry-run: only showing what would be done *\n");
printf("******************************************************************\n");
}
// Cluster locality
gLocalCluster = (!extcluster || !strcmp(url, "lite://")) ? kFALSE : kTRUE;
// Dataset option
if (!skipds) {
gSkipDataSetTest = kFALSE;
} else {
gSkipDataSetTest = gLocalCluster;
}
// Clear cache
gClearCache = clearcache;
// Log file path
Bool_t usedeflog = kTRUE;
FILE *flog = 0;
if (!logfile) logfile = getenv("STRESSPROOF_LOGFILE");
if (logfile && strlen(logfile) > 0 && !dryrun) {
usedeflog = kFALSE;
glogfile = logfile;
if (glogfile.Contains("%tmp"))
glogfile.ReplaceAll("%tmp", gSystem->TempDirectory());
if (glogfile.Contains("%p")) {
TString apid = TString::Format("%d", gSystem->GetPid());
glogfile.ReplaceAll("%p", apid);
}
if (glogfile.Contains("%d")) {
TString d(TDatime().AsSQLString());
d.Remove(d.Last(':'));
d.ReplaceAll("-", "");
d.ReplaceAll(":", "");
d.ReplaceAll(" ", "-");
glogfile.ReplaceAll("%d", d);
}
if (!gSystem->AccessPathName(glogfile, kFileExists)) {
if (gSystem->AccessPathName(glogfile, kWritePermission)) {
printf(" >>> Cannot write to log file %s - ignore file request\n", logfile);
usedeflog = kTRUE;
}
} else {
// Create the file
if (!(flog = fopen(logfile, "w"))) {
printf(" >>> Cannot create log file %s - ignore file request\n", logfile);
usedeflog = kTRUE;
}
}
}
if (usedeflog && !dryrun) {
glogfile = "ProofStress_";
if (!(flog = gSystem->TempFileName(glogfile, gSystem->TempDirectory()))) {
printf(" >>> Cannot create a temporary log file on %s - exit\n", gSystem->TempDirectory());
return 1;
}
fclose(flog);
}
if (gverbose > 0) {
printf("* Log file: %s\n", glogfile.Data());
if (cleanlog)
printf("* (NB: file will be removed if test is successful) *\n");
printf("******************************************************************\n");
}
if (gSkipDataSetTest && gverbose > 0) {
printf("* Test for dataset handling (#4, #8-10) skipped **\n");
printf("******************************************************************\n");
}
if (gUseParallelUnzip && gverbose > 0) {
printf("* Using parallel unzip where relevant **\n");
printf("******************************************************************\n");
}
if (!strcmp(url,"lite://") && gverbose > 0) {
printf("* PROOF-Lite session (tests #15 and #16 skipped) **\n");
printf("******************************************************************\n");
}
if (!h1src) h1src = getenv("STRESSPROOF_H1SRC");
if (h1src && strlen(h1src)) {
if (!strcmp(h1src, "download") && extcluster) {
if (gverbose > 0) {
printf("* External clusters: ignoring download request of H1 files\n");
printf("******************************************************************\n");
}
} else if (!gh1src.BeginsWith(h1src)) {
if (gverbose > 0) {
printf("* Taking 'h1' files from: %s\n", h1src);
printf("******************************************************************\n");
}
gh1src = h1src;
gh1ok = kFALSE;
}
}
if (!eventsrc) eventsrc = getenv("STRESSPROOF_EVENT");
if (eventsrc && strlen(eventsrc)) {
if (!strcmp(eventsrc, "download") && extcluster) {
if (gverbose > 0) {
printf("* External clusters: ignoring download request of 'event' files\n");
printf("******************************************************************\n");
}
} else if (!geventsrc.BeginsWith(eventsrc)) {
if (gverbose > 0) {
printf("* Taking 'event' files from: %s\n", eventsrc);
printf("******************************************************************\n");
}
geventsrc = eventsrc;
geventok = kFALSE;
}
}
if (!tutdir) tutdir = getenv("STRESSPROOF_TUTORIALDIR");
if (tutdir && strlen(tutdir)) {
if (!(gTutDir == tutdir)) {
if (gverbose > 0) {
printf("* Taking tutorial files from: %s\n", tutdir);
printf("******************************************************************\n");
}
gTutDir = tutdir;
}
}
if (clearcache && gverbose > 0) {
printf("* Clearing cache associated to files, if possible ... **\n");
printf("******************************************************************\n");
}
if (keeplog && gverbose > 0) {
printf("* Keeping logfiles (paths specified at the end) **\n");
printf("******************************************************************\n");
}
//
// Reset dataset settings
gEnv->SetValue("Proof.DataSetManager","");
//
// Register tests
//
TList *testList = new TList;
// Simple open
PT_Open_Args_t PToa = { url, nwrks };
testList->Add(new ProofTest("Open a session", 1, &PT_Open, (void *)&PToa));
// Get logs
testList->Add(new ProofTest("Get session logs", 2, &PT_GetLogs, (void *)&PToa, "1"));
// Simple histogram generation
testList->Add(new ProofTest("Simple random number generation", 3, &PT_Simple, 0, "1", "ProofSimple", kTRUE));
// Test of data set handling with the H1 http files
testList->Add(new ProofTest("Dataset handling with H1 files", 4, &PT_DataSets, 0, "1"));
// H1 analysis over HTTP (chain)
testList->Add(new ProofTest("H1: chain processing", 5, &PT_H1Http, 0, "1", "h1analysis", kTRUE));
// H1 analysis over HTTP (file collection)
testList->Add(new ProofTest("H1: file collection processing", 6, &PT_H1FileCollection, 0, "1", "h1analysis", kTRUE));
// H1 analysis over HTTP: classic packetizer
testList->Add(new ProofTest("H1: file collection, TPacketizer", 7,
&PT_H1FileCollection, (void *)&gStd_Old, "1", "h1analysis", kTRUE));
// H1 analysis over HTTP by dataset name
testList->Add(new ProofTest("H1: by-name processing", 8, &PT_H1DataSet, 0, "1,4", "h1analysis", kTRUE));
// H1 analysis over HTTP by dataset name split in two
testList->Add(new ProofTest("H1: multi dataset processing", 9, &PT_H1MultiDataSet, 0, "1,4", "h1analysis", kTRUE));
// H1 analysis over HTTP by dataset name
testList->Add(new ProofTest("H1: multi dataset and entry list", 10, &PT_H1MultiDSetEntryList, 0, "1,4", "h1analysis", kTRUE));
// Test package management with 'event'
testList->Add(new ProofTest("Package management with 'event'", 11, &PT_Packages, 0, "1"));
// Test package argument passing
testList->Add(new ProofTest("Package argument passing", 12, &PT_PackageArguments, 0, "1", "ProofTests"));
// Simple event analysis
testList->Add(new ProofTest("Simple 'event' generation", 13, &PT_Event, 0, "1,11", "ProofEvent", kTRUE));
// Test input data propagation (it only works in the static startup mode)
testList->Add(new ProofTest("Input data propagation", 14, &PT_InputData, 0, "1", "ProofTests"));
// Test asynchronous running
testList->Add(new ProofTest("H1, Simple: async mode", 15, &PT_H1SimpleAsync, 0, "1,3,5", "h1analysis,ProofSimple", kTRUE));
// Test admin functionality
testList->Add(new ProofTest("Admin functionality", 16, &PT_AdminFunc, 0, "1"));
// Test merging via submergers
PT_Option_t pfoptm = {1, 0};
testList->Add(new ProofTest("Dynamic sub-mergers functionality", 17,
&PT_Simple, (void *)&pfoptm, "1", "ProofSimple", kTRUE));
// Test range chain and dataset processing EventProc
testList->Add(new ProofTest("Event range processing", 18,
&PT_EventRange, 0, "1,11", "ProofEventProc,ProcFileElements", kTRUE));
// Test range chain and dataset processing EventProc with TPacketizer
testList->Add(new ProofTest("Event range, TPacketizer", 19,
&PT_EventRange, (void *)&gStd_Old, "1,11", "ProofEventProc,ProcFileElements", kTRUE));
// Test TProofOutputFile technology for ntuple creation
testList->Add(new ProofTest("File-resident output: merge", 20, &PT_POFNtuple, 0, "1", "ProofNtuple", kTRUE));
// Test TProofOutputFile technology for ntuple creation using submergers
testList->Add(new ProofTest("File-resident output: merge w/ submergers", 21,
&PT_POFNtuple, (void *)&pfoptm, "1", "ProofNtuple", kTRUE));
// Test TProofOutputFile technology for dataset creation (tests TProofDraw too)
testList->Add(new ProofTest("File-resident output: create dataset", 22, &PT_POFDataset, 0, "1", "ProofNtuple", kTRUE));
// Test selecting different TTrees in same files
testList->Add(new ProofTest("File-resident output: multi trees", 23, &PT_MultiTrees, 0, "1,22", "ProofNtuple", kTRUE));
// Test TPacketizerFile and TTree friends in separate files
testList->Add(new ProofTest("TTree friends (and TPacketizerFile)", 24, &PT_Friends, 0, "1", "ProofFriends,ProofAux", kTRUE));
// Test TPacketizerFile and TTree friends in same file
Bool_t sameFile = kTRUE;
testList->Add(new ProofTest("TTree friends, same file", 25,
&PT_Friends, (void *)&sameFile, "1", "ProofFriends,ProofAux", kTRUE));
// Test handling output via file
testList->Add(new ProofTest("Handling output via file", 26,
&PT_OutputHandlingViaFile, 0, "1", "ProofSimple", kTRUE));
// Simple histogram generation by TSelector object
testList->Add(new ProofTest("Simple: selector by object", 27, &PT_SimpleByObj, 0, "1", "ProofSimple", kTRUE));
// H1 analysis over HTTP by TSeletor object
testList->Add(new ProofTest("H1 chain: selector by object", 28, &PT_H1ChainByObj, 0, "1", "h1analysis", kTRUE));
// The selectors
if (PT_AssertTutorialDir(gTutDir) != 0) {
printf("* Some of the tutorial files are missing! Stop\n");
return 1;
}
gSelectors.Add(new TNamed("h1analysis", gH1Sel.Data()));
gSelectors.Add(new TNamed("ProofEvent", gEventSel.Data()));
gSelectors.Add(new TNamed("ProofEventProc", gEventProcSel.Data()));
gSelectors.Add(new TNamed("ProofSimple", gSimpleSel.Data()));
gSelectors.Add(new TNamed("ProofTests", gTestsSel.Data()));
gSelectors.Add(new TNamed("ProcFileElements", gProcFileElem.Data()));
gSelectors.Add(new TNamed("ProofNtuple", gNtupleSel.Data()));
gSelectors.Add(new TNamed("ProofFriends", gFriendsSel.Data()));
gSelectors.Add(new TNamed("ProofAux", gAuxSel.Data()));
if (gverbose > 0) {
if (!dryrun) {
printf("* Cleaning-up all non-source files associated to:\n");
} else {
printf("* Would clean-up all non-source files associated to:\n");
}
}
// Check what to run
ProofTest *t = 0, *treq = 0;
TIter nxt(testList);
Bool_t all = kTRUE;
if (!tests) tests = getenv("STRESSPROOF_TESTS");
if (tests && strlen(tests)) {
TString tts(tests), tsg, ts, ten;
Ssiz_t from = 0;
while (tts.Tokenize(tsg, from, ",")) {
if (tsg.CountChar('-') > 1) {
printf("* **\r");
printf("* Wrong syntax for test range specification: %s\n", tsg.Data());
continue;
}
Ssiz_t fromg = 0;
Int_t test = -1, last = -1;
while (tsg.Tokenize(ts, fromg, "-")) {
if (!ts.IsDigit()) {
printf("* **\r");
printf("* Test string is not a digit: %s\n", ts.Data());
continue;
}
if (test < 0) {
test = ts.Atoi();
} else {
last = ts.Atoi();
}
}
if (test <= 0) {
printf("* **\r");
printf("* Non-positive test number: %d\n", test);
continue;
}
const int tmx = PT_NUMTEST;
if (test > tmx) {
printf("* **\r");
printf("* Unknown test number: %d\n", test);
continue;
}
if (last > tmx) {
printf("* **\r");
printf("* Upper test range too large: %d - rescaling\n", last);
last = tmx;
} else if (last <= 0) {
last = test;
}
// For final notification
if (ten != "") ten += ",";
ten += tsg;
// Ok, now we can enable
if (all) {
all = kFALSE;
// Disable first all the tests
while ((t = (ProofTest *)nxt())) { t->Disable(); }
}
// Process one by one all enabled tests
TString cleaned;
for (Int_t xt = test; xt <= last; xt++) {
// Locate the ProofTest instance
nxt.Reset();
while ((t = (ProofTest *)nxt())) {
if (t->Num() == xt) treq = t;
}
if (!treq) {
printf("* **\r");
printf("* Test %2d not found among the registered tests - exiting\n", xt);
printf("******************************************************************\n");
return 1;
}
// Enable the required tests
Int_t tn = -1;
while ((tn = treq->NextDep()) > 0) {
nxt.Reset();
while ((t = (ProofTest *)nxt())) {
if (t->Num() == tn) {
t->Enable();
break;
}
}
}
// Reset associated selectors
TString sel, tit;
while ((treq->NextSel(sel)) == 0) {
TNamed *nm = (TNamed *) gSelectors.FindObject(sel.Data());
if (nm && cleaned.Index(nm->GetTitle()) == kNPOS) {
if (!dryrun) CleanupSelector(nm->GetTitle());
if (gverbose > 0) {
tit = nm->GetName(); tit.Resize(18);
printf("* %s in %s\n", tit.Data(), gSystem->DirName(nm->GetTitle()));
}
cleaned += TString::Format(":%s:", nm->GetTitle());
}
}
// Enable the required test
treq->Enable();
}
}
if (!all && !dryrun) {
// Notify the enabled tests
printf("* **\r");
printf("* Running only test(s) %s (and related)\n", ten.Data());
printf("******************************************************************\n");
}
}
if (all) {
// Clean all the selectors
TString tit;
TIter nxs(&gSelectors);
TNamed *nm = 0;
while ((nm = (TNamed *)nxs())) {
if (!dryrun) CleanupSelector(nm->GetTitle());
if (gverbose > 0) {
tit = nm->GetName(); tit.Resize(18);
printf("* %s in %s\n", tit.Data(), gSystem->DirName(nm->GetTitle()));
}
}
}
if (gverbose > 0)
printf("******************************************************************\n");
// If a dry-run show what we would do and exit
if (dryrun) {
nxt.Reset();
while ((t = (ProofTest *)nxt())) { t->Run(kTRUE); }
printf("******************************************************************\n");
return 0;
}
// Add the ACLiC option to the selector strings
gH1Sel += "+";
gEventSel += "+";
gEventProcSel += "+";
gSimpleSel += "+";
gTestsSel += "+";
gProcFileElem += "+";
gNtupleSel += "+";
gFriendsSel += "+";
gAuxSel += "+";
//
// Run the tests
//
Bool_t failed = kFALSE;
nxt.Reset();
while ((t = (ProofTest *)nxt()))
if (t->IsEnabled()) {
if (t->Run(kFALSE, showcpu) < 0) {
failed = kTRUE;
break;
}
}
// Done
Bool_t kept = ((usedeflog || cleanlog) && !keeplog) ? kFALSE : kTRUE;
if (failed) {
kept = kTRUE;
if (usedeflog && !gROOT->IsBatch() && !keeplog) {
const char *answer = Getline(" Some tests failed: would you like to keep the log file (N,Y)? [Y] ");
if (answer && (answer[0] == 'N' || answer[0] == 'n')) {
// Remove log file
gSystem->Unlink(glogfile);
kept = kFALSE;
}
}
} else {
printf("* All registered tests have been passed :-) *\n");
}
if (kept) {
TString logfiles(glogfile);
// Save also the logs from the workers
TProofMgr *mgr = gProof ? gProof->GetManager() : 0;
if (mgr) {
gSystem->RedirectOutput(glogfile, "a", &gRH);
TProofLog *pl = mgr->GetSessionLogs();
if (pl) {
logfiles += ".nodes";
pl->Retrieve("*", TProofLog::kAll, logfiles);
gSystem->RedirectOutput(0, 0, &gRH);
SafeDelete(pl);
} else {
gSystem->RedirectOutput(0, 0, &gRH);
printf("+++ Warning: could not get the session logs\n");
}
} else {
printf("+++ Warning: could not attach to manager to get the session logs\n");
}
printf("******************************************************************\n");
printf(" Main log file kept at %s (Proof logs in %s)\n", glogfile.Data(), logfiles.Data());
} else {
// Remove log file if not passed by the user
gSystem->Unlink(glogfile);
}
printf("******************************************************************\n");
if (gProof) {
// Get average of single PROOF marks
int navg = 0;
double avgmarks = -1.;
nxt.Reset();
if (gverbose > 1) printf(" PROOFMARKS for single tests (-1 if unmeasured): \n");
while ((t = (ProofTest *)nxt()))
if (t->IsEnabled()) {
if (gverbose > 1) printf(" %d:\t %.2f \n", t->Num(), t->ProofMarks());
if (t->UseForMarks() && t->ProofMarks() > 0) {
navg++;
avgmarks += t->ProofMarks();
}
}
if (navg > 0) avgmarks /= navg;
gProof->GetStatistics((gverbose > 0));
// Reference time measured on a HP DL580 24 core (4 x Intel(R) Xeon(R) CPU X7460
// @ 2.132 GHz, 48GB RAM, 1 Gb/s NIC) with 4 workers.
const double reftime = 70.169;
double glbmarks = (gProof->GetRealTime() > 0) ? 1000 * reftime / gProof->GetRealTime() : -1;
printf(" ROOTMARKS = %.2f (overall: %.2f) ROOT version: %s\t%s@%s\n",
avgmarks, glbmarks, gROOT->GetVersion(),
gROOT->GetGitBranch(), gROOT->GetGitCommit());
// Average from the single tests
printf("******************************************************************\n");
}
// If not PROOF-Lite, stop the daemon used for the test
if (gProof && !gProof->IsLite() && !extcluster && gROOT->IsBatch()) {
// Get the manager
TProofMgr *mgr = gProof->GetManager();
// Close the instance
gProof->Close("S");
delete gProof;
// Delete the manager
SafeDelete(mgr);
// The daemon runs on a port shifted by 1
if (killXrootdAt(uu.GetPort()+1, "xpdtut") != 0) {
printf("+++ Warning: test daemon probably still running!\n");
}
}
// Done
return (failed ? 1 : 0);
}
//_____________________________________________________________________________
Int_t PT_H1ReleaseCache(const char *h1src)
{
// Release memory cache associated with the H1 files at 'h1src', if it
// makes any sense, i.e. are local ...
if (!h1src || strlen(h1src) <= 0) {
printf("\n >>> Test failure: src dir undefined\n");
return -1;
}
// If non-local, nothing to do
if (!gh1local) return 0;
TString src;
if (gh1sep == '/') {
// Loop through the files
for (Int_t i = 0; i < 4; i++) {
src.Form("%s/%s", h1src, gh1file[i]);
ReleaseCache(src.Data());
}
} else {
// Release the zip file ...
ReleaseCache(h1src);
}
// Done
return 0;
}
//_____________________________________________________________________________
Int_t PT_H1AssertFiles(const char *h1src)
{
// Make sure that the needed H1 files are available at 'src'
// If 'src' is "download", the files are download under <tutdir>/h1
if (!h1src || strlen(h1src) <= 0) {
printf("\n >>> Test failure: src dir undefined\n");
return -1;
}
// Locality
TUrl u(h1src, kTRUE);
gh1local = (!strcmp(u.GetProtocol(), "file")) ? kTRUE : kFALSE;
gh1sep = '/';
// Special cases
if (!strncmp(h1src,"download",8)) {
if (strcmp(h1src,"download")) {
gh1src = h1src;
gh1src.ReplaceAll("download=", "");
}
if (gh1src.IsNull() || gSystem->AccessPathName(gh1src, kWritePermission))
gh1src = TString::Format("%s/h1", gtutdir.Data());
if (gSystem->AccessPathName(gh1src)) {
if (gSystem->MakeDirectory(gh1src) != 0) {
printf("\n >>> Test failure: could not create dir %s\n", gh1src.Data());
return -1;
}
}
// Copy the files now
Int_t i = 0;
for (i = 0; i < 4; i++) {
TString src = TString::Format("http://root.cern.ch/files/h1/%s", gh1file[i]);
TString dst = TString::Format("%s/%s", gh1src.Data(), gh1file[i]);
if (!TFile::Cp(src, dst)) {
printf("\n >>> Test failure: problems retrieving %s\n", src.Data());
return -1;
}
gSystem->RedirectOutput(0, 0, &gRH);
printf("%d\b", i);
gSystem->RedirectOutput(glogfile, "a", &gRH);
}
gh1local = kTRUE;
// Done
gh1ok = kTRUE;
return 0;
} else if (TString(h1src).EndsWith(".zip")) {
// The files are in a zip archive ...
if (gSystem->AccessPathName(h1src)) {
printf("\n >>> Test failure: file %s does not exist\n", h1src);
return -1;
}
Int_t i = 0;
for (i = 0; i < 4; i++) {
TString src = TString::Format("%s#%s", h1src, gh1file[i]);
TFile *f = TFile::Open(src);
if (!f || (f && f->IsZombie())) {
printf("\n >>> Test failure: file %s not found in archive %s\n", src.Data(), h1src);
return -1;
}
if (guseprogress) {
gSystem->RedirectOutput(0, 0, &gRH);
printf("%d\b", i);
gSystem->RedirectOutput(glogfile, "a", &gRH);
}
}
gh1sep = '#';
} else {
// Make sure the files exist at 'src'
Int_t i = 0;
for (i = 0; i < 4; i++) {
TString src = TString::Format("%s/%s", h1src, gh1file[i]);
if (gSystem->AccessPathName(src)) {
printf("\n >>> Test failure: file %s does not exist\n", src.Data());
return -1;
}
if (guseprogress) {
gSystem->RedirectOutput(0, 0, &gRH);
printf("%d\b", i);
gSystem->RedirectOutput(glogfile, "a", &gRH);
}
}
}
gh1src = h1src;
// Done
gh1ok = kTRUE;
return 0;
}
//_____________________________________________________________________________
Int_t PT_EventReleaseCache(const char *eventsrc, Int_t nf = 10)
{
// Release memory cache associated with the event files at 'eventsrc', if it
// makes any sense, i.e. are local ...
if (!eventsrc || strlen(eventsrc) <= 0) {
printf("\n >>> Test failure: src dir undefined\n");
return -1;
}
if (nf > 50) {
printf("\n >>> Test failure: max 50 event files can be checked\n");
return -1;
}
// If non-local, nothing to do
if (!geventlocal) return 0;
TString src;
// Loop through the files
for (Int_t i = 0; i < nf; i++) {
src.Form("%s/event_%d.root", eventsrc, i+1);
ReleaseCache(src.Data());
}
// Done
return 0;
}
//_____________________________________________________________________________
Int_t PT_EventAssertFiles(const char *eventsrc, Int_t nf = 10)
{
// Make sure that the needed 'event' files are available at 'src'
// If 'src' is "download", the files are download under <tutdir>/event .
// By default 10 files are checked; maximum is 50 (idx 1->50 not 0->49).
if (!eventsrc || strlen(eventsrc) <= 0) {
printf("\n >>> Test failure: src dir undefined\n");
return -1;
}
if (nf > 50) {
printf("\n >>> Test failure: max 50 event files can be checked\n");
return -1;
}
// Locality
TUrl u(eventsrc, kTRUE);
geventlocal = (!strcmp(u.GetProtocol(), "file")) ? kTRUE : kFALSE;
// Special case
if (!strncmp(eventsrc,"download",8)) {
if (strcmp(eventsrc,"download")) {
geventsrc = eventsrc;
geventsrc.ReplaceAll("download=", "");
}
if (geventsrc.IsNull() || gSystem->AccessPathName(geventsrc, kWritePermission))
geventsrc = TString::Format("%s/event", gtutdir.Data());
if (gSystem->AccessPathName(geventsrc)) {
if (gSystem->MakeDirectory(geventsrc) != 0) {
printf("\n >>> Test failure: could not create dir %s\n", geventsrc.Data());
return -1;
}
}
// Copy the files now
Int_t i = 0;
for (i = 0; i < nf; i++) {
TString src = TString::Format("http://root.cern.ch/files/data/event_%d.root", i+1);
TString dst = TString::Format("%s/event_%d.root", geventsrc.Data(), i+1);
if (!TFile::Cp(src, dst)) {
printf("\n >>> Test failure: problems retrieving %s\n", src.Data());
return -1;
}
if (guseprogress) {
gSystem->RedirectOutput(0, 0, &gRH);
printf("%d\b", i);
gSystem->RedirectOutput(glogfile, "a", &gRH);
}
}
geventlocal = kTRUE;
// Done
geventok = kTRUE;
return 0;
}
// Make sure the files exist at 'src'
Int_t i = 0;
for (i = 0; i < nf; i++) {
TString src = TString::Format("%s/event_%d.root", eventsrc, i+1);
if (gSystem->AccessPathName(src)) {
printf("\n >>> Test failure: file %s does not exist\n", src.Data());
return -1;
}
if (guseprogress) {
gSystem->RedirectOutput(0, 0, &gRH);
printf("%d\b", i);
gSystem->RedirectOutput(glogfile, "a", &gRH);
}
}
geventsrc = eventsrc;
// Done
geventok = kTRUE;
return 0;
}
//_____________________________________________________________________________
Int_t PT_AssertTutorialDir(const char *tutdir)
{
// Make sure that the needed files are available under the specified
// tutorial directory, setting the relevant variables
if (!tutdir || strlen(tutdir) <= 0) {
printf("\n >>> Test failure: dir undefined\n");
return -1;
}
TString path;
// Selectors
gH1Sel.Insert(0, tutdir);
gSystem->ExpandPathName(gH1Sel);
if (gSystem->AccessPathName(gH1Sel)) return -1;
//
gEventSel.Insert(0, tutdir);
gSystem->ExpandPathName(gEventSel);
if (gSystem->AccessPathName(gEventSel)) return -1;
//
gEventProcSel.Insert(0, tutdir);
gSystem->ExpandPathName(gEventProcSel);
if (gSystem->AccessPathName(gEventProcSel)) return -1;
//
gSimpleSel.Insert(0, tutdir);
gSystem->ExpandPathName(gSimpleSel);
if (gSystem->AccessPathName(gSimpleSel)) return -1;
//
gTestsSel.Insert(0, tutdir);
gSystem->ExpandPathName(gTestsSel);
if (gSystem->AccessPathName(gTestsSel)) return -1;
//
gNtupleSel.Insert(0, tutdir);
gSystem->ExpandPathName(gNtupleSel);
if (gSystem->AccessPathName(gNtupleSel)) return -1;
//
gFriendsSel.Insert(0, tutdir);
gSystem->ExpandPathName(gFriendsSel);
if (gSystem->AccessPathName(gFriendsSel)) return -1;
//
gAuxSel.Insert(0, tutdir);
gSystem->ExpandPathName(gAuxSel);
if (gSystem->AccessPathName(gAuxSel)) return -1;
// Special class
gProcFileElem.Insert(0, tutdir);
gSystem->ExpandPathName(gProcFileElem);
if (gSystem->AccessPathName(gProcFileElem)) return -1;
// Special files
gEmptyInclude.Insert(0, tutdir);
gSystem->ExpandPathName(gEmptyInclude);
if (gSystem->AccessPathName(gEmptyInclude)) return -1;
//
gNtpRndm.Insert(0, tutdir);
gSystem->ExpandPathName(gNtpRndm);
if (gSystem->AccessPathName(gNtpRndm)) return -1;
// Special packages
gPackEvent.Insert(0, tutdir);
gSystem->ExpandPathName(gPackEvent);
if (gSystem->AccessPathName(gPackEvent)) return -1;
//
gPack1.Insert(0, tutdir);
gSystem->ExpandPathName(gPack1);
if (gSystem->AccessPathName(gPack1)) return -1;
//
gPack2.Insert(0, tutdir);
gSystem->ExpandPathName(gPack2);
if (gSystem->AccessPathName(gPack2)) return -1;
// Done
return 0;
}
//_____________________________________________________________________________
Int_t PT_CheckSimple(TQueryResult *qr, Long64_t nevt, Int_t nhist)
{
// Check the result of the ProofSimple analysis
if (!qr) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the number of processed entries is the one expected
PutPoint();
if (qr->GetEntries() != nevt) {
printf("\n >>> Test failure: wrong number of entries processed: %lld (expected %lld)\n",
qr->GetEntries(), nevt);
return -1;
}
// Make sure the output list is there
PutPoint();
TList *out = qr->GetOutputList();
if (!out) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Get the histos
PutPoint();
TH1F **hist = new TH1F*[nhist];
for (Int_t i=0; i < nhist; i++) {
hist[i] = dynamic_cast<TH1F *>(TProof::GetOutput(Form("h%d",i), out));
if (!hist[i]) {
printf("\n >>> Test failure: 'h%d' histo not found\n", i);
return -1;
}
}
// Check the mean values
PutPoint();
for (Int_t i=0; i < nhist; i++) {
Double_t ave = hist[i]->GetMean();
Double_t rms = hist[i]->GetRMS();
if (TMath::Abs(ave) > 5 * rms / TMath::Sqrt(hist[i]->GetEntries())) {
printf("\n >>> Test failure: 'h%d' histo: mean > 5 * RMS/Sqrt(N)\n", i);
return -1;
}
}
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_CheckSimpleNtuple(TQueryResult *qr, Long64_t nevt, const char *dsname)
{
// Check the ntuple created by the ProofSimple analysis
if (!qr) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the output list is there
PutPoint();
TList *out = qr->GetOutputList();
if (!out) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Get the file collection
PutPoint();
TFileCollection *fc = dynamic_cast<TFileCollection *>(out->FindObject(dsname));
if (!fc) {
printf("\n >>> Test failure: TFileCollection for dataset '%s' not"
" found in the output list\n", dsname);
return -1;
}
// Check the default tree name
const char *tname = "/ntuple";
PutPoint();
if (!fc->GetDefaultTreeName() || strcmp(fc->GetDefaultTreeName(), tname)) {
printf("\n >>> Test failure: default tree name does not match (%s != %s)\n",
fc->GetDefaultTreeName(), tname);
return -1;
}
// Check the number of entries
PutPoint();
if (fc->GetTotalEntries(tname) != nevt) {
printf("\n >>> Test failure: number of entries does not match (%lld != %lld)\n",
fc->GetTotalEntries(tname), nevt);
return -1;
}
// Check 'pz' histo
TH1F *hpx = new TH1F("PT_px", "PT_px", 20, -5., 5.);
PutPoint();
gProof->DrawSelect(dsname, "px >> PT_px");
if (TMath::Abs(hpx->GetMean()) > 5 * hpx->GetRMS() / TMath::Sqrt(hpx->GetEntries())) {
printf("\n >>> Test failure: 'hpx' histo: mean > 5 * RMS/Sqrt(N) (%f,%f)\n",
hpx->GetMean(), hpx->GetRMS());
return -1;
}
// Check 'pz' histo
TH1F *hpz = new TH1F("PT_pz", "PT_pz", 20, 0., 20.);
PutPoint();
gProof->DrawSelect(dsname, "pz >> PT_pz");
if (TMath::Abs(hpz->GetMean() - 2.) > 5 * 2. / TMath::Sqrt(hpz->GetEntries())) {
printf("\n >>> Test failure: 'hpz' histo: (mean - 2) > 5 * RMS/Sqrt(N) (%f,%f)\n",
hpz->GetMean(), hpz->GetRMS());
return -1;
}
// Check 'random' histo
TH1F *hpr = new TH1F("PT_rndm", "PT_rndm", 20, 0., 20.);
PutPoint();
gProof->DrawSelect(dsname, "random >> PT_rndm");
if (TMath::Abs(hpr->GetMean() - .5) > 5 * .5 / TMath::Sqrt(hpr->GetEntries())) {
printf("\n >>> Test failure: 'hpr' histo: (mean - .5) > 5 * RMS/Sqrt(N) (%f,%f)\n",
hpr->GetMean(), hpr->GetRMS());
return -1;
}
SafeDelete(hpx);
SafeDelete(hpz);
SafeDelete(hpr);
// Clear dsname
gProof->ClearData(TProof::kDataset |TProof::kForceClear, dsname);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_CheckH1(TQueryResult *qr, Int_t irun = 0)
{
// Check the result of the H1 analysis
if (!qr) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Make sure the number of processed entries is the one expected
PutPoint();
Long64_t runEntries[2] = {283813, 7525};
if (qr->GetEntries() != runEntries[irun]) {
printf("\n >>> Test failure: wrong number of entries processed: %lld (expected %lld)\n", qr->GetEntries(), runEntries[irun]);
return -1;
}
// Make sure the output list is there
PutPoint();
TList *out = qr->GetOutputList();
if (!out) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Check the 'hdmd' histo
PutPoint();
TH1F *hdmd = dynamic_cast<TH1F*>(out->FindObject("hdmd"));
if (!hdmd) {
printf("\n >>> Test failure: 'hdmd' histo not found\n");
return -1;
}
if ((Int_t)(hdmd->GetEntries()) != 7525) {
printf("\n >>> Test failure: 'hdmd' histo: wrong number"
" of entries (%d: expected 7525) \n",(Int_t)(hdmd->GetEntries()));
return -1;
}
if (TMath::Abs((hdmd->GetMean() - 0.15512023) / 0.15512023) > 0.001) {
printf("\n >>> Test failure: 'hdmd' histo: wrong mean"
" (%f: expected 0.15512023) \n", hdmd->GetMean());
return -1;
}
PutPoint();
TH2F *h2 = dynamic_cast<TH2F*>(out->FindObject("h2"));
if (!h2) {
printf("\n >>> Test failure: 'h2' histo not found\n");
return -1;
}
if ((Int_t)(h2->GetEntries()) != 7525) {
printf("\n >>> Test failure: 'h2' histo: wrong number"
" of entries (%d: expected 7525) \n",(Int_t)(h2->GetEntries()));
return -1;
}
if (TMath::Abs((h2->GetMean() - 0.15245688) / 0.15245688) > 0.001) {
printf("\n >>> Test failure: 'h2' histo: wrong mean"
" (%f: expected 0.15245688) \n", h2->GetMean());
return -1;
}
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_CheckEvent(TQueryResult *qr, const char *pack = "TPacketizerAdaptive")
{
// Check the result of the EventProc analysis
if (!qr) {
printf("\n >>> Test failure: %s: output list not found\n", pack);
return -1;
}
// Make sure the output list is there
PutPoint();
TList *out = qr->GetOutputList();
if (!out) {
printf("\n >>> Test failure: %s: output list not found\n", pack);
return -1;
}
// Check the 'hdmd' histo
PutPoint();
TNamed *nout = dynamic_cast<TNamed *>(out->FindObject("Range_Check"));
if (!nout) {
printf("\n >>> Test failure: %s: 'Range_Check' named object not found\n", pack);
return -1;
}
if (strcmp(nout->GetTitle(), "OK")) {
printf("\n >>> Test failure: %s: 'Range_Check': wrong result: %s \n", pack, nout->GetTitle());
return -1;
}
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_CheckNtuple(TQueryResult *qr, Long64_t nevt)
{
// Check the result of the ProofNtuple analysis
if (!qr) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the number of processed entries is the one expected
PutPoint();
if (qr->GetEntries() != nevt) {
printf("\n >>> Test failure: wrong number of entries processed: %lld (expected %lld)\n",
qr->GetEntries(), nevt);
return -1;
}
// Make sure the output list is there
PutPoint();
TList *out = qr->GetOutputList();
if (!out) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Get the ntuple form the file
TProofOutputFile *pof = dynamic_cast<TProofOutputFile*>(out->FindObject("SimpleNtuple.root"));
if (!pof) {
printf("\n >>> Test failure: TProofOutputFile not found in the output list\n");
return -1;
}
// Get the file full path
TString outputFile(pof->GetOutputFileName());
TString outputName(pof->GetName());
outputName += ".root";
// Read the ntuple from the file
TFile *f = TFile::Open(outputFile);
if (!f || (f && f->IsZombie())) {
printf("\n >>> Test failure: could not open file: %s", outputFile.Data());
return -1;
}
// Get the ntuple
PutPoint();
TNtuple *ntp = dynamic_cast<TNtuple *>(f->Get("ntuple"));
if (!ntp) {
printf("\n >>> Test failure: 'ntuple' not found\n");
return -1;
}
// Check the ntuple content by filling some histos
TH1F *h1s[3] = {0};
h1s[0] = new TH1F("h1_1", "3*px+2 with px**2+py**2>1", 50, -15., 15.);
h1s[1] = new TH1F("h1_2", "2*px+2 with pz>2", 50, -10., 10.);
h1s[2] = new TH1F("h1_3", "1.3*px+2 with (px^2+py^2>4) && py>0", 50, 0., 8.);
Float_t px, py, pz;
Float_t *pp = ntp->GetArgs();
Long64_t ent = 0;
while (ent < ntp->GetEntries()) {
ntp->GetEntry(ent);
px = pp[0];
py = pp[1];
pz = pp[2];
// Fill the histos
if (px*px+py*py > 1.) h1s[0]->Fill(3.*px + 2.);
if (pz > 2.) h1s[1]->Fill(2.*px + 2.);
if (px*px+py*py > 4. && py > 0.) h1s[2]->Fill(1.3*px + 2.);
// Go next
ent++;
}
Int_t rch1s = 0;
TString emsg;
// Check the histogram entries and mean values
Int_t hent[3] = { 620, 383, 72};
Double_t hmea[3] = { 1.992, 2.062 , 3.126};
for (Int_t i = 0; i < 3; i++) {
if ((Int_t)(h1s[i]->GetEntries()) != hent[i]) {
emsg.Form("'%s' histo: wrong number of entries (%d: expected %d)",
h1s[i]->GetName(), (Int_t)(h1s[i]->GetEntries()), hent[i]);
rch1s = -1;
break;
}
if (TMath::Abs((h1s[i]->GetMean() - hmea[i]) / hmea[i]) > 0.001) {
emsg.Form("'%s' histo: wrong mean (%f: expected %f)",
h1s[i]->GetName(), h1s[i]->GetMean(), hmea[i]);
rch1s = -1;
break;
}
}
// Cleanup
for (Int_t i = 0; i < 3; i++) delete h1s[i];
f->Close();
delete f;
// Check the result
if (rch1s != 0) {
printf("\n >>> Test failure: %s\n", emsg.Data());
return -1;
}
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_CheckDataset(TQueryResult *qr, Long64_t nevt)
{
// Check the result of the ProofNtuple analysis creating a dataset
// Uses and check also TProofDraw
if (!qr) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the number of processed entries is the one expected
PutPoint();
if (qr->GetEntries() != nevt) {
printf("\n >>> Test failure: wrong number of entries processed: %lld (expected %lld)\n",
qr->GetEntries(), nevt);
return -1;
}
const char *dsname = "testNtuple";
// Make sure that the dataset exists
PutPoint();
if (!gProof->ExistsDataSet(dsname)) {
gProof->ShowDataSets();
printf("\n >>> Test failure: dataset '%s' not found in the repository\n", dsname);
return -1;
}
// ... and that the default tree is 'ntuple'
gProof->SetDataSetTreeName(dsname, "ntuple");
// Create the histos
TH1F *h1s[3] = {0};
h1s[0] = new TH1F("h1s0", "3*px+2 with px**2+py**2>1", 50, -15., 15.);
h1s[1] = new TH1F("h1s1", "2*px+2 with pz>2", 50, -10., 10.);
h1s[2] = new TH1F("h1s2", "1.3*px+2 with (px^2+py^2>4) && py>0", 50, 0., 8.);
// Fill the histos using TProofDraw
PutPoint();
{ SwitchProgressGuard spg;
gProof->DrawSelect(dsname, "3*px+2 >> h1s0","px**2+py**2>1");
PutPoint();
gProof->DrawSelect(dsname, "2*px+2 >> h1s1","pz>2");
PutPoint();
gProof->DrawSelect(dsname, "1.3*px+2 >> h1s2","(px^2+py^2>4) && py>0");
}
Int_t rch1s = 0;
TString emsg;
// Check the histogram entries and mean values
Float_t hent[3] = { .607700, .364900, .065100};
Double_t hmea[3] = { 2.022, 2.046 , 3.043};
Double_t prec = 10. / TMath::Sqrt(nevt); // ~10 sigma ... conservative
for (Int_t i = 0; i < 3; i++) {
Double_t ent = h1s[i]->GetEntries();
if (TMath::Abs(ent - hent[i] * nevt) / ent > prec) {
emsg.Form("'%s' histo: wrong number"
" of entries (%lld: expected %lld)",
h1s[i]->GetName(), (Long64_t) ent, (Long64_t)(hent[i] *nevt));
rch1s = -1;
break;
}
Double_t mprec = 5 * h1s[i]->GetRMS() / TMath::Sqrt(h1s[i]->GetEntries()) ;
if (TMath::Abs((h1s[i]->GetMean() - hmea[i]) / hmea[i]) > mprec ) {
emsg.Form("'%s' histo: wrong mean (%f: expected %f - RMS: %f)",
h1s[i]->GetName(), h1s[i]->GetMean(), hmea[i], h1s[i]->GetRMS());
rch1s = -1;
break;
}
}
// Cleanup
for (Int_t i = 0; i < 3; i++) delete h1s[i];
// Check the result
if (rch1s != 0) {
printf("\n >>> Test failure: %s\n", emsg.Data());
return -1;
}
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_CheckFriends(TQueryResult *qr, Long64_t nevt)
{
// Check the result of the ProofFriends analysis
if (!qr) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the number of processed entries is the one expected
PutPoint();
if (qr->GetEntries() != nevt) {
printf("\n >>> Test failure: wrong number of entries processed: %lld (expected %lld)\n",
qr->GetEntries(), nevt);
return -1;
}
// Make sure the output list is there
PutPoint();
TList *out = qr->GetOutputList();
if (!out) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
TString emsg;
// Check the histogram entries and mean values
Int_t rchs = 0;
const char *hnam[4] = { "histo1", "histo2", "histo3", "histo4" };
const char *hcls[4] = { "TH2F", "TH1F", "TH1F", "TH2F" };
Float_t hent[4] = { 1., .227, .0260, .0260};
TObject *o = 0;
Double_t ent = -1;
Double_t prec = 1. / TMath::Sqrt(nevt);
for (Int_t i = 0; i < 4; i++) {
if (!(o = out->FindObject(hnam[i]))) {
emsg.Form("object '%s' not found", hnam[i]);
rchs = -1;
break;
}
if (strcmp(o->IsA()->GetName(), hcls[i])) {
emsg.Form("object '%s' is not '%s'", hnam[i], hcls[i]);
rchs = -1;
break;
}
if (!strcmp(hcls[i], "TH1F")) {
ent = ((TH1F *)o)->GetEntries();
} else {
ent = ((TH2F *)o)->GetEntries();
}
if (TMath::Abs(ent - hent[i] * nevt) / (Double_t)ent > prec) {
emsg.Form("'%s' histo: wrong number of entries (%lld: expected %lld) \n",
o->GetName(), (Long64_t) ent, (Long64_t) (hent[i] * nevt));
rchs = -1;
break;
}
}
if (rchs != 0) {
printf("\n >>> Test failure: %s\n", emsg.Data());
return -1;
}
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_Open(void *args, RunTimes &tt)
{
// Test session opening
// Checking arguments
PutPoint();
PT_Open_Args_t *PToa = (PT_Open_Args_t *)args;
if (!PToa) {
printf("\n >>> Test failure: invalid arguments: %p\n", args);
return -1;
}
// Temp dir for PROOF tutorials
PutPoint();
TString tmpdir(gSystem->TempDirectory()), us;
#if defined(R__MACOSX)
// Force '/tmp' under macosx, to avoid problems with lengths and symlinks
tmpdir = "/tmp";
#endif
UserGroup_t *ug = gSystem->GetUserInfo(gSystem->GetUid());
if (!tmpdir.EndsWith(us.Data())) {
if (ug) {
us.Form("/%s", ug->fUser.Data());
tmpdir += us;
delete ug;
} else {
printf("\n >>> Test failure: could not get user info");
return -1;
}
}
#if !defined(R__MACOSX)
gtutdir.Form("%s/.proof-tutorial", tmpdir.Data());
#else
gtutdir.Form("%s/.proof", tmpdir.Data());
#endif
if (gSystem->AccessPathName(gtutdir)) {
if (gSystem->mkdir(gtutdir, kTRUE) != 0) {
printf("\n >>> Test failure: could not assert/create the temporary directory"
" for the tutorial (%s)", gtutdir.Data());
return -1;
}
}
// String to initialize the dataset manager
TString dsetmgrstr;
dsetmgrstr.Form("file dir:%s/datasets opt:-Cq:As:Sb:", gtutdir.Data());
gEnv->SetValue("Proof.DataSetManager", dsetmgrstr.Data());
// String to initialize the package dir
TString packdir;
packdir.Form("%s/packages", gtutdir.Data());
gEnv->SetValue("Proof.PackageDir", packdir.Data());
// Get the PROOF Session
PutPoint();
TProof *p = getProof(PToa->url, PToa->nwrks, gtutdir.Data(), "force", gDynamicStartup, kTRUE);
if (!p || !(p->IsValid())) {
printf("\n >>> Test failure: could not start the session\n");
return -1;
}
// Re-check locality: if the logged user name is different from the local one, we may
// not have all the rights we need, so we go no-local
if (gLocalCluster) {
UserGroup_t *pw = gSystem->GetUserInfo();
if (pw) {
if (strcmp(pw->fUser, p->GetUser())) gLocalCluster = kFALSE;
delete pw;
}
}
// Check if it is in dynamic startup mode
Int_t dyn = 0;
p->GetRC("Proof.DynamicStartup", dyn);
if (dyn != 0) gDynamicStartup = kTRUE;
// Set debug level, if required
if (gverbose > 1) {
Int_t debugscope = getDebugEnum(gverbproof.Data());
p->SetLogLevel(gverbose, debugscope);
}
PutPoint();
if (PToa->nwrks > 0 && p->GetParallel() != PToa->nwrks) {
printf("\n >>> Test failure: number of workers different from requested\n");
return -1;
}
// Clear Cache
p->ClearCache();
// Get some useful info about the cluster (the sandbox dir ...)
gSystem->RedirectOutput(0, 0, &gRH);
TString testPrint(TString::Format("%s/testPrint.log", gtutdir.Data()));
gSystem->RedirectOutput(testPrint, "w", &gRHAdmin);
gProof->Print();
gSystem->RedirectOutput(0, 0, &gRHAdmin);
gSystem->RedirectOutput(glogfile, "a", &gRH);
TMacro macroPrint(testPrint);
TObjString *os = macroPrint.GetLineWith("Working directory:");
if (!os) {
printf("\n >>> Test failure: problem parsing output from Print()\n");
return -1;
}
Int_t from = strlen("Working directory:") + 1;
while (os->GetString().Tokenize(gsandbox, from, " ")) {
if (!gsandbox.IsNull()) break;
}
if (gsandbox.IsNull()) {
printf("\n >>> Test failure: no sandbox dir found\n");
return -1;
}
gsandbox = gSystem->DirName(gsandbox);
gsandbox = gSystem->DirName(gsandbox);
PutPoint();
// Fill times
PT_GetLastTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_GetLogs(void *args, RunTimes &tt)
{
// Test log retrieving
// Checking arguments
PutPoint();
PT_Open_Args_t *PToa = (PT_Open_Args_t *)args;
if (!PToa) {
printf("\n >>> Test failure: invalid arguments: %p\n", args);
return -1;
}
PutPoint();
TProofLog *pl = TProof::Mgr(PToa->url)->GetSessionLogs();
if (!pl) {
printf("\n >>> Test failure: could not get the logs from last session\n");
return -1;
}
PutPoint();
if (PToa->nwrks > 0 && pl->GetListOfLogs()->GetSize() != (PToa->nwrks + 1)) {
printf("\n >>> Test failure: number of logs different from workers of workers + 1\n");
return -1;
}
// Fill times
PT_GetLastTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_Simple(void *opts, RunTimes &tt)
{
// Test run for the ProofSimple analysis (see tutorials)
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
PT_Option_t *ptopt = (PT_Option_t *) opts;
// Setup submergers if required
if (ptopt && ptopt->fOne > 0) {
gProof->SetParameter("PROOF_UseMergers", 0);
}
// Setup save-to-file, if required
TString opt = (ptopt && ptopt->fTwo > 0) ? "stf" : "" ;
// Define the number of events and histos
Long64_t nevt = 1000000;
Int_t nhist = 16;
// The number of histograms is added as parameter in the input list
gProof->SetParameter("ProofSimple_NHist", (Long_t)nhist);
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(gSimpleSel.Data(), nevt, opt);
gTimer.Stop();
}
// Count
gSimpleCnt++;
gSimpleTime += gTimer.RealTime();
// Remove any setting related to submergers
gProof->DeleteParameters("PROOF_UseMergers");
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckSimple(gProof->GetQueryResult(), nevt, nhist);
}
//_____________________________________________________________________________
Int_t PT_OutputHandlingViaFile(void *opts, RunTimes &tt)
{
// Test output handling via file using ProofSimple (see tutorials)
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported in dynamic mode
if (gDynamicStartup) {
return 1;
}
PutPoint();
PT_Option_t *ptopt = (PT_Option_t *) opts;
// Setup submergers if required
if (ptopt && ptopt->fOne > 0) {
gProof->SetParameter("PROOF_UseMergers", 0);
}
// Setup save-to-file, if required
TString opt = (ptopt && ptopt->fTwo > 0) ? "stf" : "" ;
// Define the number of events and histos
Long64_t nevt = 1000000 * gProof->GetParallel();
Int_t nhist = 16;
// The number of histograms is added as parameter in the input list
gProof->SetParameter("ProofSimple_NHist", (Long_t)nhist);
// Merged file pptions to be tested
const char *testopt[4] = { "stf", "of=proofsimple.root", "of=proofsimple.root;stf",
"of=master:proofsimple.root" };
for (Int_t i = 0; i < 4; i++) {
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Save results to file 'proofsimple.root'
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(gSimpleSel.Data(), nevt, testopt[i]);
gTimer.Stop();
}
if (PT_CheckSimple(gProof->GetQueryResult(), nevt, nhist) != 0) {
printf("\n >>> Test failure: output handling via file: option '%s'\n", testopt[i]);
return -1;
}
// Count
gSimpleCnt++;
gSimpleTime += gTimer.RealTime();
// Remove file
gSystem->Unlink("proofsimple.root");
}
// Test dataset creationg with a ntuple
const char *dsname = "PT_ds_proofsimple";
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
if (gProof->ExistsDataSet(dsname)) gProof->RemoveDataSet(dsname);
// We want the ntuple
gProof->SetParameter("ProofSimple_Ntuple", "");
// Save results to file 'proofsimple.root'
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(gSimpleSel.Data(), nevt, TString::Format("ds=%s|V", dsname));
gTimer.Stop();
}
if (!gProof->ExistsDataSet(dsname)) {
printf("\n >>> Test failure: output handling via file: dataset '%s' not created\n", dsname);
return -1;
}
// Remove any setting related to submergers
gProof->DeleteParameters("PROOF_UseMergers");
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckSimpleNtuple(gProof->GetQueryResult(), nevt, dsname);
}
//_____________________________________________________________________________
Int_t PT_H1Http(void *, RunTimes &tt)
{
// Test run for the H1 analysis as a chain reading the data from HTTP
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Create the chain
PutPoint();
TChain *chain = new TChain("h42");
// Assert the files, if needed
if (!gh1ok) {
if (PT_H1AssertFiles(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not assert the H1 files\n");
return -1;
}
}
Int_t i = 0;
for (i = 0; i < 4; i++) {
chain->Add(TString::Format("%s%c%s", gh1src.Data(), gh1sep, gh1file[i]));
}
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
chain->SetProof();
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
chain->Process(gH1Sel.Data());
gTimer.Stop();
}
gProof->RemoveChain(chain);
// Count
gH1Cnt++;
gH1Time += gTimer.RealTime();
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckH1(gProof->GetQueryResult());
}
//_____________________________________________________________________________
Int_t PT_H1FileCollection(void *arg, RunTimes &tt)
{
// Test run for the H1 analysis as a file collection reading the data from HTTP
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Are we asked to change the packetizer strategy?
if (arg) {
PT_Packetizer_t *strategy = (PT_Packetizer_t *)arg;
if (strcmp(strategy->fName, "TPacketizerAdaptive")) {
gProof->SetParameter("PROOF_Packetizer", strategy->fName);
} else {
if (strategy->fType != 1)
gProof->SetParameter("PROOF_PacketizerStrategy", strategy->fType);
}
}
// Create the file collection
PutPoint();
TFileCollection *fc = new TFileCollection("h42");
// Assert the files, if needed
if (!gh1ok) {
if (PT_H1AssertFiles(gh1src.Data()) != 0) {
printf("\n >>> Test failure: could not assert the H1 files\n");
return -1;
}
}
Int_t i = 0;
for (i = 0; i < 4; i++) {
fc->Add(new TFileInfo(TString::Format("%s%c%s", gh1src.Data(), gh1sep, gh1file[i])));
}
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(fc, gH1Sel.Data());
gTimer.Stop();
}
// Restore settings
gProof->DeleteParameters("PROOF_Packetizer");
gProof->DeleteParameters("PROOF_PacketizerStrategy");
// Count
gH1Cnt++;
gH1Time += gTimer.RealTime();
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckH1(gProof->GetQueryResult());
}
//_____________________________________________________________________________
Int_t PT_H1DataSet(void *, RunTimes &tt)
{
// Test run for the H1 analysis as a named dataset reading the data from HTTP
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported for PROOF-Lite
if (gSkipDataSetTest) {
return 1;
}
PutPoint();
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Name for the target dataset
const char *dsname = "h1dset";
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process the dataset by name
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(dsname, gH1Sel.Data());
gTimer.Stop();
}
// Count
gH1Cnt++;
gH1Time += gTimer.RealTime();
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckH1(gProof->GetQueryResult());
}
//_____________________________________________________________________________
Int_t PT_H1MultiDataSet(void *, RunTimes &tt)
{
// Test run for the H1 analysis as a named dataset reading the data from HTTP
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported for PROOF-Lite
if (gSkipDataSetTest) {
return 1;
}
PutPoint();
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Name for the target dataset
const char *dsname = "h1dseta h1dsetb";
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process the dataset by name
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(dsname, gH1Sel.Data());
gTimer.Stop();
}
// Count
gH1Cnt++;
gH1Time += gTimer.RealTime();
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckH1(gProof->GetQueryResult());
}
//_____________________________________________________________________________
Int_t PT_H1MultiDSetEntryList(void *, RunTimes &tt)
{
// Test run using the H1 analysis for the multi-dataset functionality and
// entry-lists
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported for PROOF-Lite
if (gSkipDataSetTest) {
return 1;
}
PutPoint();
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Multiple dataset used to create the entry list
TString dsname("h1dseta|h1dsetb");
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Entry-list creation run
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(dsname, gH1Sel.Data(), "fillList=elist.root");
gTimer.Stop();
}
// Cleanup entry-list from the input list
TIter nxi(gProof->GetInputList());
TObject *o = 0;
while ((o = nxi())) {
if (!strncmp(o->GetName(), "elist", 6) || !strcmp(o->GetName(), "fillList")) {
gProof->GetInputList()->Remove(o);
delete o;
}
}
// Count
gH1Cnt++;
gH1Time += gTimer.RealTime();
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Run using the entrylist
dsname = "h1dseta<<elist.root h1dsetb?enl=elist.root";
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(dsname, gH1Sel.Data());
gTimer.Stop();
}
// Unlink the entry list file
gSystem->Unlink("elist.root");
// Cleanup entry-list from the input list
nxi.Reset();
while ((o = nxi())) {
if (!strncmp(o->GetName(), "elist", 6)) {
gProof->GetInputList()->Remove(o);
delete o;
}
}
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckH1(gProof->GetQueryResult(), 1);
}
//_____________________________________________________________________________
Int_t PT_DataSets(void *, RunTimes &tt)
{
// Test dataset registration, verification, usage, removal.
// Use H1 analysis files on HTTP as example
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported for PROOF-Lite
if (gSkipDataSetTest) {
return 1;
}
PutPoint();
// Cleanup the area
PutPoint();
TMap *dsm = gProof->GetDataSets();
if (!dsm) {
printf("\n >>> Test failure: could not retrieve map of datasets (even empty)!\n");
return -1;
}
if (dsm->GetSize() > 0) {
// Remove the datasets already registered
TIter nxd(dsm);
TObjString *os = 0;
while ((os = (TObjString *)nxd())) {
gProof->RemoveDataSet(os->GetName());
}
// Check the result
delete dsm;
dsm = gProof->GetDataSets();
if (!dsm || dsm->GetSize() > 0) {
printf("\n >>> Test failure: could not cleanup the dataset area! (%p)\n", dsm);
delete dsm;
return -1;
}
}
delete dsm;
// Create the file collection
PutPoint();
TFileCollection *fc = new TFileCollection();
TFileCollection *fca = new TFileCollection();
TFileCollection *fcb = new TFileCollection();
// Assert the files, if needed
if (!gh1ok) {
if (PT_H1AssertFiles(gh1src.Data()) != 0) {
printf("\n >>> Test failure: could not assert the H1 files\n");
return -1;
}
}
Int_t i = 0;
for (i = 0; i < 4; i++) {
fc->Add(new TFileInfo(TString::Format("%s%c%s", gh1src.Data(), gh1sep, gh1file[i])));
if (i < 2) {
fca->Add(new TFileInfo(TString::Format("%s%c%s", gh1src.Data(), gh1sep, gh1file[i])));
} else {
fcb->Add(new TFileInfo(TString::Format("%s%c%s", gh1src.Data(), gh1sep, gh1file[i])));
}
}
fc->Update();
fca->Update();
fcb->Update();
// Name for this dataset
const char *dsname = "h1dset";
const char *dsnamea = "h1dseta";
const char *dsnameb = "h1dsetb";
// Register the dataset
PutPoint();
gProof->RegisterDataSet(dsname, fc);
gProof->RegisterDataSet(dsnamea, fca);
gProof->RegisterDataSet(dsnameb, fcb);
// Check the result
dsm = gProof->GetDataSets();
if (!dsm || dsm->GetSize() != 3) {
printf("\n >>> Test failure: could not register '%s,%s,%s' (%p)\n",
dsname, dsnamea, dsnameb, dsm);
delete dsm;
return -1;
}
delete dsm;
// Test removal
PutPoint();
gProof->RemoveDataSet(dsname);
gProof->RemoveDataSet(dsnamea);
gProof->RemoveDataSet(dsnameb);
// Check the result
dsm = gProof->GetDataSets();
if (!dsm || dsm->GetSize() != 0) {
printf("\n >>> Test failure: could not cleanup '%s,%s,%s' (%p)\n",
dsname, dsnamea, dsnameb, dsm);
delete dsm;
return -1;
}
delete dsm;
// Re-register the dataset
PutPoint();
gProof->RegisterDataSet(dsname, fc);
gProof->RegisterDataSet(dsnamea, fca);
gProof->RegisterDataSet(dsnameb, fcb);
// Check the result
dsm = gProof->GetDataSets();
if (!dsm || dsm->GetSize() != 3) {
printf("\n >>> Test failure: could not re-register '%s,%s,%s' (%p)\n",
dsname, dsnamea, dsnameb, dsm);
delete dsm;
return -1;
}
delete dsm;
// Verify the dataset
PutPoint();
if (gProof->VerifyDataSet(dsname) != 0) {
printf("\n >>> Test failure: could not verify '%s'!\n", dsname);
return -1;
}
if (gProof->VerifyDataSet(dsnamea) != 0) {
printf("\n >>> Test failure: could not verify '%s'!\n", dsnamea);
return -1;
}
if (gProof->VerifyDataSet(dsnameb) != 0) {
printf("\n >>> Test failure: could not verify '%s'!\n", dsnameb);
return -1;
}
gProof->ShowDataSets();
// Remove the file collection
delete fc;
delete fca;
delete fcb;
// The runtimes
PT_GetLastProofTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_Packages(void *, RunTimes &tt)
{
// Test package clearing, uploading, enabling, removal.
// Use event.par as example.
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Cleanup the area
PutPoint();
TList *packs = gProof->GetListOfPackages();
if (!packs) {
printf("\n >>> Test failure: could not retrieve list of packages (even empty)!\n");
return -1;
}
if (packs->GetSize() > 0) {
// Remove the packages already available
gProof->ClearPackages();
// Check the result
packs = gProof->GetListOfPackages();
if (!packs || packs->GetSize() > 0) {
printf("\n >>> Test failure: could not cleanup the package area!\n");
return -1;
}
}
// Name and location for this package
const char *pack = "event";
// Upload the package
PutPoint();
gProof->UploadPackage(gPackEvent);
// Check the result
packs = gProof->GetListOfPackages();
if (!packs || packs->GetSize() != 1) {
printf("\n >>> Test failure: could not upload '%s'!\n", gPackEvent.Data());
return -1;
}
// Test cleanup
PutPoint();
gProof->ClearPackage(pack);
// Check the result
packs = gProof->GetListOfPackages();
if (!packs || packs->GetSize() != 0) {
printf("\n >>> Test failure: could not cleanup '%s'!\n", pack);
return -1;
}
// Re-upload the package
PutPoint();
gProof->UploadPackage(gPackEvent);
// Check the result
packs = gProof->GetListOfPackages();
if (!packs || packs->GetSize() != 1) {
printf("\n >>> Test failure: could not re-upload '%s'!\n", gPackEvent.Data());
return -1;
}
// Enable the package
PutPoint();
gProof->EnablePackage(pack);
// Check the result
packs = gProof->GetListOfEnabledPackages();
if (!packs || packs->GetSize() != 1) {
printf("\n >>> Test failure: could not enable '%s'!\n", pack);
return -1;
}
// Fill times
PT_GetLastTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_Event(void *, RunTimes &tt)
{
// Test run for the ProofEvent analysis (see tutorials)
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Define the number of events
Long64_t nevt = 100000;
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
{ SwitchProgressGuard spg;
gProof->Process(gEventSel.Data(), nevt);
}
// Make sure the query result is there
PutPoint();
TQueryResult *qr = 0;
if (!(qr = gProof->GetQueryResult())) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the number of processed entries is the one expected
PutPoint();
if (qr->GetEntries() != nevt) {
printf("\n >>> Test failure: wrong number of entries processed: %lld (expected %lld)\n",
qr->GetEntries(), nevt);
return -1;
}
// Make sure the output list is there
PutPoint();
if (!(gProof->GetOutputList())) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Check the 'histo'
PutPoint();
TH1F *histo = dynamic_cast<TH1F*>(gProof->GetOutputList()->FindObject("histo"));
if (!histo) {
printf("\n >>> Test failure: 'histo' not found\n");
return -1;
}
// Check the mean values
Double_t ave = histo->GetMean();
Double_t rms = histo->GetRMS();
if (TMath::Abs(ave - 50) > 10 * rms / TMath::Sqrt(histo->GetEntries())) {
printf("\n >>> Test failure: 'histo': mean > 5 * RMS/Sqrt(N)\n");
return -1;
}
// The runtimes
PT_GetLastProofTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_InputData(void *, RunTimes &tt)
{
// Test input data functionality
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
PutPoint();
// Create the test information to be send via input and retrieved
TH1F *h1 = new TH1F("h1data","Input data from file",100,-5.,5.);
h1->FillRandom("gaus", 1000);
TList *h1list = new TList;
h1list->SetName("h1list");
h1list->SetOwner(kTRUE);
h1list->Add(h1);
h1list->Add(new TParameter<Double_t>("h1avg", h1->GetMean()));
h1list->Add(new TParameter<Double_t>("h1rms", h1->GetRMS()));
TString datafile = glogfile;
datafile += ("_h1data.root");
TFile *f = TFile::Open(datafile, "RECREATE");
if (!f) {
printf("\n >>> Test failure: could not open file for input data\n");
return -1;
}
f->cd();
h1list->Write(0, TObject::kSingleKey, 0);
f->Close();
gProof->SetInputDataFile(datafile.Data());
// Histo to be sent from memory
TH1F *h2 = new TH1F("h2data","Input data from memory",100,-5.,5.);
h2->FillRandom("gaus", 1000);
TList *h2list = new TList;
h2list->SetName("h2list");
h2list->SetOwner(kTRUE);
h2list->Add(h2);
h2list->Add(new TParameter<Double_t>("h2avg", h2->GetMean()));
h2list->Add(new TParameter<Double_t>("h2rms", h2->GetRMS()));
gProof->AddInputData(h2list);
// Normal input parameter
gProof->AddInput(new TNamed("InputObject", glogfile.Data()));
// Type of test
gProof->AddInput(new TNamed("ProofTests_Type", "InputData"));
// Define the number of events
Long64_t nevt = 1;
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
{ SwitchProgressGuard spg;
gProof->Process(gTestsSel.Data(), nevt);
}
// Cleanup
gSystem->Unlink(datafile.Data());
gProof->ClearInputData(h1list);
gProof->ClearInputData(h2list);
delete h1list;
delete h2list;
// Make sure the query result is there
PutPoint();
TQueryResult *qr = 0;
if (!(qr = gProof->GetQueryResult())) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the output list is there
PutPoint();
if (!(gProof->GetOutputList())) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Check the 'histo's
PutPoint();
TH1I *stat = dynamic_cast<TH1I*>(gProof->GetOutputList()->FindObject("TestStat"));
if (!stat) {
printf("\n >>> Test failure: 'TestStat' histo not found\n");
return -1;
}
// Test how many workers got everything successfully
Int_t nw = (Int_t) stat->GetBinContent(1);
PutPoint();
if (TMath::Abs(stat->GetBinContent(2) - nw) > .1) {
printf("\n >>> Test failure: histo 'h1' not correctly received on all workers (%.0f/%d)\n",
stat->GetBinContent(2), nw);
return -1;
}
if (TMath::Abs(stat->GetBinContent(3) - nw) > .1) {
printf("\n >>> Test failure: histo 'h2' not correctly received on all workers (%.0f/%d)\n",
stat->GetBinContent(3), nw);
return -1;
}
if (TMath::Abs(stat->GetBinContent(4) - nw) > .1) {
printf("\n >>> Test failure: test input object not correctly received on all workers (%.0f/%d)\n",
stat->GetBinContent(4), nw);
return -1;
}
// Fill times
PT_GetLastTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_PackageArguments(void *, RunTimes &tt)
{
// Testing passing arguments to packages
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
PutPoint();
// Passing a 'const char *': upload packtest1
const char *pack1 = "packtest1";
PutPoint();
gProof->UploadPackage(gPack1);
// Check the result
TList *packs = gProof->GetListOfPackages();
if (!packs || !packs->FindObject(pack1)) {
printf("\n >>> Test failure: could not upload '%s'!\n", gPack1.Data());
return -1;
}
// Enable the package now passing a 'const char *' argument
TString arg("ProofTest.ConstChar");
if (gProof->EnablePackage(pack1, arg) != 0) {
printf("\n >>> Test failure: could not enable '%s' with argument: '%s'!\n", gPack1.Data(), arg.Data());
return -1;
}
// Type of test
gProof->SetParameter("ProofTests_Type", "PackTest1");
// Define the number of events
Long64_t nevt = 1;
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Variable to check
gProof->SetParameter("testenv", arg.Data());
// Process
PutPoint();
{ SwitchProgressGuard spg;
gProof->Process(gTestsSel.Data(), nevt);
}
// Some cleanup
gProof->ClearPackage(pack1);
gProof->DeleteParameters("ProofTests_Type");
gProof->DeleteParameters("testenv");
// Make sure the query result is there
PutPoint();
TQueryResult *qr = 0;
if (!(qr = gProof->GetQueryResult())) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the output list is there
PutPoint();
if (!(gProof->GetOutputList())) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Check the 'histo's
PutPoint();
TH1I *stat = dynamic_cast<TH1I*>(gProof->GetOutputList()->FindObject("TestStat"));
if (!stat) {
printf("\n >>> Test failure: 'TestStat' histo not found\n");
return -1;
}
// Test how many workers got everything successfully
Int_t nw = (Int_t) stat->GetBinContent(1);
PutPoint();
if (TMath::Abs(stat->GetBinContent(2) - nw) > .1) {
printf("\n >>> Test failure: var '%s' not correctly set on all workers (%.0f/%d)\n",
arg.Data(), stat->GetBinContent(2), nw);
return -1;
}
// Passing a 'TList *': upload packtest2
const char *pack2 = "packtest2";
PutPoint();
gProof->UploadPackage(gPack2);
// Check the result
packs = gProof->GetListOfPackages();
if (!packs || !packs->FindObject(pack2)) {
printf("\n >>> Test failure: could not upload '%s'!\n", gPack2.Data());
return -1;
}
// Create the argument list
TList *argls = new TList;
argls->Add(new TNamed("ProofTest.ArgOne", "2."));
argls->Add(new TNamed("ProofTest.ArgTwo", "3."));
argls->Add(new TNamed("ProofTest.ArgThree", "4."));
// Enable the package now passing the 'TList *' argument
if (gProof->EnablePackage(pack2, argls) != 0) {
printf("\n >>> Test failure: could not enable '%s' with argument: '%s'!\n", gPack2.Data(), arg.Data());
return -1;
}
// Type of test
gProof->SetParameter("ProofTests_Type", "PackTest2");
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Variable to check
TString envs("ProofTest.ArgOne,ProofTest.ArgTwo,ProofTest.ArgThree");
gProof->SetParameter("testenv", envs.Data());
// Process
PutPoint();
{ SwitchProgressGuard spg;
gProof->Process(gTestsSel.Data(), nevt);
}
// Some cleanup
gProof->ClearPackage(pack2);
gProof->DeleteParameters("ProofTests_Type");
gProof->DeleteParameters("testenv");
// Make sure the query result is there
PutPoint();
qr = 0;
if (!(qr = gProof->GetQueryResult())) {
printf("\n >>> Test failure: query result not found\n");
return -1;
}
// Make sure the output list is there
PutPoint();
if (!(gProof->GetOutputList())) {
printf("\n >>> Test failure: output list not found\n");
return -1;
}
// Check the 'histo's
PutPoint();
if (!(stat = dynamic_cast<TH1I*>(gProof->GetOutputList()->FindObject("TestStat")))) {
printf("\n >>> Test failure: 'TestStat' histo not found\n");
return -1;
}
// Test how many workers got everything successfully
nw = (Int_t) stat->GetBinContent(1);
PutPoint();
if (TMath::Abs(stat->GetBinContent(2) - nw) > .1) {
printf("\n >>> Test failure: var 'ProofTest.ArgOne' not correctly set on all workers (%.0f/%d)\n",
stat->GetBinContent(2), nw);
return -1;
}
if (TMath::Abs(stat->GetBinContent(3) - nw) > .1) {
printf("\n >>> Test failure: var 'ProofTest.ArgTwo' not correctly set on all workers (%.0f/%d)\n",
stat->GetBinContent(3), nw);
return -1;
}
if (TMath::Abs(stat->GetBinContent(4) - nw) > .1) {
printf("\n >>> Test failure: var 'ProofTest.ArgThree' not correctly set on all workers (%.0f/%d)\n",
stat->GetBinContent(4), nw);
return -1;
}
// Fill times
PT_GetLastTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_H1SimpleAsync(void *arg, RunTimes &tt)
{
// Test run for the H1 and Simple analysis in asynchronous mode
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported for PROOF-Lite
if (gProof->IsLite()) {
return 1;
}
// Not supported in dynamic mode
if (gDynamicStartup) {
return 1;
}
PutPoint();
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Are we asked to change the packetizer strategy?
if (arg) {
PT_Packetizer_t *strategy = (PT_Packetizer_t *)arg;
if (strcmp(strategy->fName, "TPacketizerAdaptive")) {
gProof->SetParameter("PROOF_Packetizer", strategy->fName);
} else {
if (strategy->fType != 1)
gProof->SetParameter("PROOF_PacketizerStrategy", strategy->fType);
}
}
// Create the file collection
PutPoint();
TFileCollection *fc = new TFileCollection("h42");
// Assert the files, if needed
if (!gh1ok) {
if (PT_H1AssertFiles(gh1src.Data()) != 0) {
printf("\n >>> Test failure: could not assert the H1 files\n");
return -1;
}
}
Int_t i = 0;
for (i = 0; i < 4; i++) {
fc->Add(new TFileInfo(TString::Format("%s%c%s", gh1src.Data(), gh1sep, gh1file[i])));
}
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Clear the list of query results
PutPoint();
if (gProof->GetQueryResults()) {
gProof->GetQueryResults()->Clear();
gProof->Remove("cleanupdir");
}
// Define the number of events and histos
Long64_t nevt = 1000000;
Int_t nhist = 16;
// Submit the processing requests
PutPoint();
{ SwitchProgressGuard spg;
gProof->Process(fc, gH1Sel.Data(), "ASYN");
// The number of histograms is added as parameter in the input list
gProof->SetParameter("ProofSimple_NHist", (Long_t)nhist);
gProof->Process(gSimpleSel.Data(), nevt, "ASYN");
// Wait a bit as a function of previous runnings
Double_t dtw = 10;
if (gH1Cnt > 0 && gSimpleTime > 0) {
dtw = gH1Time / gH1Cnt + gSimpleTime / gSimpleCnt + 1;
if (dtw < 10) dtw = 10;
}
Int_t tw = (Int_t) (5 * dtw);
gTimedOut = kFALSE;
TTimeOutTimer t(tw*1000);
// Wait for the processing
while (!gProof->IsIdle() && !gTimedOut)
gSystem->InnerLoop();
}
PutPoint();
// Restore settings
gProof->DeleteParameters("PROOF_Packetizer");
gProof->DeleteParameters("PROOF_PacketizerStrategy");
// Retrieve the list of available query results
TList *ql = gProof->GetQueryResults();
if (ql && ql->GetSize() > 0) {
ql->Print();
}
TString ref;
TIter nxq(ql, kIterBackward);
Int_t nd = 2;
TQueryResult *qr = 0;
while ((qr = (TQueryResult *)nxq()) && nd > 0) {
ref.Form("%s:%s", qr->GetTitle(), qr->GetName());
gProof->Retrieve(ref);
qr = gProof->GetQueryResult(ref);
if (qr && qr->GetSelecImp()) {
if (!strcmp(qr->GetSelecImp()->GetTitle(), "h1analysis")) {
PutPoint();
if (PT_CheckH1(qr) != 0) return -1;
nd--;
} else if (!strcmp(qr->GetSelecImp()->GetTitle(), "ProofSimple")) {
PutPoint();
if (PT_CheckSimple(qr, nevt, nhist) != 0) return -1;
nd--;
} else {
printf("\n >>> Test failure: query with unexpected selector '%s'\n", qr->GetSelecImp()->GetTitle());
return -1;
}
} else {
printf("\n >>> Test failure: query undefined (%p) or with empty selector macro ('%s')\n", qr, ref.Data());
return -1;
}
}
// The runtimes
PT_GetLastProofTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_AdminFunc(void *, RunTimes &tt)
{
// Test run for the admin functionality
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported for PROOF-Lite
if (gProof->IsLite()) {
return 1;
}
PutPoint();
// Attach to the manager
TProofMgr *mgr = gProof->GetManager();
if (!mgr) {
printf("\n >>> Test failure: no PROOF manager found\n");
return -1;
}
PutPoint();
// Directory for this test
TString testDir(TString::Format("%s/stressProof-Admin", gtutdir.Data()));
if (gSystem->AccessPathName(testDir)) {
// Create the directory
if (gSystem->MakeDirectory(testDir)) {
printf("\n >>> Test failure: cannot create %s\n", testDir.Data());
return -1;
}
}
// Create a small test file
TMacro testMacro;
testMacro.AddLine("// Test macro");
testMacro.AddLine("#include \"TSystem.h\"");
testMacro.AddLine("void testMacro(Int_t opt = 1)");
testMacro.AddLine("{");
testMacro.AddLine(" if (opt == 1) {");
testMacro.AddLine(" Printf(\"Pid: \", gSystem->GetPid());");
testMacro.AddLine(" }");
testMacro.AddLine("}");
// Save the file in the temporary area
TString testFile(TString::Format("%s/testMacro.C", testDir.Data()));
if (!gSystem->AccessPathName(testFile)) {
// The file exists: remove it first
if (gSystem->Unlink(testFile)) {
printf("\n >>> Test failure: cannot unlink %s\n", testFile.Data());
return -1;
}
}
testMacro.SaveSource(testFile);
FileStat_t stloc;
if (gSystem->GetPathInfo(testFile, stloc) != 0) {
// The file was not created
printf("\n >>> Test failure: file %s was not created\n", testFile.Data());
return -1;
}
// Reference checksum
TMD5 *testMacroMd5 = testMacro.Checksum();
if (!testMacroMd5) {
// MD5 sum not calculated
printf("\n >>> Test failure: could not calculate the md5 sum of the test macro\n");
return -1;
}
PutPoint();
// Send the file to the sandbox
if (mgr->PutFile(testFile, "~/", "force") != 0) {
// The file was not sent over correctly
printf("\n >>> Test failure: problems sending file to master sandbox\n");
return -1;
}
PutPoint();
// Retrieve the file
TString testFile1(TString::Format("%s/testMacro.cxx", testDir.Data()));
if (mgr->GetFile("~/testMacro.C", testFile1, "force") != 0) {
// The file was not retrieved correctly
printf("\n >>> Test failure: problems retrieving file from the master sandbox\n");
return -1;
}
PutPoint();
// Test 'ls'
gSystem->RedirectOutput(0, 0, &gRH);
TString testLs(TString::Format("%s/testLs.log", testDir.Data()));
gSystem->RedirectOutput(testLs, "w", &gRHAdmin);
mgr->Ls("~/testMacro.C");
gSystem->RedirectOutput(0, 0, &gRHAdmin);
gSystem->RedirectOutput(glogfile, "a", &gRH);
TMacro macroLs(testLs);
TString testLsLine = TString::Format("%s/testMacro.C", gsandbox.Data());
// The first part of <tmp> maybe sligthly different
#if defined(R__MACOSX)
if (testLsLine.Index(".proof") != kNPOS)
testLsLine.Remove(0, testLsLine.Index(".proof"));
#else
if (testLsLine.Index(".proof-tutorial") != kNPOS)
testLsLine.Remove(0, testLsLine.Index(".proof-tutorial"));
#endif
if (!macroLs.GetLineWith(testLsLine)) {
printf("\n >>> Test failure: Ls: output not consistent (line: '%s')\n", testLsLine.Data());
printf(" >>> Log file: '%s'\n", testLs.Data());
printf("+++ BOF +++\n");
macroLs.Print();
printf("+++ EOF +++\n");
return -1;
}
PutPoint();
// Test 'more'
gSystem->RedirectOutput(0, 0, &gRH);
TString testMore(TString::Format("%s/testMore.log", testDir.Data()));
gSystem->RedirectOutput(testMore, "w", &gRHAdmin);
mgr->More("~/testMacro.C");
gSystem->RedirectOutput(0, 0, &gRHAdmin);
gSystem->RedirectOutput(glogfile, "a", &gRH);
TMacro macroMore(testMore);
if (macroMore.GetListOfLines()->GetSize() < 2) {
printf("\n >>> Test failure: More output not too short: %d lines\n",
macroMore.GetListOfLines()->GetSize());
return -1;
}
TObjString *os = (TObjString *) macroMore.GetListOfLines()->First();
while (!os->GetString().BeginsWith("// Test macro")) {
macroMore.GetListOfLines()->Remove(macroMore.GetListOfLines()->First());
os = (TObjString *) macroMore.GetListOfLines()->First();
}
TMD5 *testMoreMd5 = macroMore.Checksum();
if (!testMoreMd5) {
// MD5 sum not calculated
printf("\n >>> Test failure: could not calculate the md5 sum of the 'more' result\n");
return -1;
}
if (strcmp(testMacroMd5->AsString(), testMoreMd5->AsString())) {
printf("\n >>> Test failure: More: result not consistent with reference: {%s, %s}\n",
testMacroMd5->AsString(), testMoreMd5->AsString());
return -1;
}
PutPoint();
// Test 'stat'
FileStat_t strem;
if (mgr->Stat("~/testMacro.C", strem) != 0) {
// Stat failure
printf("\n >>> Test failure: could not stat remotely the test file\n");
return -1;
}
if (strem.fSize != stloc.fSize) {
// Stat failure
printf("\n >>> Test failure: stat sizes inconsistent: %lld vs %lld (bytes)\n", strem.fSize, stloc.fSize);
return -1;
}
PutPoint();
// Test 'cp' and 'md5sum;
if (mgr->Cp("http://root.cern.ch/files/h1/dstarmb.root", "~/") != 0) {
// Cp failure
printf("\n >>> Test failure: could not retrieve remotely dstarmb.root from the Root Web server\n");
return -1;
}
TString sum;
if (mgr->Md5sum("~/dstarmb.root", sum) != 0) {
// MD5
printf("\n >>> Test failure: calculating the md5sum of dstarmb.root\n");
return -1;
}
if (sum != "0a60055370e16d954f90fb50c2d1a801") {
// MD5 wrong
printf("\n >>> Test failure: wrong value for md5sum of dstarmb.root: %s\n", sum.Data());
return -1;
}
PutPoint();
// Clean up sums
SafeDelete(testMoreMd5);
SafeDelete(testMacroMd5);
// Fill times
PT_GetLastTimes(tt);
// Done
PutPoint();
return 0;
}
//_____________________________________________________________________________
Int_t PT_EventRange(void *arg, RunTimes &tt)
{
// Test processing of sub-samples (entries-from-first) from files with the
// 'event' structures
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Are we asked to change the packetizer strategy?
const char *pack = "TPacketizerAdaptive";
if (arg) {
PT_Packetizer_t *strategy = (PT_Packetizer_t *)arg;
if (strcmp(strategy->fName, "TPacketizerAdaptive")) {
gProof->SetParameter("PROOF_Packetizer", strategy->fName);
pack = strategy->fName;
} else {
if (strategy->fType != 1)
gProof->SetParameter("PROOF_PacketizerStrategy", strategy->fType);
}
}
// Test first with a chain
PutPoint();
TChain *chain = new TChain("EventTree");
// Assert the files, if needed
if (!geventok) {
if (PT_EventAssertFiles(geventsrc.Data(), geventnf) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not assert the event files\n");
return -1;
}
}
Int_t i = 0;
for (i = 0; i < geventnf; i++) {
chain->AddFile(TString::Format("%s/event_%d.root", geventsrc.Data(), i+1));
}
// Clear associated memory cache
if (gClearCache && PT_EventReleaseCache(geventsrc.Data(), geventnf) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the event files\n");
return -1;
}
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Load special class for event ranges checks
if (gProof->Load(TString::Format("%s,%s", gProcFileElem.Data(), gEmptyInclude.Data())) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not load auxilliary files %s and %s\n",
gProcFileElem.Data(), gEmptyInclude.Data());
return -1;
}
// Add some parameters for later checking in Terminate
Int_t ifst = gEventFst / gEventSiz + 1;
Long64_t efst = gEventFst - (ifst - 1) * gEventSiz;
TString ffst = TString::Format("%s/event_%d.root?fst=%lld", geventsrc.Data(), ifst, efst);
gProof->SetParameter("Range_First_File", ffst.Data());
Int_t ilst = (gEventFst + gEventNum) / gEventSiz + 1;
Long64_t elst = (gEventFst + gEventNum) - (ilst - 1) * gEventSiz - 1;
TString flst = TString::Format("%s/event_%d.root?lst=%lld", geventsrc.Data(), ilst, elst);
gProof->SetParameter("Range_Last_File", flst.Data());
gProof->SetParameter("Range_Num_Files", (Int_t) (ilst - ifst + 1));
// Process
PutPoint();
chain->SetProof();
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
chain->Process(gEventProcSel.Data(), "", gEventNum, gEventFst);
gTimer.Stop();
}
gProof->RemoveChain(chain);
// Count
gEventCnt++;
gEventTime += gTimer.RealTime();
// Check the result
Int_t rcch = PT_CheckEvent(gProof->GetQueryResult(), pack);
// We are done if not dataset test possible
if (gSkipDataSetTest) {
// Restore settings
gProof->DeleteParameters("PROOF_Packetizer");
gProof->DeleteParameters("PROOF_PacketizerStrategy");
return rcch;
}
// Create the dataset
TFileCollection *fc = new TFileCollection("dsevent", "", "");
for (i = 0; i < geventnf; i++) {
fc->Add(new TFileInfo(TString::Format("%s/event_%d.root", geventsrc.Data(), i+1)));
}
// Register the dataset
PutPoint();
gProof->RegisterDataSet("dsevent", fc);
// Check the result
if (!gProof->ExistsDataSet("dsevent")) {
printf("\n >>> Test failure: could not register 'dsevent'\n");
return -1;
}
// Verify the dataset
PutPoint();
if (gProof->VerifyDataSet("dsevent") < 0) {
printf("\n >>> Test failure: could not verify 'dsevent'!\n");
return -1;
}
// Clear associated memory cache
if (gClearCache && PT_EventReleaseCache(geventsrc.Data(), geventnf) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the event files\n");
return -1;
}
// Process
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process("dsevent", gEventProcSel.Data(), "", gEventNum, gEventFst);
gTimer.Stop();
}
gProof->RemoveDataSet("dsevent");
// Restore settings
gProof->DeleteParameters("PROOF_Packetizer");
gProof->DeleteParameters("PROOF_PacketizerStrategy");
// Count
gEventCnt++;
gEventTime += gTimer.RealTime();
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckEvent(gProof->GetQueryResult(), pack);
}
//_____________________________________________________________________________
Int_t PT_POFNtuple(void *opts, RunTimes &tt)
{
// Test TProofOutputFile technology to create a ntuple, with or without
// submergers
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
PT_Option_t *ptopt = (PT_Option_t *) opts;
// Setup submergers if required
if (ptopt && ptopt->fTwo > 0) {
gProof->SetParameter("PROOF_UseMergers", 0);
}
// Output file
TString fout("<datadir>/ProofNtuple.root");
gProof->AddInput(new TNamed("PROOF_OUTPUTFILE", fout.Data()));
// We use the 'NtpRndm' for a fixed values of randoms; we need to send over the file
gProof->SetInputDataFile(gNtpRndm);
// Set the related parameter
gProof->SetParameter("PROOF_USE_NTP_RNDM","yes");
// Define the number of events and histos
Long64_t nevt = 1000;
// We do not plot the ntuple (we are in batch mode)
gProof->SetParameter("PROOF_NTUPLE_DONT_PLOT", "yes");
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(gNtupleSel.Data(), nevt);
gTimer.Stop();
}
// Remove any setting related to submergers
gProof->DeleteParameters("PROOF_UseMergers");
gProof->DeleteParameters("PROOF_NTUPLE_DONT_PLOT");
gProof->DeleteParameters("PROOF_USE_NTP_RNDM");
gProof->SetInputDataFile(0);
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckNtuple(gProof->GetQueryResult(), nevt);
}
//_____________________________________________________________________________
Int_t PT_POFDataset(void *, RunTimes &tt)
{
// Test TProofOutputFile technology to create a dataset
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
const char *dsname = "testNtuple";
// Clean-up any existing dataset with that name
if (gProof->ExistsDataSet(dsname)) gProof->RemoveDataSet(dsname);
// Ask for registration of the dataset (the default is the the TFileCollection is return
// without registration; the name of the TFileCollection is the name of the dataset
gProof->SetParameter("SimpleNtuple.root", dsname);
// We use the 'NtpRndm' for a fixed values of randoms; we need to send over the file
gProof->SetInputDataFile(gNtpRndm);
// Set the related parameter
gProof->SetParameter("PROOF_USE_NTP_RNDM","yes");
// Define the number of events and histos
Long64_t nevt = 1000000;
// We do not plot the ntuple (we are in batch mode)
gProof->SetParameter("PROOF_NTUPLE_DONT_PLOT", "yes");
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(gNtupleSel.Data(), nevt);
gTimer.Stop();
}
// Remove any setting related to submergers
gProof->DeleteParameters("PROOF_NTUPLE_DONT_PLOT");
gProof->DeleteParameters("SimpleNtuple.root");
gProof->DeleteParameters("PROOF_USE_NTP_RNDM");
gProof->SetInputDataFile(0);
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckDataset(gProof->GetQueryResult(), nevt);
}
//_____________________________________________________________________________
Int_t PT_MultiTrees(void *, RunTimes &tt)
{
// Test processing of multiple trees in the same files
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
const char *dsname = "testNtuple";
// There must be a dataset 'testNtuple' already registered and validated
if (!gProof->ExistsDataSet(dsname)) {
printf("\n >>> Test failure: dataset '%s' does not exist\n", dsname);
return -1;
}
// Get the associated TFileCollection
TFileCollection *fc = gProof->GetDataSet(dsname);
if (!fc) {
printf("\n >>> Test failure: unable to get TFileCollection for dataset '%s'\n", dsname);
return -1;
}
// Now create a TDSet out of the TFileCollection
TDSet *dset = new TDSet("testntps", "ntuple", "/", "TTree");
TChain *ch1 = new TChain("ntuple");
TChain *ch2 = new TChain("ntuple2");
TIter nxf(fc->GetList());
TFileInfo *fi = 0;
while ((fi = (TFileInfo *) nxf())) {
dset->Add(fi->GetCurrentUrl()->GetUrl());
ch1->Add(fi->GetCurrentUrl()->GetUrl());
ch2->Add(fi->GetCurrentUrl()->GetUrl());
}
// Check the ntuple content by filling some histos
TH1F *h1s[2] = {0};
h1s[0] = new TH1F("h1_1", "3*px+2 with px**2+py**2>1", 50, -15., 15.);
h1s[1] = new TH1F("h1_2", "vx**2+vy**2 with abs(vz)<.1", 50, 0., 10.);
Int_t rch1s = 0;
TString emsg;
const char *type[3] = { "dsname", "TDSet", "TChain" };
for (Int_t j = 0; j < 3; j++) {
PutPoint();
if (j == 0) {
// Fill the first histo from the first ntuple
gProof->SetDataSetTreeName(dsname, "ntuple");
{ SwitchProgressGuard spg;
gProof->DrawSelect(dsname, "3*px+2>>h1_1", "px*px+py*py>1");
}
// Fill the second histo from the second ntuple
gProof->SetDataSetTreeName(dsname, "ntuple2");
{ SwitchProgressGuard spg;
gProof->DrawSelect(dsname, "vx*vx+vy*vy>>h1_2", "vz>-0.1&&vz<0.1");
}
} else if (j == 1) {
// Fill the first histo from the first ntuple
{ SwitchProgressGuard spg;
gProof->DrawSelect(dset, "3*px+2>>h1_1", "px*px+py*py>1");
}
// Fill the second histo from the second ntuple
dset->SetObjName("ntuple2");
{ SwitchProgressGuard spg;
gProof->DrawSelect(dset, "vx*vx+vy*vy>>h1_2", "vz>-0.1&&vz<0.1");
}
} else {
// Fill the first histo from the first ntuple
{ SwitchProgressGuard spg;
ch1->Draw("3*px+2>>h1_1", "px*px+py*py>1");
}
// Fill the second histo from the second ntuple
{ SwitchProgressGuard spg;
ch2->Draw("vx*vx+vy*vy>>h1_2", "vz>-0.1&&vz<0.1");
}
}
rch1s = 0;
// Check the histogram entries and mean values
Int_t hent[2] = { 607700, 96100};
Double_t hmea[2] = { 2.022, 1.859};
for (Int_t i = 0; i < 2; i++) {
if ((Int_t)(h1s[i]->GetEntries()) != hent[i]) {
emsg.Form("%s: '%s' histo: wrong number of entries (%d: expected %d)",
type[j], h1s[i]->GetName(), (Int_t)(h1s[i]->GetEntries()), hent[i]);
rch1s = -1;
break;
}
if (TMath::Abs((h1s[i]->GetMean() - hmea[i]) / hmea[i]) > 0.001) {
emsg.Form("%s: '%s' histo: wrong mean (%f: expected %f)",
type[j], h1s[i]->GetName(), h1s[i]->GetMean(), hmea[i]);
rch1s = -1;
break;
}
}
}
// Cleanup
for (Int_t i = 0; i < 2; i++) delete h1s[i];
// Check the result
if (rch1s != 0) {
printf("\n >>> Test failure: %s\n", emsg.Data());
return -1;
}
// Clean-up
gProof->RemoveDataSet(dsname);
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return rch1s;
}
//_____________________________________________________________________________
Int_t PT_Friends(void *sf, RunTimes &tt)
{
// Test processing of TTree friends in PROOF
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not supported in dynamic mode
if (gDynamicStartup) {
return 1;
}
PutPoint();
// Separate or same file ?
Bool_t sameFile = (sf) ? kTRUE : kFALSE;
// File generation: we use TPacketizerFile in here to create two files per node
TList *wrks = gProof->GetListOfSlaveInfos();
if (!wrks) {
printf("\n >>> Test failure: could not get the list of information about the workers\n");
return -1;
}
// Create the map
TString fntree;
TMap *files = new TMap;
files->SetName("PROOF_FilesToProcess");
TIter nxwi(wrks);
TSlaveInfo *wi = 0;
while ((wi = (TSlaveInfo *) nxwi())) {
fntree.Form("tree_%s.root", wi->GetOrdinal());
THashList *wrklist = (THashList *) files->GetValue(wi->GetName());
if (!wrklist) {
wrklist = new THashList;
wrklist->SetName(wi->GetName());
files->Add(new TObjString(wi->GetName()), wrklist);
}
wrklist->Add(new TObjString(fntree));
}
Int_t nwrk = wrks->GetSize();
// Generate the files
gProof->AddInput(files);
if (sameFile) {
Printf("runProof: friend tree stored in the same file as the main tree");
gProof->SetParameter("ProofAux_Action", "GenerateTreesSameFile");
} else {
gProof->SetParameter("ProofAux_Action", "GenerateTrees");
}
// File generation: define the number of events per worker
Long64_t nevt = 1000;
gProof->SetParameter("ProofAux_NEvents", (Long64_t)nevt);
// Special Packetizer
gProof->SetParameter("PROOF_Packetizer", "TPacketizerFile");
// Now process
gProof->Process(gAuxSel.Data(), 1);
// Remove the packetizer specifications
gProof->DeleteParameters("PROOF_Packetizer");
// Check that we got some output
if (!gProof->GetOutputList()) {
printf("\n >>> Test failure: output list not found!\n");
return -1;
}
// Create the TDSet objects
TDSet *dset = new TDSet("Tmain", "Tmain");
TDSet *dsetf = new TDSet("Tfrnd", "Tfrnd");
// Fill them with the information found in the output list
Bool_t foundMain = kFALSE, foundFriend = kFALSE;
TIter nxo(gProof->GetOutputList());
TObject *o = 0;
TObjString *os = 0;
while ((o = nxo())) {
TList *l = dynamic_cast<TList *> (o);
if (l && !strncmp(l->GetName(), "MainList-", 9)) {
foundMain = kTRUE;
TIter nxf(l);
while ((os = (TObjString *) nxf()))
dset->Add(os->GetName());
}
}
nxo.Reset();
while ((o = nxo())) {
TList *l = dynamic_cast<TList *> (o);
if (l && !strncmp(l->GetName(), "FriendList-", 11)) {
foundFriend = kTRUE;
TIter nxf(l);
while ((os = (TObjString *) nxf()))
dsetf->Add(os->GetName());
}
}
// If we did not found the main or the friend meta info we fail
if (!foundMain || !foundFriend) {
printf("\n >>> Test failure: 'main' or 'friend' meta info missing!\n");
return -1;
}
// Connect the two datasets for processing
dset->AddFriend(dsetf, "friend");
// We do not plot the ntuple (we are in batch mode)
gProof->SetParameter("PROOF_DONT_PLOT", "yes");
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Process
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
dset->Process(gFriendsSel.Data());
gTimer.Stop();
}
// Remove any setting
gProof->DeleteParameters("PROOF_DONT_PLOT");
gProof->GetInputList()->Remove(files);
files->SetOwner(kTRUE);
SafeDelete(files);
// Clear the files created by this run
gProof->ClearData(TProof::kUnregistered | TProof::kForceClear);
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckFriends(gProof->GetQueryResult(), nevt * nwrk);
}
//_____________________________________________________________________________
Int_t PT_SimpleByObj(void *submergers, RunTimes &tt)
{
// Test run for the ProofSimple analysis (see tutorials) passing the
// selector by object
// Checking arguments
PutPoint();
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Setup submergers if required
if (submergers) {
gProof->SetParameter("PROOF_UseMergers", 0);
}
// Define the number of events and histos
Long64_t nevt = 1000000;
Int_t nhist = 16;
// The number of histograms is set inside the selector object; make sure
// that it is not passed in the input list
gProof->DeleteParameters("ProofSimple_NHist");
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Define TSelector object. We use reflection to avoid including the header,
// so being able to change the tutorial directory
TString emsg;
gProof->Load(gSimpleSel);
TSelector *sel = TSelector::GetSelector(gSimpleSel);
if (sel) {
TClass *cl = sel->IsA();
if (cl) {
TDataMember *dm = cl->GetDataMember("fNhist");
if (dm) {
TMethodCall *setter = dm->SetterMethod(cl);
if (setter) {
setter->Execute(sel, TString::Format("%d", nhist).Data());
} else {
emsg = "no SetterMethod for fNhist: check version of ProofSimple";
}
} else {
emsg = "fNhist not found";
}
} else {
emsg = "IsA() failed";
}
} else {
emsg = "GetSelector failed";
}
if (!emsg.IsNull()) {
printf("\n >>> Test failure: initializing ProofSimple selector: %s\n", emsg.Data());
return -1;
}
// Process
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
gProof->Process(sel, nevt);
gTimer.Stop();
}
// Count
gSimpleCnt++;
gSimpleTime += gTimer.RealTime();
// Remove any setting related to submergers
gProof->DeleteParameters("PROOF_UseMergers");
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckSimple(gProof->GetQueryResult(), nevt, nhist);
}
//_____________________________________________________________________________
Int_t PT_H1ChainByObj(void *, RunTimes &tt)
{
// Test run for the H1 analysis as a chain reading the data from HTTP and
// passing the selector by object
// Checking arguments
if (!gProof) {
printf("\n >>> Test failure: no PROOF session found\n");
return -1;
}
// Not yet supported for PROOF-Lite
if (gSkipDataSetTest) {
return 1;
}
PutPoint();
// Set/unset the parallel unzip flag
AssertParallelUnzip();
// Create the chain
PutPoint();
TChain *chain = new TChain("h42");
// Assert the files, if needed
if (!gh1ok) {
if (PT_H1AssertFiles(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not assert the H1 files\n");
return -1;
}
}
Int_t i = 0;
for (i = 0; i < 4; i++) {
chain->Add(TString::Format("%s%c%s", gh1src.Data(), gh1sep, gh1file[i]));
}
// Clear associated memory cache
if (gClearCache && PT_H1ReleaseCache(gh1src.Data()) != 0) {
gProof->SetPrintProgress(0);
printf("\n >>> Test failure: could not clear memory cache for the H1 files\n");
return -1;
}
// Clear the list of query results
if (gProof->GetQueryResults()) gProof->GetQueryResults()->Clear();
// Load TSelector
gProof->Load(gH1Sel);
TSelector *sel = TSelector::GetSelector(gH1Sel);
// Process
PutPoint();
chain->SetProof();
PutPoint();
{ SwitchProgressGuard spg;
gTimer.Start();
chain->Process(sel);
gTimer.Stop();
}
gProof->RemoveChain(chain);
// Count
gH1Cnt++;
gH1Time += gTimer.RealTime();
// The runtimes
PT_GetLastProofTimes(tt);
// Check the results
PutPoint();
return PT_CheckH1(gProof->GetQueryResult());
}