• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/opal/ZSI/test/wsdl2py/ServiceTest.py

00001 #!/usr/bin/env python
00002 ############################################################################
00003 # Joshua R. Boverhof, LBNL
00004 # See LBNLCopyright for copyright notice!
00005 ###########################################################################
00006 from compiler.ast import Module
00007 import StringIO, copy, getopt
00008 import os, sys, unittest, urlparse, signal, time, warnings, subprocess
00009 from ConfigParser import ConfigParser, NoSectionError, NoOptionError
00010 from ZSI.wstools.TimeoutSocket import TimeoutError
00011 from ZSI.generate import commands
00012 
00013 """Global Variables:
00014     CONFIG_FILE -- configuration file 
00015     CONFIG_PARSER -- ConfigParser instance
00016     DOCUMENT -- test section variable, specifying document style.
00017     LITERAL -- test section variable, specifying literal encodings.
00018     BROKE -- test section variable, specifying broken test.
00019     TESTS -- test section variable, whitespace separated list of modules.
00020     SECTION_CONFIGURATION -- configuration section, turn on/off debuggging.
00021     TRACEFILE -- file class instance.
00022     TOPDIR -- current working directory
00023     MODULEDIR  -- stubs directory 
00024     PORT -- port of local container
00025     HOST -- address of local container
00026     SECTION_SERVERS -- services to be tested, values are paths to executables.
00027 """
00028 CONFIG_FILE = 'config.txt'
00029 CONFIG_PARSER = ConfigParser()
00030 DOCUMENT = 'document'
00031 LITERAL = 'literal'
00032 BROKE = 'broke'
00033 TESTS = 'tests'
00034 SECTION_CONFIGURATION = 'configuration'
00035 SECTION_DISPATCH = 'dispatch'
00036 TRACEFILE = sys.stdout
00037 TOPDIR = os.getcwd()
00038 MODULEDIR = os.path.join(TOPDIR, 'stubs')
00039 SECTION_SERVERS = 'servers'
00040 
00041 CONFIG_PARSER.read(CONFIG_FILE)
00042 
00043 DEBUG = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'debug')
00044 SKIP = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'skip')
00045 TWISTED = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'twisted')
00046 LAZY = CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'lazy')
00047 OUTPUT = CONFIG_PARSER.get(SECTION_CONFIGURATION, 'output') or sys.stdout
00048 
00049 if DEBUG:
00050     from ZSI.wstools.logging import setBasicLoggerDEBUG
00051     setBasicLoggerDEBUG()
00052 
00053 sys.path.append('%s/%s' %(os.getcwd(), 'stubs'))
00054 ENVIRON = copy.copy(os.environ)
00055 ENVIRON['PYTHONPATH'] = ENVIRON.get('PYTHONPATH', '') + ':' + MODULEDIR
00056 
00057 
00058 def _SimpleMain():
00059     """Gets tests to run from configuration file.
00060     """
00061     unittest.TestProgram(defaultTest="all")
00062 main = _SimpleMain
00063 
00064 
00065 def _TwistedMain():
00066     """Gets tests to run from configuration file.
00067     """
00068     from twisted.internet import reactor
00069     reactor.callWhenRunning(_TwistedTestProgram, defaultTest="all")
00070     reactor.run(installSignalHandlers=0)
00071 if TWISTED: main = _TwistedMain
00072 
00073 
00074 def _LaunchContainer(cmd):
00075     '''
00076     Parameters:
00077         cmd -- executable, sets up a ServiceContainer or ?
00078     '''
00079     host = CONFIG_PARSER.get(SECTION_DISPATCH, 'host')
00080     port = CONFIG_PARSER.get(SECTION_DISPATCH, 'port')
00081     try:
00082         process = subprocess.Popen(['python', cmd, port], env=ENVIRON)
00083     except:
00084         print >>sys.stderr, 'error executing: %s' %cmd
00085         raise
00086     time.sleep(3)
00087     return process
00088 
00089 
00090 class _TwistedTestProgram(unittest.TestProgram):
00091 
00092     def runTests(self):
00093         from twisted.internet import reactor
00094         if self.testRunner is None:
00095             self.testRunner = unittest.TextTestRunner(verbosity=self.verbosity)
00096 
00097         result = self.testRunner.run(self.test)
00098         reactor.stop()
00099         return result.wasSuccessful()
00100 
00101 
00102 
00103 class ConfigException(Exception):
00104     """Exception thrown when configuration settings arent correct.
00105     """
00106     pass
00107 
00108 class TestException(Exception):
00109     """Exception thrown when test case isn't correctly set up.
00110     """
00111     pass
00112 
00113 
00114 class ServiceTestCase(unittest.TestCase):
00115     """Conventions for method names:
00116     test_net*
00117     -- network tests
00118     
00119     test_local*
00120     -- local tests
00121     
00122     test_dispatch*
00123     -- tests that use the a spawned local container
00124     
00125     class attributes: Edit/Override these in the inheriting class as needed
00126         out -- file descriptor to write output to
00127         name -- configuration item, must be set in class.
00128         url_section -- configuration section, maps a test module 
00129            name to an URL.
00130         client_file_name --
00131         types_file_name --
00132         server_file_name --
00133     """
00134     out = OUTPUT
00135     name = None
00136     url_section = 'WSDL'
00137     client_file_name = None
00138     types_file_name = None
00139     server_file_name = None
00140     
00141     def __init__(self, methodName):
00142         """
00143         parameters:
00144            methodName -- 
00145         instance variables:
00146             client_module
00147             types_module
00148             server_module
00149             processID
00150             done
00151 
00152         """
00153         self.methodName = methodName
00154         self.url = None
00155         self.wsdl2py_args = []
00156         self.wsdl2dispatch_args = []
00157         self.portkwargs = {}
00158         self.client_module = self.types_module = self.server_module = None
00159         self.done = False
00160 
00161         if TWISTED:
00162             self.wsdl2py_args.append('--twisted')
00163 
00164         if LAZY:
00165             self.wsdl2py_args.append('--lazy')
00166 
00167         unittest.TestCase.__init__(self, methodName)
00168 
00169     write = lambda self, arg: self.out.write(arg)
00170 
00171     if sys.version_info[:2] >= (2,5):
00172         _exc_info = unittest.TestCase._exc_info
00173     else:
00174         _exc_info = unittest.TestCase._TestCase__exc_info
00175 
00176     def __call__(self, *args, **kwds):
00177         self.run(*args, **kwds)
00178 
00179     def run(self, result=None):
00180         if result is None: result = self.defaultTestResult()
00181         result.startTest(self)
00182         testMethod = getattr(self, self.methodName)
00183         try:
00184             try:
00185                 self.setUp()
00186             except KeyboardInterrupt:
00187                 raise
00188             except:
00189                 result.addError(self, self._exc_info())
00190                 return
00191 
00192             ok = False
00193             try:
00194                 t1 = time.time()
00195                 pyobj = testMethod()
00196                 t2 = time.time()
00197                 ok = True
00198             except self.failureException:
00199                 result.addFailure(self, self._exc_info())
00200             except KeyboardInterrupt:
00201                 raise
00202             except:
00203                 result.addError(self, self._exc_info())
00204 
00205             try:
00206                 self.tearDown()
00207             except KeyboardInterrupt:
00208                 raise
00209             except:
00210                 result.addError(self, self._exc_info())
00211                 ok = False
00212             if ok: 
00213                 result.addSuccess(self)
00214                 print>>self
00215                 print>>self, "|"+"-"*60
00216                 print>>self, "|  TestCase: %s" %self.methodName
00217                 print>>self, "|"+"-"*20
00218                 print>>self, "|  run time:   %s ms" %((t2-t1)*1000)
00219                 print>>self, "|  return  :   %s" %pyobj
00220                 print>>self, "|"+"-"*60
00221 
00222         finally:
00223             result.stopTest(self)
00224 
00225 
00226 
00227 
00228     def getPortKWArgs(self):
00229         kw = {}
00230         if CONFIG_PARSER.getboolean(SECTION_CONFIGURATION, 'tracefile'):
00231             kw['tracefile'] = TRACEFILE
00232         
00233         kw.update(self.portkwargs)
00234         return kw
00235     
00236     def _setUpDispatch(self):
00237         """Set this test up as a dispatch test.
00238         url -- 
00239         """
00240         host = CONFIG_PARSER.get(SECTION_DISPATCH, 'host')
00241         port = CONFIG_PARSER.get(SECTION_DISPATCH, 'port')
00242         path = CONFIG_PARSER.get(SECTION_DISPATCH, 'path')
00243         
00244         scheme = 'http'
00245         netloc = '%s:%s' %(host, port)
00246         params = query = fragment = None
00247         
00248         self.portkwargs['url'] = \
00249             urlparse.urlunparse((scheme,netloc,path,params,query,fragment))
00250         
00251     _wsdl = {}
00252     def _generate(self):
00253         """call the wsdl2py and wsdl2dispatch scripts and
00254         automatically add the "-f" or "-u" argument.  Other args
00255         can be appended via the "wsdl2py_args" and "wsdl2dispatch_args"
00256         instance attributes.
00257         """
00258         url = self.url
00259         if os.path.isfile(url):
00260             url = os.path.abspath(url)
00261 
00262         if SKIP:
00263             ServiceTestCase._wsdl[url] = True
00264             return
00265         
00266         ServiceTestCase._wsdl[url] = False
00267         try:
00268             os.mkdir(MODULEDIR)
00269         except OSError, ex:
00270             pass
00271 
00272         os.chdir(MODULEDIR)
00273         if MODULEDIR not in sys.path:
00274             sys.path.append(MODULEDIR)
00275  
00276         try:
00277             commands.wsdl2py([url] + self.wsdl2py_args)
00278             ServiceTestCase._wsdl[url] = True
00279         finally:
00280             os.chdir(TOPDIR)
00281             
00282     _process = None
00283     _lastToDispatch = None
00284     def setUp(self):
00285         """Generate types and services modules once, then make them
00286         available thru the *_module attributes if the *_file_name 
00287         attributes were specified.
00288         """
00289         section = self.url_section
00290         name = self.name
00291         if not section or not name:
00292             raise TestException, 'section(%s) or name(%s) not defined' %(
00293                 section, name)
00294             
00295         if not CONFIG_PARSER.has_section(section):
00296             raise TestException,\
00297                 'No such section(%s) in configuration file(%s)' %(
00298                 self.url_section, CONFIG_FILE)
00299 
00300         self.url = CONFIG_PARSER.get(section, name)
00301         
00302         status = ServiceTestCase._wsdl.get(self.url)
00303         if status is False:
00304             self.fail('generation failed for "%s"' %self.url)
00305             
00306         if status is None:
00307             self._generate()
00308             
00309         # Check for files
00310         tfn = self.types_file_name
00311         cfn = self.client_file_name
00312         sfn = self.server_file_name
00313     
00314         files = filter(lambda f: f is not None, [cfn, tfn,sfn])
00315         if None is cfn is tfn is sfn:
00316             return
00317         
00318         for n,m in map(lambda i: (i,__import__(i.split('.py')[0])), files):
00319             if tfn is not None and tfn == n:
00320                 self.types_module = m
00321             elif cfn is not None and cfn == n:
00322                 self.client_module = m
00323             elif sfn is not None and sfn == n:
00324                 self.server_module = m
00325             else: 
00326                 self.fail('Unexpected module %s' %n)
00327 
00328         # DISPATCH PORTION OF SETUP
00329         if not self.methodName.startswith('test_dispatch'):
00330             return
00331         
00332         self._setUpDispatch()
00333         if ServiceTestCase._process is not None:
00334             return
00335 
00336         try:
00337             expath = CONFIG_PARSER.get(SECTION_DISPATCH, name)
00338         except (NoSectionError, NoOptionError), ex:
00339             self.fail('section dispatch has no item "%s"' %name)
00340 
00341         if ServiceTestCase._lastToDispatch == expath:
00342             return
00343         
00344         if ServiceTestCase._lastToDispatch is not None:
00345            ServiceTestCase.CleanUp()
00346         
00347         ServiceTestCase._lastToDispatch = expath
00348         ServiceTestCase._process = \
00349             _LaunchContainer(os.path.join(os.path.abspath(TOPDIR), 
00350                                                           *expath.split('/')))
00351        
00352             
00353     def CleanUp(cls):
00354         """call this when dispatch server is no longer needed,
00355         maybe another needs to be started.  Assumption that
00356         a single "Suite" uses the same server, once all the
00357         tests are run in that suite do a cleanup.
00358         """
00359         if cls._process is None:
00360             return
00361         os.kill(cls._process.pid, signal.SIGKILL)
00362         cls._process = None
00363     CleanUp = classmethod(CleanUp)
00364          
00365          
00366 class ServiceTestSuite(unittest.TestSuite):
00367     """A test suite is a composite test consisting of a number of TestCases.
00368 
00369     For use, create an instance of TestSuite, then add test case instances.
00370     When all tests have been added, the suite can be passed to a test
00371     runner, such as TextTestRunner. It will run the individual test cases
00372     in the order in which they were added, aggregating the results. When
00373     subclassing, do not forget to call the base class constructor.
00374     """
00375     def __init__(self, tests=()):
00376         unittest.TestSuite.__init__(self, tests)
00377 
00378     def __call__(self, result):
00379         # for python2.4
00380         return self.run(result)
00381 
00382     def addTest(self, test):
00383         unittest.TestSuite.addTest(self, test)
00384 
00385     def run(self, result):
00386         for test in self._tests:
00387             if result.shouldStop:
00388                 break
00389             test(result)
00390             
00391         ServiceTestCase.CleanUp()
00392         return result
00393     
00394 

Generated on Wed Oct 20 2010 11:12:16 for APBS by  doxygen 1.7.2