Skip to content

Commit 21f1bac

Browse files
authored
azure-identity performance tests (#17490)
1 parent 0168981 commit 21f1bac

File tree

5 files changed

+175
-0
lines changed

5 files changed

+175
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# azure-identity Performance Tests
2+
3+
In order to run the performance tests, the `azure-devtools` package must be installed. This is done as part of the
4+
`dev_requirements` install. Start by creating a new Python 3 virtual environment.
5+
6+
## Test commands
7+
8+
Once `azure-devtools` is installed, you will have access to the `perfstress` command line tool, which will scan the
9+
current module for runnable perf tests. Only a specific test can be run at a time (i.e. there is no "run all" feature).
10+
11+
`perfstress` with no options will list all available tests:
12+
```
13+
(env) ~/azure-identity/tests> perfstress
14+
```
15+
16+
### Common perf command line options
17+
These options are available for all perf tests:
18+
- `--duration=10` Number of seconds to run as many operations (the "run" function) as possible. Default is 10.
19+
- `--iterations=1` Number of test iterations to run. Default is 1.
20+
- `--parallel=1` Number of tests to run in parallel. Default is 1.
21+
- `--warm-up=5` Number of seconds to spend warming up the connection before measuring begins. Default is 5.
22+
- `--sync` Whether to run the tests in sync or async. Default is False (async).
23+
- `--no-cleanup` Whether to keep newly created resources after test run. Default is False (resources will be deleted).
24+
25+
## Example command
26+
```
27+
(env) ~/azure-identity/tests> perfstress BearerTokenPolicyTest
28+
```
29+
30+
## Tests
31+
- `BearerTokenPolicyTest` Runs a single request through `BearerTokenCredentialPolicy`,
32+
and a mock transport
33+
- `MemoryCacheRead` retrieves an access token from the default, in memory cache.
34+
This is useful primarily as a baseline for `PersistentCacheRead`.
35+
- `PersistentCacheRead` retrives an access token from the persistent cache
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See LICENSE.txt in the project root for
4+
# license information.
5+
# -------------------------------------------------------------------------
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See LICENSE.txt in the project root for
4+
# license information.
5+
# -------------------------------------------------------------------------
6+
import asyncio
7+
import time
8+
from unittest.mock import Mock
9+
10+
from azure_devtools.perfstress_tests import PerfStressTest
11+
12+
from azure.core.credentials import AccessToken
13+
from azure.core.pipeline import AsyncPipeline, Pipeline
14+
from azure.core.pipeline.policies import AsyncBearerTokenCredentialPolicy, BearerTokenCredentialPolicy
15+
from azure.core.pipeline.transport import HttpRequest
16+
17+
18+
class BearerTokenPolicyTest(PerfStressTest):
19+
def __init__(self, arguments):
20+
super().__init__(arguments)
21+
22+
token = AccessToken("**", int(time.time() + 3600))
23+
24+
self.request = HttpRequest("GET", "https://localhost")
25+
26+
credential = Mock(get_token=Mock(return_value=token))
27+
self.pipeline = Pipeline(transport=Mock(), policies=[BearerTokenCredentialPolicy(credential=credential)])
28+
29+
completed_future = asyncio.Future()
30+
completed_future.set_result(token)
31+
async_credential = Mock(get_token=Mock(return_value=completed_future))
32+
33+
# returning a token is okay because the policy does nothing with the transport's response
34+
async_transport = Mock(send=Mock(return_value=completed_future))
35+
self.async_pipeline = AsyncPipeline(
36+
async_transport, policies=[AsyncBearerTokenCredentialPolicy(credential=async_credential)]
37+
)
38+
39+
def run_sync(self):
40+
self.pipeline.run(self.request)
41+
42+
async def run_async(self):
43+
await self.async_pipeline.run(self.request)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
from azure_devtools.perfstress_tests import PerfStressTest
6+
7+
from azure.identity import ClientSecretCredential
8+
from azure.identity.aio import ClientSecretCredential as AsyncClientSecretCredential
9+
10+
try:
11+
from dotenv import load_dotenv
12+
13+
load_dotenv()
14+
except ImportError:
15+
pass
16+
17+
18+
class MemoryCacheRead(PerfStressTest):
19+
def __init__(self, arguments):
20+
super().__init__(arguments)
21+
22+
client_id = self.get_from_env("AZURE_CLIENT_ID")
23+
tenant_id = self.get_from_env("AZURE_TENANT_ID")
24+
secret = self.get_from_env("AZURE_CLIENT_SECRET")
25+
self.credential = ClientSecretCredential(tenant_id, client_id, secret)
26+
self.async_credential = AsyncClientSecretCredential(tenant_id, client_id, secret)
27+
self.scope = "https://vault.azure.net/.default"
28+
29+
async def global_setup(self):
30+
"""Cache an access token"""
31+
32+
await super().global_setup()
33+
self.credential.get_token(self.scope)
34+
await self.async_credential.get_token(self.scope)
35+
36+
def run_sync(self):
37+
self.credential.get_token(self.scope)
38+
39+
async def run_async(self):
40+
await self.async_credential.get_token(self.scope)
41+
42+
async def close(self):
43+
await self.async_credential.close()
44+
await super().close()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
from azure_devtools.perfstress_tests import PerfStressTest
6+
7+
from azure.identity import ClientSecretCredential, TokenCachePersistenceOptions
8+
from azure.identity.aio import ClientSecretCredential as AsyncClientSecretCredential
9+
10+
try:
11+
from dotenv import load_dotenv
12+
13+
load_dotenv()
14+
except ImportError:
15+
pass
16+
17+
18+
class PersistentCacheRead(PerfStressTest):
19+
def __init__(self, arguments):
20+
super().__init__(arguments)
21+
22+
client_id = self.get_from_env("AZURE_CLIENT_ID")
23+
tenant_id = self.get_from_env("AZURE_TENANT_ID")
24+
secret = self.get_from_env("AZURE_CLIENT_SECRET")
25+
self.credential = ClientSecretCredential(
26+
tenant_id, client_id, secret, cache_persistence_options=TokenCachePersistenceOptions()
27+
)
28+
self.async_credential = AsyncClientSecretCredential(
29+
tenant_id, client_id, secret, cache_persistence_options=TokenCachePersistenceOptions()
30+
)
31+
self.scope = "https://vault.azure.net/.default"
32+
33+
async def global_setup(self):
34+
"""Cache an access token"""
35+
36+
await super().global_setup()
37+
self.credential.get_token(self.scope)
38+
await self.async_credential.get_token(self.scope)
39+
40+
def run_sync(self):
41+
self.credential.get_token(self.scope)
42+
43+
async def run_async(self):
44+
await self.async_credential.get_token(self.scope)
45+
46+
async def close(self):
47+
await self.async_credential.close()
48+
await super().close()

0 commit comments

Comments
 (0)