测试 FIDL 协议

前提条件

本教程基于 HLCPP 入门教程

概览

本教程详细介绍了 Echo.EchoString 方法结合使用。本教程介绍了如何使用这两个实用程序 可用于测试在 HLCPP 中实现的 FIDL 协议:

  • gtest 测试循环夹具 sys::testing::ComponentContextProvider
  • HLCPP 绑定提供的 fidl_test_base.h 文件

如果要自行编写代码,请删除以下目录:

rm -r examples/fidl/hlcpp/testing/*

测试将采用 examples/fidl/hlcpp/testing/main.cc 编写。

设置依赖项

如需设置依赖项,请执行以下操作:

  1. 添加测试所需的库:

    #include <fuchsia/examples/cpp/fidl.h>
    #include <fuchsia/examples/cpp/fidl_test_base.h>
    #include <lib/fidl/cpp/binding.h>
    #include <lib/sys/cpp/testing/component_context_provider.h>
    
    #include "src/lib/testing/loop_fixture/test_loop_fixture.h"
    
  2. examples/fidl/hlcpp/testing/BUILD.gn 中为测试添加构建规则:

    # Copyright 2020 The Fuchsia Authors. All rights reserved.
    # Use of this source code is governed by a BSD-style license that can be
    # found in the LICENSE file.
    import("//build/components.gni")
    
    executable("bin") {
      testonly = true
      output_name = "example_hlcpp_protocol_test"
      sources = [ "main.cc" ]
      deps = [
        "//examples/fidl/fuchsia.examples:fuchsia.examples_hlcpp",
        "//sdk/lib/fidl/hlcpp",
        "//sdk/lib/sys/cpp",
        "//sdk/lib/sys/cpp/testing:unit",
        "//src/lib/fxl/test:gtest_main",
        "//src/lib/testing/loop_fixture",
      ]
    }
    
    fuchsia_unittest_package("example-hlcpp-protocol-test") {
      deps = [ ":bin" ]
    }
    
    group("hermetic_tests") {
      testonly = true
      deps = [ ":example-hlcpp-protocol-test" ]
    }
    
    

创建服务器实现

如需创建服务器实现,请执行以下操作:

  1. 为被测试的 Echo 协议添加实现:

    class EchoImpl : public fuchsia::examples::testing::Echo_TestBase {
     public:
      void EchoString(std::string value, EchoStringCallback callback) override { callback(value); }
      void NotImplemented_(const std::string& name) override {
        std::cout << "Not implemented: " << name << std::endl;
      }
    };
    

    此实现不是继承自 fuchsia::examples::Echo,而是继承了 继承自相应的测试基类。这意味着 实现只需替换正在测试的方法 (本例中为 EchoString)以及 NotImplemented_ 方法,该方法用于 如果任何未替换的请求处理程序方法 调用。

  2. 创建一个测试类,用于封装发布 echo 协议的逻辑:

    class EchoServerInstance {
     public:
      explicit EchoServerInstance(std::unique_ptr<sys::ComponentContext> context) {
        context_ = std::move(context);
        binding_ = std::make_unique<fidl::Binding<fuchsia::examples::Echo>>(&impl_);
        fidl::InterfaceRequestHandler<fuchsia::examples::Echo> handler =
            [&](fidl::InterfaceRequest<fuchsia::examples::Echo> request) {
              binding_->Bind(std::move(request));
            };
        context_->outgoing()->AddPublicService(std::move(handler));
      }
    
     private:
      EchoImpl impl_;
      std::unique_ptr<fidl::Binding<fuchsia::examples::Echo>> binding_;
      std::unique_ptr<sys::ComponentContext> context_;
    };
    

    该代码类似于 服务器教程,但 fidl::Binding 归类所有。 这样,系统就会在销毁类时调用绑定的析构函数。 这样,代码就可以在给定的每个测试用例上发布 echo 协议 测试组件上下文的新实例。

实现测试固件类

class EchoTestFixture : public gtest::TestLoopFixture {
 public:
  void SetUp() override {
    TestLoopFixture::SetUp();
    echo_instance_.reset(new EchoServerInstance(provider_.TakeContext()));
  }

  void TearDown() override {
    TestLoopFixture::TearDown();
    echo_instance_.reset();
  }

 protected:
  fuchsia::examples::EchoPtr GetProxy() {
    fuchsia::examples::EchoPtr echo;
    provider_.ConnectToPublicService(echo.NewRequest());
    return echo;
  }

 private:
  std::unique_ptr<EchoServerInstance> echo_instance_;
  sys::testing::ComponentContextProvider provider_;
};

测试夹具会执行以下操作:

  • 存储 ComponentContextProvider 的实例。每次测试时,它都会使用 创建一个新的测试上下文,并使用 EchoServerInstance 类。
  • 提供 GetProxy() 方法,用于初始化当前测试的代理 组件上下文,并返回该上下文。

添加测试

您可以使用测试固件编写下面的测试示例:

TEST_F(EchoTestFixture, EchoString) {
  fuchsia::examples::EchoPtr proxy = GetProxy();
  bool received_response = false;
  proxy->EchoString("hello there", [&](std::string response) {
    ASSERT_EQ(response, "hello there");
    received_response = true;
  });
  proxy.set_error_handler(
      [](zx_status_t status) { ASSERT_TRUE(false && "should not throw any errors"); });
  RunLoopUntilIdle();
  EXPECT_TRUE(received_response);
}

运行测试

如需运行测试,请执行以下操作:

  1. 配置您的 GN build 以包含该测试:

    fx set core.x64 --with //examples/fidl/hlcpp/testing
  2. 运行测试:

    fx test -vo example-hlcpp-protocol-test

您应该会看到测试输出,表明测试成功。

摘要

  • gtest::TestLoopFixture 不再需要样板异步循环 设置代码。每个测试用例只需调用 RunLoopUntilIdle(),而不是 手动管理async::Loop
  • ComponentContextProvider 可让您轻松模拟组件上下文 。这对于以下情形非常有用:为容器提供特定功能 组件。
  • HLCPP 绑定测试基架为每个协议提供了一个测试库 类,其中包含每个方法的占位符实现。这样,测试 仅实现被测方法。