Skip to content

Latest commit

 

History

History
261 lines (203 loc) · 17.9 KB

README.jp.md

File metadata and controls

261 lines (203 loc) · 17.9 KB

MM regression kernel test tool

本テストツールは主に HWPOISON サブシステムのカーネル開発を推進するために、関連するテストケースをメンテ・共有するものです。

前提条件

前提条件として、テストを走行するシステムに以下のパッケージがインストールされている必要があります。

  • gcc
  • ruby
  • numactl
  • numactl-devel (on RHEL/Fedora), libnuma-dev (on Ubuntu)

その他、テストケースによっては追加でライブラリやツールが必要となることもあります。 それらが不足している場合、エラーメッセージ等で分かるようになっているはずなので、適宜インストールしてください。 また、環境がテストケースの要件を満たしていない場合、そのテストケースの実行はスキップされます。

典型的な使用方法

以下では基本的な使い方として、全テストケースを実行する場合と指定したテストケースを実行する場合について説明します。

本テストツールは全て root ユーザで実行することを想定しています。

全テストケースの実行

以下のように実行することで、デフォルトで走行対象になっている全テストケースを、フォアグラウンドで実行します。

$ git clone https://github.com/Naoya-Horiguchi/mm_regression
$ cd mm_regression
$ make
$ ./run.sh prepare debug
$ ./run.sh project run

特定のテストケースの実行

指定したテストケースを実行するには、./run.sh recipe list でテストケース一覧を表示し、適宜フィルタして work/debug/recipelist (debug は後述のテストプロジェクト名) に書き込み、その後 ./run.sh project run を実行する。

$ make
$ ./run.sh prepare debug
$ ./run.sh recipe list | grep <string> > work/debug/recipelist
$ ./run.sh project run

テストの内部構造

テスト走行条件や走行するテストケースを細かく指定したいことがあります。 以下では、そのために定義された概念や設定、走行方法について説明します。

テストプロジェクト (RUNNAME)

同じ条件 (サーバ、カーネル、パラメータなど) 下で、テストケースのセットと、各テストケースの走行結果をひとまとめにした概念をテストプロジェクトとします。 テストプロジェクトは走行前に定義する必要があり、上記コマンドの ./run.sh prepare debug はテストプロジェクト debug を定義しています。 テストプロジェクト名はテスト実行中は環境変数 RUNNAME により参照されます。 テストを実行すると走行結果は全てディレクトリ work/$RUNNAME 配下に記録されます。 このディレクトリ配下には簡単な環境情報 (work/$RUNNAME/environment) や各テストケースのレシピ (後述) を格納しているため、work 配下を保管することで、テストプロジェクトごとにどのような環境・設定でどのようなテストケースを実行したか整理して記録できます。

テストプロジェクトの設定ファイル

テストプロジェクトの設定ファイルは work/$RUNNAME/config です。 例えば以下のような構成をしています。 この設定ファイルはテスト実行時に bash の環境変数として読み込まれ、テストの動作に影響を与えます (各環境変数の意味の詳細については「その他、テスト実行に関する tips」を参照)。

$ cat work/debug/config
export RUNNAME=debug
export RUN_MODE=all
export SOFT_RETRY=1
export HARD_RETRY=1
export TEST_DESCRIPTION="MM regression test"
export UNPOISON=false
export FAILRETRY=
export PRIORITY=0-20
export BACKWARD_KEYWORD=
export FORWARD_KEYWORD=
export LOGLEVEL=1

その他、テストケースによっては固有の環境変数が与えられている前提のものがあります。 例えば KVM ゲストを用いるテストケースは仮想マシン名を環境変数 VM=... で与える必要があります。

テストケース

テストケースはレシピファイルで管理され、基本的に 1 つのレシピファイルで 1 つのテストケースを定義します。 レシピファイルは cases 配下に格納され、ファイルパスがテストケースの ID となります。 テンプレートをサポートしていて、類似するテストケースをテンプレートから自動生成することで、効率よくテストケースを記述できるようにしています。 拡張子 .set3 を持つレシピファイルは、テンプレートを用いて書かれたテストケースで、./run.sh recipe split コマンドにより拡張子 .auto3 を持つレシピファイルが生成されます。 定義済みのレシピ一覧を表示するには ./run.sh recipe list を実行します。 テストタイプ、優先度の情報を含むレシピ一覧を表示するには ./run.sh recipe list -p を実行します。

テストケースの記述方法については「テストケースの構成」を参照。

レシピリスト

./run.sh prepare コマンドでテストプロジェクトを作成すると、 全テストケースのリストが work/$RUNNAME/full_recipe_list に保存されます。

テストの実行時には、設定ファイルで与えられた環境変数を元に full_recipe_list から実行すべきテストケースを判断し、順次実行します。 実行したいテストケースが全テストケースの一部のみの場合、full_recipe_list の中から選択したテストケースを work/$RUNNAME/recipelist に書き込むことで、走行対象のテストケースを指定します。

テストの実行状態の確認

現在のテストプロジェクトを知るためには ./run.sh project show コマンドを実行します。

$ ./run.sh proj show
Project Name: debug
Total testcases: 531
Target testcases: 531

現在のテストプロジェクトの進行状態を知るには ./run.sh project summary コマンドを実行します。

$ ./run.sh proj summary
Project Name: debug
Progress: 394 / 525 (75%)
PASS 350, FAIL 26, WARN 0, SKIP 18, NONE 131

テストケース単位で細かい結果を知りたい場合は -p オプションが便利です。

$ ./run.sh proj summary -p
Project Name: 220506a
PASS mm/compaction
FAIL mm/hugetlb/deferred_dissolve/error-type-hard-offline_dissolve-dequeue.auto3
PASS mm/hugetlb/deferred_dissolve/error-type-hard-offline_dissolve-free.auto3
FAIL mm/hugetlb/deferred_dissolve/error-type-soft-offline.auto3
SKIP mm/hugetlb/deferred_dissolve_fault.auto3
PASS mm/hugetlb/dissolve_failure
PASS mm/hugetlb/per_process_usage_counter
...
Progress: 394 / 525 (75%)

テストの継続、再実行

テストを中断したり、テスト中に再起動が発生した場合、./run.sh project run を実行すると中断したテストケースからテストを再開します。

中断状態をクリアして最初から再実行したい場合は、-a オプションを指定します。 再実行時に既に PASS したテストケースは無視したいことがあります。 その場合は -a -p オプションを指定します。

テスト実行中にカーネルパニック等により再起動した場合、同じテストケースから再開しても再起動を繰り返すため、テストが進行しないという状況があります。 これを回避するには -w オプションを指定して実行します。

その他、テスト実行に関する tips

その他、テスト走行に関する細かい要求を実現するために、本テストツールは以下のような機能を持っています。 これらは全て環境変数によってコントロールされます。

  • RUN_MODE: 各テストケースには TEST_TYPE が定義されています (明示的に定義していない場合は normal)。環境変数 RUN_MODETEST_TYPE に応じてテストケースを実行するかどうかの判断に使用され、TEST_TYPERUN_MODE で指定されたタイプに一致する場合、そのテストケースは実行され、そうでない場合は SKIP となります。
    • RUN_MODE=all は特殊な値で、TEST_TYPE に関わらず全てのテストケースが実行されます。
    • RUN_MODE はカンマ区切りで複数のタイプを指定することができます。
    • テストケース側でも TEST_TYPE はカンマ区切りで複数のタイプを指定でき、全てのタイプが RUN_MODE で指定されている場合のみ、そのテストケースは実行されます。
  • SOFT_RETRY: デフォルトは 3 で、あるテストケースを SOFT_RETRY 回実行して 1 回でも成功すればそのテストケースはパスしたとみなします。
  • HARD_RETRY: デフォルトは 1 で、あるテストケースを HARD_RETRY 回実行して全て成功すればそのテストケースはパスしたとみなします。SOFT_RETRYHARD_RETRY の両方を 2 以上にした場合、SOFT_RETRY 回失敗するまでに「HARD_RETRY 回連続で成功」すればパスとみなします。
  • FAILRETRY: TODO
  • PRIORITY: 各テストケースにはテストごとの優先度が定められています。0-20 までの数字で表現され、数字が小さいほど優先度が高いとみなします。環境変数 PRIORITY は実行するテストケースの優先度範囲を指定します。PRIORITY=0-10,12,15-18 のようにカンマ区切りで複数回指定することや、ハイフンで範囲指定することができます。デフォルトは PRIORITY=0-10 です。
  • BACKWARD_KEYWORD: テスト対象のカーネルや実行環境のバージョンによっては、期待動作が変わることがあります。この環境変数にキーワードを指定した時、そのキーワードに紐付けられた期待動作として古い期待動作を採用します。upstream カーネルに新機能が入り、そのカーネルがパスするようテストケースは追随しつつ、古いカーネルでも正しくテストしたい場合に有用です。
  • FORWARD_KEYWORD: BACKWARD_KEYWORD と同様、期待動作の異なる振る舞いを選択するための環境変数です。この環境変数にキーワードを指定した時、そのキーワードに紐付けられた期待動作として新しい期待動作を採用します。今すぐ upstream に入る機能ではないが、開発版のカーネルでパスするテストケースを書きたい場合に有用です。
  • LOGLEVEL: 数値をセットしてログレベルを指定します。デフォルトは 1 で、 2 にするとログが増え、0 にするとログを減らせます。

テストケース開発者向け

以下では、テストケース開発者向けに、本テストツールの走行の流れやテストケースの追加方法について説明します。

テストケースの構成

一つのテストケースは一つのレシピファイルで定義されます。 レシピファイルは基本的には bash シェルスクリプトです。 レシピファイルはそのテストケース内だけで有効な変数を定義することができ、以下の 4 つの関数を実行します。

  • _prepare(): テストケースを実行する際の事前条件チェックや準備処理を記述します。テストケースを実行する条件を満たしていなかったり、準備処理に失敗した場合は非ゼロを返し、その場合テストロジック (_control()) は実行されません。
  • _control(): テストケースを実現するためのロジックを記述します。
  • _cleanup(): _prepare() に副作用を伴う準備処理が実行された場合、それをクリーンアップする処理を記述します。
  • _check(): _control() 処理中に採取した情報をベースにテストの pass/fail 判定する必要がある場合に処理を記述します。

これらが必要かどうかはテストケースに依存しており、単純なものでは _control() しか持たないテストケースもあります。 pass/fail 判定は返り値ベースだと解像度が足りないので、カスタムリターンコードを使用します。 テストケースに変数 EXPECTED_RETURN_CODE が指定されているとき、テスト走行中に期待通りのコードパスを通ったかどうかをチェックします。

EXPECTED_RETURN_CODE="START CHECK1 END"

_control() {
    set_return_code START
    test_logic
    if [ $? -eq 0 ] ; then
        set_return_code CHECK1
    fi
    ...
    set_return_code END
}

この場合、test_logic が成功して if 文内を通った場合にパスします。 理解しやすいリターンコードを定義することで、期待動作を管理しやすくなります。

テストの走行の流れ

本テストツールは、work/$RUNNAME/recipelist で指定されたテストケースのリストを上から順番に実行します。 レシピファイルの階層構造には意味があり、各ディレクトリごとに管理用のサブプロセスを作成し、各テストケースは別のサブプロセスで実行されます。 これはディレクトリ単位で環境変数を効率よく継承させていくとともに、あるテストケースのために定義した変数や関数が後のテストケースの動作に干渉することを避けられます。

例えば、下記のような recipelist があったとします。

cases/test1
cases/dir1/test2
cases/dir1/dir2/test3
cases/dir1/test4
cases/test5

この場合、以下の様な流れに沿ってテストケースは実行されます。

main thread
  |---> sub thread
  |     run cases/test1
  |---> sub thread
  |     (source cases/dir1/config)
  |       |---> sub thread
  |       |     run cases/dir1/test2
  |       |---> sub thread
  |       |     (source cases/dir1/dir2/config)
  |       |       |---> sub thread
  |       |       |     run cases/dir1/dir2/test3
  |       |     (dir_cleanup() in cases/dir1/dir2/config)
  |       |---> sub thread
  |       |     run cases/dir1/test4
  |      (dir_cleanup() in cases/dir1/config)
  |---> sub thread
  |     run cases/test5
  *

各テストケースごとにサブスレッドで実行されるだけでなく、ディレクトリを下る際にもサブスレッドを生成しています。 あるディレクトリ配下の全てのテストに共通の設定を config ファイルに書くことによって、共通の準備処理や事前チェックをまとめて行うことができます。 また、config 内に関数 dir_cleanup() を定義することにより、共通のクリーンナップ処理を実行できます。

テストケース開発時の tips

変数

以下の変数はテストケースのコンテキストで利用できる変数です。

  • TRDIR: このテストツールのトップディレクトリのパスを格納しています。
  • TCDIR: test_core モジュールのディレクトリパスを格納しています (TCDIR=$TRDIR/test_core)。
  • TDIR: 個々のテストケースで使用される一時ディレクトリのパスを格納しています (TDIR=$TRDIR/tmp)。
  • WDIR: テストプロジェクトの結果・進捗に関する情報を保存するためのディレクトリのパスを格納します (WDIR=$TRDIR/work)。
  • GTMPD: テストプロジェクトのディレクトリ (work/$RUNNAME) を指します。テストをコントロールするためのファイルがいくつか格納されています。
  • RTMPD: 各テストケースの情報を格納するディレクトリを指します。例えば cases/dir1/test2 というテストケースの実行時は、RTMPD=work/$RUNNAME/dir1/test2 となります。
  • TMPD: 各リトライラウンドごとの情報を格納するディレクトリを指します。例えば、SOFT_RETRY の 2 回目、HARD_RETRY の 3 回目のラウンドでは、TMPD=$RTMPD/2-3 となります。テストロジックの中間ファイルは基本的にこのディレクトリ配下に保存するようにします。

以下はテストケース内で定義することでテストの動作に影響を与える変数です。

  • MAX_REBOOT: リブートを想定したテストケースにおいて、無限にリブートをループするのを防ぐため、リブート回数の最大値を設定します。デフォルトは 0 です。
  • TEST_PRIORITY: テストの優先度を設定します。デフォルトは 10 です。テストケースの中には時間がかかるものや重要度が低いものがあるので、テストを走行する・しない、あるいは走行順序を指定するのに利用します。
  • TEST_TYPE: 開発中のテストや、他の理由でテストケースにタグをつけたい時に利用します。コンマ区切りの文字列として複数指定することができます。デフォルト値 normal 以外に設定した場合、そのテストケースはデフォルトではスキップされます。そのテストケースを走行させるためには、環境変数 RUN_MODETEST_TYPE のキーワードのどれか一つにセットする必要があります。テストケースの TEST_TYPE の一覧を取得するためには make recipe_priority コマンドを実行します。

その他

  • 全テストを流す場合、カーネルパニック発生時に再起動する仕組み (ダンプを設定したり、ブートパラメータ panic=<N> を指定する) を有効にしておくのが望ましいです。