unplugged-system/build/bazel/rules/cc/cc_proto_test.bzl

450 lines
12 KiB
Python

"""Copyright (C) 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//lib:sets.bzl", "sets")
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
load(":cc_proto.bzl", "PROTO_GEN_NAME_SUFFIX", "cc_proto_library")
PROTO_GEN = "external/protobuf/aprotoc"
VIRTUAL_IMPORT = "_virtual_imports"
RUNFILES = "_middlemen/external_Sprotobuf_Saprotoc-runfiles"
GEN_SUFFIX = [
".pb.h",
".pb.cc",
]
def _get_search_paths(action):
cmd = action.argv
search_paths = sets.make()
cmd_len = len(cmd)
for i in range(cmd_len):
if cmd[i].startswith("-I"):
sets.insert(search_paths, cmd[i].lstrip("- I"))
return search_paths
def _proto_code_gen_test_impl(ctx):
env = analysistest.begin(ctx)
target_under_test = analysistest.target_under_test(env)
actions = analysistest.target_actions(env)
package_root = ctx.label.package
local_file_output_path = paths.join(
package_root,
target_under_test.label.name,
package_root,
)
input_files = [
ctx.attr.local_file_path,
ctx.attr.external_file_path,
ctx.attr.deps_file_path,
]
output_files = [
ctx.attr.local_file_path,
ctx.attr.external_file_path,
]
asserts.true(
env,
len(actions) == 1,
"Proto gen action not found: %s" % actions,
)
action = actions[0]
asserts.set_equals(
env,
expected = sets.make(
[paths.join(package_root, file) for file in input_files] + [
PROTO_GEN,
RUNFILES,
],
),
actual = sets.make([
file.short_path
for file in action.inputs.to_list()
]),
)
asserts.set_equals(
env,
expected = sets.make(
[
paths.join(
local_file_output_path,
paths.replace_extension(file, ext),
)
for ext in GEN_SUFFIX
for file in output_files
],
),
actual = sets.make([
file.short_path
for file in action.outputs.to_list()
]),
)
search_paths = _get_search_paths(action)
asserts.equals(
env,
expected = sets.make(
["."] +
[paths.join(package_root, f) + "=" + paths.join(package_root, f) for f in input_files],
),
actual = search_paths,
)
return analysistest.end(env)
proto_code_gen_test = analysistest.make(
_proto_code_gen_test_impl,
attrs = {
"local_file_path": attr.string(),
"deps_file_path": attr.string(),
"external_file_path": attr.string(),
},
)
def _test_proto_code_gen():
test_name = "proto_code_gen_test"
local_file_path = "local/proto_local.proto"
external_file_path = "external/proto_external.proto"
deps_file_path = "deps/proto_deps.proto"
external_proto_name = test_name + "_external_proto"
deps_proto_name = test_name + "_deps_proto"
local_proto_name = test_name + "_proto"
cc_name = test_name + "_cc_proto"
native.proto_library(
name = external_proto_name,
srcs = [external_file_path],
tags = ["manual"],
)
native.proto_library(
name = deps_proto_name,
srcs = [deps_file_path],
tags = ["manual"],
)
native.proto_library(
name = local_proto_name,
srcs = [local_file_path],
deps = [":" + deps_proto_name],
tags = ["manual"],
)
cc_proto_library(
name = cc_name,
deps = [
":" + local_proto_name,
":" + external_proto_name,
],
tags = ["manual"],
)
proto_code_gen_test(
name = test_name,
target_under_test = cc_name + PROTO_GEN_NAME_SUFFIX,
local_file_path = local_file_path,
deps_file_path = deps_file_path,
external_file_path = external_file_path,
)
return test_name
def _proto_strip_import_prefix_test_impl(ctx):
env = analysistest.begin(ctx)
target_under_test = analysistest.target_under_test(env)
actions = analysistest.target_actions(env)
package_root = ctx.label.package
# strip the proto file path, src/stripped/stripped.proto -> stripped/stripped.proto
stripped_file_name = paths.relativize(ctx.attr.stripped_file_name, ctx.attr.strip_import_prefix)
stripped_file_input_path = paths.join(
package_root,
VIRTUAL_IMPORT,
ctx.attr.stripped_proto_name,
)
stripped_file_input_full_path = paths.join(
stripped_file_input_path,
stripped_file_name,
)
unstripped_file_output_path = paths.join(
package_root,
target_under_test.label.name,
package_root,
)
stripped_file_output_path = paths.join(
unstripped_file_output_path,
VIRTUAL_IMPORT,
ctx.attr.stripped_proto_name,
)
asserts.true(
env,
len(actions) == 1,
"Proto gen action not found: %s" % actions,
)
action = actions[0]
asserts.set_equals(
env,
expected = sets.make(
[
paths.join(package_root, ctx.attr.unstripped_file_name),
stripped_file_input_full_path,
PROTO_GEN,
RUNFILES,
],
),
actual = sets.make([
file.short_path
for file in action.inputs.to_list()
]),
)
asserts.set_equals(
env,
expected = sets.make(
[
paths.join(
unstripped_file_output_path,
paths.replace_extension(ctx.attr.unstripped_file_name, ext),
)
for ext in GEN_SUFFIX
] +
[
paths.join(
stripped_file_output_path,
paths.replace_extension(stripped_file_name, ext),
)
for ext in GEN_SUFFIX
],
),
actual = sets.make([
file.short_path
for file in action.outputs.to_list()
]),
)
search_paths = _get_search_paths(action)
asserts.equals(
env,
expected = sets.make([
".",
paths.join(package_root, ctx.attr.unstripped_file_name) + "=" + paths.join(package_root, ctx.attr.unstripped_file_name),
stripped_file_input_full_path + "=" +
paths.join(
ctx.genfiles_dir.path,
stripped_file_input_full_path,
),
paths.join(
ctx.genfiles_dir.path,
stripped_file_input_path,
),
]),
actual = search_paths,
)
return analysistest.end(env)
proto_strip_import_prefix_test = analysistest.make(
_proto_strip_import_prefix_test_impl,
attrs = {
"stripped_proto_name": attr.string(),
"stripped_file_name": attr.string(),
"unstripped_file_name": attr.string(),
"strip_import_prefix": attr.string(),
},
)
def _test_proto_strip_import_prefix():
test_name = "proto_strip_import_prefix_test"
unstripped_proto_name = test_name + "_unstripped_proto"
stripped_proto_name = test_name + "_stripped_proto"
unstripped_file_name = "unstripped/unstripped.proto"
stripped_file_name = "src/stripped/stripped.proto"
cc_name = test_name + "_cc_proto"
strip_import_prefix = "src"
native.proto_library(
name = unstripped_proto_name,
srcs = [unstripped_file_name],
tags = ["manual"],
)
native.proto_library(
name = stripped_proto_name,
srcs = [stripped_file_name],
strip_import_prefix = strip_import_prefix,
tags = ["manual"],
)
cc_proto_library(
name = cc_name,
deps = [
":" + stripped_proto_name,
":" + unstripped_proto_name,
],
tags = ["manual"],
)
proto_strip_import_prefix_test(
name = test_name,
target_under_test = cc_name + PROTO_GEN_NAME_SUFFIX,
stripped_proto_name = stripped_proto_name,
stripped_file_name = stripped_file_name,
unstripped_file_name = unstripped_file_name,
strip_import_prefix = strip_import_prefix,
)
return test_name
def _proto_with_external_packages_test_impl(ctx):
env = analysistest.begin(ctx)
target_under_test = analysistest.target_under_test(env)
actions = analysistest.target_actions(env)
package_root = ctx.label.package
deps_file_path = ctx.attr.deps_file_path
external_file_path = ctx.attr.external_file_path
local_file_path = ctx.attr.local_file_path
asserts.true(
env,
len(actions) == 1,
"Proto gen action not found: %s" % actions,
)
action = actions[0]
asserts.set_equals(
env,
expected = sets.make(
[
paths.join(package_root, local_file_path),
deps_file_path,
external_file_path,
PROTO_GEN,
RUNFILES,
],
),
actual = sets.make([
file.short_path
for file in action.inputs.to_list()
]),
)
asserts.set_equals(
env,
expected = sets.make(
[
paths.join(
package_root,
target_under_test.label.name,
package_root,
paths.replace_extension(local_file_path, ext),
)
for ext in GEN_SUFFIX
] +
[
paths.join(
package_root,
target_under_test.label.name,
paths.replace_extension(external_file_path, ext),
)
for ext in GEN_SUFFIX
],
),
actual = sets.make([
file.short_path
for file in action.outputs.to_list()
]),
)
search_paths = _get_search_paths(action)
asserts.equals(
env,
expected = sets.make([
".",
paths.join(package_root, local_file_path) + "=" + paths.join(package_root, local_file_path),
deps_file_path + "=" + deps_file_path,
external_file_path + "=" + external_file_path,
]),
actual = search_paths,
)
return analysistest.end(env)
proto_with_external_packages_test = analysistest.make(
_proto_with_external_packages_test_impl,
attrs = {
"local_file_path": attr.string(),
"deps_file_path": attr.string(),
"external_file_path": attr.string(),
},
)
def _test_proto_with_external_packages():
test_name = "proto_with_external_packages_test"
proto_name = test_name + "_proto"
cc_name = test_name + "_cc_proto"
local_file_path = "local/proto_local.proto"
deps_file_path = "build/bazel/examples/cc/proto/deps/src/enums/proto_deps.proto"
external_file_path = "build/bazel/examples/cc/proto/external/src/enums/proto_external.proto"
native.proto_library(
name = proto_name,
srcs = [local_file_path],
deps = ["//build/bazel/examples/cc/proto/deps:deps_proto"],
tags = ["manual"],
)
cc_proto_library(
name = cc_name,
deps = [
":" + proto_name,
"//build/bazel/examples/cc/proto/external:external_proto",
],
tags = ["manual"],
)
proto_with_external_packages_test(
name = test_name,
target_under_test = cc_name + PROTO_GEN_NAME_SUFFIX,
local_file_path = local_file_path,
deps_file_path = deps_file_path,
external_file_path = external_file_path,
)
return test_name
def cc_proto_test_suite(name):
native.test_suite(
name = name,
tests = [
_test_proto_code_gen(),
_test_proto_strip_import_prefix(),
_test_proto_with_external_packages(),
],
)