[experiments] Allow experiments to opt-in to testing against all pollers (default to not) (#35683)

Closes #35683

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/35683 from ctiller:minimize2 ac22512f99
PiperOrigin-RevId: 601886350
pull/35678/head
Craig Tiller 10 months ago committed by Copybara-Service
parent 4f45565c82
commit 2bb10be729
  1. 6
      bazel/experiments.bzl
  2. 55
      bazel/grpc_build_system.bzl
  3. 3
      bazel/test_experiments.bzl
  4. 6
      src/core/lib/experiments/experiments.yaml
  5. 15
      tools/codegen/core/experiments_compiler.py

@ -58,6 +58,12 @@ EXPERIMENT_ENABLES = {
"wrr_delegate_to_pick_first": "wrr_delegate_to_pick_first",
}
EXPERIMENT_POLLERS = [
"event_engine_client",
"event_engine_dns",
"event_engine_listener",
]
EXPERIMENTS = {
"windows": {
"dbg": {

@ -29,8 +29,8 @@ Contains macros used throughout the repo.
load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
load("//bazel:copts.bzl", "GRPC_DEFAULT_COPTS")
load("//bazel:experiments.bzl", "EXPERIMENTS", "EXPERIMENT_ENABLES")
load("//bazel:test_experiments.bzl", "TEST_EXPERIMENTS", "TEST_EXPERIMENT_ENABLES")
load("//bazel:experiments.bzl", "EXPERIMENTS", "EXPERIMENT_ENABLES", "EXPERIMENT_POLLERS")
load("//bazel:test_experiments.bzl", "TEST_EXPERIMENTS", "TEST_EXPERIMENT_ENABLES", "TEST_EXPERIMENT_POLLERS")
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load("@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl", "ios_test_runner")
load("@com_google_protobuf//bazel:upb_proto_library.bzl", "upb_proto_library", "upb_proto_reflection_library")
@ -279,8 +279,10 @@ def ios_cc_test(
deps = ios_test_deps,
)
def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, uses_event_engine, flaky):
"""Common logic used to parameterize tests for every poller and EventEngine and experiment.
def expand_poller_config(name, srcs, deps, tags, args, exclude_pollers, uses_polling, uses_event_engine, flaky):
"""Common logic used to parameterize tests for every poller and EventEngine.
Used by expand_tests (repeatedly) to form base lists of pollers for each experiment.
Args:
name: base name of the test
@ -297,6 +299,7 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
Returns:
A list of dictionaries containing modified values of name, srcs, deps, tags, and args.
"""
poller_config = []
# See work_stealing_thread_pool.cc for details.
@ -373,6 +376,27 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
"flaky": flaky,
})
return poller_config
def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, uses_event_engine, flaky):
"""Common logic used to parameterize tests for every poller and EventEngine and experiment.
Args:
name: base name of the test
srcs: source files
deps: base deps
tags: base tags
args: base args
flaky: base flaky
exclude_pollers: list of poller names to exclude for this set of tests.
uses_polling: set to False if the test is not sensitive to polling methodology.
uses_event_engine: set to False if the test is not sensitive to
EventEngine implementation differences
Returns:
A list of dictionaries containing modified values of name, srcs, deps, tags, and args.
"""
experiments = {}
# buildifier: disable=uninitialized
@ -421,13 +445,28 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
tags.append("no_test_ios")
return tags
experiment_config = list(poller_config)
base_params = {
"name": name,
"srcs": srcs,
"deps": deps,
"tags": tags,
"args": args,
"exclude_pollers": exclude_pollers,
"uses_polling": uses_polling,
"uses_event_engine": uses_event_engine,
"flaky": flaky,
}
experiment_config = expand_poller_config(**base_params)
experiment_enables = {k: v for k, v in EXPERIMENT_ENABLES.items() + TEST_EXPERIMENT_ENABLES.items()}
experiment_pollers = EXPERIMENT_POLLERS + TEST_EXPERIMENT_POLLERS
for mode, config in mode_config.items():
enabled_tags, disabled_tags = config
if enabled_tags != None:
for experiment in experiments[mode].keys():
for config in poller_config:
experiment_params = dict(base_params)
experiment_params["uses_polling"] = uses_polling and (experiment in experiment_pollers)
for config in expand_poller_config(**experiment_params):
config = dict(config)
config["name"] = config["name"] + "@experiment=" + experiment
env = dict(config["env"])
@ -443,7 +482,9 @@ def expand_tests(name, srcs, deps, tags, args, exclude_pollers, uses_polling, us
experiment_config.append(config)
if disabled_tags != None:
for experiment in experiments[mode].keys():
for config in poller_config:
experiment_params = dict(base_params)
experiment_params["uses_polling"] = uses_polling and (experiment in experiment_pollers)
for config in expand_poller_config(**experiment_params):
config = dict(config)
config["name"] = config["name"] + "@experiment=no_" + experiment
env = dict(config["env"])

@ -23,6 +23,9 @@ TEST_EXPERIMENT_ENABLES = {
"test_experiment_4": "test_experiment_4",
}
TEST_EXPERIMENT_POLLERS = [
]
TEST_EXPERIMENTS = {
"windows": {
"dbg": {

@ -26,6 +26,9 @@
# Defaults to the empty list.
# If any of the experiments in the required list is determined to
# be disabled at runtime, this experiment is disabled at runtime.
# uses_polling: optional boolean (false if not specified) that indicates that
# this experiment should be tested with all different polling
# engines.
#
# Well known test tags:
# core_end2end_test: all tests, fixtures in the core end2end suite
@ -68,6 +71,7 @@
expiry: 2024/04/01
owner: hork@google.com
test_tags: ["core_end2end_test", "event_engine_client_test"]
uses_polling: true
- name: event_engine_dns
description:
If set, use EventEngine DNSResolver for client channel resolution
@ -75,11 +79,13 @@
owner: yijiem@google.com
test_tags: ["cancel_ares_query_test", "resolver_component_tests_runner_invoker"]
allow_in_fuzzing_config: false
uses_polling: true
- name: event_engine_listener
description: Use EventEngine listeners instead of iomgr's grpc_tcp_server
expiry: 2024/04/01
owner: vigneshbabu@google.com
test_tags: ["core_end2end_test", "event_engine_listener_test"]
uses_polling: true
- name: free_large_allocator
description: If set, return all free bytes from a "big" allocator
expiry: 2024/04/01

@ -192,6 +192,7 @@ class ExperimentDefinition(object):
print("Failed to create experiment definition")
return
self._allow_in_fuzzing_config = True
self._uses_polling = False
self._name = attributes["name"]
self._description = attributes["description"]
self._expiry = attributes["expiry"]
@ -200,6 +201,9 @@ class ExperimentDefinition(object):
self._test_tags = []
self._requires = set()
if "uses_polling" in attributes:
self._uses_polling = attributes["uses_polling"]
if "allow_in_fuzzing_config" in attributes:
self._allow_in_fuzzing_config = attributes[
"allow_in_fuzzing_config"
@ -683,6 +687,17 @@ class ExperimentsCompiler(object):
)
print("}", file=B)
# Generate a list of experiments that use polling.
print(file=B)
if mode == "test":
print("TEST_EXPERIMENT_POLLERS = [", file=B)
else:
print("EXPERIMENT_POLLERS = [", file=B)
for name, exp in self._experiment_definitions.items():
if exp._uses_polling:
print(f' "{name}",', file=B)
print("]", file=B)
print(file=B)
if mode == "test":
print("TEST_EXPERIMENTS = {", file=B)

Loading…
Cancel
Save