casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
testbase.py
Go to the documentation of this file.
00001 ###Base class for casa test scripts
00002 ###More complicated tests may inherit from this
00003 import os
00004 import string
00005 import commands
00006 import shutil
00007 import sys
00008 from  casac import *
00009 import inspect
00010 import re
00011 #from tasks import *  # execfile
00012 #from taskinit import casalog
00013 
00014 ia=casac.image()
00015 ms=casac.ms()
00016 tb=casac.table()
00017 
00018 class testbase :
00019     def __init__(self, workdir=None):
00020         if workdir == None:
00021             workdir=os.getcwd()
00022         self.dataBaseDirectory=[workdir+'/Data']
00023         self.resultDirectory=workdir+'/Results'
00024         self.workingDirectory=workdir
00025         self.scriptRepository=workdir+'/Scripts'
00026         self.testsToRun=[]
00027         self.testList={}
00028         self.notest=False
00029 
00030     def createDirs(self):
00031         if os.access(self.resultDirectory, os.F_OK) is False:
00032             print self.resultDirectory+' does not exist, creating it'
00033             os.makedirs(self.resultDirectory)
00034         if os.access(self.workingDirectory, os.F_OK) is False:
00035             print self.workingDirectory+' does not exist, creating it'
00036             os.makedirs(self.workingDirectory)
00037             
00038     def setDataBaseDir(self, dir=['./Data']):
00039         if type(dir) != type(["directory", "list"]):
00040             raise TypeError, type(dir)
00041         self.dataBaseDirectory=dir
00042 
00043     def setResultDir(self, dir='./Results'):
00044         self.resultDirectory=dir
00045 
00046     def setWorkingDir(self, dir='./Temporaire'):
00047         self.workingDirectory=dir
00048         
00049     def setScriptsDir(self, dir='./Scripts'):
00050         self.scriptRepository=dir
00051 
00052     def cleanup(self):
00053         if os.path.isdir(self.workingDirectory):
00054             #print 'Removing '+ self.workingDirectory
00055             shutil.rmtree(self.workingDirectory)
00056 
00057     def locateTests(self, tests=None):
00058         theF=[]
00059         theFiles=[]
00060         if tests is None :
00061             # This does not work, need to search also for DIR/name.py
00062             # Also, searching in .../tests/<name>/regression.py is
00063             # obsolete
00064             raise Exception, "Unsupported!"
00065         
00066             theFiles=os.listdir(self.scriptRepository)
00067             tempy=[]
00068             ###locate only the *.py files
00069             for leF in theFiles:
00070                 if os.path.isdir(self.scriptRepository + '/tests/' + leF) and \
00071                    os.path.isfile(self.scriptRepository + '/tests/' + leF + '/regression.py'):
00072                     tempy.append(leF + '/regression.py')
00073             theFiles=tempy
00074         else:
00075             for leF in tests :
00076                 leScript=self.searchscript(leF)
00077                 if(leScript != ''):
00078                    theFiles.append(leScript)
00079 
00080         self.testsToRun=[]
00081         for k  in range(len(theFiles)):
00082             #self.testsToRun.append(string.split(theFiles[k],'.py')[0])
00083             self.testsToRun.append(theFiles[k])          
00084         print "tests to run = ", self.testsToRun
00085         return len(self.testsToRun)
00086 
00087     def getTest(self, testnamek, testName):
00088         #Copy the script to the working dir
00089         if testnamek[0:6] == 'tests/':
00090             shutil.copy(self.scriptRepository+'/'+testnamek,
00091                         self.workingDirectory+'/'+testName+'.py')
00092         shutil.copy(self.scriptRepository+'/'+testnamek, \
00093                     self.workingDirectory+'/')
00094     
00095     def testname(self, ind=0):
00096         if(len(self.testsToRun)==0):
00097             print 'No tests defined yet'
00098             return ''
00099         return self.testsToRun[ind]
00100 
00101     def getDescription(self, testName, testId):
00102         leFile=self.testsToRun[testId]
00103 
00104         if leFile[0:6] == 'tests/':
00105             leTest = __import__(testName)
00106             reload(leTest)
00107             try:
00108                 # Fails if module does not
00109                 # define the description() function
00110                 desc = leTest.description()
00111                 desc = re.sub('\s+', ' ', desc)
00112 
00113             except:
00114                 desc = None
00115         else:
00116             desc = None
00117         return desc
00118             
00119     def runtests(self, testName, testId=0, dry=False):
00120         try:
00121             leFile=self.testsToRun[testId]
00122 
00123             if leFile[0:6] == 'tests/':
00124                 print "Import", leFile
00125                 leTest = __import__(testName)
00126                 #print "  imported"
00127                 allData=leTest.data()
00128                 # check if there is a doCopy function and use it if possible
00129                 try:
00130                     doCopy=leTest.doCopy()
00131                     print doCopy
00132                     if (len(doCopy) != len(allData)):
00133                         doCopy=[-1]
00134                         print 'Error: doCopy function supplied list of incorrect length.'
00135                     else:
00136                         print 'Using doCopy function to determine whether to copy or link input data.'
00137                 except:
00138                     doCopy=[-1]
00139                     
00140                 print "Required data =", allData
00141                 for leIndex, leData in enumerate(allData) : 
00142                     theData=self.locatedata(leData)
00143                     if(theData != ''):
00144                         os.system('rm -rf '+ self.workingDirectory+'/'+leData)
00145                         if(os.path.isdir(theData)):
00146                             if(doCopy[0] == -1 or doCopy[leIndex] != 0):
00147                                 shutil.copytree(theData, self.workingDirectory+'/'+leData)
00148                             else:
00149                                 os.system('ln -sf '+theData+' '+self.workingDirectory+'/'+leData)
00150                         if(os.path.isfile(theData)):
00151                             if(doCopy[0] == -1 or doCopy[leIndex] != 0):
00152                                 shutil.copy(theData, self.workingDirectory+'/'+leData)
00153                             else:
00154                                 os.system('ln -sf '+theData+' '+self.workingDirectory+'/'+leData)
00155                 if not dry:
00156                     theImages=leTest.run()
00157                 else:
00158                     # ngc5921redux
00159                     theImages = ['ngc5921_regression/ngc5921.clean.image']
00160 
00161                     # h121
00162                     theImages =  ['nrao150.3mm.image', 'h121.co10.image',  '0224b.3mm.image', 'h121b.co10.image', 'h121all.3mm.image', 'h121c.co10.image' ]
00163 
00164 
00165                 del leTest
00166 
00167                 if type(theImages) == None:
00168                     raise Exception, "Illegal return value from run()"                   
00169                     
00170                 leResult=[]
00171                 for leImage in theImages :
00172                     leResult.append(self.workingDirectory+'/'+leImage)
00173                 self.defineQualityTestList(leResult)
00174                 return leResult, theImages
00175             else:
00176                 print "execfile", leFile
00177                 if dry:
00178                     return [], []
00179                 a=inspect.stack()
00180                 stacklevel=0
00181                 for k in range(len(a)):
00182                     if (string.find(a[k][1], 'ipython console') > 0):
00183                         stacklevel=k
00184                         break
00185                 gl=sys._getframe(stacklevel).f_globals
00186 
00187                 # Execute the test from a generated exec-<test>.py
00188                 # which does the following
00189                 #    regstate=True
00190                 #    execfile(leFile)
00191                 #    if not regstate:
00192                 #        raise Exception ...
00193                 #
00194                 # This is a workaround: Changes in regstate
00195                 # do not propagate to here if the regression
00196                 # script is run directly with execfile() from
00197                 # here. But an exeption propagates
00198                 
00199                 fd=open('exec-'+leFile, 'w')
00200                 print >> fd, "regstate=True"   # used in regression scripts to signal error
00201                 print >> fd, "execfile('"+leFile+"')"
00202                 print >> fd, "print 'regstate =', regstate"
00203                 print >> fd, "if not regstate:"
00204                 print >> fd, "    raise Exception, 'regstate = False'"
00205                 fd.close()
00206 
00207                 # What we really want, but regstate doesn't propagate:
00208                 # execfile(leFile, gl)
00209                 execfile('./exec-'+leFile, gl)
00210                 
00211                 return [], []   # no product images known
00212         except:
00213             self.notest=True
00214             #print >> sys.stderr, "Error running test:", sys.exc_info()[0]
00215             raise
00216             
00217     def defineQualityTestList(self,theResult):
00218         self.testList.clear()
00219         for k in range(len(theResult)) :
00220             if(os.path.isdir(theResult[k])):
00221                 # previous developer said:
00222                 # Good chance its an image for now till i know whether its a caltable or ms
00223                 # actually check for ms, if not assume image
00224                 tb.open(theResult[k])
00225                 tabkwords=tb.keywordnames()
00226                 tb.done()
00227                 if('MS_VERSION' in tabkwords):
00228                     ms.open(theResult[k])
00229                     self.testList[theResult[k]]=[]
00230                     self.testList[theResult[k]].append('ms')
00231                     ms.done()
00232                 elif('coords' in tabkwords):
00233                     ## table is an image                    
00234                     self.testList[theResult[k]]=[]
00235                     self.testList[theResult[k]].append('simple')
00236                     ia.open(theResult[k])
00237                     shp=ia.shape()
00238                     ## Moment images do not have a spectral axis...
00239                     # much assumes the "canonical" CASA axis order.
00240                     # imageTest will adddegaxes to any im it opens (2011/12/15)
00241                     mycs=ia.coordsys()
00242                     findstok=mycs.findcoordinate("stokes")
00243                     findspec=mycs.findcoordinate("spectral")
00244                     if findspec[0]:                        
00245                         spix=findspec[1]
00246                         if(shp[spix]>5):
00247                             print 'spectral shape= ', shp[spix],' ', theResult[k], k 
00248                             self.testList[theResult[k]].append('cube')
00249                     if findstok[0]:
00250                         kpix=findstok[1]
00251                         if(shp[kpix]==1):
00252                             self.testList[theResult[k]].append('pol1')
00253                         elif( shp[kpix]==2):
00254                             self.testList[theResult[k]].append('pol2')
00255                         elif(shp[kpix]==4):
00256                             self.testList[theResult[k]].append('pol4')
00257                     ia.close()                
00258             
00259     def whatQualityTest(self):
00260         if(self.notest):
00261             return []
00262         return self.testList
00263     
00264     def searchscript(self,  testname):
00265         scriptdir=self.scriptRepository
00266         print "searching for script", testname, "in ",scriptdir
00267         testName=string.lower(testname)
00268 
00269         # search for DIR/tests/<name>.py
00270         if os.path.isdir(scriptdir+'/tests/'):
00271             allScripts=os.listdir(scriptdir+'/tests/')
00272         else:
00273             allScripts=[]
00274         print "allScripts = ", allScripts
00275         theScript=''
00276         numOfScript=0
00277         for scr in allScripts :
00278             #if(string.find(scr,testname)>=0):
00279             if(scr == testname+'.py'):
00280                 print scr, testname
00281                 #if (self.ispythonscript(scr)):
00282                 theScript = 'tests/'+scr
00283                 numOfScript +=1
00284 
00285         # search for DIR/<name>.py
00286         if os.path.isdir(scriptdir):
00287             allScripts=os.listdir(scriptdir)
00288         else:
00289             allScripts=[]
00290         print "allScripts = ", allScripts
00291         for scr in allScripts:
00292             #print scriptdir, scr, testname
00293             if (scr == testname + '.py'):
00294                 theScript = scr
00295                 numOfScript += 1             
00296         if numOfScript == 0:
00297             raise Exception("Could not find test %s" % testname)
00298         if( numOfScript > 1) :
00299             print 'More than 1 scripts found for name '+testname
00300             print 'Using the following one '+ theScript
00301         print "Found", theScript
00302         return theScript
00303 
00304     def ispythonscript(self, thescript):
00305         if(string.find(thescript,'.py', len(thescript)-3) > 0):
00306             return True
00307         else:
00308             return False
00309 
00310     def locatedata(self, datafile):
00311         for repository in self.dataBaseDirectory :
00312 
00313             # Skip hidden directories
00314             filter_hidden = ' | grep -vE "^\\."  | grep -vE "/\\."'
00315             
00316             # See if find understands -L or -follow (depends on find version)
00317             (err, a) = commands.getstatusoutput('find -L ' + repository+'/ 1>/dev/null 2>&1')
00318             if not err:
00319                 findstr='find -L '+repository+'/ -name '+datafile+' -print 2>/dev/null' + filter_hidden
00320             else:
00321                 findstr='find '+repository+'/ -follow -name '+datafile+' -print 2>/dev/null' + filter_hidden
00322             # A '/' is appended to the directory name; otherwise sometimes find doesn't find.
00323             # Also, ignore error messages such as missing directory permissions
00324             
00325             (find_errorcode, a)=commands.getstatusoutput(findstr)   # stdout and stderr
00326             #if find_errorcode != 0:
00327             #    print >> sys.stderr, "%s failed: %s" % (findstr, a)
00328             retval=''
00329             b=['']
00330             if(a!=''):
00331                 b=string.split(a, '\n')
00332                 retval=b[len(b)-1]
00333                 if(len(b) > 1):
00334                     print 'more than 1 file found with name '+datafile
00335                 print 'will use', retval
00336                 return retval
00337         raise Exception, 'Could not find datafile %s in the repository directories %s' \
00338               % (datafile, self.dataBaseDirectory)