From 4a0ab9caa8400ca682f1940ae9103641ae4381ba Mon Sep 17 00:00:00 2001 From: Etienne Perot Date: Fri, 3 Jun 2022 17:01:28 -0700 Subject: [PATCH] Export `GVISOR_PLATFORM_SUPPORT` environment variable for tests. This environment variable encodes what capabilities the platform supports, and is consumed by `platform_util.cc` to determine which syscall tests are appropriate to run. PiperOrigin-RevId: 452870567 --- test/runner/BUILD | 1 + test/runner/defs.bzl | 21 +++++++++- test/runner/main.go | 13 ++++++ test/util/platform_util.cc | 75 ++++++++++++++++++++++++++++++----- tools/bazeldefs/platforms.bzl | 24 +++++++++++ tools/defs.bzl | 3 +- 6 files changed, 124 insertions(+), 13 deletions(-) diff --git a/test/runner/BUILD b/test/runner/BUILD index 2d93aa6af..7c6bebd3b 100644 --- a/test/runner/BUILD +++ b/test/runner/BUILD @@ -27,4 +27,5 @@ bzl_library( name = "defs_bzl", srcs = ["defs.bzl"], visibility = ["//visibility:private"], + deps = ["//tools:defs_bzl"], ) diff --git a/test/runner/defs.bzl b/test/runner/defs.bzl index 0061a4ddb..85ecaeea9 100644 --- a/test/runner/defs.bzl +++ b/test/runner/defs.bzl @@ -1,6 +1,15 @@ """Defines a rule for syscall test targets.""" -load("//tools:defs.bzl", "default_platform", "platforms") +load("//tools:defs.bzl", "default_platform", "platform_capabilities", "platforms") + +# Maps platform names to a GVISOR_PLATFORM_SUPPORT environment variable consumed by platform_util.cc +_platform_support_env_vars = { + platform: ",".join(sorted([ + ("%s:%s" % (capability, "TRUE" if supported else "FALSE")) + for capability, supported in support.items() + ])) + for platform, support in platform_capabilities.items() +} def _runner_test_impl(ctx): # Generate a runner binary. @@ -105,9 +114,19 @@ def _syscall_test( container = "container" in tags + if platform == "native": + # The "native" platform supports everything. + platform_support = ",".join(sorted([ + ("%s:TRUE" % key) + for key in platform_capabilities[default_platform].keys() + ])) + else: + platform_support = _platform_support_env_vars.get(platform, "") + runner_args = [ # Arguments are passed directly to runner binary. "--platform=" + platform, + "--platform-support=" + platform_support, "--network=" + network, "--use-tmpfs=" + str(use_tmpfs), "--file-access=" + file_access, diff --git a/test/runner/main.go b/test/runner/main.go index 9c5755bf3..8040dfa79 100644 --- a/test/runner/main.go +++ b/test/runner/main.go @@ -43,6 +43,7 @@ var ( debug = flag.Bool("debug", false, "enable debug logs") strace = flag.Bool("strace", false, "enable strace logs") platform = flag.String("platform", "ptrace", "platform to run on") + platformSupport = flag.String("platform-support", "", "String passed to the test as GVISOR_PLATFORM_SUPPORT environment variable. Used to determine which syscall tests are expected to work with the current platform.") network = flag.String("network", "none", "network stack to run on (sandbox, host, none)") useTmpfs = flag.Bool("use-tmpfs", false, "mounts tmpfs for /tmp") fileAccess = flag.String("file-access", "exclusive", "mounts root in exclusive or shared mode") @@ -58,6 +59,11 @@ var ( leakCheck = flag.Bool("leak-check", false, "check for reference leaks") ) +const ( + // Environment variable used by platform_util.cc to determine platform capabilities. + platformSupportEnvVar = "GVISOR_PLATFORM_SUPPORT" +) + // runTestCaseNative runs the test case directly on the host machine. func runTestCaseNative(testBin string, tc gtest.TestCase, t *testing.T) { // These tests might be running in parallel, so make sure they have a @@ -100,6 +106,10 @@ func runTestCaseNative(testBin string, tc gtest.TestCase, t *testing.T) { env = append(env, "TEST_UDS_ATTACH_TREE="+socketDir) } + if *platformSupport != "" { + env = append(env, fmt.Sprintf("%s=%s", platformSupportEnvVar, *platformSupport)) + } + cmd := exec.Command(testBin, tc.Args()...) cmd.Env = env cmd.Stdout = os.Stdout @@ -399,6 +409,9 @@ func runTestCaseRunsc(testBin string, tc gtest.TestCase, t *testing.T) { lisafsVar = "LISAFS_ENABLED" ) env := append(os.Environ(), platformVar+"="+*platform, networkVar+"="+*network) + if *platformSupport != "" { + env = append(env, fmt.Sprintf("%s=%s", platformSupportEnvVar, *platformSupport)) + } if *fuse { env = append(env, fuseVar+"=TRUE") } else { diff --git a/test/util/platform_util.cc b/test/util/platform_util.cc index c9200d381..a3f7f272c 100644 --- a/test/util/platform_util.cc +++ b/test/util/platform_util.cc @@ -14,34 +14,87 @@ #include "test/util/platform_util.h" +#include + #include "test/util/test_util.h" namespace gvisor { namespace testing { PlatformSupport PlatformSupport32Bit() { - if (GvisorPlatform() == Platform::kPtrace || - GvisorPlatform() == Platform::kKVM) { - return PlatformSupport::NotSupported; - } else { - return PlatformSupport::Allowed; + const char* support = std::getenv("GVISOR_PLATFORM_SUPPORT"); + if (support != nullptr) { + if (std::string(support).find("32BIT:TRUE") != std::string::npos) { + return PlatformSupport::Allowed; + } + if (std::string(support).find("32BIT:FALSE") != std::string::npos) { + return PlatformSupport::NotSupported; + } + std::cerr << "GVISOR_PLATFORM_SUPPORT variable does not contain 32BIT " + "support information: " + << support << std::endl; + TEST_CHECK(false); } + std::cerr << "GVISOR_PLATFORM_SUPPORT variable undefined" << std::endl; + TEST_CHECK(false); } PlatformSupport PlatformSupportAlignmentCheck() { - return PlatformSupport::Allowed; + const char* support = std::getenv("GVISOR_PLATFORM_SUPPORT"); + if (support != nullptr) { + if (std::string(support).find("ALIGNMENT_CHECK:TRUE") != + std::string::npos) { + return PlatformSupport::Allowed; + } + if (std::string(support).find("ALIGNMENT_CHECK:FALSE") != + std::string::npos) { + return PlatformSupport::NotSupported; + } + std::cerr + << "GVISOR_PLATFORM_SUPPORT variable does not contain ALIGNMENT_CHECK " + "support information: " + << support << std::endl; + TEST_CHECK(false); + } + std::cerr << "GVISOR_PLATFORM_SUPPORT variable undefined" << std::endl; + TEST_CHECK(false); } PlatformSupport PlatformSupportMultiProcess() { - return PlatformSupport::Allowed; + const char* support = std::getenv("GVISOR_PLATFORM_SUPPORT"); + if (support != nullptr) { + if (std::string(support).find("MULTIPROCESS:TRUE") != std::string::npos) { + return PlatformSupport::Allowed; + } + if (std::string(support).find("MULTIPROCESS:FALSE") != std::string::npos) { + return PlatformSupport::NotSupported; + } + std::cerr + << "GVISOR_PLATFORM_SUPPORT variable does not contain MULTIPROCESS " + "support information: " + << support << std::endl; + TEST_CHECK(false); + } + std::cerr << "GVISOR_PLATFORM_SUPPORT variable undefined" << std::endl; + TEST_CHECK(false); } PlatformSupport PlatformSupportInt3() { - if (GvisorPlatform() == Platform::kKVM) { - return PlatformSupport::NotSupported; - } else { - return PlatformSupport::Allowed; + const char* support = std::getenv("GVISOR_PLATFORM_SUPPORT"); + if (support != nullptr) { + if (std::string(support).find("INT3:TRUE") != std::string::npos) { + return PlatformSupport::Allowed; + } + if (std::string(support).find("INT3:FALSE") != std::string::npos) { + return PlatformSupport::NotSupported; + } + std::cerr << "GVISOR_PLATFORM_SUPPORT variable does not contain INT3 " + "support information: " + << support << std::endl; + TEST_CHECK(false); } + std::cerr << "GVISOR_PLATFORM_SUPPORT variable undefined" << std::endl; + TEST_CHECK(false); } } // namespace testing diff --git a/tools/bazeldefs/platforms.bzl b/tools/bazeldefs/platforms.bzl index 165b22311..2fcad3091 100644 --- a/tools/bazeldefs/platforms.bzl +++ b/tools/bazeldefs/platforms.bzl @@ -6,4 +6,28 @@ platforms = { "kvm": [], } +# Capabilities that platforms may or may not support. +# Used by platform_util.cc to determine which syscall tests are appropriate. +_CAPABILITY_32BIT = "32BIT" +_CAPABILITY_ALIGNMENT_CHECK = "ALIGNMENT_CHECK" +_CAPABILITY_MULTIPROCESS = "MULTIPROCESS" +_CAPABILITY_INT3 = "INT3" + +# platform_capabilities maps platform names to a dictionary of capabilities mapped to +# True (supported) or False (unsupported). +platform_capabilities = { + "ptrace": { + _CAPABILITY_32BIT: False, + _CAPABILITY_ALIGNMENT_CHECK: True, + _CAPABILITY_MULTIPROCESS: True, + _CAPABILITY_INT3: True, + }, + "kvm": { + _CAPABILITY_32BIT: False, + _CAPABILITY_ALIGNMENT_CHECK: True, + _CAPABILITY_MULTIPROCESS: True, + _CAPABILITY_INT3: False, + }, +} + default_platform = "ptrace" diff --git a/tools/defs.bzl b/tools/defs.bzl index cee8583a8..ccc1d2990 100644 --- a/tools/defs.bzl +++ b/tools/defs.bzl @@ -12,7 +12,7 @@ load("//tools/bazeldefs:defs.bzl", _BuildSettingInfo = "BuildSettingInfo", _amd6 load("//tools/bazeldefs:cc.bzl", _cc_binary = "cc_binary", _cc_flags_supplier = "cc_flags_supplier", _cc_grpc_library = "cc_grpc_library", _cc_library = "cc_library", _cc_proto_library = "cc_proto_library", _cc_test = "cc_test", _cc_toolchain = "cc_toolchain", _gbenchmark = "gbenchmark", _gbenchmark_internal = "gbenchmark_internal", _grpcpp = "grpcpp", _gtest = "gtest", _vdso_linker_option = "vdso_linker_option") load("//tools/bazeldefs:go.bzl", _gazelle = "gazelle", _go_binary = "go_binary", _go_embed_data = "go_embed_data", _go_grpc_and_proto_libraries = "go_grpc_and_proto_libraries", _go_library = "go_library", _go_path = "go_path", _go_proto_library = "go_proto_library", _go_rule = "go_rule", _go_test = "go_test", _gotsan_flag_values = "gotsan_flag_values", _gotsan_values = "gotsan_values", _select_goarch = "select_goarch", _select_goos = "select_goos") load("//tools/bazeldefs:pkg.bzl", _pkg_deb = "pkg_deb", _pkg_tar = "pkg_tar") -load("//tools/bazeldefs:platforms.bzl", _default_platform = "default_platform", _platforms = "platforms") +load("//tools/bazeldefs:platforms.bzl", _default_platform = "default_platform", _platform_capabilities = "platform_capabilities", _platforms = "platforms") load("//tools/bazeldefs:tags.bzl", "go_suffixes") # Core rules. @@ -59,6 +59,7 @@ pkg_tar = _pkg_tar # Platform options. default_platform = _default_platform platforms = _platforms +platform_capabilities = _platform_capabilities def _go_add_tags(ctx): """ Adds tags to the given source file. """