|
1 | | -"""RED integration test — `cli index_repository` rejects a non-ASCII repo_path. |
| 1 | +"""GREEN regression guard — `cli index_repository` honors a non-ASCII repo_path. |
2 | 2 |
|
3 | | -Reproduces the CLI-argv half of issue #636 / #423 / #20 on native Windows. |
| 3 | +Guards the CLI-argv fix for issue #636 / #423 / #20 on native Windows. |
4 | 4 |
|
5 | 5 | The documented entrypoint `codebase-memory-mcp cli index_repository '<json>'` |
6 | | -receives its JSON argument through argv. main() is declared as |
7 | | -`int main(int argc, char **argv)` (src/main.c) — it does not use wmain / |
8 | | -GetCommandLineW — so on Windows the C runtime hands it argv in the active ANSI |
9 | | -code page. A repo_path containing non-ASCII characters is therefore mangled (or, |
10 | | -when yyjson rejects the now-invalid UTF-8, the whole argument is discarded), and |
11 | | -the command fails with "repo_path is required" / "Pipeline failed" instead of |
12 | | -indexing the real directory. |
| 6 | +receives its JSON argument through argv. main() used to take only the narrow |
| 7 | +`int main(int argc, char **argv)` (src/main.c), so on Windows the C runtime handed |
| 8 | +it argv in the active ANSI code page: a repo_path containing non-ASCII characters |
| 9 | +was mangled (or, when yyjson rejected the now-invalid UTF-8, the whole argument was |
| 10 | +discarded), and the command failed with "repo_path is required" / "Pipeline failed" |
| 11 | +instead of indexing the real directory. |
| 12 | +
|
| 13 | +Fixed: on Windows main() now rebuilds argv from the wide command line |
| 14 | +(GetCommandLineW + CommandLineToArgvW) and converts each element to UTF-8, so a |
| 15 | +non-ASCII repo path survives. This test asserts that fix stays in place — it was RED |
| 16 | +before it and is GREEN after. (It is inherently green on Linux/macOS, where argv is |
| 17 | +already UTF-8 bytes.) |
13 | 18 |
|
14 | 19 | The directory itself is created with the Windows wide API (Python uses |
15 | 20 | CreateFileW/_wmkdir under the hood), so it genuinely exists on disk; only the |
16 | | -argv path delivery is lossy. |
17 | | -
|
18 | | -Passes on Linux/macOS (argv is UTF-8 bytes). Fails on native Windows until the |
19 | | -CLI reads the wide command line (GetCommandLineW + CommandLineToArgvW, or a |
20 | | -wmain entrypoint) and converts to UTF-8. |
| 21 | +argv path delivery was lossy. |
21 | 22 |
|
22 | 23 | Exit code: 0 == honored (green), 1 == rejected/mangled (red), 2 == setup error. |
23 | 24 |
|
@@ -80,21 +81,29 @@ def main(): |
80 | 81 |
|
81 | 82 | env2 = dict(os.environ) |
82 | 83 | env2["CBM_CACHE_DIR"] = cache |
| 84 | + # Exercise the DEFAULT (supervisor-enabled) path, not in-process. The non-ASCII |
| 85 | + # repo path must survive BOTH the argv read (main() wide command line) AND the |
| 86 | + # supervisor -> worker spawn (CreateProcessW). The suite runner sets |
| 87 | + # CBM_INDEX_SUPERVISOR=0 for determinism across the other guards; forcing it OFF |
| 88 | + # here would run in-process and mask the spawn-boundary half of #423/#20, so we |
| 89 | + # drop the override and let the supervisor wrap the worker as it does for users. |
| 90 | + env2.pop("CBM_INDEX_SUPERVISOR", None) |
83 | 91 | arg = json.dumps({"repo_path": repo}, ensure_ascii=False) |
84 | 92 | p = subprocess.run([binary, "cli", "index_repository", arg], |
85 | 93 | capture_output=True, timeout=120, env=env2) |
86 | 94 | out = (p.stdout or b"").decode("utf-8", "replace") |
87 | 95 | err = (p.stderr or b"").decode("utf-8", "replace") |
88 | 96 | honored = '"nodes"' in out and '"nodes":0' not in out.replace(" ", "") |
89 | 97 | print("ASCII control: indexed OK") |
90 | | - print("non-ASCII argv: rc=%d" % p.returncode) |
| 98 | + print("non-ASCII argv (supervised): rc=%d" % p.returncode) |
91 | 99 | print(" stdout: %s" % out[:200].replace("\n", " ")) |
92 | 100 | print(" stderr: %s" % err[-200:].replace("\n", " ")) |
93 | 101 | if honored: |
94 | | - print("\nGREEN: CLI honored the non-ASCII repo_path.") |
| 102 | + print("\nGREEN: CLI honored the non-ASCII repo_path (argv + worker spawn).") |
95 | 103 | return 0 |
96 | | - print("\nRED: CLI did not index the non-ASCII repo_path (argv delivered " |
97 | | - "in the ANSI code page; main() does not read the wide command line).") |
| 104 | + print("\nRED: CLI did not index the non-ASCII repo_path — the path was mangled " |
| 105 | + "either in the argv read (narrow main()) or re-mangled at the " |
| 106 | + "supervisor->worker CreateProcess boundary (ANSI code page).") |
98 | 107 | return 1 |
99 | 108 | finally: |
100 | 109 | shutil.rmtree(work, ignore_errors=True) |
|
0 commit comments