Example #1
0
def parse_variables(content, variable_mapping):
    """ replace all variables of string content with mapping value.
    @param (str) content
    @return (str) parsed content

    e.g.
        variable_mapping = {
            "var_1": "abc",
            "var_2": "def"
        }
        $var_1 => "abc"
        $var_1#XYZ => "abc#XYZ"
        /$var_1/$var_2/var3 => "/abc/def/var3"
        ${func($var_1, $var_2, xyz)} => "${func(abc, def, xyz)}"
    """
    variable_name_list = get_contain_variables(content)
    for variable_name in variable_name_list:
        variable_value = variable_mapping.get(variable_name)
        if variable_value is None:
            raise ParamsError("%s is not defined in bind variables!" %
                              variable_name)

        if "${}".format(variable_name) == content:
            # content is a variable
            content = variable_value
        else:
            # content contains one or many variables
            content = content.replace("${}".format(variable_name),
                                      str(variable_value), 1)

    return content
Example #2
0
def query_json(json_content, query, delimiter='.'):
    """ Do an xpath-like query with json_content.
    @param (json_content) json_content
        json_content = {
            "ids": [1, 2, 3, 4],
            "person": {
                "name": {
                    "first_name": "Leo",
                    "last_name": "Lee",
                },
                "age": 29,
                "cities": ["Guangzhou", "Shenzhen"]
            }
        }
    @param (str) query
        "person.name.first_name"  =>  "Leo"
        "person.cities.0"         =>  "Guangzhou"
    @return queried result
    """
    stripped_query = query.strip(delimiter)
    if not stripped_query:
        return None

    try:
        for key in stripped_query.split(delimiter):
            if isinstance(json_content, list):
                key = int(key)
            json_content = json_content[key]
    except (KeyError, ValueError, IndexError):
        raise ParamsError("invalid query string in extract_binds!")

    return json_content
Example #3
0
def get_timestamp(str_len=13):
    """ get timestamp string, length can only between 0 and 16
    """
    if isinstance(str_len, int) and 0 < str_len < 17:
        return str(time.time()).replace(".", "")[:str_len]

    raise ParamsError("timestamp length can only between 0 and 16.")
Example #4
0
 def _build_url(self, path):
     """ prepend url with hostname unless it's already an absolute URL """
     if absolute_http_url_regexp.match(path):
         return path
     elif self.base_url:
         return "%s%s" % (self.base_url, path)
     else:
         raise ParamsError("base url missed!")
Example #5
0
def load_testcases(testcase_file_path):
    file_suffix = os.path.splitext(testcase_file_path)[1]
    if file_suffix == '.json':
        return load_json_file(testcase_file_path)
    elif file_suffix in ['.yaml', '.yml']:
        return load_yaml_file(testcase_file_path)
    else:
        # '' or other suffix
        raise ParamsError("Bad testcase file name!")
Example #6
0
    def register_request(self, request_dict, level="testcase"):
        if "headers" in request_dict:
            # convert keys in request headers to lowercase
            headers = request_dict.pop("headers")
            if not isinstance(headers, dict):
                raise ParamsError("HTTP Request Headers invalid!")
            request_dict["headers"] = {key.lower(): headers[key] for key in headers}

        self.__update_context_request_config(level, request_dict)
Example #7
0
def match_expected(value, expected, comparator="eq"):
    """ check if value matches expected value.
    @param value: value that get from response.
    @param expected: expected result described in testcase
    @param comparator: compare method
    """
    try:
        if comparator in ["eq", "equals", "=="]:
            assert value == expected
        elif comparator in ["str_eq", "string_equals"]:
            assert str(value) == str(expected)
        elif comparator in ["ne", "not_equals"]:
            assert value != expected
        elif comparator in ["len_eq", "length_equal", "count_eq"]:
            assert len(value) == expected
        elif comparator in [
                "len_gt", "count_gt", "length_greater_than",
                "count_greater_than"
        ]:
            assert len(value) > expected
        elif comparator in ["len_ge", "count_ge", "length_greater_than_or_equals", \
            "count_greater_than_or_equals"]:
            assert len(value) >= expected
        elif comparator in [
                "len_lt", "count_lt", "length_less_than", "count_less_than"
        ]:
            assert len(value) < expected
        elif comparator in ["len_le", "count_le", "length_less_than_or_equals", \
            "count_less_than_or_equals"]:
            assert len(value) <= expected
        elif comparator in ["lt", "less_than"]:
            assert value < expected
        elif comparator in ["le", "less_than_or_equals"]:
            assert value <= expected
        elif comparator in ["gt", "greater_than"]:
            assert value > expected
        elif comparator in ["ge", "greater_than_or_equals"]:
            assert value >= expected
        elif comparator in ["contains"]:
            assert expected in value
        elif comparator in ["contained_by"]:
            assert value in expected
        elif comparator in ["regex"]:
            assert re.match(expected, value)
        elif comparator in ["str_len", "string_length"]:
            assert len(value) == int(expected)
        elif comparator in ["startswith"]:
            assert str(value).startswith(str(expected))
        else:
            raise ParamsError("comparator not supported!")

        return True
    except AssertionError:
        return False
Example #8
0
def parse_content_with_variables(content, variables_binds):
    """ replace variables with bind value
    """
    # check if content includes $variable
    matched = re.match(r"^(.*)\$(\w+)(.*)$", content)
    if matched:
        # this is a variable, and will replace with its bind value
        variable_name = matched.group(2)
        value = variables_binds.get(variable_name)
        if value is None:
            raise ParamsError("%s is not defined in bind variables!" %
                              variable_name)
        if matched.group(1) or matched.group(3):
            # e.g. /api/users/$uid
            return content.replace("$%s" % variable_name, value)

        return value

    return content
Example #9
0
def parse_content_with_variables(content, variables_binds):
    """ replace variables with bind value
    """
    # check if content includes ${variable}
    matched = re.match(r"(.*)\$\{(.*)\}(.*)", content)
    if matched:
        # this is a variable, and will replace with its bind value
        variable_name = matched.group(2)
        value = variables_binds.get(variable_name)
        if value is None:
            raise ParamsError("%s is not defined in bind variables!" %
                              variable_name)
        if matched.group(1) or matched.group(3):
            # e.g. /api/users/${uid}
            return re.sub(r"\$\{.*\}", value, content)

        return value

    return content
Example #10
0
def parse_content_with_bindings(content, variables_binds, functions_binds):
    """ evaluate content recursively, each variable in content will be
        evaluated with bind variables and functions.

    variables marker: $variable.
    @param (dict) content in any data structure
        {
            "url": "http://127.0.0.1:5000/api/users/$uid",
            "method": "POST",
            "headers": {
                "Content-Type": "application/json",
                "authorization": "$authorization",
                "random": "$random",
                "sum": "${add_two_nums(1, 2)}"
            },
            "body": "$data"
        }
    @param (dict) variables_binds, variables binds mapping
        {
            "authorization": "a83de0ff8d2e896dbd8efb81ba14e17d",
            "random": "A2dEx",
            "data": {"name": "user", "password": "******"}
        }
    @param (dict) functions_binds, functions binds mapping
        {
            "add_two_nums": lambda a, b=1: a + b
        }
    @return (dict) parsed content with evaluated bind values
        {
            "url": "http://127.0.0.1:5000/api/users/1000",
            "method": "POST",
            "headers": {
                "Content-Type": "application/json",
                "authorization": "a83de0ff8d2e896dbd8efb81ba14e17d",
                "random": "A2dEx",
                "sum": 3
            },
            "body": {"name": "user", "password": "******"}
        }
    """

    if isinstance(content, (list, tuple)):
        return [
            parse_content_with_bindings(item, variables_binds, functions_binds)
            for item in content
        ]

    if isinstance(content, dict):
        evaluated_data = {}
        for key, value in content.items():
            evaluated_data[key] = parse_content_with_bindings(
                value, variables_binds, functions_binds)

        return evaluated_data

    if isinstance(content, (int, float)):
        return content

    # content is in string format here
    content = "" if content is None else content.strip()

    if is_functon(content):
        # function marker: ${func(1, 2, a=3, b=4)}
        fuction_meta = parse_function(content)
        func_name = fuction_meta['func_name']

        func = functions_binds.get(func_name)
        if func is None:
            raise ParamsError("%s is not defined in bind functions!" %
                              func_name)

        args = fuction_meta.get('args', [])
        kwargs = fuction_meta.get('kwargs', {})
        args = parse_content_with_bindings(args, variables_binds,
                                           functions_binds)
        kwargs = parse_content_with_bindings(kwargs, variables_binds,
                                             functions_binds)
        return func(*args, **kwargs)

    elif get_contain_variables(content):
        parsed_data = parse_variables(content, variables_binds)
        return parsed_data

    else:
        return content