Skip to content

Commit d338dc8

Browse files
fix
1 parent 9c046c3 commit d338dc8

1 file changed

Lines changed: 167 additions & 159 deletions

File tree

Lines changed: 167 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,167 @@
1-
# Copyright (c) Microsoft. All rights reserved.
2-
3-
import unittest
4-
5-
from microsoft_agents_a365.runtime.power_platform_api_discovery import PowerPlatformApiDiscovery
6-
7-
8-
class TestPowerPlatformApiDiscovery(unittest.TestCase):
9-
def test_host_suffix_and_audience(self):
10-
expected_host_suffixes = {
11-
"local": "api.powerplatform.localhost",
12-
"dev": "api.powerplatform.com",
13-
"test": "api.powerplatform.com",
14-
"preprod": "api.powerplatform.com",
15-
"firstrelease": "api.powerplatform.com",
16-
"prod": "api.powerplatform.com",
17-
"gov": "api.gov.powerplatform.microsoft.us",
18-
"high": "api.high.powerplatform.microsoft.us",
19-
"dod": "api.appsplatform.us",
20-
"mooncake": "api.powerplatform.partner.microsoftonline.cn",
21-
"ex": "api.powerplatform.eaglex.ic.gov",
22-
"rx": "api.powerplatform.microsoft.scloud",
23-
}
24-
25-
for cluster, expected in expected_host_suffixes.items():
26-
with self.subTest(cluster=cluster):
27-
disc = PowerPlatformApiDiscovery(cluster) # type: ignore[arg-type]
28-
self.assertEqual(disc.get_token_endpoint_host(), expected)
29-
self.assertEqual(disc.get_token_audience(), f"https://{expected}")
30-
31-
def test_hex_suffix_length_rules(self):
32-
prod = PowerPlatformApiDiscovery("prod")
33-
first = PowerPlatformApiDiscovery("firstrelease")
34-
dev = PowerPlatformApiDiscovery("dev")
35-
36-
self.assertEqual(prod._get_hex_api_suffix_length(), 2)
37-
self.assertEqual(first._get_hex_api_suffix_length(), 2)
38-
self.assertEqual(dev._get_hex_api_suffix_length(), 1)
39-
40-
def test_tenant_endpoint_generation_prod(self):
41-
disc = PowerPlatformApiDiscovery("prod")
42-
tenant_id = "abc-012" # normalized -> abc012; suffix length 2 -> '12'
43-
expected = "abc0.12.tenant.api.powerplatform.com"
44-
self.assertEqual(disc.get_tenant_endpoint(tenant_id), expected)
45-
46-
def test_tenant_endpoint_generation_dev(self):
47-
disc = PowerPlatformApiDiscovery("dev")
48-
tenant_id = "A1B2" # normalized -> a1b2; suffix length 1 -> '2'
49-
expected = "a1b.2.tenant.api.powerplatform.com"
50-
self.assertEqual(disc.get_tenant_endpoint(tenant_id), expected)
51-
52-
def test_tenant_island_cluster_endpoint(self):
53-
disc = PowerPlatformApiDiscovery("prod")
54-
tenant_id = "abc-1234" # normalized -> abc1234; suffix '34', prefix 'abc12'
55-
expected = "il-abc12.34.tenant.api.powerplatform.com"
56-
self.assertEqual(disc.get_tenant_island_cluster_endpoint(tenant_id), expected)
57-
58-
def test_invalid_characters_in_tenant_identifier(self):
59-
disc = PowerPlatformApiDiscovery("dev")
60-
with self.assertRaisesRegex(ValueError, r"invalid host name characters"):
61-
disc.get_tenant_endpoint("invalid$name")
62-
63-
def test_tenant_identifier_too_short_for_suffix(self):
64-
disc = PowerPlatformApiDiscovery("prod")
65-
# prod requires normalized length >= 3 (2 + 1). Provide only 2 characters.
66-
with self.assertRaisesRegex(ValueError, r"must be at least"):
67-
disc.get_tenant_endpoint("ab")
68-
69-
def test_normalization_of_tenant_id(self):
70-
disc = PowerPlatformApiDiscovery("dev")
71-
tenant_id = "Ab-Cd-Ef" # normalized -> abcdef; suffix 1 -> 'f', prefix 'abcde'
72-
expected = "abcde.f.tenant.api.powerplatform.com"
73-
self.assertEqual(disc.get_tenant_endpoint(tenant_id), expected)
74-
75-
def test_nodejs_tenant_examples(self):
76-
tenant_id = "e3064512-cc6d-4703-be71-a2ecaecaa98a"
77-
expected_map = {
78-
"local": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.localhost",
79-
"dev": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com",
80-
"test": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com",
81-
"preprod": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com",
82-
"firstrelease": "e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com",
83-
"prod": "e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com",
84-
"gov": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.gov.powerplatform.microsoft.us",
85-
"high": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.high.powerplatform.microsoft.us",
86-
"dod": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.appsplatform.us",
87-
"mooncake": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.partner.microsoftonline.cn",
88-
"ex": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.eaglex.ic.gov",
89-
"rx": "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.microsoft.scloud",
90-
}
91-
92-
for cluster, expected in expected_map.items():
93-
with self.subTest(cluster=cluster):
94-
disc = PowerPlatformApiDiscovery(cluster) # type: ignore[arg-type]
95-
self.assertEqual(disc.get_tenant_endpoint(tenant_id), expected)
96-
97-
def test_nodejs_tenant_island_examples(self):
98-
tenant_id = "e3064512-cc6d-4703-be71-a2ecaecaa98a"
99-
expected_map = {
100-
"local": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.localhost",
101-
"dev": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com",
102-
"test": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com",
103-
"preprod": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com",
104-
"firstrelease": "il-e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com",
105-
"prod": "il-e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com",
106-
"gov": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.gov.powerplatform.microsoft.us",
107-
"high": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.high.powerplatform.microsoft.us",
108-
"dod": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.appsplatform.us",
109-
"mooncake": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.partner.microsoftonline.cn",
110-
"ex": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.eaglex.ic.gov",
111-
"rx": "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.microsoft.scloud",
112-
}
113-
114-
for cluster, expected in expected_map.items():
115-
with self.subTest(cluster=cluster):
116-
disc = PowerPlatformApiDiscovery(cluster) # type: ignore[arg-type]
117-
self.assertEqual(disc.get_tenant_island_cluster_endpoint(tenant_id), expected)
118-
119-
def test_nodejs_invalid_characters_exact_message(self):
120-
disc = PowerPlatformApiDiscovery("local")
121-
expected_msg = "Cannot generate Power Platform API endpoint because the tenant identifier contains invalid host name characters, only alphanumeric and dash characters are expected: invalid?"
122-
with self.assertRaises(ValueError) as cm:
123-
disc.get_tenant_endpoint("invalid?")
124-
self.assertEqual(str(cm.exception), expected_msg)
125-
126-
def test_nodejs_insufficient_length_exact_messages(self):
127-
disc_local = PowerPlatformApiDiscovery("local")
128-
with self.assertRaises(ValueError) as cm1:
129-
disc_local.get_tenant_endpoint("a")
130-
self.assertEqual(
131-
str(cm1.exception),
132-
"Cannot generate Power Platform API endpoint because the normalized tenant identifier must be at least 2 characters in length: a",
133-
)
134-
135-
with self.assertRaises(ValueError) as cm2:
136-
disc_local.get_tenant_endpoint("a-")
137-
self.assertEqual(
138-
str(cm2.exception),
139-
"Cannot generate Power Platform API endpoint because the normalized tenant identifier must be at least 2 characters in length: a",
140-
)
141-
142-
disc_prod = PowerPlatformApiDiscovery("prod")
143-
with self.assertRaises(ValueError) as cm3:
144-
disc_prod.get_tenant_endpoint("aa")
145-
self.assertEqual(
146-
str(cm3.exception),
147-
"Cannot generate Power Platform API endpoint because the normalized tenant identifier must be at least 3 characters in length: aa",
148-
)
149-
150-
with self.assertRaises(ValueError) as cm4:
151-
disc_prod.get_tenant_endpoint("a-a")
152-
self.assertEqual(
153-
str(cm4.exception),
154-
"Cannot generate Power Platform API endpoint because the normalized tenant identifier must be at least 3 characters in length: aa",
155-
)
156-
157-
158-
if __name__ == "__main__":
159-
unittest.main()
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
"""Unit tests for PowerPlatformApiDiscovery class."""
5+
6+
import re
7+
import pytest
8+
9+
from microsoft_agents_a365.runtime.power_platform_api_discovery import (
10+
PowerPlatformApiDiscovery,
11+
)
12+
13+
14+
# Tests for get_token_endpoint_host and get_token_audience
15+
@pytest.mark.parametrize(
16+
"cluster,expected_host",
17+
[
18+
("local", "api.powerplatform.localhost"),
19+
("dev", "api.powerplatform.com"),
20+
("test", "api.powerplatform.com"),
21+
("preprod", "api.powerplatform.com"),
22+
("firstrelease", "api.powerplatform.com"),
23+
("prod", "api.powerplatform.com"),
24+
("gov", "api.gov.powerplatform.microsoft.us"),
25+
("high", "api.high.powerplatform.microsoft.us"),
26+
("dod", "api.appsplatform.us"),
27+
("mooncake", "api.powerplatform.partner.microsoftonline.cn"),
28+
("ex", "api.powerplatform.eaglex.ic.gov"),
29+
("rx", "api.powerplatform.microsoft.scloud"),
30+
],
31+
)
32+
def test_host_suffix_and_audience(cluster, expected_host):
33+
"""Test get_token_endpoint_host and get_token_audience return correct values for each cluster."""
34+
disc = PowerPlatformApiDiscovery(cluster)
35+
assert disc.get_token_endpoint_host() == expected_host
36+
assert disc.get_token_audience() == f"https://{expected_host}"
37+
38+
39+
# Tests for _get_hex_api_suffix_length
40+
@pytest.mark.parametrize(
41+
"cluster,expected_length",
42+
[
43+
("prod", 2),
44+
("firstrelease", 2),
45+
("dev", 1),
46+
("test", 1),
47+
("preprod", 1),
48+
("local", 1),
49+
("gov", 1),
50+
("high", 1),
51+
("dod", 1),
52+
("mooncake", 1),
53+
("ex", 1),
54+
("rx", 1),
55+
],
56+
)
57+
def test_hex_suffix_length_rules(cluster, expected_length):
58+
"""Test _get_hex_api_suffix_length returns correct suffix length for each cluster."""
59+
disc = PowerPlatformApiDiscovery(cluster)
60+
assert disc._get_hex_api_suffix_length() == expected_length
61+
62+
63+
# Tests for get_tenant_endpoint
64+
@pytest.mark.parametrize(
65+
"cluster,tenant_id,expected",
66+
[
67+
("prod", "abc-012", "abc0.12.tenant.api.powerplatform.com"),
68+
("dev", "A1B2", "a1b.2.tenant.api.powerplatform.com"),
69+
("dev", "Ab-Cd-Ef", "abcde.f.tenant.api.powerplatform.com"),
70+
],
71+
)
72+
def test_tenant_endpoint_generation(cluster, tenant_id, expected):
73+
"""Test get_tenant_endpoint for various clusters and tenant IDs."""
74+
disc = PowerPlatformApiDiscovery(cluster)
75+
assert disc.get_tenant_endpoint(tenant_id) == expected
76+
77+
78+
@pytest.mark.parametrize(
79+
"cluster,expected",
80+
[
81+
("local", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.localhost"),
82+
("dev", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com"),
83+
("test", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com"),
84+
("preprod", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com"),
85+
("firstrelease", "e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com"),
86+
("prod", "e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com"),
87+
("gov", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.gov.powerplatform.microsoft.us"),
88+
("high", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.high.powerplatform.microsoft.us"),
89+
("dod", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.appsplatform.us"),
90+
(
91+
"mooncake",
92+
"e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.partner.microsoftonline.cn",
93+
),
94+
("ex", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.eaglex.ic.gov"),
95+
("rx", "e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.microsoft.scloud"),
96+
],
97+
)
98+
def test_tenant_endpoint_with_real_uuid(cluster, expected):
99+
"""Test get_tenant_endpoint with real UUID across all clusters."""
100+
tenant_id = "e3064512-cc6d-4703-be71-a2ecaecaa98a"
101+
disc = PowerPlatformApiDiscovery(cluster)
102+
assert disc.get_tenant_endpoint(tenant_id) == expected
103+
104+
105+
# Tests for get_tenant_island_cluster_endpoint
106+
@pytest.mark.parametrize(
107+
"cluster,expected",
108+
[
109+
("local", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.localhost"),
110+
("dev", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com"),
111+
("test", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com"),
112+
("preprod", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.com"),
113+
("firstrelease", "il-e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com"),
114+
("prod", "il-e3064512cc6d4703be71a2ecaecaa9.8a.tenant.api.powerplatform.com"),
115+
("gov", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.gov.powerplatform.microsoft.us"),
116+
("high", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.high.powerplatform.microsoft.us"),
117+
("dod", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.appsplatform.us"),
118+
(
119+
"mooncake",
120+
"il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.partner.microsoftonline.cn",
121+
),
122+
("ex", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.eaglex.ic.gov"),
123+
("rx", "il-e3064512cc6d4703be71a2ecaecaa98.a.tenant.api.powerplatform.microsoft.scloud"),
124+
],
125+
)
126+
def test_tenant_island_cluster_endpoint(cluster, expected):
127+
"""Test get_tenant_island_cluster_endpoint with real UUID across all clusters."""
128+
tenant_id = "e3064512-cc6d-4703-be71-a2ecaecaa98a"
129+
disc = PowerPlatformApiDiscovery(cluster)
130+
assert disc.get_tenant_island_cluster_endpoint(tenant_id) == expected
131+
132+
133+
# Tests for error handling
134+
@pytest.mark.parametrize(
135+
"tenant_id",
136+
[
137+
"invalid$name",
138+
"invalid?",
139+
"tenant@id",
140+
"tenant#123",
141+
"tenant with spaces",
142+
"",
143+
"---",
144+
"-",
145+
],
146+
)
147+
def test_invalid_tenant_identifier(tenant_id):
148+
"""Test ValueError is raised for invalid tenant IDs (invalid chars, empty, or all dashes)."""
149+
disc = PowerPlatformApiDiscovery("dev")
150+
with pytest.raises(ValueError):
151+
disc.get_tenant_endpoint(tenant_id)
152+
153+
154+
@pytest.mark.parametrize(
155+
"cluster,tenant_id,min_length",
156+
[
157+
("local", "a", 2),
158+
("local", "a-", 2),
159+
("prod", "aa", 3),
160+
("prod", "a-a", 3),
161+
],
162+
)
163+
def test_tenant_identifier_too_short(cluster, tenant_id, min_length):
164+
"""Test ValueError is raised when tenant ID is too short after normalization."""
165+
disc = PowerPlatformApiDiscovery(cluster)
166+
with pytest.raises(ValueError, match=f"must be at least {min_length}"):
167+
disc.get_tenant_endpoint(tenant_id)

0 commit comments

Comments
 (0)