Files
Alexey MilovidovandClaude Opus 5.5 4cbdcbc1c9 Remove low-value integration tests
This is a stricter version of https://github.com/ClickHouse/ClickHouse/pull/122485,
which was reverted in https://github.com/ClickHouse/ClickHouse/pull/122679.

Remove 85 integration test files. They test the integration test harness,
server misconfigurations, corner cases in obscure functionality, contrived or
hand-corrupted states, internal races rebuilt with failpoints, or only assert
that a metric, log line or setting exists.

Unlike the previous attempt, keep the tests related to data lakes (Iceberg,
Delta Lake, Paimon, Hive, catalogs and their helpers, Spark), the
`test_system_stop.py` tests of streaming engines, and a few other tests of real
user-facing behavior.

The durations table in `ci/jobs/scripts/integration_tests_configs.py` is left
unchanged to avoid merge conflicts; entries for files that no longer exist are
ignored.

Also add guidelines against low-value integration tests to `.claude/CLAUDE.md`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 03:13:59 +02:00

17 KiB

When working with a branch, do not use rebase or amend - add new commits instead.

Do not commit to the master branch. Create a new branch for every task.

When writing text such as documentation, comments, or commit messages, wrap literal names from ClickHouse SQL language, classes and functions, or literal excerpts from log messages inside inline code blocks, such as: MergeTree.

When adding headers to documentation files under docs/, every header must include an explicit anchor in the form {#kebab-case-anchor} at the end of the header line, e.g. ## My Section {#my-section}. This is mandatory for all heading levels. New documentation files must also include a frontmatter block at the top (before the first heading) with description, sidebarTitle, slug, title, and doc_type fields, modelled on existing English .mdx files under docs/.

Before editing a documentation page, inspect it for AUTOGENERATED_START and AUTOGENERATED_END. Do not edit content between these markers directly; update the generator's source of truth instead. For reference documentation under docs/reference/, the source of truth is the structured documentation in the defining ClickHouse source registration, such as FunctionDocumentation or a DECLARE doc string. Do not update generated localized output directly. Direct changes to generated regions are reserved for the dedicated documentation autogeneration workflow and PRs which make changes to these sections without the pr-autogenerated-docs label will fail the docs check.

When writing text such as documentation, comments, or commit messages, write names of functions and methods as f instead of f() - we prefer it for mathematical purity when it refers a function itself rather than its application.

When a change alters the bytes on the wire of the Native format or the native TCP protocol - a new packet or handshake field, a protocol revision bump, or a new or changed column encoding - update the matching spec under docs/reference/interfaces/specs/ in the same change. Refactors and fixes that keep the wire layout do not need a spec update.

When mentioning logical errors, say "exception" instead of "crash", because they don't crash the server in the release build.

Links to ClickHouse CI should be analyzed using the tool at .claude/tools/fetch_ci_report.js, which directly fetches the underlying JSON data without requiring a browser. It accepts GitHub PR URLs (fetches all CI reports) or direct S3/CI HTML URLs.

# Fetch all CI reports for a PR
node .claude/tools/fetch_ci_report.js "https://github.com/ClickHouse/ClickHouse/pull/12345"

# Show only failed tests with CIDB links
node .claude/tools/fetch_ci_report.js "https://github.com/ClickHouse/ClickHouse/pull/12345" --failed --cidb

# Fetch only a specific report from a PR (by index)
node .claude/tools/fetch_ci_report.js "https://github.com/ClickHouse/ClickHouse/pull/12345" --report 2

# Filter by test name, show artifact links
node .claude/tools/fetch_ci_report.js "<url>" --test peak_memory --links

# Download logs and show failed tests
node .claude/tools/fetch_ci_report.js "<url>" --failed --download-logs

# Options:
#   --test <name>               Filter tests by name
#   --failed                    Show only failed tests
#   --all                       Show all test results
#   --links                     Show artifact links (logs.tar.gz, etc.)
#   --cidb                      Show CIDB links for failed tests
#   --report <number>           For PR URLs: fetch only one specific report
#   --download-logs [path]      Download logs to path (default: /tmp/ci_logs.tar.{gz,zst})
#   --credentials <user,password>  HTTP Basic Auth for private repositories

After downloading logs, extract specific test logs:

tar -xzf /tmp/ci_logs.tar.gz ci/tmp/pytest_parallel.jsonl
grep "test_name" ci/tmp/pytest_parallel.jsonl | python3 -c "import sys,json; [print(json.loads(l).get('longrepr','')) for l in sys.stdin if 'failed' in l]"

To analyze CI performance comparison results (slower/faster queries, unstable queries), use the tool at .claude/tools/fetch_perf_report.py. It fetches the machine-readable all-query-metrics.tsv from S3 for each performance shard, filters to client_time, and classifies queries as changed or unstable using the same thresholds as compare.sh.

# Show performance changes for a PR (default: changed + unstable queries only)
python3 .claude/tools/fetch_perf_report.py "https://github.com/ClickHouse/ClickHouse/pull/12345"

# Filter by architecture
python3 .claude/tools/fetch_perf_report.py "https://github.com/ClickHouse/ClickHouse/pull/12345" --arch amd

# Show only per-shard summary (no individual queries)
python3 .claude/tools/fetch_perf_report.py "https://github.com/ClickHouse/ClickHouse/pull/12345" --summary

# Filter by test name
python3 .claude/tools/fetch_perf_report.py "https://github.com/ClickHouse/ClickHouse/pull/12345" --test group_by

# Show all queries (not just changes)
python3 .claude/tools/fetch_perf_report.py "https://github.com/ClickHouse/ClickHouse/pull/12345" --all --sort times

# JSON output for structured analysis
python3 .claude/tools/fetch_perf_report.py "https://github.com/ClickHouse/ClickHouse/pull/12345" --json

# TSV output for piping
python3 .claude/tools/fetch_perf_report.py "https://github.com/ClickHouse/ClickHouse/pull/12345" --tsv

# Also accepts CI HTML URLs
python3 .claude/tools/fetch_perf_report.py "https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?PR=12345&sha=abc123"

Key options: --arch <amd|arm|all> to filter architecture, --metric <name> to change metric (default client_time), --shard <n> for a specific shard, --test <name> / --query <text> for substring filtering, --sort <diff|times|threshold|test> for ordering, --summary for shard-level overview only, --json / --tsv for machine-readable output.

To compile and run C++ code snippets against the ClickHouse codebase without modifying any source files, use the tool at .claude/tools/cppexpr.sh. This is a wrapper around utils/c++expr that auto-detects build directories and handles working directory setup. When asked about the size, layout, or alignment of ClickHouse data structures, or asked to compare performance of code snippets, use this tool to get a definitive answer instead of guessing.

# Query the size of a ClickHouse data structure
.claude/tools/cppexpr.sh -i Core/Block.h 'OUT(sizeof(DB::Block))'

# Query multiple expressions at once
.claude/tools/cppexpr.sh -i Core/Field.h 'OUT(sizeof(DB::Field)) OUT(sizeof(DB::Array))'

# Use global code for helper functions or custom types
.claude/tools/cppexpr.sh -g 'struct Foo { int a; double b; };' 'OUT(sizeof(Foo)) OUT(alignof(Foo))'

# Benchmark a code snippet (100000 iterations, 5 tests)
.claude/tools/cppexpr.sh -i Common/Stopwatch.h -b 100000 'Stopwatch sw;'

# Standalone mode (no ClickHouse headers, just standard C++)
.claude/tools/cppexpr.sh --plain 'OUT(sizeof(std::string))'

Key options: -i HEADER to include headers, -g 'CODE' for global-scope code, -b STEPS for benchmarking, -l LIB to link extra libraries, --plain for standalone compilation without ClickHouse. The OUT(expr) macro prints expr -> value.

When asked to analyze assembly, inspect generated code, find register spills, check branch density, compare codegen between builds, or investigate optimization opportunities in compiled functions, use the tool at .claude/tools/analyze-assembly.py. It disassembles functions from a compiled binary, builds a CFG, computes metrics (spill/branch/call density), and reports findings. Use it instead of manually running llvm-objdump or llvm-nm.

# Basic analysis of a function
python3 .claude/tools/analyze-assembly.py <binary> "<function_name>"

# Search for overloaded/templated functions by regex
python3 .claude/tools/analyze-assembly.py <binary> "insertRangeFrom" --search

# Pick a specific overload from ambiguous results
python3 .claude/tools/analyze-assembly.py <binary> "insertRangeFrom" --search --select 3

# JSON output for structured analysis
python3 .claude/tools/analyze-assembly.py <binary> "<function_name>" --format json

# Source-interleaved disassembly (needs debug info)
python3 .claude/tools/analyze-assembly.py <binary> "<function_name>" --source

# Microarchitectural analysis of loop bodies (--mcpu is required)
python3 .claude/tools/analyze-assembly.py <binary> "<function_name>" --mca --mcpu=znver3

# Profile-weighted analysis (re-ranks findings by runtime impact)
python3 .claude/tools/analyze-assembly.py <binary> "<function_name>" --perf-map tmp/perf.map.jsonl

# Compare codegen between two builds
python3 .claude/tools/analyze-assembly.py --before <old_binary> --after <new_binary> "<function_name>"

# Analyze function at a specific address (useful for heavily-templated symbols)
python3 .claude/tools/analyze-assembly.py <binary> 0x0dc7c780

# Verbose mode to see tool commands
python3 .claude/tools/analyze-assembly.py <binary> "<function_name>" -v

Key options: --search for regex matching, --fuzzy for substring matching, --select N to pick from ambiguous results, --all to analyze all matches, --context N to show surrounding symbols, --max-instructions N to control output size, --mca --mcpu=<model> for llvm-mca throughput analysis, --perf-map <file> for runtime-weighted scoring, --before/--after for diff mode. Hex addresses (e.g. 0x0dc7c780) are resolved to the enclosing symbol automatically — useful when symbol names are too long for regex matching. The tool caches symbol tables by build-id for fast repeated queries.

You can build multiple versions of ClickHouse inside build_* directories, such as build, build_debug, build_asan, etc.

You can run integration tests as in tests/integration/README.md using: python -m ci.praktika run "integration" --test <selectors> invoked from the repository root.

When writing tests, do not add "no-*" tags (like "no-parallel") unless strictly necessarily.

When writing tests in tests/queries, prefer adding a new test instead of extending existing ones.

When removing a feature, do not write tests asserting that the feature no longer exists (for example, a test checking that a removed function or setting now throws an error). Instead, delete the tests of the removed feature. Such tests only pin down the absence of something and become noise.

Integration tests (tests/integration/) are the most expensive part of CI: about 40% of its cost, and the suite barely fits in its timeout. Add an integration test only when a stateless .sql/.sh test cannot cover the behavior, for example when it needs several servers, restarts, a real external service, or a special server configuration. Stateless tests already have ZooKeeper, local clusters (remote('127.0.0.{1,2}'), test_cluster_one_shard_three_replicas_localhost), failpoints, and S3 via MinIO. Keep integration tests small: reuse one module-scoped cluster, reuse existing test modules and their clusters where possible, cover a few core cases rather than a matrix of every combination, and never wait with a fixed time.sleep. Do not add integration tests of these kinds:

  • Rare corner cases that real users are not going to hit: hand-corrupted parts or metadata, contrived combinations of legacy formats and obsolete settings.
  • Tests of the test infrastructure (helpers/cluster.py, Python helpers, the CI image), or of developer tools, rather than of the server.
  • Tests of malformed or absurd configurations: the server refuses to start or reports a config error.
  • Trivia: a metric, profile event, log line, warning, or setting exists, has some value, or is re-read on config reload.
  • A dedicated cluster only to check that a disabled feature flag rejects a request.
  • Reproductions of an internal race that rebuild internals with failpoints and log-line assertions, probabilistic stress loops, and wall-clock timing assertions.
  • Duplicates of existing stateless tests, or tests that run existing stateless tests again with a setting changed.
  • Tests that are skipped as a whole or never run in CI.

These categories do not cover tests of interoperability with external systems, such as data lakes (Iceberg, Delta Lake, Paimon), catalogs, and Spark. Such tests are valuable, including those for compatibility with files written by other implementations.

When adding a new test, use ./tests/queries/0_stateless/add-test <name> for .sql tests or ./tests/queries/0_stateless/add-test <name>.sh for .sh tests. It assigns the next available number prefix and creates both the test and reference files.

When writing C++ code, always use Allman-style braces (opening brace on a new line). This is enforced by the style check in CI.

Never use sleep in C++ code to fix race conditions - this is stupid and not acceptable!

Avoid fallback paths. When an operation fails, prefer letting the error propagate over silently substituting a default value or alternate behavior. Fallbacks hide bugs and make incidents harder to diagnose. If a fallback is genuinely needed, follow the fail-close principle: never perform a destructive, expensive, or otherwise consequential action on the fallback path. Skip the operation and surface the error instead — for example, when label-attribution data is unavailable, do not assume "human-added" and create backports anyway; let the run fail and retry once the data is available.

When writing messages, say ASan, not ASAN, and similar (because there are two words: Address Sanitizer).

When checking the CI status, pay attention to the comment from robot with the links first. Look at the Praktika reports first. The logs of GitHub actions usually contain less info.

Do not use -j argument with ninja; do not use nproc - let it decide automatically.

When building ClickHouse (running ninja), always redirect output to the build log file in the build directory. Always use a subagent to analyze the log and return only a concise summary.

When running tests, always redirect output to a log file in the build directory (e.g. <build_directory>/test_<test_name>.log). Use unique file names per test so multiple tests can run in parallel. Always use a subagent to analyze each log and return only a concise summary.

If I provided a URL with the CI report, logs, or examples, include it in the commit message. If the link has PR=..., also add a link to the corresponding PR.

When creating or updating a pull request, use .github/PULL_REQUEST_TEMPLATE.md as the PR body template. The body should contain: a short description of the change and motivation, then the Changelog category (leave one from the list), then the Changelog entry. Do not invent a custom "## Summary" or "## Test plan" structure — follow the template exactly. The "Bug Fix" category should be used only for real bug fixes, while for fixing CI reports you can use the "CI Fix or improvement" category. Include the URL to CI report I provided if any. If the PR is about a CI failure, search for the corresponding open issues and provide a link in the PR description.

Link related pull requests and issues explicitly, using full GitHub URLs, one relationship per line:

  • When a pull request fixes an issue, put Closes: <full link to the issue> on its own line in the pull request description. GitHub renders this as Closes: #<number> and closes the issue automatically when the pull request is merged into the default branch (auto-close only fires when targeting the default branch).
  • When an issue was caused by a pull request (a regression), put Caused by: <full link to the pull request> on its own line in the issue.
  • For any other relevant pull request or issue, put Related: <full link> on its own line.

Use the keyword Closes (not Fixes or Resolves) for consistency, even though GitHub also auto-closes on Fixes and Resolves. Caused by and Related are not GitHub keywords and trigger no automatic closing; they are conventions for humans and tooling. Issues never close pull requests, so the issue side uses only Caused by and Related.

ARM machines in CI are not slow. They are similar to x86 in performance.

Use tmp subdirectory in the current directory for temporary files (logs, downloads, scripts, etc.), do not use /tmp. Create the directory if needed.

Always use YYYY-MM-DD (ISO) date format. Never write in the American date style. Never omit the year in dates. Never use the relative time (like xxx days ago).

Do not try/catch exceptions to fall back to a less-optimized case. Let the exceptions propagate.

Prefer functional (.sql/.sh) tests over unit (gtest) tests whenever possible. Unit tests are larger, too specific, and they are difficult to maintain.

When you want to test changes in the CI scripts, you can write and run a throwaway test, but you don't need to commit it to the repository, because we don't have automated CI tests.