From f3d1e0d63a6022236bc606ca6581edf0450decaf Mon Sep 17 00:00:00 2001
From: Johannes Altmanninger <aclopte@gmail.com>
Date: Sat, 9 Dec 2023 20:18:45 +0100
Subject: [PATCH] Port test_new_parser_errors

---
 fish-rust/src/tests/parser.rs | 31 ++++++++++++++++++++
 src/fish_tests.cpp            | 53 -----------------------------------
 2 files changed, 31 insertions(+), 53 deletions(-)

diff --git a/fish-rust/src/tests/parser.rs b/fish-rust/src/tests/parser.rs
index 4d09940bf..ed59e2395 100644
--- a/fish-rust/src/tests/parser.rs
+++ b/fish-rust/src/tests/parser.rs
@@ -558,6 +558,37 @@ add_test!("test_new_parser_ad_hoc", || {
     assert!(errors[0].code == ParseErrorCode::tokenizer_unterminated_quote);
 });
 
+add_test!("test_new_parser_errors", || {
+    macro_rules! validate {
+        ($src:expr, $expected_code:expr) => {
+            let mut errors = vec![];
+            let ast = Ast::parse(L!($src), ParseTreeFlags::default(), Some(&mut errors));
+            assert!(ast.errored());
+            assert_eq!(
+                errors.into_iter().map(|e| e.code).collect::<Vec<_>>(),
+                vec![$expected_code],
+            );
+        };
+    }
+
+    validate!("echo 'abc", ParseErrorCode::tokenizer_unterminated_quote);
+    validate!("'", ParseErrorCode::tokenizer_unterminated_quote);
+    validate!("echo (abc", ParseErrorCode::tokenizer_unterminated_subshell);
+
+    validate!("end", ParseErrorCode::unbalancing_end);
+    validate!("echo hi ; end", ParseErrorCode::unbalancing_end);
+
+    validate!("else", ParseErrorCode::unbalancing_else);
+    validate!("if true ; end ; else", ParseErrorCode::unbalancing_else);
+
+    validate!("case", ParseErrorCode::unbalancing_case);
+    validate!("if true ; case ; end", ParseErrorCode::generic);
+
+    validate!("true | and", ParseErrorCode::andor_in_pipeline);
+
+    validate!("a=", ParseErrorCode::bare_variable_assignment);
+});
+
 add_test!("test_eval_recursion_detection", || {
     // Ensure that we don't crash on infinite self recursion and mutual recursion. These must use
     // the principal parser because we cannot yet execute jobs on other parsers.
diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp
index 1198a06b9..d21792233 100644
--- a/src/fish_tests.cpp
+++ b/src/fish_tests.cpp
@@ -1077,58 +1077,6 @@ static void test_input() {
     }
 }
 
-// todo!("port this")
-static void test_new_parser_errors() {
-    say(L"Testing new parser error reporting");
-    const struct {
-        const wchar_t *src;
-        parse_error_code_t code;
-    } tests[] = {
-        {L"echo 'abc", parse_error_code_t::tokenizer_unterminated_quote},
-        {L"'", parse_error_code_t::tokenizer_unterminated_quote},
-        {L"echo (abc", parse_error_code_t::tokenizer_unterminated_subshell},
-
-        {L"end", parse_error_code_t::unbalancing_end},
-        {L"echo hi ; end", parse_error_code_t::unbalancing_end},
-
-        {L"else", parse_error_code_t::unbalancing_else},
-        {L"if true ; end ; else", parse_error_code_t::unbalancing_else},
-
-        {L"case", parse_error_code_t::unbalancing_case},
-        {L"if true ; case ; end", parse_error_code_t::generic},
-
-        {L"true | and", parse_error_code_t::andor_in_pipeline},
-
-        {L"a=", parse_error_code_t::bare_variable_assignment},
-    };
-
-    for (const auto &test : tests) {
-        const wcstring src = test.src;
-        parse_error_code_t expected_code = test.code;
-
-        auto errors = new_parse_error_list();
-        auto ast = ast_parse(src, parse_flag_none, &*errors);
-        if (!ast->errored()) {
-            err(L"Source '%ls' was expected to fail to parse, but succeeded", src.c_str());
-        }
-
-        if (errors->size() != 1) {
-            err(L"Source '%ls' was expected to produce 1 error, but instead produced %lu errors",
-                src.c_str(), errors->size());
-            for (size_t i = 0; i < errors->size(); i++) {
-                fprintf(stderr, "%ls\n", errors->at(i)->describe(src, false)->c_str());
-            }
-        } else if (errors->at(0)->code() != expected_code) {
-            err(L"Source '%ls' was expected to produce error code %lu, but instead produced error "
-                L"code %lu",
-                src.c_str(), expected_code, (unsigned long)errors->at(0)->code());
-            for (size_t i = 0; i < errors->size(); i++) {
-                err(L"\t\t%ls", errors->at(i)->describe(src, true)->c_str());
-            }
-        }
-    }
-}
-
 // Given a format string, returns a list of non-empty strings separated by format specifiers. The
 // format specifiers themselves are omitted.
 static std::vector<wcstring> separate_by_format_specifiers(const wchar_t *format) {
@@ -1539,7 +1487,6 @@ static const test_t s_tests[]{
     {TEST_GROUP("enum"), test_enum_array},
     {TEST_GROUP("autosuggestion"), test_autosuggestion_combining},
     {TEST_GROUP("test_abbreviations"), test_abbreviations},
-    {TEST_GROUP("new_parser_errors"), test_new_parser_errors},
     {TEST_GROUP("error_messages"), test_error_messages},
     {TEST_GROUP("convert"), test_convert},
     {TEST_GROUP("convert"), test_convert_private_use},