開始使用¶
本頁面包含 kunit_tool 和 KUnit 框架的概述,介紹如何執行現有測試,以及如何編寫一個簡單的測試用例,並涵蓋使用者首次使用 KUnit 時遇到的常見問題。
安裝依賴¶
KUnit 具有與 Linux 核心相同的依賴項。 只要您可以構建核心,就可以執行 KUnit。
使用 kunit_tool 執行測試¶
kunit_tool 是一個 Python 指令碼,用於配置和構建核心、執行測試以及格式化測試結果。 從核心儲存庫中,您可以執行 kunit_tool
./tools/testing/kunit/kunit.py run
注意
您可能會看到以下錯誤:“The source tree is not clean, please run ‘make ARCH=um mrproper’”(原始碼樹不乾淨,請執行 ‘make ARCH=um mrproper’)
發生這種情況是因為 kunit.py 在內部透過引數 --build_dir 在命令 make O=output/dir 中將 .kunit(預設選項)指定為構建目錄。 因此,在啟動樹外構建之前,必須清理原始碼樹。
在 admin-guide 的“核心構建目錄”部分中也提到了相同的注意事項,即它的使用,它必須用於 make 的所有呼叫。 好訊息是,它確實可以透過執行 make ARCH=um mrproper 來解決,但請注意,這將刪除當前配置和所有生成的檔案。
如果一切正常,您應該看到以下內容
Configuring KUnit Kernel ...
Building KUnit Kernel ...
Starting KUnit Kernel ...
測試將透過或失敗。
注意
因為這是第一次構建大量原始檔,所以 Building KUnit Kernel 步驟可能需要一段時間。
有關此包裝器的詳細資訊,請參閱: 使用 kunit_tool 執行測試。
選擇要執行的測試¶
預設情況下,kunit_tool 使用最小配置執行所有可訪問的測試,即使用 kconfig 選項的大多數預設值。 但是,您可以透過以下方式選擇要執行的測試:
自定義 Kconfig 用於編譯核心,或者
按名稱篩選測試 以專門選擇要執行的已編譯測試。
自定義 Kconfig¶
.kunitconfig 的一個好的起點是 KUnit 預設配置。 如果您尚未執行 kunit.py run,則可以透過執行以下命令來生成它:
cd $PATH_TO_LINUX_REPO
tools/testing/kunit/kunit.py config
cat .kunit/.kunitconfig
注意
.kunitconfig 位於 kunit.py 使用的 --build_dir 中,預設情況下為 .kunit。
在執行測試之前,kunit_tool 確保 .kunitconfig 中設定的所有配置選項都已在核心 .config 中設定。 如果您沒有包含所用選項的依賴項,它會發出警告。
有很多方法可以自定義配置
編輯
.kunit/.kunitconfig。 該檔案應包含執行所需測試所需的 kconfig 選項列表,包括它們的依賴項。 您可能需要從.kunitconfig中刪除 CONFIG_KUNIT_ALL_TESTS,因為它會啟用許多您可能不需要的其他測試。 如果您需要在 UML 以外的架構上執行,請參閱 在 QEMU 上執行測試。在
.kunit/.kunitconfig之上啟用其他 kconfig 選項。 例如,要包含核心的連結串列測試,您可以執行./tools/testing/kunit/kunit.py run \ --kconfig_add CONFIG_LIST_KUNIT_TEST=y從樹中提供一個或多個 .kunitconfig 檔案的路徑。 例如,要僅執行
FAT_FS和EXT4測試,您可以執行./tools/testing/kunit/kunit.py run \ --kunitconfig ./fs/fat/.kunitconfig \ --kunitconfig ./fs/ext4/.kunitconfig如果您更改
.kunitconfig,kunit.py 將觸發.config檔案的重建。 但是您可以直接編輯.config檔案,或使用make menuconfig O=.kunit等工具進行編輯。 只要它是.kunitconfig的超集,kunit.py 就不會覆蓋您的更改。
注意
要在找到令人滿意的配置後儲存 .kunitconfig
make savedefconfig O=.kunit
cp .kunit/defconfig .kunit/.kunitconfig
按名稱篩選測試¶
如果您想要比 Kconfig 可以提供的更具體的資訊,還可以透過傳遞 glob 過濾器(閱讀 manpage glob(7) 中關於模式的說明)來選擇在啟動時執行哪些測試。 如果過濾器中存在 "."(句點),則它將被解釋為測試套件名稱和測試用例之間的分隔符,否則,它將被解釋為測試套件的名稱。 例如,假設我們正在使用預設配置
通知測試套件的名稱,如
"kunit_executor_test",以執行它包含的每個測試用例./tools/testing/kunit/kunit.py run "kunit_executor_test"
通知測試用例的名稱,以其測試套件作為字首,如
"example.example_simple_test",以專門執行該測試用例./tools/testing/kunit/kunit.py run "example.example_simple_test"
使用萬用字元 (
*?[) 執行與模式匹配的任何測試用例,如"*.*64*"執行任何測試套件中名稱包含"64"的測試用例./tools/testing/kunit/kunit.py run "*.*64*"
不使用 KUnit 包裝器執行測試¶
如果您不想使用 KUnit 包裝器(例如:您希望被測程式碼與其他系統整合,或者使用不同/不受支援的架構或配置),則可以將 KUnit 包含在任何核心中,並且可以手動讀取和解析結果。
注意
不應在生產環境中啟用 CONFIG_KUNIT。 啟用 KUnit 會停用核心地址空間佈局隨機化 (KASLR),並且測試可能會以不適合生產的方式影響核心狀態。
配置核心¶
要啟用 KUnit 本身,您需要啟用 CONFIG_KUNIT Kconfig 選項(在 menuconfig 中的 Kernel Hacking/Kernel Testing and Coverage 下)。 從那裡,您可以啟用任何 KUnit 測試。 它們通常具有以 _KUNIT_TEST 結尾的配置選項。
KUnit 和 KUnit 測試可以編譯為模組。 模組中的測試將在載入模組時執行。
執行測試(不使用 KUnit 包裝器)¶
構建並執行您的核心。 在核心日誌中,測試輸出以 TAP 格式打印出來。 預設情況下,只有在 KUnit/測試是內建的情況下才會發生這種情況。 否則,需要載入該模組。
注意
一些行和/或資料可能會散佈在 TAP 輸出中。
編寫您的第一個測試¶
在您的核心儲存庫中,讓我們新增一些可以測試的程式碼。
建立一個檔案
drivers/misc/example.h,其中包括
int misc_example_add(int left, int right);
建立一個檔案
drivers/misc/example.c,其中包括
#include <linux/errno.h>
#include "example.h"
int misc_example_add(int left, int right)
{
return left + right;
}
將以下行新增到
drivers/misc/Kconfig
config MISC_EXAMPLE
bool "My example"
將以下行新增到
drivers/misc/Makefile
obj-$(CONFIG_MISC_EXAMPLE) += example.o
現在我們準備編寫測試用例了。
在
drivers/misc/example_test.c中新增以下測試用例
#include <kunit/test.h>
#include "example.h"
/* Define the test cases. */
static void misc_example_add_test_basic(struct kunit *test)
{
KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0));
KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1));
KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1));
KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX));
KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN));
}
static void misc_example_test_failure(struct kunit *test)
{
KUNIT_FAIL(test, "This test never passes.");
}
static struct kunit_case misc_example_test_cases[] = {
KUNIT_CASE(misc_example_add_test_basic),
KUNIT_CASE(misc_example_test_failure),
{}
};
static struct kunit_suite misc_example_test_suite = {
.name = "misc-example",
.test_cases = misc_example_test_cases,
};
kunit_test_suite(misc_example_test_suite);
MODULE_LICENSE("GPL");
將以下行新增到
drivers/misc/Kconfig
config MISC_EXAMPLE_TEST
tristate "Test for my example" if !KUNIT_ALL_TESTS
depends on MISC_EXAMPLE && KUNIT
default KUNIT_ALL_TESTS
注意:如果您的測試不支援作為可載入模組構建(不鼓勵),請將 tristate 替換為 bool,並依賴於 KUNIT=y 而不是 KUNIT。
將以下行新增到
drivers/misc/Makefile
obj-$(CONFIG_MISC_EXAMPLE_TEST) += example_test.o
將以下行新增到
.kunit/.kunitconfig
CONFIG_MISC_EXAMPLE=y
CONFIG_MISC_EXAMPLE_TEST=y
執行測試
./tools/testing/kunit/kunit.py run
您應該看到以下失敗
...
[16:08:57] [PASSED] misc-example:misc_example_add_test_basic
[16:08:57] [FAILED] misc-example:misc_example_test_failure
[16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17
[16:08:57] This test never passes.
...
恭喜! 您剛剛編寫了您的第一個 KUnit 測試。
下一步¶
如果您有興趣使用 kunit.py 的一些更高階的功能,請檢視 使用 kunit_tool 執行測試
如果您想在不使用 kunit.py 的情況下執行測試,請檢視 不使用 kunit_tool 執行測試
有關編寫 KUnit 測試的更多資訊(包括一些用於測試不同事物的常用技術),請參閱 編寫測試