mirror of
https://github.com/Relintai/regression-test-project.git
synced 2025-02-08 16:30:11 +01:00
Better prints messages (#46)
This commit is contained in:
parent
4d82f9f873
commit
4a4a1543d9
@ -2,28 +2,21 @@ extends Node
|
|||||||
|
|
||||||
var regression_test_project : bool = true # Set it to true in RegressionTestProject
|
var regression_test_project : bool = true # Set it to true in RegressionTestProject
|
||||||
|
|
||||||
# Contains info about disabled classes
|
### Contains info about disabled classes and allows to take info about allowed methods
|
||||||
# Also allows to get list of available classes
|
|
||||||
|
|
||||||
var properties_exceptions : Array = [
|
# Globablly disabled functions for all classes
|
||||||
"user_data",
|
|
||||||
"config_file",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
]
|
|
||||||
var function_exceptions : Array = [
|
var function_exceptions : Array = [
|
||||||
"_set_user_data",
|
|
||||||
"get_packet", # TODO
|
"get_packet", # TODO
|
||||||
"create_from_mesh",
|
"_gui_input", # TODO probably missing cherrypick #GH 47636
|
||||||
|
"_input",
|
||||||
|
"_unhandled_input",
|
||||||
|
"_unhandled_key_input",
|
||||||
|
"connect_to_signal", # Should be chrrypicked
|
||||||
|
|
||||||
# They exists without assigment like Class.method, because they may be a parent of other objects and children also should have disabled child.method, its children also etc. which is too much to do
|
# They exists without assigment like Class.method, because they may be a parent of other objects and children also should have disabled child.method, its children also etc. which is too much to do
|
||||||
"connect_to_signal", # GH 47572
|
#"connect_to_signal", # GH 47572
|
||||||
"set_config_file", # GH 45997
|
|
||||||
"class_get_property", # GH 47573
|
|
||||||
"class_set_property", # GH 47573
|
|
||||||
"_editor_settings_changed",# GH 45979
|
"_editor_settings_changed",# GH 45979
|
||||||
"_submenu_timeout", # GH 45981
|
"_submenu_timeout", # GH 45981
|
||||||
"_gui_input", # GH 45998
|
|
||||||
"_unhandled_key_input", # GH 45998
|
|
||||||
"_thread_done", #GH 46000
|
"_thread_done", #GH 46000
|
||||||
"generate", #GH 46001
|
"generate", #GH 46001
|
||||||
"_proximity_group_broadcast", #GH 46002
|
"_proximity_group_broadcast", #GH 46002
|
||||||
@ -31,13 +24,10 @@ var function_exceptions : Array = [
|
|||||||
"create_from", #GH 46004
|
"create_from", #GH 46004
|
||||||
"create_from_blend_shape", #GH 46004
|
"create_from_blend_shape", #GH 46004
|
||||||
"append_from", #GH 46004
|
"append_from", #GH 46004
|
||||||
"_unhandled_input", # TODO
|
|
||||||
"_input", # TODO
|
|
||||||
"_set_tile_data", #GH 46015
|
"_set_tile_data", #GH 46015
|
||||||
"get", #GH 46019
|
"get", #GH 46019
|
||||||
"instance_has", #GH 46020
|
"instance_has", #GH 46020
|
||||||
"get_var", #GH 46096
|
"get_var", #GH 46096
|
||||||
"force_drag", #GH 46114
|
|
||||||
"set_script", #GH 46120
|
"set_script", #GH 46120
|
||||||
"getvar", #GH 46019
|
"getvar", #GH 46019
|
||||||
"get_available_chars", #GH 46118
|
"get_available_chars", #GH 46118
|
||||||
@ -47,22 +37,16 @@ var function_exceptions : Array = [
|
|||||||
"set_editor_hint", #GH 46252
|
"set_editor_hint", #GH 46252
|
||||||
"get_item_at_position", #TODO hard to find
|
"get_item_at_position", #TODO hard to find
|
||||||
"set_probe_data", #GH 46570
|
"set_probe_data", #GH 46570
|
||||||
"_range_click_timeout",
|
"_range_click_timeout", #GH 46648
|
||||||
"draw", #GH 46648
|
|
||||||
"get_indexed", #GH 46019
|
"get_indexed", #GH 46019
|
||||||
"_vp_input", # TODO
|
|
||||||
"_vp_unhandled_input", # TODO
|
|
||||||
"remove_joy_mapping", #GH 46754
|
|
||||||
"add_joy_mapping", #GH 46754
|
|
||||||
"add_vertex", #GH 47066
|
"add_vertex", #GH 47066
|
||||||
"create_client", # TODO, strange memory leak
|
"create_client", # TODO, strange memory leak
|
||||||
"create_shape_owner", #47135
|
"create_shape_owner", #47135
|
||||||
"shape_owner_get_owner", #47135
|
"shape_owner_get_owner", #47135
|
||||||
|
|
||||||
"collide", #GH 46137
|
"get_bind_bone", #GH 47358
|
||||||
"collide_and_get_contacts", #GH 46137
|
"get_bind_name", #GH 47358
|
||||||
"collide_with_motion", #GH 46137
|
"get_bind_pose", #GH 47358
|
||||||
"collide_with_motion_and_get_contacts", #GH 46137
|
|
||||||
|
|
||||||
# TODO Check this later
|
# TODO Check this later
|
||||||
"propagate_notification",
|
"propagate_notification",
|
||||||
@ -162,67 +146,10 @@ var function_exceptions : Array = [
|
|||||||
"raise",
|
"raise",
|
||||||
"add_child",
|
"add_child",
|
||||||
"add_child_below_node",
|
"add_child_below_node",
|
||||||
]
|
"add_sibling",
|
||||||
var exported : Array = [
|
|
||||||
"get_bind_bone",
|
|
||||||
"get_bind_name",
|
|
||||||
"get_bind_pose",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# List of slow functions, which may frooze project(not simple executing each function alone)
|
# Globally disabled classes which causes bugs or are very hard to us
|
||||||
var slow_functions : Array = [
|
|
||||||
"interpolate_baked",
|
|
||||||
"get_baked_length",
|
|
||||||
"get_baked_points",
|
|
||||||
"get_closest_offset",
|
|
||||||
"get_closest_point", # Only Curve, but looks that a lot of other classes uses this
|
|
||||||
"get_baked_up_vectors",
|
|
||||||
"interpolate_baked_up_vector",
|
|
||||||
"tessellate",
|
|
||||||
"get_baked_tilts",
|
|
||||||
"set_enabled_inputs",
|
|
||||||
"grow_mask",
|
|
||||||
"force_update_transform",
|
|
||||||
|
|
||||||
|
|
||||||
# In 3d view some options are really slow, needs to be limited
|
|
||||||
"set_rings",
|
|
||||||
"set_amount", # Particles
|
|
||||||
|
|
||||||
|
|
||||||
# Just a little slow functions
|
|
||||||
"is_enabler_enabled",
|
|
||||||
"set_enabler",
|
|
||||||
"get_aabb",
|
|
||||||
"set_aabb",
|
|
||||||
"is_on_screen"
|
|
||||||
]
|
|
||||||
# Specific classes which are initialized in specific way e.g. var undo_redo = get_undo_redo() instead var undo_redo = UndoRedo.new()
|
|
||||||
var only_instance : Array = [
|
|
||||||
"UndoRedo",
|
|
||||||
"Object",
|
|
||||||
"JSONRPC",
|
|
||||||
"MainLoop",
|
|
||||||
"SceneTree",
|
|
||||||
"ARVRPositionalTracker",
|
|
||||||
]
|
|
||||||
var invalid_signals : Array = [
|
|
||||||
"multi_selected",
|
|
||||||
"item_collapsed",
|
|
||||||
"button_pressed",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
|
|
||||||
|
|
||||||
# Probably Vararg
|
|
||||||
"tween_step",
|
|
||||||
"tween_completed",
|
|
||||||
"tween_started",
|
|
||||||
"data_channel_received",
|
|
||||||
"",
|
|
||||||
]
|
|
||||||
# Used only in ValueCreator
|
|
||||||
var disabled_classes : Array = [
|
var disabled_classes : Array = [
|
||||||
"ProjectSettings", # Don't mess with project settings, because they can broke entire your workflow
|
"ProjectSettings", # Don't mess with project settings, because they can broke entire your workflow
|
||||||
"EditorSettings", # Also don't mess with editor settings
|
"EditorSettings", # Also don't mess with editor settings
|
||||||
@ -239,6 +166,8 @@ var disabled_classes : Array = [
|
|||||||
"IP_Unix",
|
"IP_Unix",
|
||||||
"JNISingleton",
|
"JNISingleton",
|
||||||
|
|
||||||
|
# Only one class - JavaClass returns Null when using JavaClass.new().get_class
|
||||||
|
"JavaClass",
|
||||||
|
|
||||||
# Just don't use these because they are not normal things
|
# Just don't use these because they are not normal things
|
||||||
"_Thread",
|
"_Thread",
|
||||||
@ -246,53 +175,63 @@ var disabled_classes : Array = [
|
|||||||
"_Mutex",
|
"_Mutex",
|
||||||
]
|
]
|
||||||
|
|
||||||
# GH 47358
|
|
||||||
func _init():
|
|
||||||
function_exceptions.append_array(exported)
|
|
||||||
|
|
||||||
# Checks if function can be executed
|
# Checks if function can be executed
|
||||||
# Looks at its arguments an
|
# Looks at its arguments an
|
||||||
func check_if_is_allowed(method_data : Dictionary) -> bool:
|
func check_if_is_allowed(method_data : Dictionary) -> bool:
|
||||||
# Function is virtual, so we just skip it
|
# Function is virtual or vararg, so we just skip it
|
||||||
if method_data["flags"] == method_data["flags"] | METHOD_FLAG_VIRTUAL:
|
if method_data["flags"] == method_data["flags"] | METHOD_FLAG_VIRTUAL:
|
||||||
return false
|
return false
|
||||||
|
if method_data["flags"] == method_data["flags"] | 128: # VARARG TODO, Godot issue, add missing flag binding
|
||||||
|
return false
|
||||||
|
|
||||||
for arg in method_data["args"]:
|
for arg in method_data["args"]:
|
||||||
var name_of_class : String = arg["class_name"]
|
var name_of_class : String = arg["class_name"]
|
||||||
if name_of_class.empty():
|
if name_of_class.empty():
|
||||||
continue
|
continue
|
||||||
if !ClassDB.class_exists(name_of_class): # This is enum not object, but we allow it
|
|
||||||
continue
|
|
||||||
if name_of_class in disabled_classes:
|
if name_of_class in disabled_classes:
|
||||||
return false
|
return false
|
||||||
if name_of_class.find("Server") != -1 && ClassDB.class_exists(name_of_class) && !ClassDB.is_parent_class(name_of_class,"Reference"):
|
if name_of_class.find("Server") != -1 && ClassDB.class_exists(name_of_class) && !ClassDB.is_parent_class(name_of_class,"Reference"):
|
||||||
return false
|
return false
|
||||||
if name_of_class.find("Editor") != -1: # TODO not sure about it
|
# Editor stuff usually aren't good choice for arhuments
|
||||||
|
if name_of_class.find("Editor") != -1 || name_of_class.find("SkinReference") != -1:
|
||||||
|
return false
|
||||||
|
|
||||||
|
# In case of adding new type, this prevents from crashing due not recognizing this type
|
||||||
|
# In case of removing/rename type, just comment e.g. TYPE_ARRAY and all occurencies on e.g. switch statement with it
|
||||||
|
var t : int = arg["type"]
|
||||||
|
if !(t == TYPE_NIL || t == TYPE_AABB || t == TYPE_ARRAY || t == TYPE_BASIS || t == TYPE_BOOL || t == TYPE_COLOR || t == TYPE_COLOR_ARRAY || t == TYPE_DICTIONARY || t == TYPE_INT || t == TYPE_INT_ARRAY || t == TYPE_NODE_PATH || t == TYPE_OBJECT || t == TYPE_PLANE || t == TYPE_QUAT || t == TYPE_RAW_ARRAY || t == TYPE_REAL || t == TYPE_REAL_ARRAY || t == TYPE_RECT2 || t == TYPE_RID || t == TYPE_STRING || t == TYPE_TRANSFORM || t == TYPE_TRANSFORM2D || t == TYPE_VECTOR2 || t == TYPE_VECTOR2_ARRAY || t == TYPE_VECTOR3 || t == TYPE_VECTOR3_ARRAY):
|
||||||
|
print("----------------------------------------------------------- TODO - MISSING TYPE, ADD SUPPORT IT") # Add assert here to get info which type is missing
|
||||||
return false
|
return false
|
||||||
|
|
||||||
#This is only for RegressionTestProject, because it needs for now clear visual info what is going on screen, but some nodes broke view
|
#This is only for RegressionTestProject, because it needs for now clear visual info what is going on screen, but some nodes broke view
|
||||||
if regression_test_project:
|
if regression_test_project:
|
||||||
|
# That means that this is constant, not class
|
||||||
|
if !ClassDB.class_exists(name_of_class):
|
||||||
|
continue
|
||||||
if !ClassDB.is_parent_class(name_of_class, "Node") && !ClassDB.is_parent_class(name_of_class, "Reference"):
|
if !ClassDB.is_parent_class(name_of_class, "Node") && !ClassDB.is_parent_class(name_of_class, "Reference"):
|
||||||
return false
|
return false
|
||||||
|
|
||||||
# In case of adding new type, this prevents from crashing due not recognizing this type
|
|
||||||
var t : int = arg["type"]
|
|
||||||
if !(t == TYPE_NIL || t == TYPE_AABB || t == TYPE_ARRAY || t == TYPE_BASIS || t == TYPE_BOOL || t == TYPE_COLOR || t == TYPE_COLOR_ARRAY || t == TYPE_DICTIONARY || t == TYPE_INT || t == TYPE_INT_ARRAY || t == TYPE_NODE_PATH || t == TYPE_OBJECT || t == TYPE_PLANE || t == TYPE_QUAT || t == TYPE_RAW_ARRAY || t == TYPE_REAL || t == TYPE_REAL_ARRAY || t == TYPE_RECT2 || t == TYPE_RID || t == TYPE_STRING || t == TYPE_TRANSFORM || t == TYPE_TRANSFORM2D || t == TYPE_VECTOR2 || t == TYPE_VECTOR2_ARRAY || t == TYPE_VECTOR3 || t == TYPE_VECTOR3_ARRAY):
|
|
||||||
print("----------------------------------------------------------- TODO - MISSING TYPE, ADD SUPPORT IT")
|
|
||||||
return false
|
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# Return all available classes to instance and test
|
func remove_disabled_methods(method_list : Array, exceptions : Array) -> void:
|
||||||
|
for exception in exceptions:
|
||||||
|
var index: int = -1
|
||||||
|
for method_index in range(method_list.size()):
|
||||||
|
if method_list[method_index]["name"] == exception:
|
||||||
|
index = method_index
|
||||||
|
break
|
||||||
|
if index != -1:
|
||||||
|
method_list.remove(index)
|
||||||
|
|
||||||
|
# Return all available classes which can be used
|
||||||
func get_list_of_available_classes(must_be_instantable : bool = true) -> Array:
|
func get_list_of_available_classes(must_be_instantable : bool = true) -> Array:
|
||||||
var full_class_list : Array = Array(ClassDB.get_class_list())
|
var full_class_list : Array = Array(ClassDB.get_class_list())
|
||||||
var classes : Array = []
|
var classes : Array = []
|
||||||
full_class_list.sort()
|
full_class_list.sort()
|
||||||
var c = 0
|
var c = 0
|
||||||
var rr = 0
|
# var rr = 0
|
||||||
for name_of_class in full_class_list:
|
for name_of_class in full_class_list:
|
||||||
rr += 1
|
# rr += 1
|
||||||
if name_of_class in disabled_classes:
|
if name_of_class in disabled_classes:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -306,7 +245,7 @@ func get_list_of_available_classes(must_be_instantable : bool = true) -> Array:
|
|||||||
|
|
||||||
if name_of_class.find("Server") != -1 && !ClassDB.is_parent_class(name_of_class,"Reference"):
|
if name_of_class.find("Server") != -1 && !ClassDB.is_parent_class(name_of_class,"Reference"):
|
||||||
continue
|
continue
|
||||||
if name_of_class.find("Editor") != -1: # TODO not sure about it
|
if name_of_class.find("Editor") != -1 && regression_test_project:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,18 +1,32 @@
|
|||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
# Execute every object function
|
### Script:
|
||||||
|
### - takes all available classes
|
||||||
|
### - checks if method is allowed
|
||||||
|
### - checks each argument if is allowed(in case e.g. adding new, to prevent crashes due not recognizing types)
|
||||||
|
### - print info if needed to console
|
||||||
|
### - execute function with parameters
|
||||||
|
|
||||||
var debug_print: bool = true
|
var debug_print: bool = true
|
||||||
var add_to_tree: bool = false # Adds nodes to tree, freeze godot when removing a lot of nodes
|
var add_to_tree: bool = false # Adds nodes to tree, freeze godot when removing a lot of nodes
|
||||||
var use_parent_methods: bool = false # Allows Node2D use Node methods etc. - it is a little slow option which rarely shows
|
var use_parent_methods: bool = false # Allows Node2D use Node methods etc. - it is a little slow option which rarely shows
|
||||||
var use_always_new_object: bool = true # Don't allow to "remeber" other function effects
|
var use_always_new_object: bool = true # Don't allow to "remeber" other function effects
|
||||||
var exiting: bool = true
|
var exiting: bool = false
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
if BasicData.regression_test_project:
|
||||||
|
ValueCreator.random = false # Results in RegressionTestProject must be always reproducible
|
||||||
|
else:
|
||||||
|
ValueCreator.random = true
|
||||||
|
|
||||||
|
ValueCreator.number = 100
|
||||||
|
ValueCreator.should_be_always_valid = false
|
||||||
|
|
||||||
if BasicData.regression_test_project:
|
if BasicData.regression_test_project:
|
||||||
tests_all_functions()
|
tests_all_functions()
|
||||||
|
|
||||||
|
|
||||||
func _process(_delta: float) -> void:
|
func _process(_delta: float) -> void:
|
||||||
if !BasicData.regression_test_project:
|
if !BasicData.regression_test_project:
|
||||||
tests_all_functions()
|
tests_all_functions()
|
||||||
@ -23,44 +37,54 @@ func _process(_delta: float) -> void:
|
|||||||
# Test all functions
|
# Test all functions
|
||||||
func tests_all_functions() -> void:
|
func tests_all_functions() -> void:
|
||||||
for name_of_class in BasicData.get_list_of_available_classes():
|
for name_of_class in BasicData.get_list_of_available_classes():
|
||||||
|
if debug_print:
|
||||||
|
print("\n#################### " + name_of_class + " ####################")
|
||||||
|
|
||||||
var object: Object = ClassDB.instance(name_of_class)
|
var object: Object = ClassDB.instance(name_of_class)
|
||||||
|
assert(object != null, "Object must be instantable")
|
||||||
if add_to_tree:
|
if add_to_tree:
|
||||||
if object is Node:
|
if object is Node:
|
||||||
add_child(object)
|
add_child(object)
|
||||||
var method_list: Array = ClassDB.class_get_method_list(name_of_class, !use_parent_methods)
|
var method_list: Array = ClassDB.class_get_method_list(name_of_class, !use_parent_methods)
|
||||||
|
|
||||||
## Exception
|
# Removes excluded methods
|
||||||
for exception in BasicData.function_exceptions:
|
BasicData.remove_disabled_methods(method_list, BasicData.function_exceptions)
|
||||||
var index: int = -1
|
|
||||||
for method_index in range(method_list.size()):
|
|
||||||
if method_list[method_index]["name"] == exception:
|
|
||||||
index = method_index
|
|
||||||
break
|
|
||||||
if index != -1:
|
|
||||||
method_list.remove(index)
|
|
||||||
|
|
||||||
if debug_print:
|
|
||||||
print("#################### " + name_of_class +" ####################")
|
|
||||||
for _i in range(1):
|
for _i in range(1):
|
||||||
for method_data in method_list:
|
for method_data in method_list:
|
||||||
if !BasicData.check_if_is_allowed(method_data):
|
if !BasicData.check_if_is_allowed(method_data):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if debug_print:
|
var arguments: Array = ParseArgumentType.parse_and_return_objects(method_data, name_of_class, debug_print)
|
||||||
print(name_of_class + "." + method_data["name"])
|
|
||||||
|
if debug_print:
|
||||||
|
var to_print: String = "GDSCRIPT CODE: "
|
||||||
|
if (
|
||||||
|
ClassDB.is_parent_class(name_of_class, "Object")
|
||||||
|
&& !ClassDB.is_parent_class(name_of_class, "Node")
|
||||||
|
&& !ClassDB.is_parent_class(name_of_class, "Reference")
|
||||||
|
&& !ClassDB.class_has_method(name_of_class, "new")
|
||||||
|
):
|
||||||
|
to_print += "ClassDB.instance(\"" + name_of_class + "\")." + method_data["name"] + "("
|
||||||
|
else:
|
||||||
|
to_print += name_of_class.trim_prefix("_") + ".new()." + method_data["name"] + "("
|
||||||
|
|
||||||
|
for i in arguments.size():
|
||||||
|
to_print += ParseArgumentType.return_gdscript_code_which_run_this_object(arguments[i])
|
||||||
|
if i != arguments.size() - 1:
|
||||||
|
to_print += ", "
|
||||||
|
to_print += ")"
|
||||||
|
print(to_print)
|
||||||
|
|
||||||
var arguments: Array = ParseArgumentType.parse_and_return_objects(method_data, debug_print)
|
|
||||||
object.callv(method_data["name"], arguments)
|
object.callv(method_data["name"], arguments)
|
||||||
|
|
||||||
for argument in arguments:
|
for argument in arguments:
|
||||||
if argument != null:
|
if argument is Node:
|
||||||
if argument is Node:
|
argument.queue_free()
|
||||||
argument.queue_free()
|
elif argument is Object && !(argument is Reference):
|
||||||
elif argument is Object && !(argument is Reference):
|
argument.free()
|
||||||
argument.free()
|
|
||||||
|
|
||||||
if use_always_new_object:
|
if use_always_new_object:
|
||||||
assert(object != null, "Object must be instantable")
|
|
||||||
if object is Node:
|
if object is Node:
|
||||||
object.queue_free()
|
object.queue_free()
|
||||||
elif object is Object && !(object is Reference):
|
elif object is Object && !(object is Reference):
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
# Parse arguments and return needed info/objects etc.
|
### Scripts to arguments and return needed info about them.
|
||||||
|
|
||||||
|
|
||||||
|
### Class which contains informations about used
|
||||||
class SingleArgument:
|
class SingleArgument:
|
||||||
var name: String # E.G. var roman, can be empty, so temp variable isn't created(nodes and objects must be created with temp_variable due to memory leaks)
|
var name: String # E.G. var roman, can be empty, so temp variable isn't created(nodes and objects must be created with temp_variable due to memory leaks)
|
||||||
var type: String # np. Vector2 or Object
|
var type: String # np. Vector2 or Object
|
||||||
@ -15,10 +17,6 @@ class SingleArgument:
|
|||||||
func create_gdscript_arguments(arguments: Array) -> Array:
|
func create_gdscript_arguments(arguments: Array) -> Array:
|
||||||
var argument_array: Array = []
|
var argument_array: Array = []
|
||||||
|
|
||||||
ValueCreator.number = 10
|
|
||||||
ValueCreator.random = true
|
|
||||||
ValueCreator.should_be_always_valid = true # DO NOT CHANGE, BECAUSE NON VALID VALUES WILL SHOW GDSCRIPT ERRORS!
|
|
||||||
|
|
||||||
var counter = 0
|
var counter = 0
|
||||||
for argument in arguments:
|
for argument in arguments:
|
||||||
counter += 1
|
counter += 1
|
||||||
@ -122,17 +120,9 @@ func create_gdscript_arguments(arguments: Array) -> Array:
|
|||||||
return argument_array
|
return argument_array
|
||||||
|
|
||||||
|
|
||||||
func parse_and_return_objects(method_data: Dictionary, debug_print: bool = false) -> Array:
|
func parse_and_return_objects(method_data: Dictionary, name_of_class: String, debug_print: bool = false) -> Array:
|
||||||
var arguments_array: Array = []
|
var arguments_array: Array = []
|
||||||
|
|
||||||
if BasicData.regression_test_project:
|
|
||||||
ValueCreator.number = 100
|
|
||||||
ValueCreator.random = false # Results in RegressionTestProject must be always reproducible
|
|
||||||
else:
|
|
||||||
ValueCreator.number = 1000
|
|
||||||
ValueCreator.random = true
|
|
||||||
ValueCreator.should_be_always_valid = false
|
|
||||||
|
|
||||||
for argument in method_data["args"]:
|
for argument in method_data["args"]:
|
||||||
match argument.type:
|
match argument.type:
|
||||||
TYPE_NIL: # Looks that this means VARIANT not null
|
TYPE_NIL: # Looks that this means VARIANT not null
|
||||||
@ -213,5 +203,196 @@ func parse_and_return_objects(method_data: Dictionary, debug_print: bool = false
|
|||||||
assert(false, "Missing type, needs to be added to project")
|
assert(false, "Missing type, needs to be added to project")
|
||||||
|
|
||||||
if debug_print:
|
if debug_print:
|
||||||
print("Parameters " + str(arguments_array))
|
print("\n" + name_of_class + "." + method_data["name"] + " --- executing with " + str(arguments_array.size()) + " parameters " + str(arguments_array))
|
||||||
return arguments_array
|
return arguments_array
|
||||||
|
|
||||||
|
|
||||||
|
func return_gdscript_code_which_run_this_object(data) -> String:
|
||||||
|
if data == null:
|
||||||
|
return "null"
|
||||||
|
|
||||||
|
var return_string: String = ""
|
||||||
|
|
||||||
|
match typeof(data):
|
||||||
|
TYPE_NIL: # Looks that this means VARIANT not null
|
||||||
|
assert("false", "This is even possible?")
|
||||||
|
TYPE_AABB:
|
||||||
|
return_string = "AABB("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.position)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.size)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_ARRAY:
|
||||||
|
return_string = "Array(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
TYPE_BASIS:
|
||||||
|
return_string = "Basis("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.x)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.y)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.z)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_BOOL:
|
||||||
|
if data == true:
|
||||||
|
return_string = "true"
|
||||||
|
else:
|
||||||
|
return_string = "false"
|
||||||
|
TYPE_COLOR:
|
||||||
|
return_string = "Color("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.r)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.g)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.b)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.a)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_COLOR_ARRAY:
|
||||||
|
return_string = "PoolColorArray(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
TYPE_DICTIONARY:
|
||||||
|
return_string = "{"
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.keys()[i])
|
||||||
|
return_string += " : "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.values()[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "}"
|
||||||
|
TYPE_INT:
|
||||||
|
return_string = str(data)
|
||||||
|
TYPE_INT_ARRAY:
|
||||||
|
return_string = "PoolIntArray(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
TYPE_NODE_PATH:
|
||||||
|
return_string = "NodePath("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(str(data))
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_OBJECT:
|
||||||
|
if data == null:
|
||||||
|
return_string = "null"
|
||||||
|
else:
|
||||||
|
var name_of_class: String = data.get_class()
|
||||||
|
if (
|
||||||
|
ClassDB.is_parent_class(name_of_class, "Object")
|
||||||
|
&& !ClassDB.is_parent_class(name_of_class, "Node")
|
||||||
|
&& !ClassDB.is_parent_class(name_of_class, "Reference")
|
||||||
|
&& !ClassDB.class_has_method(name_of_class, "new")
|
||||||
|
):
|
||||||
|
return_string += "ClassDB.instance(\"" + name_of_class + "\")"
|
||||||
|
else:
|
||||||
|
return_string = name_of_class.trim_prefix("_")
|
||||||
|
return_string += ".new()"
|
||||||
|
|
||||||
|
TYPE_PLANE:
|
||||||
|
return_string = "Plane("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.x)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.y)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.z)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.d)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_QUAT:
|
||||||
|
return_string = "Quat("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.x)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.y)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.z)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.w)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_RAW_ARRAY:
|
||||||
|
return_string = "PoolByteArray(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
TYPE_REAL:
|
||||||
|
return_string = str(data)
|
||||||
|
TYPE_REAL_ARRAY:
|
||||||
|
return_string = "PoolRealArray(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
TYPE_RECT2:
|
||||||
|
return_string = "Rect2("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.position)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.size)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_RID:
|
||||||
|
return_string = "RID()"
|
||||||
|
TYPE_STRING:
|
||||||
|
return_string = "\"" + data + "\""
|
||||||
|
TYPE_STRING_ARRAY:
|
||||||
|
return_string = "PoolStringArray(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
TYPE_TRANSFORM:
|
||||||
|
return_string = "Transform("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.basis)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.origin)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_TRANSFORM2D:
|
||||||
|
return_string = "Transform2D("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.x)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.y)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.origin)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_VECTOR2:
|
||||||
|
return_string = "Vector2("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.x)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.y)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_VECTOR2_ARRAY:
|
||||||
|
return_string = "PoolVector2Array(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
TYPE_VECTOR3:
|
||||||
|
return_string = "Vector3("
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.x)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.y)
|
||||||
|
return_string += ", "
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data.z)
|
||||||
|
return_string += ")"
|
||||||
|
TYPE_VECTOR3_ARRAY:
|
||||||
|
return_string = "PoolVector3Array(["
|
||||||
|
for i in data.size():
|
||||||
|
return_string += return_gdscript_code_which_run_this_object(data[i])
|
||||||
|
if i != data.size() - 1:
|
||||||
|
return_string += ", "
|
||||||
|
return_string += "])"
|
||||||
|
_:
|
||||||
|
assert(false, "Missing type, needs to be added to project")
|
||||||
|
|
||||||
|
return return_string
|
||||||
|
54
README.md
54
README.md
@ -50,18 +50,19 @@ A scene that will probably give people a hard time quite often is `FunctionExecu
|
|||||||
This is a fuzzer, but with removed ability to use random argument values (the arguments are identical every time it is run).
|
This is a fuzzer, but with removed ability to use random argument values (the arguments are identical every time it is run).
|
||||||
When the engine crashes, in logs usually will be something like this:
|
When the engine crashes, in logs usually will be something like this:
|
||||||
```
|
```
|
||||||
#################### SkeletonModification2DPhysicalBones ####################
|
#################### LineEdit ####################
|
||||||
SkeletonModification2DPhysicalBones.set_physical_bone_node
|
|
||||||
Parameters [100, ]
|
LineEdit._text_changed --- executing with 0 parameters []
|
||||||
ERROR: Joint index out of range!
|
GDSCRIPT CODE: LineEdit.new()._text_changed()
|
||||||
at: set_physical_bone_node (scene/resources/skeleton_modification_2d_physicalbones.cpp:259)
|
|
||||||
SkeletonModification2DPhysicalBones.get_physical_bone_node
|
LineEdit._toggle_draw_caret --- executing with 0 parameters []
|
||||||
Parameters [100]
|
GDSCRIPT CODE: LineEdit.new()._toggle_draw_caret()
|
||||||
ERROR: Joint index out of range!
|
|
||||||
at: get_physical_bone_node (scene/resources/skeleton_modification_2d_physicalbones.cpp:265)
|
LineEdit.set_align --- executing with 1 parameters [100]
|
||||||
SkeletonModification2DPhysicalBones.fetch_physical_bones
|
GDSCRIPT CODE: LineEdit.new().set_align(100)
|
||||||
Parameters []
|
ERROR: set_align: Index (int)p_align = 100 is out of bounds (4 = 4).
|
||||||
scene/resources/skeleton_modification_2d_physicalbones.cpp:186:2: runtime error: member access within null pointer of type 'struct SkeletonModificationStack2D'
|
At: scene/gui/line_edit.cpp:592.
|
||||||
|
scene/resources/line_edit.cpp:186:2: runtime error: member access within null pointer of type 'struct LineEdit'
|
||||||
handle_crash: Program crashed with signal 11
|
handle_crash: Program crashed with signal 11
|
||||||
Dumping the backtrace. Please include this when reporting the bug on godotengine/godot/issues
|
Dumping the backtrace. Please include this when reporting the bug on godotengine/godot/issues
|
||||||
[1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54)
|
[1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54)
|
||||||
@ -70,24 +71,24 @@ Dumping the backtrace. Please include this when reporting the bug on godotengine
|
|||||||
There are some interesting things to discuss here.
|
There are some interesting things to discuss here.
|
||||||
This line shows what class we are testing now
|
This line shows what class we are testing now
|
||||||
```
|
```
|
||||||
#################### SkeletonModification2DPhysicalBones ####################
|
#################### LineEdit ####################
|
||||||
```
|
```
|
||||||
which method
|
which method
|
||||||
```
|
```
|
||||||
SkeletonModification2DPhysicalBones.set_physical_bone_node
|
LineEdit.set_align
|
||||||
```
|
```
|
||||||
and which parameters (here are two arguments - `100`, \` \`(empty string))
|
and which parameters
|
||||||
```
|
```
|
||||||
Parameters [100, ]
|
--- executing with 1 parameters [100]
|
||||||
```
|
```
|
||||||
To make testing easier, each object is created from scratch and by looking at the class definition in Godot - `set_physical_bone_node(int, String)` we can create an expression that is executed on this line:
|
Next you can see GDScript command which is executed and you can copy it and test manually in Godot
|
||||||
```
|
```
|
||||||
SkeletonModification2DPhysicalBones.new().set_physical_bone_node(100,"")
|
GDSCRIPT CODE: LineEdit.new()._toggle_draw_caret()
|
||||||
```
|
```
|
||||||
Then you can see errors caused by invalid arguments, which you can ignore if they don't cause other crashes/leaks etc.
|
Then you can see errors caused by invalid arguments, which you can ignore if they don't cause other crashes/leaks etc.
|
||||||
```
|
```
|
||||||
ERROR: Joint index out of range!
|
ERROR: set_align: Index (int)p_align = 100 is out of bounds (4 = 4).
|
||||||
at: get_physical_bone_node (scene/resources/skeleton_modification_2d_physicalbones.cpp:265)
|
At: scene/gui/line_edit.cpp:592.
|
||||||
```
|
```
|
||||||
At the end we can see Godot's crash log with additional information that tried to use null pointer incorrectly:
|
At the end we can see Godot's crash log with additional information that tried to use null pointer incorrectly:
|
||||||
```
|
```
|
||||||
@ -97,14 +98,14 @@ Dumping the backtrace. Please include this when reporting the bug on godotengine
|
|||||||
[1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54)
|
[1] bin/godot.linuxbsd.tools.64s() [0x1e697d8] (/home/runner/work/godot/godot/platform/linuxbsd/crash_handler_linuxbsd.cpp:54)
|
||||||
[2] /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7fd1ca5b0210] (??:0)
|
[2] /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7fd1ca5b0210] (??:0)
|
||||||
```
|
```
|
||||||
we can assume that this is caused by calling the function immediately before the crash:
|
In most situations, the latest executed function/created object is responsible for crash
|
||||||
```
|
```
|
||||||
SkeletonModification2DPhysicalBones.fetch_physical_bones
|
LineEdit.set_align --- executing with 1 parameters [100]
|
||||||
Parameters []
|
GDSCRIPT CODE: LineEdit.new().set_align(100)
|
||||||
```
|
```
|
||||||
We can test this by running a function in Godot that looks like this(just add `.new()` after class name and fill function arguments from `Parameters`):
|
So we can just take GDScript code from above, copy it into Godot and test project, which should crash engine
|
||||||
```
|
```
|
||||||
SkeletonModification2DPhysicalBones.new().fetch_physical_bones()
|
LineEdit.new().set_align(100)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Nodes
|
## Nodes
|
||||||
@ -125,7 +126,8 @@ Scenes like `Physics2D.tscn` or `Lights3D.tscn` are normal scenes with specific
|
|||||||
|
|
||||||
## 4.0 version limitations
|
## 4.0 version limitations
|
||||||
ReparentingDeleting is in 4.0 only Reparenting - bug https://github.com/godotengine/godot/issues/45471
|
ReparentingDeleting is in 4.0 only Reparenting - bug https://github.com/godotengine/godot/issues/45471
|
||||||
Some scenes available in 3.x branch, but due freezes and long loading times are disabled.
|
Some scenes available in 3.x branch, but due freezes and long loading times are disabled(mostly Vulkan fault).
|
||||||
|
Some patches are applied to e.g. handle rename `OS` -> `Platform` or `Transform` -> `Transform3D`
|
||||||
|
|
||||||
## Epilepsy Warning
|
## Epilepsy Warning
|
||||||
Due using by project a lot of functions from each type of Node, screen may flicker, images and objects may change randomly color and size which may lead some users to health problems.
|
Due using by project a lot of functions from each type of Node, screen may flicker, images and objects may change randomly color and size which may lead some users to health problems.
|
||||||
|
Loading…
Reference in New Issue
Block a user