Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions sdk/identity/azure-identity/tests/perfstress_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# azure-identity Performance Tests

In order to run the performance tests, the `azure-devtools` package must be installed. This is done as part of the
`dev_requirements` install. Start by creating a new Python 3 virtual environment.

## Test commands

Once `azure-devtools` is installed, you will have access to the `perfstress` command line tool, which will scan the
current module for runnable perf tests. Only a specific test can be run at a time (i.e. there is no "run all" feature).

`perfstress` with no options will list all available tests:
```
(env) ~/azure-identity/tests> perfstress
```

### Common perf command line options
These options are available for all perf tests:
- `--duration=10` Number of seconds to run as many operations (the "run" function) as possible. Default is 10.
- `--iterations=1` Number of test iterations to run. Default is 1.
- `--parallel=1` Number of tests to run in parallel. Default is 1.
- `--warm-up=5` Number of seconds to spend warming up the connection before measuring begins. Default is 5.
- `--sync` Whether to run the tests in sync or async. Default is False (async).
- `--no-cleanup` Whether to keep newly created resources after test run. Default is False (resources will be deleted).

## Example command
```
(env) ~/azure-identity/tests> perfstress BearerTokenPolicyTest
```

## Tests
- `BearerTokenPolicyTest` Runs a single request through `BearerTokenCredentialPolicy`,
and a mock transport
- `MemoryCacheRead` retrieves an access token from the default, in memory cache.
This is useful primarily as a baseline for `PersistentCacheRead`.
- `PersistentCacheRead` retrives an access token from the persistent cache
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE.txt in the project root for
# license information.
# -------------------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE.txt in the project root for
# license information.
# -------------------------------------------------------------------------
import asyncio
import time
from unittest.mock import Mock

from azure_devtools.perfstress_tests import PerfStressTest

from azure.core.credentials import AccessToken
from azure.core.pipeline import AsyncPipeline, Pipeline
from azure.core.pipeline.policies import AsyncBearerTokenCredentialPolicy, BearerTokenCredentialPolicy
from azure.core.pipeline.transport import HttpRequest


class BearerTokenPolicyTest(PerfStressTest):
def __init__(self, arguments):
super().__init__(arguments)

token = AccessToken("**", int(time.time() + 3600))

self.request = HttpRequest("GET", "https://localhost")

credential = Mock(get_token=Mock(return_value=token))
self.pipeline = Pipeline(transport=Mock(), policies=[BearerTokenCredentialPolicy(credential=credential)])

completed_future = asyncio.Future()
completed_future.set_result(token)
async_credential = Mock(get_token=Mock(return_value=completed_future))

# returning a token is okay because the policy does nothing with the transport's response
async_transport = Mock(send=Mock(return_value=completed_future))
self.async_pipeline = AsyncPipeline(
async_transport, policies=[AsyncBearerTokenCredentialPolicy(credential=async_credential)]
)

def run_sync(self):
self.pipeline.run(self.request)

async def run_async(self):
await self.async_pipeline.run(self.request)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
from azure_devtools.perfstress_tests import PerfStressTest

from azure.identity import ClientSecretCredential
from azure.identity.aio import ClientSecretCredential as AsyncClientSecretCredential

try:
from dotenv import load_dotenv

load_dotenv()
except ImportError:
pass


class MemoryCacheRead(PerfStressTest):
def __init__(self, arguments):
super().__init__(arguments)

client_id = self.get_from_env("AZURE_CLIENT_ID")
tenant_id = self.get_from_env("AZURE_TENANT_ID")
secret = self.get_from_env("AZURE_CLIENT_SECRET")
self.credential = ClientSecretCredential(tenant_id, client_id, secret)
self.async_credential = AsyncClientSecretCredential(tenant_id, client_id, secret)
self.scope = "https://vault.azure.net/.default"

async def global_setup(self):
"""Cache an access token"""

await super().global_setup()
self.credential.get_token(self.scope)
await self.async_credential.get_token(self.scope)

def run_sync(self):
self.credential.get_token(self.scope)

async def run_async(self):
await self.async_credential.get_token(self.scope)

async def close(self):
await self.async_credential.close()
await super().close()
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
from azure_devtools.perfstress_tests import PerfStressTest

from azure.identity import ClientSecretCredential, TokenCachePersistenceOptions
from azure.identity.aio import ClientSecretCredential as AsyncClientSecretCredential

try:
from dotenv import load_dotenv

load_dotenv()
except ImportError:
pass


class PersistentCacheRead(PerfStressTest):
def __init__(self, arguments):
super().__init__(arguments)

client_id = self.get_from_env("AZURE_CLIENT_ID")
tenant_id = self.get_from_env("AZURE_TENANT_ID")
secret = self.get_from_env("AZURE_CLIENT_SECRET")
self.credential = ClientSecretCredential(
tenant_id, client_id, secret, cache_persistence_options=TokenCachePersistenceOptions()
)
self.async_credential = AsyncClientSecretCredential(
tenant_id, client_id, secret, cache_persistence_options=TokenCachePersistenceOptions()
)
self.scope = "https://vault.azure.net/.default"

async def global_setup(self):
"""Cache an access token"""

await super().global_setup()
self.credential.get_token(self.scope)
await self.async_credential.get_token(self.scope)

def run_sync(self):
self.credential.get_token(self.scope)

async def run_async(self):
await self.async_credential.get_token(self.scope)

async def close(self):
await self.async_credential.close()
await super().close()