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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# coding: utf-8
# -------------------------------------------------------------------------
# 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,27 @@

# coding: utf-8
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
import functools
import asyncio
from azure_devtools.scenario_tests.utilities import trim_kwargs_from_test_function
from .testcase import CommunicationTestCase

class AsyncCommunicationTestCase(CommunicationTestCase):

@staticmethod
def await_prepared_test(test_fn):
"""Synchronous wrapper for async test methods. Used to avoid making changes
upstream to AbstractPreparer (which doesn't await the functions it wraps)
"""

@functools.wraps(test_fn)
def run(test_class_instance, *args, **kwargs):
trim_kwargs_from_test_function(test_fn, kwargs)
loop = asyncio.get_event_loop()
return loop.run_until_complete(test_fn(test_class_instance, **kwargs))

return run
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------

import datetime

from azure.mgmt.communication import CommunicationServiceManagementClient
from azure.mgmt.communication.models import CommunicationServiceResource
from devtools_testutils import(
AzureMgmtPreparer,
ResourceGroupPreparer,
FakeResource
)
from devtools_testutils.resource_testcase import RESOURCE_GROUP_PARAM
from azure_devtools.scenario_tests.exceptions import AzureTestError

class CommunicationServicePreparer(AzureMgmtPreparer):
"""Communication Service Preparer.
Creating and destroying test resources on demand
"""
def __init__(
self,
name_prefix="communication",
resource_group_parameter_name=RESOURCE_GROUP_PARAM,
disable_recording=True,
use_cache=False,
playback_fake_resource=None,
client_kwargs=None,
):
super(CommunicationServicePreparer, self).__init__(
name_prefix,
random_name_length=24,
disable_recording=disable_recording,
playback_fake_resource=playback_fake_resource,
client_kwargs=client_kwargs,
)
self.resource_group_parameter_name = resource_group_parameter_name
self.random_name_enabled = True
self.service_name = "TEST-SERVICE-NAME"
self.mgmt_client = None
self.set_cache(use_cache)
self.scrubbed_resource_name = "communicationegrcrs"

def _get_resource_group(self, **kwargs):
try:
return kwargs[self.resource_group_parameter_name]
except KeyError:
template = (
"To create a communication service a resource group is required. Please add "
"decorator @{} in front of this preparer."
)
raise AzureTestError(template.format(ResourceGroupPreparer.__name__))

def create_resource(self, name, **kwargs):
if not self.is_live:
self.resource = FakeResource(name=self.scrubbed_resource_name, id=name)

return {
"connection_string": "endpoint=https://{}.communication.azure.com/;accesskey=fake===".format(self.resource.name),
}

self.test_class_instance.scrubber.register_name_pair(name, self.scrubbed_resource_name)
group_name = self._get_resource_group(**kwargs).name

self.client = self.create_mgmt_client(CommunicationServiceManagementClient, polling_interval=30)

self.resource = self.client.communication_service.begin_create_or_update(
group_name,
name,
CommunicationServiceResource(location="global", data_location="UnitedStates")
).result()

self.service_name = self.resource.name

primary_connection_string = self.client.communication_service.list_keys(
group_name,
self.resource.name).primary_connection_string

return {
"connection_string": primary_connection_string,
}

def remove_resource(self, name, **kwargs):
if not self.is_live:
return

group_name = self._get_resource_group(**kwargs).name
self.client.communication_service.begin_delete(group_name, self.service_name).wait()
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
from azure_devtools.scenario_tests import RecordingProcessor

class URIIdentityReplacer(RecordingProcessor):
"""Replace the identity in request uri"""
def process_request(self, request):
import re
request.uri = re.sub('/identities/([^/?]+)', '/identities/sanitized', request.uri)
return request

def process_response(self, response):
import re
if 'url' in response:
response['url'] = re.sub('/identities/([^/?]+)', '/identities/sanitized', response['url'])
return response
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
import re
from devtools_testutils import AzureTestCase
from azure_devtools.scenario_tests import RecordingProcessor, ReplayableTest
from azure_devtools.scenario_tests.utilities import is_text_payload

class ResponseReplacerProcessor(RecordingProcessor):
def __init__(self, keys=None, replacement="sanitized"):
self._keys = keys if keys else []
self._replacement = replacement

def process_response(self, response):
def sanitize_dict(dictionary):
for key in dictionary:
value = dictionary[key]
if isinstance(value, str):
dictionary[key] = re.sub(
r"("+'|'.join(self._keys)+r")",
self._replacement,
dictionary[key])
elif isinstance(value, dict):
sanitize_dict(value)

sanitize_dict(response)

return response

class BodyReplacerProcessor(RecordingProcessor):
"""Sanitize the sensitive info inside request or response bodies"""

def __init__(self, keys=None, replacement="sanitized"):
self._replacement = replacement
self._keys = keys if keys else []

def process_request(self, request):
if is_text_payload(request) and request.body:
request.body = self._replace_keys(request.body.decode()).encode()

return request

def process_response(self, response):
if is_text_payload(response) and response['body']['string']:
response['body']['string'] = self._replace_keys(response['body']['string'])

return response

def _replace_keys(self, body):
import json
try:
body = json.loads(body)
for key in self._keys:
if key in body:
body[key] = self._replacement

except (KeyError, ValueError):
return body

return json.dumps(body)

class CommunicationTestCase(AzureTestCase):
FILTER_HEADERS = ReplayableTest.FILTER_HEADERS + ['x-azure-ref', 'x-ms-content-sha256', 'location']

def __init__(self, method_name, *args, **kwargs):
super(CommunicationTestCase, self).__init__(method_name, *args, **kwargs)
11 changes: 11 additions & 0 deletions sdk/communication/azure-communication-identity/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
import sys

# Ignore collection of async tests for Python 2
collect_ignore_glob = []
if sys.version_info < (3, 5):
collect_ignore_glob.append("*_async.py")
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '0'
Date:
- Tue, 22 Dec 2020 18:26:56 GMT
User-Agent:
- azsdk-python-communication-administration/1.0.0b4 Python/3.8.5 (Windows-10-10.0.19041-SP0)
x-ms-return-client-request-id:
- 'true'
method: POST
uri: https://communicationegrcrs.communication.azure.com/identities?api-version=2020-07-20-preview2
response:
body:
string: '{"id": "sanitized"}'
headers:
api-supported-versions:
- 2020-01-15-preview3, 2020-07-20-preview1, 2020-07-20-preview2
content-type:
- application/json; charset=utf-8
date:
- Tue, 22 Dec 2020 18:26:55 GMT
ms-cv:
- 4whAoum970WIzePHLz1Ujg.0
strict-transport-security:
- max-age=2592000
transfer-encoding:
- chunked
x-processing-time:
- 18ms
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '0'
User-Agent:
- azsdk-python-communication-administration/1.0.0b4 Python/3.8.5 (Windows-10-10.0.19041-SP0)
method: POST
uri: https://communicationegrcrs.communication.azure.com/identities?api-version=2020-07-20-preview2
response:
body:
string: '{"id": "sanitized"}'
headers:
api-supported-versions:
- 2020-01-15-preview3, 2020-07-20-preview1, 2020-07-20-preview2
content-type:
- application/json; charset=utf-8
date:
- Tue, 22 Dec 2020 18:28:04 GMT
ms-cv:
- /4JsXqUuEkmQ1v304iaBTw.0
strict-transport-security:
- max-age=2592000
transfer-encoding:
- chunked
x-processing-time:
- 635ms
status:
code: 200
message: OK
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '0'
Date:
- Tue, 22 Dec 2020 18:29:13 GMT
User-Agent:
- azsdk-python-communication-administration/1.0.0b4 Python/3.8.5 (Windows-10-10.0.19041-SP0)
x-ms-return-client-request-id:
- 'true'
method: POST
uri: https://communicationegrcrs.communication.azure.com/identities?api-version=2020-07-20-preview2
response:
body:
string: '{"id": "sanitized"}'
headers:
api-supported-versions:
- 2020-01-15-preview3, 2020-07-20-preview1, 2020-07-20-preview2
content-type:
- application/json; charset=utf-8
date:
- Tue, 22 Dec 2020 18:29:12 GMT
ms-cv:
- UzbbWyNM6Ee4hx1Ym7MwSA.0
strict-transport-security:
- max-age=2592000
transfer-encoding:
- chunked
x-processing-time:
- 19ms
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '0'
Date:
- Tue, 22 Dec 2020 18:29:14 GMT
User-Agent:
- azsdk-python-communication-administration/1.0.0b4 Python/3.8.5 (Windows-10-10.0.19041-SP0)
x-ms-return-client-request-id:
- 'true'
method: DELETE
uri: https://communicationegrcrs.communication.azure.com/identities/sanitized?api-version=2020-07-20-preview2
response:
body:
string: ''
headers:
api-supported-versions:
- 2020-01-15-preview3, 2020-07-20-preview1, 2020-07-20-preview2
date:
- Tue, 22 Dec 2020 18:29:13 GMT
ms-cv:
- bD8oBIuNQEWXEaluFwupbA.0
strict-transport-security:
- max-age=2592000
x-processing-time:
- 764ms
status:
code: 204
message: No Content
version: 1
Loading