From 5f325498bf2cb1de3bd0ff26b1cdeab0f6786055 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Sat, 25 Jul 2026 01:43:43 +0900 Subject: [PATCH 1/2] Fix HOME shorthand test expectation (#4810) --- TESTING_GUIDE.md | 2 ++ changelog.d/unreleased/4810.fixed.md | 16 ++++++++++++++++ tests/CodeIndex.Tests/ProgramRunnerTests.cs | 6 +++++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 changelog.d/unreleased/4810.fixed.md diff --git a/TESTING_GUIDE.md b/TESTING_GUIDE.md index bca2aa67e..b3a29cd92 100644 --- a/TESTING_GUIDE.md +++ b/TESTING_GUIDE.md @@ -176,6 +176,7 @@ Use `docs/test-doc-maintenance-plan.md` before moving oversized suites or adding CLI parsing, command execution, and installer behavior. Index command coverage is split by run mode or feature area, and query command coverage is split by command family with partial test classes so shared console and fixture helpers stay centralized. Keep repeated query-result fixtures, such as overlapping chunk content used by multiple search deduplication tests, in narrow class-level helpers instead of duplicating local builders. `ProgramCliTests.cs` covers top-level entrypoint behavior that must be exercised through a subprocess, while `InstallScriptTests.cs` runs focused bash snippets against `install.sh` in library mode to lock in release-installer regressions without performing real network installs. Installer bundle-generation tests must also verify that `install.sh` is marked generated while every canonical `install_modules/` source remains unmarked. `ConsoleUiTests.cs` keeps each generated shell's complete long-flag catalog aligned with `CliFlagSchema` and checks every Fish command scope against the shared per-command completion projection. Add flags to the schema rather than weakening this Bash / Zsh / Fish / PowerShell parity contract. `ProgramRunnerTests.cs` enumerates `CliCommandCatalog.CommandSubcommands` and requires every valid nested verb to resolve to verb-specific usage with an example. It also pins destructive index confirmation and aggregate dependency-filter help, plus the read-only GitHub duplicate-preflight boundary for suggestion exports. + Global-tool-log home-shorthand coverage derives its Unix expectation from the process `HOME` environment, with the platform user-profile API as the Windows or missing-value fallback, so sandboxed test processes do not compare the resolver against the host account profile. Grouped-search limit coverage must seed more matches and files than the returned page, then assert query-wide matched/group/file totals separately from grouped, emitted, and omitted row counts so a bounded page cannot report itself as complete. Cursor-pagination coverage for `outline` and `unused` must replay the emitted opaque token successfully, then prove that changed filters/order and a changed index-generation stamp fail with restart-required diagnostics. Discovery-pagination coverage must page compact search/symbol/file output and the opt-in search-array/languages envelopes, assert authoritative total/omitted/stable-at metadata, reject query or generation cursor mismatches, and prove that a partial `find --all` scan resumes after the last scanned line. @@ -1028,6 +1029,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests" CLI の引数解析、コマンド実行、installer 挙動のテスト。Index command coverage は run mode または機能領域ごとの partial suite に分割し、Query command coverage は command family ごとの partial test class に分割して、共有 console / fixture helper は一箇所に保ちます。`ProgramCliTests.cs` はグローバル引数の解釈や完全な CLI 起動フローのように subprocess 経由で確認すべき Program エントリポイント挙動を扱い、`InstallScriptTests.cs` は `install.sh` を library mode で source した bash snippet を実行して、実ネットワーク install を行わずに release installer の回帰を固定する。installer bundle 生成テストでは、`install.sh` が generated と判定される一方、canonical な `install_modules/` source はすべて unmarked のままであることも検証してください。 `ConsoleUiTests.cs` は各生成シェルの long flag 全カタログを `CliFlagSchema` と同期させ、Fish の全 command scope を共有の command 別 completion 射影と照合します。この Bash / Zsh / Fish / PowerShell parity 契約を弱めず、新しい flag は schema に追加してください。 `ProgramRunnerTests.cs` は `CliCommandCatalog.CommandSubcommands` を列挙し、すべての有効な nested verb が例を含む verb 固有 usage に解決されることを必須とします。さらに destructive な index confirmation、aggregate dependency filter help、suggestion export の read-only GitHub duplicate-preflight 境界を固定します。 + global tool log の home shorthand coverage は、Unix では process の `HOME` 環境変数から期待値を導出し、Windows または値がない場合だけ platform の user-profile API へ fallback します。これにより sandbox 化された test process で resolver と host account profile を比較しません。 grouped search の limit coverage では、返却 page より多い match と file を seed し、query 全体の match/group/file 総数と grouped、emitted、omitted row 数を別々に検証して、上限付き page が完了済みと報告できないようにしてください。 `outline` と `unused` の cursor pagination coverage では、出力された opaque token の再利用成功に加え、filter/order の変更と index-generation stamp の変更が restart-required 診断で失敗することを検証してください。 discovery pagination の coverage では compact search / symbol / file と opt-in の search array / languages envelope をページングし、authoritative な total / omitted / stable-at metadata、query / generation 不一致 cursor の拒否、partial な `find --all` scan が最後に scan した line の次から再開することを検証してください。 diff --git a/changelog.d/unreleased/4810.fixed.md b/changelog.d/unreleased/4810.fixed.md new file mode 100644 index 000000000..0f7c6b097 --- /dev/null +++ b/changelog.d/unreleased/4810.fixed.md @@ -0,0 +1,16 @@ +--- +category: fixed +issues: + - 4810 +affected: + - tests/CodeIndex.Tests/ProgramRunnerTests.cs + - TESTING_GUIDE.md +--- + +## English + +- **Made global-tool-log home-shorthand tests honor sandboxed `HOME` (#4810)** — the test expectation now follows the process environment on Unix, while retaining the platform user-profile fallback for Windows or missing values. + +## 日本語 + +- **global tool log の home shorthand テストが sandbox 化された `HOME` を尊重するようになりました (#4810)** — Unix の期待値は process 環境に従い、Windows または値がない場合は platform の user-profile fallback を維持します。 diff --git a/tests/CodeIndex.Tests/ProgramRunnerTests.cs b/tests/CodeIndex.Tests/ProgramRunnerTests.cs index 1cde3a51b..992e50430 100644 --- a/tests/CodeIndex.Tests/ProgramRunnerTests.cs +++ b/tests/CodeIndex.Tests/ProgramRunnerTests.cs @@ -4129,7 +4129,11 @@ public void GlobalToolLog_OverrideDirectory_ExpandsHomeShorthand(string override env.Set("XDG_STATE_HOME", null); env.Set("XDG_CACHE_HOME", null); env.Set("XDG_RUNTIME_DIR", null); - var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var home = OperatingSystem.IsWindows() + ? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + : Environment.GetEnvironmentVariable("HOME"); + if (string.IsNullOrWhiteSpace(home)) + home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); var resolved = GlobalToolLog.ResolveLogDirectoryForReport(); From ff044ebcbbb288f2c7d4a9ea96a1f9c9dec751e3 Mon Sep 17 00:00:00 2001 From: Widthdom Date: Sat, 25 Jul 2026 01:55:47 +0900 Subject: [PATCH 2/2] Isolate HOME expansion test from write probes (#4810) --- TESTING_GUIDE.md | 4 ++-- changelog.d/unreleased/4810.fixed.md | 5 +++-- src/CodeIndex/Cli/GlobalToolLog.cs | 9 +++++++-- tests/CodeIndex.Tests/ProgramRunnerTests.cs | 8 ++------ 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/TESTING_GUIDE.md b/TESTING_GUIDE.md index 75b148ac5..850f6843f 100644 --- a/TESTING_GUIDE.md +++ b/TESTING_GUIDE.md @@ -176,7 +176,7 @@ Use `docs/test-doc-maintenance-plan.md` before moving oversized suites or adding CLI parsing, command execution, and installer behavior. Index command coverage is split by run mode or feature area, and query command coverage is split by command family with partial test classes so shared console and fixture helpers stay centralized. Keep repeated query-result fixtures, such as overlapping chunk content used by multiple search deduplication tests, in narrow class-level helpers instead of duplicating local builders. `ProgramCliTests.cs` covers top-level entrypoint behavior that must be exercised through a subprocess, while `InstallScriptTests.cs` runs focused bash snippets against `install.sh` in library mode to lock in release-installer regressions without performing real network installs. Installer bundle-generation tests must also verify that `install.sh` is marked generated while every canonical `install_modules/` source remains unmarked. `ConsoleUiTests.cs` keeps each generated shell's complete long-flag catalog aligned with `CliFlagSchema` and checks every Fish command scope against the shared per-command completion projection. Add flags to the schema rather than weakening this Bash / Zsh / Fish / PowerShell parity contract. `ProgramRunnerTests.cs` enumerates `CliCommandCatalog.CommandSubcommands` and requires every valid nested verb to resolve to verb-specific usage with an example. It also pins destructive index confirmation and aggregate dependency-filter help, plus the read-only GitHub duplicate-preflight boundary for suggestion exports. - Global-tool-log home-shorthand coverage derives its Unix expectation from the process `HOME` environment, with the platform user-profile API as the Windows or missing-value fallback, so sandboxed test processes do not compare the resolver against the host account profile. + Global-tool-log home-shorthand coverage resolves the normalized first candidate through the test-only no-write-probe seam, so sandbox permissions cannot turn an expansion assertion into a writability-fallback assertion. Grouped-search limit coverage must seed more matches and files than the returned page, then assert query-wide matched/group/file totals separately from grouped, emitted, and omitted row counts so a bounded page cannot report itself as complete. Cursor-pagination coverage for `outline` and `unused` must replay the emitted opaque token successfully, then prove that changed filters/order and a changed index-generation stamp fail with restart-required diagnostics. Discovery-pagination coverage must page compact search/symbol/file output and the opt-in search-array/languages envelopes, assert authoritative total/omitted/stable-at metadata, reject query or generation cursor mismatches, and prove that a partial `find --all` scan resumes after the last scanned line. @@ -1029,7 +1029,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests" CLI の引数解析、コマンド実行、installer 挙動のテスト。Index command coverage は run mode または機能領域ごとの partial suite に分割し、Query command coverage は command family ごとの partial test class に分割して、共有 console / fixture helper は一箇所に保ちます。`ProgramCliTests.cs` はグローバル引数の解釈や完全な CLI 起動フローのように subprocess 経由で確認すべき Program エントリポイント挙動を扱い、`InstallScriptTests.cs` は `install.sh` を library mode で source した bash snippet を実行して、実ネットワーク install を行わずに release installer の回帰を固定する。installer bundle 生成テストでは、`install.sh` が generated と判定される一方、canonical な `install_modules/` source はすべて unmarked のままであることも検証してください。 `ConsoleUiTests.cs` は各生成シェルの long flag 全カタログを `CliFlagSchema` と同期させ、Fish の全 command scope を共有の command 別 completion 射影と照合します。この Bash / Zsh / Fish / PowerShell parity 契約を弱めず、新しい flag は schema に追加してください。 `ProgramRunnerTests.cs` は `CliCommandCatalog.CommandSubcommands` を列挙し、すべての有効な nested verb が例を含む verb 固有 usage に解決されることを必須とします。さらに destructive な index confirmation、aggregate dependency filter help、suggestion export の read-only GitHub duplicate-preflight 境界を固定します。 - global tool log の home shorthand coverage は、Unix では process の `HOME` 環境変数から期待値を導出し、Windows または値がない場合だけ platform の user-profile API へ fallback します。これにより sandbox 化された test process で resolver と host account profile を比較しません。 + global tool log の home shorthand coverage は、test 専用の write probe なし seam から正規化済みの先頭 candidate を解決します。これにより sandbox permission の影響で、展開の assertion が writability fallback の assertion に変わることを防ぎます。 grouped search の limit coverage では、返却 page より多い match と file を seed し、query 全体の match/group/file 総数と grouped、emitted、omitted row 数を別々に検証して、上限付き page が完了済みと報告できないようにしてください。 `outline` と `unused` の cursor pagination coverage では、出力された opaque token の再利用成功に加え、filter/order の変更と index-generation stamp の変更が restart-required 診断で失敗することを検証してください。 discovery pagination の coverage では compact search / symbol / file と opt-in の search array / languages envelope をページングし、authoritative な total / omitted / stable-at metadata、query / generation 不一致 cursor の拒否、partial な `find --all` scan が最後に scan した line の次から再開することを検証してください。 diff --git a/changelog.d/unreleased/4810.fixed.md b/changelog.d/unreleased/4810.fixed.md index 0f7c6b097..345392be9 100644 --- a/changelog.d/unreleased/4810.fixed.md +++ b/changelog.d/unreleased/4810.fixed.md @@ -3,14 +3,15 @@ category: fixed issues: - 4810 affected: + - src/CodeIndex/Cli/GlobalToolLog.cs - tests/CodeIndex.Tests/ProgramRunnerTests.cs - TESTING_GUIDE.md --- ## English -- **Made global-tool-log home-shorthand tests honor sandboxed `HOME` (#4810)** — the test expectation now follows the process environment on Unix, while retaining the platform user-profile fallback for Windows or missing values. +- **Isolated global-tool-log home-shorthand tests from sandbox writability fallback (#4810)** — the test now verifies the resolver's normalized first candidate through a no-write-probe test seam, while production resolution continues to require a writable directory. ## 日本語 -- **global tool log の home shorthand テストが sandbox 化された `HOME` を尊重するようになりました (#4810)** — Unix の期待値は process 環境に従い、Windows または値がない場合は platform の user-profile fallback を維持します。 +- **global tool log の home shorthand テストを sandbox の writability fallback から分離しました (#4810)** — test は write probe なし seam から resolver の正規化済み先頭 candidate を検証し、production の解決では引き続き書込可能な directory を必須とします。 diff --git a/src/CodeIndex/Cli/GlobalToolLog.cs b/src/CodeIndex/Cli/GlobalToolLog.cs index 868bcd0ea..45f2b0e35 100644 --- a/src/CodeIndex/Cli/GlobalToolLog.cs +++ b/src/CodeIndex/Cli/GlobalToolLog.cs @@ -275,14 +275,19 @@ private static bool ContainsPathSegments(string path, string[] expectedSegments, internal static string ResolveLogDirectoryForStatus() => ResolveLogDirectory(); - private static string ResolveLogDirectory() + private static string ResolveLogDirectory() => ResolveLogDirectory(requireWritableCandidate: true); + + internal static string ResolveLogDirectoryWithoutWriteProbeForTesting() + => ResolveLogDirectory(requireWritableCandidate: false); + + private static string ResolveLogDirectory(bool requireWritableCandidate) { foreach (var candidate in EnumerateLogDirectoryCandidates()) { if (!TryNormalizeLogDirectoryCandidate(candidate, out var fullPath)) continue; - if (CanWriteProbe(fullPath)) + if (!requireWritableCandidate || CanWriteProbe(fullPath)) return fullPath; } diff --git a/tests/CodeIndex.Tests/ProgramRunnerTests.cs b/tests/CodeIndex.Tests/ProgramRunnerTests.cs index 992e50430..d5174008e 100644 --- a/tests/CodeIndex.Tests/ProgramRunnerTests.cs +++ b/tests/CodeIndex.Tests/ProgramRunnerTests.cs @@ -4129,13 +4129,9 @@ public void GlobalToolLog_OverrideDirectory_ExpandsHomeShorthand(string override env.Set("XDG_STATE_HOME", null); env.Set("XDG_CACHE_HOME", null); env.Set("XDG_RUNTIME_DIR", null); - var home = OperatingSystem.IsWindows() - ? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) - : Environment.GetEnvironmentVariable("HOME"); - if (string.IsNullOrWhiteSpace(home)) - home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - var resolved = GlobalToolLog.ResolveLogDirectoryForReport(); + var resolved = GlobalToolLog.ResolveLogDirectoryWithoutWriteProbeForTesting(); Assert.Equal(Path.GetFullPath(Path.Combine(home, childDirectory)), resolved); }