駕駛組測試快速入門

按照這個快速入門的說明,根據 簡易單元測試程式碼範例

包含程式庫依附元件

包含這個程式庫依附元件,以及 gtest 依附元件:

#include <lib/driver/testing/cpp/driver_test.h>

#include <gtest/gtest.h>

程式庫提供兩個可用於測試的類別。 在本範例中,我們使用 ForegroundDriverTest 可使用 BackgroundDriverTest。 詳情請參閱下方的「前景與背景」一節。

建立設定類別

測試會定義要傳送至程式庫的設定類別 您將通過範本參數測試 類別會負責管理單元測試的個別部分 確定它們是在正確的調度器環境中執行。

這個設定類別必須定義兩種型別,一種用於驅動程式庫,另一種類型為 其環境依附元件 專區。

以下為範例的設定類別範例:

class TestConfig final {
 public:
  using DriverType = simple::SimpleDriver;
  using EnvironmentType = SimpleDriverTestEnvironment;
};

定義環境類型類別

EnvironmentType 必須是獨立類別 可提供驅動程式的自訂依附元件 您不需要提供架構依附元件 (compat::DeviceServer 除外), 因為程式庫已經存在

如果不需要額外依附元件,請使用 fdf_testing::MinimalCompatEnvironment 可提供預設的 compat::DeviceServer (請注意,這項功能僅適用於 即 Compat 通訊協定不在 SDK 中)。

範例中的環境如下:

class SimpleDriverTestEnvironment : public fdf_testing::Environment {
 public:
  zx::result<> Serve(fdf::OutgoingDirectory& to_driver_vfs) override {
    // Perform any additional initialization here, such as setting up compat device servers
    // and FIDL servers.
    return zx::ok();
  }
};

定義測試

現在我們可以一起測試看看了。這個畫面看起來會像這樣 在我們的範例中:

class SimpleDriverTest : public ::testing::Test {
 public:
  void SetUp() override {
    zx::result<> result = driver_test().StartDriver();
    ASSERT_EQ(ZX_OK, result.status_value());
  }
  void TearDown() override {
    zx::result<> result = driver_test().StopDriver();
    ASSERT_EQ(ZX_OK, result.status_value());
  }

  fdf_testing::ForegroundDriverTest<TestConfig>& driver_test() {
    return driver_test_;
  }

 private:
  fdf_testing::ForegroundDriverTest<TestConfig> driver_test_;
};

TEST_F(SimpleDriverTest, VerifyChildNode) {
  driver_test().RunInNodeContext([](fdf_testing::TestNode& node) {
    EXPECT_EQ(1u, node.children().size());
    EXPECT_TRUE(node.children().count("simple_child"));
  });
}

執行單元測試

驅動程式單元測試會從驅動程式庫本身的測試資料夾中執行。 例如,執行下列指令來執行驅動程式庫測試 針對 iwlwifi 驅動程式庫:

tools/bazel test third_party/iwlwifi/test:iwlwifi_test_pkg

設定引數

DriverType

接受測試的驅動程式庫類型,將透過 driver()RunInDriverContext() 函式。

在預設情況下,這不會用於驅動程式庫生命週期管理 (例如啟動/停止驅動程式庫)。 這項作業是透過驅動程式庫登記符號進行 由驅動程式庫的 FUCHSIA_DRIVER_EXPORT 巨集呼叫建立。

DriverType 中使用自訂測試專屬驅動程式庫時 (例如 提供測試專用函式),請新增靜態 GetDriverRegistration 函式,如下所示。這會覆寫全域註冊符號。

static DriverRegistration GetDriverRegistration()

EnvironmentType

類別包含受測試驅動程式庫的自訂依附元件。 環境一律會在背景調度工具中運作。

這必須是可從 fdf_testing::Environment class 衍生的預設可建構項目 並覆寫以下函式: zx::result<> Serve(fdf::OutgoingDirectory& to_driver_vfs) override;

系統會在背景環境調度器上自動呼叫此函式 請務必留意這一點 請務必將其部分加入提供的 fdf::OutgoingDirectory object。 通常會透過 AddService 方法完成 OutgoingDirectory 會傳回驅動程式庫傳入的命名空間,因此其名稱 to_driver_vfs

以下自訂環境會提供 Compat 通訊協定和 自訂測試定義的 FIDL 伺服器如下所示:

class MyFidlServer : public fidl::WireServer<fuchsia_examples_gizmo::Proto> {...};

class CustomEnvironment : public fdf_testing::Environment {
 public:
  zx::result<> Serve(fdf::OutgoingDirectory& to_driver_vfs) {
    device_server_.Init(component::kDefaultInstance, "root");
    EXPECT_EQ(ZX_OK, device_server_.Serve(
    fdf::Dispatcher::GetCurrent()->async_dispatcher(), &to_driver_vfs));

    EXPECT_EQ(ZX_OK, to_driver_vfs.AddService<fuchsia_examples_gizmo::Service::Proto>(
      custom_server_.CreateInstanceHandler()).status_value());

    return zx::ok();
  }

 private:
  compat::DeviceServer device_server_;
  MyFidlServer custom_server_;
};

前景與背景

要選擇前景或背景驅動程式庫測試,就在於測試計畫 與駕駛通過測試的駕駛通訊如果測試將呼叫驅動程式庫的公用方法 很多時候都應選擇前景驅動程式庫測試。如果測試將透過 驅動程式庫程式較常公開 FIDL,則應選擇背景驅動程式庫測試。

使用前景版本時,測試可以存取受測試的驅動程式庫 並透過 driver() 方法直接呼叫該方法 但傳送至驅動程式庫提供的 FIDL 的同步處理用戶端工作,必須完成 RunOnBackgroundDispatcherSync()

使用背景版本時,測試可將 FIDL 呼叫同步到 驅動程式庫提供的 FIDL,但必須在發生時通過 RunInDriverContext() 存取驅動程式庫程式執行個體

Driver_test()

如上方的範例測試所示,driver_test() getter 表示 建立測試,以傳回程式庫類別的參照。這個物件提供 測試功能可用來在測試中 執行各種作業 例如啟動驅動程式庫、連線至該驅動程式以及執行任務 前景和背景測試都提供幾種方法 也有一些是執行緒模式特有的功能請參閱下方資訊,瞭解 方法。

前景測試可用方法

驅動程式庫

您可以直接從測試中存取驅動程式庫。 驅動程式庫在前景可放心存取 在主測試執行緒上呼叫

RunOnBackgroundDispatcherSync

在背景調度工具上執行工作,與驅動程式庫分開。 這是為了避免在進行同步用戶端呼叫時造成驅動程式庫死結 即可生成在前景的驅動程式庫

背景測試可用的方法

RunInDriverContext

這可用於在受測的驅動程式庫上執行回呼。 回呼輸入將擁有驅動程式庫的參照。 驅動程式庫操作時必須完成這項程序,因為與驅動程式庫接觸是不安全的方式 於主要測試執行緒上進行呼叫。

兩者皆提供的方法

播放時長

存取驅動程式庫執行階段物件。 這可用於建立新的背景調度工具 執行前景調度器 使用者不需要為環境明確建立調度工具。 因為程式庫會負責處理這些元件

StartDriver

這可用來啟動受測試的驅動程式庫。等待開始 完成,然後才傳回結果

StartDriverWithCustomStartArgs

與 StartDriver 相同,但可以在傳送前修改驅動程式庫起始引數 送給驅動程式庫

StopDriver

停止測試中的驅動程式庫。這會在 DriverBase 上呼叫 PrepareStop 並等待作業完成若 StartDriver,就必須呼叫這個方法 成功。如果 StartDriver 故障,但為了符合 驅動程式代管程序的行為,這只是免人工管理。

ShutdownAndDestroyDriver

關閉由驅動程式庫下測的驅動程式庫調度工具,然後 呼叫驅動程式庫 destroy 掛鉤。刪除作業會自動執行這項作業 但如果需要執行測試,可手動呼叫 以便進行部分驗證 重新啟動驅動程式庫

連線

連線至驅動程式庫接受測試的服務成員執行個體。 這可以是驅動程式庫運輸或 Zircon 管道傳輸服務。

ConnectThroughDevfs

連線至驅動程式庫透過 devfs 匯出的通訊協定。 這可以是 devfs 節點的 node_name, 或是節點名稱清單,在到達 devfs 節點前進行週遊。

RunInEnvironmentTypeContext

在測試使用的 EnvironmentType 執行個體上執行工作。

RunInNodeContext

在測試使用的 fdf_testing::TestNode 執行個體上執行工作。 這可用來驗證驅動程式與驅動程式庫程式架構節點的互動 (例如確認已新增多少孩童)。

在單一測試中多次啟動驅動程式庫

在不變更 請務必完成全部 3 個步驟: - StartDriver/StartDriverWithCustomStartArgs - StopDriver - 關閉 AndDestroyDriver

執行* 函式警告

使用執行* 函式時請務必謹慎 (RunInDriverContextRunOnBackgroundDispatcherSyncRunInEnvironmentTypeContextRunInNodeContext)。 這些工作在特定調度器上執行,因此可能不安全:

  • 將原始指標從其他情境傳遞到這些指標 要在函式中使用的 (主要執行緒或其他 Run* 種類)
  • 從擷取的參照或傳回類型傳回原始指標 用於主執行緒,或是在另一個 Run* 函式中擷取/使用 (同一種類的 Run* 函式除外)。

範例