## The execution context ## It contains all the necessary information about the executed stage, such as memory observers, reports, orphan monitor class_name GdUnitExecutionContext var _parent_context :GdUnitExecutionContext var _sub_context :Array[GdUnitExecutionContext] = [] var _orphan_monitor :GdUnitOrphanNodesMonitor var _memory_observer :GdUnitMemoryObserver var _report_collector :GdUnitTestReportCollector var _timer :LocalTime var _test_case_name: StringName var _name :String var error_monitor : GodotGdErrorMonitor = null: set (value): error_monitor = value get: if _parent_context != null: return _parent_context.error_monitor return error_monitor var test_suite : GdUnitTestSuite = null: set (value): test_suite = value get: if _parent_context != null: return _parent_context.test_suite return test_suite var test_case : _TestCase = null: get: if _test_case_name.is_empty(): return null return test_suite.find_child(_test_case_name, false, false) func _init(name :String, parent_context :GdUnitExecutionContext = null) -> void: _name = name _parent_context = parent_context _timer = LocalTime.now() _orphan_monitor = GdUnitOrphanNodesMonitor.new(name) _orphan_monitor.start() _memory_observer = GdUnitMemoryObserver.new() error_monitor = GodotGdErrorMonitor.new() _report_collector = GdUnitTestReportCollector.new(get_instance_id()) if parent_context != null: parent_context._sub_context.append(self) func dispose() -> void: _timer = null _orphan_monitor = null _report_collector = null _memory_observer = null _parent_context = null test_suite = null test_case = null for context in _sub_context: context.dispose() _sub_context.clear() func set_active() -> void: test_suite.__execution_context = self GdUnitThreadManager.get_current_context().set_execution_context(self) static func of_test_suite(test_suite_ :GdUnitTestSuite) -> GdUnitExecutionContext: assert(test_suite_, "test_suite is null") var context := GdUnitExecutionContext.new(test_suite_.get_name()) context.test_suite = test_suite_ context.set_active() return context static func of_test_case(pe :GdUnitExecutionContext, test_case_name :StringName) -> GdUnitExecutionContext: var context := GdUnitExecutionContext.new(test_case_name, pe) context._test_case_name = test_case_name context.set_active() return context static func of(pe :GdUnitExecutionContext) -> GdUnitExecutionContext: var context := GdUnitExecutionContext.new(pe._test_case_name, pe) context._test_case_name = pe._test_case_name context.set_active() return context func test_failed() -> bool: return has_failures() or has_errors() func error_monitor_start() -> void: error_monitor.start() func error_monitor_stop() -> void: await error_monitor.scan() for error_report in error_monitor.to_reports(): if error_report.is_error(): _report_collector._reports.append(error_report) func orphan_monitor_start() -> void: _orphan_monitor.start() func orphan_monitor_stop() -> void: _orphan_monitor.stop() func reports() -> Array[GdUnitReport]: return _report_collector.reports() func build_report_statistics(orphans :int, recursive := true) -> Dictionary: return { GdUnitEvent.ORPHAN_NODES: orphans, GdUnitEvent.ELAPSED_TIME: _timer.elapsed_since_ms(), GdUnitEvent.FAILED: has_failures(), GdUnitEvent.ERRORS: has_errors(), GdUnitEvent.WARNINGS: has_warnings(), GdUnitEvent.SKIPPED: has_skipped(), GdUnitEvent.FAILED_COUNT: count_failures(recursive), GdUnitEvent.ERROR_COUNT: count_errors(recursive), GdUnitEvent.SKIPPED_COUNT: count_skipped(recursive) } func has_failures() -> bool: return _sub_context.any(func(c): return c.has_failures()) or _report_collector.has_failures() func has_errors() -> bool: return _sub_context.any(func(c): return c.has_errors()) or _report_collector.has_errors() func has_warnings() -> bool: return _sub_context.any(func(c): return c.has_warnings()) or _report_collector.has_warnings() func has_skipped() -> bool: return _sub_context.any(func(c): return c.has_skipped()) or _report_collector.has_skipped() func count_failures(recursive :bool) -> int: if not recursive: return _report_collector.count_failures() return _sub_context\ .map(func(c): return c.count_failures(recursive))\ .reduce(sum, _report_collector.count_failures()) func count_errors(recursive :bool) -> int: if not recursive: return _report_collector.count_errors() return _sub_context\ .map(func(c): return c.count_errors(recursive))\ .reduce(sum, _report_collector.count_errors()) func count_skipped(recursive :bool) -> int: if not recursive: return _report_collector.count_skipped() return _sub_context\ .map(func(c): return c.count_skipped(recursive))\ .reduce(sum, _report_collector.count_skipped()) func count_orphans() -> int: var orphans := 0 for c in _sub_context: orphans += c._orphan_monitor.orphan_nodes() return _orphan_monitor.orphan_nodes() - orphans func sum(accum :int, number :int) -> int: return accum + number func register_auto_free(obj :Variant) -> Variant: return _memory_observer.register_auto_free(obj) ## Runs the gdunit garbage collector to free registered object func gc() -> void: await _memory_observer.gc() orphan_monitor_stop()