From 51dd25319746e2de9cd4f145ef897fdc89397578 Mon Sep 17 00:00:00 2001 From: Ali Caglayan Date: Sat, 1 Nov 2025 16:06:51 +0000 Subject: [PATCH 1/5] test(runtest): runtest hints Signed-off-by: Ali Caglayan --- .../test-cases/runtest-cmd-hints.t | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/blackbox-tests/test-cases/runtest-cmd-hints.t diff --git a/test/blackbox-tests/test-cases/runtest-cmd-hints.t b/test/blackbox-tests/test-cases/runtest-cmd-hints.t new file mode 100644 index 00000000000..f61550f2c9c --- /dev/null +++ b/test/blackbox-tests/test-cases/runtest-cmd-hints.t @@ -0,0 +1,22 @@ +Test the "did you mean" hints for dune runtest command. + + $ cat > dune-project < (lang dune 3.21) + > EOF + + $ mkdir dir.t other_dir + $ cat > dir.t/run.t < $ echo "Directory-based cram test" + > Directory-based cram test + > EOF + $ cat > dir_t + + $ dune test dip.t + Error: "dip.t" does not match any known test. + Hint: did you mean dir_t or dir.t? + [1] + + $ dune test other_dip + Error: "other_dip" does not match any known test. + Hint: did you mean other_dir? + [1] From ff33ed99176aed9505882204012802a3b8814d7c Mon Sep 17 00:00:00 2001 From: Ali Caglayan Date: Sun, 26 Oct 2025 23:03:42 +0100 Subject: [PATCH 2/5] refactor: split finding cram tests and collecting cram tests Signed-off-by: Ali Caglayan --- bin/runtest_common.ml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/bin/runtest_common.ml b/bin/runtest_common.ml index 29f908f56bc..3dba565e0c9 100644 --- a/bin/runtest_common.ml +++ b/bin/runtest_common.ml @@ -1,21 +1,23 @@ open Import -let find_cram_test path ~parent_dir = +let cram_tests_of_dir parent_dir = let open Memo.O in Source_tree.find_dir parent_dir >>= function - | None -> Memo.return None - | Some dir -> - Dune_rules.Cram_rules.cram_tests dir - >>| List.find_map ~f:(function - | Ok cram_test when Path.Source.equal path (Source.Cram_test.path cram_test) -> - Some cram_test - (* We raise any error we encounter when looking for our test specifically. *) - | Error (Dune_rules.Cram_rules.Missing_run_t cram_test) - when Path.Source.equal path (Source.Cram_test.path cram_test) -> - Dune_rules.Cram_rules.missing_run_t cram_test - (* Any errors or successes unrelated to our test are discarded. *) - | Error (Dune_rules.Cram_rules.Missing_run_t _) | Ok _ -> None) + | None -> Memo.return [] + | Some dir -> Dune_rules.Cram_rules.cram_tests dir +;; + +let find_cram_test cram_tests path = + List.find_map cram_tests ~f:(function + | Ok cram_test when Path.Source.equal path (Source.Cram_test.path cram_test) -> + Some cram_test + (* We raise any error we encounter when looking for our test specifically. *) + | Error (Dune_rules.Cram_rules.Missing_run_t cram_test) + when Path.Source.equal path (Source.Cram_test.path cram_test) -> + Dune_rules.Cram_rules.missing_run_t cram_test + (* Any errors or successes unrelated to our test are discarded. *) + | Error (Dune_rules.Cram_rules.Missing_run_t _) | Ok _ -> None) ;; let explain_unsuccessful_search path ~parent_dir = @@ -57,8 +59,8 @@ let disambiguate_test_name path = | None -> Memo.return @@ `Runtest (Path.source Path.Source.root) | Some parent_dir -> let open Memo.O in - find_cram_test path ~parent_dir - >>= (function + let* cram_tests = cram_tests_of_dir parent_dir in + (match find_cram_test cram_tests path with | Some test -> (* If we find the cram test, then we request that is run. *) Memo.return (`Cram (parent_dir, test)) From e80ac2de7cdde77f6f53e3ac79a4a8e849b01c40 Mon Sep 17 00:00:00 2001 From: Ali Caglayan Date: Sun, 26 Oct 2025 23:12:09 +0100 Subject: [PATCH 3/5] cram: only suggest cram tests in error Signed-off-by: Ali Caglayan --- bin/runtest_common.ml | 11 +++++++---- test/blackbox-tests/test-cases/runtest-cmd-hints.t | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/bin/runtest_common.ml b/bin/runtest_common.ml index 3dba565e0c9..404cb47bb0f 100644 --- a/bin/runtest_common.ml +++ b/bin/runtest_common.ml @@ -27,9 +27,12 @@ let explain_unsuccessful_search path ~parent_dir = (* We search for all files and directories in the parent directory and suggest them as possible candidates. *) let+ candidates = - let+ file_candidates = - let+ files = Source_tree.files_of parent_dir in - Path.Source.Set.to_list_map files ~f:Path.Source.to_string + let+ cram_candidates = + let+ cram_tests = cram_tests_of_dir parent_dir in + List.filter_map cram_tests ~f:(fun res -> + Result.to_option res + |> Option.map ~f:(fun test -> + Source.Cram_test.path test |> Path.Source.to_string)) and+ dir_candidates = let* parent_source_dir = Source_tree.find_dir parent_dir in match parent_source_dir with @@ -42,7 +45,7 @@ let explain_unsuccessful_search path ~parent_dir = >>| Source_tree.Dir.path >>| Path.Source.to_string) in - List.concat [ file_candidates; dir_candidates ] + List.concat [ cram_candidates; dir_candidates ] in User_message.did_you_mean (Path.Source.to_string path) ~candidates in diff --git a/test/blackbox-tests/test-cases/runtest-cmd-hints.t b/test/blackbox-tests/test-cases/runtest-cmd-hints.t index f61550f2c9c..5f77f830b7a 100644 --- a/test/blackbox-tests/test-cases/runtest-cmd-hints.t +++ b/test/blackbox-tests/test-cases/runtest-cmd-hints.t @@ -13,7 +13,7 @@ Test the "did you mean" hints for dune runtest command. $ dune test dip.t Error: "dip.t" does not match any known test. - Hint: did you mean dir_t or dir.t? + Hint: did you mean dir.t or dir.t? [1] $ dune test other_dip From 8273a71b5fdc3c8ac68c6ce9cf4f160ba0b29b51 Mon Sep 17 00:00:00 2001 From: Ali Caglayan Date: Sun, 26 Oct 2025 23:22:10 +0100 Subject: [PATCH 4/5] refactor(runtest): split finding candidates and did you mean error Signed-off-by: Ali Caglayan --- bin/runtest_common.ml | 52 ++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/bin/runtest_common.ml b/bin/runtest_common.ml index 404cb47bb0f..e6cd58f50af 100644 --- a/bin/runtest_common.ml +++ b/bin/runtest_common.ml @@ -20,37 +20,33 @@ let find_cram_test cram_tests path = | Error (Dune_rules.Cram_rules.Missing_run_t _) | Ok _ -> None) ;; -let explain_unsuccessful_search path ~parent_dir = +let all_tests_of_dir parent_dir = let open Memo.O in - (* If the user misspelled the test name, we give them a hint. *) - let+ hints = - (* We search for all files and directories in the parent directory and - suggest them as possible candidates. *) - let+ candidates = - let+ cram_candidates = - let+ cram_tests = cram_tests_of_dir parent_dir in - List.filter_map cram_tests ~f:(fun res -> - Result.to_option res - |> Option.map ~f:(fun test -> - Source.Cram_test.path test |> Path.Source.to_string)) - and+ dir_candidates = - let* parent_source_dir = Source_tree.find_dir parent_dir in - match parent_source_dir with - | None -> Memo.return [] - | Some parent_source_dir -> - let dirs = Source_tree.Dir.sub_dirs parent_source_dir in - String.Map.to_list dirs - |> Memo.List.map ~f:(fun (_candidate, candidate_path) -> - Source_tree.Dir.sub_dir_as_t candidate_path - >>| Source_tree.Dir.path - >>| Path.Source.to_string) - in - List.concat [ cram_candidates; dir_candidates ] - in - User_message.did_you_mean (Path.Source.to_string path) ~candidates + let+ cram_candidates = + cram_tests_of_dir parent_dir + >>| List.filter_map ~f:(fun res -> + Result.to_option res + |> Option.map ~f:(fun test -> Source.Cram_test.path test |> Path.Source.to_string)) + and+ dir_candidates = + let* parent_source_dir = Source_tree.find_dir parent_dir in + match parent_source_dir with + | None -> Memo.return [] + | Some parent_source_dir -> + let dirs = Source_tree.Dir.sub_dirs parent_source_dir in + String.Map.to_list dirs + |> Memo.List.map ~f:(fun (_candidate, candidate_path) -> + Source_tree.Dir.sub_dir_as_t candidate_path + >>| Source_tree.Dir.path + >>| Path.Source.to_string) in + List.concat [ cram_candidates; dir_candidates ] +;; + +let explain_unsuccessful_search path ~parent_dir = + let open Memo.O in + let+ candidates = all_tests_of_dir parent_dir in User_error.raise - ~hints + ~hints:(User_message.did_you_mean (Path.Source.to_string path) ~candidates) [ Pp.textf "%S does not match any known test." (Path.Source.to_string path) ] ;; From 07459510d5f7a8d6fab10845f6cc365cbbcad587 Mon Sep 17 00:00:00 2001 From: Ali Caglayan Date: Sun, 26 Oct 2025 23:22:10 +0100 Subject: [PATCH 5/5] cram: deduplicate candidates for test not found Signed-off-by: Ali Caglayan --- bin/runtest_common.ml | 2 ++ test/blackbox-tests/test-cases/runtest-cmd-hints.t | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/runtest_common.ml b/bin/runtest_common.ml index e6cd58f50af..c235a30ae76 100644 --- a/bin/runtest_common.ml +++ b/bin/runtest_common.ml @@ -40,6 +40,8 @@ let all_tests_of_dir parent_dir = >>| Path.Source.to_string) in List.concat [ cram_candidates; dir_candidates ] + |> String.Set.of_list + |> String.Set.to_list ;; let explain_unsuccessful_search path ~parent_dir = diff --git a/test/blackbox-tests/test-cases/runtest-cmd-hints.t b/test/blackbox-tests/test-cases/runtest-cmd-hints.t index 5f77f830b7a..105a567eb20 100644 --- a/test/blackbox-tests/test-cases/runtest-cmd-hints.t +++ b/test/blackbox-tests/test-cases/runtest-cmd-hints.t @@ -13,7 +13,7 @@ Test the "did you mean" hints for dune runtest command. $ dune test dip.t Error: "dip.t" does not match any known test. - Hint: did you mean dir.t or dir.t? + Hint: did you mean dir.t? [1] $ dune test other_dip