Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions TESTING_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ If you change test code, test helpers, test execution flow, or testing conventio

## Quick Start

Search-alternative coverage in `QueryCommandRunnerSearchIssue4906Tests` uses an initialized temporary database and project for every invocation (#5266). Keep the suite in the SQLite pool sensitive collection, pin `CDIDX_DATA_DIR` without adding explicit CLI flags, disable ambient config, and restore the environment and current directory in `finally`. Preserve the absent `--db` / `--data-dir` replay assertions and validate both net8.0 and net9.0 while the repository index is updating; language-alias resolution and compact output must not read that live index.

Baseline review regressions also exercise indexing exclusion changes, a different indexed root at the same DB path, contradictory/missing omission metadata, and the partial exit code for empty incomparable snapshots.

`AuditBaselineIssue5261Tests` covers compatible deltas, moved lines, changed reviewed evidence, incomplete/legacy metadata, ambiguous duplicates/renames, bounded counts, private atomic writes, invalid paths and malformed/oversized input, plus actual index/recipe CLI export and compare. Keep human/JSON error identity and contextual help/completion checks on both net8.0 and net9.0. Use the console-sensitive collection for CLI capture and isolated temporary projects for baseline files.
Expand Down Expand Up @@ -1186,6 +1188,8 @@ Check the following:
<a id="テストガイド"></a>
# テストガイド

`QueryCommandRunnerSearchIssue4906Tests` の検索代替案テストは、呼び出しごとに初期化済みの一時DBとプロジェクトを使用します (#5266)。SQLite pool sensitive コレクションで実行し、CLIフラグを追加せずに `CDIDX_DATA_DIR` を固定し、外部の設定読み込みを無効にして、環境変数とカレントディレクトリを `finally` で復元してください。再実行案に `--db` / `--data-dir` が含まれない検証を維持し、リポジトリの索引更新中にも net8.0 と net9.0 の両方で検証します。言語エイリアス解決とcompact出力が作業用索引を参照してはいけません。

baseline レビューの回帰テストでは、索引除外設定の変更、同一 DB パスでの索引ルートの変更、矛盾・欠落した省略メタデータ、空の比較不能スナップショットの部分終了コードも検証します。

`AuditBaselineIssue5261Tests` は互換性のある差分、行移動、レビュー済み証拠の変化、不完全・旧形式のメタデータ、曖昧な重複・リネーム、上限付き件数、機密ファイルのアトミック保存、不正パス・壊れた入力・過大入力、および実際の索引・レシピによる CLI 保存と比較を検証します。human/JSON のエラー識別と文脈別ヘルプ・補完を net8.0 と net9.0 の両方で維持してください。CLI 出力の捕捉は console-sensitive コレクションに置き、baseline は分離した一時プロジェクトに保存してください。
Expand Down
16 changes: 16 additions & 0 deletions changelog.d/unreleased/5266.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
category: internal
issues:
- 5266
affected:
- tests/CodeIndex.Tests/QueryCommandRunnerSearchIssue4906Tests.cs
- TESTING_GUIDE.md
---

## English

- Isolated search-alternative tests from the live repository index with temporary database/project contexts, preserving implicit database replay behavior during concurrent index updates (#5266).

## 日本語

- 検索代替案のテストに一時DBとプロジェクトを使用し、作業用索引への依存を解消しました。索引更新中も、DB指定を明示しない再実行案の契約を維持します (#5266)。
47 changes: 37 additions & 10 deletions tests/CodeIndex.Tests/QueryCommandRunnerSearchIssue4906Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace CodeIndex.Tests;

[Collection("SQLite pool sensitive")]
public class QueryCommandRunnerSearchIssue4906Tests
{
[Theory]
Expand All @@ -13,7 +14,7 @@ public void RunSearch_ScanOnlyFlagsPointHumanUsersToFindWithoutExecuting_Issue49
string query,
string scanFlag)
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(
["search", query, scanFlag],
JsonOptions,
Expand All @@ -36,7 +37,7 @@ public void RunSearch_RegexJsonReturnsTypedShellSafeFindAlternative_Issue4906()
{
const string query = "a'b $value; .*";
const string path = "src/space dir/**";
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(
[
"search",
Expand Down Expand Up @@ -89,6 +90,7 @@ public void RunSearch_RegexJsonReturnsTypedShellSafeFindAlternative_Issue4906()
Assert.Contains("--include-generated", argv);
Assert.Contains("--json", argv);
Assert.DoesNotContain("--all", argv);
Assert.DoesNotContain("--db", argv);
Assert.DoesNotContain("--data-dir", argv);

var posix = alternative.GetProperty("posix_sh").GetString()!;
Expand All @@ -102,7 +104,7 @@ public void RunSearch_RegexJsonReturnsTypedShellSafeFindAlternative_Issue4906()
[Fact]
public void RunSearch_StructuredFormatDoesNotInventJsonFlag_Issue4906()
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(
["search", "TODO", "--regex", "--path", "src/**", "--format", "csv"],
JsonOptions,
Expand All @@ -117,7 +119,7 @@ public void RunSearch_StructuredFormatDoesNotInventJsonFlag_Issue4906()
[Fact]
public void RunSearch_FormatCountPreservesStructuredFindOutput_Issue4906()
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(
["search", "TODO", "--regex", "--format", "count"],
JsonOptions,
Expand Down Expand Up @@ -155,7 +157,7 @@ public void RunSearch_OptionShapedQueryIsNotReinterpretedInFindAlternative_Issue

foreach (var testCase in cases)
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(testCase.Args, JsonOptions, "1.0.0-test"));

Assert.Equal(CommandExitCodes.UsageError, exitCode);
Expand All @@ -179,7 +181,7 @@ public void RunSearch_OptionShapedQueryIsNotReinterpretedInFindAlternative_Issue
};
foreach (var args in consumedOptionCases)
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(args, JsonOptions, "1.0.0-test"));

Assert.Equal(CommandExitCodes.UsageError, exitCode);
Expand Down Expand Up @@ -227,7 +229,7 @@ public void RunSearch_UnmappableOrUnsafeScanRequestsExplainWhyWithoutCommand_Iss

foreach (var testCase in cases)
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(testCase.Args, JsonOptions, "1.0.0-test"));

Assert.Equal(CommandExitCodes.UsageError, exitCode);
Expand All @@ -254,7 +256,7 @@ public void RunSearch_UnmappableOrUnsafeScanRequestsExplainWhyWithoutCommand_Iss
[Fact]
public void RunSearch_FindAlternativeRejectsIncompatibleCompactSnippetOutput_Issue4906()
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(
[
"search", "TODO", "--regex", "--path", "src/**",
Expand All @@ -279,7 +281,7 @@ public void RunSearch_FindAlternativeRejectsIncompatibleCompactSnippetOutput_Iss
public void RunSearch_FindAlternativeHonorsJsonByteBudget_Issue4906()
{
const int maxJsonBytes = 200;
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(
[
"search", "TODO", "--regex", "--path", "src/**",
Expand Down Expand Up @@ -322,7 +324,7 @@ public void RunSearch_FindAlternativeRejectsFindValidationFailures_Issue4906()

foreach (var testCase in cases)
{
var (exitCode, stdout, stderr) = CaptureConsole(() =>
var (exitCode, stdout, stderr) = CaptureIsolatedConsole(() =>
ProgramRunner.Run(testCase.Args, JsonOptions, "1.0.0-test"));

Assert.Equal(CommandExitCodes.UsageError, exitCode);
Expand All @@ -336,6 +338,31 @@ public void RunSearch_FindAlternativeRejectsFindValidationFailures_Issue4906()
}
}

private static (int Result, string Stdout, string Stderr) CaptureIsolatedConsole(Func<int> action)
=> CaptureConsole(() =>
{
using var project = TestProjectHelper.CreateTempProjectScope("cdidx_search_alternative");
var dbPath = TestProjectHelper.CreateProjectDb(project.Root);
var previousDirectory = Environment.CurrentDirectory;
var previousDataDir = Environment.GetEnvironmentVariable(DbPathResolver.DataDirEnvironmentVariable);
var previousConfigDisable = Environment.GetEnvironmentVariable(CdidxConfigFile.DisableEnvVar);
try
{
// Language resolution and compact output can open the DB before rejecting
// scan-only flags. Isolate those reads without adding explicit replay flags.
Environment.CurrentDirectory = project.Root;
Environment.SetEnvironmentVariable(DbPathResolver.DataDirEnvironmentVariable, Path.GetDirectoryName(dbPath));
Environment.SetEnvironmentVariable(CdidxConfigFile.DisableEnvVar, "1");
return action();
}
finally
{
Environment.SetEnvironmentVariable(CdidxConfigFile.DisableEnvVar, previousConfigDisable);
Environment.SetEnvironmentVariable(DbPathResolver.DataDirEnvironmentVariable, previousDataDir);
Environment.CurrentDirectory = previousDirectory;
}
});

private static string ValueAfterIssue4906(IReadOnlyList<string> argv, string option)
{
var index = -1;
Expand Down
Loading