diff --git a/TESTING_GUIDE.md b/TESTING_GUIDE.md index 7c6a16fbb..7fee787a7 100644 --- a/TESTING_GUIDE.md +++ b/TESTING_GUIDE.md @@ -390,7 +390,7 @@ Use `docs/test-doc-maintenance-plan.md` before moving oversized suites or adding - `IndexCommandRunnerTests.SymbolExtractionWorker_LegacyEnvironmentHooksAreIgnored_Issue3398` launches the isolated symbol worker to prove legacy worker environment variables are ignored. Its callback budget includes process startup and is intentionally wider than ordinary in-process checks so local process load does not turn the legacy-env regression check into a timeout flake (#3863). - `IndexCommandRunnerTests.SymbolExtractionWorker_Utf8RequestsPreserveUnicodeAcrossLanguages` - reuses one isolated worker for C#, Java, TypeScript, Python, Go, and Rust requests whose content and paths contain Japanese text. It keeps direct UTF-8 request framing language-neutral and protects Unicode fidelity without creating a large fixture. + reuses one isolated worker for C#, Java, TypeScript, Python, Go, and Rust requests whose content and paths contain Japanese text. It first sends an ASCII warm-up with the wider test-only startup budget so parallel net8.0/net9.0 process-startup contention is separated from callback timing, then keeps every Unicode request on the ordinary five-second callback budget. This preserves language-neutral direct UTF-8 request framing and Unicode fidelity without weakening the production worker timeout contract or creating a large fixture (#4937). - `IndexCommandRunnerTests.SymbolExtractionWorker_StreamResponseWritesBomlessUtf8Frame` exercises the production stream-response overload with a Japanese C# symbol and verifies one BOM-less, newline-terminated UTF-8 JSON frame. Keep the `StringWriter` protocol tests as the in-process diagnostic path while this test protects process stdout framing. - `BoundedLineReaderTests.ReadUtf8LineAsync_BuffersFramesWithoutDecoding`, `ReadUtf8LineAsync_EnforcesByteLimitBeforeGrowth`, and `ReadUtf8LineAsync_HandlesCrLfAcrossBufferBoundary` @@ -1347,7 +1347,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests" - `IndexCommandRunnerTests.SymbolExtractionWorker_LegacyEnvironmentHooksAreIgnored_Issue3398` isolated symbol worker を起動し、legacy worker 環境変数が無視されることを検証します。この callback budget はプロセス起動時間も含むため、通常の in-process チェックより意図的に広く取り、ローカル負荷で legacy-env 回帰テストが timeout flake にならないようにします(#3863)。 - `IndexCommandRunnerTests.SymbolExtractionWorker_Utf8RequestsPreserveUnicodeAcrossLanguages` - 1つの isolated worker を再利用し、日本語の content と path を含む C#、Java、TypeScript、Python、Go、Rust の request を順に送ります。大規模 fixture を作らず、direct UTF-8 request framing の言語非依存性と Unicode fidelity を固定します。 + 1つの isolated worker を再利用し、日本語の content と path を含む C#、Java、TypeScript、Python、Go、Rust の request を順に送ります。最初に test 専用の広い startup budget で ASCII warm-up を行い、net8.0/net9.0 の並列 process 起動競合と callback の計測を分離したうえで、すべての Unicode request を通常の5秒 callback budget で検証します。production worker の timeout 契約を緩めず、大規模 fixture を作ることなく direct UTF-8 request framing の言語非依存性と Unicode fidelity を固定します(#4937)。 - `IndexCommandRunnerTests.SymbolExtractionWorker_StreamResponseWritesBomlessUtf8Frame` 日本語の C# symbol で本番用 stream-response overload を実行し、BOM なし・改行終端の UTF-8 JSON frame が1件出ることを検証します。`StringWriter` の protocol tests は in-process diagnostic 経路として維持し、このテストで process stdout framing を固定します。 - `BoundedLineReaderTests.ReadUtf8LineAsync_BuffersFramesWithoutDecoding`、`ReadUtf8LineAsync_EnforcesByteLimitBeforeGrowth`、`ReadUtf8LineAsync_HandlesCrLfAcrossBufferBoundary` diff --git a/changelog.d/unreleased/4937.internal.md b/changelog.d/unreleased/4937.internal.md new file mode 100644 index 000000000..de2434c33 --- /dev/null +++ b/changelog.d/unreleased/4937.internal.md @@ -0,0 +1,16 @@ +--- +category: internal +issues: + - 4937 +affected: + - tests/CodeIndex.Tests/IndexCommandRunnerTests.cs + - TESTING_GUIDE.md +--- + +## English + +- **The cross-language UTF-8 symbol-worker regression test now separates process startup from callback timing (#4937)** — the test warms its reusable isolated worker with a dedicated 30-second test-only startup budget, then verifies every Unicode request under the existing five-second callback budget so parallel net8.0/net9.0 startup contention no longer causes a false timeout without changing the production contract. + +## 日本語 + +- **言語横断 UTF-8 symbol-worker 回帰テストで process 起動と callback 計測を分離しました (#4937)** — 再利用する isolated worker を test 専用の30秒 startup budget で warm-up してから、すべての Unicode request を既存の5秒 callback budget で検証するため、production 契約を変更せずに net8.0/net9.0 の並列起動競合による誤 timeout を防ぎます。 diff --git a/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs b/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs index 7feb53bbe..e2fe8ed9e 100644 --- a/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs +++ b/tests/CodeIndex.Tests/IndexCommandRunnerTests.cs @@ -23,7 +23,8 @@ namespace CodeIndex.Tests; [Collection("SQLite pool sensitive")] public partial class IndexCommandRunnerTests { - private static readonly TimeSpan LegacyEnvironmentHookWorkerBudget = TimeSpan.FromSeconds(30); + private static readonly TimeSpan SymbolWorkerStartupBudget = TimeSpan.FromSeconds(30); + private static readonly TimeSpan SymbolWorkerRequestBudget = TimeSpan.FromSeconds(5); private static readonly object FullScanContentLoadHookGate = new(); private readonly JsonSerializerOptions _jsonOptions = new() @@ -476,7 +477,7 @@ public void SymbolExtractionWorker_LegacyEnvironmentHooksAreIgnored_Issue3398() "public class App { }\n", Path.Combine(projectRoot, "App.cs"), projectRoot, - LegacyEnvironmentHookWorkerBudget); + SymbolWorkerStartupBudget); Assert.True(result.Success, result.WorkerError); Assert.False(result.TimedOut); @@ -507,6 +508,16 @@ public void SymbolExtractionWorker_Utf8RequestsPreserveUnicodeAcrossLanguages() (Lang: "rust", Extension: ".rs", Content: "// 顧客\npub struct Customer {}\n"), }; using var worker = new SymbolExtractionWorkerClient(); + var warmup = worker.Invoke( + 0, + "csharp", + "public class StartupProbe { }\n", + Path.Combine(projectRoot, "StartupProbe.cs"), + projectRoot, + SymbolWorkerStartupBudget); + + Assert.False(warmup.TimedOut, "symbol worker startup exceeded the test-only startup budget"); + Assert.True(warmup.Success, $"symbol worker startup: {warmup.WorkerError}"); foreach (var testCase in cases) { @@ -516,8 +527,11 @@ public void SymbolExtractionWorker_Utf8RequestsPreserveUnicodeAcrossLanguages() testCase.Content, Path.Combine(sourceDirectory, "顧客" + testCase.Extension), projectRoot, - TimeSpan.FromSeconds(5)); + SymbolWorkerRequestBudget); + Assert.False( + result.TimedOut, + $"{testCase.Lang}: symbol worker callback exceeded the request budget after startup warm-up"); Assert.True(result.Success, $"{testCase.Lang}: {result.WorkerError}"); Assert.Contains(result.Symbols!, symbol => symbol.Name == "Customer"); }