diff --git a/manifests/cpp.yml b/manifests/cpp.yml index 9b5972ee348..2d5f4f953e2 100644 --- a/manifests/cpp.yml +++ b/manifests/cpp.yml @@ -65,6 +65,8 @@ manifest: tests/parametric/otel_env_vars/test_otel_exporter_otlp_logs_endpoint.py::Test_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: missing_feature tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: missing_feature tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: missing_feature tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: missing_feature tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: missing_feature tests/parametric/otel_env_vars/test_otel_resource_attributes.py::Test_OTEL_RESOURCE_ATTRIBUTES: missing_feature diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index fcfa71d8418..c49e3db2bb0 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -942,6 +942,16 @@ manifest: ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT::test_empty_falls_back_to_global_endpoint : bug (APMAPI-2509) tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: v3.41.0 + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: v3.41.0 + ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS::test_empty_is_treated_as_unset + : bug (APMAPI-2479) + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: v3.41.0 + ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL::test_empty_is_treated_as_unset + : bug (APMAPI-2531) + ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL::test_grpc_protocol_is_used_for_trace_export + : missing_feature (Trace exporter does not support gRPC) + ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL::test_unset_uses_specification_default + : bug (APMAPI-2531) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: v3.37.0 tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_console: missing_feature (Only otlp and none exporters are implemented) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_deprecated_values: missing_feature (Only otlp and none exporters are implemented) diff --git a/manifests/golang.yml b/manifests/golang.yml index 9334e2d4ba7..804fe7d2d4b 100644 --- a/manifests/golang.yml +++ b/manifests/golang.yml @@ -1964,6 +1964,8 @@ manifest: tests/parametric/otel_env_vars/test_otel_exporter_otlp_logs_endpoint.py::Test_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: v2.7.0 tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: v2.6.0 tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: v2.8.0 + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: missing_feature tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: missing_feature (OTEL_LOGS_EXPORTER does not configure the logs pipeline) tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v2.5.0 tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_invalid_values: bug (APMAPI-2460) diff --git a/manifests/java.yml b/manifests/java.yml index 86b608c1189..1511f4e8f16 100644 --- a/manifests/java.yml +++ b/manifests/java.yml @@ -3963,6 +3963,12 @@ manifest: tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: v1.61.0 ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT::test_empty_falls_back_to_global_endpoint : bug (APMAPI-2412) + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: v1.61.0 + ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS::test_empty_is_treated_as_unset + : bug (APMAPI-2474) + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: v1.61.0 + ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL::test_grpc_protocol_is_used_for_trace_export + : incomplete_test_app (gRPC trace requests are not captured by the HTTP request assertion) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: v1.54.0 tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_console: missing_feature (Only otlp and none exporters are implemented) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_deprecated_values: missing_feature (Only otlp and none exporters are implemented) diff --git a/manifests/nodejs.yml b/manifests/nodejs.yml index 101d6548197..c32c1d984b5 100644 --- a/manifests/nodejs.yml +++ b/manifests/nodejs.yml @@ -2300,6 +2300,8 @@ manifest: ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT::test_otlp_metrics_custom_endpoint_grpc : missing_feature (Does not support grpc) tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: v6.0.0 + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: missing_feature tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: missing_feature (OTEL_LOGS_EXPORTER does not configure the logs pipeline) tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT: v5.83.0 tests/parametric/otel_env_vars/test_otel_metric_export_timeout.py::Test_OTEL_METRIC_EXPORT_TIMEOUT::test_invalid_values: bug (APMAPI-2463) diff --git a/manifests/php.yml b/manifests/php.yml index 049e49fb250..6e4b66179b8 100644 --- a/manifests/php.yml +++ b/manifests/php.yml @@ -1398,6 +1398,8 @@ manifest: ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT::test_otlp_metrics_custom_endpoint_grpc : missing_feature (Does not support grpc) tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: missing_feature tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: v1.23.0 tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_deprecated_values: missing_feature (Deprecated logging exporter is not implemented) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_invalid: bug (APMAPI-2507) diff --git a/manifests/python.yml b/manifests/python.yml index d95faa6e538..219ed23b4ef 100644 --- a/manifests/python.yml +++ b/manifests/python.yml @@ -1952,6 +1952,10 @@ manifest: ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT::test_empty_falls_back_to_global_endpoint : bug (APMAPI-2414) tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: v4.11.0 + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: v4.11.0 + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: v4.11.0 + ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL::test_grpc_protocol_is_used_for_trace_export + : missing_feature (Trace exporter does not support gRPC) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: # TODO: a lower version might be supported - declaration: missing_feature (OTEL_LOGS_EXPORTER does not configure the logs pipeline) component_version: <4.15.2 diff --git a/manifests/ruby.yml b/manifests/ruby.yml index 3c60f8a234c..bad6fbad9aa 100644 --- a/manifests/ruby.yml +++ b/manifests/ruby.yml @@ -2339,6 +2339,8 @@ manifest: ? tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT::test_otlp_metrics_custom_endpoint_grpc : missing_feature (Does not support grpc) tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: missing_feature tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: v2.34.0 tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_console: missing_feature (Only otlp and none exporters are implemented) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_deprecated_values: missing_feature (Only otlp and none exporters are implemented) diff --git a/manifests/rust.yml b/manifests/rust.yml index fb2806fba96..7c6100555f9 100644 --- a/manifests/rust.yml +++ b/manifests/rust.yml @@ -85,6 +85,8 @@ manifest: tests/parametric/otel_env_vars/test_otel_exporter_otlp_logs_endpoint.py::Test_OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: v0.3.0 tests/parametric/otel_env_vars/test_otel_exporter_otlp_metrics_endpoint.py::Test_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: v0.3.0 tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_endpoint.py::Test_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py::Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: missing_feature + tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py::Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: missing_feature tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER: v0.3.0 tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_console: missing_feature (Only otlp and none exporters are implemented) tests/parametric/otel_env_vars/test_otel_logs_exporter.py::Test_OTEL_LOGS_EXPORTER::test_deprecated_values: missing_feature (Only otlp and none exporters are implemented) diff --git a/tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py b/tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py new file mode 100644 index 00000000000..dc99d58ea42 --- /dev/null +++ b/tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_headers.py @@ -0,0 +1,96 @@ +from tests.parametric.conftest import APMLibrary +from utils import features, pytest, scenarios +from utils.docker_fixtures import TestAgentAPI +from utils.docker_fixtures._test_agent import AgentRequest + + +VARIABLE = "OTEL_EXPORTER_OTLP_TRACES_HEADERS" + +BASE_ENVIRONMENT = { + "DD_TRACE_AGENT_PROTOCOL_VERSION": None, + "DD_TRACE_ENABLED": None, + "DD_TRACE_OTEL_ENABLED": "true", + "OTEL_EXPORTER_OTLP_HEADERS": "dd-protocol=otlp,dd-otlp-path=agent", + "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": "http/protobuf", + "OTEL_TRACES_EXPORTER": "otlp", +} + + +@pytest.fixture(autouse=True) +def _trace_export_endpoint( + library_env: dict[str, str], + test_agent: TestAgentAPI, + test_agent_otlp_http_port: int, +) -> None: + library_env["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = ( + f"http://{test_agent.container_name}:{test_agent_otlp_http_port}/v1/traces" + ) + + +def _trace_request(test_agent: TestAgentAPI, test_library: APMLibrary) -> AgentRequest: + with test_library as library: + with library.dd_start_span(name="otel-otlp-traces-headers"): + pass + library.dd_flush() + + requests = [request for request in test_agent.requests() if request["url"].endswith("/v1/traces")] + assert requests, f"Expected OTLP trace request, got {test_agent.requests()}" + return requests[0] + + +def _request_headers(request: AgentRequest) -> dict[str, str]: + return {name.lower(): value for name, value in request["headers"].items()} + + +def _assert_routing_headers(headers: dict[str, str]) -> None: + assert headers.get("dd-protocol") == "otlp" + assert headers.get("dd-otlp-path") == "agent" + + +@scenarios.parametric +@features.otel_exporter_otlp_traces_headers +class Test_OTEL_EXPORTER_OTLP_TRACES_HEADERS: + @pytest.mark.parametrize( + ("library_env", "expected_headers"), + [ + pytest.param( + { + **BASE_ENVIRONMENT, + VARIABLE: "dd-protocol=otlp,dd-otlp-path=agent,header-one=value-one,header-two=value-two", + }, + {"header-one": "value-one", "header-two": "value-two"}, + id="two-header-pairs", + ), + ], + ) + def test_header_pairs_are_sent_on_trace_export( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + *, + expected_headers: dict[str, str], + ) -> None: + headers = _request_headers(_trace_request(test_agent, test_library)) + _assert_routing_headers(headers) + for name, value in expected_headers.items(): + assert headers.get(name) == value, f"Expected {name}={value}, got {headers}" + + @pytest.mark.parametrize("library_env", [pytest.param({**BASE_ENVIRONMENT}, id="unset")]) + def test_unset_uses_global_headers( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + ) -> None: + headers = _request_headers(_trace_request(test_agent, test_library)) + _assert_routing_headers(headers) + assert all(name not in headers for name in ("header-one", "header-two")) + + @pytest.mark.parametrize("library_env", [pytest.param({**BASE_ENVIRONMENT, VARIABLE: ""}, id="empty")]) + def test_empty_is_treated_as_unset( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + ) -> None: + headers = _request_headers(_trace_request(test_agent, test_library)) + _assert_routing_headers(headers) + assert all(name not in headers for name in ("header-one", "header-two")) diff --git a/tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py b/tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py new file mode 100644 index 00000000000..4cfcd48497a --- /dev/null +++ b/tests/parametric/otel_env_vars/test_otel_exporter_otlp_traces_protocol.py @@ -0,0 +1,133 @@ +from tests.parametric.conftest import APMLibrary +from utils import features, pytest, scenarios +from utils.docker_fixtures import TestAgentAPI +from utils.docker_fixtures._test_agent import AgentRequest + + +OTLP_TRACE_PATH = "/v1/traces" +ROUTING_HEADERS = "dd-protocol=otlp,dd-otlp-path=agent" +DEFAULT_PROTOCOL = "http/protobuf" + +BASE_ENVIRONMENT = { + "DD_TRACE_AGENT_PROTOCOL_VERSION": None, + "DD_TRACE_ENABLED": None, + "DD_TRACE_OTEL_ENABLED": "true", + "OTEL_EXPORTER_OTLP_TRACES_HEADERS": ROUTING_HEADERS, + "OTEL_TRACES_EXPORTER": "otlp", +} + +CONTENT_TYPES = { + "grpc": "application/grpc", + "http/protobuf": "application/x-protobuf", + "http/json": "application/json", +} + +GRPC_PROTOCOL_VALUE = [ + pytest.param({**BASE_ENVIRONMENT, "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": "grpc"}, "grpc", id="grpc"), +] + +HTTP_PROTOCOL_VALUES = [ + pytest.param( + {**BASE_ENVIRONMENT, "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": "http/protobuf"}, + "http/protobuf", + id="http-protobuf", + ), + pytest.param( + {**BASE_ENVIRONMENT, "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": "http/json"}, + "http/json", + id="http-json", + ), +] + +UNSET_VALUE = [pytest.param({**BASE_ENVIRONMENT}, DEFAULT_PROTOCOL, id="unset")] +EMPTY_VALUE = [ + pytest.param( + {**BASE_ENVIRONMENT, "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": ""}, + DEFAULT_PROTOCOL, + id="empty", + ) +] + + +@pytest.fixture(autouse=True) +def _trace_export_endpoint( + library_env: dict[str, str], + test_agent: TestAgentAPI, + test_agent_otlp_http_port: int, + test_agent_otlp_grpc_port: int, +) -> None: + protocol = library_env.get("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL") or DEFAULT_PROTOCOL + if protocol == "grpc": + library_env["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = ( + f"http://{test_agent.container_name}:{test_agent_otlp_grpc_port}" + ) + return + + library_env["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"] = ( + f"http://{test_agent.container_name}:{test_agent_otlp_http_port}{OTLP_TRACE_PATH}" + ) + + +def _trace_request(test_agent: TestAgentAPI, test_library: APMLibrary) -> AgentRequest: + with test_library as library: + with library.dd_start_span(name="otel-otlp-traces-protocol"): + pass + library.dd_flush() + + requests = [request for request in test_agent.requests() if request["url"].endswith(OTLP_TRACE_PATH)] + assert requests, f"Expected OTLP trace request, got {test_agent.requests()}" + return requests[0] + + +def _assert_protocol( + test_agent: TestAgentAPI, + test_library: APMLibrary, + expected_protocol: str, +) -> None: + request = _trace_request(test_agent, test_library) + headers = {name.lower(): value for name, value in request["headers"].items()} + assert headers.get("content-type", "").startswith(CONTENT_TYPES[expected_protocol]) + + +@scenarios.parametric +@features.otel_exporter_otlp_traces_protocol +class Test_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: + @pytest.mark.parametrize(("library_env", "expected_protocol"), GRPC_PROTOCOL_VALUE) + def test_grpc_protocol_is_used_for_trace_export( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + *, + expected_protocol: str, + ) -> None: + _assert_protocol(test_agent, test_library, expected_protocol) + + @pytest.mark.parametrize(("library_env", "expected_protocol"), HTTP_PROTOCOL_VALUES) + def test_http_protocol_is_used_for_trace_export( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + *, + expected_protocol: str, + ) -> None: + _assert_protocol(test_agent, test_library, expected_protocol) + + @pytest.mark.parametrize(("library_env", "expected_protocol"), UNSET_VALUE) + def test_unset_uses_specification_default( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + *, + expected_protocol: str, + ) -> None: + _assert_protocol(test_agent, test_library, expected_protocol) + + @pytest.mark.parametrize(("library_env", "expected_protocol"), EMPTY_VALUE) + def test_empty_is_treated_as_unset( + self, + test_agent: TestAgentAPI, + test_library: APMLibrary, + *, + expected_protocol: str, + ) -> None: + _assert_protocol(test_agent, test_library, expected_protocol)