開始使用

本頁面包含 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

.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 中設定。 如果您沒有包含所用選項的依賴項,它會發出警告。

有很多方法可以自定義配置

  1. 編輯 .kunit/.kunitconfig。 該檔案應包含執行所需測試所需的 kconfig 選項列表,包括它們的依賴項。 您可能需要從 .kunitconfig 中刪除 CONFIG_KUNIT_ALL_TESTS,因為它會啟用許多您可能不需要的其他測試。 如果您需要在 UML 以外的架構上執行,請參閱 在 QEMU 上執行測試

  2. .kunit/.kunitconfig 之上啟用其他 kconfig 選項。 例如,要包含核心的連結串列測試,您可以執行

    ./tools/testing/kunit/kunit.py run \
            --kconfig_add CONFIG_LIST_KUNIT_TEST=y
    
  3. 從樹中提供一個或多個 .kunitconfig 檔案的路徑。 例如,要僅執行 FAT_FSEXT4 測試,您可以執行

    ./tools/testing/kunit/kunit.py run \
            --kunitconfig ./fs/fat/.kunitconfig \
            --kunitconfig ./fs/ext4/.kunitconfig
    
  4. 如果您更改 .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) 中關於模式的說明)來選擇在啟動時執行哪些測試。 如果過濾器中存在 "."(句點),則它將被解釋為測試套件名稱和測試用例之間的分隔符,否則,它將被解釋為測試套件的名稱。 例如,假設我們正在使用預設配置

  1. 通知測試套件的名稱,如 "kunit_executor_test",以執行它包含的每個測試用例

    ./tools/testing/kunit/kunit.py run "kunit_executor_test"
    
  2. 通知測試用例的名稱,以其測試套件作為字首,如 "example.example_simple_test",以專門執行該測試用例

    ./tools/testing/kunit/kunit.py run "example.example_simple_test"
    
  3. 使用萬用字元 (*?[) 執行與模式匹配的任何測試用例,如 "*.*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 輸出中。

編寫您的第一個測試

在您的核心儲存庫中,讓我們新增一些可以測試的程式碼。

  1. 建立一個檔案 drivers/misc/example.h,其中包括

int misc_example_add(int left, int right);
  1. 建立一個檔案 drivers/misc/example.c,其中包括

#include <linux/errno.h>

#include "example.h"

int misc_example_add(int left, int right)
{
        return left + right;
}
  1. 將以下行新增到 drivers/misc/Kconfig

config MISC_EXAMPLE
        bool "My example"
  1. 將以下行新增到 drivers/misc/Makefile

obj-$(CONFIG_MISC_EXAMPLE) += example.o

現在我們準備編寫測試用例了。

  1. 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");
  1. 將以下行新增到 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。

  1. 將以下行新增到 drivers/misc/Makefile

obj-$(CONFIG_MISC_EXAMPLE_TEST) += example_test.o
  1. 將以下行新增到 .kunit/.kunitconfig

CONFIG_MISC_EXAMPLE=y
CONFIG_MISC_EXAMPLE_TEST=y
  1. 執行測試

./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 測試的更多資訊(包括一些用於測試不同事物的常用技術),請參閱 編寫測試