upgrade gut

This commit is contained in:
anyreso 2026-02-19 03:14:22 -05:00
parent 6e724f67fe
commit 82aeebfd35
201 changed files with 8547 additions and 3871 deletions

View file

@ -1 +1 @@
uid://cfqihvbcwhtkg
uid://1pauyfnd1cre

View file

@ -105,6 +105,10 @@ Options whose values are lists/arrays can be specified multiple times:
-gdir c,d
-gdir e
# results in -gdir equaling [a, b, c, d, e]
To not use an empty value instead of a default value, specifiy the option with
an immediate "=":
-gconfig=
"""
opts.add_heading("Test Config:")
opts.add('-gdir', options.dirs, 'List of directories to search for test scripts in.')
@ -125,6 +129,8 @@ Options whose values are lists/arrays can be specified multiple times:
opts.add('-gexit', false, 'Exit after running tests. If not specified you have to manually close the window.')
opts.add('-gexit_on_success', false, 'Only exit if zero tests fail.')
opts.add('-gignore_pause', false, 'Ignores any calls to pause_before_teardown.')
opts.add('-gno_error_tracking', false, 'Disable error tracking.')
opts.add('-gfailure_error_types', options.failure_error_types, 'Error types that will cause tests to fail if the are encountered during the execution of a test. Default "[default]"')
opts.add_heading("Display Settings:")
opts.add('-glog', options.log_level, 'Log level [0-3]. Default [default]')
@ -138,6 +144,7 @@ Options whose values are lists/arrays can be specified multiple times:
opts.add('-gbackground_color', options.background_color, 'Background color as an html color, default "[default]"')
opts.add('-gfont_color',options.font_color, 'Font color as an html color, default "[default]"')
opts.add('-gpaint_after', options.paint_after, 'Delay before GUT will add a 1 frame pause to paint the screen/GUI. default [default]')
opts.add('-gwait_log_delay', options.wait_log_delay, 'Delay before GUT will print a message to indicate a test is awaiting one of the wait_* methods. Default [default]')
opts.add_heading("Result Export:")
opts.add('-gjunit_xml_file', options.junit_xml_file, 'Export results of run to this file in the Junit XML format.')
@ -148,16 +155,22 @@ Options whose values are lists/arrays can be specified multiple times:
opts.add('-gpo', false, 'Print option values from all sources and the value used.')
opts.add('-gprint_gutconfig_sample', false, 'Print out json that can be used to make a gutconfig file.')
# run as in editor, for shelling out purposes through Editor.
var o = opts.add('-graie', false, 'do not use')
o.show_in_help = false
return opts
# Parses options, applying them to the _tester or setting values
# in the options struct.
func extract_command_line_options(from, to):
to.compact_mode = from.get_value_or_null('-gcompact_mode')
to.config_file = from.get_value_or_null('-gconfig')
to.dirs = from.get_value_or_null('-gdir')
to.disable_colors = from.get_value_or_null('-gdisable_colors')
to.double_strategy = from.get_value_or_null('-gdouble_strategy')
to.errors_do_not_cause_failure = from.get_value_or_null('-gerrors_do_not_cause_failure')
to.hide_orphans = from.get_value_or_null('-ghide_orphans')
to.ignore_pause = from.get_value_or_null('-gignore_pause')
to.include_subdirs = from.get_value_or_null('-ginclude_subdirs')
to.inner_class = from.get_value_or_null('-ginner_class')
@ -170,22 +183,24 @@ func extract_command_line_options(from, to):
to.should_exit = from.get_value_or_null('-gexit')
to.should_exit_on_success = from.get_value_or_null('-gexit_on_success')
to.should_maximize = from.get_value_or_null('-gmaximize')
to.compact_mode = from.get_value_or_null('-gcompact_mode')
to.hide_orphans = from.get_value_or_null('-ghide_orphans')
to.suffix = from.get_value_or_null('-gsuffix')
to.errors_do_not_cause_failure = from.get_value_or_null('-gerrors_do_not_cause_failure')
to.tests = from.get_value_or_null('-gtest')
to.unit_test_name = from.get_value_or_null('-gunit_test_name')
to.wait_log_delay = from.get_value_or_null('-gwait_log_delay')
to.font_size = from.get_value_or_null('-gfont_size')
to.font_name = from.get_value_or_null('-gfont_name')
to.background_color = from.get_value_or_null('-gbackground_color')
to.font_color = from.get_value_or_null('-gfont_color')
to.font_name = from.get_value_or_null('-gfont_name')
to.font_size = from.get_value_or_null('-gfont_size')
to.paint_after = from.get_value_or_null('-gpaint_after')
to.junit_xml_file = from.get_value_or_null('-gjunit_xml_file')
to.junit_xml_timestamp = from.get_value_or_null('-gjunit_xml_timestamp')
to.failure_error_types = from.get_value_or_null('-gfailure_error_types')
to.no_error_tracking = from.get_value_or_null('-gno_error_tracking')
to.raie = from.get_value_or_null('-graie')
func _print_gutconfigs(values):
@ -217,7 +232,10 @@ func _run_tests(opt_resolver):
runner.set_gut_config(_gut_config)
get_tree().root.add_child(runner)
runner.run_tests()
if(opt_resolver.cmd_opts.raie):
runner.run_from_editor()
else:
runner.run_tests()
# parse options and run Gut

View file

@ -1 +1 @@
uid://ddx1kavbbraby
uid://bhuudqinp4bth

View file

@ -42,7 +42,8 @@
## created Option instance. See that class above for more info. You can use
## the returned instance to get values, or use get_value/get_value_or_null.
## add("--name", "default", "Description goes here")
## add_required("--name", "default", "Description goes here")
## add(["--name", "--aliases"], "default", "Description goes here")
## add_required(["--name", "--aliases"], "default", "Description goes here")
## add_positional("--name", "default", "Description goes here")
## add_positional_required("--name", "default", "Description goes here")
##
@ -153,6 +154,8 @@ class Option:
var default = null
var description = ''
var required = false
var aliases: Array[String] = []
var show_in_help = true
func _init(name,default_value,desc=''):
@ -162,12 +165,51 @@ class Option:
_value = default
func to_s(min_space=0):
func wrap_text(text, left_indent, max_length, wiggle_room=15):
var line_indent = str("\n", " ".repeat(left_indent + 1))
var wrapped = ''
var position = 0
var split_length = max_length
while(position < text.length()):
if(position > 0):
wrapped += line_indent
var split_by = split_length
if(position + split_by + wiggle_room >= text.length()):
split_by = text.length() - position
else:
var min_space = text.rfind(' ', position + split_length)
var max_space = text.find(' ', position + split_length)
if(max_space <= position + split_length + wiggle_room):
split_by = max_space - position
else:
split_by = min_space - position
wrapped += text.substr(position, split_by).lstrip(' ')
if(position == 0):
split_length = max_length - left_indent
position += split_by
return wrapped
func to_s(min_space=0, wrap_length=100):
var line_indent = str("\n", " ".repeat(min_space + 1))
var subbed_desc = description
if not aliases.is_empty():
subbed_desc += "\naliases: " + ", ".join(aliases)
subbed_desc = subbed_desc.replace('[default]', str(default))
subbed_desc = subbed_desc.replace("\n", line_indent)
return str(option_name.rpad(min_space), ' ', subbed_desc)
var final = str(option_name.rpad(min_space), ' ', subbed_desc)
if(wrap_length != -1):
final = wrap_text(final, min_space, wrap_length)
return final
func has_been_set():
@ -196,7 +238,7 @@ class Options:
var default_heading = OptionHeading.new()
var script_option = Option.new('-s', '?', 'script option provided by Godot')
var _options_by_name = {}
var _options_by_name = {"--script": script_option, "-s": script_option}
var _options_by_heading = [default_heading]
var _cur_heading = default_heading
@ -208,11 +250,16 @@ class Options:
_options_by_heading.append(heading)
func add(option):
func add(option, aliases=null):
options.append(option)
_options_by_name[option.option_name] = option
_cur_heading.options.append(option)
if aliases != null:
for a in aliases:
_options_by_name[a] = option
option.aliases.assign(aliases)
func add_positional(option):
positional.append(option)
@ -221,9 +268,7 @@ class Options:
func get_by_name(option_name):
var found_param = null
if(option_name == script_option.option_name):
found_param = script_option
elif(_options_by_name.has(option_name)):
if(_options_by_name.has(option_name)):
found_param = _options_by_name[option_name]
return found_param
@ -240,8 +285,8 @@ class Options:
if(heading != default_heading):
text += str("\n", heading.display, "\n")
for option in heading.options:
text += str(' ', option.to_s(longest + 2).replace("\n", "\n "), "\n")
if(option.show_in_help):
text += str(' ', option.to_s(longest + 2).replace("\n", "\n "), "\n")
return text
@ -296,19 +341,28 @@ class Options:
#-------------------------------------------------------------------------------
#
# optarse
#
#-------------------------------------------------------------------------------
var options = Options.new()
var banner = ''
var option_name_prefix = '-'
## @ignore
var options := Options.new()
## Set the banner property to any text you want to appear before the usage and
## options sections when printing the options help.
var banner := ''
## optparse uses option_name_prefix to differentiate between option names and
## values. Any argument that starts with this value will be treated as an
## argument name. The default is "-". Set this before calling parse if you want
## to change it.
var option_name_prefix := '-'
## @ignore
var unused = []
## @ignore
var parsed_args = []
var values = {}
## @ignore
var values: Dictionary = {}
func _populate_values_dictionary():
for entry in options.options:
@ -320,7 +374,6 @@ func _populate_values_dictionary():
values[value_key] = entry.value
func _convert_value_to_array(raw_value):
var split = raw_value.split(',')
# This is what an empty set looks like from the command line. If we do
@ -330,7 +383,6 @@ func _convert_value_to_array(raw_value):
split = []
return split
# REMEMBER raw_value not used for bools.
func _set_option_value(option, raw_value):
var t = typeof(option.default)
@ -403,30 +455,87 @@ func _parse_command_line_arguments(args):
return parsed_opts
func is_option(arg):
## Test if something is an existing argument. If [code]str(arg)[/code] begins
## with the [member option_name_prefix], it will considered true,
## otherwise it will be considered false.
func is_option(arg) -> bool:
return str(arg).begins_with(option_name_prefix)
func add(op_name, default, desc):
var new_op = null
## Adds a command line option.
## If [param op_names] is a String, this is set as the argument's name.
## If [param op_names] is an Array of Strings, all elements of the array
## will be aliases for the same argument and will be treated as such during
## parsing.
## [param default] is the default value the option will be set to if it is not
## explicitly set during parsing.
## [param desc] is a human readable text description of the option.
## If the option is successfully added, the Option object will be returned.
## If the option is not successfully added (e.g. a name collision with another
## option occurs), an error message will be printed and [code]null[/code]
## will be returned.
func add(op_names, default, desc: String) -> Option:
var op_name: String
var aliases: Array[String] = []
var new_op: Option = null
if(typeof(op_names) == TYPE_STRING):
op_name = op_names
else:
op_name = op_names[0]
aliases.assign(op_names.slice(1))
var bad_alias: int = aliases.map(
func (a: String) -> bool: return options.get_by_name(a) != null
).find(true)
if(options.get_by_name(op_name) != null):
push_error(str('Option [', op_name, '] already exists.'))
elif bad_alias != -1:
push_error(str('Option [', aliases[bad_alias], '] already exists.'))
else:
new_op = Option.new(op_name, default, desc)
options.add(new_op)
options.add(new_op, aliases)
return new_op
func add_required(op_name, default, desc):
var op = add(op_name, default, desc)
## Adds a required command line option.
## Required options that have not been set may be collected after parsing
## by calling [method get_missing_required_options].
## If [param op_names] is a String, this is set as the argument's name.
## If [param op_names] is an Array of Strings, all elements of the array
## will be aliases for the same argument and will be treated as such during
## parsing.
## [param default] is the default value the option will be set to if it is not
## explicitly set during parsing.
## [param desc] is a human readable text description of the option.
## If the option is successfully added, the Option object will be returned.
## If the option is not successfully added (e.g. a name collision with another
## option occurs), an error message will be printed and [code]null[/code]
## will be returned.
func add_required(op_names, default, desc: String) -> Option:
var op := add(op_names, default, desc)
if(op != null):
op.required = true
return op
func add_positional(op_name, default, desc):
## Adds a positional command line option.
## Positional options are parsed by their position in the list of arguments
## are are not assigned by name by the user.
## If [param op_name] is a String, this is set as the argument's name.
## If [param op_name] is an Array of Strings, all elements of the array
## will be aliases for the same argument and will be treated as such during
## parsing.
## [param default] is the default value the option will be set to if it is not
## explicitly set during parsing.
## [param desc] is a human readable text description of the option.
## If the option is successfully added, the Option object will be returned.
## If the option is not successfully added (e.g. a name collision with another
## option occurs), an error message will be printed and [code]null[/code]
## will be returned.
func add_positional(op_name, default, desc: String) -> Option:
var new_op = null
if(options.get_by_name(op_name) != null):
push_error(str('Positional option [', op_name, '] already exists.'))
@ -436,35 +545,64 @@ func add_positional(op_name, default, desc):
return new_op
func add_positional_required(op_name, default, desc):
## Adds a required positional command line option.
## If [param op_name] is a String, this is set as the argument's name.
## Required options that have not been set may be collected after parsing
## by calling [method get_missing_required_options].
## Positional options are parsed by their position in the list of arguments
## are are not assigned by name by the user.
## If [param op_name] is an Array of Strings, all elements of the array
## will be aliases for the same argument and will be treated as such during
## parsing.
## [param default] is the default value the option will be set to if it is not
## explicitly set during parsing.
## [param desc] is a human readable text description of the option.
## If the option is successfully added, the Option object will be returned.
## If the option is not successfully added (e.g. a name collision with another
## option occurs), an error message will be printed and [code]null[/code]
## will be returned.
func add_positional_required(op_name, default, desc: String) -> Option:
var op = add_positional(op_name, default, desc)
if(op != null):
op.required = true
return op
func add_heading(display_text):
## Headings are used to separate logical groups of command line options
## when printing out options from the help menu.
## Headings are printed out between option descriptions in the order
## that [method add_heading] was called.
func add_heading(display_text: String) -> void:
options.add_heading(display_text)
func get_value(name):
var found_param = options.get_by_name(name)
## Gets the value assigned to an option after parsing.
## [param name] can be the name of the option or an alias of it.
## [param name] specifies the option whose value you wish to query.
## If the option exists, the value assigned to it during parsing is returned.
## Otherwise, an error message is printed and [code]null[/code] is returned.
func get_value(name: String):
var found_param: Option = options.get_by_name(name)
if(found_param != null):
return found_param.value
else:
print("COULD NOT FIND OPTION " + name)
push_error("COULD NOT FIND OPTION " + name)
return null
# This will return null instead of the default value if an option has not been
# specified. This can be useful when providing an order of precedence to your
# values. For example if
# default value < config file < command line
# then you do not want to get the default value for a command line option or it
# will overwrite the value in a config file.
func get_value_or_null(name):
var found_param = options.get_by_name(name)
## Gets the value assigned to an option after parsing,
## returning null if the option was not assigned instead of its default value.
## [param name] specifies the option whose value you wish to query.
## This can be useful when providing an order of precedence to your values.
## For example if
## [codeblock]
## default value < config file < command line
## [/codeblock]
## then you do not want to get the default value for a command line option or
## it will overwrite the value in a config file.
func get_value_or_null(name: String):
var found_param: Option = options.get_by_name(name)
if(found_param != null and found_param.has_been_set()):
return found_param.value
@ -472,10 +610,11 @@ func get_value_or_null(name):
return null
func get_help():
var sep = '---------------------------------------------------------'
## Returns the help text for all defined options.
func get_help() -> String:
var sep := '---------------------------------------------------------'
var text = str(sep, "\n", banner, "\n\n")
var text := str(sep, "\n", banner, "\n\n")
text += "Usage\n-----------\n"
text += " " + options.get_usage_text() + "\n\n"
text += "\nOptions\n-----------\n"
@ -484,11 +623,18 @@ func get_help():
return text
func print_help():
## Prints out the help text for all defined options.
func print_help() -> void:
print(get_help())
func parse(cli_args=null):
## Parses a string for all options that have been set in this optparse.
## if [param cli_args] is passed as a String, then it is parsed.
## Otherwise if [param cli_args] is null,
## aruments passed to the Godot engine at startup are parsed.
## See the explanation at the top of addons/gut/cli/optparse.gd to understand
## which arguments this will have access to.
func parse(cli_args=null) -> void:
parsed_args = cli_args
if(parsed_args == null):
@ -499,7 +645,9 @@ func parse(cli_args=null):
_populate_values_dictionary()
func get_missing_required_options():
## Get all options that were required and were not set during parsing.
## The return value is an Array of Options.
func get_missing_required_options() -> Array:
return options.get_missing_required_options()

View file

@ -1 +1 @@
uid://bt37la38fetnn
uid://c8m4fojwln6bq