diff options
Diffstat (limited to 'opentelemetry-api/tests')
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]) |
