summaryrefslogtreecommitdiff
path: root/addons/gut/stubber.gd
diff options
context:
space:
mode:
Diffstat (limited to 'addons/gut/stubber.gd')
-rw-r--r--addons/gut/stubber.gd216
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