Google is committed to advancing racial equity for Black communities. See how.

Compiling FIDL

Prerequisites

This tutorial builds on the Compiling FIDL tutorial. For the full set of FIDL tutorials, refer to the overview

Overview

This tutorial covers how to include the HLCPP FIDL bindings into code you write by creating a unit test that will serve as a "playground" for exploring the the HLCPP bindings.

This document covers how to complete the following tasks:

  • Write a C++ host test.
  • Add the HLCPP bindings of a FIDL library as a build dependency.
  • Include the HLCPP bindings into your C++ code.
  • Inspect and using the generated bindings code

If you'd like to follow along and write the code yourself, feel free to delete the example code:

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

Write a host test

Add a gtest stub to examples/fidl/hlcpp/unittests/main.cc:

#include <gtest/gtest.h>

namespace {

} // namespace

Define a build target for the host test

Next, create a target that will make it possible to run the test on host, by defining a test for it, then depending on it through the $host_toolchain.

This is done by adding the following to examples/fidl/hlcpp/unittests/BUILD.gn.

import("//build/test.gni")
group("unittests") {
  testonly = true
  deps = [ ":example-cpp-host-test($host_toolchain)" ]
}


test("example-cpp-host-test") {
  sources = [ "main.cc" ]
  deps = [ "//third_party/googletest:gtest_main" ]
}

Run the host test

You can now run the empty test suite:

fx set core.x64 --with //examples/fidl/hlcpp/unittests
fx test -vo example-cpp-host-test

You should see test output indicating that zero tests have run, since no tests have been added yet.

Add the HLCPP FIDL bindings as a dependency.

Add a dependency on the HLCPP bindings by referencing the FIDL target directly. The new test target should look like:

test("example-cpp-host-test") {
  sources = [ "main.cc" ]
  deps = [
    "//examples/fidl/fuchsia.examples",
    "//third_party/googletest:gtest_main",
  ]
}

(Optional) To view the newly generated bindings:

  1. Rebuild using fx build.
  2. Change to the generated files directory: out/default/fidling/gen/examples/fidl/fuchsia.examples/fuchsia/examples. You may need to change out/default if you have set a different build output directory. You can check your build output directory by running cat .fx-build-dir.

For more information on how to find generated bindings code, see Viewing Generated Bindings Code.

Include the bindings, by adding the following include statement to the top of examples/fidl/hlcpp/unittests/main.cc

#include <fuchsia/examples/cpp/fidl.h>

Now, feel free to write some tests and play around with the bindings by referring to the generated code or the HLCPP Bindings Reference.

Here's some example code to get started. You can add this inside the anonymous namespace in main.cc:

TEST(FidlExamples, Bits) {
  auto flags = fuchsia::examples::FileMode::READ | fuchsia::examples::FileMode::WRITE;
  ASSERT_EQ(static_cast<uint16_t>(flags), 0b11);
  flags |= fuchsia::examples::FileMode::EXECUTE;
  ASSERT_EQ(flags, fuchsia::examples::FileModeMask);
}

TEST(FidlExamples, Enums) {
  ASSERT_EQ(static_cast<uint32_t>(fuchsia::examples::LocationType::MUSEUM), 1u);
}

TEST(FidlExamples, Structs) {
  fuchsia::examples::Color default_color;
  ASSERT_EQ(default_color.id, 0u);
  ASSERT_EQ(default_color.name, "red");

  fuchsia::examples::Color blue = {1, "blue"};
  ASSERT_EQ(blue.id, 1u);
}

TEST(FidlExamples, Unions) {
  auto int_val = fuchsia::examples::JsonValue::WithIntValue(1);
  ASSERT_EQ(int_val.Which(), fuchsia::examples::JsonValue::Tag::kIntValue);
  ASSERT_TRUE(int_val.is_int_value());

  auto str_val = fuchsia::examples::JsonValue::WithStringValue("1");
  ASSERT_EQ(str_val.Which(), fuchsia::examples::JsonValue::Tag::kStringValue);
  ASSERT_TRUE(str_val.is_string_value());

  fuchsia::examples::JsonValuePtr other_int_val = fuchsia::examples::JsonValue::New();
  other_int_val->set_int_value(5);
  ASSERT_EQ(other_int_val->int_value(), 5);
}

TEST(FidlExamples, Tables) {
  fuchsia::examples::User user;
  ASSERT_FALSE(user.has_age());
  user.set_age(100);
  *user.mutable_age() += 100;
  ASSERT_EQ(user.age(), 200);
  user.clear_age();
  ASSERT_TRUE(user.IsEmpty());
}

Rebuild and rerun the tests by running:

fx test -vo example-cpp-host-test