Validates that the given parameters are exactly the method's declared parameters.

    :param method: The method to be called
    :type method: function
    :param parameters: The parameters to use in the call
    :type parameters: dict[str, object] | list[object]

def validate_params_match(method, parameters):
    """Validates that the given parameters are exactly the method's declared parameters.

    :param method: The method to be called
    :type method: function
    :param parameters: The parameters to use in the call
    :type parameters: dict[str, object] | list[object]
    """
    argspec = inspect.getargspec(method)  # pylint: disable=deprecated-method
    default_length = len(argspec.defaults) if argspec.defaults is not None else 0

    if isinstance(parameters, list):
        if len(parameters) > len(argspec.args) and argspec.varargs is None:
            raise InvalidParamsError("Too many parameters")

        remaining_parameters = len(argspec.args) - len(parameters)
        if remaining_parameters > default_length:
            raise InvalidParamsError("Not enough parameters")

    elif isinstance(parameters, dict):
        missing_parameters = [key for key in argspec.args if key not in parameters]
        default_parameters = set(argspec.args[len(argspec.args) - default_length:])
        for key in missing_parameters:
            if key not in default_parameters:
                raise InvalidParamsError("Parameter {} has not been satisfied".format(key))

        extra_params = [key for key in parameters if key not in argspec.args]
        if len(extra_params) > 0 and argspec.keywords is None:
            raise InvalidParamsError("Too many parameters")