|
12 | 12 | _additional_properties, |
13 | 13 | _map_compression, |
14 | 14 | _parse_headers, |
| 15 | + _resolve_component, |
15 | 16 | load_entry_point, |
16 | 17 | ) |
17 | 18 | from opentelemetry.sdk._configuration._exceptions import ConfigurationError |
@@ -289,3 +290,84 @@ def test_log_record_exporter(self): |
289 | 290 |
|
290 | 291 | def test_push_metric_exporter(self): |
291 | 292 | self._assert_supports_additional_properties(PushMetricExporter) |
| 293 | + |
| 294 | + |
| 295 | +class TestResolveComponent(unittest.TestCase): |
| 296 | + def setUp(self): |
| 297 | + @_additional_properties |
| 298 | + @dataclass |
| 299 | + class _Config: |
| 300 | + builtin_a: dict | None = None |
| 301 | + builtin_b: str | None = None |
| 302 | + additional_properties: ClassVar[dict[str, Any]] |
| 303 | + |
| 304 | + self.cls = _Config |
| 305 | + self.registry = { |
| 306 | + "builtin_a": lambda v: ("resolved_a", v), |
| 307 | + "builtin_b": lambda v: ("resolved_b", v), |
| 308 | + } |
| 309 | + |
| 310 | + def test_resolves_builtin_from_registry(self): |
| 311 | + config = self.cls(builtin_a={"key": "val"}) |
| 312 | + result = _resolve_component( |
| 313 | + config, self.registry, "test_group", "test component" |
| 314 | + ) |
| 315 | + self.assertEqual(result, ("resolved_a", {"key": "val"})) |
| 316 | + |
| 317 | + def test_resolves_plugin_via_entry_point(self): |
| 318 | + mock_instance = MagicMock() |
| 319 | + mock_class = MagicMock(return_value=mock_instance) |
| 320 | + with patch( |
| 321 | + "opentelemetry.sdk._configuration._common.entry_points", |
| 322 | + return_value=[MagicMock(**{"load.return_value": mock_class})], |
| 323 | + ): |
| 324 | + # pylint: disable=unexpected-keyword-arg |
| 325 | + config = self.cls(my_plugin={"opt": "val"}) |
| 326 | + result = _resolve_component( |
| 327 | + config, self.registry, "test_group", "test component" |
| 328 | + ) |
| 329 | + self.assertIs(result, mock_instance) |
| 330 | + mock_class.assert_called_once_with(opt="val") |
| 331 | + |
| 332 | + def test_plugin_with_empty_config(self): |
| 333 | + mock_instance = MagicMock() |
| 334 | + mock_class = MagicMock(return_value=mock_instance) |
| 335 | + with patch( |
| 336 | + "opentelemetry.sdk._configuration._common.entry_points", |
| 337 | + return_value=[MagicMock(**{"load.return_value": mock_class})], |
| 338 | + ): |
| 339 | + # pylint: disable=unexpected-keyword-arg |
| 340 | + config = self.cls(my_plugin={}) |
| 341 | + _resolve_component( |
| 342 | + config, self.registry, "test_group", "test component" |
| 343 | + ) |
| 344 | + mock_class.assert_called_once_with() |
| 345 | + |
| 346 | + def test_no_component_raises_configuration_error(self): |
| 347 | + config = self.cls() |
| 348 | + with self.assertRaises(ConfigurationError): |
| 349 | + _resolve_component( |
| 350 | + config, self.registry, "test_group", "test component" |
| 351 | + ) |
| 352 | + |
| 353 | + def test_plugin_not_found_raises_configuration_error(self): |
| 354 | + with patch( |
| 355 | + "opentelemetry.sdk._configuration._common.entry_points", |
| 356 | + return_value=[], |
| 357 | + ): |
| 358 | + # pylint: disable=unexpected-keyword-arg |
| 359 | + config = self.cls(missing_plugin={}) |
| 360 | + with self.assertRaises(ConfigurationError): |
| 361 | + _resolve_component( |
| 362 | + config, self.registry, "test_group", "test component" |
| 363 | + ) |
| 364 | + |
| 365 | + def test_first_registry_match_wins_when_multiple_set(self): |
| 366 | + """When multiple built-in fields are set (which the schema should |
| 367 | + prevent), the first registry match wins.""" |
| 368 | + config = self.cls(builtin_a={"a": 1}, builtin_b="b") |
| 369 | + result = _resolve_component( |
| 370 | + config, self.registry, "test_group", "test component" |
| 371 | + ) |
| 372 | + # builtin_a comes first in the registry dict |
| 373 | + self.assertEqual(result, ("resolved_a", {"a": 1})) |
0 commit comments