ClickHouse/docs/ja/development/tests.md
2024-11-18 11:58:58 +09:00

32 KiB
Raw Blame History

slug sidebar_position sidebar_label title description
/ja/development/tests 72 テスト ClickHouseのテスト ほとんどのClickHouseの機能は機能テストでテスト可能であり、ClickHouseコードの変更には必ずこれを使用する必要があります。

機能テスト

機能テストは最も簡単で便利に使用できるものです。ほとんどのClickHouseの機能は機能テストでテストすることができ、そのようにテストできるClickHouseコードの変更には必ず使用することが求められます。

各機能テストは、実行中のClickHouseサーバーに対して一つまたは複数のクエリを送信し、結果を参照と比較します。

テストは queries ディレクトリに配置されています。二つのサブディレクトリがあり、それぞれ statelessstateful です。Statelessテストは、事前にロードしたテストデータなしでクエリを実行し、テスト内で小さな合成データセットを即席で作成することが多いです。Statefulテストは、ClickHouseから事前にロードされたテストデータを必要とし、一般公開されています。

各テストは .sql または .sh のどちらかの形式であり得ます。.sql テストは clickhouse-client にパイプされる単純なSQLスクリプトです。.sh テストはそれ自体で実行されるスクリプトです。通常、SQLテストは .sh テストよりも好まれます。.sh テストは通常のSQLでは試せない機能clickhouse-client にデータをパイプしたり、clickhouse-local をテストしたりする際など)のテストが必要な場合にのみ使用すべきです。

:::note 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 substring。また、テストを並行して実行したり、ランダムな順序で実行したりするオプションもあります。

新しいテストの追加

新しいテストを追加するには、queries/0_stateless ディレクトリに .sql または .sh ファイルを作成し、手動で確認した後で次の方法で .reference ファイルを生成します: clickhouse-client < 00000_test.sql > 00000_test.reference または ./00000_test.sh > ./00000_test.reference

テストは、事前に作成されていると仮定される test データベース内のテーブル(作成、削除など)を使用するのみで、また一時テーブルを使用することもできます。

テスト実行を制限する

テストには、テスト実行の制限を指定するために零個またはそれ以上の テストタグ を含めることができます。

.sh テストのタグは、二行目にコメントとして記述します:

#!/usr/bin/env bash
# Tags: no-fasttest

.sql テストのタグは、一行目にSQLコメントとして配置します:

-- Tags: no-fasttest
SELECT 1
タグ名 内容 使用例
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 テーブルエンジンは高速テストで無効化されている
no-[asan, tsan, msan, ubsan] サニタイザを使用するビルドでテストを無効化 QEMUの下でのテストはサニタイザと動作しない
no-replicated-database
no-ordinary-database
no-parallel 他のテストと並行して実行されることを禁止 テストは system テーブルから読み取られ、不変条件が破られる可能性がある
no-parallel-replicas
no-debug
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

上記の設定に加えて、特定のClickHouse機能の使用を定義するために system.build_optionsUSE_* フラグを使用できます。 例えば、テストが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 を使用できます。

テスト名の選び方

テスト名は、5桁の接頭辞に続く説明的な名前で開始します例: 00422_hash_function_constexpr.sql。接頭辞を選ぶには、そのディレクトリで既に存在する最大の接頭辞を見つけ、それを1ずつ増やします。その間に、同じ数の接頭辞を持つ他のテストが追加されるかもしれませんが、それは問題ではなく、その後で変更する必要はありません。

発生すべきエラーの確認

時々、サーバーエラーが不正なクエリに対して発生するかテストしたいことがあります。このために、SQLテストで次の形式の特別なアテーションをサポートしています:

select x; -- { serverError 49 }

このテストは、サーバーが未知のカラム x に関するエラーコード49を返すことを保証します。エラーが発生しないか、別のエラーが発生した場合、テストは失敗します。クライアント側でエラーが発生することを確認したい場合は、clientError アノテーションを使用してください。

エラーメッセージの具体的な表現の確認はしないでください。将来的に変更される可能性があり、テストが不必要に壊れます。エラーコードだけを確認してください。既存のエラーコードがあなたのニーズに十分に厳密でない場合、新しいエラーコードを追加することを検討してください。

分散クエリのテスト

機能テストで分散クエリを使用したい場合は、127.0.0.{1..2} アドレスを使ってサーバーが自身をクエリする remote テーブル関数を活用することができます。または、サーバー設定ファイルで事前に定義されたテストクラスター(例: test_shard_localhostを使用することができます。分散クエリをサポートするためにサーバーが正しく構成されているCI設定で実行されるよう、テスト名に shard または distributed という単語を追加してください。

一時ファイルの取り扱い

時にはシェルテストで、作業用に即席でファイルを作成する必要があるかもしれません。いくつかのCIチェックでは、テストが並行して実行されるため、一意ではない名前のファイルをスクリプト内で作成または削除すると、フレーク状のファイルなどのCIチェックが失敗する可能性があります。この問題を回避するため、環境変数 $CLICKHOUSE_TEST_UNIQUE_NAME を使用して、実行中のテストに固有の名前を一時ファイルに付けるべきです。これにより、セットアップ時に作成したりクリーンアップ時に削除したりするファイルが、そのテストのみで使用中のファイルであり、並行して実行される他のテストではないことが確認できます。

既知のバグ

機能テストによって容易に再現できるバグが見つかっている場合、その準備された機能テストを tests/queries/bugs ディレクトリに保存します。バグが修正された際には、これらのテストは tests/queries/0_stateless に移動されます。

統合テスト

統合テストは、ClickHouseのクラスター構成でのテストや、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 というツールがあり、これは標準入力のトークン化を行い、標準出力にカラー化された結果を書き出します。これらの種類のツールはコード例として、または検証や手動テストのために使用できます。

その他のテスト

tests/external_models には機械学習モデルのテストがあります。これらのテストは更新されておらず、統合テストに移行する必要があります。

クォーラム挿入のための個別のテストがあります。このテストはClickHouseクラスターを別のサーバー上で実行し、いくつかの故障ケースをエミュレートします: ネットワーク分割、パケットドロップClickHouseード間、ClickHouseとZooKeeper間、ClickHouseサーバーとクライアント間などkill -9kill -STOP、およびkill -CONTなどを、Jepsen のように。そして、すべての確認された挿入が記録され、すべて拒否された挿入が記録されていないことを確認します。

クォーラムテストは、ClickHouseがオープンソース化される前に別のチームによって書かれました。このチームは現在ClickHouseに関与していません。テストは誤ってJavaで書かれてしまいました。これらの理由から、クォーラムテストは書き直され、統合テストに移行されるべきです。

手動テスト

新しい機能を開発する際には、手動で機能をテストすることも合理的です。以下の手順でそれを行うことができます:

ClickHouseをビルドします。ターミナルからClickHouseを実行します: programs/clickhouse-server ディレクトリに移動し、./clickhouse-server で実行します。デフォルトで現在のディレクトリから設定ファイル(config.xmlusers.xml、および config.dusers.d ディレクトリ内のファイルを使用します。ClickHouseサーバーに接続するには、programs/clickhouse-client/clickhouse-client を実行します。

すべてのclickhouseツールサーバー、クライアントなどclickhouse という単一のバイナリにリンクされているだけです。このバイナリは programs/clickhouse にあります。すべてのツールは clickhouse tool として、あるいは clickhouse-tool として起動することができます。

別の方法として、ClickHouseパッケージをインストールすることもできます: ClickHouseリポジトリからの安定版リリースまたは./release を使用して自分自身でビルドしたパッケージを入手可能です。サーバーを起動するには 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.d ディレクトリ内のファイルで上書きすることにより自分の config.xml のポート番号を変更して適切なデータパスを提供し、実行できます。

clickhouse バイナリはほとんど依存関係がなく、幅広いLinuxディストリビューションで動作します。サーバー上での変更を素早く確認したい場合、ビルドした clickhouse バイナリをサーバーに scp し、上記の例のようにそれを実行することができます。

ビルドテスト

ビルドテストを行うことで、異なる代替構成や一部の外国のシステムでビルドが壊れていないことを確認できます。これらのテストは自動化されています。

例:

  • Darwin x86_64macOS用のクロスコンパイル
  • FreeBSD x86_64用のクロスコンパイル
  • Linux AArch64用のクロスコンパイル
  • システムパッケージからのライブラリでUbuntu上でビルド推奨されない
  • ライブラリの共有リンクでビルド(推奨されない)

例えば、システムパッケージからのビルドは悪い慣習です。なぜなら、システムが何のバージョンのパッケージを持つかを保証できないからです。しかし、これはDebianのメンテナによってどうしても必要とされます。このため、少なくともこのビルドのバリエーションをサポートする必要があります。別の例としては、共有リンクは一般的なトラブルの原因となりますが、一部の愛好家には必要です。

全てのビルドのバリエーションに全てのテストを実行することはできませんが、少なくとも様々なビルドバリエーションが壊れていないことは確認したいと考えています。この目的でビルドテストを使用します。

また、コンパイルするのに時間がかかるか、多くのRAMを必要とする翻訳単位がないこともテストします。

また、大きすぎるスタックフレームがないこともテストします。

プロトコル互換性のテスト

ClickHouseネットワークプロトコルを拡張する際には、古いclickhouse-clientが新しいclickhouse-serverと動作するか、新しいclickhouse-clientが古いclickhouse-serverと動作するかを手動でテストしています対応するパッケージからのバイナリを実行することで確認

また、統合テストでいくつかのケースを自動的にテストしています:

  • 古いバージョンのClickHouseによって書かれたデータが新しいバージョンで正しく読み取り可能であるかどうか。
  • 異なるClickHouseバージョンが混在するクラスターで分散クエリが機能するかどうか。

コンパイラの支援

メインのClickHouseコードdbms ディレクトリにあるコード)は、-Wall -Wextra -Werror およびいくつかの追加の警告が有効になってビルドされます。ただし、これらのオプションはサードパーティのライブラリには適用されていません。

Clangにはさらに多くの有用な警告があります - -Weverything を使ってそれらを探し、デフォルトビルドに取り入れるものを選ぶことができます。

本番ビルドではclangが使用されますが、gccビルドもテストしています。開発では、clangを使用する方が通常は便利です。自分のマシンでデバッグモードでビルドするラップトップのバッテリーを節約するためことができますが、コンパイラは -O3 を使ってより良い制御フローおよび手続き間解析を行い、より多くの警告を生成することができることを注意してください。デバッグモードでclangを使用するとき、libc++ のデバッグバージョンが使用され、実行時により多くのエラーをキャッチできるようになります。

サニタイザ

:::note ローカルで起動するときにプロセスClickHouseサーバーまたはクライアントがクラッシュする場合は、アドレス空間レイアウトランダム化を無効にする必要があるかもしれません: sudo sysctl kernel.randomize_va_space=0 :::

アドレスサニタイザ

ASanの下での機能テスト、統合テスト、ストレステスト、およびユニットテストをコミットごとに実行しています。

スレッドサニタイザ

TSanの下での機能テスト、統合テスト、ストレステスト、およびユニットテストをコミットごとに実行しています。

メモリサニタイザ

MSanの下での機能テスト、統合テスト、ストレステスト、およびユニットテストをコミットごとに実行しています。

不定動作サニタイザ

UBSanの下での機能テスト、統合テスト、ストレステスト、およびユニットテストをコミットごとに実行しています。いくつかのサードパーティライブラリのコードはUBについてのサニタイジングがされていません。

ValgrindMemcheck

過去にはValgrindを使って夜間に機能テストを実行していましたが、今は行っていません。数時間かかります。現在、re2 ライブラリに既知の偽陽性が一つあります。詳細はこの記事を参照してください。

ファジング

ClickHouseのファジングは、libFuzzer とランダムSQLクエリの両方を使用して実装されています。 すべてのファジーテストはサニタイザ(アドレスおよび不定動作)を使用して実行するべきです。

LibFuzzerはライブラリコードの孤立したファジーテストに使用されます。ファジーはテストコードの一部として実装され、「_fuzzer」という名前の接尾辞が付けられます。 ファザーの例は src/Parsers/fuzzers/lexer_fuzzer.cpp にあります。LibFuzzer固有の設定、Dictionary、およびコーパスは tests/fuzz に保存されています。 ユーザー入力を処理するすべての機能に対してファジーテストを書くことを奨励します。

ファッザーはデフォルトでビルドされません。ファッザーをビルドするには -DENABLE_FUZZING=1 および -DENABLE_TESTS=1 オプションを設定する必要があります。 ジェマロックを無効にしてファジーテストをビルドすることをお勧めします。ClickHouseのファッジングをGoogleのOSS-Fuzzに統合するために使用される構成は docker/fuzz にあります。

また、サーバーがそれらを実行するときに死なないことを確認するためにランダムSQLクエリを生成する単純なファジーテストも使用します。 00746_sql_fuzzy.pl にあります。これは継続的に(夜間や長時間にわたって)実行されるべきテストです。

また、ASTベースの高度なクエリファザーを使用し、多くのコーナーケースを見つけることができます。これはクエリASTでランダムな置換を行います。テストの途中でそれらをランダムな順序で処理する際に、以前のテストからASTードを記憶し、後続のテストのファジングにそれらを使用します。このファザーについての詳細はこのブログ記事で学ぶことができます。

ストレステスト

ストレステストはファジングの別のケースです。これは一つのサーバーでランダムな順序で並行してすべての機能テストを実行します。テスト結果は確認されません。

確認されること:

  • サーバーがクラッシュしないこと、デバッグまたはサニタイザのトラップが発動されないこと
  • デッドロックがないこと
  • データベース構造が一貫していること
  • テスト後にサーバーが正常に停止でき、例外なく再起動できること

デバッグ、ASan、TSan、MSan、UBSanの五つのバリエーションがあります。

スレッドファザー

スレッドサニタイザと混同しないでください。スレッドファザーはスレッドの実行順序をランダム化する別の種類のファジングです。それにより、さらに特別なケースを見つけることができます。

セキュリティ監査

セキュリティチームはClickHouseの能力について基本的な概要を行いました。

静的解析

clang-tidy をコミットごとに実行しています。clang-static-analyzer チェックも有効にしています。clang-tidy は一部のスタイルチェックにも使用されています。

clang-tidyCoveritycppcheckPVS-StudiotscancodeCodeQL を評価しました。使用方法についての指示は tests/instructions/ ディレクトリにあります。

CLion をIDEとして使用している場合、いくつかの clang-tidy チェックをそのまま使用することができます。

また、shellcheck をシェルスクリプトの静的解析に使用しております。

ハードニング

デバッグビルドでは、ユーザーレベルの割り当てのASLRアドレス空間レイアウトランダム化を行うカスタムアロケータを使用しています。

また、アロケーション後に読み取り専用であることが期待されるメモリ領域を手動で保護します。

デバッグビルドでは、古く、非推奨であるか、セキュリティ上問題があるか、スレッド安全でないとされる関数が呼び出されないことを保証するカスタマイズが施されています。

デバッグアサーションが広範に使用されています。

デバッグビルドでは、"論理エラー" コード(バグを含意)で例外がスローされる場合、プログラムは直ちに停止されます。これにより、リリースビルドでは例外を使用し、デバッグビルドではアサーションとして扱うことができます。

デバッグビルドではジェマロックのデバッグバージョンを使用しています。 デバッグビルドではlibc++のデバッグバージョンも使用しています。

実行時整合性チェック

ディスクに保存されたデータにはチェックサムが付けられています。MergeTreeテーブルのデータは3つの方法で同時にチェックサムされます圧縮データブロック、非圧縮データブロック、ブロック間の総合チェックサム。クライアントとサーバー間、またはサーバー間で転送されるデータもチェックサムされています。レプリケーションはレプリカ上のビット単位で同一のデータを保証します。

これは、故障したハードウェアストレージメディアのビット腐食、サーバーのRAMのビットフリップ、ネットワークコントローラのRAMのビットフリップ、ネットワークスイッチのRAMのビットフリップ、クライアントのRAMのビットフリップ、ワイヤ上のビットフリップから保護するために必要です。ビットフリップは一般的であり、ECC RAMでも、TCPチェックサムが存在していても発生する可能性があります数千のサーバーが毎日ペタバイトのデータを処理すると管理する必要があることもあります動画を参照してください(ロシア語).

ClickHouseはopsエンジニアが故障したハードウェアを見つけるのに役立つ診断を提供します。

* そしてそれは遅くありません。

コードスタイル

コードスタイルのルールはここに記載されています。

一般的なスタイル違反をチェックするために、utils/check-style スクリプトを使用することができます。

コードの適切なスタイルを強制するために、clang-format を使用することができます。.clang-format ファイルはソースのルートにあります。これは私たちの実際のコードスタイルと主に一致しています。しかし、既存のファイルに clang-format を適用することは推奨されません。フォーマットが悪くなるからです。clangソースリポジトリにある clang-format-diff ツールを使用することができます。

また、uncrustify ツールを試してコードを再フォーマットすることができます。設定はソースのルートにある uncrustify.cfg にあります。clang-format よりもテストされていない部分があります。

CLion には独自のコードフォーマッタがあり、私たちのコードスタイルに合わせて調整する必要があります。

また、codespell を使用してコード内のスペルミスを見つけます。これは自動化されています。

テストカバレッジ

機能テストのみでテストカバレッジを追跡していますが、clickhouse-serverのみです。これは日次で実行されます。

テストのためのテスト

不安定なテスト用の自動チェックがあります。すべての新しいテストを100回機能テストの場合または10回統合テストの場合実行します。少なくとも一回でもテストが失敗した場合、それはフレーク状とみなされます。

テストの自動化

テストはGitHub Actionsを利用して実行されます。

ビルドジョブとテストはコミットごとにSandboxで実行されます。生成されたパッケージとテスト結果はGitHubに公開され、直接リンクでダウンロードすることができます。成果物は数か月間保存されます。GitHubでプルリクエストを送信すると、それは「テスト可能」とタグ付けされ、CIシステムがClickHouseパッケージリリース、デバッグ、アドレスサニタイザ付をビルドしてくれます。

時間と計算力に制限があるため、Travis CIは使用していません。 Jenkinsは使用していません。それはかつて使用されていましたが、現在は使用していないことに満足しています。