11# Copyright (c) Microsoft. All rights reserved.
22
33import json
4+ import os
45import unittest
56from unittest .mock import Mock , patch
67
@@ -20,11 +21,25 @@ def setUp(self):
2021 self .mock_token_resolver = Mock ()
2122 self .mock_token_resolver .return_value = "test_token_123"
2223
23- # Don't patch the class in setUp, do it per test
24+ # Store original environment variable values for cleanup
25+ self ._original_domain_override = os .environ .get ("A365_OBSERVABILITY_DOMAIN_OVERRIDE" )
26+
27+ # Ensure no override is set by default for most tests
28+ os .environ .pop ("A365_OBSERVABILITY_DOMAIN_OVERRIDE" , None )
29+
30+ # Create default exporter for tests that don't need special setup
2431 self .exporter = _Agent365Exporter (
2532 token_resolver = self .mock_token_resolver , cluster_category = "test"
2633 )
2734
35+ def tearDown (self ):
36+ """Clean up test environment."""
37+ # Restore original environment variable value
38+ if self ._original_domain_override is None :
39+ os .environ .pop ("A365_OBSERVABILITY_DOMAIN_OVERRIDE" , None )
40+ else :
41+ os .environ ["A365_OBSERVABILITY_DOMAIN_OVERRIDE" ] = self ._original_domain_override
42+
2843 def _create_mock_span (
2944 self ,
3045 name : str = "test_span" ,
@@ -384,6 +399,172 @@ def test_exporter_is_internal(self):
384399 "Exporter class should be prefixed with underscore to indicate it's private/internal" ,
385400 )
386401
402+ def test_export_uses_domain_override_when_env_var_set (self ):
403+ """Test that domain override is used when A365_OBSERVABILITY_DOMAIN_OVERRIDE is set."""
404+ # Arrange
405+ override_domain = "override.example.com"
406+ os .environ ["A365_OBSERVABILITY_DOMAIN_OVERRIDE" ] = override_domain
407+
408+ # Create exporter after setting environment variable so it reads the override
409+ exporter = _Agent365Exporter (
410+ token_resolver = self .mock_token_resolver , cluster_category = "test"
411+ )
412+
413+ spans = [self ._create_mock_span ("override_test_span" )]
414+
415+ # Mock the PowerPlatformApiDiscovery class (should not be called when override is set)
416+ with patch (
417+ "microsoft_agents_a365.observability.core.exporters.agent365_exporter.PowerPlatformApiDiscovery"
418+ ) as mock_discovery_class :
419+ # Mock the _post_with_retries method
420+ with patch .object (exporter , "_post_with_retries" , return_value = True ) as mock_post :
421+ # Act
422+ result = exporter .export (spans )
423+
424+ # Assert
425+ self .assertEqual (result , SpanExportResult .SUCCESS )
426+ mock_post .assert_called_once ()
427+
428+ # Verify the call arguments - should use override domain with complete URL
429+ args , kwargs = mock_post .call_args
430+ url , body , headers = args
431+
432+ expected_url = f"https://{ override_domain } /maven/agent365/agents/test-agent-456/traces?api-version=1"
433+ self .assertEqual (url , expected_url )
434+
435+ # Verify PowerPlatformApiDiscovery was not instantiated
436+ mock_discovery_class .assert_not_called ()
437+
438+ def test_export_uses_default_domain_when_no_override (self ):
439+ """Test that default domain resolution is used when no override is set."""
440+ # Arrange
441+ # Ensure override is not set
442+ os .environ .pop ("A365_OBSERVABILITY_DOMAIN_OVERRIDE" , None )
443+
444+ # Create exporter after clearing environment variable
445+ exporter = _Agent365Exporter (
446+ token_resolver = self .mock_token_resolver , cluster_category = "test"
447+ )
448+
449+ spans = [self ._create_mock_span ("default_domain_span" )]
450+
451+ # Mock the PowerPlatformApiDiscovery class
452+ with patch (
453+ "microsoft_agents_a365.observability.core.exporters.agent365_exporter.PowerPlatformApiDiscovery"
454+ ) as mock_discovery_class :
455+ mock_discovery = Mock ()
456+ mock_discovery .get_tenant_island_cluster_endpoint .return_value = "default-endpoint.com"
457+ mock_discovery_class .return_value = mock_discovery
458+
459+ # Mock the _post_with_retries method
460+ with patch .object (exporter , "_post_with_retries" , return_value = True ) as mock_post :
461+ # Act
462+ result = exporter .export (spans )
463+
464+ # Assert
465+ self .assertEqual (result , SpanExportResult .SUCCESS )
466+ mock_post .assert_called_once ()
467+
468+ # Verify the call arguments - should use default domain
469+ args , kwargs = mock_post .call_args
470+ url , body , headers = args
471+
472+ self .assertIn ("default-endpoint.com" , url )
473+ self .assertIn ("/maven/agent365/agents/test-agent-456/traces" , url )
474+
475+ # Verify PowerPlatformApiDiscovery was called
476+ mock_discovery_class .assert_called_once_with ("test" )
477+ mock_discovery .get_tenant_island_cluster_endpoint .assert_called_once_with (
478+ "test-tenant-123"
479+ )
480+
481+ def test_export_ignores_empty_domain_override (self ):
482+ """Test that empty or whitespace-only domain override is ignored."""
483+ # Arrange
484+ os .environ ["A365_OBSERVABILITY_DOMAIN_OVERRIDE" ] = " " # whitespace only
485+
486+ # Create exporter after setting environment variable
487+ exporter = _Agent365Exporter (
488+ token_resolver = self .mock_token_resolver , cluster_category = "test"
489+ )
490+
491+ spans = [self ._create_mock_span ("test_span" )]
492+
493+ # Mock the PowerPlatformApiDiscovery class (should be called since override is invalid)
494+ with patch (
495+ "microsoft_agents_a365.observability.core.exporters.agent365_exporter.PowerPlatformApiDiscovery"
496+ ) as mock_discovery_class :
497+ mock_discovery = Mock ()
498+ mock_discovery .get_tenant_island_cluster_endpoint .return_value = "default-endpoint.com"
499+ mock_discovery_class .return_value = mock_discovery
500+
501+ with patch .object (exporter , "_post_with_retries" , return_value = True ):
502+ # Act
503+ result = exporter .export (spans )
504+
505+ # Assert
506+ self .assertEqual (result , SpanExportResult .SUCCESS )
507+ # Verify PowerPlatformApiDiscovery was called (override was ignored)
508+ mock_discovery_class .assert_called_once_with ("test" )
509+
510+ def test_export_ignores_invalid_domain_with_protocol (self ):
511+ """Test that domain override containing protocol is ignored."""
512+ # Arrange
513+ os .environ ["A365_OBSERVABILITY_DOMAIN_OVERRIDE" ] = "https://invalid.example.com"
514+
515+ # Create exporter after setting environment variable
516+ exporter = _Agent365Exporter (
517+ token_resolver = self .mock_token_resolver , cluster_category = "test"
518+ )
519+
520+ spans = [self ._create_mock_span ("test_span" )]
521+
522+ # Mock the PowerPlatformApiDiscovery class (should be called since override is invalid)
523+ with patch (
524+ "microsoft_agents_a365.observability.core.exporters.agent365_exporter.PowerPlatformApiDiscovery"
525+ ) as mock_discovery_class :
526+ mock_discovery = Mock ()
527+ mock_discovery .get_tenant_island_cluster_endpoint .return_value = "default-endpoint.com"
528+ mock_discovery_class .return_value = mock_discovery
529+
530+ with patch .object (exporter , "_post_with_retries" , return_value = True ):
531+ # Act
532+ result = exporter .export (spans )
533+
534+ # Assert
535+ self .assertEqual (result , SpanExportResult .SUCCESS )
536+ # Verify PowerPlatformApiDiscovery was called (override was ignored)
537+ mock_discovery_class .assert_called_once_with ("test" )
538+
539+ def test_export_ignores_invalid_domain_with_path (self ):
540+ """Test that domain override containing path separator is ignored."""
541+ # Arrange
542+ os .environ ["A365_OBSERVABILITY_DOMAIN_OVERRIDE" ] = "invalid.example.com/path"
543+
544+ # Create exporter after setting environment variable
545+ exporter = _Agent365Exporter (
546+ token_resolver = self .mock_token_resolver , cluster_category = "test"
547+ )
548+
549+ spans = [self ._create_mock_span ("test_span" )]
550+
551+ # Mock the PowerPlatformApiDiscovery class (should be called since override is invalid)
552+ with patch (
553+ "microsoft_agents_a365.observability.core.exporters.agent365_exporter.PowerPlatformApiDiscovery"
554+ ) as mock_discovery_class :
555+ mock_discovery = Mock ()
556+ mock_discovery .get_tenant_island_cluster_endpoint .return_value = "default-endpoint.com"
557+ mock_discovery_class .return_value = mock_discovery
558+
559+ with patch .object (exporter , "_post_with_retries" , return_value = True ):
560+ # Act
561+ result = exporter .export (spans )
562+
563+ # Assert
564+ self .assertEqual (result , SpanExportResult .SUCCESS )
565+ # Verify PowerPlatformApiDiscovery was called (override was ignored)
566+ mock_discovery_class .assert_called_once_with ("test" )
567+
387568
388569if __name__ == "__main__" :
389570 unittest .main ()
0 commit comments