diff options
| author | radiohotline <radoihotline@disroot.rg> | 2026-08-25 16:33:56 +0300 |
|---|---|---|
| committer | radiohotline <radoihotline@disroot.rg> | 2026-08-25 16:33:56 +0300 |
| commit | a89e744ed0e8c759caf041a580112365bbfe4303 (patch) | |
| tree | dd61e320904176995727e86a857d00c90d4933ba /addons/gdUnit4/src/mocking/GdUnitMockImpl.gd | |
| parent | 6d53d8cac78250dc888aa49d5f9d4175c6652feb (diff) | |
Diffstat (limited to 'addons/gdUnit4/src/mocking/GdUnitMockImpl.gd')
| -rw-r--r-- | addons/gdUnit4/src/mocking/GdUnitMockImpl.gd | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/addons/gdUnit4/src/mocking/GdUnitMockImpl.gd b/addons/gdUnit4/src/mocking/GdUnitMockImpl.gd new file mode 100644 index 0000000..774ca3e --- /dev/null +++ b/addons/gdUnit4/src/mocking/GdUnitMockImpl.gd @@ -0,0 +1,143 @@ +class_name DoubledMockClassSourceClassName + +################################################################################ +# internal mocking stuff +################################################################################ + +const __INSTANCE_ID := "gdunit_doubler_instance_id_{instance_id}" + + +class GdUnitMockDoublerState: + const __SOURCE_CLASS := "{gdunit_source_class}" + + var excluded_methods := PackedStringArray() + var working_mode := GdUnitMock.RETURN_DEFAULTS + var is_prepare_return := false + var return_values := Dictionary() + var return_value: Variant = null + + + func _init(working_mode_ := GdUnitMock.RETURN_DEFAULTS) -> void: + working_mode = working_mode_ + + +var __mock_state := GdUnitMockDoublerState.new() +@warning_ignore("unused_private_class_variable") +var __verifier_instance := GdUnitObjectInteractionsVerifier.new() + + +func __init(__script: GDScript, mock_working_mode: String) -> void: + super.set_script(__script) + __init_doubler() + __mock_state.working_mode = mock_working_mode + + +static func __doubler_state() -> GdUnitMockDoublerState: + if Engine.has_meta(__INSTANCE_ID): + return Engine.get_meta(__INSTANCE_ID).__mock_state + return null + + +func __init_doubler() -> void: + Engine.set_meta(__INSTANCE_ID, self) + + +func _notification(what: int) -> void: + if what == NOTIFICATION_PREDELETE and Engine.has_meta(__INSTANCE_ID): + Engine.remove_meta(__INSTANCE_ID) + + +static func __get_verifier() -> GdUnitObjectInteractionsVerifier: + return Engine.get_meta(__INSTANCE_ID).__verifier_instance + + +static func __is_prepare_return_value() -> bool: + return __doubler_state().is_prepare_return + + +static func __sort_by_argument_matcher(__left_args: Array, __right_args: Array) -> bool: + for __index in __left_args.size(): + var __larg: Variant = __left_args[__index] + if __larg is GdUnitArgumentMatcher: + return false + return true + + +# we need to sort by matcher arguments so that they are all at the end of the list +static func __sort_dictionary(__unsorted_args: Dictionary) -> Dictionary: + # only need to sort if contains more than one entry + if __unsorted_args.size() <= 1: + return __unsorted_args + var __sorted_args: Array = __unsorted_args.keys() + __sorted_args.sort_custom(__sort_by_argument_matcher) + var __sorted_result := {} + for __index in __sorted_args.size(): + var key :Variant = __sorted_args[__index] + __sorted_result[key] = __unsorted_args[key] + return __sorted_result + + +static func __save_function_return_value(__func_name: String, __func_args: Array) -> void: + var doubler_state := __doubler_state() + var mocked_return_value_by_args: Dictionary = doubler_state.return_values.get(__func_name, {}) + + mocked_return_value_by_args[__func_args] = doubler_state.return_value + doubler_state.return_values[__func_name] = __sort_dictionary(mocked_return_value_by_args) + doubler_state.return_value = null + doubler_state.is_prepare_return = false + + +static func __is_mocked_args_match(__func_args: Array, __mocked_args: Array) -> bool: + var __is_matching := false + for __index in __mocked_args.size(): + var __fuction_args: Array = __mocked_args[__index] + if __func_args.size() != __fuction_args.size(): + continue + __is_matching = true + for __arg_index in __func_args.size(): + var __func_arg: Variant = __func_args[__arg_index] + var __mock_arg: Variant = __fuction_args[__arg_index] + if __mock_arg is GdUnitArgumentMatcher: + @warning_ignore("unsafe_method_access") + __is_matching = __is_matching and __mock_arg.is_match(__func_arg) + else: + __is_matching = __is_matching and typeof(__func_arg) == typeof(__mock_arg) and __func_arg == __mock_arg + if not __is_matching: + break + if __is_matching: + break + return __is_matching + + +static func __return_mock_value(__func_name: String, __func_args: Array, __default_return_value: Variant) -> Variant: + var doubler_state := __doubler_state() + if not doubler_state.return_values.has(__func_name): + return __default_return_value + @warning_ignore("unsafe_method_access") + var __mocked_args: Array = doubler_state.return_values.get(__func_name).keys() + for __index in __mocked_args.size(): + var __margs: Variant = __mocked_args[__index] + if __is_mocked_args_match(__func_args, [__margs]): + return doubler_state.return_values[__func_name][__margs] + return __default_return_value + + +static func __is_do_not_call_real_func(__func_name: String, __func_args := []) -> bool: + var doubler_state := __doubler_state() + var __is_call_real_func: bool = doubler_state.working_mode == GdUnitMock.CALL_REAL_FUNC and not doubler_state.excluded_methods.has(__func_name) + # do not call real funcions for mocked functions + if __is_call_real_func and doubler_state.return_values.has(__func_name): + @warning_ignore("unsafe_method_access") + var __mocked_args: Array = doubler_state.return_values.get(__func_name).keys() + return __is_mocked_args_match(__func_args, __mocked_args) + return !__is_call_real_func + + +func __exclude_method_call(exluded_methods: PackedStringArray) -> void: + __doubler_state().excluded_methods.append_array(exluded_methods) + + +func __do_return(mock_do_return_value: Variant) -> Object: + __doubler_state().return_value = mock_do_return_value + __doubler_state().is_prepare_return = true + return self |
