Перейти к основному содержанию

Типы тестов

В ClickHouse есть следующие типы тестов:

Функциональные тесты

Функциональные тесты — самый простой и удобный вариант. Большинство возможностей ClickHouse можно проверять с помощью функциональных тестов, и их обязательно нужно использовать для любого изменения в коде ClickHouse, которое можно протестировать таким способом. Каждый функциональный тест отправляет один или несколько запросов на работающий сервер ClickHouse и сравнивает результат с эталоном. Тесты находятся в каталоге ./tests/queries. Каждый тест может быть одного из двух типов: .sql и .sh.
  • Тест .sql — это простой SQL-скрипт, который передаётся в clickhouse-client.
  • Тест .sh — это скрипт, который запускается самостоятельно.
Как правило, SQL-тесты предпочтительнее тестов .sh. Тесты .sh следует использовать только тогда, когда нужно проверить какую-то возможность, недоступную в чистом SQL, например передачу входных данных в clickhouse-client или тестирование clickhouse-local.
Распространённая ошибка при тестировании типов данных DateTime и DateTime64 — считать, что сервер использует определённый часовой пояс (например, “UTC”). Это не так: в CI часовые пояса в тестовых прогонах намеренно выбираются случайным образом. Самый простой способ обойти это — явно указывать часовой пояс для тестовых значений, например toDateTime64(val, 3, 'Europe/Amsterdam').

Локальный запуск теста

Запустите сервер ClickHouse локально на порту по умолчанию (9000). Чтобы запустить, например, тест 01428_hash_set_nan_key, перейдите в каталог репозитория и выполните следующую команду:
PATH=<path to clickhouse-client>:$PATH tests/clickhouse-test 01428_hash_set_nan_key
Результаты тестов (stderr и stdout) записываются в файлы 01428_hash_set_nan_key.[stderr|stdout], которые находятся рядом с самим тестом (для queries/0_stateless/foo.sql вывод будет записан в queries/0_stateless/foo.stdout). См. tests/clickhouse-test --help для просмотра всех параметров clickhouse-test. Вы можете запустить все тесты или только их часть, указав filter по именам тестов: ./clickhouse-test substring. Также есть параметры для запуска тестов параллельно или в случайном порядке.

Запуск быстрых тестов

Для запуска подмножества тестов (так называемого “Быстрый тест”) может потребоваться достаточно мощная машина. Приведённые ниже команды работают на AWS-инстансе t3.2xlarge с Ubuntu amd64 и хранилищем 100 ГБ.
  1. Установите необходимые зависимости и заново войдите в систему.
sudo apt-get update
sudo apt-get install docker.io
sudo usermod -aG docker "$USER"
  1. Скачайте исходный код.
git clone --single-branch https://github.com/ClickHouse/ClickHouse
cd ClickHouse
  1. Соберите код и запустите “быстрые тесты”.
python -m ci.praktika run fast
Должно получиться
Failed: 0, Passed: 7394, Skipped: 1795
Если вы оставляете запуск без присмотра, можно использовать nohup или disown, чтобы он продолжал выполняться после потери ssh-соединения.

Запуск тестов без сохранения состояния

Для запуска тестов без сохранения состояния может потребоваться достаточно мощная машина. Приведённый ниже вариант работает на инстансе AWS m7i.8xlarge (Ubuntu amd64) с хранилищем объёмом 200 ГБ.
  1. Установите необходимые зависимости и снова войдите в систему.
sudo apt-get update
sudo apt-get install docker.io
sudo usermod -aG docker "$USER"
sudo tee /etc/docker/daemon.json <<'EOF'
{
  "ipv6": true,
  "ip6tables": true
}
EOF
sudo systemctl restart docker
  1. Скачайте исходный код.
git clone --single-branch https://github.com/ClickHouse/ClickHouse
cd ClickHouse
  1. Соберите код.
python -m ci.praktika run build_debug
cp ci/tmp/build/programs/clickhouse ci/tmp
  1. Запустите тесты без сохранения состояния, которые можно запускать параллельно.
python -m ci.praktika run functional
Должно получиться
Failed: 0, Passed: 8497, Skipped: 103
Примечание. Команды python -m ci.praktika run запускают конкретную задачу непрерывной интеграции; подробнее о ClickHouse CI можно прочитать здесь.

Добавление нового теста

Чтобы добавить новый тест, сначала создайте файл .sql или .sh в каталоге queries/0_stateless. Затем сгенерируйте соответствующий файл .reference с помощью clickhouse-client < 12345_test.sql > 12345_test.reference или ./12345_test.sh > ./12345_test.reference. В тестах следует только создавать, удалять, выбирать данные из и т. д. таблиц в базе данных test, которая автоматически создаётся заранее. Допустимо использовать временные таблицы. Чтобы локально настроить такое же окружение, как в CI, установите конфигурации для тестов (они будут использовать mock-реализацию ZooKeeper и скорректируют некоторые настройки)
cd <repository>/tests/config
sudo ./install.sh
Тесты должны быть
  • минимальными: создавать только абсолютно необходимые таблицы и столбцы и сохранять минимальную сложность,
  • быстрыми: выполняться не дольше нескольких секунд (а лучше — меньше секунды),
  • корректными и детерминированными: завершаться с ошибкой тогда и только тогда, когда тестируемая возможность не работает,
  • изолированными/без состояния: не зависеть от окружения и таймингов
  • исчерпывающими: охватывать пограничные случаи, такие как нули, NULL-значения, пустые множества, исключения (отрицательные тесты; для этого используйте синтаксис -- { serverError xyz } и -- { clientError xyz }),
  • очищать таблицы в конце теста (на случай, если что-то осталось),
  • убеждаться, что другие тесты не проверяют то же самое (то есть сначала выполните grep).

Ограничение запуска тестов

У теста может быть ноль или более тегов, задающих ограничения на то, в каких контекстах он запускается в CI. Для тестов .sql теги указываются в первой строке в виде SQL-комментария:
-- Tags: no-fasttest, no-replicated-database
-- no-fasttest: <укажите_причину_для_тега_здесь>
-- no-replicated-database: <укажите_причину_здесь>

SELECT 1
Для тестов .sh теги записываются в виде комментария во второй строке:
#!/usr/bin/env bash
# Tags: no-fasttest, no-replicated-database
# - no-fasttest: <укажите_причину_здесь>
# - no-replicated-database: <укажите_причину_здесь>
Список доступных тегов:
Название тегаЧто делаетПример использования
disabledТест не запускается
longВремя выполнения теста увеличивается с 1 до 10 минут
deadlockТест долго выполняется в цикле
raceТо же, что и deadlock. Предпочтителен deadlock
shardСервер должен принимать соединения на 127.0.0.*
distributedТо же, что и shard. Предпочтителен shard
globalТо же, что и shard. Предпочтителен shard
zookeeperДля запуска теста требуется ZooKeeper или ClickHouse KeeperТест использует ReplicatedMergeTree
replicaТо же, что и zookeeper. Предпочтителен zookeeper
no-fasttestТест не запускается в Быстром тестеТест использует движок таблицы MySQL, который отключен в Быстром тесте
fasttest-onlyТест запускается только в Быстром тесте
no-[asan, tsan, msan, ubsan]Отключает тесты в сборках с санитайзерамиТест запускается под QEMU, который не работает с санитайзерами
no-replicated-databaseОтключает тест, если база данных по умолчанию использует ReplicatedDatabaseEngine
no-ordinary-databaseОтключает тест, если движок базы данных по умолчанию — Ordinary
no-parallelЗапрещает параллельный запуск других тестов вместе с этимТест читает из таблиц system, и инварианты могут быть нарушены
no-parallel-replicasОтключает тест, если включены параллельные реплики
no-debugОтключает тесты в Debug-сборках
no-releaseОтключает тесты в Release-сборках
no-darwinОтключает тест в macOS (Darwin)Тест зависит от специфичных для Linux возможностей, таких как распределенные запросы, procfs или HTTP-сервер
Также поддерживаются следующие параметры: no-stress, no-polymorphic-parts, no-random-settings, no-random-merge-tree-settings, no-backward-compatibility-check, no-cpu-x86_64, no-cpu-aarch64, no-cpu-ppc64le, no-s3-storage. Помимо перечисленных выше настроек, вы можете использовать флаги USE_* из system.build_options, чтобы указывать использование конкретных возможностей ClickHouse. Например, если ваш тест использует таблицу MySQL, следует добавить тег use-mysql.

Указание ограничений для случайных настроек

В тесте можно задать минимальные и максимальные допустимые значения для настроек, которые могут случайным образом изменяться во время выполнения теста. Для тестов .sh ограничения записываются в виде комментария в строке рядом с тегами или на второй строке, если теги не указаны:
#!/usr/bin/env bash
# Tags: no-fasttest
# Random settings limits: max_block_size=(1000, 10000); index_granularity=(100, None)
Для тестов .sql теги указываются в виде SQL-комментария в строке рядом с тегами или в первой строке:
-- Tags: no-fasttest
-- Random settings limits: max_block_size=(1000, 10000); index_granularity=(100, None)
SELECT 1
Если нужно указать только одно ограничение, для второго можно использовать None.

Выбор имени теста

Имя теста начинается с пятизначного префикса, за которым следует описательное имя, например 00422_hash_function_constexpr.sql. Чтобы выбрать префикс, найдите наибольший префикс, уже имеющийся в каталоге, и увеличьте его на единицу.
ls tests/queries/0_stateless/[0-9]*.reference | tail -n 1
Тем временем могут быть добавлены и другие тесты с тем же числовым префиксом, но это нормально и не создаст никаких проблем — позже вам не придётся ничего менять.

Проверка ошибки, которая должна возникнуть

Иногда требуется проверить, что при некорректном запросе возникает ошибка сервера. Для этого в SQL-тестах поддерживаются специальные annotations следующего вида:
SELECT x; -- { serverError 49 }
Этот тест проверяет, что сервер возвращает ошибку с кодом 49 о неизвестном столбце x. Если ошибка не возникает или отличается от ожидаемой, тест завершится неудачей. Если вы хотите убедиться, что ошибка возникает на стороне клиента, используйте аннотацию clientError. Не проверяйте конкретную формулировку сообщения об ошибке: в будущем она может измениться, и тест будет ломаться без необходимости. Проверяйте только код ошибки. Если существующий код ошибки недостаточно точен для ваших задач, подумайте о том, чтобы добавить новый.

Тестирование распределённого запроса

Если вы хотите использовать распределённые запросы в функциональных тестах, можно воспользоваться табличной функцией remote с адресами 127.0.0.{1..2}, чтобы сервер отправлял запросы самому себе; либо использовать предопределённые тестовые кластеры из файла конфигурации сервера, например test_shard_localhost. Не забудьте добавить слова shard или distributed в имя теста, чтобы он запускался в CI с правильной конфигурацией, где сервер поддерживает распределённые запросы.

Работа с временными файлами

Иногда в shell-тесте может потребоваться создать файл на лету. Имейте в виду, что некоторые проверки CI запускают тесты параллельно, поэтому, если вы создаёте или удаляете временный файл в своём скрипте без уникального имени, это может привести к сбою некоторых проверок CI, например Flaky. Чтобы избежать этого, используйте переменную окружения $CLICKHOUSE_TEST_UNIQUE_NAME, чтобы задавать временным файлам уникальные имена для каждого выполняемого теста. Так вы сможете быть уверены, что файл, который вы создаёте при подготовке или удаляете при очистке, используется только этим тестом, а не каким-то другим, выполняющимся параллельно.

Известные ошибки

Если нам известны ошибки, которые можно легко воспроизвести с помощью функциональных тестов, мы помещаем соответствующие готовые тесты в каталог tests/queries/bugs. После исправления ошибок эти тесты переносятся в tests/queries/0_stateless.

Интеграционные тесты

Интеграционные тесты позволяют тестировать ClickHouse в кластерной конфигурации, а также его взаимодействие с другими серверами, такими как MySQL, Postgres и MongoDB. Они полезны для эмуляции разделения сети, потери пакетов и т. п. Эти тесты запускаются в Docker и создают несколько контейнеров с различным ПО. См. tests/integration/README.md, чтобы узнать, как запускать эти тесты. Обратите внимание, что интеграция ClickHouse со сторонними драйверами не тестируется. Кроме того, сейчас у нас нет интеграционных тестов для наших драйверов JDBC и ODBC.

Модульные тесты

Модульные тесты полезны, когда нужно тестировать не ClickHouse целиком, а отдельную изолированную библиотеку или класс. Сборку тестов можно включить или отключить с помощью параметра CMake ENABLE_TESTS. Модульные тесты (и другие тестовые программы) находятся в подкаталогах tests по всему коду. Чтобы запустить модульные тесты, выполните ninja test. Некоторые тесты используют gtest, а некоторые — это просто программы, которые при сбое теста возвращают ненулевой код завершения. Модульные тесты не обязательны, если код уже покрыт функциональными тестами (к тому же функциональные тесты обычно гораздо проще в использовании). Вы можете запускать отдельные проверки gtest, вызывая исполняемый файл напрямую, например:
$ ./src/unit_tests_dbms --gtest_filter=LocalAddress*

Тесты производительности

Тесты производительности позволяют измерять и сравнивать производительность отдельных изолированных частей ClickHouse на синтетических запросах. Тесты производительности находятся в каталоге tests/performance/. Каждый тест представлен файлом .xml с описанием тестового сценария. Тесты запускаются с помощью инструмента docker/test/performance-comparison. Инструкции по запуску см. в файле readme. Каждый тест в цикле выполняет один или несколько запросов (возможно, с различными комбинациями параметров). Если вы хотите повысить производительность ClickHouse в каком-либо сценарии и улучшения можно наблюдать на простых запросах, настоятельно рекомендуется написать тест производительности. Также рекомендуется писать тесты производительности при добавлении или изменении SQL-функций, которые достаточно изолированы и не слишком узкоспециализированы. Во время тестирования всегда полезно использовать perf top или другие инструменты perf.

Инструменты и скрипты для тестирования

Некоторые программы в каталоге tests — это не готовые тесты, а вспомогательные инструменты для тестирования. Например, для Lexer есть инструмент src/Parsers/tests/lexer, который просто разбивает stdin на токены и записывает результат с цветовой подсветкой в stdout. Вы можете использовать такие инструменты как примеры кода, а также для изучения и ручного тестирования.

Прочие тесты

В tests/external_models есть тесты для моделей машинного обучения. Эти тесты не поддерживаются и должны быть перенесены в интеграционные тесты. Есть отдельный тест для вставок с кворумом. Этот тест запускает кластер ClickHouse на отдельных серверах и эмулирует различные сценарии сбоев: сетевое разделение, потерю пакетов (между узлами ClickHouse, между ClickHouse и ZooKeeper, между сервером ClickHouse и клиентом и т. д.), kill -9, kill -STOP и kill -CONT, как в Jepsen. Затем тест проверяет, что все подтверждённые вставки были записаны, а все отклонённые — нет.

Ручное тестирование

Когда вы разрабатываете новую возможность, имеет смысл также протестировать её вручную. Это можно сделать, выполнив следующие шаги: Соберите ClickHouse. Запустите ClickHouse из терминала: перейдите в каталог programs/clickhouse-server и выполните ./clickhouse-server. По умолчанию он будет использовать конфигурацию (config.xml, users.xml и файлы в каталогах config.d и users.d) из текущего каталога. Чтобы подключиться к серверу ClickHouse, запустите programs/clickhouse-client/clickhouse-client. Обратите внимание, что все инструменты ClickHouse (server, client и т. д.) — это просто символьные ссылки на один бинарный файл с именем clickhouse. Этот бинарный файл находится в programs/clickhouse. Все инструменты также можно запускать как clickhouse tool вместо clickhouse-tool. Кроме того, вы можете установить пакет ClickHouse: либо стабильный релиз из репозитория ClickHouse, либо собрать пакет самостоятельно с помощью ./release в корневом каталоге исходного кода ClickHouse. Затем запустите сервер командой sudo clickhouse start (или stop, чтобы остановить сервер). Ищите журнал по пути /etc/clickhouse-server/clickhouse-server.log. Если ClickHouse уже установлен в вашей системе, вы можете собрать новый бинарный файл clickhouse и заменить существующий бинарный файл:
$ sudo clickhouse stop
$ sudo cp ./clickhouse /usr/bin/
$ sudo clickhouse start
Также можно остановить системный clickhouse-server и запустить свой экземпляр с той же конфигурацией, но с выводом логов в терминал:
$ sudo clickhouse stop
$ sudo -u clickhouse /usr/bin/clickhouse server --config-file /etc/clickhouse-server/config.xml
Пример с gdb:
$ sudo -u clickhouse gdb --args /usr/bin/clickhouse server --config-file /etc/clickhouse-server/config.xml
Если системный clickhouse-server уже запущен и вы не хотите его останавливать, можно изменить номера портов в config.xml (или переопределить их в файле в каталоге config.d), указать подходящий путь к данным и запустить сервер. Бинарный файл clickhouse почти не имеет зависимостей и работает в широком спектре дистрибутивов Linux. Чтобы быстро проверить свои изменения на сервере, можно просто скопировать с помощью scp свежесобранный бинарный файл clickhouse на сервер, а затем запустить его, как в примерах выше.

Тесты сборки

Тесты сборки позволяют проверить, что сборка не ломается в различных альтернативных конфигурациях и на некоторых других системах. Эти тесты тоже автоматизированы. Примеры:
  • кросс-компиляция для Darwin x86_64 (macOS)
  • кросс-компиляция для FreeBSD x86_64
  • кросс-компиляция для Linux AArch64
  • сборка на Ubuntu с библиотеками из системных пакетов (не рекомендуется)
  • сборка с динамической компоновкой библиотек (не рекомендуется)
Например, сборка с использованием системных пакетов — плохая практика, потому что мы не можем гарантировать, какая именно версия пакетов установлена в системе. Но это действительно необходимо сопровождающим Debian. Поэтому мы как минимум должны поддерживать этот вариант сборки. Ещё один пример: динамическая компоновка часто становится источником проблем, но некоторым энтузиастам она нужна. Хотя мы не можем запускать все тесты для всех вариантов сборки, мы хотим хотя бы проверять, что разные варианты сборки не сломаны. Для этого мы и используем тесты сборки. Мы также проверяем, что нет единиц компиляции, которые компилируются слишком долго или требуют слишком много оперативной памяти. Мы также проверяем, что нет слишком больших кадров стека.

Проверка совместимости протокола

При расширении сетевого протокола ClickHouse мы вручную проверяем, что старый clickhouse-client работает с новым clickhouse-server, а новый clickhouse-client — со старым clickhouse-server (для этого достаточно запустить бинарные файлы из соответствующих пакетов). Некоторые случаи мы также проверяем автоматически с помощью интеграционных тестов:
  • можно ли в новой версии успешно прочитать данные, записанные старой версией ClickHouse;
  • работают ли распределенные запросы в кластере с разными версиями ClickHouse.

Помощь от компилятора

Основной код ClickHouse (то есть код, расположенный в каталоге src) собирается с флагами -Wall -Wextra -Werror и некоторыми дополнительными предупреждениями. Однако для сторонних библиотек эти параметры не включены. У Clang есть ещё больше полезных предупреждений — их можно посмотреть с помощью -Weverything и выбрать некоторые для сборки по умолчанию. Мы всегда используем clang для сборки ClickHouse — и для разработки, и в production. Вы можете собирать на своей машине в режиме отладки (чтобы экономить заряд ноутбука), но обратите внимание, что компилятор может генерировать больше предупреждений с -O3 благодаря более качественному анализу потока управления и межпроцедурному анализу. При сборке с clang в режиме отладки используется отладочная версия libc++, которая позволяет выявлять больше ошибок во время выполнения.

Санитайзеры

Если процесс (сервер ClickHouse или клиент) аварийно завершается при запуске локально, возможно, потребуется отключить рандомизацию адресного пространства: sudo sysctl kernel.randomize_va_space=0

AddressSanitizer

Мы запускаем функциональные, интеграционные, стрессовые и модульные тесты с ASan при каждом коммите.

Санитайзер потоков

Мы запускаем функциональные, интеграционные, стрессовые и модульные тесты с TSan для каждого коммита.

Санитайзер памяти

Мы запускаем функциональные, интеграционные, стрессовые и модульные тесты под MSan для каждого коммита.

Санитайзер неопределённого поведения

Мы запускаем функциональные, интеграционные, стресс- и модульные тесты с UBSan для каждого коммита. Для кода некоторых сторонних библиотек проверка на UB с помощью UBSan не выполняется.

Valgrind (memcheck)

Раньше мы запускали функциональные тесты под Valgrind по ночам, но теперь этого больше не делаем. Это занимает несколько часов. В настоящее время известно об одном ложноположительном срабатывании в библиотеке re2, см. эту статью.

Фаззинг

Фаззинг в ClickHouse реализован как с использованием libFuzzer, так и с помощью случайных SQL-запросов. Все фазз-тесты следует выполнять с санитайзерами (Address и Undefined). LibFuzzer используется для изолированного фазз-тестирования библиотечного кода. Фаззеры реализованы как часть тестового кода и имеют суффикс “_fuzzer” в имени. Пример фаззера можно найти в src/Parsers/fuzzers/lexer_fuzzer.cpp. Конфигурации, словари и корпус данных для LibFuzzer хранятся в tests/fuzz. Мы рекомендуем писать фазз-тесты для любой функциональности, которая обрабатывает пользовательский ввод. По умолчанию фаззеры не собираются. Чтобы собрать фаззеры, нужно задать оба параметра: -DENABLE_FUZZING=1 и -DENABLE_TESTS=1. Мы рекомендуем отключать Jemalloc при сборке фаззеров. Конфигурацию, используемую для интеграции фаззинга ClickHouse с Google OSS-Fuzz, можно найти в docker/fuzz. Мы также используем простой фазз-тест для генерации случайных SQL-запросов и проверки того, что сервер не падает при их выполнении. Вы можете найти его в 00746_sql_fuzzy.pl. Этот тест следует запускать непрерывно (в течение ночи и дольше). Мы также используем более сложный фаззер запросов на основе AST, который способен находить огромное количество граничных случаев. Он выполняет случайные перестановки и подстановки в AST запросов. Он запоминает узлы AST из предыдущих тестов, чтобы использовать их для фаззинга последующих тестов, обрабатывая их в случайном порядке. Подробнее об этом фаззере можно узнать в этой статье блога.

Стресс-тест

Стресс-тесты — ещё один вид фаззинга. Он запускает все функциональные тесты параллельно, в случайном порядке, на одном сервере. Результаты тестов не проверяются. Проверяется, что:
  • сервер не падает, не срабатывают ловушки отладчика или санитайзера;
  • отсутствуют взаимные блокировки;
  • структура базы данных остаётся согласованной;
  • сервер может успешно остановиться после теста и снова запуститься без исключений.
Существует пять вариантов (Debug, ASan, TSan, MSan, UBSan).

Thread fuzzer

Thread Fuzzer (не путайте с Thread Sanitizer) — это ещё один вид фаззинга, который позволяет случайным образом изменять порядок выполнения потоков. Он помогает находить ещё больше нетривиальных случаев.

Аудит безопасности

Наша команда по безопасности провела общий обзор возможностей ClickHouse с точки зрения безопасности.

Статические анализаторы

Мы запускаем clang-tidy для каждого коммита. Проверки clang-static-analyzer также включены. clang-tidy также используется для некоторых проверок стиля. Мы протестировали clang-tidy, Coverity, cppcheck, PVS-Studio, tscancode, CodeQL. Инструкции по использованию вы найдете в каталоге tests/instructions/. Если вы используете CLion в качестве IDE, некоторые проверки clang-tidy будут доступны сразу. Мы также используем shellcheck для статического анализа shell-скриптов.

Усиление защиты

В отладочной сборке мы используем собственный аллокатор, который выполняет ASLR для пользовательских выделений памяти. Мы также вручную защищаем области памяти, которые после выделения должны оставаться только для чтения. В отладочной сборке мы также используем модифицированную libc, которая гарантирует, что не будут вызываться «вредные» (устаревшие, небезопасные, непотокобезопасные) функции. Assert-проверки в отладочной сборке используются очень широко. В отладочной сборке, если генерируется исключение с кодом “logical error” (что указывает на ошибку в программе), программа аварийно завершается. Это позволяет использовать исключения в релизной сборке, но в отладочной сборке трактовать их как assert-проверку. Для отладочных сборок используется отладочная версия jemalloc. Для отладочных сборок используется отладочная версия libc++.

Проверки целостности во время работы

Для данных, хранящихся на диске, вычисляются контрольные суммы. Для данных в таблицах MergeTree контрольные суммы одновременно вычисляются тремя способами* (для сжатых блоков данных, несжатых блоков данных и в виде общей контрольной суммы по всем блокам). Для данных, передаваемых по сети между клиентом и сервером или между серверами, также вычисляются контрольные суммы. Репликация обеспечивает побитовую идентичность данных на репликах. Это необходимо для защиты от неисправностей оборудования (деградации битов на носителях данных, инверсии битов в оперативной памяти сервера, инверсии битов в оперативной памяти сетевого контроллера, инверсии битов в оперативной памяти сетевого коммутатора, инверсии битов в оперативной памяти клиента, инверсии битов при передаче по сети). Обратите внимание, что инверсии битов — обычное явление и, скорее всего, будут происходить даже при использовании ECC-памяти и при наличии контрольных сумм TCP (если вы эксплуатируете тысячи серверов, ежедневно обрабатывающих PB данных). Смотрите видео (на русском). ClickHouse предоставляет средства диагностики, которые помогут инженерам по эксплуатации найти неисправное оборудование.
  • и это не замедляет работу.

Стиль кода

Правила стиля кода описаны здесь. Чтобы проверить некоторые распространённые нарушения стиля, можно использовать скрипт utils/check-style. Чтобы привести код к правильному стилю, можно использовать clang-format. Файл .clang-format находится в корне исходников. Он в целом соответствует нашему текущему стилю кода. Но применять clang-format к существующим файлам не рекомендуется, поскольку это может ухудшить форматирование. Вместо этого можно использовать инструмент clang-format-diff, который находится в репозитории с исходным кодом clang. Кроме того, можно попробовать инструмент uncrustify для переформатирования кода. Конфигурация находится в uncrustify.cfg в корне исходников. Он протестирован меньше, чем clang-format. У CLion есть собственный форматтер кода, который нужно настроить под наш стиль кода. Мы также используем codespell для поиска опечаток в коде. Это тоже делается автоматически.

Покрытие тестов

Мы также отслеживаем покрытие тестов, но только для функциональных тестов и только для clickhouse-server. Оно измеряется ежедневно.

Проверка самих тестов

Есть автоматическая проверка на нестабильные тесты. Она запускает все новые тесты 100 раз (для функциональных тестов) или 10 раз (для интеграционных тестов). Если тест не проходит хотя бы один раз, он считается нестабильным.

Автоматизация тестирования

Мы запускаем тесты с помощью GitHub Actions. Задачи сборки и тесты выполняются в песочнице для каждого коммита. Полученные пакеты и результаты тестов публикуются на GitHub, откуда их можно скачать по прямым ссылкам. Артефакты хранятся несколько месяцев. Когда вы отправляете pull request на GitHub, мы помечаем его меткой “can be tested”, и наша CI-система собирает для вас пакеты ClickHouse (release, debug, с AddressSanitizer и т. д.).
Последнее изменение 10 июня 2026 г.