diff options
Diffstat (limited to 'addons/gut/stubber.gd')
| -rw-r--r-- | addons/gut/stubber.gd | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/addons/gut/stubber.gd b/addons/gut/stubber.gd new file mode 100644 index 0000000..a8fc2ac --- /dev/null +++ b/addons/gut/stubber.gd @@ -0,0 +1,216 @@ +# ------------- +# returns{} and parameters {} have the followin structure +# ------------- +# { +# inst_id_or_path1:{ +# method_name1: [StubParams, StubParams], +# method_name2: [StubParams, StubParams] +# }, +# inst_id_or_path2:{ +# method_name1: [StubParams, StubParams], +# method_name2: [StubParams, StubParams] +# } +# } +var returns = {} +var _utils = load('res://addons/gut/utils.gd').get_instance() +var _lgr = _utils.get_logger() +var _strutils = _utils.Strutils.new() + + +func _make_key_from_metadata(doubled): + var to_return = doubled.__gut_metadata_.path + + if(doubled.__gut_metadata_.from_singleton != ''): + to_return = str(doubled.__gut_metadata_.from_singleton) + elif(doubled.__gut_metadata_.subpath != ''): + to_return += str('-', doubled.__gut_metadata_.subpath) + + return to_return + + +# Creates they key for the returns hash based on the type of object passed in +# obj could be a string of a path to a script with an optional subpath or +# it could be an instance of a doubled object. +func _make_key_from_variant(obj, subpath=null): + var to_return = null + + match typeof(obj): + TYPE_STRING: + # this has to match what is done in _make_key_from_metadata + to_return = obj + if(subpath != null and subpath != ''): + to_return += str('-', subpath) + TYPE_OBJECT: + if(_utils.is_instance(obj)): + to_return = _make_key_from_metadata(obj) + elif(_utils.is_native_class(obj)): + to_return = _utils.get_native_class_name(obj) + else: + to_return = obj.resource_path + + return to_return + + +func _add_obj_method(obj, method, subpath=null): + var key = _make_key_from_variant(obj, subpath) + if(_utils.is_instance(obj)): + key = obj + + if(!returns.has(key)): + returns[key] = {} + if(!returns[key].has(method)): + returns[key][method] = [] + + return key + +# ############## +# Public +# ############## + +# Searches returns for an entry that matches the instance or the class that +# passed in obj is. +# +# obj can be an instance, class, or a path. +func _find_stub(obj, method, parameters=null, find_overloads=false): + var key = _make_key_from_variant(obj) + var to_return = null + + if(_utils.is_instance(obj)): + if(returns.has(obj) and returns[obj].has(method)): + key = obj + elif(obj.get('__gut_metadata_')): + key = _make_key_from_metadata(obj) + + if(returns.has(key) and returns[key].has(method)): + var param_match = null + var null_match = null + var overload_match = null + + for i in range(returns[key][method].size()): + if(returns[key][method][i].parameters == parameters): + param_match = returns[key][method][i] + + if(returns[key][method][i].parameters == null): + null_match = returns[key][method][i] + + if(returns[key][method][i].has_param_override()): + overload_match = returns[key][method][i] + + if(find_overloads and overload_match != null): + to_return = overload_match + # We have matching parameter values so return the stub value for that + elif(param_match != null): + to_return = param_match + # We found a case where the parameters were not specified so return + # parameters for that. Only do this if the null match is not *just* + # a paramerter override stub. + elif(null_match != null and !null_match.is_param_override_only()): + to_return = null_match + else: + _lgr.warn(str('Call to [', method, '] was not stubbed for the supplied parameters ', parameters, '. Null was returned.')) + + return to_return + + +func add_stub(stub_params): + if(stub_params.stub_method == '_init'): + _lgr.error("You cannot stub _init. Super's _init is ALWAYS called.") + else: + var key = _add_obj_method(stub_params.stub_target, stub_params.stub_method, stub_params.target_subpath) + returns[key][stub_params.stub_method].append(stub_params) + + +# Gets a stubbed return value for the object and method passed in. If the +# instance was stubbed it will use that, otherwise it will use the path and +# subpath of the object to try to find a value. +# +# It will also use the optional list of parameter values to find a value. If +# the object was stubbed with no parameters than any parameters will match. +# If it was stubbed with specific parameter values then it will try to match. +# If the parameters do not match BUT there was also an empty parameter list stub +# then it will return those. +# If it cannot find anything that matches then null is returned.for +# +# Parameters +# obj: this should be an instance of a doubled object. +# method: the method called +# parameters: optional array of parameter vales to find a return value for. +func get_return(obj, method, parameters=null): + var stub_info = _find_stub(obj, method, parameters) + + if(stub_info != null): + return stub_info.return_val + else: + return null + + +func should_call_super(obj, method, parameters=null): + if(_utils.non_super_methods.has(method)): + return false + + var stub_info = _find_stub(obj, method, parameters) + + var is_partial = false + if(typeof(obj) != TYPE_STRING): # some stubber tests test with strings + is_partial = obj.__gut_metadata_.is_partial + var should = is_partial + + if(stub_info != null): + should = stub_info.call_super + elif(!is_partial): + # this log message is here because of how the generated doubled scripts + # are structured. With this log msg here, you will only see one + # "unstubbed" info instead of multiple. + _lgr.info('Unstubbed call to ' + method + '::' + _strutils.type2str(obj)) + should = false + + return should + + +func get_parameter_count(obj, method): + var to_return = null + var stub_info = _find_stub(obj, method, null, true) + + if(stub_info != null and stub_info.has_param_override()): + to_return = stub_info.parameter_count + + return to_return + + +func get_default_value(obj, method, p_index): + var to_return = null + var stub_info = _find_stub(obj, method, null, true) + if(stub_info != null and + stub_info.parameter_defaults != null and + stub_info.parameter_defaults.size() > p_index): + + to_return = stub_info.parameter_defaults[p_index] + + return to_return + + +func clear(): + returns.clear() + + +func get_logger(): + return _lgr + + +func set_logger(logger): + _lgr = logger + + +func to_s(): + var text = '' + for thing in returns: + text += str("-- ", thing, " --\n") + for method in returns[thing]: + text += str("\t", method, "\n") + for i in range(returns[thing][method].size()): + text += "\t\t" + returns[thing][method][i].to_s() + "\n" + + if(text == ''): + text = 'Stubber is empty'; + + return text |
