summaryrefslogtreecommitdiff
path: root/opentelemetry-api/tests
diff options
context:
space:
mode:
Diffstat (limited to 'opentelemetry-api/tests')
-rw-r--r--opentelemetry-api/tests/metrics/test_meter.py24
-rw-r--r--opentelemetry-api/tests/propagators/test__envcarrier.py82
-rw-r--r--opentelemetry-api/tests/propagators/test_propagators.py4
-rw-r--r--opentelemetry-api/tests/util/test__importlib_metadata.py26
4 files changed, 122 insertions, 14 deletions
diff --git a/opentelemetry-api/tests/metrics/test_meter.py b/opentelemetry-api/tests/metrics/test_meter.py
index b910046..79b30b6 100644
--- a/opentelemetry-api/tests/metrics/test_meter.py
+++ b/opentelemetry-api/tests/metrics/test_meter.py
@@ -4,7 +4,7 @@
from logging import WARNING
from unittest import TestCase
-from unittest.mock import Mock, patch
+from unittest.mock import Mock
from opentelemetry.metrics import Meter, NoOpMeter
@@ -72,9 +72,7 @@ class ChildMeter(Meter):
class TestMeter(TestCase):
# pylint: disable=no-member
- # TODO: convert to assertNoLogs instead of mocking logger when 3.10 is baseline
- @patch("opentelemetry.metrics._internal._logger")
- def test_repeated_instrument_names(self, logger_mock):
+ def test_repeated_instrument_names(self):
try:
test_meter = NoOpMeter("name")
@@ -96,18 +94,24 @@ class TestMeter(TestCase):
"histogram",
"gauge",
]:
- getattr(test_meter, f"create_{instrument_name}")(instrument_name)
- logger_mock.warning.assert_not_called()
+ with self.assertNoLogs(
+ "opentelemetry.metrics._internal", level="WARNING"
+ ):
+ getattr(test_meter, f"create_{instrument_name}")(
+ instrument_name
+ )
for instrument_name in [
"observable_counter",
"observable_gauge",
"observable_up_down_counter",
]:
- getattr(test_meter, f"create_{instrument_name}")(
- instrument_name, Mock()
- )
- logger_mock.warning.assert_not_called()
+ with self.assertNoLogs(
+ "opentelemetry.metrics._internal", level="WARNING"
+ ):
+ getattr(test_meter, f"create_{instrument_name}")(
+ instrument_name, Mock()
+ )
def test_repeated_instrument_names_with_different_advisory(self):
try:
diff --git a/opentelemetry-api/tests/propagators/test__envcarrier.py b/opentelemetry-api/tests/propagators/test__envcarrier.py
index e3e36f4..8d00c62 100644
--- a/opentelemetry-api/tests/propagators/test__envcarrier.py
+++ b/opentelemetry-api/tests/propagators/test__envcarrier.py
@@ -14,6 +14,7 @@ from opentelemetry.context import Context, get_current
from opentelemetry.propagators._envcarrier import (
EnvironmentGetter,
EnvironmentSetter,
+ _is_normalized_key,
_normalize_key,
)
from opentelemetry.trace.propagation.tracecontext import (
@@ -40,7 +41,25 @@ class TestNormalizeKey(unittest.TestCase):
self.assertEqual(_normalize_key("ALREADY_VALID"), "ALREADY_VALID")
def test_empty_string(self):
- self.assertEqual(_normalize_key(""), "")
+ self.assertEqual(_normalize_key(""), "_")
+
+
+class TestIsNormalizedKey(unittest.TestCase):
+ """Unit tests for _is_normalized_key."""
+
+ def test_normalized_keys(self):
+ self.assertTrue(_is_normalized_key("TRACEPARENT"))
+ self.assertTrue(_is_normalized_key("X_B3_TRACEID"))
+ self.assertTrue(_is_normalized_key("H_LLO"))
+ self.assertTrue(_is_normalized_key("_1ABC"))
+
+ def test_non_normalized_keys(self):
+ self.assertFalse(_is_normalized_key(""))
+ self.assertFalse(_is_normalized_key("traceparent"))
+ self.assertFalse(_is_normalized_key("TraceParent"))
+ self.assertFalse(_is_normalized_key("X-B3-TRACEID"))
+ self.assertFalse(_is_normalized_key("1ABC"))
+ self.assertFalse(_is_normalized_key("héllo"))
class TestEnvironmentGetter(unittest.TestCase):
@@ -75,6 +94,13 @@ class TestEnvironmentGetter(unittest.TestCase):
result = getter.get({}, "empty_key")
self.assertEqual(result, [""])
+ def test_get_empty_key_maps_to_underscore(self):
+ """Test empty key lookup uses the normalized underscore name."""
+ with patch.dict(os.environ, {"_": "underscore_value"}, clear=True):
+ getter = EnvironmentGetter()
+ result = getter.get({}, "")
+ self.assertEqual(result, ["underscore_value"])
+
def test_get_with_special_characters(self):
"""Test environment variables with special characters."""
with patch.dict(
@@ -84,15 +110,45 @@ class TestEnvironmentGetter(unittest.TestCase):
result = getter.get({}, "test_key")
self.assertEqual(result, ["value with spaces and !@#$%"])
+ def test_get_ignores_non_normalized_env_var_name(self):
+ """Test that non-normalized environment variable names are ignored."""
+ with patch.dict(os.environ, {"X-B3-TRACEID": "ignored"}, clear=True):
+ getter = EnvironmentGetter()
+ self.assertIsNone(getter.get({}, "x-b3-traceid"))
+ self.assertIsNone(getter.get({}, "X_B3_TRACEID"))
+
+ def test_get_prefers_normalized_env_var_name(self):
+ """Test deterministic lookup when normalized names collide."""
+ with patch.dict(
+ os.environ,
+ {"X_B3_TRACEID": "expected", "X-B3-TRACEID": "ignored"},
+ clear=True,
+ ):
+ getter = EnvironmentGetter()
+ self.assertEqual(getter.get({}, "x-b3-traceid"), ["expected"])
+
def test_keys(self):
"""Test getting all environment variable keys."""
- test_env = {"KEY1": "value1", "KEY2": "value2", "key3": "value3"}
+ test_env = {"KEY1": "value1", "KEY2": "value2", "KEY3": "value3"}
with patch.dict(os.environ, test_env, clear=True):
getter = EnvironmentGetter()
keys = getter.keys({})
expected_keys = {"KEY1", "KEY2", "KEY3"}
self.assertEqual(set(keys), expected_keys)
+ def test_keys_ignores_non_normalized_env_var_names(self):
+ """Test that keys returns only already-normalized names."""
+ test_env = {
+ "KEY1": "value1",
+ "X-B3-TRACEID": "ignored",
+ "1START": "ignored",
+ "_1START": "value2",
+ }
+ with patch.dict(os.environ, test_env, clear=True):
+ getter = EnvironmentGetter()
+ keys = getter.keys({})
+ self.assertEqual(set(keys), {"KEY1", "_1START"})
+
def test_keys_empty_environment(self):
"""Test getting keys when environment is empty."""
with patch.dict(os.environ, {}, clear=True):
@@ -185,6 +241,13 @@ class TestEnvironmentSetter(unittest.TestCase):
setter.set(carrier, "empty_key", "")
self.assertEqual(carrier, {"EMPTY_KEY": ""})
+ def test_set_empty_key_maps_to_underscore(self):
+ """Test setting an empty key uses the normalized underscore name."""
+ setter = EnvironmentSetter()
+ carrier = {}
+ setter.set(carrier, "", "value")
+ self.assertEqual(carrier, {"_": "value"})
+
def test_does_not_modify_os_environ(self):
"""Test that setter does not modify os.environ."""
setter = EnvironmentSetter()
@@ -249,6 +312,21 @@ class TestEnvironmentCarrierWithTraceContext(unittest.TestCase):
self.assertEqual(span_context.trace_state.get("vendor1"), "value1")
self.assertEqual(span_context.trace_state.get("vendor2"), "value2")
+ @unittest.skipIf(
+ os.name == "nt",
+ "Windows environment variable names are case-insensitive",
+ )
+ def test_extract_ignores_lowercase_trace_context_names(self):
+ """Test extraction ignores non-normalized trace context env names."""
+ traceparent = f"00-{self.TRACE_ID:032x}-{self.SPAN_ID:016x}-01"
+
+ ctx = self._extract_with_env(
+ {"traceparent": traceparent, "tracestate": "vendor=value"}
+ )
+
+ span_context = trace.get_current_span(ctx).get_span_context()
+ self.assertFalse(span_context.is_valid)
+
def test_extract_invalid_traceparent(self):
"""Test that invalid traceparent formats are handled gracefully.
diff --git a/opentelemetry-api/tests/propagators/test_propagators.py b/opentelemetry-api/tests/propagators/test_propagators.py
index a62f8c0..a4cc973 100644
--- a/opentelemetry-api/tests/propagators/test_propagators.py
+++ b/opentelemetry-api/tests/propagators/test_propagators.py
@@ -40,7 +40,7 @@ class TestPropagators(TestCase):
@patch.dict(environ, {OTEL_PROPAGATORS: "None"})
@patch("opentelemetry.propagators.composite.CompositePropagator")
- def test_none_propogators(self, mock_compositehttppropagator):
+ def test_none_propagators(self, mock_compositehttppropagator):
def test_propagators(propagators):
propagators = {propagator.__class__ for propagator in propagators}
@@ -61,7 +61,7 @@ class TestPropagators(TestCase):
@patch.dict(environ, {OTEL_PROPAGATORS: "tracecontext, None"})
@patch("opentelemetry.propagators.composite.CompositePropagator")
- def test_multiple_propogators_with_none(
+ def test_multiple_propagators_with_none(
self, mock_compositehttppropagator
):
def test_propagators(propagators):
diff --git a/opentelemetry-api/tests/util/test__importlib_metadata.py b/opentelemetry-api/tests/util/test__importlib_metadata.py
index f7e5152..18b7505 100644
--- a/opentelemetry-api/tests/util/test__importlib_metadata.py
+++ b/opentelemetry-api/tests/util/test__importlib_metadata.py
@@ -1,8 +1,16 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
+import unittest
+import warnings
from unittest import TestCase
+try:
+ # pylint: disable-next=no-name-in-module
+ from importlib.metadata import SelectableGroups as _SelectableGroups
+except ImportError:
+ _SelectableGroups = None
+
from opentelemetry.metrics import MeterProvider
from opentelemetry.util._importlib_metadata import (
EntryPoint,
@@ -117,3 +125,21 @@ class TestEntryPoints(TestCase):
self.assertIsInstance(normalized, EntryPoints)
self.assertEqual(len(normalized), 2)
self.assertEqual(list(normalized), [ep1, ep2])
+
+ @unittest.skipIf(
+ _SelectableGroups is None,
+ "SelectableGroups not available on this Python version",
+ )
+ def test_as_entry_points_selectable_groups_no_deprecation_warning(self):
+ ep1 = EntryPoint(name="foo", value="bar:baz", group="gp")
+ ep2 = EntryPoint(name="foo2", value="bar2:baz2", group="gp")
+
+ sg = _SelectableGroups({"gp": [ep1, ep2]}) # type: ignore
+
+ with warnings.catch_warnings():
+ warnings.simplefilter("error")
+ normalized = _as_entry_points(sg)
+
+ self.assertIsInstance(normalized, EntryPoints)
+ self.assertEqual(len(normalized), 2)
+ self.assertEqual(list(normalized), [ep1, ep2])