eval each prepared variable and function in variables_mapping.

    Args:
        variables_mapping (dict):
            {
                "varA": LazyString(123$varB),
                "varB": LazyString(456$varC),
                "varC": LazyString(${sum_two($a, $b)}),
                "a": 1,
                "b": 2,
                "c": {"key": LazyString($b)},
                "d": [LazyString($a), 3]
            }
        ignore (bool): If set True, VariableNotFound will be ignored.
            This is used when initializing tests.

    Returns:
        dict: parsed variables_mapping should not contain any variable or function.
            {
                "varA": "1234563",
                "varB": "4563",
                "varC": "3",
                "a": 1,
                "b": 2,
                "c": {"key": 2},
                "d": [1, 3]
            }

def parse_variables_mapping(variables_mapping, ignore=False):
    """ eval each prepared variable and function in variables_mapping.

    Args:
        variables_mapping (dict):
            {
                "varA": LazyString(123$varB),
                "varB": LazyString(456$varC),
                "varC": LazyString(${sum_two($a, $b)}),
                "a": 1,
                "b": 2,
                "c": {"key": LazyString($b)},
                "d": [LazyString($a), 3]
            }
        ignore (bool): If set True, VariableNotFound will be ignored.
            This is used when initializing tests.

    Returns:
        dict: parsed variables_mapping should not contain any variable or function.
            {
                "varA": "1234563",
                "varB": "4563",
                "varC": "3",
                "a": 1,
                "b": 2,
                "c": {"key": 2},
                "d": [1, 3]
            }

    """
    run_times = 0
    parsed_variables_mapping = {}

    while len(parsed_variables_mapping) != len(variables_mapping):
        for var_name in variables_mapping:

            run_times += 1
            if run_times > len(variables_mapping) * 4:
                not_found_variables = {
                    key: variables_mapping[key]
                    for key in variables_mapping
                    if key not in parsed_variables_mapping
                }
                raise exceptions.VariableNotFound(not_found_variables)

            if var_name in parsed_variables_mapping:
                continue

            value = variables_mapping[var_name]
            variables = extract_variables(value)

            # check if reference variable itself
            if var_name in variables:
                # e.g.
                # var_name = "token"
                # variables_mapping = {"token": LazyString($token)}
                # var_name = "key"
                # variables_mapping = {"key": [LazyString($key), 2]}
                if ignore:
                    parsed_variables_mapping[var_name] = value
                    continue
                raise exceptions.VariableNotFound(var_name)

            if variables:
                # reference other variable, or function call with other variable
                # e.g. {"varA": "123$varB", "varB": "456$varC"}
                # e.g. {"varC": "${sum_two($a, $b)}"}
                if any([_var_name not in parsed_variables_mapping for _var_name in variables]):
                    # reference variable not parsed
                    continue

            parsed_value = parse_lazy_data(value, parsed_variables_mapping)
            parsed_variables_mapping[var_name] = parsed_value

    return parsed_variables_mapping