123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- # coding: utf-8
- # Copyright (C) 1994-2018 Altair Engineering, Inc.
- # For more information, contact Altair at www.altair.com.
- #
- # This file is part of the PBS Professional ("PBS Pro") software.
- #
- # Open Source License Information:
- #
- # PBS Pro is free software. You can redistribute it and/or modify it under the
- # terms of the GNU Affero General Public License as published by the Free
- # Software Foundation, either version 3 of the License, or (at your option) any
- # later version.
- #
- # PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
- # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- # FOR A PARTICULAR PURPOSE.
- # See the GNU Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- #
- # Commercial License Information:
- #
- # For a copy of the commercial license terms and conditions,
- # go to: (http://www.pbspro.com/UserArea/agreement.html)
- # or contact the Altair Legal Department.
- #
- # Altair’s dual-license business model allows companies, individuals, and
- # organizations to create proprietary derivative works of PBS Pro and
- # distribute them - whether embedded or bundled with other software -
- # under a commercial license agreement.
- #
- # Use of Altair’s trademarks, including but not limited to "PBS™",
- # "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
- # trademark licensing policies.
- import sys
- import logging
- from nose.plugins.base import Plugin
- from ptl.utils.pbs_testsuite import PBSTestSuite
- from ptl.utils.plugins.ptl_test_tags import TAGKEY
- from copy import deepcopy
- log = logging.getLogger('nose.plugins.PTLTestInfo')
- class FakeRunner(object):
- def __init__(self, config):
- self.config = config
- def run(self, test):
- self.config.plugins.finalize(None)
- sys.exit(0)
- class PTLTestInfo(Plugin):
- """
- Load test cases from given parameter
- """
- name = 'PTLTestInfo'
- score = sys.maxint - 1
- logger = logging.getLogger(__name__)
- def __init__(self):
- self.list_test = None
- self.showinfo = None
- self.verbose = None
- self.gen_ts_tree = None
- self.suites = []
- self._tree = {}
- self.total_suite = 0
- self.total_case = 0
- self.__ts_tree = {}
- self.__tags_tree = {'NoTags': {}}
- def options(self, parser, env):
- """
- Register command line options
- """
- pass
- def set_data(self, suites, list_test, showinfo, verbose, gen_ts_tree):
- """
- Set the data required for running the tests
- :param suites: Test suites to run
- :param list_test: List of test to run
- :param gen_ts_tree: Generate test suite tree
- """
- self.suites = suites.split(',')
- self.list_test = list_test
- self.showinfo = showinfo
- self.verbose = verbose
- self.gen_ts_tree = gen_ts_tree
- def configure(self, options, config):
- """
- Configure the plugin and system, based on selected options
- :param options: Options to configure plugin and system
- """
- self.config = config
- self.enabled = True
- def prepareTestRunner(self, runner):
- return FakeRunner(config=self.config)
- def wantClass(self, cls):
- """
- Is the class wanted?
- """
- if not issubclass(cls, PBSTestSuite):
- return False
- if cls.__name__ == 'PBSTestSuite':
- return False
- self._tree.setdefault(cls.__name__, cls)
- if len(cls.__bases__) > 0:
- self.wantClass(cls.__bases__[0])
- return False
- def wantFunction(self, function):
- """
- Is the function wanted?
- """
- return False
- def wantMethod(self, method):
- """
- Is the method wanted?
- """
- return False
- def _get_hierarchy(self, cls, level=0):
- delim = ' ' * level
- msg = [delim + cls.__name__]
- subclses = cls.__subclasses__()
- for subcls in subclses:
- msg.extend(self._get_hierarchy(subcls, level + 1))
- return msg
- def _print_suite_info(self, suite):
- w = sys.stdout
- self.total_suite += 1
- if self.list_test:
- w.write('\n\n')
- w.write('Test Suite: %s\n\n' % suite.__name__)
- w.write(' file: %s.py\n\n' % suite.__module__.replace('.', '/'))
- w.write(' module: %s\n\n' % suite.__module__)
- tags = getattr(suite, TAGKEY, None)
- if tags is not None:
- w.write(' Tags: %s\n\n' % (', '.join(tags)))
- w.write(' Suite Doc: \n')
- for l in str(suite.__doc__).split('\n'):
- w.write(' %s\n' % l)
- dcl = suite.__dict__
- cases = []
- for k in dcl.keys():
- if k.startswith('test_'):
- k = getattr(suite, k)
- try:
- k.__name__
- except:
- # not a test case, ignore
- continue
- self.total_case += 1
- cases.append('\t%s\n' % (k.__name__))
- if self.verbose:
- tags = getattr(k, TAGKEY, None)
- if tags is not None:
- cases.append('\n\t Tags: %s\n\n' %
- (', '.join(tags)))
- doc = k.__doc__
- if doc is not None:
- cases.append('\t Test Case Doc: \n')
- for l in str(doc).split('\n'):
- cases.append('\t%s\n' % (l))
- if len(cases) > 0:
- w.write(' Test Cases: \n')
- w.writelines(cases)
- if self.list_test or self.showinfo:
- lines = self._get_hierarchy(suite, 1)[1:]
- if len(lines) > 0:
- w.write('\n Test suite hierarchy:\n')
- for l in lines:
- w.write(l + '\n')
- def _gen_ts_tree(self, suite):
- n = suite.__name__
- tsd = {}
- tsd['doc'] = str(suite.__doc__)
- tstags = getattr(suite, TAGKEY, [])
- numnodes = 1
- for tag in tstags:
- if 'numnodes' in tag:
- numnodes = tag.split('=')[1].strip()
- break
- tsd['tags'] = tstags if len(tstags) > 0 else "None"
- tsd['numnodes'] = str(numnodes)
- tsd['file'] = suite.__module__.replace('.', '/') + '.py'
- tsd['module'] = suite.__module__
- dcl = suite.__dict__
- tcs = {}
- for k in dcl.keys():
- if k.startswith('test_'):
- tcd = {}
- tc = getattr(suite, k)
- try:
- tc.__name__
- except:
- # not a test case, ignore
- continue
- tcd['doc'] = str(tc.__doc__)
- tctags = sorted(set(tstags + getattr(tc, TAGKEY, [])))
- numnodes = 1
- for tag in tctags:
- if 'numnodes' in tag:
- numnodes = tag.split('=')[1].strip()
- break
- tcd['tags'] = tctags if len(tctags) > 0 else "None"
- tcd['numnodes'] = str(numnodes)
- tcs[k] = deepcopy(tcd)
- if len(tctags) > 0:
- for tag in tctags:
- if tag not in self.__tags_tree.keys():
- self.__tags_tree[tag] = {}
- if n not in self.__tags_tree[tag].keys():
- self.__tags_tree[tag][n] = deepcopy(tsd)
- if 'tclist' not in self.__tags_tree[tag][n].keys():
- self.__tags_tree[tag][n]['tclist'] = {}
- self.__tags_tree[tag][n]['tclist'][k] = deepcopy(tcd)
- else:
- if n not in self.__tags_tree['NoTags'].keys():
- self.__tags_tree['NoTags'][n] = deepcopy(tsd)
- if 'tclist' not in self.__tags_tree['NoTags'][n].keys():
- self.__tags_tree['NoTags'][n]['tclist'] = {}
- self.__tags_tree['NoTags'][n]['tclist'][k] = deepcopy(tcd)
- if len(tcs.keys()) > 0:
- self.__ts_tree[n] = deepcopy(tsd)
- self.__ts_tree[n]['tclist'] = tcs
- def finalize(self, result):
- if self.list_test or self.gen_ts_tree:
- suites = self._tree.keys()
- else:
- suites = self.suites
- suites.sort()
- unknown = []
- if self.gen_ts_tree:
- func = self._gen_ts_tree
- else:
- func = self._print_suite_info
- for k in suites:
- try:
- suite = eval(k, globals(), self._tree)
- except:
- unknown.append(k)
- continue
- func(suite)
- if self.list_test:
- w = sys.stdout
- w.write('\n\n')
- w.write('Total number of Test Suites: %d\n' % (self.total_suite))
- w.write('Total number of Test Cases: %d\n' % (self.total_case))
- elif self.gen_ts_tree:
- tsdata = ''
- tagsdata = ''
- try:
- import json
- tsdata = json.dumps(self.__ts_tree, indent=4)
- tagsdata = json.dumps(self.__tags_tree, indent=4)
- except ImportError:
- try:
- import simplejson
- tsdata = simplejson.dumps(self.__ts_tree, indent=4)
- tagsdata = simplejson.dumps(self.__tags_tree, indent=4)
- except ImportError:
- _pre = str(self.__ts_tree).replace('"', '\\"')
- tsdata = _pre.replace('\'', '"')
- _pre = str(self.__tags_tree).replace('"', '\\"')
- tagsdata = _pre.replace('\'', '"')
- f = open('ptl_ts_tree.json', 'w+')
- f.write(tsdata)
- f.close()
- f = open('ptl_tags_tree.json', 'w+')
- f.write(tagsdata)
- f.close()
- if len(unknown) > 0:
- self.logger.error('Unknown testsuite(s): %s' % (','.join(unknown)))
|