From abe4fe7bc8599485ce69cac710c7403cea8707cb Mon Sep 17 00:00:00 2001 From: Widthdom Date: Sat, 22 Aug 2026 16:03:42 +0900 Subject: [PATCH] Stabilize Docker entrypoint test timeout (#5132) --- TESTING_GUIDE.md | 4 ++-- changelog.d/unreleased/5132.fixed.md | 16 ++++++++++++++++ .../ReleaseWorkflowDockerContractTests.cs | 6 ++++-- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 changelog.d/unreleased/5132.fixed.md diff --git a/TESTING_GUIDE.md b/TESTING_GUIDE.md index 0bafbfaaf..d5c0b1d84 100644 --- a/TESTING_GUIDE.md +++ b/TESTING_GUIDE.md @@ -396,7 +396,7 @@ Candidate-ordered parallel-index recovery tests must prove that the fatal result TypeScript and Java language-alias filtering share one multi-language database because unique query markers isolate each language result. Kotlin backtick and Java Unicode-escape canonicalization share the path-filtered C# verbatim canonical fixture rather than creating separate databases. `TrimmedCliTestHelper` owns trimmed publish setup and published CLI subprocess execution. Use its shared non-single-file publish for published CLI smoke coverage so a test process pays that publish cost once; keep single-file tests on an explicit per-test publish because they verify a distinct apphost shape. Published CLI smoke tests run only on the `net8.0` test target because the production CLI targets `net8.0`; focused in-process tests keep cross-target behavior covered without repeating the expensive publish on `net9.0`. - Installer snippet and Docker entrypoint script coverage use `ProductionCliFactAttribute` / `ProductionCliTheoryAttribute`, run only on the `net8.0` test target, and are skipped during discovery on Windows because they require a Unix shell. This avoids constructing per-test temporary installer fixtures for cases that cannot execute on that platform. + Installer snippet and Docker entrypoint script coverage use `ProductionCliFactAttribute` / `ProductionCliTheoryAttribute`, run only on the `net8.0` test target, and are skipped during discovery on Windows because they require a Unix shell. This avoids constructing per-test temporary installer fixtures for cases that cannot execute on that platform. The Docker entrypoint fixture keeps a bounded 30-second process deadline so concurrent full-suite scheduling contention does not turn a sub-second shell contract into a false timeout; timeout still kills the fixture process tree. `RunBuiltCli` / `RunCliInSubprocess` subprocess coverage, including timeout-guarded subprocess probes, uses `ProductionRuntimeFactAttribute` / `ProductionRuntimeTheoryAttribute` and runs only on the `net8.0` test target when the subprocess resolves to the production `net8.0` CLI; keep direct in-process command-runner tests cross-target. When a production-runtime test only needs the built CLI to create an indexed fixture, keep that subprocess boundary on the indexing step and run query assertions, including count/path/format variants, in-process through the command runner helpers unless the assertion depends on process-boundary behavior. Full-scan scheduling coverage that only needs one active post-extraction hook uses the compact `CodeIndex.HookIsolationFixture` assembly. Do not copy the full test assembly into that fixture when hook contents are not part of the assertion. @@ -1496,7 +1496,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests" TypeScriptとJavaのlanguage-alias filteringは、固有query markerで各言語結果を分離できるため1つのmulti-language databaseを共有してください。 Kotlin backtickとJava Unicode-escape canonicalizationは別databaseを作らず、path-filtered C# verbatim canonical fixtureを共有してください。 `TrimmedCliTestHelper` が trimmed publish setup と published CLI subprocess execution を所有します。published CLI smoke coverage は共有の non-single-file publish を使い、test process あたり 1 回の publish cost に抑えてください。single-file test は apphost shape が別なので、明示的な per-test publish のままにします。published CLI smoke test は production CLI が `net8.0` target であることに合わせて `net8.0` test target でのみ実行し、`net9.0` では高コストな publish を繰り返さず focused な in-process test で cross-target behavior を維持します。 - installer snippet と Docker entrypoint script coverage は `ProductionCliFactAttribute` / `ProductionCliTheoryAttribute` を使い、これらの shell script が target framework 非依存で production CLI が `net8.0` target であることに合わせて `net8.0` test target でのみ実行し、Unix shellを使えないWindowsではdiscovery時にskipします。実行不能なcaseごとのtemporary installer fixture構築を避けてください。 + installer snippet と Docker entrypoint script coverage は `ProductionCliFactAttribute` / `ProductionCliTheoryAttribute` を使い、これらの shell script が target framework 非依存で production CLI が `net8.0` target であることに合わせて `net8.0` test target でのみ実行し、Unix shellを使えないWindowsではdiscovery時にskipします。実行不能なcaseごとのtemporary installer fixture構築を避けてください。Docker entrypoint fixture は有界な30秒のprocess deadlineを使い、同時実行されるfull-suiteのscheduler競合で1秒未満のshell契約が誤ってtimeoutにならないようにします。timeout時は引き続きfixtureのprocess treeをkillします。 `RunBuiltCli` / `RunCliInSubprocess` subprocess coverage は、timeout guard 付きの subprocess probe も含め、subprocess が production `net8.0` CLI に解決される場合は `ProductionRuntimeFactAttribute` / `ProductionRuntimeTheoryAttribute` を使って `net8.0` test target でのみ実行し、direct in-process command-runner test は cross-target のままにします。 production-runtime test が built CLI を indexed fixture の作成にだけ必要とする場合は、subprocess boundary を indexing step に残し、count/path/format variant も含め、process boundary の挙動に依存する assertion を除いて query assertion を command runner helper 経由で in-process 実行してください。 activeなpost-extraction hookが1件あれば十分なfull-scan scheduling coverageでは、小型の`CodeIndex.HookIsolationFixture` assemblyを使います。hook内容自体がassertion対象でない場合に巨大なtest assemblyをfixtureへcopyしないでください。 diff --git a/changelog.d/unreleased/5132.fixed.md b/changelog.d/unreleased/5132.fixed.md new file mode 100644 index 000000000..67e9db8f3 --- /dev/null +++ b/changelog.d/unreleased/5132.fixed.md @@ -0,0 +1,16 @@ +--- +category: fixed +issues: + - 5132 +affected: + - tests/CodeIndex.Tests/ReleaseWorkflowDockerContractTests.cs + - TESTING_GUIDE.md +--- + +## English + +- **Docker entrypoint contract tests now tolerate normal full-suite contention (#5132)** — the fixture keeps a bounded 30-second process deadline, preventing a load-sensitive false timeout while still killing a genuinely stuck process tree. + +## 日本語 + +- **Docker entrypoint 契約テストが通常の full-suite 競合を許容するようになりました (#5132)** — fixture は有界な30秒の process deadline を使い、負荷依存の誤った timeout を防ぎつつ、実際に停止した process tree は引き続き kill します。 diff --git a/tests/CodeIndex.Tests/ReleaseWorkflowDockerContractTests.cs b/tests/CodeIndex.Tests/ReleaseWorkflowDockerContractTests.cs index eb275a0cc..eeeeb7129 100644 --- a/tests/CodeIndex.Tests/ReleaseWorkflowDockerContractTests.cs +++ b/tests/CodeIndex.Tests/ReleaseWorkflowDockerContractTests.cs @@ -6,6 +6,8 @@ namespace CodeIndex.Tests; public partial class ReleaseWorkflowTests { + private static readonly TimeSpan DockerEntrypointFixtureTimeout = TimeSpan.FromSeconds(30); + [Fact] public void ReleaseWorkflow_DockerfileDocumentsSdkRuntimeSplit() { @@ -157,10 +159,10 @@ private static (int ExitCode, string Stdout, string Stderr) RunDockerEntrypoint( process.StartInfo.Environment["CDIDX_RUN_GID"] = targetGid; process.Start(); - if (!process.WaitForExit(5000)) + if (!process.WaitForExit((int)DockerEntrypointFixtureTimeout.TotalMilliseconds)) { process.Kill(entireProcessTree: true); - throw new TimeoutException("docker-entrypoint.sh fixture did not exit within 5 seconds."); + throw new TimeoutException($"docker-entrypoint.sh fixture did not exit within {DockerEntrypointFixtureTimeout.TotalSeconds:0} seconds."); } return (process.ExitCode, process.StandardOutput.ReadToEnd(), process.StandardError.ReadToEnd());