Skip to content

Commit f8ab40d

Browse files
authored
Merge pull request #3888 from Widthdom/codex/refactor-indexing-tests
[codex] Refactor indexing and test workflow
2 parents faecdf1 + c5d6699 commit f8ab40d

32 files changed

Lines changed: 871 additions & 423 deletions

.github/workflows/dotnet.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,6 @@ jobs:
230230
throw "High or critical NuGet vulnerability detected."
231231
}
232232
233-
- name: Verify formatting
234-
if: matrix.os == 'ubuntu-latest' && matrix.test-framework == 'net8.0'
235-
run: dotnet format whitespace CodeIndex.sln --verify-no-changes --no-restore --verbosity minimal
236-
237233
- name: Verify Release solution build
238234
if: matrix.os == 'ubuntu-latest' && matrix.test-framework == 'net8.0'
239235
run: dotnet build CodeIndex.sln --configuration Release --no-restore -p:UseSharedCompilation=false
@@ -243,6 +239,7 @@ jobs:
243239
run: make lint
244240

245241
- name: Build
242+
if: matrix.os != 'ubuntu-latest' || matrix.test-framework != 'net8.0'
246243
run: dotnet build tests/CodeIndex.Tests/CodeIndex.Tests.csproj --configuration Release --framework ${{ matrix.test-framework }} --no-restore
247244

248245
- name: Test
@@ -254,6 +251,7 @@ jobs:
254251
"--configuration", "Release",
255252
"--framework", "${{ matrix.test-framework }}",
256253
"--no-build",
254+
"--no-restore",
257255
"--nologo",
258256
"--settings", "tests/CodeIndex.Tests/CodeIndex.Tests.runsettings",
259257
"--blame-crash",

TESTING_GUIDE.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Use the full suite by default. Use targeted filters only while iterating locally
2626
- These test-only packages are separate from the production dependency rule in `src/CodeIndex`, which still allows only `Microsoft.Data.Sqlite` at runtime.
2727
- `FsCheck.Xunit` is reserved for property-based tests that assert universal invariants (never-throws contracts, idempotence, "output is parseable by downstream consumer") across randomly generated inputs. Use it to complement, not replace, the example-based `[Fact]` / `[Theory]` tests — pick FsCheck when the property is a universally quantified claim, and an example test when a specific concrete case is the contract.
2828
- Test parallelism: enabled by default across independent test classes. Tests that touch process-global state such as SQLite pool resets, environment variables, or current-directory overrides must use an explicit non-parallel collection, and tests that swap `Console.Out` / `Console.Error` must lock on `TestConsoleLock.Gate`.
29-
- CI runs the test project through `tests/CodeIndex.Tests/CodeIndex.Tests.runsettings`, enables VSTest blame crash and hang collection, applies a 45-minute session timeout plus 60-second xUnit long-running diagnostics, and reruns the suite once after an initial failure. If the retry passes, CI uploads `TestResults/flaky-retry.txt` with the TRX and blame artifacts so the run is treated as suspect instead of silently trusted. XPlat Code Coverage collection is limited to the `ubuntu-latest` / `net8.0` lane so every OS/framework lane still exercises the full suite without paying collector overhead.
29+
- CI runs the test project through `tests/CodeIndex.Tests/CodeIndex.Tests.runsettings`, enables VSTest blame crash and hang collection, applies a 45-minute session timeout plus 60-second xUnit long-running diagnostics, and reruns the suite once after an initial failure. If the retry passes, CI uploads `TestResults/flaky-retry.txt` with the TRX and blame artifacts so the run is treated as suspect instead of silently trusted. XPlat Code Coverage collection is limited to the `ubuntu-latest` / `net8.0` lane so every OS/framework lane still exercises the full suite without paying collector overhead. Test execution runs with `--no-restore --no-build` after the locked restore and Release build steps. The `ubuntu-latest` / `net8.0` lane also reuses the earlier Release solution build instead of running the per-framework test-project build again, and uses `make lint` as the single formatting verifier.
3030

3131
## Test Layout
3232

@@ -116,11 +116,13 @@ Use the inventory below before adding or moving a test class:
116116
Prefer the existing helper before writing new setup code.
117117

118118
- `CreateTempProject(prefix)` creates a unique temp workspace.
119+
- Use `CreateTempProject(prefix)` instead of adding local `Path.GetTempPath()` / `Guid.NewGuid()` directory helpers; keep any local wrapper as a thin prefix-specific delegate only when it preserves existing call-site readability.
119120
- `InitializeGitRepo(projectRoot)` initializes git and sets repo-local `user.name` and `user.email`.
120121
- `CreateProjectDb(projectRoot)` creates `<projectRoot>/.cdidx/codeindex.db`, initializes schema, and seeds `codeindex_meta.indexed_project_root` to match the project root.
121122
- `InsertIndexedFile(...)` inserts a realistic indexed file with content-derived checksum, chunks, symbols, and references, and now passes the file path into Python symbol extraction so `__init__.py`-based re-export tests can exercise qualified package names.
122123
- `RunGit(...)` executes git without shell quoting issues.
123124
- `DeleteDirectory(path)` retries temp-project cleanup and normalizes attributes. To avoid process-global cross-test interference, it only requests SQLite pool cleanup through `SqlitePoolCleanup` as a Windows-specific retry fallback after a delete failure.
125+
- Use `DeleteDirectory(path)` in temp-workspace `finally` / `Dispose` cleanup paths, including tests that intentionally remove the workspace earlier in the scenario.
124126
- `DeleteFile(path)` retries standalone temp-DB cleanup and uses the same Windows-specific SQLite pool release fallback when pooled handles block deletion.
125127
- `SqlitePoolCleanup` centralizes the Windows SQLite pool workaround for tests. Tests that own a temporary SQLite file for their whole lifetime can enter an exclusive owner lease and dispose it idempotently before deleting the file, instead of calling `SqliteConnection.ClearAllPools()` directly from `Dispose`.
126128
- Tests that intentionally call `SqliteConnection.ClearAllPools()`, mutate process-global environment variables, or override the process current directory are grouped into the non-parallel `SQLite pool sensitive` xUnit collection. Add new tests with those hazards to that collection instead of letting them run in parallel with unrelated classes.
@@ -238,7 +240,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests"
238240
- これらの test-only package は `src/CodeIndex` の本番依存ルールとは別であり、runtime 側は引き続き `Microsoft.Data.Sqlite` のみを許容する。
239241
- `FsCheck.Xunit` はランダム生成入力に対する普遍的不変条件(never-throws、idempotence、"出力が downstream consumer で parse 可能" 等)を表明する property-based テスト専用です。例ベースの `[Fact]` / `[Theory]` を置き換えるのではなく補完するもので、普遍量化された主張なら FsCheck、特定の具体ケースが契約なら例ベースという形で使い分けてください。
240242
- テスト並列実行: 独立したテストクラス間ではデフォルトで有効です。SQLite pool の解放、環境変数の変更、カレントディレクトリの上書きのような process-global 状態を触るテストは、明示的な non-parallel collection に入れてください。`Console.Out` / `Console.Error` を差し替えるテストは `TestConsoleLock.Gate` で lock してください。
241-
- CI は `tests/CodeIndex.Tests/CodeIndex.Tests.runsettings` 経由でテストプロジェクトを実行し、VSTest の blame crash / hang 収集、45分のセッションタイムアウト、60秒の xUnit long-running 診断を有効にします。初回失敗時は suite を1回だけ再実行し、再実行で成功した場合は TRX / blame artifact と一緒に `TestResults/flaky-retry.txt` を upload して、その実行を疑わしい flaky run として扱います。XPlat Code Coverage の収集は `ubuntu-latest` / `net8.0` lane に限定し、すべての OS/framework lane で full suite を実行しつつ collector overhead を避けます。
243+
- CI は `tests/CodeIndex.Tests/CodeIndex.Tests.runsettings` 経由でテストプロジェクトを実行し、VSTest の blame crash / hang 収集、45分のセッションタイムアウト、60秒の xUnit long-running 診断を有効にします。初回失敗時は suite を1回だけ再実行し、再実行で成功した場合は TRX / blame artifact と一緒に `TestResults/flaky-retry.txt` を upload して、その実行を疑わしい flaky run として扱います。XPlat Code Coverage の収集は `ubuntu-latest` / `net8.0` lane に限定し、すべての OS/framework lane で full suite を実行しつつ collector overhead を避けます。テスト実行は locked restore と Release build の後に `--no-restore --no-build` で走らせます。`ubuntu-latest` / `net8.0` lane では、直前の Release solution build を再利用し、per-framework の test-project build は再実行しません。また、formatting verifier は `make lint` だけを使います。
242244

243245
## テスト構成
244246

@@ -329,11 +331,13 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests"
329331
新しいセットアップコードを書く前に、既存ヘルパーを優先してください。
330332

331333
- `CreateTempProject(prefix)` は一意な一時ワークスペースを作成します。
334+
- 独自に `Path.GetTempPath()` / `Guid.NewGuid()` を組み合わせた directory helper を増やさず、`CreateTempProject(prefix)` を使ってください。既存呼び出し側の読みやすさを保つ場合だけ、local wrapper は prefix 固有の薄い委譲に留めます。
332335
- `InitializeGitRepo(projectRoot)` は git を初期化し、repo-local の `user.name``user.email` を設定します。
333336
- `CreateProjectDb(projectRoot)``<projectRoot>/.cdidx/codeindex.db` を作成し、スキーマを初期化したうえで `codeindex_meta.indexed_project_root` に project root を書き込みます。
334337
- `InsertIndexedFile(...)` は内容由来の checksum、chunks、symbols、references を含む現実的なインデックス済みファイルを挿入し、Python の symbol extraction には file path も渡すため、`__init__.py` ベースの再エクスポートテストで package 修飾名を扱えます。
335338
- `RunGit(...)` は shell の quoting 問題に依存せず git を実行します。
336339
- `DeleteDirectory(path)` は temp project cleanup のリトライと属性正規化を扱います。プロセス全体への干渉を避けるため、SQLite pool の解放は Windows で削除に失敗した場合のリトライ時だけに限定します。
340+
- 一時 workspace の `finally` / `Dispose` cleanup では、そのテストシナリオ内で workspace を意図的に先に削除する場合も含めて、`DeleteDirectory(path)` を使ってください。
337341
- `DeleteFile(path)` は standalone な temp DB cleanup をリトライし、pooled handle が削除を妨げる場合は同じ Windows 向け SQLite pool 解放フォールバックを使います。
338342
- `SqlitePoolCleanup` は Windows 向け SQLite pool workaround を集約します。テストの生存期間中ずっと一時 SQLite ファイルを所有するテストは、`SqliteConnection.ClearAllPools()` を直接呼ぶ代わりに exclusive owner lease に入り、削除前に冪等に dispose できます。
339343
- `SqliteConnection.ClearAllPools()` を意図的に呼ぶテスト、process-global な環境変数を変更するテスト、プロセスのカレントディレクトリを上書きするテストは、xUnit の non-parallel collection `SQLite pool sensitive` にまとめます。これらのハザードを持つ新しいテストも、この collection に入れて無関係なクラスとの並列実行を避けてください。

USER_GUIDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,7 @@ cdidx helps AI tools by replacing repeated repo-wide scans with a reusable local
19911991
- `status --json`, `map --json`, and `inspect --json` expose freshness and git-state signals so an agent can decide whether the index is trustworthy.
19921992
- `unused --json` and MCP `unused_symbols` expose bucketed dead-code triage metadata plus graph-support signals, so machine clients can distinguish likely-private cleanup from public/config/reflection suspects and from unsupported-language empty pages.
19931993
- `cdidx mcp` gives Claude Code, Cursor, Windsurf, Copilot, and Codex a native MCP server instead of forcing them to scrape shell text.
1994+
- MCP `tools/list` includes `result._meta` discovery metadata with a first-time AI guide, capability groups, recommended workflows, and the contract that disabled tools are omitted from both `tools` and `_meta`.
19941995

19951996
For the full MCP tool list, JSON field contracts, exact-match metadata, and fallback behavior on legacy databases, see [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md).
19961997

@@ -4551,6 +4552,7 @@ cdidx が AI ワークフローで効く最大の理由は、毎ターン同じ
45514552
- `status --json``map --json``inspect --json` は鮮度と Git 状態のシグナルを返すため、AI がインデックスを信用してよいか判断できます。
45524553
- `unused --json` と MCP `unused_symbols` は、bucket 化されたデッドコード候補と graph-support シグナルを返すため、private cleanup 候補と public/config/reflection suspect、未対応言語の空ページを機械的に区別できます。
45534554
- `cdidx mcp` を使えば、Claude Code、Cursor、Windsurf、Copilot、Codex からシェル出力を無理に解釈せずにネイティブ接続できます。
4555+
- MCP `tools/list``result._meta` discovery metadata として、初回 AI 向けガイド、機能グループ、推奨ワークフロー、無効化済みツールが `tools``_meta` の両方から省かれる契約を返します。
45544556

45554557
MCP ツール一覧、JSON フィールド契約、`--exact` まわりのメタデータ、旧 DB フォールバック時の挙動は [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md#開発者ガイド) を参照してください。
45564558

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
category: internal
3+
affected:
4+
- .github/workflows/dotnet.yml
5+
- TESTING_GUIDE.md
6+
---
7+
8+
## English
9+
10+
- **CI test execution skips redundant restore checks** — the Build and Test workflow now runs `dotnet test` with `--no-restore --no-build` after the locked restore and Release build steps.
11+
12+
## 日本語
13+
14+
- **CI の test execution で重複した restore 確認を省くようにしました** — Build and Test workflow は locked restore と Release build の後、`dotnet test``--no-restore --no-build` で実行します。
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
category: internal
3+
affected:
4+
- .github/workflows/dotnet.yml
5+
- TESTING_GUIDE.md
6+
---
7+
8+
## English
9+
10+
- **CI skips one redundant test-project build** — the `ubuntu-latest` / `net8.0` test lane now reuses the earlier Release solution build instead of rebuilding the same test project before running tests.
11+
12+
## 日本語
13+
14+
- **CI の重複した test-project build を 1 回省くようにしました**`ubuntu-latest` / `net8.0` の test lane は、テスト実行前に同じ test project を再ビルドせず、直前の Release solution build を再利用します。
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
category: internal
3+
affected:
4+
- .github/workflows/dotnet.yml
5+
- dev.sh
6+
- TESTING_GUIDE.md
7+
---
8+
9+
## English
10+
11+
- **CI removes a duplicate formatting check** — the Build and Test workflow now relies on `make lint` as the single whitespace verifier, and `dev.sh lint` runs without a redundant restore.
12+
13+
## 日本語
14+
15+
- **CI の重複した formatting check を削除しました** — Build and Test workflow は `make lint` を唯一の whitespace verifier として使い、`dev.sh lint` は重複した restore なしで実行します。
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
category: fixed
3+
affected:
4+
- src/CodeIndex/Indexer/References/ReferenceExtractor.Core.cs
5+
- src/CodeIndex/Indexer/References/ReferenceExtractor.Preparation.cs
6+
---
7+
8+
## English
9+
10+
- **Reduced C# reference extraction work during full indexing** — files without XML doc comment markers now skip C# XML-doc line-state construction and per-line doc-comment probing.
11+
12+
## 日本語
13+
14+
- **full index 時の C# reference extraction 作業を削減しました** — XML doc comment marker を含まないファイルでは、C# XML-doc 用 line-state 構築と行ごとの doc-comment 判定を省略するようになりました。
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
category: fixed
3+
affected:
4+
- src/CodeIndex/Indexer/Symbols/SymbolExtractor.cs
5+
- tests/CodeIndex.Tests/SymbolExtractorCSharpTests.cs
6+
---
7+
8+
## English
9+
10+
- **C# symbol ranges no longer run away when method bodies write JSON braces** — brace-bodied C# symbols now use raw-source range scanning only when the physical line starts in normal code, so string literal braces inside methods no longer stretch later symbol ranges to the end of large files.
11+
12+
## 日本語
13+
14+
- **C# symbol range が JSON braces を書き込む method body で過大化しなくなりました** — brace body を持つ C# symbol は物理行の開始状態が通常コードのときだけ raw source で範囲走査するため、method 内の string literal braces で後続 symbol range が巨大ファイル末尾まで伸びなくなりました。
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
category: fixed
3+
affected:
4+
- src/CodeIndex/Indexer/Symbols/SymbolExtractor.cs
5+
- src/CodeIndex/Indexer/Symbols/SymbolExtractor.CSharpScanner.cs
6+
- tests/CodeIndex.Tests/SymbolExtractorCSharpTests.cs
7+
---
8+
9+
## English
10+
11+
- **Reduced C# symbol extraction allocation during full indexing** — line-comment-only filtering now avoids allocating a trimmed copy for every C# source line.
12+
13+
## 日本語
14+
15+
- **full index 時の C# symbol extraction allocation を削減しました** — 行コメントだけの行を判定するとき、C# source line ごとの trimmed copy allocation を避けるようになりました。
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
category: fixed
3+
affected:
4+
- src/CodeIndex/Indexer/Scanning/FileContentLoader.cs
5+
- src/CodeIndex/Indexer/References/Languages/CSharpReferenceExtractor.cs
6+
- src/CodeIndex/Indexer/References/Support/StructuralLineMasker.cs
7+
- src/CodeIndex/Indexer/References/ReferenceExtractor.TypeReferences.cs
8+
- tests/CodeIndex.Tests/FileIndexerTests.cs
9+
- tests/CodeIndex.Tests/ReferenceExtractorTests.cs
10+
---
11+
12+
## English
13+
14+
- **Reduced full-index file loading, masking, and C# reference-shape overhead** — normal UTF-8 source files no longer repeat UTF-16 detection during binary checks or allocate a second whole-file UTF-8 byte array just to compute the canonical checksum; languages that do not need structural line masking no longer clone every line array; and common C# type/attribute shapes avoid LINQ array allocation when compacting whitespace.
15+
16+
## 日本語
17+
18+
- **full index 時の file loading / masking / C# reference-shape overhead を削減しました** — 通常の UTF-8 source file では binary check 中の UTF-16 判定の重複と、canonical checksum のためだけに whole-file UTF-8 byte 配列をもう一度確保する処理を省き、structural line masking が不要な言語では行配列全体の clone も避け、一般的な C# type / attribute shape の whitespace compact で LINQ array allocation を避けるようにしました。

0 commit comments

Comments
 (0)