239 lines
5.8 KiB
GDScript
239 lines
5.8 KiB
GDScript
|
class_name _TestCase
|
||
|
extends Node
|
||
|
|
||
|
signal completed()
|
||
|
|
||
|
# default timeout 5min
|
||
|
const DEFAULT_TIMEOUT := -1
|
||
|
const ARGUMENT_TIMEOUT := "timeout"
|
||
|
const ARGUMENT_SKIP := "do_skip"
|
||
|
const ARGUMENT_SKIP_REASON := "skip_reason"
|
||
|
|
||
|
var _iterations: int = 1
|
||
|
var _current_iteration: int = -1
|
||
|
var _seed: int
|
||
|
var _fuzzers: Array[GdFunctionArgument] = []
|
||
|
var _test_param_index := -1
|
||
|
var _line_number: int = -1
|
||
|
var _script_path: String
|
||
|
var _skipped := false
|
||
|
var _skip_reason := ""
|
||
|
var _expect_to_interupt := false
|
||
|
var _timer: Timer
|
||
|
var _interupted: bool = false
|
||
|
var _failed := false
|
||
|
var _report: GdUnitReport = null
|
||
|
var _parameter_set_resolver: GdUnitTestParameterSetResolver
|
||
|
var _is_disposed := false
|
||
|
|
||
|
var timeout: int = DEFAULT_TIMEOUT:
|
||
|
set(value):
|
||
|
timeout = value
|
||
|
get:
|
||
|
if timeout == DEFAULT_TIMEOUT:
|
||
|
timeout = GdUnitSettings.test_timeout()
|
||
|
return timeout
|
||
|
|
||
|
|
||
|
@warning_ignore("shadowed_variable_base_class")
|
||
|
func configure(p_name: String, p_line_number: int, p_script_path: String, p_timeout: int=DEFAULT_TIMEOUT, p_fuzzers: Array[GdFunctionArgument]=[], p_iterations: int=1, p_seed: int=-1) -> _TestCase:
|
||
|
set_name(p_name)
|
||
|
_line_number = p_line_number
|
||
|
_fuzzers = p_fuzzers
|
||
|
_iterations = p_iterations
|
||
|
_seed = p_seed
|
||
|
_script_path = p_script_path
|
||
|
timeout = p_timeout
|
||
|
return self
|
||
|
|
||
|
|
||
|
func execute(p_test_parameter := Array(), p_iteration := 0) -> void:
|
||
|
_failure_received(false)
|
||
|
_current_iteration = p_iteration - 1
|
||
|
if _current_iteration == - 1:
|
||
|
_set_failure_handler()
|
||
|
set_timeout()
|
||
|
if not p_test_parameter.is_empty():
|
||
|
update_fuzzers(p_test_parameter, p_iteration)
|
||
|
_execute_test_case(name, p_test_parameter)
|
||
|
else:
|
||
|
_execute_test_case(name, [])
|
||
|
await completed
|
||
|
|
||
|
|
||
|
func execute_paramaterized(p_test_parameter: Array) -> void:
|
||
|
_failure_received(false)
|
||
|
set_timeout()
|
||
|
# We need here to add a empty array to override the `test_parameters` to prevent initial "default" parameters from being used.
|
||
|
# This prevents objects in the argument list from being unnecessarily re-instantiated.
|
||
|
var test_parameters := p_test_parameter.duplicate() # is strictly need to duplicate the paramters before extend
|
||
|
test_parameters.append([])
|
||
|
_execute_test_case(name, test_parameters)
|
||
|
await completed
|
||
|
|
||
|
|
||
|
func dispose() -> void:
|
||
|
if _is_disposed:
|
||
|
return
|
||
|
_is_disposed = true
|
||
|
Engine.remove_meta("GD_TEST_FAILURE")
|
||
|
stop_timer()
|
||
|
_remove_failure_handler()
|
||
|
_fuzzers.clear()
|
||
|
_report = null
|
||
|
|
||
|
|
||
|
@warning_ignore("shadowed_variable_base_class", "redundant_await")
|
||
|
func _execute_test_case(name: String, test_parameter: Array) -> void:
|
||
|
# needs at least on await otherwise it breaks the awaiting chain
|
||
|
await get_parent().callv(name, test_parameter)
|
||
|
await Engine.get_main_loop().process_frame
|
||
|
completed.emit()
|
||
|
|
||
|
|
||
|
func update_fuzzers(input_values: Array, iteration: int) -> void:
|
||
|
for fuzzer :Variant in input_values:
|
||
|
if fuzzer is Fuzzer:
|
||
|
fuzzer._iteration_index = iteration + 1
|
||
|
|
||
|
|
||
|
func set_timeout() -> void:
|
||
|
if is_instance_valid(_timer):
|
||
|
return
|
||
|
var time: float = timeout / 1000.0
|
||
|
_timer = Timer.new()
|
||
|
add_child(_timer)
|
||
|
_timer.set_name("gdunit_test_case_timer_%d" % _timer.get_instance_id())
|
||
|
_timer.timeout.connect(func do_interrupt() -> void:
|
||
|
if is_fuzzed():
|
||
|
_report = GdUnitReport.new().create(GdUnitReport.INTERUPTED, line_number(), GdAssertMessages.fuzzer_interuped(_current_iteration, "timedout"))
|
||
|
else:
|
||
|
_report = GdUnitReport.new().create(GdUnitReport.INTERUPTED, line_number(), GdAssertMessages.test_timeout(timeout))
|
||
|
_interupted = true
|
||
|
completed.emit()
|
||
|
, CONNECT_DEFERRED)
|
||
|
_timer.set_one_shot(true)
|
||
|
_timer.set_wait_time(time)
|
||
|
_timer.set_autostart(false)
|
||
|
_timer.start()
|
||
|
|
||
|
|
||
|
func _set_failure_handler() -> void:
|
||
|
if not GdUnitSignals.instance().gdunit_set_test_failed.is_connected(_failure_received):
|
||
|
GdUnitSignals.instance().gdunit_set_test_failed.connect(_failure_received)
|
||
|
|
||
|
|
||
|
func _remove_failure_handler() -> void:
|
||
|
if GdUnitSignals.instance().gdunit_set_test_failed.is_connected(_failure_received):
|
||
|
GdUnitSignals.instance().gdunit_set_test_failed.disconnect(_failure_received)
|
||
|
|
||
|
|
||
|
func _failure_received(is_failed: bool) -> void:
|
||
|
# is already failed?
|
||
|
if _failed:
|
||
|
return
|
||
|
_failed = is_failed
|
||
|
Engine.set_meta("GD_TEST_FAILURE", is_failed)
|
||
|
|
||
|
|
||
|
func stop_timer() -> void:
|
||
|
# finish outstanding timeouts
|
||
|
if is_instance_valid(_timer):
|
||
|
_timer.stop()
|
||
|
_timer.call_deferred("free")
|
||
|
_timer = null
|
||
|
|
||
|
|
||
|
func expect_to_interupt() -> void:
|
||
|
_expect_to_interupt = true
|
||
|
|
||
|
|
||
|
func is_interupted() -> bool:
|
||
|
return _interupted
|
||
|
|
||
|
|
||
|
func is_expect_interupted() -> bool:
|
||
|
return _expect_to_interupt
|
||
|
|
||
|
|
||
|
func is_parameterized() -> bool:
|
||
|
return _parameter_set_resolver.is_parameterized()
|
||
|
|
||
|
|
||
|
func is_skipped() -> bool:
|
||
|
return _skipped
|
||
|
|
||
|
|
||
|
func report() -> GdUnitReport:
|
||
|
return _report
|
||
|
|
||
|
|
||
|
func skip_info() -> String:
|
||
|
return _skip_reason
|
||
|
|
||
|
|
||
|
func line_number() -> int:
|
||
|
return _line_number
|
||
|
|
||
|
|
||
|
func iterations() -> int:
|
||
|
return _iterations
|
||
|
|
||
|
|
||
|
func seed_value() -> int:
|
||
|
return _seed
|
||
|
|
||
|
|
||
|
func is_fuzzed() -> bool:
|
||
|
return not _fuzzers.is_empty()
|
||
|
|
||
|
|
||
|
func fuzzer_arguments() -> Array[GdFunctionArgument]:
|
||
|
return _fuzzers
|
||
|
|
||
|
|
||
|
func script_path() -> String:
|
||
|
return _script_path
|
||
|
|
||
|
|
||
|
func ResourcePath() -> String:
|
||
|
return _script_path
|
||
|
|
||
|
|
||
|
func generate_seed() -> void:
|
||
|
if _seed != -1:
|
||
|
seed(_seed)
|
||
|
|
||
|
|
||
|
func skip(skipped: bool, reason: String="") -> void:
|
||
|
_skipped = skipped
|
||
|
_skip_reason = reason
|
||
|
|
||
|
|
||
|
func set_function_descriptor(fd: GdFunctionDescriptor) -> void:
|
||
|
_parameter_set_resolver = GdUnitTestParameterSetResolver.new(fd)
|
||
|
|
||
|
|
||
|
func set_test_parameter_index(index: int) -> void:
|
||
|
_test_param_index = index
|
||
|
|
||
|
|
||
|
func test_parameter_index() -> int:
|
||
|
return _test_param_index
|
||
|
|
||
|
|
||
|
func test_case_names() -> PackedStringArray:
|
||
|
return _parameter_set_resolver.build_test_case_names(self)
|
||
|
|
||
|
|
||
|
func load_parameter_sets() -> Array:
|
||
|
return _parameter_set_resolver.load_parameter_sets(self, true)
|
||
|
|
||
|
|
||
|
func parameter_set_resolver() -> GdUnitTestParameterSetResolver:
|
||
|
return _parameter_set_resolver
|
||
|
|
||
|
|
||
|
func _to_string() -> String:
|
||
|
return "%s :%d (%dms)" % [get_name(), _line_number, timeout]
|