| # Copyright 2022 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/fidl/fidl.gni") |
| import("//build/go/go_binary.gni") |
| import("//build/go/go_library.gni") |
| import("//build/rust/rustc_binary.gni") |
| import("//build/toolchain/ifs_shared_library.gni") |
| import("//tools/fidl/lib/fidlgentest/fidlgentest_go_test.gni") |
| import("zither_golden_files.gni") |
| import("zither_library.gni") |
| |
| group("tests") { |
| testonly = true |
| |
| deps = [ |
| # basic unit tests |
| ":unittests($host_toolchain)", |
| |
| # golden testing |
| ":aliases", |
| ":bits", |
| ":constants", |
| ":enums", |
| ":experimental_zx_types", |
| ":multifile", |
| ":output_namespace_override", |
| ":resources", |
| ":structs", |
| ":zx.test", |
| ] |
| } |
| |
| if (is_host) { |
| go_binary("zither") { |
| library = ":main" |
| } |
| |
| go_library("main") { |
| visibility = [ ":*" ] |
| source_dir = "cmd" |
| sources = [ "main.go" ] |
| deps = [ |
| ":common", |
| "backends/asm", |
| "backends/c", |
| "backends/go_runtime", |
| "backends/golang", |
| "backends/kernel", |
| "backends/legacy_syscall_cdecl", |
| "backends/rust", |
| "backends/rust_syscall", |
| "backends/syscall_docs", |
| "backends/zircon_ifs", |
| "//tools/fidl/lib/fidlgen", |
| "//tools/lib/color", |
| "//tools/lib/flagmisc", |
| "//tools/lib/logger", |
| ] |
| } |
| |
| go_library("common") { |
| visibility = [ "./*" ] |
| deps = [ |
| "//tools/fidl/lib/fidlgen", |
| "//tools/fidl/lib/fidlgen_cpp", |
| ] |
| sources = [ |
| "c_family.go", |
| "names.go", |
| "readme.go", |
| "zither_ir.go", |
| "zither_ir_test.go", |
| ] |
| } |
| |
| fidlgentest_go_test("unittests") { |
| library = ":common" |
| output_name = "zither-unittests" |
| deps = [ |
| "//third_party/golibs:github.com/google/go-cmp", |
| "//tools/fidl/lib/fidlgen", |
| "//tools/fidl/lib/fidlgentest", |
| ] |
| } |
| } |
| |
| # |
| # Build-time golden tests |
| # |
| |
| # zither_golden_test() defines a suite of build-time golden tests for zither |
| # backends: a FIDL library and its expected bindings are supplied, and the diff |
| # checks are made as build actions. Further, a check is made that the bindings |
| # give valid, compilable code. |
| # |
| # `target_name` is assumed to be the associated test case name, as is formally |
| # defined by the subdirectory names in testdata/ (see testdata/README.md). |
| # This template further assumes the following properties of the directory's |
| # organizational structure: |
| # * FIDL sources are found in testdata/${case_name}/, at the root of the |
| # 'case data directory'; |
| # * Goldens, for a given backend, are found in |
| # testdata/${case_name}/goldens/${backend}, the 'backend's case golden |
| # directory' |
| # |
| # Parameters: |
| # |
| # * sources |
| # - Required: FIDL files comprising a single library, from which bindings |
| # will be generated, relative to the case FIDL directory. The name of this |
| # library is assumed to be `"zither." + string_replace(case_name, "_", ".")`. |
| # We derive the FIDL library name with character replacement since |
| # underscores are not a permitted as library name characters and a period |
| # is the defined separator. One exception to this is "zx.test": if that is |
| # the target name, then the library is expected to be called "zx", which |
| # permits the testing of things that FIDL currently requires to be defined |
| # in a library of that name. |
| # - Type: list(relative path) |
| # |
| # * experimental_flags |
| # - Optional: See fidl(). |
| # - Type: list(string) |
| # |
| # * backend_parameters |
| # - Optional: |
| # - Type: scope |
| # |
| # * cases |
| # - Required: A list of test cases. |
| # - Type: list(scope) |
| # |
| # Each scope contains: |
| # * backend: |
| # - Required: The backend with which to generate bindings. Must be one |
| # of `zither_supported_backends` (see zither_library.gni). |
| # - Type: string |
| # * files |
| # - Required: The list of names for the files to be generated by the |
| # backend. This list should be in one-to-one correspondence with the |
| # the goldens found in the backend's case golden directory - or "*" in |
| # the case of backends with dynamic outputs. |
| # - Type: list(string) or "*" |
| # |
| template("zither_golden_test") { |
| assert(defined(invoker.sources), "no sources given") |
| assert(defined(invoker.cases) && invoker.cases != [], "no test cases defined") |
| |
| main_target = target_name |
| if (target_name == "zx.test") { |
| library_target = "zx" |
| } else { |
| library_target = "zither." + string_replace(target_name, "_", ".") |
| } |
| |
| case_name = target_name |
| case_data_dir = "testdata/${case_name}" |
| |
| extra_backend_parameters = { |
| if (defined(invoker.backend_parameters)) { |
| forward_variables_from(invoker.backend_parameters, "*") |
| } |
| } |
| |
| fidl(library_target) { |
| forward_variables_from(invoker, [ "experimental_flags" ]) |
| sources = [] |
| foreach(source, invoker.sources) { |
| sources += [ "${case_data_dir}/$source" ] |
| } |
| enable_zither = true |
| |
| zither = extra_backend_parameters |
| } |
| |
| all_cases = [] |
| foreach(case, invoker.cases) { |
| if (case.backend == "go" && current_cpu == "riscv64") { |
| # Go builds are not supported for RISC-V. |
| case = false |
| } |
| if (case != false && !support_rust && |
| (case.backend == "rust" || case.backend == "rust_syscall")) { |
| # Skip Rust cases. |
| case = false |
| } |
| if (case != false) { |
| all_cases += [ case ] |
| } |
| } |
| |
| case_deps = [] |
| foreach(case, all_cases) { |
| assert(defined(case.backend), "`${case}` must provide `backend`") |
| assert(defined(case.files) && case.files != [], |
| "`${case}` must provide `files`") |
| |
| backend_label = ":${library_target}_zither.${case.backend}" |
| |
| goldens_target = |
| "_zither_golden_test.${target_name}-${case.backend}.zither_golden_files" |
| compilation_check_target = |
| "_zither_golden_test.${target_name}-${case.backend}.compilation_check" |
| |
| zither_golden_files(goldens_target) { |
| fidl = ":$library_target" |
| backend = case.backend |
| |
| _golden_dir = "${case_data_dir}/goldens/${case.backend}" |
| if (case.files == "*") { |
| source_dir = _golden_dir |
| } else { |
| sources = [] |
| foreach(file, case.files) { |
| sources += [ "${_golden_dir}/${file}" ] |
| } |
| } |
| } |
| case_deps += [ ":$goldens_target" ] |
| |
| # Clear from previous iteration. |
| backend_info = { |
| } |
| backend_params = { |
| } |
| output_namespace_info = { |
| } |
| |
| backend_info = supported_zither_backend_info[case.backend] |
| |
| # Reconstruct the output subdirectory per `zither_library()` documentation, |
| # taking any explicit override into account. |
| backend_params = { |
| if (defined(extra_backend_parameters[case.backend])) { |
| forward_variables_from(extra_backend_parameters[case.backend], "*") |
| } |
| } |
| if (defined(backend_params.output_namespace)) { |
| output_namespace = backend_params.output_namespace |
| } else { |
| output_namespace_info = { |
| prefix_parts = [] |
| suffix_parts = [] |
| part_separator = "/" |
| forward_variables_from(backend_info.output_namespace, "*") |
| parts = prefix_parts |
| if (defined(library_name_separator)) { |
| parts += |
| [ string_replace(library_target, ".", library_name_separator) ] |
| } |
| parts += suffix_parts |
| path = string_join(part_separator, parts) |
| } |
| if (output_namespace_info.path != "") { |
| output_namespace = output_namespace_info.path |
| } |
| } |
| |
| # A per (backend, case) output directory for use below, if needed. |
| # Not related to the zither output directory. |
| case_output_dir = "$target_gen_dir/${target_name}-${case.backend}" |
| |
| # Now verify that the bindings give valid code. |
| if (case.backend == "c" || case.backend == "asm") { |
| create_source_target = "${compilation_check_target}.create_source" |
| |
| if (case.backend == "c") { |
| suffix = "c" |
| } else if (case.backend == "asm") { |
| suffix = "S" |
| } else { |
| suffix = "cc" |
| } |
| source = "$case_output_dir/compile-check.$suffix" |
| action(create_source_target) { |
| visibility = [ ":*" ] |
| testonly = true |
| script = "scripts/create-file-with-includes.py" |
| args = [ |
| "--comment", |
| "Generated by //" + rebase_path(script, "//"), |
| "--output", |
| rebase_path(source, root_build_dir), |
| ] |
| foreach(file, case.files) { |
| if (get_path_info(file, "extension") != "md") { |
| args += [ "${output_namespace}/${file}" ] |
| } |
| } |
| outputs = [ source ] |
| } |
| |
| # loadable_module() over source_set() to pass `-z defs` muster. |
| loadable_module(compilation_check_target) { |
| visibility = [ ":*" ] |
| testonly = true |
| sources = [ source ] |
| deps = [ |
| ":$create_source_target", |
| backend_label, |
| ] |
| } |
| } else if (case.backend == "go") { |
| # We create a simple main file that imports the generated package, which |
| # will feed into our compilation check. There is unfortunately no real |
| # equivalent of `source_set()` in our go build. |
| create_main_target = "${compilation_check_target}.create_main" |
| main_file = "$case_output_dir/main.go" |
| generated_file(create_main_target) { |
| visibility = [ ":*" ] |
| testonly = true |
| |
| contents = [ |
| "package main", |
| "", |
| "import (", |
| " _ \"${output_namespace}\"", # `_` to avoid usage complaints |
| " _ \"syscall/zx\"", # Required by fuchsia support quirks. |
| ")", |
| "", |
| "func main() {}", |
| "", |
| ] |
| outputs = [ main_file ] |
| } |
| |
| # The generated main file now needs to be declared in a package/library. |
| main_library_target = "${compilation_check_target}.main_library" |
| main_pkg_name = rebase_path(case_output_dir, root_build_dir) |
| go_library(main_library_target) { |
| visibility = [ ":*" ] |
| testonly = true |
| |
| name = main_pkg_name |
| source_dir = case_output_dir |
| sources = [ rebase_path(main_file, source_dir) ] |
| deps = [ backend_label ] |
| non_go_deps = [ ":$create_main_target" ] |
| } |
| |
| go_binary(compilation_check_target) { |
| library = ":$main_library_target" |
| visibility = [ ":*" ] |
| testonly = true |
| } |
| } else if (case.backend == "zircon_ifs") { |
| if (current_toolchain == default_toolchain) { |
| backend_outputs = get_target_outputs("${backend_label}.gen") |
| ifs = "" |
| foreach(output, backend_outputs) { |
| if (get_path_info(output, "extension") == "ifs") { |
| ifs = output |
| } |
| } |
| ifs_shared_library(compilation_check_target) { |
| abi = ifs |
| deps = [ backend_label ] |
| } |
| } else { |
| group(compilation_check_target) { |
| testonly = true |
| deps = [ ":$compilation_check_target($default_toolchain)" ] |
| } |
| } |
| not_needed([ |
| "backend_label", |
| "case_output_dir", |
| "output_namespace", |
| ]) |
| } else if (case.backend == "rust" || case.backend == "kernel" || |
| case.backend == "legacy_syscall_cdecl" || |
| case.backend == "rust_syscall" || case.backend == "go_runtime" || |
| case.backend == "syscall_docs") { |
| # The generated rust library targets should already enforce compilation. |
| # |
| # The kernel and syscall-related backends generate sources that rely on a |
| # number of other kernel and vDSO-specific definitions. Given that and |
| # the fact the singular use-case for these sources will be exercised in |
| # any default build invocation, it is neither worthwhile nor all that |
| # practical to do a compilation check here. |
| group(compilation_check_target) { |
| visibility = [ ":*" ] |
| testonly = true |
| deps = [ backend_label ] |
| } |
| not_needed([ |
| "case_output_dir", |
| "output_namespace", |
| ]) |
| } |
| |
| case_deps += [ ":$compilation_check_target" ] |
| } |
| |
| group(main_target) { |
| testonly = true |
| visibility = [ ":*" ] |
| deps = case_deps |
| } |
| } |
| |
| # FIDL: testdata/constants/ |
| # Goldens: testdata/constants/goldens/${backend}/ |
| zither_golden_test("constants") { |
| sources = [ "constants.test.fidl" ] |
| |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "constants.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "asm" |
| files = [ "constants.h" ] |
| }, |
| { |
| backend = "go" |
| files = [ |
| "constants.go", |
| "pkg_name.txt", |
| ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "constants.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/enums/ |
| # Goldens: testdata/enums/goldens/${backend}/ |
| zither_golden_test("enums") { |
| sources = [ "enums.test.fidl" ] |
| |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "enums.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "asm" |
| files = [ "enums.h" ] |
| }, |
| { |
| backend = "go" |
| files = [ |
| "enums.go", |
| "pkg_name.txt", |
| ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "enums.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/bits/ |
| # Goldens: testdata/bits/goldens/${backend}/ |
| zither_golden_test("bits") { |
| sources = [ "bits.test.fidl" ] |
| |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "bits.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "asm" |
| files = [ "bits.h" ] |
| }, |
| { |
| backend = "go" |
| files = [ |
| "bits.go", |
| "pkg_name.txt", |
| ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "bits.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/structs/ |
| # Goldens: testdata/structs/goldens/${backend}/ |
| zither_golden_test("structs") { |
| sources = [ "structs.test.fidl" ] |
| |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "structs.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "asm" |
| files = [ "structs.h" ] |
| }, |
| { |
| backend = "go" |
| files = [ |
| "pkg_name.txt", |
| "structs.go", |
| ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "structs.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/multifile/ |
| # Goldens: testdata/multifile/goldens/${backend}/ |
| zither_golden_test("multifile") { |
| sources = [ |
| "a.test.fidl", |
| "b.test.fidl", |
| "c.test.fidl", |
| ] |
| |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "a.h", |
| "b.h", |
| "c.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "asm" |
| files = [ |
| "a.h", |
| "b.h", |
| "c.h", |
| ] |
| }, |
| { |
| backend = "go" |
| files = [ |
| "a.go", |
| "b.go", |
| "c.go", |
| "pkg_name.txt", |
| ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "a.rs", |
| "b.rs", |
| "c.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/output_namespace_override/ |
| # Goldens: testdata/constants/goldens/${backend}/ |
| zither_golden_test("output_namespace_override") { |
| sources = [ "output_namespace_override.test.fidl" ] |
| |
| backend_parameters = { |
| c = { |
| output_namespace = "my/custom/c/header/guard" |
| } |
| asm = { |
| output_namespace = "my/custom/asm/header/guard" |
| } |
| } |
| |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "output_namespace_override.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "asm" |
| files = [ "output_namespace_override.h" ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/aliases/ |
| # Goldens: testdata/aliases/goldens/${backend}/ |
| zither_golden_test("aliases") { |
| sources = [ "aliases.test.fidl" ] |
| |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "aliases.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "go" |
| files = [ |
| "aliases.go", |
| "pkg_name.txt", |
| ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "aliases.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/zx/ |
| # Goldens: testdata/zx/goldens/${backend}/ |
| zither_golden_test("zx.test") { |
| experimental_flags = [ "zx_c_types" ] |
| sources = [ "zx.test.fidl" ] |
| |
| cases = [ |
| { |
| backend = "zircon_ifs" |
| files = [ "zircon.ifs" ] |
| }, |
| { |
| backend = "kernel" |
| files = [ |
| "category.inc", |
| "kernel.inc", |
| "kernel-wrappers.inc", |
| "syscalls.inc", |
| "zx-syscall-numbers.h", |
| ] |
| }, |
| { |
| backend = "legacy_syscall_cdecl" |
| files = [ |
| "cdecls.inc", |
| "testonly-cdecls.inc", |
| "cdecls-next.inc", |
| ] |
| }, |
| { |
| backend = "rust_syscall" |
| files = [ "definitions.rs" ] |
| }, |
| { |
| backend = "go_runtime" |
| files = [ |
| "syscalls_fuchsia.go", |
| "syscalls_fuchsia_amd64.s", |
| "syscalls_fuchsia_arm64.s", |
| "vdso_keys_fuchsia.go", |
| "vdsocalls_fuchsia_amd64.s", |
| "vdsocalls_fuchsia_arm64.s", |
| ] |
| }, |
| { |
| backend = "syscall_docs" |
| files = "*" |
| }, |
| ] |
| } |
| |
| # TODO(https://fxbug.dev/42061412): These tests reference some experimental built-in |
| # types introduced in the context of this bug. |
| zither_golden_test("experimental_zx_types") { |
| experimental_flags = [ "zx_c_types" ] |
| |
| sources = [ "experimental_zx_types.test.fidl" ] |
| |
| cases = [ |
| { |
| backend = "asm" |
| files = [ "experimental_zx_types.h" ] |
| }, |
| { |
| backend = "c" |
| files = [ |
| "experimental_zx_types.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "go" |
| files = [ "experimental_zx_types.go" ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "experimental_zx_types.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |
| |
| # FIDL: testdata/resources/ |
| # Goldens: testdata/resources/goldens/${backend}/ |
| zither_golden_test("resources") { |
| sources = [ "resources.test.fidl" ] |
| cases = [ |
| { |
| backend = "c" |
| files = [ |
| "resources.h", |
| "README.md", |
| ] |
| }, |
| { |
| backend = "go" |
| files = [ "resources.go" ] |
| }, |
| { |
| backend = "rust" |
| files = [ |
| "resources.rs", |
| "lib.rs", |
| ] |
| }, |
| ] |
| } |