Beispiel #1
0
    def test_abstract_extractor_readableconfig(self):
        """ Test human-readable extractor config string output """
        config = 'key.val'
        extractor = validators.parse_extractor('jsonpath_mini', config)
        expected_string = 'Extractor Type: jsonpath_mini,  Query: "key.val", Templated?: False'
        self.assertEqual(expected_string, extractor.get_readable_config())

        # Check empty context & args uses okay
        context = Context()
        self.assertEqual(expected_string, extractor.get_readable_config(context=context))
        context.bind_variable('foo', 'bar')
        self.assertEqual(expected_string, extractor.get_readable_config(context=context))
        extractor.args = dict()
        self.assertEqual(expected_string, extractor.get_readable_config(context=context))

        # Check args output is handled correctly
        extractor.args = {'caseSensitive': True}
        self.assertEqual(expected_string+", Args: "+str(extractor.args), extractor.get_readable_config(context=context))

        # Check template handling is okay
        config = {'template': 'key.$templated'}
        context.bind_variable('templated', 'val')
        extractor = validators.parse_extractor('jsonpath_mini', config)
        expected_string = 'Extractor Type: jsonpath_mini,  Query: "key.val", Templated?: True'
        self.assertEqual(expected_string, extractor.get_readable_config(context=context))
Beispiel #2
0
    def test_raw_body_extractor(self):
        query = ''
        extractor = validators.parse_extractor('raw_body', None)
        extractor = validators.parse_extractor('raw_body', query)
        self.assertTrue(isinstance(extractor, validators.RawBodyExtractor))
        self.assertTrue(extractor.is_body_extractor)
        self.assertFalse(extractor.is_header_extractor)

        bod = 'j1j21io312j3'
        val = extractor.extract(body=bod, headers='')
        self.assertEqual(bod, val)
Beispiel #3
0
    def test_raw_body_extractor(self):
        query = ''
        extractor = validators.parse_extractor('raw_body', None)
        extractor = validators.parse_extractor('raw_body', query)
        self.assertTrue(isinstance(extractor, validators.RawBodyExtractor))
        self.assertTrue(extractor.is_body_extractor)
        self.assertFalse(extractor.is_header_extractor)

        bod = 'j1j21io312j3'
        val = extractor.extract(body=bod, headers='')
        self.assertEqual(bod, val)
Beispiel #4
0
 def test_parse_extractor(self):
     """ Test parsing an extractor using the registry """
     config = 'key.val'
     myjson = '{"key": {"val": 3}}'
     extractor = validators.parse_extractor('jsonpath_mini', config)
     self.assertTrue(isinstance(extractor, validators.AbstractExtractor))
     self.assertEqual(3, extractor.extract(body=myjson))
Beispiel #5
0
 def test_parse_header_extractor(self):
     query = 'content-type'
     extractor = validators.parse_extractor('header', query)
     self.assertTrue(isinstance(extractor, validators.HeaderExtractor))
     self.assertTrue(extractor.is_header_extractor)
     self.assertFalse(extractor.is_body_extractor)
Beispiel #6
0
    def parse_test(cls, base_url, node, input_test = None, test_path=None):
        """ Create or modify a test, input_test, using configuration in node, and base_url
        If no input_test is given, creates a new one

        Test_path gives path to test file, used for setting working directory in setting up input bodies

        Uses explicitly specified elements from the test input structure
        to make life *extra* fun, we need to handle list <-- > dict transformations.

        This is to say: list(dict(),dict()) or dict(key,value) -->  dict() for some elements

        Accepted structure must be a single dictionary of key-value pairs for test configuration """

        mytest = input_test
        if not mytest:
            mytest = Test()

        node = lowercase_keys(flatten_dictionaries(node)) #Clean up for easy parsing

        #Copy/convert input elements into appropriate form for a test object
        for configelement, configvalue in node.items():
            #Configure test using configuration elements
            if configelement == u'url':
                temp = configvalue
                if isinstance(configvalue, dict):
                    # Template is used for URL
                    val = lowercase_keys(configvalue)[u'template']
                    assert isinstance(val,str) or isinstance(val,unicode) or isinstance(val,int)
                    url = base_url + unicode(val,'UTF-8').encode('ascii','ignore')
                    mytest.set_url(url, isTemplate=True)
                else:
                    assert isinstance(configvalue,str) or isinstance(configvalue,unicode) or isinstance(configvalue,int)
                    mytest.url = base_url + unicode(configvalue,'UTF-8').encode('ascii','ignore')
            elif configelement == u'auth_username':
                assert isinstance(configvalue,str) or isinstance(configvalue,unicode)
                mytest.auth_username = unicode(configvalue,'UTF-8').encode('ascii','ignore')
            elif configelement == u'auth_password':
                assert isinstance(configvalue,str) or isinstance(configvalue,unicode)
                mytest.auth_password = unicode(configvalue,'UTF-8').encode('ascii','ignore')
            elif configelement == u'method': #Http method, converted to uppercase string
                var = unicode(configvalue,'UTF-8').upper()
                assert var in HTTP_METHODS
                mytest.method = var
            elif configelement == u'group': #Test group
                assert isinstance(configvalue,str) or isinstance(configvalue,unicode) or isinstance(configvalue,int)
                mytest.group = unicode(configvalue,'UTF-8')
            elif configelement == u'name': #Test name
                assert isinstance(configvalue,str) or isinstance(configvalue,unicode) or isinstance(configvalue,int)
                mytest.name = unicode(configvalue,'UTF-8')
            elif configelement == u'extract_binds':
                # Add a list of extractors, of format:
                # {variable_name: {extractor_type: extractor_config}, ... }
                binds = flatten_dictionaries(configvalue)
                if mytest.extract_binds is None:
                    mytest.extract_binds = dict()

                for variable_name, extractor in binds.items():
                    if not isinstance(extractor, dict) or len(extractor) == 0:
                        raise TypeError("Extractors must be defined as maps of extractorType:{configs} with 1 entry")
                    if len(extractor) > 1:
                        raise ValueError("Cannot define multiple extractors for given variable name")
                    extractor_type, extractor_config = extractor.items()[0]
                    extractor = validators.parse_extractor(extractor_type, extractor_config)
                    mytest.extract_binds[variable_name] = extractor

            elif configelement == u'validators':
                # Add a list of validators
                if not isinstance(configvalue, list):
                    raise Exception('Misconfigured validator section, must be a list of validators')
                if mytest.validators is None:
                    mytest.validators = list()

                # create validator and add to list of validators
                for var in configvalue:
                    if not isinstance(var, dict):
                        raise TypeError("Validators must be defined as validatorType:{configs} ")
                    for validator_type, validator_config in var.items():
                        validator = validators.parse_validator(validator_type, validator_config)
                        mytest.validators.append(validator)

            elif configelement == u'body': #Read request body, as a ContentHandler
                # Note: os.path.expandirs removed
                mytest.body = ContentHandler.parse_content(configvalue)
            elif configelement == 'headers': #HTTP headers to use, flattened to a single string-string dictionary
                mytest.headers
                configvalue = flatten_dictionaries(configvalue)

                if isinstance(configvalue, dict):
                    templates = filter(lambda x: str(x[0]).lower() == 'template', configvalue.items())
                else:
                    templates = None

                if templates:
                    # Should have single entry in dictionary keys
                    mytest.set_headers(templates[0][1], isTemplate=True)
                elif isinstance(configvalue, dict):
                    mytest.headers = configvalue
                else:
                    raise TypeError("Illegal header type: headers must be a dictionary or list of dictionary keys")

            elif configelement == 'expected_status': #List of accepted HTTP response codes, as integers
                expected = list()
                #If item is a single item, convert to integer and make a list of 1
                #Otherwise, assume item is a list and convert to a list of integers
                if isinstance(configvalue,list):
                    for item in configvalue:
                        expected.append(int(item))
                else:
                    expected.append(int(configvalue))
                mytest.expected_status = expected
            elif configelement == 'variable_binds':
                mytest.variable_binds = flatten_dictionaries(configvalue)
            elif configelement == 'generator_binds':
                output = flatten_dictionaries(configvalue)
                output2 = dict()
                for key, value in output.items():
                    output2[str(key)] = str(value)
                mytest.generator_binds = output2
            elif configelement == 'stop_on_failure':
                mytest.stop_on_failure = safe_to_bool(configvalue)

        #Next, we adjust defaults to be reasonable, if the user does not specify them

        #For non-GET requests, accept additional response codes indicating success
        # (but only if not expected statuses are not explicitly specified)
        #  this is per HTTP spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
        if 'expected_status' not in node.keys():
            if mytest.method == 'POST':
                mytest.expected_status = [200,201,204]
            elif mytest.method == 'PUT':
                mytest.expected_status = [200,201,204]
            elif mytest.method == 'DELETE':
                mytest.expected_status = [200,202,204]
        return mytest
Beispiel #7
0
    def parse_workflow(cls, base_url,node,input_workflow=None, test_path=None , global_gen=None):
        
        myworkflow = input_workflow
        if not myworkflow:
            myworkflow = WorkFlow()

        # Clean up for easy parsing
        node = lowercase_keys(flatten_dictionaries(node))
       


        # Simple table of variable name, coerce function, and optionally special store function
        CONFIG_ELEMENTS = {
            # Simple variables
            u'name': [coerce_string_to_ascii],
            u'tests': [coerce_list_of_strings],
            u'body': [ContentHandler.parse_content],
            u'group': [coerce_to_string] # Test group name
           
        }

        def use_config_parser(configobject, configelement, configvalue):
            """ Try to use parser bindings to find an option for parsing and storing config element
                :configobject: Object to store configuration
                :configelement: Configuratione element name
                :configvalue: Value to use to set configuration
                :returns: True if found match for config element, False if didn't
            """
            
            myparsing = CONFIG_ELEMENTS.get(configelement)
            if myparsing:
                converted = myparsing[0](configvalue)
                setattr(configobject, configelement, converted)
                return True
            return False
       
        """Fuction mapping"""
        functions_case={'setvalue_body':[WorkFlow.setvalue_body],'setvalue_headers':[WorkFlow.setvalue_headers],'setvalue_auth_password':[WorkFlow.setvalue_auth_password],'setvalue_auth_username':        				 [WorkFlow.setvalue_auth_username],'setvalue_url':[WorkFlow.setvalue_url],'setvalue_method':[WorkFlow.setvalue_method],'setvalue_expected_status':[WorkFlow.setvalue_expected_status]}
        
        # Copy/convert input elements into appropriate form for a test object
        for configelement, configvalue in node.items():
            
            if use_config_parser(myworkflow, configelement, configvalue):
                continue
          
            elif configelement == u'name':
                myworkflow.name = str(configvalue)
         
           
            elif configelement == u'extract_binds':
                # Add a list of extractors, of format:
                # {variable_name: {extractor_type: extractor_config}, ... }
                binds = flatten_dictionaries(configvalue)
                if myworkflow.extract_binds is None:
                    myworkflow.extract_binds = dict()
                
                for variable_name, extractor in binds.items():
                    if not isinstance(extractor, dict) or len(extractor) == 0:
                        raise TypeError(
                            "Extractors must be defined as maps of extractorType:{configs} with 1 entry")
                    if len(extractor) > 1:
                        raise ValueError(
                            "Cannot define multiple extractors for given variable name")

                    # Safe because length can only be 1
                    for extractor_type, extractor_config in extractor.items():
                        myworkflow.extract_binds[variable_name] = validators.parse_extractor(extractor_type, extractor_config)
                        mytest.variable_binds= validators.parse_extractor(extractor_type, extractor_config)
            
           

            elif configelement == u'params':
                params_flag=1
                dict_params=dict()
                dict_templated_params=dict()
                for p in range(len(configvalue)):
                  
                    for key1,value1 in configvalue[p].items():
                        list_params=list()
                        list_templated_params=list()
                        for q in range(len(value1)):                            
                            for key2,value2 in value1[q].items():
				
                                if(key2 == "name"):
        			    raise Exception("Cannot overwrite name attribute of original test case")

    				if(key2 == "group"):
        			    raise Exception("Cannot overwrite group attribute of original test case")	               

                                if(key2=="body"):
                                    assert isinstance(value2, dict)
                                    myparsing = CONFIG_ELEMENTS.get(key2)
                                    converted = myparsing[0](value2)
                                    myworkflow.setvalue_body(converted,list_params)
                                    continue

 				if(key2=="generator_binds"):
 				    assert isinstance(value2, dict)
		                    atrr_dict=dict()
                                    atrr_dict[key2]=value2
    		                    list_params.append(atrr_dict)
                                    continue

				if(key2=="delay" or key2 == "retries" or key2 == "repeat"):
                                    assert isinstance(value2, int)
		                    atrr_dict=dict()
                                    atrr_dict[key2]=value2
    		                    list_params.append(atrr_dict)
                                    continue
                                  
				if(key2=="extract_binds"):
                                   
                                    temp_dict=dict()
		                    atrr_dict=dict()
                                    for index in range(len(value2)):
                                        for variable_name, extractor in value2[index].items():
                                            if not isinstance(extractor, dict) or len(extractor) == 0:
                                                raise TypeError(
                                                            "Extractors must be defined as maps of extractorType:{configs} with 1 entry")
                                            if len(extractor) > 1:
                                                raise ValueError(
                                                             "Cannot define multiple extractors for given variable name")

                                       	    # Safe because length can only be 1
                                            for extractor_type, extractor_config in extractor.items():
                                                temp_dict[variable_name] = validators.parse_extractor(extractor_type, extractor_config)

                                            atrr_dict[key2]=temp_dict
    		                            list_params.append(atrr_dict)
                                            continue                                

                                var_func="setvalue_"+key2

                                if isinstance(value2, dict):
                                    output = flatten_dictionaries(value2)
                                else:
                                    output = value2
                                #output={'template': {'license': {'name': 'randhir', 'properties': '$var22'}}}
		                if isinstance(output, dict):
		                    filterfunc  = lambda x: str(x[0]).lower() == 'template'  # Templated items
		                    templates = [x for x in ifilter(filterfunc, output.items())]#output_items=[('template', {'license': {'name': 'randhir', 'properties': '$var22'}})]
		                else:
		                    templates = None
                                
                                
		                if templates:
                                    list_templated_params.append(key2)
   
                                    if(var_func=='setvalue_auth_username'):    
                                        functions_case[var_func][0](myworkflow,templates[0][1],list_params,isTemplate=True)
                                    if(var_func=='setvalue_auth_password'):    
                                        functions_case[var_func][0](myworkflow,templates[0][1],list_params,isTemplate=True)
                                    if(var_func=='setvalue_headers'):
                                        functions_case[var_func][0](myworkflow,templates[0][1],list_params,isTemplate=True)
				    if(var_func=='setvalue_url'):
                                        temp=urlparse.urljoin(base_url,coerce_to_string(templates[0][1]))
                                        functions_case[var_func][0](myworkflow,temp,list_params,isTemplate=True)
                                    if(var_func=='setvalue_method'):
                                        functions_case[var_func][0](myworkflow,templates[0][1],list_params,isTemplate=True)
                                    if(var_func=='setvalue_expected_status'):
                                        functions_case[var_func][0](myworkflow,templates[0][1],list_params,isTemplate=True)

                                else: 
                                    
                                    if(var_func=='setvalue_auth_username'):    
                                        functions_case[var_func][0](myworkflow,output,list_params)
                                    if(var_func=='setvalue_auth_password'):    
                                        functions_case[var_func][0](myworkflow,output,list_params)
                                    if(var_func=='setvalue_headers'):
                                        functions_case[var_func][0](myworkflow,output,list_params)
				    if(var_func=='setvalue_url'):
                                        temp=urlparse.urljoin(base_url,coerce_to_string(output))
                                        functions_case[var_func][0](myworkflow,temp,list_params)
                                    if(var_func=='setvalue_method'):
                                        functions_case[var_func][0](myworkflow,output,list_params)
                                    if(var_func=='setvalue_expected_status'):
                                        functions_case[var_func][0](myworkflow,output,list_params)


		                
		                
                        dict_params[str(key1)]=list_params
                        dict_templated_params[str(key1)]=list_templated_params
                myworkflow.params=dict_params
                myworkflow.params_templated=dict_templated_params
  
            elif configelement == 'variable_binds':
                myworkflow.variable_binds = flatten_dictionaries(configvalue)
           
        return myworkflow
Beispiel #8
0
    def parse_test(cls, base_url, node, input_test=None, test_path=None):
        """ Create or modify a test, input_test, using configuration in node, and base_url
        If no input_test is given, creates a new one

        Test_path gives path to test file, used for setting working directory in setting up input bodies

        Uses explicitly specified elements from the test input structure
        to make life *extra* fun, we need to handle list <-- > dict transformations.

        This is to say: list(dict(),dict()) or dict(key,value) -->  dict() for some elements

        Accepted structure must be a single dictionary of key-value pairs for test configuration """

        mytest = input_test
        if not mytest:
            mytest = Test()

        node = lowercase_keys(
            flatten_dictionaries(node))  #Clean up for easy parsing

        #Copy/convert input elements into appropriate form for a test object
        for configelement, configvalue in node.items():
            #Configure test using configuration elements
            if configelement == u'url':
                temp = configvalue
                if isinstance(configvalue, dict):
                    # Template is used for URL
                    val = lowercase_keys(configvalue)[u'template']
                    assert isinstance(val, str) or isinstance(
                        val, unicode) or isinstance(val, int)
                    url = base_url + unicode(val, 'UTF-8').encode(
                        'ascii', 'ignore')
                    mytest.set_url(url, isTemplate=True)
                else:
                    assert isinstance(configvalue, str) or isinstance(
                        configvalue, unicode) or isinstance(configvalue, int)
                    mytest.url = base_url + unicode(
                        configvalue, 'UTF-8').encode('ascii', 'ignore')
            elif configelement == u'auth_username':
                assert isinstance(configvalue, str) or isinstance(
                    configvalue, unicode)
                mytest.auth_username = unicode(configvalue, 'UTF-8').encode(
                    'ascii', 'ignore')
            elif configelement == u'auth_password':
                assert isinstance(configvalue, str) or isinstance(
                    configvalue, unicode)
                mytest.auth_password = unicode(configvalue, 'UTF-8').encode(
                    'ascii', 'ignore')
            elif configelement == u'method':  #Http method, converted to uppercase string
                var = unicode(configvalue, 'UTF-8').upper()
                assert var in HTTP_METHODS
                mytest.method = var
            elif configelement == u'group':  #Test group
                assert isinstance(configvalue, str) or isinstance(
                    configvalue, unicode) or isinstance(configvalue, int)
                mytest.group = unicode(configvalue, 'UTF-8')
            elif configelement == u'name':  #Test name
                assert isinstance(configvalue, str) or isinstance(
                    configvalue, unicode) or isinstance(configvalue, int)
                mytest.name = unicode(configvalue, 'UTF-8')
            elif configelement == u'extract_binds':
                # Add a list of extractors, of format:
                # {variable_name: {extractor_type: extractor_config}, ... }
                binds = flatten_dictionaries(configvalue)
                if mytest.extract_binds is None:
                    mytest.extract_binds = dict()

                for variable_name, extractor in binds.items():
                    if not isinstance(extractor, dict) or len(extractor) == 0:
                        raise TypeError(
                            "Extractors must be defined as maps of extractorType:{configs} with 1 entry"
                        )
                    if len(extractor) > 1:
                        raise ValueError(
                            "Cannot define multiple extractors for given variable name"
                        )
                    extractor_type, extractor_config = extractor.items()[0]
                    extractor = validators.parse_extractor(
                        extractor_type, extractor_config)
                    mytest.extract_binds[variable_name] = extractor

            elif configelement == u'validators':
                # Add a list of validators
                if not isinstance(configvalue, list):
                    raise Exception(
                        'Misconfigured validator section, must be a list of validators'
                    )
                if mytest.validators is None:
                    mytest.validators = list()

                # create validator and add to list of validators
                for var in configvalue:
                    if not isinstance(var, dict):
                        raise TypeError(
                            "Validators must be defined as validatorType:{configs} "
                        )
                    for validator_type, validator_config in var.items():
                        validator = validators.parse_validator(
                            validator_type, validator_config)
                        mytest.validators.append(validator)

            elif configelement == u'body':  #Read request body, as a ContentHandler
                # Note: os.path.expandirs removed
                mytest.body = ContentHandler.parse_content(configvalue)
            elif configelement == 'headers':  #HTTP headers to use, flattened to a single string-string dictionary
                mytest.headers
                configvalue = flatten_dictionaries(configvalue)

                if isinstance(configvalue, dict):
                    templates = filter(
                        lambda x: str(x[0]).lower() == 'template',
                        configvalue.items())
                else:
                    templates = None

                if templates:
                    # Should have single entry in dictionary keys
                    mytest.set_headers(templates[0][1], isTemplate=True)
                elif isinstance(configvalue, dict):
                    mytest.headers = configvalue
                else:
                    raise TypeError(
                        "Illegal header type: headers must be a dictionary or list of dictionary keys"
                    )

            elif configelement == 'expected_status':  #List of accepted HTTP response codes, as integers
                expected = list()
                #If item is a single item, convert to integer and make a list of 1
                #Otherwise, assume item is a list and convert to a list of integers
                if isinstance(configvalue, list):
                    for item in configvalue:
                        expected.append(int(item))
                else:
                    expected.append(int(configvalue))
                mytest.expected_status = expected
            elif configelement == 'variable_binds':
                mytest.variable_binds = flatten_dictionaries(configvalue)
            elif configelement == 'generator_binds':
                output = flatten_dictionaries(configvalue)
                output2 = dict()
                for key, value in output.items():
                    output2[str(key)] = str(value)
                mytest.generator_binds = output2
            elif configelement == 'stop_on_failure':
                mytest.stop_on_failure = safe_to_bool(configvalue)

        #Next, we adjust defaults to be reasonable, if the user does not specify them

        #For non-GET requests, accept additional response codes indicating success
        # (but only if not expected statuses are not explicitly specified)
        #  this is per HTTP spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
        if 'expected_status' not in node.keys():
            if mytest.method == 'POST':
                mytest.expected_status = [200, 201, 204]
            elif mytest.method == 'PUT':
                mytest.expected_status = [200, 201, 204]
            elif mytest.method == 'DELETE':
                mytest.expected_status = [200, 202, 204]
        return mytest
Beispiel #9
0
    def parse_test(cls, base_url, node, input_test=None, test_path=None):
        """ Create or modify a test, input_test, using configuration in node, and base_url
        If no input_test is given, creates a new one

        Test_path gives path to test file, used for setting working directory in setting up input bodies

        Uses explicitly specified elements from the test input structure
        to make life *extra* fun, we need to handle list <-- > dict transformations.

        This is to say: list(dict(),dict()) or dict(key,value) -->  dict() for some elements

        Accepted structure must be a single dictionary of key-value pairs for test configuration """
        
        
        mytest = input_test
        if not mytest:
            mytest = Test()

        # Clean up for easy parsing
        node = lowercase_keys(flatten_dictionaries(node))
        


        # Simple table of variable name, coerce function, and optionally special store function
        CONFIG_ELEMENTS = {
            # Simple variables
           # u'auth_username': [coerce_string_to_ascii],
           # u'auth_password': [coerce_string_to_ascii],
           # u'method': [coerce_http_method], # HTTP METHOD
            u'delay': [lambda x: int(x)], # Delay before running
            u'group': [coerce_to_string], # Test group name
            u'name': [coerce_to_string],  # Test name
           # u'expected_status': [coerce_list_of_ints],
            u'delay': [lambda x: int(x)],
            u'stop_on_failure': [safe_to_bool],
            u'retries': [lambda x: int(x)],
            u'depends_on': [coerce_list_of_strings],

            # Templated / special handling
            #u'url': [coerce_templatable, set_templated],  # TODO: special handling for templated content, sigh
            u'body': [ContentHandler.parse_content]
            #u'headers': [],

            # COMPLEX PARSE OPTIONS
            #u'extract_binds':[],  # Context variable-to-extractor output binding
            #u'variable_binds': [],  # Context variable to value binding
            #u'generator_binds': [],  # Context variable to generator output binding
            #u'validators': [],  # Validation functions to run
        }

        def use_config_parser(configobject, configelement, configvalue):
            """ Try to use parser bindings to find an option for parsing and storing config element
                :configobject: Object to store configuration
                :configelement: Configuratione element name
                :configvalue: Value to use to set configuration
                :returns: True if found match for config element, False if didn't
            """
            
            myparsing = CONFIG_ELEMENTS.get(configelement)
            if myparsing:
                converted = myparsing[0](configvalue)
                setattr(configobject, configelement, converted)
                return True
            return False

        # Copy/convert input elements into appropriate form for a test object
        for configelement, configvalue in node.items():
            if use_config_parser(mytest, configelement, configvalue):
                continue
            
            # Configure test using configuration elements
            if configelement == u'url':
                temp = configvalue
                if isinstance(configvalue, dict):
                    # Template is used for URL
                    val = lowercase_keys(configvalue)[u'template']
                    assert isinstance(val, basestring) or isinstance(val, int)
                    url = urlparse.urljoin(base_url, coerce_to_string(val))
                    mytest.set_url(url, isTemplate=True)
                else:
                    assert isinstance(configvalue, basestring) or isinstance(
                        configvalue, int)
                    mytest.url = urlparse.urljoin(base_url, coerce_to_string(configvalue))


            if configelement == u'display_name':
                 temp = configvalue
                 if isinstance(configvalue, dict):
                     # Template is used for Disply Name
                     val = lowercase_keys(configvalue)[u'template']
                     assert isinstance(val, basestring) or isinstance(val, int)
                     mytest.set_display_name(val, isTemplate=True)
                 else:
                     assert isinstance(configvalue, basestring) or isinstance(
                         configvalue, int)
                     mytest.display_name = urlparse.urljoin(base_url, coerce_to_string(configvalue)) 
                    

            if configelement == u'auth_password':
                temp = configvalue
                
                if isinstance(configvalue, basestring):
                    
                    val = lowercase_keys(configvalue)
                    assert isinstance(val, basestring) or isinstance(val, int)
                    
                    mytest.set_auth_password(val)
            
            if configelement == u'auth_username':
                temp = configvalue
                
                if isinstance(configvalue, basestring):
                    val = lowercase_keys(configvalue)
                    assert isinstance(val, basestring) or isinstance(val, int)
                    
                    mytest.set_auth_username(val)
            

            if configelement == u'method':
                val = configvalue
                
                if isinstance(configvalue, basestring) or isinstance(val, list):
                    assert isinstance(val, basestring) or isinstance(val, list)
                    mytest.set_method(val)

            
            if configelement == u'expected_status':
                val = configvalue               
                assert isinstance(val, basestring) or isinstance(val, list)
                mytest.set_expected_status(val)


            if configelement == u'extract_binds':
                # Add a list of extractors, of format:
                # {variable_name: {extractor_type: extractor_config}, ... }
                
                binds = flatten_dictionaries(configvalue)
                if mytest.extract_binds is None:
                    mytest.extract_binds = dict()
 		
                for variable_name, extractor in binds.items():
                    if not isinstance(extractor, dict) or len(extractor) == 0:
                        raise TypeError(
                            "Extractors must be defined as maps of extractorType:{configs} with 1 entry")
                    if len(extractor) > 1:
                        raise ValueError(
                            "Cannot define multiple extractors for given variable name")

                    # Safe because length can only be 1
                    for extractor_type, extractor_config in extractor.items():
                        
                        mytest.extract_binds[variable_name] = validators.parse_extractor(extractor_type, extractor_config)
            

            if configelement == u'validators':
                # Add a list of validators
                if not isinstance(configvalue, list):
                    raise Exception(
                        'Misconfigured validator section, must be a list of validators')
                if mytest.validators is None:
                    mytest.validators = list()

                # create validator and add to list iof validators
                for var in configvalue:
                    if not isinstance(var, dict):
                        raise TypeError(
                            "Validators must be defined as validatorType:{configs} ")
                    for validator_type, validator_config in var.items():
                        validator = validators.parse_validator(
                            validator_type, validator_config)
                        mytest.validators.append(validator)

            if configelement == 'headers':  # HTTP headers to use, flattened to a single string-string dictionary
                mytest.headers
                configvalue = flatten_dictionaries(configvalue)
                
                if isinstance(configvalue, dict):
                    filterfunc  = lambda x: str(x[0]).lower() == 'template'  # Templated items
                    templates = [x for x in ifilter(filterfunc, configvalue.items())]
                else:
                    templates = None
                
                if templates:
                    
                    # Should have single entry in dictionary keys
                    mytest.set_headers(templates[0][1], isTemplate=True)
                elif isinstance(configvalue, dict):
                   
                    mytest.headers = configvalue
                else:
                    raise TypeError(
                        "Illegal header type: headers must be a dictionary or list of dictionary keys")
            if configelement == 'variable_binds':
                mytest.variable_binds = flatten_dictionaries(configvalue)
            if configelement == 'generator_binds':
                
                if(True):
                    output = flatten_dictionaries(configvalue)
                    output2 = dict()
                    for key, value in output.items():
                        output2[str(key)] = str(value)
                    mytest.generator_binds = output2
            if configelement.startswith('curl_option_'):
                curlopt = configelement[12:].upper()
                if hasattr(BASECURL, curlopt):
                    if not mytest.curl_options:
                        mytest.curl_options = dict()
                    mytest.curl_options[curlopt] = configvalue
                else:
                    raise ValueError(
                        "Illegal curl option: {0}".format(curlopt))

        # For non-GET requests, accept additional response codes indicating success
        # (but only if not expected statuses are not explicitly specified)
        # this is per HTTP spec:
        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
        
        if 'expected_status' not in node.keys():
            if mytest.method == 'POST':
                mytest.expected_status = [200, 201, 204]
            elif mytest.method == 'PUT':
                mytest.expected_status = [200, 201, 204]
            elif mytest.method == 'DELETE':
                mytest.expected_status = [200, 202, 204]
            # Fallthrough default is simply [200]
        return mytest
Beispiel #10
0
    def parse_workflow(cls,
                       base_url,
                       node,
                       input_workflow=None,
                       test_path=None,
                       global_gen=None):

        myworkflow = input_workflow
        if not myworkflow:
            myworkflow = WorkFlow()

        # Clean up for easy parsing
        node = lowercase_keys(flatten_dictionaries(node))

        # Simple table of variable name, coerce function, and optionally special store function
        CONFIG_ELEMENTS = {
            # Simple variables
            u'name': [coerce_string_to_ascii],
            u'tests': [coerce_list_of_strings],
            u'body': [ContentHandler.parse_content],
            u'group': [coerce_to_string]  # Test group name
        }

        def use_config_parser(configobject, configelement, configvalue):
            """ Try to use parser bindings to find an option for parsing and storing config element
                :configobject: Object to store configuration
                :configelement: Configuratione element name
                :configvalue: Value to use to set configuration
                :returns: True if found match for config element, False if didn't
            """

            myparsing = CONFIG_ELEMENTS.get(configelement)
            if myparsing:
                converted = myparsing[0](configvalue)
                setattr(configobject, configelement, converted)
                return True
            return False

        """Fuction mapping"""
        functions_case = {
            'setvalue_body': [WorkFlow.setvalue_body],
            'setvalue_headers': [WorkFlow.setvalue_headers],
            'setvalue_auth_password': [WorkFlow.setvalue_auth_password],
            'setvalue_auth_username': [WorkFlow.setvalue_auth_username],
            'setvalue_url': [WorkFlow.setvalue_url],
            'setvalue_method': [WorkFlow.setvalue_method],
            'setvalue_expected_status': [WorkFlow.setvalue_expected_status]
        }

        # Copy/convert input elements into appropriate form for a test object
        for configelement, configvalue in node.items():

            if use_config_parser(myworkflow, configelement, configvalue):
                continue

            elif configelement == u'name':
                myworkflow.name = str(configvalue)

            elif configelement == u'extract_binds':
                # Add a list of extractors, of format:
                # {variable_name: {extractor_type: extractor_config}, ... }
                binds = flatten_dictionaries(configvalue)
                if myworkflow.extract_binds is None:
                    myworkflow.extract_binds = dict()

                for variable_name, extractor in binds.items():
                    if not isinstance(extractor, dict) or len(extractor) == 0:
                        raise TypeError(
                            "Extractors must be defined as maps of extractorType:{configs} with 1 entry"
                        )
                    if len(extractor) > 1:
                        raise ValueError(
                            "Cannot define multiple extractors for given variable name"
                        )

                    # Safe because length can only be 1
                    for extractor_type, extractor_config in extractor.items():
                        myworkflow.extract_binds[
                            variable_name] = validators.parse_extractor(
                                extractor_type, extractor_config)
                        mytest.variable_binds = validators.parse_extractor(
                            extractor_type, extractor_config)

            elif configelement == u'params':
                params_flag = 1
                dict_params = dict()
                dict_templated_params = dict()
                for p in range(len(configvalue)):

                    for key1, value1 in configvalue[p].items():
                        list_params = list()
                        list_templated_params = list()
                        for q in range(len(value1)):
                            for key2, value2 in value1[q].items():

                                if (key2 == "name"):
                                    raise Exception(
                                        "Cannot overwrite name attribute of original test case"
                                    )

                                if (key2 == "group"):
                                    raise Exception(
                                        "Cannot overwrite group attribute of original test case"
                                    )

                                if (key2 == "body"):
                                    assert isinstance(value2, dict)
                                    myparsing = CONFIG_ELEMENTS.get(key2)
                                    converted = myparsing[0](value2)
                                    myworkflow.setvalue_body(
                                        converted, list_params)
                                    continue

                                if (key2 == "generator_binds"):
                                    assert isinstance(value2, dict)
                                    atrr_dict = dict()
                                    atrr_dict[key2] = value2
                                    list_params.append(atrr_dict)
                                    continue

                                if (key2 == "delay" or key2 == "retries"
                                        or key2 == "repeat"):
                                    assert isinstance(value2, int)
                                    atrr_dict = dict()
                                    atrr_dict[key2] = value2
                                    list_params.append(atrr_dict)
                                    continue

                                if (key2 == "extract_binds"):

                                    temp_dict = dict()
                                    atrr_dict = dict()
                                    for index in range(len(value2)):
                                        for variable_name, extractor in value2[
                                                index].items():
                                            if not isinstance(
                                                    extractor, dict) or len(
                                                        extractor) == 0:
                                                raise TypeError(
                                                    "Extractors must be defined as maps of extractorType:{configs} with 1 entry"
                                                )
                                            if len(extractor) > 1:
                                                raise ValueError(
                                                    "Cannot define multiple extractors for given variable name"
                                                )

                                    # Safe because length can only be 1
                                            for extractor_type, extractor_config in extractor.items(
                                            ):
                                                temp_dict[
                                                    variable_name] = validators.parse_extractor(
                                                        extractor_type,
                                                        extractor_config)

                                            atrr_dict[key2] = temp_dict
                                            list_params.append(atrr_dict)
                                            continue

                                var_func = "setvalue_" + key2

                                if isinstance(value2, dict):
                                    output = flatten_dictionaries(value2)
                                else:
                                    output = value2
                                #output={'template': {'license': {'name': 'randhir', 'properties': '$var22'}}}
                                if isinstance(output, dict):
                                    filterfunc = lambda x: str(x[0]).lower(
                                    ) == 'template'  # Templated items
                                    templates = [
                                        x for x in ifilter(
                                            filterfunc, output.items())
                                    ]  #output_items=[('template', {'license': {'name': 'randhir', 'properties': '$var22'}})]
                                else:
                                    templates = None

                                if templates:
                                    list_templated_params.append(key2)

                                    if (var_func == 'setvalue_auth_username'):
                                        functions_case[var_func][0](
                                            myworkflow,
                                            templates[0][1],
                                            list_params,
                                            isTemplate=True)
                                    if (var_func == 'setvalue_auth_password'):
                                        functions_case[var_func][0](
                                            myworkflow,
                                            templates[0][1],
                                            list_params,
                                            isTemplate=True)
                                    if (var_func == 'setvalue_headers'):
                                        functions_case[var_func][0](
                                            myworkflow,
                                            templates[0][1],
                                            list_params,
                                            isTemplate=True)
                                    if (var_func == 'setvalue_url'):
                                        temp = urlparse.urljoin(
                                            base_url,
                                            coerce_to_string(templates[0][1]))
                                        functions_case[var_func][0](
                                            myworkflow,
                                            temp,
                                            list_params,
                                            isTemplate=True)
                                    if (var_func == 'setvalue_method'):
                                        functions_case[var_func][0](
                                            myworkflow,
                                            templates[0][1],
                                            list_params,
                                            isTemplate=True)
                                    if (var_func == 'setvalue_expected_status'
                                        ):
                                        functions_case[var_func][0](
                                            myworkflow,
                                            templates[0][1],
                                            list_params,
                                            isTemplate=True)

                                else:

                                    if (var_func == 'setvalue_auth_username'):
                                        functions_case[var_func][0](
                                            myworkflow, output, list_params)
                                    if (var_func == 'setvalue_auth_password'):
                                        functions_case[var_func][0](
                                            myworkflow, output, list_params)
                                    if (var_func == 'setvalue_headers'):
                                        functions_case[var_func][0](
                                            myworkflow, output, list_params)
                                    if (var_func == 'setvalue_url'):
                                        temp = urlparse.urljoin(
                                            base_url, coerce_to_string(output))
                                        functions_case[var_func][0](
                                            myworkflow, temp, list_params)
                                    if (var_func == 'setvalue_method'):
                                        functions_case[var_func][0](
                                            myworkflow, output, list_params)
                                    if (var_func == 'setvalue_expected_status'
                                        ):
                                        functions_case[var_func][0](
                                            myworkflow, output, list_params)

                        dict_params[str(key1)] = list_params
                        dict_templated_params[str(
                            key1)] = list_templated_params
                myworkflow.params = dict_params
                myworkflow.params_templated = dict_templated_params

            elif configelement == 'variable_binds':
                myworkflow.variable_binds = flatten_dictionaries(configvalue)

        return myworkflow
Beispiel #11
0
    def parse_test(cls, base_url, node, input_test=None, test_path=None):
        """ Create or modify a test, input_test, using configuration in node, and base_url
        If no input_test is given, creates a new one

        Test_path gives path to test file, used for setting working directory in setting up input bodies

        Uses explicitly specified elements from the test input structure
        to make life *extra* fun, we need to handle list <-- > dict transformations.

        This is to say: list(dict(),dict()) or dict(key,value) -->  dict() for some elements

        Accepted structure must be a single dictionary of key-value pairs for test configuration """

        mytest = input_test
        if not mytest:
            mytest = Test()

        # Clean up for easy parsing
        node = lowercase_keys(flatten_dictionaries(node))

        # Simple table of variable name, coerce function, and optionally special store function
        CONFIG_ELEMENTS = {
            # Simple variables
            # u'auth_username': [coerce_string_to_ascii],
            # u'auth_password': [coerce_string_to_ascii],
            # u'method': [coerce_http_method], # HTTP METHOD
            u'delay': [lambda x: int(x)],  # Delay before running
            u'group': [coerce_to_string],  # Test group name
            u'name': [coerce_to_string],  # Test name
            # u'expected_status': [coerce_list_of_ints],
            u'delay': [lambda x: int(x)],
            u'stop_on_failure': [safe_to_bool],
            u'retries': [lambda x: int(x)],
            u'depends_on': [coerce_list_of_strings],

            # Templated / special handling
            #u'url': [coerce_templatable, set_templated],  # TODO: special handling for templated content, sigh
            u'body': [ContentHandler.parse_content]
            #u'headers': [],

            # COMPLEX PARSE OPTIONS
            #u'extract_binds':[],  # Context variable-to-extractor output binding
            #u'variable_binds': [],  # Context variable to value binding
            #u'generator_binds': [],  # Context variable to generator output binding
            #u'validators': [],  # Validation functions to run
        }

        def use_config_parser(configobject, configelement, configvalue):
            """ Try to use parser bindings to find an option for parsing and storing config element
                :configobject: Object to store configuration
                :configelement: Configuratione element name
                :configvalue: Value to use to set configuration
                :returns: True if found match for config element, False if didn't
            """

            myparsing = CONFIG_ELEMENTS.get(configelement)
            if myparsing:
                converted = myparsing[0](configvalue)
                setattr(configobject, configelement, converted)
                return True
            return False

        # Copy/convert input elements into appropriate form for a test object
        for configelement, configvalue in node.items():
            if use_config_parser(mytest, configelement, configvalue):
                continue

            # Configure test using configuration elements
            if configelement == u'url':
                temp = configvalue
                if isinstance(configvalue, dict):
                    # Template is used for URL
                    val = lowercase_keys(configvalue)[u'template']
                    assert isinstance(val, basestring) or isinstance(val, int)
                    url = urlparse.urljoin(base_url, coerce_to_string(val))
                    mytest.set_url(url, isTemplate=True)
                else:
                    assert isinstance(configvalue, basestring) or isinstance(
                        configvalue, int)
                    mytest.url = urlparse.urljoin(
                        base_url, coerce_to_string(configvalue))

            if configelement == u'display_name':
                temp = configvalue
                if isinstance(configvalue, dict):
                    # Template is used for Disply Name
                    val = lowercase_keys(configvalue)[u'template']
                    assert isinstance(val, basestring) or isinstance(val, int)
                    mytest.set_display_name(val, isTemplate=True)
                else:
                    assert isinstance(configvalue, basestring) or isinstance(
                        configvalue, int)
                    mytest.display_name = urlparse.urljoin(
                        base_url, coerce_to_string(configvalue))

            if configelement == u'auth_password':
                temp = configvalue

                if isinstance(configvalue, basestring):

                    val = lowercase_keys(configvalue)
                    assert isinstance(val, basestring) or isinstance(val, int)

                    mytest.set_auth_password(val)

            if configelement == u'auth_username':
                temp = configvalue

                if isinstance(configvalue, basestring):
                    val = lowercase_keys(configvalue)
                    assert isinstance(val, basestring) or isinstance(val, int)

                    mytest.set_auth_username(val)

            if configelement == u'method':
                val = configvalue

                if isinstance(configvalue, basestring) or isinstance(
                        val, list):
                    assert isinstance(val, basestring) or isinstance(val, list)
                    mytest.set_method(val)

            if configelement == u'expected_status':
                val = configvalue
                assert isinstance(val, basestring) or isinstance(val, list)
                mytest.set_expected_status(val)

            if configelement == u'extract_binds':
                # Add a list of extractors, of format:
                # {variable_name: {extractor_type: extractor_config}, ... }

                binds = flatten_dictionaries(configvalue)
                if mytest.extract_binds is None:
                    mytest.extract_binds = dict()

                for variable_name, extractor in binds.items():
                    if not isinstance(extractor, dict) or len(extractor) == 0:
                        raise TypeError(
                            "Extractors must be defined as maps of extractorType:{configs} with 1 entry"
                        )
                    if len(extractor) > 1:
                        raise ValueError(
                            "Cannot define multiple extractors for given variable name"
                        )

                    # Safe because length can only be 1
                    for extractor_type, extractor_config in extractor.items():

                        mytest.extract_binds[
                            variable_name] = validators.parse_extractor(
                                extractor_type, extractor_config)

            if configelement == u'validators':
                # Add a list of validators
                if not isinstance(configvalue, list):
                    raise Exception(
                        'Misconfigured validator section, must be a list of validators'
                    )
                if mytest.validators is None:
                    mytest.validators = list()

                # create validator and add to list iof validators
                for var in configvalue:
                    if not isinstance(var, dict):
                        raise TypeError(
                            "Validators must be defined as validatorType:{configs} "
                        )
                    for validator_type, validator_config in var.items():
                        validator = validators.parse_validator(
                            validator_type, validator_config)
                        mytest.validators.append(validator)

            if configelement == 'headers':  # HTTP headers to use, flattened to a single string-string dictionary
                mytest.headers
                configvalue = flatten_dictionaries(configvalue)

                if isinstance(configvalue, dict):
                    filterfunc = lambda x: str(x[0]).lower(
                    ) == 'template'  # Templated items
                    templates = [
                        x for x in ifilter(filterfunc, configvalue.items())
                    ]
                else:
                    templates = None

                if templates:

                    # Should have single entry in dictionary keys
                    mytest.set_headers(templates[0][1], isTemplate=True)
                elif isinstance(configvalue, dict):

                    mytest.headers = configvalue
                else:
                    raise TypeError(
                        "Illegal header type: headers must be a dictionary or list of dictionary keys"
                    )
            if configelement == 'variable_binds':
                mytest.variable_binds = flatten_dictionaries(configvalue)
            if configelement == 'generator_binds':

                if (True):
                    output = flatten_dictionaries(configvalue)
                    output2 = dict()
                    for key, value in output.items():
                        output2[str(key)] = str(value)
                    mytest.generator_binds = output2
            if configelement.startswith('curl_option_'):
                curlopt = configelement[12:].upper()
                if hasattr(BASECURL, curlopt):
                    if not mytest.curl_options:
                        mytest.curl_options = dict()
                    mytest.curl_options[curlopt] = configvalue
                else:
                    raise ValueError(
                        "Illegal curl option: {0}".format(curlopt))

        # For non-GET requests, accept additional response codes indicating success
        # (but only if not expected statuses are not explicitly specified)
        # this is per HTTP spec:
        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5

        if 'expected_status' not in node.keys():
            if mytest.method == 'POST':
                mytest.expected_status = [200, 201, 204]
            elif mytest.method == 'PUT':
                mytest.expected_status = [200, 201, 204]
            elif mytest.method == 'DELETE':
                mytest.expected_status = [200, 202, 204]
            # Fallthrough default is simply [200]
        return mytest