diff --git a/check.sh b/check.sh index 01b409730..76d50b6e4 100755 --- a/check.sh +++ b/check.sh @@ -34,11 +34,14 @@ Commands: Options: -h, --help print this help text --double run check with double-precision + -f, --filter only run integration tests which contain any of the + args (comma-separated). requires itest. Examples: check.sh fmt clippy check.sh check.sh --double clippy + check.sh test itest -f variant,static RUSTUP_TOOLCHAIN=nightly check.sh EOF @@ -140,7 +143,7 @@ function cmd_test() { function cmd_itest() { findGodot && \ run cargo build -p itest "${extraCargoArgs[@]}" && \ - run "$godotBin" --path itest/godot --headless + run "$godotBin" --path itest/godot --headless -- "[${extraArgs[@]}]" } function cmd_doc() { @@ -159,6 +162,8 @@ function cmd_dok() { # between `itest` compilations and `check.sh` runs. extraCargoArgs=("--no-default-features") cmds=() +eatArgsAsFilter=false +extraArgs=() for arg in "$@"; do case "$arg" in @@ -172,9 +177,17 @@ for arg in "$@"; do fmt | clippy | test | itest | doc | dok) cmds+=("$arg") ;; + -f | --filtering) + eatArgsAsFilter=true + ;; *) - log "Unrecognized argument '$arg'. Use '$0 --help' to see what's available." - exit 2 + if $eatArgsAsFilter; then + extraArgs+=("$arg") + eatArgsAsFilter=false + else + log "Unrecognized argument '$arg'. Use '$0 --help' to see what's available." + exit 2 + fi ;; esac done diff --git a/itest/godot/TestRunner.gd b/itest/godot/TestRunner.gd index 4d492e346..e352c4ff5 100644 --- a/itest/godot/TestRunner.gd +++ b/itest/godot/TestRunner.gd @@ -10,13 +10,18 @@ func _ready(): await get_tree().physics_frame var allow_focus := true + var filters: Array = [] var unrecognized_args: Array = [] for arg in OS.get_cmdline_user_args(): match arg: "--disallow-focus": allow_focus = false _: - unrecognized_args.push_back(arg) + if not arg.begins_with("[") or not arg.ends_with("]"): + unrecognized_args.push_back(arg) + + var args = arg.lstrip("[").rstrip("]").split(",") + filters.append_array(args) if unrecognized_args: push_error("Unrecognized arguments: ", unrecognized_args) @@ -53,6 +58,7 @@ func _ready(): gdscript_suites.size(), allow_focus, self, + filters ) var exit_code: int = 0 if success else 1 diff --git a/itest/godot/project.godot b/itest/godot/project.godot index ffccee723..75b364aa8 100644 --- a/itest/godot/project.godot +++ b/itest/godot/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="IntegrationTests" run/main_scene="res://TestRunner.tscn" -config/features=PackedStringArray("4.0") +config/features=PackedStringArray("4.1") run/flush_stdout_on_print=true [debug] diff --git a/itest/rust/src/lib.rs b/itest/rust/src/lib.rs index ebdb311be..77469ac3a 100644 --- a/itest/rust/src/lib.rs +++ b/itest/rust/src/lib.rs @@ -85,7 +85,7 @@ unsafe impl ExtensionLibrary for runner::IntegrationTests {} sys::plugin_registry!(__GODOT_ITEST: RustTestCase); /// Finds all `#[itest]` tests. -fn collect_rust_tests() -> (Vec, usize, bool) { +fn collect_rust_tests(filters: &[String]) -> (Vec, usize, bool) { let mut all_files = std::collections::HashSet::new(); let mut tests: Vec = vec![]; let mut is_focus_run = false; @@ -99,7 +99,7 @@ fn collect_rust_tests() -> (Vec, usize, bool) { } // Only collect tests if normal mode, or focus mode and test is focused. - if !is_focus_run || test.focused { + if (!is_focus_run || test.focused) && passes_filter(filters, test.name) { all_files.insert(test.file); tests.push(*test); } @@ -126,3 +126,7 @@ struct RustTestCase { line: u32, function: fn(&TestContext), } + +pub(crate) fn passes_filter(filters: &[String], test_name: &str) -> bool { + filters.is_empty() || filters.iter().any(|x| test_name.contains(x)) +} diff --git a/itest/rust/src/runner.rs b/itest/rust/src/runner.rs index e86763217..93d3581b1 100644 --- a/itest/rust/src/runner.rs +++ b/itest/rust/src/runner.rs @@ -12,7 +12,7 @@ use godot::engine::{Engine, Node}; use godot::log::godot_error; use godot::obj::Gd; -use crate::{RustTestCase, TestContext}; +use crate::{passes_filter, RustTestCase, TestContext}; #[derive(GodotClass, Debug)] #[class(init)] @@ -33,10 +33,19 @@ impl IntegrationTests { gdscript_file_count: i64, allow_focus: bool, scene_tree: Gd, + filters: VariantArray, ) -> bool { println!("{}Run{} Godot integration tests...", FMT_CYAN_BOLD, FMT_END); - - let (rust_tests, rust_file_count, focus_run) = super::collect_rust_tests(); + let filters: Vec = filters.iter_shared().map(|v| v.to::()).collect(); + let gdscript_tests = gdscript_tests + .iter_shared() + .filter(|test| { + let test_name = get_property(test, "method_name"); + passes_filter(filters.as_slice(), &test_name) + }) + .collect::>(); + let (rust_tests, rust_file_count, focus_run) = + super::collect_rust_tests(filters.as_slice()); self.focus_run = focus_run; if focus_run { println!(" {FMT_CYAN}Focused run{FMT_END} -- execute only selected Rust tests.")