commit 743e6f57cf72058a253134cce092aad9ea95379a Author: Isis Lovecruft isis@torproject.org Date: Sun Nov 4 12:28:36 2012 +0000
* Still working on NetTestAdaptor * Fixed so many errors in pretty much everything that I can't even count. --- ooni/nettest.py | 136 ++++++++++++++++++++++------------ ooni/runner.py | 187 ++++++++++++++------------------------------- ooni/templates/scapyt.py | 4 +- 3 files changed, 148 insertions(+), 179 deletions(-)
diff --git a/ooni/nettest.py b/ooni/nettest.py index 7f9f72c..03e391e 100644 --- a/ooni/nettest.py +++ b/ooni/nettest.py @@ -25,6 +25,7 @@ from ooni.utils import log
pyunit = __import__('unittest')
+ class InputTestSuite(pyunit.TestSuite): """ This in an extension of a unittest test suite. It adds support for inputs @@ -70,13 +71,14 @@ class NetTestAdaptor(unittest.TestCase): XXX fill me in """
- @classmethod - def __new__(cls, *args, **kwargs): - if hasattr(cls, "setUpClass"): - super( NetTestAdaptor, cls ).setUpClass(cls) - else: - log.debug("NetTestAdaptor: constructor could not find setUpClass") - return super( NetTestAdaptor, cls ).__new__(cls, *args, **kwargs) + # @classmethod + # def __new__(cls, *args, **kwargs): + # try: + # setUpClass() + # except Exception, e: + # log.debug("NetTestAdaptor: constructor could not find setUpClass") + # log.err(e) + # return super( NetTestAdaptor, cls ).__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs): """ @@ -114,10 +116,12 @@ class NetTestAdaptor(unittest.TestCase): #self._input_parser = copyattr("inputParser", alt=__input_parser__) #self._nettest_name = copyattr("name", alt="NetTestAdaptor"))
- if self.parsed_inputs: - self.inputs = self.parsed_inputs - else: - log.debug("Unable to find parsed inputs") + #self.setUpClass(self.__class__) + + #if hasattr(self, parsed_inputs): + # self.inputs = self.parsed_inputs + #else: + # log.debug("Unable to find parsed inputs")
@staticmethod def __copyattr__(obj, old, new=None, alt=None): @@ -220,7 +224,8 @@ class NetTestAdaptor(unittest.TestCase): pass ## don't burn cycles on testing null inputs else: log.msg("Received direct inputs:\n%s" % cls._raw_inputs) - parsed.extend([cls._input_parser(x) for x in cls._raw_inputs]) + parsed.extend( + [cls._input_parser(x) for x in cls._raw_inputs]) elif isinstance(cls._raw_inputs, str): separated = cls._raw_inputs.translate(None, ',') ## space delineates inputlist = separated.split(' ') @@ -229,43 +234,83 @@ class NetTestAdaptor(unittest.TestCase): log.debug("inputs not string or list; type: %s" % type(cls._raw_inputs))
+ if cls.subarg_inputs: + log.debug("NetTestAdaptor: __get_inputs__ found subarg_inputs=%s" + % cls.subarg_inputs) + parsed.extend([cls._input_parser(x) for x in cls.subarg_inputs]) + if cls._input_file: try: - log.debug("Opening input file") + log.debug("NetTestAdaptor: __get_inputs__ Opening input file") fp = open(cls._input_file) except: - log.debug("Couldn't open input file") + log.debug("NetTestAdaptor: __get_inputs__ Couldn't open input file") else: - log.debug("Running input file processor") + log.debug("NetTestAdaptor: __get_inputs__ Running input file processor") lines = [line.strip() for line in fp.readlines()] fp.close()
## add to what we've already parsed, if any: - log.debug("Parsing lines from input file") + log.debug("NetTestAdaptor: __get_inputs__ Parsing lines from input file") parsed.extend([cls._input_parser(ln) for ln in lines]) else: - log.debug("%s specified that it doesn't need inputFile." + log.debug("NetTestAdaptor: %s specified that it doesn't need inputFile." % cls._nettest_name)
return parsed
@classmethod - def __optstruct__(cls): + def __getopt__(cls, parseArgs=None): """ Constuctor for a custom t.p.usage.Options class, per NetTestCase. + + old code from runner.py: + opts = Options() + opts.parseOptions(config['subArgs']) + cls.localOptions = opts """ - #if cls._opt_parameters is None: - # cls._opt_parameters = [ list() ] + if cls._testopt_params or cls._input_file: + if not cls._testopt_params: + cls._testopt_params = [] + + if cls._input_file: + cls._testopt_params.append(cls.input_file)
class NetTestOptions(usage.Options): """Per NetTestCase Options class.""" - optParameters = cls._testopt_params - optFlags = cls._testopt_flags - subOptions = cls._sub_options - subCommands = cls._sub_command + optParameters = cls._testopt_params + optFlags = cls._testopt_flags + subOptions = cls._sub_options + subCommands = cls._sub_commands + defaultSubCommand = cls._default_subcmd + ## XXX i'm not sure if this part will work: + parseArgs = lambda a: cls.subarg_inputs.append(a) + + def opt_version(self): + """Display test version and exit.""" + print "Test version: ", cls._nettest_version + sys.exit(0) + + options = NetTestOptions() + return options
- def buildUsageOptions(self, *args, **kwargs): - pass + #if cls._input_file: + # cls._input_file = cls.options[cls._input_file[0]] + + @classmethod + def addSubArgToInputs(cls, subarg): + cls.subarg_inputs.append(subarg) + + @classmethod + def buildOptions(cls, from_global): + log.debug("NetTestAdaptor: getTestOptions called") + options = cls.__getopt__() + log.debug("NetTestAdaptor: getTestOptions: cls.options = %s" + % options) + options.parseOptions(from_global) + setattr(cls, "local_options", options) + log.debug("NetTestAdaptor: getTestOptions: cls.local_options = %s" + % cls.local_options)
@classmethod def setUpClass(cls): @@ -278,24 +323,29 @@ class NetTestAdaptor(unittest.TestCase): subclass of :class:`ooni.nettest.NetTestCase`, so that the calling functions during NetTestCase class setup can handle them correctly. """ + + log.debug("NetTestAdaptor: setUpClass called") + ## These internal inputs are for handling inputs and inputFile - cls._raw_inputs = __copyattr__(cls, "inputs") - cls._input_file = __copyattr__(cls, "inputFile") - cls._input_parser = __copyattr__(cls, "inputParser", alt=__input_parser__) - cls._nettest_name = __copyattr__(cls, "name", alt="NetTestAdaptor") + cls._raw_inputs = cls.__copyattr__(cls, "inputs") + cls._input_file = cls.__copyattr__(cls, "inputFile") + cls._input_parser = cls.__copyattr__(cls, "inputParser", + alt=cls.__input_parser__) + cls._nettest_name = cls.__copyattr__(cls, "name", alt="NetTestAdaptor")
## This creates a class attribute with all of the parsed inputs, ## which the instance will later set to be `self.inputs`. - cls.parsed_inputs = __get_inputs__(cls) + cls.parsed_inputs = cls.__get_inputs__() + cls.subarg_inputs = cls.__copyattr__(cls, "subarg_inputs", + alt=[])
## XXX we should handle options generation here - cls._testopt_params = __copyattr__(cls, "optParameters") - cls._testopt_flags = __copyattr__(cls, "optFlags") - cls._sub_options = __copyattr__(cls, "subOptions") - cls._sub_command = __copyattr__(cls, "subCommand") - cls._default_subcmd = __copyattr__(cls, "defaultSubCommand") - cls._nettest_version = __copyattr__(cls, "version") - + cls._testopt_params = cls.__copyattr__(cls, "optParameters") + cls._testopt_flags = cls.__copyattr__(cls, "optFlags") + cls._sub_options = cls.__copyattr__(cls, "subOptions") + cls._sub_commands = cls.__copyattr__(cls, "subCommands") + cls._default_subcmd = cls.__copyattr__(cls, "defaultSubCommand") + cls._nettest_version = cls.__copyattr__(cls, "version")
class NetTestCase(NetTestAdaptor): """ @@ -376,15 +426,6 @@ class NetTestCase(NetTestAdaptor): return inputs
def getOptions(self): - ''' - for attr in attributes: - if not attr.name is 'optParameters' or attr.name is 'optFlags': - continue - elif attr.name is 'optParameters': - cls._optParameters = attr.object - else: - log.debug("How did we get here? attr.name = %s" % attr.name) - ''' log.debug("Getting options for test")
if self.localOptions: @@ -408,4 +449,3 @@ class NetTestCase(NetTestAdaptor):
def __repr__(self): return "<%s inputs=%s>" % (self.__class__, self.inputs) - diff --git a/ooni/runner.py b/ooni/runner.py index a7973dc..f6db105 100644 --- a/ooni/runner.py +++ b/ooni/runner.py @@ -25,6 +25,13 @@ from ooni.utils import log, date from ooni.utils.legacy import LegacyOONITest from ooni.utils.legacy import start_legacy_test, adapt_legacy_test
+ +def isTemplate(obj): + origin = obj.__module__ + if origin.find('templates') >= 0: + return True + return False + def isLegacyTest(obj): """ Returns True if the test in question is written using the OONITest legacy @@ -36,48 +43,6 @@ def isLegacyTest(obj): except TypeError: return False
-def processTest(obj, config): - """ - Process the parameters and :class:`twisted.python.usage.Options` of a - :class:`ooni.nettest.Nettest`. - - :param obj: - An uninstantiated old test, which should be a subclass of - :class:`ooni.plugoo.tests.OONITest`. - :param config: - A configured and instantiated :class:`twisted.python.usage.Options` - class. - """ - - input_file = obj.inputFile - if obj.requiresRoot: - if os.getuid() != 0: - raise Exception("This test requires root to run") - - if obj.optParameters or input_file: - if not obj.optParameters: - obj.optParameters = [] - - if input_file: - obj.optParameters.append(input_file) - - class Options(usage.Options): - optParameters = obj.optParameters - - options = Options() - options.parseOptions(config['subArgs']) - obj.localOptions = options - - if input_file: - obj.inputFile = options[input_file[0]] - try: - tmp_obj = obj() - tmp_obj.getOptions() - except usage.UsageError: - options.opt_help() - - return obj - def findTestClassesFromConfig(config): """ Takes as input the command line config parameters and returns the test @@ -98,24 +63,32 @@ def findTestClassesFromConfig(config): module = filenameToModule(filename) for name, val in inspect.getmembers(module): if isTestCase(val): - log.debug("Detected TestCase %s" % val) - classes.append(val) + if val != NetTestCase and not isTemplate(val): + log.debug("findTestClassesFromConfig: detected %s" + % val.__name__) + classes.append(val) elif isLegacyTest(val): log.debug("Detected Legacy Test %s" % val) classes.append(adapt_legacy_test(val, config)) return classes
-def makeTestCases(klass, tests, method_prefix): +def makeTestCases(klass, tests, method_prefix=None): """ Takes a class some tests and returns the test cases. method_prefix is how the test case functions should be prefixed with. """ + if not method_prefix: + method_prefix = 'test' + cases = [] for test in tests: - cases.append(klass(method_prefix+test)) + log.debug("makeTestCases: making test case for %s" % test) + method_name = str(method_prefix)+str(test) + log.debug("makeTestCases: using methodName=%s" % method_name) + cases.append(klass(methodName=method_name)) return cases
-def processTestOptions(cls, config): +def getTestOptions(cls, subargs): """ Process the parameters and :class:`twisted.python.usage.Options` of a :class:`ooni.nettest.Nettest`. @@ -126,48 +99,16 @@ def processTestOptions(cls, config): A configured and instantiated :class:`twisted.python.usage.Options` class. """ - #if cls.optParameters or cls.inputFile: - if not cls.optParameters: - cls.optParameters = [] - - if cls.inputFile: - cls.optParameters.append(cls.inputFile) - - log.debug("CLS IS %s" % cls) - log.debug("CLS OPTPARAM IS %s" % cls.optParameters) - - #if not hasattr(cls, subCommands): - # cls.subCommands = [] - - if not cls.subCommands: - cls.subCommands = [] - - class Options(usage.Options): - optParameters = cls.optParameters - parseArgs = lambda a: cls.subCommands.append(a) - - opts = Options() - opts.parseOptions(config['subArgs']) - cls.localOptions = opts + if cls.requiresRoot: + if os.getuid() != 0: + raise Exception("This test requires root to run")
- if cls.inputFile: - cls.inputFile = opts[cls.inputFile[0]] - """ try: - log.debug("%s: trying %s.localoptions.getOptions()..." - % (__name__, cls.name)) - try: - assert hasattr(cls, 'getOptions') - except AssertionError, ae: - options = opts.opt_help() - raise Exception, "Cannot find %s.getOptions()" % cls.name - else: - options = cls.getOptions() - except usage.UsageError: - options = opts.opt_help() - else: - """ - return cls.localOptions + cls.buildOptions(subargs) + except Exception, e: + log.err(e) + + return cls.local_options
def loadTestsAndOptions(classes, config): """ @@ -184,15 +125,14 @@ def loadTestsAndOptions(classes, config):
for klass in classes: if isinstance(klass, DEPRECATED): - #not issubclass(klass, TestCase): try: cases, opts = processLegacyTest(klass, config) if cases: - log.debug("Processing cases: %s" % str(cases)) + log.debug("loadTestsAndOptions: processing cases %s" + % str(cases)) return [], [] test_cases.append(cases) - except Exception, e: - log.err(e) + except Exception, e: log.err(e) else: try: opts = klass.local_options @@ -214,45 +154,37 @@ def loadTestsAndOptions(classes, config):
def processNetTest(klass, config, method_prefix): try: - log.debug("Processing cases and options for OONI %s test" - % (klass.name if hasattr(klass, 'name') else 'Network Test')) + klass.setUpClass() + except Exception, e: + log.err(e) + + subargs_from_config = config['subArgs'] + log.debug("processNetTest: received subargs from config: %s" + % str(subargs_from_config)) + try: + opts = getTestOptions(klass, subargs_from_config) + except Exception, e: + opts = [] + log.err(e)
+ try: + log.debug("processNetTest: processing cases for %s" + % (klass.name if hasattr(klass, 'name') else 'Network Test')) tests = reflect.prefixedMethodNames(klass, method_prefix) + except Exception, e: + cases = [] + opts = [] + log.err(e) + else: if tests: cases = makeTestCases(klass, tests, method_prefix) - log.debug("loadTestsAndOptions(): test %s found cases=%s"% (tests, cases)) - try: - k = klass() - opts = processTestOptions(k, config) - except Exception, e: - opts = [] - log.err(e) + log.debug("processNetTest: test %s found cases %s" + % (tests, cases)) else: cases = [] - except Exception, e: - log.err(e)
return cases, opts
-''' - if hasattr(klass, 'optParameters') or hasattr(klass, 'inputFile'): - try: - opts = processTestOptions(klass, config) - except: - opts = [] - finally: - try: - k = klass() - inputs = k._getInputs() - except Exception, e: - inputs = [] - log.err(e) - else: - if opts and len(inputs) != 0: - opts.append(['inputs', '', inputs, "cmdline inputs"]) - log.debug("loadTestsAndOptions(): inputs=%s" % inputs) -''' - def processLegacyTest(klass, config): log.msg("Processing cases and options for legacy test %s" % ( klass.shortName if hasattr(klass, shortName) else 'oonitest' )) @@ -277,22 +209,19 @@ def processLegacyTest(klass, config): opts = {}
elif hasattr(klass, local_options): ## we've been initialized already - log.debug("%s.local_options found" % klass) + log.debug("processLegacyTest: %s.local_options found" % str(klass)) try: - assert klass.local_options is not None opts = klass.local_options - except AttributeError, ae: - opts = {}; log.err(ae) + except AttributeError, ae: opts = {}; log.err(ae) + log.debug("processLegacyTest: opts set to %s" % str(opts))
try: cases = start_legacy_test(klass) ## XXX we need to get these results into the reporter if cases: + log.debug("processLegacyTest: found cases: %s" % str(cases)) return [], [] - except Exception, e: - cases = []; log.err(e) - finally: - log.debug(str(cases)) + except Exception, e: cases = []; log.err(e)
return cases, opts
diff --git a/ooni/templates/scapyt.py b/ooni/templates/scapyt.py index f71ab57..1b19dbf 100644 --- a/ooni/templates/scapyt.py +++ b/ooni/templates/scapyt.py @@ -32,7 +32,7 @@ class ScapyTest(NetTestCase): receive = True timeout = 1 pcapfile = None - input = IP()/TCP() + packet = IP()/TCP() reactor = None def setUp(self): if not self.reactor: @@ -56,5 +56,5 @@ class ScapyTest(NetTestCase): """ Override this method to build scapy packets. """ - return self.input + return self.packet
tor-commits@lists.torproject.org