Skip to content

Commit a6f73a6

Browse files
authored
Merge pull request DeusData#1704 from DeusData/fix/stdin-gate-tests-post-1181
fix: unbreak main — stdin-gate DeusData#1359 guards + Windows search_code UTF-8 pipe
2 parents 4d7d9f1 + 4dd0996 commit a6f73a6

4 files changed

Lines changed: 125 additions & 59 deletions

File tree

‎src/cli/cli.c‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12561,6 +12561,8 @@ static void cli_add_typed(yyjson_mut_doc *out, yyjson_mut_val *obj, const char *
1256112561
yyjson_mut_obj_add(obj, yyjson_mut_strcpy(out, key), vv);
1256212562
}
1256312563

12564+
static bool cli_stdin_allowed_for_schema(const char *schema_str);
12565+
1256412566
bool cbm_cli_args_from_stdin_allowed(const char *tool_name, bool stdin_is_tty) {
1256512567
/* An interactive run has nothing piped to read: consulting the terminal
1256612568
* would just sit waiting for the user to type JSON. Unchanged by #1359 —
@@ -12589,6 +12591,17 @@ bool cbm_cli_args_from_stdin_allowed(const char *tool_name, bool stdin_is_tty) {
1258912591
return false;
1259012592
}
1259112593

12594+
return cli_stdin_allowed_for_schema(schema_str);
12595+
}
12596+
12597+
/* Schema→decision core of the stdin gate, split out so the zero-argument
12598+
* branch stays TESTED even when no shipped tool is zero-argument anymore:
12599+
* #1181 gave list_projects pagination parameters, retiring the last
12600+
* empty-properties schema, and the #1359 regression tests had leaned on it
12601+
* as their live example. The product contract is unchanged — a schema that
12602+
* declares no properties means stdin has nothing to carry and the read is
12603+
* pure deadlock; the tests now exercise this path directly. */
12604+
static bool cli_stdin_allowed_for_schema(const char *schema_str) {
1259212605
yyjson_doc *schema_doc = yyjson_read(schema_str, strlen(schema_str), 0);
1259312606
if (!schema_doc) {
1259412607
/* The schemas are compile-time constants, so a parse failure means a
@@ -12604,6 +12617,12 @@ bool cbm_cli_args_from_stdin_allowed(const char *tool_name, bool stdin_is_tty) {
1260412617
return accepts_arguments;
1260512618
}
1260612619

12620+
#ifdef CBM_CLI_ENABLE_TEST_API
12621+
bool cbm_cli_stdin_allowed_for_schema_for_test(const char *schema_str) {
12622+
return cli_stdin_allowed_for_schema(schema_str);
12623+
}
12624+
#endif
12625+
1260712626
char *cbm_cli_build_args_json(const char *tool_name, int argc, char **argv, char **err_out) {
1260812627
if (err_out) {
1260912628
*err_out = NULL;

‎src/mcp/mcp.c‎

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8848,6 +8848,16 @@ bool cbm_search_code_file_pattern_can_prefilter(const char *file_pattern) {
88488848
/* Build the grep/search command string based on scoped vs recursive mode.
88498849
* On Windows, uses PowerShell Select-String with tab-delimited output.
88508850
* On POSIX, uses grep with colon-delimited output. */
8851+
/* Windows PowerShell 5.1 encodes stdout for a native-process pipe in the
8852+
* console OEM codepage, so any character the inherited CP cannot carry
8853+
* (Cyrillic under CP437/850, etc.) degrades to '?' before it ever reaches
8854+
* collect_grep_matches — and WHETHER it degrades depends on the console the
8855+
* server happened to inherit. Pin the pipe to UTF-8 inside every generated
8856+
* command so raw search content is codepage-independent. (The read side is
8857+
* already safe: Select-String decodes BOM-less UTF-8 via .NET StreamReader
8858+
* defaults.) */
8859+
#define CBM_PS_UTF8_PRELUDE "[Console]::OutputEncoding=[System.Text.Encoding]::UTF8; "
8860+
88518861
void cbm_search_code_build_grep_cmd(char *cmd, size_t cmd_sz, bool use_regex, bool scoped,
88528862
const char *file_pattern, const char *tmpfile,
88538863
const char *filelist, const char *root_path) {
@@ -8858,7 +8868,8 @@ void cbm_search_code_build_grep_cmd(char *cmd, size_t cmd_sz, bool use_regex, bo
88588868
if (cbm_search_code_file_pattern_can_prefilter(file_pattern)) {
88598869
snprintf(
88608870
cmd, cmd_sz,
8861-
"powershell -Command \"$pat = Get-Content -Encoding UTF8 -LiteralPath '%s'; "
8871+
"powershell -Command \"" CBM_PS_UTF8_PRELUDE
8872+
"$pat = Get-Content -Encoding UTF8 -LiteralPath '%s'; "
88628873
"Get-Content -Encoding UTF8 -LiteralPath '%s'"
88638874
" | Where-Object { $_ -like '%s' }"
88648875
" | ForEach-Object { Select-String -LiteralPath $_ -Pattern $pat%s "
@@ -8869,7 +8880,8 @@ void cbm_search_code_build_grep_cmd(char *cmd, size_t cmd_sz, bool use_regex, bo
88698880
} else {
88708881
snprintf(
88718882
cmd, cmd_sz,
8872-
"powershell -Command \"$pat = Get-Content -Encoding UTF8 -LiteralPath '%s'; "
8883+
"powershell -Command \"" CBM_PS_UTF8_PRELUDE
8884+
"$pat = Get-Content -Encoding UTF8 -LiteralPath '%s'; "
88738885
"Get-Content -Encoding UTF8 -LiteralPath '%s' | ForEach-Object { Select-String "
88748886
"-LiteralPath $_ -Pattern $pat%s "
88758887
"-ErrorAction SilentlyContinue }"
@@ -8880,7 +8892,8 @@ void cbm_search_code_build_grep_cmd(char *cmd, size_t cmd_sz, bool use_regex, bo
88808892
} else {
88818893
snprintf(
88828894
cmd, cmd_sz,
8883-
"powershell -Command \"$pat = Get-Content -Encoding UTF8 -LiteralPath '%s'; "
8895+
"powershell -Command \"" CBM_PS_UTF8_PRELUDE
8896+
"$pat = Get-Content -Encoding UTF8 -LiteralPath '%s'; "
88848897
"Get-Content -Encoding UTF8 -LiteralPath '%s' | ForEach-Object { Select-String "
88858898
"-LiteralPath $_ -Pattern $pat%s "
88868899
"-ErrorAction SilentlyContinue }"
@@ -8891,7 +8904,8 @@ void cbm_search_code_build_grep_cmd(char *cmd, size_t cmd_sz, bool use_regex, bo
88918904
if (file_pattern) {
88928905
snprintf(
88938906
cmd, cmd_sz,
8894-
"powershell -Command \"Get-ChildItem -Recurse -Path '%s\\*' -Include '%s' -File "
8907+
"powershell -Command \"" CBM_PS_UTF8_PRELUDE
8908+
"Get-ChildItem -Recurse -Path '%s\\*' -Include '%s' -File "
88958909
"-ErrorAction SilentlyContinue"
88968910
" | Select-String -Pattern (Get-Content -Encoding UTF8 -LiteralPath '%s')%s "
88978911
"-ErrorAction SilentlyContinue"
@@ -8900,7 +8914,8 @@ void cbm_search_code_build_grep_cmd(char *cmd, size_t cmd_sz, bool use_regex, bo
89008914
} else {
89018915
snprintf(
89028916
cmd, cmd_sz,
8903-
"powershell -Command \"Get-ChildItem -Recurse -Path '%s\\*' -File -ErrorAction "
8917+
"powershell -Command \"" CBM_PS_UTF8_PRELUDE
8918+
"Get-ChildItem -Recurse -Path '%s\\*' -File -ErrorAction "
89048919
"SilentlyContinue"
89058920
" | Select-String -Pattern (Get-Content -Encoding UTF8 -LiteralPath '%s')%s "
89068921
"-ErrorAction SilentlyContinue"

‎tests/test_cli.c‎

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ int cbm_cli_activation_abort_cleanup_probe_for_test(void);
5454
bool cbm_cli_activation_test_ops_installed(void);
5555
int cbm_cli_build_yaml_stdio_mcp_block_for_test(const char *binary_path, bool goose_schema,
5656
char *block, size_t block_size);
57+
bool cbm_cli_stdin_allowed_for_schema_for_test(const char *schema_str);
5758

5859
TEST(cli_progress_visibility_policy) {
5960
ASSERT_TRUE(cbm_cli_progress_enabled(true, false));
@@ -12453,22 +12454,22 @@ TEST(cli_print_tool_help_issue680) {
1245312454
* properties, so stdin could never have carried anything it accepts: the read
1245412455
* was pure deadlock. Gate the read on the tool actually declaring arguments. */
1245512456
TEST(cli_zero_argument_tool_never_reads_stdin_issue1359) {
12456-
/* The reported hang: zero-argument tool + non-terminal stdin. */
12457-
ASSERT_FALSE(cbm_cli_args_from_stdin_allowed("list_projects", false));
12458-
12459-
/* The documented `echo '<json>' | cli <tool>` channel must survive. */
12460-
ASSERT_TRUE(cbm_cli_args_from_stdin_allowed("index_status", false));
12461-
ASSERT_TRUE(cbm_cli_args_from_stdin_allowed("search_graph", false));
12462-
ASSERT_TRUE(cbm_cli_args_from_stdin_allowed("index_repository", false));
12463-
12464-
/* Interactive runs never read the terminal for arguments — unchanged. */
12465-
ASSERT_FALSE(cbm_cli_args_from_stdin_allowed("index_status", true));
12457+
/* #1359's deadlock class: a tool whose schema declares no properties must
12458+
* never read stdin (nothing it could carry; the read is pure deadlock).
12459+
* Since #1181 no SHIPPED tool is zero-argument anymore — list_projects,
12460+
* the original example, now declares pagination properties — so the
12461+
* zero-argument branch is exercised directly through the schema seam,
12462+
* and list_projects asserts its NEW truth. */
12463+
ASSERT_FALSE(
12464+
cbm_cli_stdin_allowed_for_schema_for_test("{\"type\":\"object\",\"properties\":{}}"));
12465+
ASSERT_FALSE(cbm_cli_stdin_allowed_for_schema_for_test("{\"type\":\"object\"}"));
12466+
ASSERT_TRUE(cbm_cli_stdin_allowed_for_schema_for_test(
12467+
"{\"type\":\"object\",\"properties\":{\"p\":{\"type\":\"string\"}}}"));
12468+
12469+
/* list_projects now takes piped arguments (offset/limit/include_details);
12470+
* the TTY guard still refuses regardless of schema. */
12471+
ASSERT_TRUE(cbm_cli_args_from_stdin_allowed("list_projects", false));
1246612472
ASSERT_FALSE(cbm_cli_args_from_stdin_allowed("list_projects", true));
12467-
12468-
/* An unknown tool is rejected by name; blocking for input first can only
12469-
* delay that verdict, never change it. */
12470-
ASSERT_FALSE(cbm_cli_args_from_stdin_allowed("nope_not_a_tool", false));
12471-
ASSERT_FALSE(cbm_cli_args_from_stdin_allowed(NULL, false));
1247212473
PASS();
1247312474
}
1247412475

@@ -12496,8 +12497,12 @@ TEST(cli_stdin_args_gate_tracks_tool_schema_issue1359) {
1249612497
ASSERT_EQ(cbm_cli_args_from_stdin_allowed(name, false), declares_properties);
1249712498
ASSERT_FALSE(cbm_cli_args_from_stdin_allowed(name, true));
1249812499
}
12499-
/* list_projects at minimum; without one the sweep above proves nothing. */
12500-
ASSERT_GTE(zero_argument_tools, 1);
12500+
/* Since #1181 every shipped tool declares properties, so the sweep's
12501+
* zero-argument branch can be empty here — that branch is pinned directly
12502+
* against the schema seam in the test above, which survives the registry
12503+
* having no zero-argument example. The sweep still proves schema↔gate
12504+
* parity for every tool that exists. */
12505+
(void)zero_argument_tools;
1250112506
PASS();
1250212507
}
1250312508

‎tests/test_mcp.c‎

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,7 @@ TEST(tool_search_graph_includes_node_properties) {
21202120
ASSERT_NOT_NULL(strstr(inner, "func HandleRequest")); /* its value */
21212121
ASSERT_NOT_NULL(strstr(inner, "\"base_classes\""));
21222122
ASSERT_NOT_NULL(strstr(inner, "[\"HandlerBase\",\"Audited\"]"));
2123-
ASSERT_NULL(strstr(inner, "is_exported")); /* blob never spills */
2123+
ASSERT_NULL(strstr(inner, "is_exported")); /* blob never spills */
21242124
free(inner);
21252125
free(resp);
21262126

@@ -2680,15 +2680,13 @@ TEST(tool_check_index_coverage_accepts_truncated_ignored_catalog_for_fresh_path_
26802680
((int64_t)source_stat.st_mtimespec.tv_sec * (int64_t)CBM_NSEC_PER_SEC) +
26812681
(int64_t)source_stat.st_mtimespec.tv_nsec;
26822682
#elif defined(_WIN32)
2683-
int64_t source_mtime_ns =
2684-
(int64_t)source_stat.st_mtime * (int64_t)CBM_NSEC_PER_SEC;
2683+
int64_t source_mtime_ns = (int64_t)source_stat.st_mtime * (int64_t)CBM_NSEC_PER_SEC;
26852684
#else
2686-
int64_t source_mtime_ns =
2687-
((int64_t)source_stat.st_mtim.tv_sec * (int64_t)CBM_NSEC_PER_SEC) +
2688-
(int64_t)source_stat.st_mtim.tv_nsec;
2685+
int64_t source_mtime_ns = ((int64_t)source_stat.st_mtim.tv_sec * (int64_t)CBM_NSEC_PER_SEC) +
2686+
(int64_t)source_stat.st_mtim.tv_nsec;
26892687
#endif
2690-
ASSERT_EQ(cbm_store_upsert_file_hash(store, "test-project", "main.go", "",
2691-
source_mtime_ns, source_stat.st_size),
2688+
ASSERT_EQ(cbm_store_upsert_file_hash(store, "test-project", "main.go", "", source_mtime_ns,
2689+
source_stat.st_size),
26922690
CBM_STORE_OK);
26932691
cbm_project_t project = {0};
26942692
ASSERT_EQ(cbm_store_get_project(store, "test-project", &project), CBM_STORE_OK);
@@ -2702,8 +2700,7 @@ TEST(tool_check_index_coverage_accepts_truncated_ignored_catalog_for_fresh_path_
27022700
.coverage_version = 1,
27032701
.hash_records_complete = true,
27042702
};
2705-
ASSERT_EQ(cbm_store_coverage_replace_ex(store, "test-project", NULL, 0, &meta),
2706-
CBM_STORE_OK);
2703+
ASSERT_EQ(cbm_store_coverage_replace_ex(store, "test-project", NULL, 0, &meta), CBM_STORE_OK);
27072704
cbm_project_free_fields(&project);
27082705

27092706
char *response = cbm_mcp_handle_tool(
@@ -4351,12 +4348,12 @@ TEST(search_code_full_preserves_utf8_source) {
43514348
.end_line = 2};
43524349
ASSERT_GT(cbm_store_upsert_node(st, &section), 0);
43534350

4354-
char *resp = cbm_mcp_server_handle(
4355-
srv, "{\"jsonrpc\":\"2.0\",\"id\":97,\"method\":\"tools/call\","
4356-
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4357-
"\"project\":\"utf8-search\",\"pattern\":\"accounting-design\","
4358-
"\"file_pattern\":\"*.md\",\"path_filter\":\"^design/\","
4359-
"\"mode\":\"full\",\"format\":\"json\",\"limit\":5}}}");
4351+
char *resp =
4352+
cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":97,\"method\":\"tools/call\","
4353+
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4354+
"\"project\":\"utf8-search\",\"pattern\":\"accounting-design\","
4355+
"\"file_pattern\":\"*.md\",\"path_filter\":\"^design/\","
4356+
"\"mode\":\"full\",\"format\":\"json\",\"limit\":5}}}");
43604357
ASSERT_NOT_NULL(resp);
43614358
char *inner = extract_text_content(resp);
43624359
ASSERT_NOT_NULL(inner);
@@ -4408,11 +4405,11 @@ TEST(search_code_raw_match_preserves_utf8_content) {
44084405
.end_line = 1};
44094406
ASSERT_GT(cbm_store_upsert_node(st, &node), 0);
44104407

4411-
char *resp = cbm_mcp_server_handle(
4412-
srv, "{\"jsonrpc\":\"2.0\",\"id\":98,\"method\":\"tools/call\","
4413-
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4414-
"\"project\":\"test-project\",\"pattern\":\"raw-\","
4415-
"\"file_pattern\":\"*.md\",\"format\":\"json\",\"limit\":5}}}");
4408+
char *resp =
4409+
cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":98,\"method\":\"tools/call\","
4410+
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4411+
"\"project\":\"test-project\",\"pattern\":\"raw-\","
4412+
"\"file_pattern\":\"*.md\",\"format\":\"json\",\"limit\":5}}}");
44164413
ASSERT_NOT_NULL(resp);
44174414
char *inner = extract_text_content(resp);
44184415
ASSERT_NOT_NULL(inner);
@@ -4459,11 +4456,11 @@ TEST(search_code_context_preserves_utf8_context) {
44594456
.end_line = 3};
44604457
ASSERT_GT(cbm_store_upsert_node(st, &node), 0);
44614458

4462-
char *resp = cbm_mcp_server_handle(
4463-
srv, "{\"jsonrpc\":\"2.0\",\"id\":99,\"method\":\"tools/call\","
4464-
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4465-
"\"project\":\"test-project\",\"pattern\":\"context-needle\","
4466-
"\"format\":\"json\",\"context\":1,\"limit\":5}}}");
4459+
char *resp =
4460+
cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":99,\"method\":\"tools/call\","
4461+
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4462+
"\"project\":\"test-project\",\"pattern\":\"context-needle\","
4463+
"\"format\":\"json\",\"context\":1,\"limit\":5}}}");
44674464
ASSERT_NOT_NULL(resp);
44684465
char *inner = extract_text_content(resp);
44694466
ASSERT_NOT_NULL(inner);
@@ -4507,8 +4504,8 @@ TEST(search_code_invalid_utf8_still_returns_valid_json) {
45074504
char invalid_path[512];
45084505
snprintf(invalid_path, sizeof(invalid_path), "%s/project/invalid.md", tmp);
45094506
static const unsigned char invalid_source[] = {
4510-
'i', 'n', 'v', 'a', 'l', 'i', 'd', '-', 'n', 'e', 'e', 'd', 'l', 'e', '\n',
4511-
'c', 'o', 'n', 't', 'e', 'x', 't', ' ', 0xFF, '\n',
4507+
'i', 'n', 'v', 'a', 'l', 'i', 'd', '-', 'n', 'e', 'e', 'd', 'l',
4508+
'e', '\n', 'c', 'o', 'n', 't', 'e', 'x', 't', ' ', 0xFF, '\n',
45124509
};
45134510
FILE *fp = cbm_fopen(invalid_path, "wb");
45144511
ASSERT_NOT_NULL(fp);
@@ -4526,11 +4523,11 @@ TEST(search_code_invalid_utf8_still_returns_valid_json) {
45264523
.end_line = 2};
45274524
ASSERT_GT(cbm_store_upsert_node(st, &node), 0);
45284525

4529-
char *resp = cbm_mcp_server_handle(
4530-
srv, "{\"jsonrpc\":\"2.0\",\"id\":100,\"method\":\"tools/call\","
4531-
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4532-
"\"project\":\"test-project\",\"pattern\":\"invalid-needle\","
4533-
"\"mode\":\"full\",\"format\":\"json\",\"limit\":5}}}");
4526+
char *resp =
4527+
cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":100,\"method\":\"tools/call\","
4528+
"\"params\":{\"name\":\"search_code\",\"arguments\":{"
4529+
"\"project\":\"test-project\",\"pattern\":\"invalid-needle\","
4530+
"\"mode\":\"full\",\"format\":\"json\",\"limit\":5}}}");
45344531
ASSERT_NOT_NULL(resp);
45354532
char *inner = extract_text_content(resp);
45364533
ASSERT_NOT_NULL(inner);
@@ -4921,6 +4918,35 @@ TEST(search_code_windows_prefilter_precedes_content_scan) {
49214918
#endif
49224919
}
49234920

4921+
/* Windows raw scans must pin the PowerShell pipe to UTF-8: PS 5.1 otherwise
4922+
* emits stdout in the console OEM codepage and non-ASCII content degrades to
4923+
* '?' depending on the inherited console CP (seen as test_mcp raw-Русский
4924+
* mojibake on CI). Every builder variant must carry the prelude. */
4925+
TEST(search_code_windows_scan_pins_utf8_output) {
4926+
#ifdef _WIN32
4927+
static const char prelude[] =
4928+
"powershell -Command \"[Console]::OutputEncoding=[System.Text.Encoding]::UTF8; ";
4929+
char command[CBM_SZ_4K];
4930+
struct {
4931+
bool scoped;
4932+
const char *file_pattern;
4933+
} cases[] = {{true, "*.go"}, /* scoped + prefilterable pattern */
4934+
{true, "*x*z*.go"}, /* scoped + non-prefilterable pattern */
4935+
{true, NULL}, /* scoped, no pattern */
4936+
{false, "*.go"}, /* unscoped + pattern */
4937+
{false, NULL}}; /* unscoped, no pattern */
4938+
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
4939+
cbm_search_code_build_grep_cmd(command, sizeof(command), false, cases[i].scoped,
4940+
cases[i].file_pattern, "C:/tmp/pattern", "C:/tmp/filelist",
4941+
"C:/tmp/root");
4942+
ASSERT_TRUE(strncmp(command, prelude, sizeof(prelude) - 1) == 0);
4943+
}
4944+
PASS();
4945+
#else
4946+
SKIP_PLATFORM("PowerShell scan encoding applies on Windows");
4947+
#endif
4948+
}
4949+
49244950
/* issue #283: search_code with regex=true and a syntactically invalid pattern
49254951
* must return an explicit error, not an empty result indistinguishable from a
49264952
* legitimate no-match. */
@@ -8769,10 +8795,10 @@ TEST(tool_resolve_store_by_internal_name_issue704) {
87698795
ASSERT_NULL(strstr(list, "ghost704")); /* 0-byte ghost filtered (RED before) */
87708796
free(list);
87718797

8772-
char *page = cbm_mcp_server_handle(
8773-
srv, "{\"jsonrpc\":\"2.0\",\"id\":11,\"method\":\"tools/call\","
8774-
"\"params\":{\"name\":\"list_projects\","
8775-
"\"arguments\":{\"offset\":0,\"limit\":1}}}");
8798+
char *page =
8799+
cbm_mcp_server_handle(srv, "{\"jsonrpc\":\"2.0\",\"id\":11,\"method\":\"tools/call\","
8800+
"\"params\":{\"name\":\"list_projects\","
8801+
"\"arguments\":{\"offset\":0,\"limit\":1}}}");
87768802
ASSERT_NOT_NULL(page);
87778803
ASSERT_NOT_NULL(strstr(page, "\\\"total\\\":3"));
87788804
ASSERT_NOT_NULL(strstr(page, "\\\"limit\\\":1"));
@@ -11223,6 +11249,7 @@ SUITE(mcp) {
1122311249
RUN_TEST(search_code_path_filter_matches_nothing);
1122411250
RUN_TEST(search_code_file_pattern_prefilter_boundaries);
1122511251
RUN_TEST(search_code_windows_prefilter_precedes_content_scan);
11252+
RUN_TEST(search_code_windows_scan_pins_utf8_output);
1122611253
RUN_TEST(search_code_invalid_regex_errors_issue283);
1122711254
RUN_TEST(search_code_literal_pipe_warns_issue282);
1122811255
RUN_TEST(search_code_reports_phase_timings_only_in_debug_mode);

0 commit comments

Comments
 (0)