From 1f88855d5d0a8e504bc85c4ebaa21f912d6decbb Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 3 Feb 2021 13:20:16 -0500 Subject: [PATCH 01/13] trimming test case and testing live for replay processor --- .../tests/_shared/asynctestcase.py | 2 - .../tests/_shared/testcase.py | 80 +------------------ 2 files changed, 1 insertion(+), 81 deletions(-) diff --git a/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py b/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py index 69cd33157efe..764e859b104f 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py @@ -9,8 +9,6 @@ from .testcase import TableTestCase -LOGGING_FORMAT = '%(asctime)s %(name)-20s %(levelname)-5s %(message)s' - class AsyncFakeTokenCredential(object): """Protocol for classes able to provide OAuth tokens. :param str scopes: Lets you specify the type of access needed. diff --git a/sdk/tables/azure-data-tables/tests/_shared/testcase.py b/sdk/tables/azure-data-tables/tests/_shared/testcase.py index 16804952c029..f3115c3c53fd 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/testcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/testcase.py @@ -65,8 +65,7 @@ class TableTestCase(AzureTestCase): def __init__(self, *args, **kwargs): super(TableTestCase, self).__init__(*args, **kwargs) - self.replay_processors.append(XMSRequestIDBody()) - self._RESOURCE_GROUP = None, + # self.replay_processors.append(XMSRequestIDBody()) # this one might be needed, need to test in live setting def connection_string(self, account, key): return "DefaultEndpointsProtocol=https;AccountName=" + account + ";AccountKey=" + str(key) + ";EndpointSuffix=core.windows.net" @@ -90,87 +89,10 @@ def account_url(self, account, endpoint_type): if endpoint_type == "cosmos": return "https://{}.table.cosmos.azure.com".format(account) - - def configure_logging(self): - try: - enable_logging = self.get_settings_value("ENABLE_LOGGING") - except AzureTestError: - enable_logging = True # That's the default value in fake settings - - self.enable_logging() if enable_logging else self.disable_logging() - - def enable_logging(self): - handler = logging.StreamHandler() - handler.setFormatter(logging.Formatter(LOGGING_FORMAT)) - self.logger.handlers = [handler] - self.logger.setLevel(logging.INFO) - self.logger.propagate = True - self.logger.disabled = False - - def disable_logging(self): - self.logger.propagate = False - self.logger.disabled = True - self.logger.handlers = [] - def sleep(self, seconds): if self.is_live: time.sleep(seconds) - def get_random_bytes(self, size): - # recordings don't like random stuff. making this more - # deterministic. - return b'a'*size - - def get_random_text_data(self, size): - '''Returns random unicode text data exceeding the size threshold for - chunking blob upload.''' - checksum = zlib.adler32(self.qualified_test_name.encode()) & 0xffffffff - rand = random.Random(checksum) - text = u'' - words = [u'hello', u'world', u'python', u'啊齄丂狛狜'] - while (len(text) < size): - index = int(rand.random()*(len(words) - 1)) - text = text + u' ' + words[index] - - return text - - @staticmethod - def _set_test_proxy(service, settings): - if settings.USE_PROXY: - service.set_proxy( - settings.PROXY_HOST, - settings.PROXY_PORT, - settings.PROXY_USER, - settings.PROXY_PASSWORD, - ) - - def assertNamedItemInContainer(self, container, item_name, msg=None): - def _is_string(obj): - if sys.version_info >= (3,): - return isinstance(obj, str) - else: - return isinstance(obj, basestring) - for item in container: - if _is_string(item): - if item == item_name: - return - elif item.name == item_name: - return - elif hasattr(item, 'snapshot') and item.snapshot == item_name: - return - - - standardMsg = '{0} not found in {1}'.format( - repr(item_name), [str(c) for c in container]) - self.fail(self._formatMessage(msg, standardMsg)) - - def assertNamedItemNotInContainer(self, container, item_name, msg=None): - for item in container: - if item.name == item_name: - standardMsg = '{0} unexpectedly found in {1}'.format( - repr(item_name), repr(container)) - self.fail(self._formatMessage(msg, standardMsg)) - def generate_oauth_token(self): if self.is_live: from azure.identity import ClientSecretCredential From 7166468fa9627da08623c70009d0e12a88544fcb Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 3 Feb 2021 14:59:12 -0500 Subject: [PATCH 02/13] changed all the test imports, fixed the test_table.py file --- .../tests/_shared/testcase.py | 41 ++------- .../azure-data-tables/tests/test_table.py | 91 ++++++++++--------- .../tests/test_table_async.py | 4 +- .../tests/test_table_batch.py | 4 +- .../tests/test_table_batch_async.py | 4 +- .../tests/test_table_batch_cosmos.py | 4 +- .../tests/test_table_batch_cosmos_async.py | 4 +- .../tests/test_table_client.py | 4 +- .../tests/test_table_client_async.py | 4 +- .../tests/test_table_client_cosmos.py | 4 +- .../tests/test_table_client_cosmos_async.py | 4 +- .../tests/test_table_cosmos.py | 4 +- .../tests/test_table_cosmos_async.py | 4 +- .../tests/test_table_entity.py | 4 +- .../tests/test_table_entity_async.py | 4 +- .../tests/test_table_entity_cosmos.py | 4 +- .../tests/test_table_entity_cosmos_async.py | 4 +- .../tests/test_table_service_properties.py | 4 +- .../test_table_service_properties_async.py | 4 +- .../test_table_service_properties_cosmos.py | 4 +- ...t_table_service_properties_cosmos_async.py | 4 +- .../tests/test_table_service_stats.py | 4 +- .../tests/test_table_service_stats_async.py | 4 +- .../tests/test_table_service_stats_cosmos.py | 4 +- .../test_table_service_stats_cosmos_async.py | 4 +- 25 files changed, 125 insertions(+), 99 deletions(-) diff --git a/sdk/tables/azure-data-tables/tests/_shared/testcase.py b/sdk/tables/azure-data-tables/tests/_shared/testcase.py index f3115c3c53fd..07e860053e5d 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/testcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/testcase.py @@ -9,31 +9,21 @@ import os import time from datetime import datetime, timedelta - -import zlib -import sys import string import random -import re import logging -from devtools_testutils import AzureTestCase -from azure_devtools.scenario_tests import RecordingProcessor, AzureTestError -try: - from cStringIO import StringIO -except ImportError: - from io import StringIO - -from azure.core.credentials import AccessToken - -from azure.data.tables import generate_account_sas, AccountSasPermissions, ResourceTypes import pytest +from devtools_testutils import AzureTestCase +from azure.core.credentials import AccessToken +from azure.data.tables import generate_account_sas, AccountSasPermissions, ResourceTypes LOGGING_FORMAT = '%(asctime)s %(name)-20s %(levelname)-5s %(message)s' SLEEP_DELAY = 30 + class FakeTokenCredential(object): """Protocol for classes able to provide OAuth tokens. :param str scopes: Lets you specify the type of access needed. @@ -45,27 +35,10 @@ def get_token(self, *args): return self.token -class XMSRequestIDBody(RecordingProcessor): - """This process is used for Storage batch call only, to avoid the echo policy. - """ - def process_response(self, response): - content_type = None - for key, value in response.get('headers', {}).items(): - if key.lower() == 'content-type': - content_type = (value[0] if isinstance(value, list) else value).lower() - break - - if content_type and 'multipart/mixed' in content_type: - response['body']['string'] = re.sub(b"x-ms-client-request-id: [a-f0-9-]+\r\n", b"", response['body']['string']) - - return response - - -class TableTestCase(AzureTestCase): +class TableTestCase(object): - def __init__(self, *args, **kwargs): - super(TableTestCase, self).__init__(*args, **kwargs) - # self.replay_processors.append(XMSRequestIDBody()) # this one might be needed, need to test in live setting + # def __init__(self, *args, **kwargs): + # super(TableTestCase, self).__init__(*args, **kwargs) def connection_string(self, account, key): return "DefaultEndpointsProtocol=https;AccountName=" + account + ";AccountKey=" + str(key) + ";EndpointSuffix=core.windows.net" diff --git a/sdk/tables/azure-data-tables/tests/test_table.py b/sdk/tables/azure-data-tables/tests/test_table.py index 6cfee9a948fa..876c26e5a2c6 100644 --- a/sdk/tables/azure-data-tables/tests/test_table.py +++ b/sdk/tables/azure-data-tables/tests/test_table.py @@ -12,6 +12,8 @@ import os from datetime import datetime, timedelta +from devtools_testutils import AzureTestCase + from azure.data.tables import ( ResourceTypes, AccountSasPermissions, @@ -47,7 +49,10 @@ # ------------------------------------------------------------------------------ -class StorageTableTest(TableTestCase): +class StorageTableTest(AzureTestCase, TableTestCase): + + def __init__(self, *args, **kwargs): + super(StorageTableTest, self).__init__(*args, **kwargs) # --Helpers----------------------------------------------------------------- def _get_table_reference(self, prefix=TEST_TABLE_PREFIX): @@ -197,32 +202,6 @@ def test_create_table_if_exists_new_table(self, tables_storage_account_name, tab assert t.table_name == table_name ts.delete_table(table_name) - @TablesPreparer() - def test_create_table_invalid_name(self, tables_storage_account_name, tables_primary_storage_account_key): - # Arrange - account_url = self.account_url(tables_storage_account_name, "table") - ts = self.create_client_from_credential(TableServiceClient, tables_primary_storage_account_key, account_url=account_url) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - ts.create_table(table_name=invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - - @TablesPreparer() - def test_delete_table_invalid_name(self, tables_storage_account_name, tables_primary_storage_account_key): - # Arrange - account_url = self.account_url(tables_storage_account_name, "table") - ts = self.create_client_from_credential(TableServiceClient, tables_primary_storage_account_key, account_url=account_url) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - ts.create_table(invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - @TablesPreparer() def test_query_tables(self, tables_storage_account_name, tables_primary_storage_account_key): # Arrange @@ -354,21 +333,6 @@ def test_delete_table_with_non_existing_table_fail_not_exist(self, tables_storag with pytest.raises(HttpResponseError): ts.delete_table(table_name) - @TablesPreparer() - def test_unicode_create_table_unicode_name(self, tables_storage_account_name, tables_primary_storage_account_key): - # Arrange - account_url = self.account_url(tables_storage_account_name, "table") - ts = self.create_client_from_credential(TableServiceClient, tables_primary_storage_account_key, account_url=account_url) - - table_name = u'啊齄丂狛狜' - - # Act - with pytest.raises(ValueError) as excinfo: - ts.create_table(table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - @TablesPreparer() def test_get_table_acl(self, tables_storage_account_name, tables_primary_storage_account_key): # Arrange @@ -555,3 +519,46 @@ def test_locale(self, tables_storage_account_name, tables_primary_storage_accoun ts.delete_table(table) locale.setlocale(locale.LC_ALL, init_locale[0] or 'en_US') + + +class TestTablesUnitTest(TableTestCase): + tables_storage_account_name = "fake_storage_account" + tables_primary_storage_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" + + def test_unicode_create_table_unicode_name(self): + # Arrange + account_url = self.account_url(self.tables_storage_account_name, "table") + tsc = TableServiceClient(account_url, credential=self.tables_primary_storage_account_key) + + table_name = u'啊齄丂狛狜' + + # Act + with pytest.raises(ValueError) as excinfo: + tsc.create_table(table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + def test_create_table_invalid_name(self): + # Arrange + account_url = self.account_url(self.tables_storage_account_name, "table") + tsc = TableServiceClient(account_url, credential=self.tables_primary_storage_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + tsc.create_table(invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + def test_delete_table_invalid_name(self): + # Arrange + account_url = self.account_url(self.tables_storage_account_name, "table") + tsc = TableServiceClient(account_url, credential=self.tables_primary_storage_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + tsc.delete_table(invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) diff --git a/sdk/tables/azure-data-tables/tests/test_table_async.py b/sdk/tables/azure-data-tables/tests/test_table_async.py index 9b9cb9b45ce8..85a0b1ff74c7 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_async.py @@ -5,6 +5,8 @@ import pytest +from devtools_testutils import AzureTestCase + from azure.core.exceptions import ResourceNotFoundError, ResourceExistsError from azure.data.tables import ( AccessPolicy, @@ -24,7 +26,7 @@ # ------------------------------------------------------------------------------ -class TableTestAsync(AsyncTableTestCase): +class TableTestAsync(AzureTestCase, AsyncTableTestCase): # --Helpers----------------------------------------------------------------- def _get_table_reference(self, prefix=TEST_TABLE_PREFIX): table_name = self.get_resource_name(prefix) diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch.py b/sdk/tables/azure-data-tables/tests/test_table_batch.py index a27a0513c040..81ff90dc0938 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch.py @@ -13,6 +13,8 @@ import sys import uuid +from devtools_testutils import AzureTestCase + from azure.core import MatchConditions from azure.core.exceptions import ( ResourceExistsError, @@ -39,7 +41,7 @@ TEST_TABLE_PREFIX = 'table' #------------------------------------------------------------------------------ -class StorageTableBatchTest(TableTestCase): +class StorageTableBatchTest(AzureTestCase, TableTestCase): def _set_up(self, tables_storage_account_name, tables_primary_storage_account_key): self.ts = TableServiceClient(self.account_url(tables_storage_account_name, "table"), tables_primary_storage_account_key) diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_async.py b/sdk/tables/azure-data-tables/tests/test_table_batch_async.py index b6c0f426aa8e..784eb35062bd 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_async.py @@ -13,6 +13,8 @@ from dateutil.tz import tzutc import sys +from devtools_testutils import AzureTestCase + from azure.core import MatchConditions from azure.core.exceptions import ( ResourceExistsError, @@ -37,7 +39,7 @@ TEST_TABLE_PREFIX = 'table' #------------------------------------------------------------------------------ -class StorageTableBatchTest(TableTestCase): +class StorageTableBatchTest(AzureTestCase, TableTestCase): async def _set_up(self, tables_storage_account_name, tables_primary_storage_account_key): self.ts = TableServiceClient(self.account_url(tables_storage_account_name, "table"), tables_primary_storage_account_key) diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py index c8e83f68a422..7810a3fda236 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py @@ -13,6 +13,8 @@ import pytest +from devtools_testutils import AzureTestCase + from azure.core import MatchConditions from azure.core.exceptions import ( ResourceExistsError, @@ -39,7 +41,7 @@ TEST_TABLE_PREFIX = 'table' #------------------------------------------------------------------------------ -class StorageTableClientTest(TableTestCase): +class StorageTableClientTest(AzureTestCase, TableTestCase): def _set_up(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): self.ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py index d536b7b3fabf..135de95897f8 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py @@ -14,6 +14,8 @@ import pytest +from devtools_testutils import AzureTestCase + from azure.core import MatchConditions from azure.core.exceptions import ( ResourceExistsError, @@ -38,7 +40,7 @@ TEST_TABLE_PREFIX = 'table' #------------------------------------------------------------------------------ -class StorageTableBatchTest(TableTestCase): +class StorageTableBatchTest(AzureTestCase, TableTestCase): async def _set_up(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): self.ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) diff --git a/sdk/tables/azure-data-tables/tests/test_table_client.py b/sdk/tables/azure-data-tables/tests/test_table_client.py index 494ebde9547c..be7e28d2c4e7 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client.py @@ -6,6 +6,8 @@ import pytest import platform +from devtools_testutils import AzureTestCase + from azure.data.tables import TableServiceClient, TableClient from azure.data.tables._version import VERSION from azure.core.exceptions import HttpResponseError @@ -27,7 +29,7 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint', 'cosmos': 'TableSecondaryEndpoint'} -class StorageTableClientTest(TableTestCase): +class StorageTableClientTest(AzureTestCase, TableTestCase): def setUp(self): super(StorageTableClientTest, self).setUp() self.sas_token = self.generate_sas_token() diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_async.py b/sdk/tables/azure-data-tables/tests/test_table_client_async.py index 5317a776b6d0..89acb591c782 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_async.py @@ -6,6 +6,8 @@ import pytest import platform +from devtools_testutils import AzureTestCase + from azure.data.tables.aio import TableServiceClient, TableClient from azure.data.tables._version import VERSION @@ -22,7 +24,7 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint'} -class StorageTableClientTest(TableTestCase): +class StorageTableClientTest(AzureTestCase, TableTestCase): def setUp(self): super(StorageTableClientTest, self).setUp() self.sas_token = self.generate_sas_token() diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py index 968d0233fa3b..42ea214add6d 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py @@ -8,6 +8,8 @@ from time import sleep import sys +from devtools_testutils import AzureTestCase + from azure.data.tables import TableServiceClient, TableClient from azure.data.tables._version import VERSION @@ -27,7 +29,7 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint', 'cosmos': 'TableSecondaryEndpoint'} -class StorageTableClientTest(TableTestCase): +class StorageTableClientTest(AzureTestCase, TableTestCase): def setUp(self): super(StorageTableClientTest, self).setUp() self.sas_token = self.generate_sas_token() diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py index efe6f5a91cab..3470dc4bc019 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py @@ -7,6 +7,8 @@ import platform from time import sleep +from devtools_testutils import AzureTestCase + from azure.data.tables.aio import TableServiceClient, TableClient from azure.data.tables._version import VERSION @@ -28,7 +30,7 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint', 'cosmos': 'TableSecondaryEndpoint'} -class StorageTableClientTest(TableTestCase): +class StorageTableClientTest(AzureTestCase, TableTestCase): def setUp(self): super(StorageTableClientTest, self).setUp() self.sas_token = self.generate_sas_token() diff --git a/sdk/tables/azure-data-tables/tests/test_table_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_cosmos.py index 6867b6216b42..f3467cd73e2d 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_cosmos.py @@ -15,6 +15,8 @@ timedelta, ) +from devtools_testutils import AzureTestCase + from azure.core.exceptions import ( HttpResponseError, ResourceNotFoundError, @@ -48,7 +50,7 @@ TEST_TABLE_PREFIX = 'pytablesync' # ------------------------------------------------------------------------------ -class StorageTableTest(TableTestCase): +class StorageTableTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _get_table_reference(self, prefix=TEST_TABLE_PREFIX): diff --git a/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py index 65deccdc646e..b5134ff1be49 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py @@ -6,6 +6,8 @@ import pytest +from devtools_testutils import AzureTestCase + from azure.core.exceptions import ResourceNotFoundError, ResourceExistsError, HttpResponseError from _shared.asynctestcase import AsyncTableTestCase from _shared.testcase import SLEEP_DELAY @@ -25,7 +27,7 @@ # ------------------------------------------------------------------------------ -class TableTestAsync(AsyncTableTestCase): +class TableTestAsync(AzureTestCase, AsyncTableTestCase): # --Helpers----------------------------------------------------------------- def _get_table_reference(self, prefix=TEST_TABLE_PREFIX): table_name = self.get_resource_name(prefix) diff --git a/sdk/tables/azure-data-tables/tests/test_table_entity.py b/sdk/tables/azure-data-tables/tests/test_table_entity.py index 76b737eff18a..605960de62fb 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_entity.py +++ b/sdk/tables/azure-data-tables/tests/test_table_entity.py @@ -14,6 +14,8 @@ from math import isnan import uuid +from devtools_testutils import AzureTestCase + from azure.data.tables import ( TableServiceClient, TableClient, @@ -39,7 +41,7 @@ # ------------------------------------------------------------------------------ -class StorageTableEntityTest(TableTestCase): +class StorageTableEntityTest(AzureTestCase, TableTestCase): def _set_up(self, tables_storage_account_name, tables_primary_storage_account_key, url='table'): self.table_name = self.get_resource_name('uttable') diff --git a/sdk/tables/azure-data-tables/tests/test_table_entity_async.py b/sdk/tables/azure-data-tables/tests/test_table_entity_async.py index 726c74c32cff..56250952d724 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_entity_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_entity_async.py @@ -13,6 +13,8 @@ from math import isnan import uuid +from devtools_testutils import AzureTestCase + from azure.core import MatchConditions from azure.core.exceptions import ( HttpResponseError, @@ -30,7 +32,7 @@ # TODO: change to `with table_client as client:` to close sessions # ------------------------------------------------------------------------------ -class StorageTableEntityTest(TableTestCase): +class StorageTableEntityTest(AzureTestCase, TableTestCase): async def _set_up(self, tables_storage_account_name, tables_primary_storage_account_key): account_url = self.account_url(tables_storage_account_name, "table") diff --git a/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos.py index dfc35086202c..18091aa04b14 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos.py @@ -15,6 +15,8 @@ from time import sleep import uuid +from devtools_testutils import AzureTestCase + from azure.core import MatchConditions from azure.core.exceptions import ( HttpResponseError, @@ -38,7 +40,7 @@ # ------------------------------------------------------------------------------ -class StorageTableEntityTest(TableTestCase): +class StorageTableEntityTest(AzureTestCase, TableTestCase): def _set_up(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): self.ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) diff --git a/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py index e6f49b7fc79d..0a04b5b15f7c 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py @@ -15,6 +15,8 @@ from time import sleep import uuid +from devtools_testutils import AzureTestCase + from azure.data.tables import ( generate_table_sas, TableEntity, @@ -39,7 +41,7 @@ # TODO: change to `with table_client as client:` to close sessions # ------------------------------------------------------------------------------ -class StorageTableEntityTest(TableTestCase): +class StorageTableEntityTest(AzureTestCase, TableTestCase): async def _set_up(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): account_url = self.account_url(tables_cosmos_account_name, "cosmos") diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties.py index 595f1e307291..c5cd1a828f04 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties.py @@ -8,6 +8,8 @@ import time import pytest +from devtools_testutils import AzureTestCase + from azure.data.tables import TableServiceClient from azure.data.tables._models import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule from azure.core.exceptions import HttpResponseError @@ -18,7 +20,7 @@ # ------------------------------------------------------------------------------ -class TableServicePropertiesTest(TableTestCase): +class TableServicePropertiesTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_properties_default(self, prop): assert prop is not None diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py index ec6d8ae927c3..a25f896a43b4 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py @@ -8,6 +8,8 @@ import time import pytest +from devtools_testutils import AzureTestCase + from azure.core.exceptions import HttpResponseError from azure.data.tables._models import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule @@ -19,7 +21,7 @@ # ------------------------------------------------------------------------------ -class TableServicePropertiesTest(TableTestCase): +class TableServicePropertiesTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_properties_default(self, prop): assert prop is not None diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py index e807a813f894..d4076febd771 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py @@ -8,6 +8,8 @@ import time import pytest +from devtools_testutils import AzureTestCase + from azure.core.exceptions import HttpResponseError from azure.data.tables import TableServiceClient @@ -17,7 +19,7 @@ from preparers import CosmosPreparer # ------------------------------------------------------------------------------ -class TableServicePropertiesTest(TableTestCase): +class TableServicePropertiesTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_properties_default(self, prop): assert prop is not None diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py index 0c66f575ad39..82face1012d9 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py @@ -8,6 +8,8 @@ import pytest from time import sleep +from devtools_testutils import AzureTestCase + from azure.data.tables._models import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule from azure.data.tables.aio import TableServiceClient from azure.core.exceptions import HttpResponseError @@ -16,7 +18,7 @@ from preparers import CosmosPreparer # ------------------------------------------------------------------------------ -class TableServicePropertiesTest(TableTestCase): +class TableServicePropertiesTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_properties_default(self, prop): assert prop is not None diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_stats.py b/sdk/tables/azure-data-tables/tests/test_table_service_stats.py index 5fc48d82c3ee..765d9ad6ff10 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_stats.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_stats.py @@ -5,6 +5,8 @@ # -------------------------------------------------------------------------- import pytest +from devtools_testutils import AzureTestCase + from azure.data.tables import TableServiceClient from _shared.testcase import TableTestCase from preparers import TablesPreparer @@ -18,7 +20,7 @@ '> ' # --Test Class ----------------------------------------------------------------- -class TableServiceStatsTest(TableTestCase): +class TableServiceStatsTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_stats_default(self, stats): assert stats is not None diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py index d0f0e74d6fe8..b73dd4645a59 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py @@ -5,6 +5,8 @@ # -------------------------------------------------------------------------- import pytest +from devtools_testutils import AzureTestCase + from azure.data.tables.aio import TableServiceClient from _shared.testcase import TableTestCase @@ -20,7 +22,7 @@ # --Test Class ----------------------------------------------------------------- -class TableServiceStatsTest(TableTestCase): +class TableServiceStatsTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_stats_default(self, stats): assert stats is not None diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos.py index 6c1d35e02663..d8ea51d41044 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos.py @@ -6,6 +6,8 @@ import pytest from time import sleep +from devtools_testutils import AzureTestCase + from azure.data.tables import TableServiceClient from _shared.testcase import TableTestCase, SLEEP_DELAY from preparers import CosmosPreparer @@ -20,7 +22,7 @@ # --Test Class ----------------------------------------------------------------- -class TableServiceStatsTest(TableTestCase): +class TableServiceStatsTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_stats_default(self, stats): assert stats is not None diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos_async.py index f4089fad3f4d..7cb4238b5e02 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_stats_cosmos_async.py @@ -5,6 +5,8 @@ # -------------------------------------------------------------------------- import pytest +from devtools_testutils import AzureTestCase + from azure.data.tables.aio import TableServiceClient from _shared.testcase import TableTestCase, SLEEP_DELAY @@ -19,7 +21,7 @@ '> ' # --Test Class ----------------------------------------------------------------- -class TableServiceStatsTest(TableTestCase): +class TableServiceStatsTest(AzureTestCase, TableTestCase): # --Helpers----------------------------------------------------------------- def _assert_stats_default(self, stats): assert stats is not None From 4ab65d02a91548d67cc1c25565a0e77178f45051 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 3 Feb 2021 16:37:34 -0500 Subject: [PATCH 03/13] everything up through client_cosmos.py is split correctly now --- ...t_table_client.test_response_callback.yaml | 39 -- ...ient.test_service_client_create_table.yaml | 101 ---- ...t_table_client.test_user_agent_custom.yaml | 20 +- ..._table_client.test_user_agent_default.yaml | 10 +- ..._client_cosmos.test_user_agent_custom.yaml | 49 +- ...client_cosmos.test_user_agent_default.yaml | 10 +- .../tests/test_table_async.py | 87 ++-- .../tests/test_table_batch.py | 53 +- .../tests/test_table_batch_async.py | 41 -- .../tests/test_table_batch_cosmos.py | 48 -- .../tests/test_table_batch_cosmos_async.py | 23 - .../tests/test_table_client.py | 387 +++++++-------- .../tests/test_table_client_async.py | 381 +++++++-------- .../tests/test_table_client_cosmos.py | 459 ++++++++---------- 14 files changed, 722 insertions(+), 986 deletions(-) delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_response_callback.yaml delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_service_client_create_table.yaml diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_response_callback.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_response_callback.yaml deleted file mode 100644 index fd9bd5a4d21e..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_response_callback.yaml +++ /dev/null @@ -1,39 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/xml - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Date: - - Wed, 01 Jul 2020 18:18:37 GMT - User-Agent: - - azsdk-python-storage-table/2019-07-07 Python/3.8.3 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Wed, 01 Jul 2020 18:18:37 GMT - x-ms-version: - - '2019-07-07' - method: GET - uri: https://storagename.table.core.windows.net/?restype=service&comp=properties - response: - body: - string: "\uFEFF1.0falsefalsefalsefalse1.0truetruetrue71.0falsefalse" - headers: - content-type: - - application/xml - date: - - Wed, 01 Jul 2020 18:18:35 GMT - server: - - Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 - transfer-encoding: - - chunked - x-ms-version: - - '2019-07-07' - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_service_client_create_table.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_service_client_create_table.yaml deleted file mode 100644 index 2f34fe002e7a..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_service_client_create_table.yaml +++ /dev/null @@ -1,101 +0,0 @@ -interactions: -- request: - body: '{"TableName": "foo"}' - headers: - Accept: - - application/json;odata=minimalmetadata - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '20' - Content-Type: - - application/json;odata=nometadata - DataServiceVersion: - - '3.0' - Date: - - Tue, 25 Aug 2020 20:12:58 GMT - User-Agent: - - azsdk-python-data-tables/2019-07-07 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Tue, 25 Aug 2020 20:12:58 GMT - x-ms-version: - - '2019-07-07' - method: POST - uri: https://storagename.table.core.windows.net/Tables - response: - body: - string: '{"odata.metadata":"https://storagename.table.core.windows.net/$metadata#Tables/@Element","TableName":"foo"}' - headers: - cache-control: - - no-cache - content-type: - - application/json;odata=minimalmetadata;streaming=true;charset=utf-8 - date: - - Tue, 25 Aug 2020 20:12:59 GMT - location: - - https://storagename.table.core.windows.net/Tables('foo') - server: - - Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 - transfer-encoding: - - chunked - x-content-type-options: - - nosniff - x-ms-version: - - '2019-07-07' - status: - code: 201 - message: Created -- request: - body: '{"PartitionKey": "pk", "RowKey": "rk", "Value": "2", "Value@odata.type": - "Edm.Int64"}' - headers: - Accept: - - application/json;odata=minimalmetadata - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '85' - Content-Type: - - application/json;odata=nometadata - DataServiceVersion: - - '3.0' - Date: - - Tue, 25 Aug 2020 20:12:59 GMT - User-Agent: - - azsdk-python-data-tables/2019-07-07 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Tue, 25 Aug 2020 20:12:59 GMT - x-ms-version: - - '2019-07-07' - method: POST - uri: https://storagename.table.core.windows.net/foo - response: - body: - string: '{"odata.metadata":"https://storagename.table.core.windows.net/$metadata#foo/@Element","odata.etag":"W/\"datetime''2020-08-25T20%3A12%3A59.6939685Z''\"","PartitionKey":"pk","RowKey":"rk","Timestamp":"2020-08-25T20:12:59.6939685Z","Value@odata.type":"Edm.Int64","Value":"2"}' - headers: - cache-control: - - no-cache - content-type: - - application/json;odata=minimalmetadata;streaming=true;charset=utf-8 - date: - - Tue, 25 Aug 2020 20:12:59 GMT - etag: - - W/"datetime'2020-08-25T20%3A12%3A59.6939685Z'" - location: - - https://storagename.table.core.windows.net/foo(PartitionKey='pk',RowKey='rk') - server: - - Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 - transfer-encoding: - - chunked - x-content-type-options: - - nosniff - x-ms-version: - - '2019-07-07' - status: - code: 201 - message: Created -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_custom.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_custom.yaml index a132cdfc1ba4..052b07dc743b 100644 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_custom.yaml +++ b/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_custom.yaml @@ -11,25 +11,25 @@ interactions: DataServiceVersion: - '3.0' Date: - - Fri, 18 Dec 2020 17:08:50 GMT + - Wed, 03 Feb 2021 20:56:20 GMT User-Agent: - - TestApp/v1.0 azsdk-python-data-tables/12.0.0b4 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + - TestApp/v1.0 azsdk-python-data-tables/12.0.0b5 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) x-ms-date: - - Fri, 18 Dec 2020 17:08:50 GMT + - Wed, 03 Feb 2021 20:56:20 GMT x-ms-version: - '2019-02-02' method: GET uri: https://fake_table_account.table.core.windows.net/Tables response: body: - string: '{"odata.metadata":"https://fake_table_account.table.core.windows.net/$metadata#Tables","value":[{"TableName":"listtable0cac14c3"},{"TableName":"listtable1cac14c3"},{"TableName":"listtable2cac14c3"},{"TableName":"listtable3cac14c3"}]}' + string: '{"odata.metadata":"https://fake_table_account.table.core.windows.net/$metadata#Tables","value":[]}' headers: cache-control: - no-cache content-type: - application/json;odata=minimalmetadata;streaming=true;charset=utf-8 date: - - Fri, 18 Dec 2020 17:08:50 GMT + - Wed, 03 Feb 2021 20:56:20 GMT server: - Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 transfer-encoding: @@ -53,26 +53,26 @@ interactions: DataServiceVersion: - '3.0' Date: - - Fri, 18 Dec 2020 17:08:51 GMT + - Wed, 03 Feb 2021 20:56:21 GMT User-Agent: - - TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/12.0.0b4 Python/3.9.0rc1 + - TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/12.0.0b5 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) x-ms-date: - - Fri, 18 Dec 2020 17:08:51 GMT + - Wed, 03 Feb 2021 20:56:21 GMT x-ms-version: - '2019-02-02' method: GET uri: https://fake_table_account.table.core.windows.net/Tables response: body: - string: '{"odata.metadata":"https://fake_table_account.table.core.windows.net/$metadata#Tables","value":[{"TableName":"listtable0cac14c3"},{"TableName":"listtable1cac14c3"},{"TableName":"listtable2cac14c3"},{"TableName":"listtable3cac14c3"}]}' + string: '{"odata.metadata":"https://fake_table_account.table.core.windows.net/$metadata#Tables","value":[]}' headers: cache-control: - no-cache content-type: - application/json;odata=minimalmetadata;streaming=true;charset=utf-8 date: - - Fri, 18 Dec 2020 17:08:51 GMT + - Wed, 03 Feb 2021 20:56:20 GMT server: - Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 transfer-encoding: diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_default.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_default.yaml index 1379bcf2cbe0..9ba5e2cece5b 100644 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_default.yaml +++ b/sdk/tables/azure-data-tables/tests/recordings/test_table_client.test_user_agent_default.yaml @@ -11,25 +11,25 @@ interactions: DataServiceVersion: - '3.0' Date: - - Fri, 18 Dec 2020 17:08:51 GMT + - Wed, 03 Feb 2021 20:56:21 GMT User-Agent: - - azsdk-python-data-tables/12.0.0b4 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + - azsdk-python-data-tables/12.0.0b5 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) x-ms-date: - - Fri, 18 Dec 2020 17:08:51 GMT + - Wed, 03 Feb 2021 20:56:21 GMT x-ms-version: - '2019-02-02' method: GET uri: https://fake_table_account.table.core.windows.net/Tables response: body: - string: '{"odata.metadata":"https://fake_table_account.table.core.windows.net/$metadata#Tables","value":[{"TableName":"listtable0cac14c3"},{"TableName":"listtable1cac14c3"},{"TableName":"listtable2cac14c3"},{"TableName":"listtable3cac14c3"}]}' + string: '{"odata.metadata":"https://fake_table_account.table.core.windows.net/$metadata#Tables","value":[]}' headers: cache-control: - no-cache content-type: - application/json;odata=minimalmetadata;streaming=true;charset=utf-8 date: - - Fri, 18 Dec 2020 17:08:51 GMT + - Wed, 03 Feb 2021 20:56:21 GMT server: - Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 transfer-encoding: diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_custom.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_custom.yaml index 1a7df4ec0508..6c7412bda73c 100644 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_custom.yaml +++ b/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_custom.yaml @@ -11,23 +11,60 @@ interactions: DataServiceVersion: - '3.0' Date: - - Fri, 30 Oct 2020 21:53:05 GMT + - Wed, 03 Feb 2021 21:17:55 GMT User-Agent: - - TestApp/v1.0 azsdk-python-data-tables/12.0.0b3 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + - TestApp/v1.0 azsdk-python-data-tables/12.0.0b5 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) x-ms-date: - - Fri, 30 Oct 2020 21:53:05 GMT + - Wed, 03 Feb 2021 21:17:55 GMT x-ms-version: - '2019-02-02' method: GET - uri: https://tablestestcosmosname.table.cosmos.azure.com/Tables + uri: https://fake_cosmos_account.table.cosmos.azure.com/Tables response: body: - string: '' + string: '{"value":[],"odata.metadata":"https://fake_cosmos_account.table.cosmos.azure.com/$metadata#Tables"}' headers: content-type: - application/json;odata=minimalmetadata date: - - Fri, 30 Oct 2020 21:53:06 GMT + - Wed, 03 Feb 2021 21:17:56 GMT + server: + - Microsoft-HTTPAPI/2.0 + transfer-encoding: + - chunked + status: + code: 200 + message: Ok +- request: + body: null + headers: + Accept: + - application/json;odata=minimalmetadata + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + DataServiceVersion: + - '3.0' + Date: + - Wed, 03 Feb 2021 21:17:56 GMT + User-Agent: + - TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/12.0.0b5 Python/3.9.0rc1 + (Windows-10-10.0.19041-SP0) + x-ms-date: + - Wed, 03 Feb 2021 21:17:56 GMT + x-ms-version: + - '2019-02-02' + method: GET + uri: https://fake_cosmos_account.table.cosmos.azure.com/Tables + response: + body: + string: '{"value":[],"odata.metadata":"https://fake_cosmos_account.table.cosmos.azure.com/$metadata#Tables"}' + headers: + content-type: + - application/json;odata=minimalmetadata + date: + - Wed, 03 Feb 2021 21:17:56 GMT server: - Microsoft-HTTPAPI/2.0 transfer-encoding: diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_default.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_default.yaml index 744f0388ee69..14fe819fa136 100644 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_default.yaml +++ b/sdk/tables/azure-data-tables/tests/recordings/test_table_client_cosmos.test_user_agent_default.yaml @@ -11,23 +11,23 @@ interactions: DataServiceVersion: - '3.0' Date: - - Tue, 22 Dec 2020 18:45:42 GMT + - Wed, 03 Feb 2021 21:18:26 GMT User-Agent: - - azsdk-python-data-tables/12.0.0b4 Python/2.7.18 (Windows-10-10.0.19041) + - azsdk-python-data-tables/12.0.0b5 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) x-ms-date: - - Tue, 22 Dec 2020 18:45:42 GMT + - Wed, 03 Feb 2021 21:18:26 GMT x-ms-version: - '2019-02-02' method: GET uri: https://fake_cosmos_account.table.cosmos.azure.com/Tables response: body: - string: !!python/unicode '{"value":[],"odata.metadata":"https://fake_cosmos_account.table.cosmos.azure.com/$metadata#Tables"}' + string: '{"value":[],"odata.metadata":"https://fake_cosmos_account.table.cosmos.azure.com/$metadata#Tables"}' headers: content-type: - application/json;odata=minimalmetadata date: - - Tue, 22 Dec 2020 18:45:41 GMT + - Wed, 03 Feb 2021 21:18:27 GMT server: - Microsoft-HTTPAPI/2.0 transfer-encoding: diff --git a/sdk/tables/azure-data-tables/tests/test_table_async.py b/sdk/tables/azure-data-tables/tests/test_table_async.py index 85a0b1ff74c7..da04970556cb 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_async.py @@ -114,32 +114,6 @@ async def test_query_tables_per_page(self, tables_storage_account_name, tables_p for i in range(5): await ts.delete_table(table_name + str(i)) - @TablesPreparer() - async def test_create_table_invalid_name(self, tables_storage_account_name, tables_primary_storage_account_key): - # Arrange - account_url = self.account_url(tables_storage_account_name, "table") - ts = self.create_client_from_credential(TableServiceClient, tables_primary_storage_account_key, account_url=account_url) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - await ts.create_table(table_name=invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - - @TablesPreparer() - async def test_delete_table_invalid_name(self, tables_storage_account_name, tables_primary_storage_account_key): - # Arrange - account_url = self.account_url(tables_storage_account_name, "table") - ts = self.create_client_from_credential(TableServiceClient, tables_primary_storage_account_key, account_url=account_url) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - await ts.create_table(invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - @TablesPreparer() async def test_list_tables(self, tables_storage_account_name, tables_primary_storage_account_key): # Arrange @@ -273,21 +247,6 @@ async def test_delete_table_with_non_existing_table_fail_not_exist(self, tables_ # Assert - @TablesPreparer() - async def test_unicode_create_table_unicode_name(self, tables_storage_account_name, tables_primary_storage_account_key): - # Arrange - account_url = self.account_url(tables_storage_account_name, "table") - ts = self.create_client_from_credential(TableServiceClient, tables_primary_storage_account_key, account_url=account_url) - - table_name = u'啊齄丂狛狜' - - # Act - with pytest.raises(ValueError) as excinfo: - await ts.create_table(table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - @TablesPreparer() async def test_get_table_acl(self, tables_storage_account_name, tables_primary_storage_account_key): # Arrange @@ -463,3 +422,49 @@ async def test_locale(self, tables_storage_account_name, tables_primary_storage_ await ts.delete_table(table) locale.setlocale(locale.LC_ALL, init_locale[0] or 'en_US') + + +class TestTablesUnitTest(AsyncTableTestCase): + tables_storage_account_name = "fake_storage_account" + tables_primary_storage_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" + + @pytest.mark.asyncio + async def test_unicode_create_table_unicode_name(self): + # Arrange + account_url = self.account_url(self.tables_storage_account_name, "table") + tsc = TableServiceClient(account_url, credential=self.tables_primary_storage_account_key) + + table_name = u'啊齄丂狛狜' + + # Act + with pytest.raises(ValueError) as excinfo: + await tsc.create_table(table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + @pytest.mark.asyncio + async def test_create_table_invalid_name(self): + # Arrange + account_url = self.account_url(self.tables_storage_account_name, "table") + tsc = TableServiceClient(account_url, credential=self.tables_primary_storage_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + await tsc.create_table(table_name=invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + @pytest.mark.asyncio + async def test_delete_table_invalid_name(self): + # Arrange + account_url = self.account_url(self.tables_storage_account_name, "table") + tsc = TableServiceClient(account_url, credential=self.tables_primary_storage_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + await tsc.create_table(invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch.py b/sdk/tables/azure-data-tables/tests/test_table_batch.py index 81ff90dc0938..87dba13a1a81 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch.py @@ -171,31 +171,6 @@ def _assert_valid_batch_transaction(self, transaction, length): assert length == len(transaction.results) assert length == len(transaction.requests) - #--Test cases for batch --------------------------------------------- - def test_inferred_types(self): - # Arrange - # Act - entity = TableEntity() - entity.PartitionKey = '003' - entity.RowKey = 'batch_all_operations_together-1' - entity.test = EntityProperty(True) - entity.test2 = EntityProperty(b'abcdef') - entity.test3 = EntityProperty(u'c9da6455-213d-42c9-9a79-3e9149a57833') - entity.test4 = EntityProperty(datetime(1973, 10, 4, tzinfo=tzutc())) - entity.test5 = EntityProperty(u"stringystring") - entity.test6 = EntityProperty(3.14159) - entity.test7 = EntityProperty(100) - entity.test8 = EntityProperty(2 ** 33, EdmType.INT64) - - # Assert - assert entity.test.type == EdmType.BOOLEAN - assert entity.test2.type == EdmType.BINARY - assert entity.test3.type == EdmType.GUID - assert entity.test4.type == EdmType.DATETIME - assert entity.test5.type == EdmType.STRING - assert entity.test6.type == EdmType.DOUBLE - assert entity.test7.type == EdmType.INT32 - assert entity.test8.type == EdmType.INT64 @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3") @TablesPreparer() @@ -875,3 +850,31 @@ def test_new_delete_nonexistent_entity(self, tables_storage_account_name, tables finally: self._tear_down() + +class TestTableUnitTest(TableTestCase): + + #--Test cases for batch --------------------------------------------- + def test_inferred_types(self): + # Arrange + # Act + entity = TableEntity() + entity.PartitionKey = '003' + entity.RowKey = 'batch_all_operations_together-1' + entity.test = EntityProperty(True) + entity.test2 = EntityProperty(b'abcdef') + entity.test3 = EntityProperty(u'c9da6455-213d-42c9-9a79-3e9149a57833') + entity.test4 = EntityProperty(datetime(1973, 10, 4, tzinfo=tzutc())) + entity.test5 = EntityProperty(u"stringystring") + entity.test6 = EntityProperty(3.14159) + entity.test7 = EntityProperty(100) + entity.test8 = EntityProperty(2 ** 33, EdmType.INT64) + + # Assert + assert entity.test.type == EdmType.BOOLEAN + assert entity.test2.type == EdmType.BINARY + assert entity.test3.type == EdmType.GUID + assert entity.test4.type == EdmType.DATETIME + assert entity.test5.type == EdmType.STRING + assert entity.test6.type == EdmType.DOUBLE + assert entity.test7.type == EdmType.INT32 + assert entity.test8.type == EdmType.INT64 \ No newline at end of file diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_async.py b/sdk/tables/azure-data-tables/tests/test_table_batch_async.py index 784eb35062bd..65355024a859 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_async.py @@ -632,47 +632,6 @@ async def test_batch_all_operations_together_context_manager(self, tables_storag finally: await self._tear_down() - @pytest.mark.skip("Not sure this is how the batching should operate, will consult w/ Anna") - @TablesPreparer() - async def test_batch_reuse(self, tables_storage_account_name, tables_primary_storage_account_key): - # Arrange - await self._set_up(tables_storage_account_name, tables_primary_storage_account_key) - try: - table2 = self._get_table_reference('table2') - table2.create_table() - - # Act - entity = TableEntity() - entity.PartitionKey = '003' - entity.RowKey = 'batch_all_operations_together-1' - entity.test = EntityProperty(True) - entity.test2 = 'value' - entity.test3 = 3 - entity.test4 = EntityProperty(1234567890) - entity.test5 = datetime.utcnow() - - batch = self.table.create_batch() - batch.create_entity(entity) - entity.RowKey = 'batch_all_operations_together-2' - batch.create_entity(entity) - entity.RowKey = 'batch_all_operations_together-3' - batch.create_entity(entity) - entity.RowKey = 'batch_all_operations_together-4' - batch.create_entity(entity) - - await self.table.send_batch(batch) - with pytest.raises(HttpResponseError): - resp = await table2.send_batch(batch) - - # Assert - entities = self.table.query_entities("PartitionKey eq '003'") - length = 0 - async for e in entities: - length += 1 - assert 5 == length - finally: - await self._tear_down() - # @pytest.mark.skip("This does not throw an error, but it should") @TablesPreparer() async def test_batch_same_row_operations_fail(self, tables_storage_account_name, tables_primary_storage_account_key): diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py index 7810a3fda236..e7ebc9341b67 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos.py @@ -157,32 +157,6 @@ def _assert_updated_entity(self, entity): assert entity['_metadata']['etag'] is not None #--Test cases for batch --------------------------------------------- - - def test_inferred_types(self): - # Arrange - # Act - entity = TableEntity() - entity.PartitionKey = '003' - entity.RowKey = 'batch_all_operations_together-1' - entity.test = EntityProperty(True) - entity.test2 = EntityProperty(b'abcdef') - entity.test3 = EntityProperty(u'c9da6455-213d-42c9-9a79-3e9149a57833') - entity.test4 = EntityProperty(datetime(1973, 10, 4, tzinfo=tzutc())) - entity.test5 = EntityProperty(u"stringystring") - entity.test6 = EntityProperty(3.14159) - entity.test7 = EntityProperty(100) - entity.test8 = EntityProperty(10, EdmType.INT64) - - # Assert - assert entity.test.type == EdmType.BOOLEAN - assert entity.test2.type == EdmType.BINARY - assert entity.test3.type == EdmType.GUID - assert entity.test4.type == EdmType.DATETIME - assert entity.test5.type == EdmType.STRING - assert entity.test6.type == EdmType.DOUBLE - assert entity.test7.type == EdmType.INT32 - assert entity.test8.type == EdmType.INT64 - def _assert_valid_batch_transaction(self, transaction, length): assert isinstance(transaction, BatchTransactionResult) assert length == len(transaction.entities) @@ -665,28 +639,6 @@ def test_new_non_existent_table(self, tables_cosmos_account_name, tables_primary finally: self._tear_down() - @pytest.mark.skip("Cannot fake cosmos credential") - @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3") - @CosmosPreparer() - def test_new_invalid_key(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Arrange - invalid_key = tables_primary_cosmos_account_key[0:-6] + "==" # cut off a bit from the end to invalidate - key_list = list(tables_primary_cosmos_account_key) - - key_list[-6:] = list("0000==") - invalid_key = ''.join(key_list) - - self.ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "table"), invalid_key) - self.table_name = self.get_resource_name('uttable') - self.table = self.ts.get_table_client(self.table_name) - - entity = self._create_random_entity_dict('001', 'batch_negative_1') - - batch = self.table.create_batch() - batch.create_entity(entity) - - with pytest.raises(ClientAuthenticationError): - resp = self.table.send_batch(batch) @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3") @CosmosPreparer() diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py index 135de95897f8..7e45abc9c66a 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py @@ -732,29 +732,6 @@ async def test_new_non_existent_table(self, tables_cosmos_account_name, tables_p finally: await self._tear_down() - @pytest.mark.skip("Cannot fake cosmos credential") - @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3") - @CosmosPreparer() - async def test_new_invalid_key(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Arrange - invalid_key = tables_primary_cosmos_account_key[0:-6] + "==" # cut off a bit from the end to invalidate - key_list = list(tables_primary_cosmos_account_key) - - key_list[-6:] = list("0000==") - invalid_key = ''.join(key_list) - - self.ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "table"), invalid_key) - self.table_name = self.get_resource_name('uttable') - self.table = self.ts.get_table_client(self.table_name) - - entity = self._create_random_entity_dict('001', 'batch_negative_1') - - batch = self.table.create_batch() - batch.create_entity(entity) - - with pytest.raises(ClientAuthenticationError): - resp = await self.table.send_batch(batch) - @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3") @CosmosPreparer() async def test_new_delete_nonexistent_entity(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): diff --git a/sdk/tables/azure-data-tables/tests/test_table_client.py b/sdk/tables/azure-data-tables/tests/test_table_client.py index be7e28d2c4e7..f4d9dc2ef51b 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client.py @@ -29,11 +29,66 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint', 'cosmos': 'TableSecondaryEndpoint'} -class StorageTableClientTest(AzureTestCase, TableTestCase): - def setUp(self): - super(StorageTableClientTest, self).setUp() - self.sas_token = self.generate_sas_token() - self.token_credential = self.generate_oauth_token() +class TestTableClient(AzureTestCase, TableTestCase): + + @TablesPreparer() + def test_user_agent_custom(self, tables_storage_account_name, tables_primary_storage_account_key): + custom_app = "TestApp/v1.0" + service = TableServiceClient( + self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, user_agent=custom_app) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = list(service.list_tables(raw_response_hook=callback)) + assert isinstance(tables, list) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = list(service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0")) + assert isinstance(tables, list) + + @TablesPreparer() + def test_user_agent_append(self, tables_storage_account_name, tables_primary_storage_account_key): + service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert response.http_request.headers['User-Agent'] == "azsdk-python-data-tables/{} Python/{} ({}) customer_user_agent".format( + VERSION, + platform.python_version(), + platform.platform()) + + custom_headers = {'User-Agent': 'customer_user_agent'} + tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) + + @TablesPreparer() + def test_user_agent_default(self, tables_storage_account_name, tables_primary_storage_account_key): + service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = list(service.list_tables(raw_response_hook=callback)) + assert isinstance(tables, list) + + +class TestTableUnitTests(TableTestCase): + tables_storage_account_name = "fake_storage_account" + tables_primary_storage_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, account_name, account_key): @@ -44,104 +99,74 @@ def validate_standard_account_endpoints(self, service, account_name, account_key assert ('{}.{}'.format(account_name, 'table.core.windows.net') in service.url) or ('{}.{}'.format(account_name, 'table.cosmos.azure.com') in service.url) # --Direct Parameters Test Cases -------------------------------------------- - @TablesPreparer() - def test_create_service_with_key(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_key(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_storage_account_name, url), credential=tables_primary_storage_account_key, table_name='foo') + self.account_url(self.tables_storage_account_name, url), credential=self.tables_primary_storage_account_key, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'https' - @TablesPreparer() - def test_create_service_with_connection_string(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_connection_string(self): for service_type in SERVICES.items(): # Act service = service_type[0].from_connection_string( - self.connection_string(tables_storage_account_name, tables_primary_storage_account_key), table_name="test") + self.connection_string(self.tables_storage_account_name, self.tables_primary_storage_account_key), table_name="test") # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'https' - @TablesPreparer() - def test_create_service_with_sas(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_sas(self): # Arrange - url = self.account_url(tables_storage_account_name, "table") + url = self.account_url(self.tables_storage_account_name, "table") suffix = '.table.core.windows.net' for service_type in SERVICES: # Act service = service_type( - self.account_url(tables_storage_account_name, "table"), credential=self.sas_token, table_name='foo') + self.account_url(self.tables_storage_account_name, "table"), credential=self.generate_sas_token(), table_name='foo') # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + suffix) - assert service.url.endswith(self.sas_token) + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + suffix) + assert service.url.endswith(self.generate_sas_token()) assert service.credential is None - @TablesPreparer() - def test_create_service_with_token(self, tables_storage_account_name, tables_primary_storage_account_key): - url = self.account_url(tables_storage_account_name, "table") - suffix = '.table.core.windows.net' - for service_type in SERVICES: - # Act - service = service_type(url, credential=self.token_credential, table_name='foo') - - # Assert - assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + suffix) - assert service.credential == self.token_credential - assert not hasattr(service.credential, 'account_key') - assert hasattr(service.credential, 'get_token') - - @TablesPreparer() - def test_create_service_with_token_and_http(self, tables_storage_account_name, tables_primary_storage_account_key): - for service_type in SERVICES: - # Act - with pytest.raises(ValueError): - url = self.account_url(tables_storage_account_name, "table").replace('https', 'http') - service_type(url, credential=self.token_credential, table_name='foo') - - @TablesPreparer() - def test_create_service_china(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_china(self): # Arrange for service_type in SERVICES.items(): # Act - url = self.account_url(tables_storage_account_name, "table").replace('core.windows.net', 'core.chinacloudapi.cn') + url = self.account_url(self.tables_storage_account_name, "table").replace('core.windows.net', 'core.chinacloudapi.cn') service = service_type[0]( - url, credential=tables_primary_storage_account_key, table_name='foo') + url, credential=self.tables_primary_storage_account_key, table_name='foo') # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key - assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(tables_storage_account_name, "table")) + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key + assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(self.tables_storage_account_name, "table")) - @TablesPreparer() - def test_create_service_protocol(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_protocol(self): # Arrange for service_type in SERVICES.items(): # Act - url = self.account_url(tables_storage_account_name, "table").replace('https', 'http') + url = self.account_url(self.tables_storage_account_name, "table").replace('https', 'http') service = service_type[0]( - url, credential=tables_primary_storage_account_key, table_name='foo') + url, credential=self.tables_primary_storage_account_key, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'http' - @TablesPreparer() - def test_create_service_empty_key(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_empty_key(self): # Arrange TABLE_SERVICES = [TableServiceClient, TableClient] @@ -152,45 +177,42 @@ def test_create_service_empty_key(self, tables_storage_account_name, tables_prim # test non-string account URL with pytest.raises(ValueError): - test_service = service_type(account_url=123456, credential=tables_primary_storage_account_key, table_name='foo') + test_service = service_type(account_url=123456, credential=self.tables_primary_storage_account_key, table_name='foo') assert str(e.value) == "You need to provide either a SAS token or an account shared key to authenticate." - @TablesPreparer() - def test_create_service_with_socket_timeout(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_socket_timeout(self): # Arrange for service_type in SERVICES.items(): # Act default_service = service_type[0]( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, table_name='foo') + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='foo') service = service_type[0]( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='foo', connection_timeout=22) # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service._client._client._pipeline._transport.connection_config.timeout == 22 assert default_service._client._client._pipeline._transport.connection_config.timeout in [20, (20, 2000)] # --Connection String Test Cases -------------------------------------------- - @TablesPreparer() - def test_create_service_with_connection_string_key(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_connection_string_key(self): # Arrange - conn_string = 'AccountName={};AccountKey={};'.format(tables_storage_account_name, tables_primary_storage_account_key) + conn_string = 'AccountName={};AccountKey={};'.format(self.tables_storage_account_name, self.tables_primary_storage_account_key) for service_type in SERVICES.items(): # Act service = service_type[0].from_connection_string(conn_string, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'https' - @TablesPreparer() - def test_create_service_with_connection_string_sas(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_connection_string_sas(self): # Arrange - conn_string = 'AccountName={};SharedAccessSignature={};'.format(tables_storage_account_name, self.sas_token) + conn_string = 'AccountName={};SharedAccessSignature={};'.format(self.tables_storage_account_name, self.generate_sas_token()) for service_type in SERVICES: # Act @@ -198,16 +220,15 @@ def test_create_service_with_connection_string_sas(self, tables_storage_account_ # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + '.table.core.windows.net') - assert service.url.endswith(self.sas_token) + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + '.table.core.windows.net') + assert service.url.endswith(self.generate_sas_token()) assert service.credential is None - @TablesPreparer() - def test_create_service_with_connection_string_cosmos(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_connection_string_cosmos(self): # Arrange conn_string = 'DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};TableEndpoint=https://{0}.table.cosmos.azure.com:443/;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) for service_type in SERVICES: # Act @@ -215,18 +236,17 @@ def test_create_service_with_connection_string_cosmos(self, tables_storage_accou # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + '.table.cosmos.azure.com') - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key - assert service._primary_endpoint.startswith('https://' + tables_storage_account_name + '.table.cosmos.azure.com') + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + '.table.cosmos.azure.com') + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key + assert service._primary_endpoint.startswith('https://' + self.tables_storage_account_name + '.table.cosmos.azure.com') assert service.scheme == 'https' - @TablesPreparer() - def test_create_service_with_connection_string_endpoint_protocol(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_connection_string_endpoint_protocol(self): # Arrange conn_string = 'AccountName={};AccountKey={};DefaultEndpointsProtocol=http;EndpointSuffix=core.chinacloudapi.cn;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) for service_type in SERVICES.items(): # Act @@ -234,62 +254,58 @@ def test_create_service_with_connection_string_endpoint_protocol(self, tables_st # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key - assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(tables_storage_account_name, "table")) + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key + assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(self.tables_storage_account_name, "table")) assert service.scheme == 'http' - @TablesPreparer() - def test_create_service_with_connection_string_emulated(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_connection_string_emulated(self): # Arrange for service_type in SERVICES.items(): - conn_string = 'UseDevelopmentStorage=true;'.format(tables_storage_account_name, tables_primary_storage_account_key) + conn_string = 'UseDevelopmentStorage=true;'.format(self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - @TablesPreparer() - def test_create_service_with_connection_string_custom_domain(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_connection_string_custom_domain(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - def test_create_service_with_conn_str_custom_domain_trailing_slash(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_conn_str_custom_domain_trailing_slash(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - def test_create_service_with_conn_str_custom_domain_sec_override(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_conn_str_custom_domain_sec_override(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act service = service_type[0].from_connection_string( @@ -297,17 +313,16 @@ def test_create_service_with_conn_str_custom_domain_sec_override(self, tables_st # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - def test_create_service_with_conn_str_fails_if_sec_without_primary(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_conn_str_fails_if_sec_without_primary(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;'.format( - tables_storage_account_name, tables_primary_storage_account_key, + self.tables_storage_account_name, self.tables_primary_storage_account_key, _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) # Act @@ -316,13 +331,12 @@ def test_create_service_with_conn_str_fails_if_sec_without_primary(self, tables_ with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - @TablesPreparer() - def test_create_service_with_conn_str_succeeds_if_sec_with_primary(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_service_with_conn_str_succeeds_if_sec_with_primary(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;{}=www-sec.mydomain.com;'.format( - tables_storage_account_name, - tables_primary_storage_account_key, + self.tables_storage_account_name, + self.tables_primary_storage_account_key, _CONNECTION_ENDPOINTS.get(service_type[1]), _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) @@ -331,25 +345,24 @@ def test_create_service_with_conn_str_succeeds_if_sec_with_primary(self, tables_ # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - def test_create_service_with_custom_account_endpoint_path(self, tables_storage_account_name, tables_primary_storage_account_key): - custom_account_url = "http://local-machine:11002/custom/account/path/" + self.sas_token + def test_create_service_with_custom_account_endpoint_path(self): + custom_account_url = "http://local-machine:11002/custom/account/path/" + self.generate_sas_token() for service_type in SERVICES.items(): conn_string = 'DefaultEndpointsProtocol=http;AccountName={};AccountKey={};TableEndpoint={};'.format( - tables_storage_account_name, tables_primary_storage_account_key, custom_account_url) + self.tables_storage_account_name, self.tables_primary_storage_account_key, custom_account_url) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_hostname == 'local-machine:11002/custom/account/path' service = TableServiceClient(account_url=custom_account_url) @@ -365,88 +378,32 @@ def test_create_service_with_custom_account_endpoint_path(self, tables_storage_a assert service._primary_hostname == 'local-machine:11002/custom/account/path' assert service.url.startswith('http://local-machine:11002/custom/account/path') - service = TableClient.from_table_url("http://local-machine:11002/custom/account/path/foo" + self.sas_token) + service = TableClient.from_table_url("http://local-machine:11002/custom/account/path/foo" + self.generate_sas_token()) assert service.account_name == None assert service.table_name == "foo" assert service.credential == None assert service._primary_hostname == 'local-machine:11002/custom/account/path' assert service.url.startswith('http://local-machine:11002/custom/account/path') - @TablesPreparer() - def test_user_agent_default(self, tables_storage_account_name, tables_primary_storage_account_key): - service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = list(service.list_tables(raw_response_hook=callback)) - assert isinstance(tables, list) - - @TablesPreparer() - def test_user_agent_custom(self, tables_storage_account_name, tables_primary_storage_account_key): - custom_app = "TestApp/v1.0" - service = TableServiceClient( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, user_agent=custom_app) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = list(service.list_tables(raw_response_hook=callback)) - assert isinstance(tables, list) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = list(service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0")) - assert isinstance(tables, list) - - @TablesPreparer() - def test_user_agent_append(self, tables_storage_account_name, tables_primary_storage_account_key): - service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert response.http_request.headers['User-Agent'] == "azsdk-python-data-tables/{} Python/{} ({}) customer_user_agent".format( - VERSION, - platform.python_version(), - platform.platform()) - - custom_headers = {'User-Agent': 'customer_user_agent'} - tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) - - @TablesPreparer() - def test_create_table_client_with_complete_table_url(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_table_client_with_complete_table_url(self): # Arrange - table_url = self.account_url(tables_storage_account_name, "table") + "/foo" - service = TableClient(table_url, table_name='bar', credential=tables_primary_storage_account_key) + table_url = self.account_url(self.tables_storage_account_name, "table") + "/foo" + service = TableClient(table_url, table_name='bar', credential=self.tables_primary_storage_account_key) # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_storage_account_name + assert service.account_name == self.tables_storage_account_name - @TablesPreparer() - def test_create_table_client_with_complete_url(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_create_table_client_with_complete_url(self): # Arrange - table_url = "https://{}.table.core.windows.net:443/foo".format(tables_storage_account_name) - service = TableClient(account_url=table_url, table_name='bar', credential=tables_primary_storage_account_key) + table_url = "https://{}.table.core.windows.net:443/foo".format(self.tables_storage_account_name) + service = TableClient(account_url=table_url, table_name='bar', credential=self.tables_primary_storage_account_key) # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_storage_account_name + assert service.account_name == self.tables_storage_account_name def test_create_table_client_with_invalid_name(self): # Arrange @@ -455,7 +412,7 @@ def test_create_table_client_with_invalid_name(self): # Assert with pytest.raises(ValueError) as excinfo: - service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="tables_primary_storage_account_key") + service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="self.tables_primary_storage_account_key") assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long." in str(excinfo) @@ -473,24 +430,54 @@ def test_error_with_malformed_conn_str(self): elif conn_str in ("foobar=baz=foo" , "foo=;bar=;", "=", "=;=="): assert str(e.value) == "Connection string missing required connection details." - @TablesPreparer() - def test_closing_pipeline_client(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_closing_pipeline_client(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, table_name='table') + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='table') # Assert with service: assert hasattr(service, 'close') service.close() - @TablesPreparer() - def test_closing_pipeline_client_simple(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_closing_pipeline_client_simple(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, table_name='table') + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='table') service.close() + + def test_create_service_with_token_and_http(self): + for service_type in SERVICES: + + with pytest.raises(ValueError): + url = self.account_url(self.tables_storage_account_name, "table").replace('https', 'http') + service_type(url, credential=self.generate_fake_token(), table_name='foo') + + def test_create_service_with_token(self): + url = self.account_url(self.tables_storage_account_name, "table") + suffix = '.table.core.windows.net' + self.token_credential = self.generate_fake_token() + + service = TableClient(url, credential=self.token_credential, table_name='foo') + + # Assert + assert service is not None + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + suffix) + assert service.credential == self.token_credential + assert not hasattr(service.credential, 'account_key') + assert hasattr(service.credential, 'get_token') + + service = TableServiceClient(url, credential=self.token_credential, table_name='foo') + + # Assert + assert service is not None + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + suffix) + assert service.credential == self.token_credential + assert not hasattr(service.credential, 'account_key') + assert hasattr(service.credential, 'get_token') diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_async.py b/sdk/tables/azure-data-tables/tests/test_table_client_async.py index 89acb591c782..1f1b2431fac5 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_async.py @@ -11,7 +11,7 @@ from azure.data.tables.aio import TableServiceClient, TableClient from azure.data.tables._version import VERSION -from _shared.testcase import TableTestCase +from _shared.asynctestcase import AsyncTableTestCase from preparers import TablesPreparer from devtools_testutils import AzureTestCase # ------------------------------------------------------------------------------ @@ -24,11 +24,68 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint'} -class StorageTableClientTest(AzureTestCase, TableTestCase): - def setUp(self): - super(StorageTableClientTest, self).setUp() - self.sas_token = self.generate_sas_token() - self.token_credential = self.generate_oauth_token() + +class TestTableClient(AzureTestCase, AsyncTableTestCase): + + @TablesPreparer() + async def test_user_agent_default_async(self, tables_storage_account_name, tables_primary_storage_account_key): + service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert response.http_request.headers['User-Agent'] in "azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) + + tables = service.list_tables(raw_response_hook=callback) + assert tables is not None + + @TablesPreparer() + async def test_user_agent_custom_async(self, tables_storage_account_name, tables_primary_storage_account_key): + custom_app = "TestApp/v1.0" + service = TableServiceClient( + self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, user_agent=custom_app) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = service.list_tables(raw_response_hook=callback) + assert tables is not None + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0") + assert tables is not None + + @TablesPreparer() + async def test_user_agent_append(self, tables_storage_account_name, tables_primary_storage_account_key): + # TODO: fix this one + service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert response.http_request.headers['User-Agent'] == "azsdk-python-data-tables/{} Python/{} ({}) customer_user_agent".format( + VERSION, + platform.python_version(), + platform.platform()) + + custom_headers = {'User-Agent': 'customer_user_agent'} + tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) + + +class TestTableClientUnit(AsyncTableTestCase): + tables_storage_account_name = "fake_storage_account" + tables_primary_storage_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, account_name, account_key): @@ -39,105 +96,106 @@ def validate_standard_account_endpoints(self, service, account_name, account_key assert ('{}.{}'.format(account_name, 'table.core.windows.net') in service.url) or ('{}.{}'.format(account_name, 'table.cosmos.azure.com') in service.url) # --Direct Parameters Test Cases -------------------------------------------- - @TablesPreparer() - async def test_create_service_with_key_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_key_async(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_storage_account_name, url), credential=tables_primary_storage_account_key, table_name='foo') + self.account_url(self.tables_storage_account_name, url), credential=self.tables_primary_storage_account_key, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'https' - @TablesPreparer() - async def test_create_service_with_connection_string_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_async(self): for service_type in SERVICES.items(): # Act service = service_type[0].from_connection_string( - self.connection_string(tables_storage_account_name, tables_primary_storage_account_key), table_name="test") + self.connection_string(self.tables_storage_account_name, self.tables_primary_storage_account_key), table_name="test") # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'https' - @TablesPreparer() - async def test_create_service_with_sas_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_sas_async(self): # Arrange - url = self.account_url(tables_storage_account_name, "table") + url = self.account_url(self.tables_storage_account_name, "table") suffix = '.table.core.windows.net' for service_type in SERVICES: # Act service = service_type( - self.account_url(tables_storage_account_name, "table"), credential=self.sas_token, table_name='foo') + self.account_url(self.tables_storage_account_name, "table"), credential=self.generate_sas_token(), table_name='foo') # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + suffix) - assert service.url.endswith(self.sas_token) + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + suffix) + assert service.url.endswith(self.generate_sas_token()) assert service.credential is None - @TablesPreparer() - async def test_create_service_with_token_async(self, tables_storage_account_name, tables_primary_storage_account_key): - url = self.account_url(tables_storage_account_name, "table") + @pytest.mark.asyncio + async def test_create_service_with_token_async(self): + url = self.account_url(self.tables_storage_account_name, "table") suffix = '.table.core.windows.net' + self.token_credential = self.generate_fake_token() for service_type in SERVICES: # Act service = service_type(url, credential=self.token_credential, table_name='foo') # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + suffix) - assert service.credential == self.token_credential + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + suffix) + assert service.credential == self.token_credential assert not hasattr(service.credential, 'account_key') assert hasattr(service.credential, 'get_token') - @TablesPreparer() - async def test_create_service_with_token_and_http_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_token_and_http_async(self): for service_type in SERVICES: # Act with pytest.raises(ValueError): - url = self.account_url(tables_storage_account_name, "table").replace('https', 'http') - service_type(url, credential=self.token_credential, table_name='foo') + url = self.account_url(self.tables_storage_account_name, "table").replace('https', 'http') + service_type(url, credential=self.generate_fake_token(), table_name='foo') - @TablesPreparer() - async def test_create_service_china_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_china_async(self): # Arrange # TODO: Confirm regional cloud cosmos URLs for service_type in SERVICES.items(): # Act - url = self.account_url(tables_storage_account_name, "table").replace('core.windows.net', 'core.chinacloudapi.cn') + url = self.account_url(self.tables_storage_account_name, "table").replace('core.windows.net', 'core.chinacloudapi.cn') service = service_type[0]( - url, credential=tables_primary_storage_account_key, table_name='foo') + url, credential=self.tables_primary_storage_account_key, table_name='foo') # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key - assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(tables_storage_account_name, "table")) + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key + assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(self.tables_storage_account_name, "table")) - @TablesPreparer() - async def test_create_service_protocol_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_protocol_async(self): # Arrange for service_type in SERVICES.items(): # Act - url = self.account_url(tables_storage_account_name, "table").replace('https', 'http') + url = self.account_url(self.tables_storage_account_name, "table").replace('https', 'http') service = service_type[0]( - url, credential=tables_primary_storage_account_key, table_name='foo') + url, credential=self.tables_primary_storage_account_key, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'http' - @TablesPreparer() - async def test_create_service_empty_key_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_empty_key_async(self): # Arrange TABLE_SERVICES = [TableServiceClient, TableClient] @@ -148,41 +206,41 @@ async def test_create_service_empty_key_async(self, tables_storage_account_name, assert str(e.value) == "You need to provide either a SAS token or an account shared key to authenticate." - @TablesPreparer() - async def test_create_service_with_socket_timeout_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_socket_timeout_async(self): # Arrange for service_type in SERVICES.items(): # Act default_service = service_type[0]( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, table_name='foo') + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='foo') service = service_type[0]( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='foo', connection_timeout=22) # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service._client._client._pipeline._transport.connection_config.timeout == 22 assert default_service._client._client._pipeline._transport.connection_config.timeout in [20, (20, 2000)] # --Connection String Test Cases -------------------------------------------- - @TablesPreparer() - async def test_create_service_with_connection_string_key_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_key_async(self): # Arrange - conn_string = 'AccountName={};AccountKey={};'.format(tables_storage_account_name, tables_primary_storage_account_key) + conn_string = 'AccountName={};AccountKey={};'.format(self.tables_storage_account_name, self.tables_primary_storage_account_key) for service_type in SERVICES.items(): # Act service = service_type[0].from_connection_string(conn_string, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_storage_account_name, tables_primary_storage_account_key) + self.validate_standard_account_endpoints(service, self.tables_storage_account_name, self.tables_primary_storage_account_key) assert service.scheme == 'https' - @TablesPreparer() - async def test_create_service_with_connection_string_sas_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_sas_async(self): # Arrange - conn_string = 'AccountName={};SharedAccessSignature={};'.format(tables_storage_account_name, self.sas_token) + conn_string = 'AccountName={};SharedAccessSignature={};'.format(self.tables_storage_account_name, self.generate_sas_token()) for service_type in SERVICES: # Act @@ -190,16 +248,16 @@ async def test_create_service_with_connection_string_sas_async(self, tables_stor # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + '.table.core.windows.net') - assert service.url.endswith(self.sas_token) + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + '.table.core.windows.net') + assert service.url.endswith(self.generate_sas_token()) assert service.credential is None - @TablesPreparer() - async def test_create_service_with_connection_string_cosmos_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_cosmos_async(self): # Arrange conn_string = 'DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};TableEndpoint=https://{0}.table.cosmos.azure.com:443/;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) for service_type in SERVICES: # Act @@ -207,18 +265,18 @@ async def test_create_service_with_connection_string_cosmos_async(self, tables_s # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.url.startswith('https://' + tables_storage_account_name + '.table.cosmos.azure.com') - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key - assert service._primary_endpoint.startswith('https://' + tables_storage_account_name + '.table.cosmos.azure.com') + assert service.account_name == self.tables_storage_account_name + assert service.url.startswith('https://' + self.tables_storage_account_name + '.table.cosmos.azure.com') + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key + assert service._primary_endpoint.startswith('https://' + self.tables_storage_account_name + '.table.cosmos.azure.com') assert service.scheme == 'https' - @TablesPreparer() - async def test_create_service_with_connection_string_endpoint_protocol_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_endpoint_protocol_async(self): # Arrange conn_string = 'AccountName={};AccountKey={};DefaultEndpointsProtocol=http;EndpointSuffix=core.chinacloudapi.cn;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) for service_type in SERVICES.items(): # Act @@ -226,62 +284,62 @@ async def test_create_service_with_connection_string_endpoint_protocol_async(sel # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key - assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(tables_storage_account_name, "table")) + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key + assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(self.tables_storage_account_name, "table")) assert service.scheme == 'http' - @TablesPreparer() - async def test_create_service_with_connection_string_emulated_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_emulated_async(self): # Arrange for service_type in SERVICES.items(): - conn_string = 'UseDevelopmentStorage=true;'.format(tables_storage_account_name, tables_primary_storage_account_key) + conn_string = 'UseDevelopmentStorage=true;'.format(self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - @TablesPreparer() - async def test_create_service_with_connection_string_custom_domain_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_custom_domain_async(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - async def test_create_service_with_conn_str_custom_domain_trailing_slash_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_custom_domain_trailing_slash_async(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - async def test_create_service_with_conn_str_custom_domain_sec_override_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_custom_domain_sec_override_async(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_storage_account_name, tables_primary_storage_account_key) + self.tables_storage_account_name, self.tables_primary_storage_account_key) # Act service = service_type[0].from_connection_string( @@ -289,30 +347,30 @@ async def test_create_service_with_conn_str_custom_domain_sec_override_async(sel # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - async def test_create_service_with_conn_str_fails_if_sec_without_primary_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_fails_if_sec_without_primary_async(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;'.format( - tables_storage_account_name, tables_primary_storage_account_key, + self.tables_storage_account_name, self.tables_primary_storage_account_key, _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) # Fails if primary excluded with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - @TablesPreparer() - async def test_create_service_with_conn_str_succeeds_if_sec_with_primary_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_succeeds_if_sec_with_primary_async(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;{}=www-sec.mydomain.com;'.format( - tables_storage_account_name, - tables_primary_storage_account_key, + self.tables_storage_account_name, + self.tables_primary_storage_account_key, _CONNECTION_ENDPOINTS.get(service_type[1]), _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) @@ -321,25 +379,25 @@ async def test_create_service_with_conn_str_succeeds_if_sec_with_primary_async(s # Assert assert service is not None - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @TablesPreparer() - async def test_create_service_with_custom_account_endpoint_path_async(self, tables_storage_account_name, tables_primary_storage_account_key): - custom_account_url = "http://local-machine:11002/custom/account/path/" + self.sas_token + @pytest.mark.asyncio + async def test_create_service_with_custom_account_endpoint_path_async(self): + custom_account_url = "http://local-machine:11002/custom/account/path/" + self.generate_sas_token() for service_type in SERVICES.items(): conn_string = 'DefaultEndpointsProtocol=http;AccountName={};AccountKey={};TableEndpoint={};'.format( - tables_storage_account_name, tables_primary_storage_account_key, custom_account_url) + self.tables_storage_account_name, self.tables_primary_storage_account_key, custom_account_url) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert - assert service.account_name == tables_storage_account_name - assert service.credential.account_name == tables_storage_account_name - assert service.credential.account_key == tables_primary_storage_account_key + assert service.account_name == self.tables_storage_account_name + assert service.credential.account_name == self.tables_storage_account_name + assert service.credential.account_key == self.tables_primary_storage_account_key assert service._primary_hostname == 'local-machine:11002/custom/account/path' service = TableServiceClient(account_url=custom_account_url) @@ -355,91 +413,36 @@ async def test_create_service_with_custom_account_endpoint_path_async(self, tabl assert service._primary_hostname == 'local-machine:11002/custom/account/path' assert service.url.startswith('http://local-machine:11002/custom/account/path') - service = TableClient.from_table_url("http://local-machine:11002/custom/account/path/foo" + self.sas_token) + service = TableClient.from_table_url("http://local-machine:11002/custom/account/path/foo" + self.generate_sas_token()) assert service.account_name == None assert service.table_name == "foo" assert service.credential == None assert service._primary_hostname == 'local-machine:11002/custom/account/path' assert service.url.startswith('http://local-machine:11002/custom/account/path') - @TablesPreparer() - async def test_user_agent_default_async(self, tables_storage_account_name, tables_primary_storage_account_key): - service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert response.http_request.headers['User-Agent'] in "azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) - - tables = service.list_tables(raw_response_hook=callback) - assert tables is not None - - @TablesPreparer() - async def test_user_agent_custom_async(self, tables_storage_account_name, tables_primary_storage_account_key): - custom_app = "TestApp/v1.0" - service = TableServiceClient( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, user_agent=custom_app) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = service.list_tables(raw_response_hook=callback) - assert tables is not None - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0") - assert tables is not None - - @TablesPreparer() - async def test_user_agent_append(self, tables_storage_account_name, tables_primary_storage_account_key): - # TODO: fix this one - service = TableServiceClient(self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert response.http_request.headers['User-Agent'] == "azsdk-python-data-tables/{} Python/{} ({}) customer_user_agent".format( - VERSION, - platform.python_version(), - platform.platform()) - - custom_headers = {'User-Agent': 'customer_user_agent'} - tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) - - @TablesPreparer() - async def test_create_table_client_with_complete_table_url_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_table_client_with_complete_table_url_async(self): # Arrange - table_url = self.account_url(tables_storage_account_name, "table") + "/foo" - service = TableClient(table_url, table_name='bar', credential=tables_primary_storage_account_key) + table_url = self.account_url(self.tables_storage_account_name, "table") + "/foo" + service = TableClient(table_url, table_name='bar', credential=self.tables_primary_storage_account_key) # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_storage_account_name + assert service.account_name == self.tables_storage_account_name - @TablesPreparer() - async def test_create_table_client_with_complete_url_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_create_table_client_with_complete_url_async(self): # Arrange - table_url = "https://{}.table.core.windows.net:443/foo".format(tables_storage_account_name) - service = TableClient(account_url=table_url, table_name='bar', credential=tables_primary_storage_account_key) + table_url = "https://{}.table.core.windows.net:443/foo".format(self.tables_storage_account_name) + service = TableClient(account_url=table_url, table_name='bar', credential=self.tables_primary_storage_account_key) # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_storage_account_name + assert service.account_name == self.tables_storage_account_name - @AzureTestCase.await_prepared_test + @pytest.mark.asyncio async def test_create_table_client_with_invalid_name_async(self): # Arrange table_url = "https://{}.table.core.windows.net:443/foo".format("storage_account_name") @@ -447,11 +450,11 @@ async def test_create_table_client_with_invalid_name_async(self): # Assert with pytest.raises(ValueError) as excinfo: - service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="tables_primary_storage_account_key") + service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="self.tables_primary_storage_account_key") assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long."in str(excinfo) - @AzureTestCase.await_prepared_test + @pytest.mark.asyncio async def test_error_with_malformed_conn_str_async(self): # Arrange @@ -466,24 +469,24 @@ async def test_error_with_malformed_conn_str_async(self): elif conn_str in ("foobar=baz=foo" , "foo=;bar=;", "=", "=;=="): assert str(e.value) == "Connection string missing required connection details." - @TablesPreparer() - async def test_closing_pipeline_client_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_closing_pipeline_client_async(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, table_name='table') + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='table') # Assert async with service: assert hasattr(service, 'close') await service.close() - @TablesPreparer() - async def test_closing_pipeline_client_simple_async(self, tables_storage_account_name, tables_primary_storage_account_key): + @pytest.mark.asyncio + async def test_closing_pipeline_client_simple_async(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_storage_account_name, "table"), credential=tables_primary_storage_account_key, table_name='table') + self.account_url(self.tables_storage_account_name, "table"), credential=self.tables_primary_storage_account_key, table_name='table') await service.close() diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py index 42ea214add6d..a0c4d057bbc5 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py @@ -29,11 +29,79 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint', 'cosmos': 'TableSecondaryEndpoint'} -class StorageTableClientTest(AzureTestCase, TableTestCase): - def setUp(self): - super(StorageTableClientTest, self).setUp() - self.sas_token = self.generate_sas_token() - self.token_credential = self.generate_oauth_token() +class TestTableClient(AzureTestCase, TableTestCase): + + @pytest.mark.skipif(sys.version_info < (3, 0), reason="Malformed string") + @CosmosPreparer() + def test_user_agent_default(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + service = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = list(service.list_tables(raw_response_hook=callback)) + assert isinstance(tables, list) + + if self.is_live: + sleep(SLEEP_DELAY) + + @CosmosPreparer() + def test_user_agent_custom(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + custom_app = "TestApp/v1.0" + service = TableServiceClient( + self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, user_agent=custom_app) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = list(service.list_tables(raw_response_hook=callback)) + assert isinstance(tables, list) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = list(service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0")) + assert isinstance(tables, list) + + if self.is_live: + sleep(SLEEP_DELAY) + + @CosmosPreparer() + def test_user_agent_append(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + service = self.create_client_from_credential( + TableServiceClient, + account_url=self.account_url(tables_cosmos_account_name, "cosmos"), + credential=tables_primary_cosmos_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert response.http_request.headers['User-Agent'] == "azsdk-python-data-tables/{} Python/{} ({}) customer_user_agent".format( + VERSION, + platform.python_version(), + platform.platform()) + + custom_headers = {'User-Agent': 'customer_user_agent'} + tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) + + if self.is_live: + sleep(SLEEP_DELAY) + + +class TestTableClientUnit(TableTestCase): + tables_cosmos_account_name = "fake_storage_account" + tables_primary_cosmos_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, account_name, account_key): @@ -47,134 +115,117 @@ def _account_url(self, account_name): return "https://{}.table.cosmos.azure.com".format(account_name) # --Direct Parameters Test Cases -------------------------------------------- - @CosmosPreparer() - def test_create_service_with_key(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_key(self): # Arrange for client, url in SERVICES.items(): # Act - service = self.create_client_from_credential( - client, - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key, + service = client( + account_url=self._account_url(self.tables_cosmos_account_name), + credential=self.tables_primary_cosmos_account_key, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'https' - @CosmosPreparer() - def test_create_service_with_connection_string(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_connection_string(self): for client, url in SERVICES.items(): # Act - service = self.create_client_from_credential( - client, - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key, + service = client( + account_url=self._account_url(self.tables_cosmos_account_name), + credential=self.tables_primary_cosmos_account_key, table_name="test") # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'https' - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() - def test_create_service_with_sas(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_with_sas(self): # Arrange - url = self.account_url(tables_cosmos_account_name, "cosmos") + url = self.account_url(self.tables_cosmos_account_name, "cosmos") suffix = '.table.cosmos.azure.com' + self.sas_token = self.generate_sas_token() for service_type in SERVICES: # Act - service = self.create_client_from_credential( - service_type, - account_url=self._account_url(tables_cosmos_account_name), + service = service_type( + account_url=self._account_url(self.tables_cosmos_account_name), credential=self.sas_token, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.url.startswith('https://' + tables_cosmos_account_name + suffix) + assert service.account_name == self.tables_cosmos_account_name + assert service.url.startswith('https://' + self.tables_cosmos_account_name + suffix) assert service.url.endswith(self.sas_token) assert service.credential is None - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() - def test_create_service_with_token(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - url = self.account_url(tables_cosmos_account_name, "cosmos") + def test_create_service_with_token(self): + url = self.account_url(self.tables_cosmos_account_name, "cosmos") suffix = '.table.cosmos.azure.com' for service_type in SERVICES: # Act - service = self.create_client_from_credential( - service_type, - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key, + service = service_type( + account_url=self._account_url(self.tables_cosmos_account_name), + credential=self.tables_primary_cosmos_account_key, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.url.startswith('https://' + tables_cosmos_account_name + suffix) + assert service.account_name == self.tables_cosmos_account_name + assert service.url.startswith('https://' + self.tables_cosmos_account_name + suffix) assert not hasattr(service, 'account_key') - @CosmosPreparer() - def test_create_service_with_token_and_http(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_token_and_http(self): + self.token_credential = self.generate_fake_token() for service_type in SERVICES: # Act with pytest.raises(ValueError): - url = self.account_url(tables_cosmos_account_name, "cosmos").replace('https', 'http') - service = self.create_client_from_credential( - service_type, + url = self.account_url(self.tables_cosmos_account_name, "cosmos").replace('https', 'http') + service = service_type( account_url=url, credential=self.token_credential, table_name="foo") @pytest.mark.skip("Testing against a different cloud than the one created in powershell script") - @CosmosPreparer() - def test_create_service_china(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_china(self): # Arrange # TODO: Confirm regional cloud cosmos URLs for service_type in SERVICES.items(): # Act - url = self.account_url(tables_cosmos_account_name, "cosmos").replace('core.windows.net', 'core.chinacloudapi.cn') + url = self.account_url(self.tables_cosmos_account_name, "cosmos").replace('core.windows.net', 'core.chinacloudapi.cn') if 'cosmos.azure' in url: pytest.skip("Confirm cosmos national cloud URLs") service = service_type[0]( - url, credential=tables_primary_cosmos_account_key, table_name='foo') + url, credential=self.tables_primary_cosmos_account_key, table_name='foo') # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key - assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(tables_cosmos_account_name, "table")) + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key + assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(self.tables_cosmos_account_name, "table")) - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - def test_create_service_protocol(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_protocol(self): # Arrange - url = self._account_url(tables_cosmos_account_name).replace('https', 'http') + url = self._account_url(self.tables_cosmos_account_name).replace('https', 'http') suffix = '.table.cosmos.azure.com' for service_type in SERVICES: # Act - service = self.create_client_from_credential( - service_type, + service = service_type( account_url=url, - credential=tables_primary_cosmos_account_key, + credential=self.tables_primary_cosmos_account_key, table_name="foo") # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'http' - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() - def test_create_service_empty_key(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_empty_key(self): # Arrange TABLE_SERVICES = [TableServiceClient, TableClient] @@ -185,51 +236,44 @@ def test_create_service_empty_key(self, tables_cosmos_account_name, tables_prima assert str(e.value) == "You need to provide either a SAS token or an account shared key to authenticate." - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - def test_create_service_with_socket_timeout(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_with_socket_timeout(self): # Arrange for service_type in SERVICES.items(): # Act - default_service = self.create_client_from_credential( - service_type[0], - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key, + default_service = service_type[0]( + account_url=self._account_url(self.tables_cosmos_account_name), + credential=self.tables_primary_cosmos_account_key, table_name="foo") - service = self.create_client_from_credential( - service_type[0], - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key, + service = service_type[0]( + account_url=self._account_url(self.tables_cosmos_account_name), + credential=self.tables_primary_cosmos_account_key, table_name="foo", connection_timeout=22) # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service._client._client._pipeline._transport.connection_config.timeout == 22 assert default_service._client._client._pipeline._transport.connection_config.timeout in [20, (20, 2000)] - if self.is_live: - sleep(SLEEP_DELAY) + # --Connection String Test Cases -------------------------------------------- - @CosmosPreparer() - def test_create_service_with_connection_string_key(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_with_connection_string_key(self): # Arrange - conn_string = 'AccountName={};AccountKey={};'.format(tables_cosmos_account_name, tables_primary_cosmos_account_key) + conn_string = 'AccountName={};AccountKey={};'.format(self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) for service_type in SERVICES.items(): # Act service = service_type[0].from_connection_string(conn_string, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'https' - @CosmosPreparer() - def test_create_service_with_connection_string_sas(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_connection_string_sas(self): # Arrange - conn_string = 'AccountName={};SharedAccessSignature={};'.format(tables_cosmos_account_name, self.sas_token) + self.sas_token = self.generate_sas_token() + conn_string = 'AccountName={};SharedAccessSignature={};'.format(self.tables_cosmos_account_name, self.sas_token) for service_type in SERVICES: # Act @@ -237,15 +281,15 @@ def test_create_service_with_connection_string_sas(self, tables_cosmos_account_n # Assert assert service is not None - assert service.url.startswith('https://' + tables_cosmos_account_name + '.table.core.windows.net') + assert service.url.startswith('https://' + self.tables_cosmos_account_name + '.table.core.windows.net') assert service.url.endswith(self.sas_token) assert service.credential is None - @CosmosPreparer() - def test_create_service_with_connection_string_cosmos(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_connection_string_cosmos(self): # Arrange conn_string = 'DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};TableEndpoint=https://{0}.table.cosmos.azure.com:443/;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) for service_type in SERVICES: # Act @@ -253,19 +297,19 @@ def test_create_service_with_connection_string_cosmos(self, tables_cosmos_accoun # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.url.startswith('https://' + tables_cosmos_account_name + '.table.cosmos.azure.com') - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key - assert service._primary_endpoint.startswith('https://' + tables_cosmos_account_name + '.table.cosmos.azure.com') + assert service.account_name == self.tables_cosmos_account_name + assert service.url.startswith('https://' + self.tables_cosmos_account_name + '.table.cosmos.azure.com') + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key + assert service._primary_endpoint.startswith('https://' + self.tables_cosmos_account_name + '.table.cosmos.azure.com') assert service.scheme == 'https' @pytest.mark.skip("Tests fail with non-standard clouds") - @CosmosPreparer() - def test_create_service_with_connection_string_endpoint_protocol(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_connection_string_endpoint_protocol(self): # Arrange conn_string = 'AccountName={};AccountKey={};DefaultEndpointsProtocol=http;EndpointSuffix=core.chinacloudapi.cn;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) for service_type in SERVICES.items(): # Act @@ -273,64 +317,61 @@ def test_create_service_with_connection_string_endpoint_protocol(self, tables_co # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key - assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(tables_cosmos_account_name, "table")) + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key + assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(self.tables_cosmos_account_name, "table")) assert service.scheme == 'http' - @CosmosPreparer() - def test_create_service_with_connection_string_emulated(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_connection_string_emulated(self): # Arrange for service_type in SERVICES.items(): - conn_string = 'UseDevelopmentStorage=true;'.format(tables_cosmos_account_name, tables_primary_cosmos_account_key) + conn_string = 'UseDevelopmentStorage=true;'.format(self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - @CosmosPreparer() - def test_create_service_with_connection_string_custom_domain(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_connection_string_custom_domain(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - @CosmosPreparer() - def test_create_service_with_conn_str_custom_domain_trailing_slash(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_conn_str_custom_domain_trailing_slash(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() - def test_create_service_with_conn_str_custom_domain_sec_override(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_with_conn_str_custom_domain_sec_override(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act service = service_type[0].from_connection_string( @@ -338,19 +379,16 @@ def test_create_service_with_conn_str_custom_domain_sec_override(self, tables_co # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() - def test_create_service_with_conn_str_fails_if_sec_without_primary(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_with_conn_str_fails_if_sec_without_primary(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key, + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key, _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) # Act @@ -359,13 +397,13 @@ def test_create_service_with_conn_str_fails_if_sec_without_primary(self, tables_ with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - @CosmosPreparer() - def test_create_service_with_conn_str_succeeds_if_sec_with_primary(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_service_with_conn_str_succeeds_if_sec_with_primary(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;{}=www-sec.mydomain.com;'.format( - tables_cosmos_account_name, - tables_primary_cosmos_account_key, + self.tables_cosmos_account_name, + self.tables_primary_cosmos_account_key, _CONNECTION_ENDPOINTS.get(service_type[1]), _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) @@ -374,27 +412,25 @@ def test_create_service_with_conn_str_succeeds_if_sec_with_primary(self, tables_ # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() - def test_create_service_with_custom_account_endpoint_path(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_service_with_custom_account_endpoint_path(self): + self.sas_token = self.generate_sas_token() custom_account_url = "http://local-machine:11002/custom/account/path/" + self.sas_token for service_type in SERVICES.items(): conn_string = 'DefaultEndpointsProtocol=http;AccountName={};AccountKey={};TableEndpoint={};'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key, custom_account_url) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key, custom_account_url) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_hostname == 'local-machine:11002/custom/account/path' service = TableServiceClient(account_url=custom_account_url) @@ -418,106 +454,32 @@ def test_create_service_with_custom_account_endpoint_path(self, tables_cosmos_ac assert service._primary_hostname == 'local-machine:11002/custom/account/path' assert service.url.startswith('http://local-machine:11002/custom/account/path') - if self.is_live: - sleep(SLEEP_DELAY) - - @pytest.mark.skipif(sys.version_info < (3, 0), reason="Malformed string") - @CosmosPreparer() - def test_user_agent_default(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - service = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = list(service.list_tables(raw_response_hook=callback)) - assert isinstance(tables, list) - - if self.is_live: - sleep(SLEEP_DELAY) - - @pytest.mark.skip("Tests fail with non-standard clouds") - @CosmosPreparer() - def test_user_agent_custom(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - custom_app = "TestApp/v1.0" - service = TableServiceClient( - self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, user_agent=custom_app) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = list(service.list_tables(raw_response_hook=callback)) - assert isinstance(tables, list) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-data-tables/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = list(service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0")) - assert isinstance(tables, list) - - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - def test_user_agent_append(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - service = self.create_client_from_credential( - TableServiceClient, - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert response.http_request.headers['User-Agent'] == "azsdk-python-data-tables/{} Python/{} ({}) customer_user_agent".format( - VERSION, - platform.python_version(), - platform.platform()) - - custom_headers = {'User-Agent': 'customer_user_agent'} - tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) - - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - def test_create_table_client_with_complete_table_url(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_create_table_client_with_complete_table_url(self): # Arrange - table_url = self._account_url(tables_cosmos_account_name) + "/foo" - service = self.create_client_from_credential( - TableClient, + table_url = self._account_url(self.tables_cosmos_account_name) + "/foo" + service = TableClient( account_url=table_url, - credential=tables_primary_cosmos_account_key, + credential=self.tables_primary_cosmos_account_key, table_name="bar") # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_cosmos_account_name + assert service.account_name == self.tables_cosmos_account_name - @CosmosPreparer() - def test_create_table_client_with_complete_url(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_create_table_client_with_complete_url(self): # Arrange - table_url = "https://{}.table.cosmos.azure.com:443/foo".format(tables_cosmos_account_name) - service = self.create_client_from_credential( - TableClient, + table_url = "https://{}.table.cosmos.azure.com:443/foo".format(self.tables_cosmos_account_name) + service = TableClient( account_url=table_url, - credential=tables_primary_cosmos_account_key, + credential=self.tables_primary_cosmos_account_key, table_name="bar") # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_cosmos_account_name + assert service.account_name == self.tables_cosmos_account_name def test_create_table_client_with_invalid_name(self): # Arrange @@ -526,13 +488,10 @@ def test_create_table_client_with_invalid_name(self): # Assert with pytest.raises(ValueError) as excinfo: - service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="tables_primary_cosmos_account_key") + service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="self.tables_primary_cosmos_account_key") assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long." in str(excinfo) - if self.is_live: - sleep(SLEEP_DELAY) - def test_error_with_malformed_conn_str(self): # Arrange @@ -547,18 +506,13 @@ def test_error_with_malformed_conn_str(self): elif conn_str in ("foobar=baz=foo" , "foo=;bar=;", "=", "=;=="): assert str(e.value) == "Connection string missing required connection details." - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - def test_closing_pipeline_client(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + def test_closing_pipeline_client(self): # Arrange for client, url in SERVICES.items(): # Act - service = self.create_client_from_credential( - client, - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key, + service = client( + account_url=self._account_url(self.tables_cosmos_account_name), + credential=self.tables_primary_cosmos_account_key, table_name='table') # Assert @@ -566,15 +520,14 @@ def test_closing_pipeline_client(self, tables_cosmos_account_name, tables_primar assert hasattr(service, 'close') service.close() - @CosmosPreparer() - def test_closing_pipeline_client_simple(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + + def test_closing_pipeline_client_simple(self): # Arrange for client, url in SERVICES.items(): # Act - service = self.create_client_from_credential( - client, - account_url=self._account_url(tables_cosmos_account_name), - credential=tables_primary_cosmos_account_key, + service = client( + account_url=self._account_url(self.tables_cosmos_account_name), + credential=self.tables_primary_cosmos_account_key, table_name='table') service.close() From a621ddeacda533a6e1a679fe154cb97a8a0d06fb Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 3 Feb 2021 18:19:31 -0500 Subject: [PATCH 04/13] moved all non-http generating tests to unit tests --- ...ervice_properties_async.test_set_cors.yaml | 37 -- ...roperties_async.test_set_hour_metrics.yaml | 36 -- ...ice_properties_async.test_set_logging.yaml | 36 -- ...perties_async.test_set_minute_metrics.yaml | 36 -- ...s_async.test_table_service_properties.yaml | 37 -- ...sync.test_table_service_stats_f_async.yaml | 30 -- ..._service_stats_when_unavailable_async.yaml | 30 -- .../tests/test_table_client_cosmos_async.py | 408 ++++++++---------- .../tests/test_table_cosmos.py | 84 ++-- .../tests/test_table_cosmos_async.py | 89 ++-- .../tests/test_table_service_properties.py | 15 +- .../test_table_service_properties_async.py | 17 +- .../test_table_service_properties_cosmos.py | 55 ++- ...t_table_service_properties_cosmos_async.py | 17 +- 14 files changed, 324 insertions(+), 603 deletions(-) delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_cors.yaml delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_hour_metrics.yaml delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_logging.yaml delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_minute_metrics.yaml delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_table_service_properties.yaml delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_f_async.yaml delete mode 100644 sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_when_unavailable_async.yaml diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_cors.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_cors.yaml deleted file mode 100644 index 5f2105c9acc7..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_cors.yaml +++ /dev/null @@ -1,37 +0,0 @@ -interactions: -- request: - body: ' - - www.xyz.comGET0www.xyz.com,www.ab.com,www.bc.comGET,PUTx-ms-meta-data*,x-ms-meta-target*,x-ms-meta-xyz,x-ms-meta-foox-ms-meta-data*,x-ms-meta-source*,x-ms-meta-abc,x-ms-meta-bcd500' - headers: - Content-Length: - - '631' - Content-Type: - - application/xml - Date: - - Mon, 10 Aug 2020 16:44:50 GMT - User-Agent: - - azsdk-python-storage-table/12.0.0b1 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Mon, 10 Aug 2020 16:44:50 GMT - x-ms-version: - - 12.0.0b1 - method: PUT - uri: https://storagename.table.core.windows.net/?restype=service&comp=properties - response: - body: - string: "\uFEFF\r\n\r\n - \ InvalidHeaderValue\r\n The value - for one of the HTTP headers is not in the correct format.\nRequestId:16266bd7-7002-006d-3835-6fffef000000\nTime:2020-08-10T16:44:51.9401828Z\r\n" - headers: - content-length: '371' - content-type: application/xml - date: Mon, 10 Aug 2020 16:44:51 GMT - server: Microsoft-HTTPAPI/2.0 - status: - code: 400 - message: The value for one of the HTTP headers is not in the correct format. - url: https://storagename.table.core.windows.net/?restype=service&comp=properties -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_hour_metrics.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_hour_metrics.yaml deleted file mode 100644 index 25ff77268b76..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_hour_metrics.yaml +++ /dev/null @@ -1,36 +0,0 @@ -interactions: -- request: - body: ' - - 1.0truetruetrue5' - headers: - Content-Length: - - '267' - Content-Type: - - application/xml - Date: - - Mon, 10 Aug 2020 16:44:51 GMT - User-Agent: - - azsdk-python-storage-table/12.0.0b1 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Mon, 10 Aug 2020 16:44:51 GMT - x-ms-version: - - 12.0.0b1 - method: PUT - uri: https://storagename.table.core.windows.net/?restype=service&comp=properties - response: - body: - string: "\uFEFF\r\n\r\n - \ InvalidHeaderValue\r\n The value - for one of the HTTP headers is not in the correct format.\nRequestId:b6f9f451-0002-008c-7d35-6f189a000000\nTime:2020-08-10T16:44:52.2987018Z\r\n" - headers: - content-length: '371' - content-type: application/xml - date: Mon, 10 Aug 2020 16:44:51 GMT - server: Microsoft-HTTPAPI/2.0 - status: - code: 400 - message: The value for one of the HTTP headers is not in the correct format. - url: https://storagename.table.core.windows.net/?restype=service&comp=properties -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_logging.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_logging.yaml deleted file mode 100644 index 3b2ea91b04fa..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_logging.yaml +++ /dev/null @@ -1,36 +0,0 @@ -interactions: -- request: - body: ' - - 1.0truetruetruetrue5' - headers: - Content-Length: - - '262' - Content-Type: - - application/xml - Date: - - Mon, 10 Aug 2020 16:38:41 GMT - User-Agent: - - azsdk-python-storage-table/12.0.0b1 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Mon, 10 Aug 2020 16:38:41 GMT - x-ms-version: - - 12.0.0b1 - method: PUT - uri: https://storagename.table.core.windows.net/?restype=service&comp=properties - response: - body: - string: "\uFEFF\r\n\r\n - \ InvalidHeaderValue\r\n The value - for one of the HTTP headers is not in the correct format.\nRequestId:617bd8f1-c002-0116-7534-6fd20a000000\nTime:2020-08-10T16:38:42.9984604Z\r\n" - headers: - content-length: '371' - content-type: application/xml - date: Mon, 10 Aug 2020 16:38:42 GMT - server: Microsoft-HTTPAPI/2.0 - status: - code: 400 - message: The value for one of the HTTP headers is not in the correct format. - url: https://storagename.table.core.windows.net/?restype=service&comp=properties -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_minute_metrics.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_minute_metrics.yaml deleted file mode 100644 index 0aa821f62161..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_set_minute_metrics.yaml +++ /dev/null @@ -1,36 +0,0 @@ -interactions: -- request: - body: ' - - 1.0truetruetrue5' - headers: - Content-Length: - - '271' - Content-Type: - - application/xml - Date: - - Mon, 10 Aug 2020 16:44:51 GMT - User-Agent: - - azsdk-python-storage-table/12.0.0b1 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Mon, 10 Aug 2020 16:44:51 GMT - x-ms-version: - - 12.0.0b1 - method: PUT - uri: https://storagename.table.core.windows.net/?restype=service&comp=properties - response: - body: - string: "\uFEFF\r\n\r\n - \ InvalidHeaderValue\r\n The value - for one of the HTTP headers is not in the correct format.\nRequestId:3f3ccf8b-8002-005a-2835-6f5340000000\nTime:2020-08-10T16:44:52.6990255Z\r\n" - headers: - content-length: '371' - content-type: application/xml - date: Mon, 10 Aug 2020 16:44:52 GMT - server: Microsoft-HTTPAPI/2.0 - status: - code: 400 - message: The value for one of the HTTP headers is not in the correct format. - url: https://storagename.table.core.windows.net/?restype=service&comp=properties -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_table_service_properties.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_table_service_properties.yaml deleted file mode 100644 index 81930db36e2b..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_properties_async.test_table_service_properties.yaml +++ /dev/null @@ -1,37 +0,0 @@ -interactions: -- request: - body: ' - - 1.0falsefalsefalsefalse1.0falsefalse1.0falsefalse' - headers: - Content-Length: - - '528' - Content-Type: - - application/xml - Date: - - Mon, 10 Aug 2020 16:38:03 GMT - User-Agent: - - azsdk-python-storage-table/12.0.0b1 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Mon, 10 Aug 2020 16:38:03 GMT - x-ms-version: - - 12.0.0b1 - method: PUT - uri: https://storagename.table.core.windows.net/?restype=service&comp=properties - response: - body: - string: "\uFEFF\r\n\r\n - \ InvalidHeaderValue\r\n The value - for one of the HTTP headers is not in the correct format.\nRequestId:66b65521-9002-0082-3734-6ff491000000\nTime:2020-08-10T16:38:05.2926871Z\r\n" - headers: - content-length: '371' - content-type: application/xml - date: Mon, 10 Aug 2020 16:38:04 GMT - server: Microsoft-HTTPAPI/2.0 - status: - code: 400 - message: The value for one of the HTTP headers is not in the correct format. - url: https://storagename.table.core.windows.net/?restype=service&comp=properties -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_f_async.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_f_async.yaml deleted file mode 100644 index 6361e9f6e28b..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_f_async.yaml +++ /dev/null @@ -1,30 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/xml - Date: - - Wed, 16 Sep 2020 21:58:16 GMT - User-Agent: - - azsdk-python-data-tables/12.0.0b2 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Wed, 16 Sep 2020 21:58:16 GMT - x-ms-version: - - '2019-02-02' - method: GET - uri: https://pyacrstoragestorname-secondary.table.core.windows.net/?restype=service&comp=stats - response: - body: - string: "\uFEFFunavailable" - headers: - content-type: application/xml - date: Wed, 16 Sep 2020 21:58:16 GMT - server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 - transfer-encoding: chunked - x-ms-version: '2019-02-02' - status: - code: 200 - message: OK - url: https://pyacrstoragemxivwppgccaw-secondary.table.core.windows.net/?restype=service&comp=stats -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_when_unavailable_async.yaml b/sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_when_unavailable_async.yaml deleted file mode 100644 index a54e41e0544b..000000000000 --- a/sdk/tables/azure-data-tables/tests/recordings/test_table_service_stats_async.test_table_service_stats_when_unavailable_async.yaml +++ /dev/null @@ -1,30 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/xml - Date: - - Wed, 16 Sep 2020 21:58:38 GMT - User-Agent: - - azsdk-python-data-tables/12.0.0b2 Python/3.8.4 (Windows-10-10.0.19041-SP0) - x-ms-date: - - Wed, 16 Sep 2020 21:58:38 GMT - x-ms-version: - - '2019-02-02' - method: GET - uri: https://pyacrstoragestorname-secondary.table.core.windows.net/?restype=service&comp=stats - response: - body: - string: "\uFEFFunavailable" - headers: - content-type: application/xml - date: Wed, 16 Sep 2020 21:58:38 GMT - server: Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0 - transfer-encoding: chunked - x-ms-version: '2019-02-02' - status: - code: 200 - message: OK - url: https://pyacrstorage4wq73yk5234v-secondary.table.core.windows.net/?restype=service&comp=stats -version: 1 diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py index 3470dc4bc019..63d615bf1ad0 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py @@ -12,10 +12,8 @@ from azure.data.tables.aio import TableServiceClient, TableClient from azure.data.tables._version import VERSION -from _shared.testcase import ( - TableTestCase, - SLEEP_DELAY -) +from _shared.asynctestcase import AsyncTableTestCase +from _shared.testcase import SLEEP_DELAY from preparers import CosmosPreparer from devtools_testutils import AzureTestCase @@ -30,11 +28,66 @@ _CONNECTION_ENDPOINTS_SECONDARY = {'table': 'TableSecondaryEndpoint', 'cosmos': 'TableSecondaryEndpoint'} -class StorageTableClientTest(AzureTestCase, TableTestCase): - def setUp(self): - super(StorageTableClientTest, self).setUp() - self.sas_token = self.generate_sas_token() - self.token_credential = self.generate_oauth_token() +class TestTableClient(AzureTestCase, AsyncTableTestCase): + + @CosmosPreparer() + async def test_user_agent_default_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + service = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert response.http_request.headers['User-Agent'] == "azsdk-python-storage-table/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) + + tables = service.list_tables(raw_response_hook=callback) + assert tables is not None + + @CosmosPreparer() + async def test_user_agent_custom_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + custom_app = "TestApp/v1.0" + service = TableServiceClient( + self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, user_agent=custom_app) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v1.0 azsdk-python-storage-table/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = service.list_tables(raw_response_hook=callback) + assert tables is not None + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-storage-table/{} Python/{} ({})".format( + VERSION, + platform.python_version(), + platform.platform()) in response.http_request.headers['User-Agent'] + + tables = service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0") + assert tables is not None + + @CosmosPreparer() + async def test_user_agent_append(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + service = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key) + + def callback(response): + assert 'User-Agent' in response.http_request.headers + assert response.http_request.headers['User-Agent'] == "azsdk-python-storage-tables/{} Python/{} ({}) customer_user_agent".format( + VERSION, + platform.python_version(), + platform.platform()) + + custom_headers = {'User-Agent': 'customer_user_agent'} + tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) + + +class TestTableClientUnit(AsyncTableTestCase): + tables_cosmos_account_name = "fake_storage_account" + tables_primary_cosmos_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" # --Helpers----------------------------------------------------------------- def validate_standard_account_endpoints(self, service, account_name, account_key): @@ -45,116 +98,109 @@ def validate_standard_account_endpoints(self, service, account_name, account_key assert '{}.{}'.format(account_name, 'table.core.windows.net') in service.url or '{}.{}'.format(account_name, 'table.cosmos.azure.com') in service.url # --Direct Parameters Test Cases -------------------------------------------- - - @CosmosPreparer() - async def test_create_service_with_key_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_key_async(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_cosmos_account_name, url), credential=tables_primary_cosmos_account_key, table_name='foo') + self.account_url(self.tables_cosmos_account_name, url), credential=self.tables_primary_cosmos_account_key, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'https' - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - async def test_create_service_with_connection_string_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_async(self): for service_type in SERVICES.items(): # Act service = service_type[0].from_connection_string( - self.connection_string(tables_cosmos_account_name, tables_primary_cosmos_account_key), table_name="test") + self.connection_string(self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key), table_name="test") # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'https' - - @CosmosPreparer() - async def test_create_service_with_sas_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_sas_async(self): # Arrange - url = self.account_url(tables_cosmos_account_name, "cosmos") + url = self.account_url(self.tables_cosmos_account_name, "cosmos") suffix = '.table.cosmos.azure.com' + self.sas_token = self.generate_sas_token() for service_type in SERVICES: # Act service = service_type( - self.account_url(tables_cosmos_account_name, "cosmos"), credential=self.sas_token, table_name='foo') + self.account_url(self.tables_cosmos_account_name, "cosmos"), credential=self.sas_token, table_name='foo') # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.url.startswith('https://' +tables_cosmos_account_name + suffix) + assert service.account_name == self.tables_cosmos_account_name + assert service.url.startswith('https://' +self.tables_cosmos_account_name + suffix) assert service.url.endswith(self.sas_token) assert service.credential is None - - @CosmosPreparer() - async def test_create_service_with_token_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - url = self.account_url(tables_cosmos_account_name, "cosmos") + @pytest.mark.asyncio + async def test_create_service_with_token_async(self): + url = self.account_url(self.tables_cosmos_account_name, "cosmos") suffix = '.table.cosmos.azure.com' + self.token_credential = self.generate_fake_token() for service_type in SERVICES: # Act service = service_type(url, credential=self.token_credential, table_name='foo') # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.url.startswith('https://' + tables_cosmos_account_name + suffix) + assert service.account_name == self.tables_cosmos_account_name + assert service.url.startswith('https://' + self.tables_cosmos_account_name + suffix) assert service.credential == self.token_credential assert not hasattr(service.credential, 'account_key') assert hasattr(service.credential, 'get_token') - - @CosmosPreparer() - async def test_create_service_with_token_and_http_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_token_and_http_async(self): + self.token_credential = self.generate_fake_token() for service_type in SERVICES: # Act with pytest.raises(ValueError): - url = self.account_url(tables_cosmos_account_name, "cosmos").replace('https', 'http') + url = self.account_url(self.tables_cosmos_account_name, "cosmos").replace('https', 'http') service_type(url, credential=self.token_credential, table_name='foo') @pytest.mark.skip("Confirm cosmos national cloud URLs") - - @CosmosPreparer() - async def test_create_service_china_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_china_async(self): # Arrange # TODO: Confirm regional cloud cosmos URLs for service_type in SERVICES.items(): # Act - url = self.account_url(tables_cosmos_account_name, "cosmos").replace('core.windows.net', 'core.chinacloudapi.cn') + url = self.account_url(self.tables_cosmos_account_name, "cosmos").replace('cosmos.azure.com', 'core.chinacloudapi.cn') service = service_type[0]( - url, credential=tables_primary_cosmos_account_key, table_name='foo') + url, credential=self.tables_primary_cosmos_account_key, table_name='foo') # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key - assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(tables_cosmos_account_name, "cosmos")) - + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key + assert service._primary_endpoint.startswith('https://{}.{}.core.chinacloudapi.cn'.format(self.tables_cosmos_account_name, "cosmos")) - @CosmosPreparer() - async def test_create_service_protocol_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_protocol_async(self): # Arrange for service_type in SERVICES.items(): # Act - url = self.account_url(tables_cosmos_account_name, "cosmos").replace('https', 'http') + url = self.account_url(self.tables_cosmos_account_name, "cosmos").replace('https', 'http') service = service_type[0]( - url, credential=tables_primary_cosmos_account_key, table_name='foo') + url, credential=self.tables_primary_cosmos_account_key, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'http' - - @CosmosPreparer() - async def test_create_service_empty_key_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_empty_key_async(self): # Arrange TABLE_SERVICES = [TableServiceClient, TableClient] @@ -165,45 +211,43 @@ async def test_create_service_empty_key_async(self, tables_cosmos_account_name, assert str(e.value) == "You need to provide either a SAS token or an account shared key to authenticate." - - @CosmosPreparer() - async def test_create_service_with_socket_timeout_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_socket_timeout_async(self): # Arrange for service_type in SERVICES.items(): # Act default_service = service_type[0]( - self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, table_name='foo') + self.account_url(self.tables_cosmos_account_name, "cosmos"), credential=self.tables_primary_cosmos_account_key, table_name='foo') service = service_type[0]( - self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, + self.account_url(self.tables_cosmos_account_name, "cosmos"), credential=self.tables_primary_cosmos_account_key, table_name='foo', connection_timeout=22) # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service._client._client._pipeline._transport.connection_config.timeout == 22 assert default_service._client._client._pipeline._transport.connection_config.timeout in [20, (20, 2000)] # --Connection String Test Cases -------------------------------------------- - - @CosmosPreparer() - async def test_create_service_with_connection_string_key_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_key_async(self): # Arrange - conn_string = 'AccountName={};AccountKey={};'.format(tables_cosmos_account_name, tables_primary_cosmos_account_key) + conn_string = 'AccountName={};AccountKey={};'.format(self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) for service_type in SERVICES.items(): # Act service = service_type[0].from_connection_string(conn_string, table_name='foo') # Assert - self.validate_standard_account_endpoints(service, tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.validate_standard_account_endpoints(service, self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) assert service.scheme == 'https' - @pytest.mark.skip("Error with sas formation") - - @CosmosPreparer() - async def test_create_service_with_connection_string_sas_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + # @pytest.mark.skip("Error with sas formation") + @pytest.mark.asyncio + async def test_create_service_with_connection_string_sas_async(self): + self.sas_token = self.generate_sas_token() # Arrange - conn_string = 'AccountName={};SharedAccessSignature={};'.format(tables_cosmos_account_name, self.sas_token) + conn_string = 'AccountName={};SharedAccessSignature={};'.format(self.tables_cosmos_account_name, self.sas_token) for service_type in SERVICES: # Act @@ -211,17 +255,16 @@ async def test_create_service_with_connection_string_sas_async(self, tables_cosm # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.url.startswith('https://' + tables_cosmos_account_name + '.table.core.windows.net') + assert service.account_name == self.tables_cosmos_account_name + assert service.url.startswith('https://' + self.tables_cosmos_account_name + '.table.core.windows.net') assert service.url.endswith(self.sas_token) assert service.credential is None - - @CosmosPreparer() - async def test_create_service_with_connection_string_cosmos_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_cosmos_async(self): # Arrange conn_string = 'DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};TableEndpoint=https://{0}.table.cosmos.azure.com:443/;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) for service_type in SERVICES: # Act @@ -229,19 +272,18 @@ async def test_create_service_with_connection_string_cosmos_async(self, tables_c # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.url.startswith('https://' + tables_cosmos_account_name + '.table.cosmos.azure.com') - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key - assert service._primary_endpoint.startswith('https://' + tables_cosmos_account_name + '.table.cosmos.azure.com') + assert service.account_name == self.tables_cosmos_account_name + assert service.url.startswith('https://' + self.tables_cosmos_account_name + '.table.cosmos.azure.com') + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key + assert service._primary_endpoint.startswith('https://' + self.tables_cosmos_account_name + '.table.cosmos.azure.com') assert service.scheme == 'https' - - @CosmosPreparer() - async def test_create_service_with_connection_string_endpoint_protocol_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_endpoint_protocol_async(self): # Arrange conn_string = 'AccountName={};AccountKey={};DefaultEndpointsProtocol=http;EndpointSuffix=core.chinacloudapi.cn;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) for service_type in SERVICES.items(): # Act @@ -249,66 +291,62 @@ async def test_create_service_with_connection_string_endpoint_protocol_async(sel # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key - assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(tables_cosmos_account_name, "table")) + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key + assert service._primary_endpoint.startswith('http://{}.{}.core.chinacloudapi.cn'.format(self.tables_cosmos_account_name, "table")) assert service.scheme == 'http' - - @CosmosPreparer() - async def test_create_service_with_connection_string_emulated_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_emulated_async(self): # Arrange for service_type in SERVICES.items(): - conn_string = 'UseDevelopmentStorage=true;'.format(tables_cosmos_account_name, tables_primary_cosmos_account_key) + conn_string = 'UseDevelopmentStorage=true;'.format(self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - - @CosmosPreparer() - async def test_create_service_with_connection_string_custom_domain_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_connection_string_custom_domain_async(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - - @CosmosPreparer() - async def test_create_service_with_conn_str_custom_domain_trailing_slash_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_custom_domain_trailing_slash_async(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - - @CosmosPreparer() - async def test_create_service_with_conn_str_custom_domain_sec_override_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_custom_domain_sec_override_async(self): # Arrange for service_type in SERVICES.items(): conn_string = 'AccountName={};AccountKey={};TableEndpoint=www.mydomain.com/;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key) # Act service = service_type[0].from_connection_string( @@ -316,32 +354,30 @@ async def test_create_service_with_conn_str_custom_domain_sec_override_async(sel # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - - @CosmosPreparer() - async def test_create_service_with_conn_str_fails_if_sec_without_primary_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_fails_if_sec_without_primary_async(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key, + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key, _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) # Fails if primary excluded with pytest.raises(ValueError): service = service_type[0].from_connection_string(conn_string, table_name="foo") - - @CosmosPreparer() - async def test_create_service_with_conn_str_succeeds_if_sec_with_primary_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_conn_str_succeeds_if_sec_with_primary_async(self): for service_type in SERVICES.items(): # Arrange conn_string = 'AccountName={};AccountKey={};{}=www.mydomain.com;{}=www-sec.mydomain.com;'.format( - tables_cosmos_account_name, - tables_primary_cosmos_account_key, + self.tables_cosmos_account_name, + self.tables_primary_cosmos_account_key, _CONNECTION_ENDPOINTS.get(service_type[1]), _CONNECTION_ENDPOINTS_SECONDARY.get(service_type[1])) @@ -350,26 +386,26 @@ async def test_create_service_with_conn_str_succeeds_if_sec_with_primary_async(s # Assert assert service is not None - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_endpoint.startswith('https://www.mydomain.com') - - @CosmosPreparer() - async def test_create_service_with_custom_account_endpoint_path_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_service_with_custom_account_endpoint_path_async(self): + self.sas_token = self.generate_sas_token() custom_account_url = "http://local-machine:11002/custom/account/path/" + self.sas_token for service_type in SERVICES.items(): conn_string = 'DefaultEndpointsProtocol=http;AccountName={};AccountKey={};TableEndpoint={};'.format( - tables_cosmos_account_name, tables_primary_cosmos_account_key, custom_account_url) + self.tables_cosmos_account_name, self.tables_primary_cosmos_account_key, custom_account_url) # Act service = service_type[0].from_connection_string(conn_string, table_name="foo") # Assert - assert service.account_name == tables_cosmos_account_name - assert service.credential.account_name == tables_cosmos_account_name - assert service.credential.account_key == tables_primary_cosmos_account_key + assert service.account_name == self.tables_cosmos_account_name + assert service.credential.account_name == self.tables_cosmos_account_name + assert service.credential.account_key == self.tables_primary_cosmos_account_key assert service._primary_hostname == 'local-machine:11002/custom/account/path' service = TableServiceClient(account_url=custom_account_url) @@ -393,90 +429,30 @@ async def test_create_service_with_custom_account_endpoint_path_async(self, tabl assert service._primary_hostname == 'local-machine:11002/custom/account/path' assert service.url.startswith('http://local-machine:11002/custom/account/path') - - @CosmosPreparer() - async def test_user_agent_default_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - service = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert response.http_request.headers['User-Agent'] == "azsdk-python-storage-table/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) - - tables = service.list_tables(raw_response_hook=callback) - assert tables is not None - - - @CosmosPreparer() - async def test_user_agent_custom_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - custom_app = "TestApp/v1.0" - service = TableServiceClient( - self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, user_agent=custom_app) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v1.0 azsdk-python-storage-table/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = service.list_tables(raw_response_hook=callback) - assert tables is not None - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert "TestApp/v2.0 TestApp/v1.0 azsdk-python-storage-table/{} Python/{} ({})".format( - VERSION, - platform.python_version(), - platform.platform()) in response.http_request.headers['User-Agent'] - - tables = service.list_tables(raw_response_hook=callback, user_agent="TestApp/v2.0") - assert tables is not None - - - @CosmosPreparer() - async def test_user_agent_append(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # TODO: fix this one - service = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key) - - def callback(response): - assert 'User-Agent' in response.http_request.headers - assert response.http_request.headers['User-Agent'] == "azsdk-python-storage-tables/{} Python/{} ({}) customer_user_agent".format( - VERSION, - platform.python_version(), - platform.platform()) - - custom_headers = {'User-Agent': 'customer_user_agent'} - tables = service.list_tables(raw_response_hook=callback, headers=custom_headers) - - - @CosmosPreparer() - async def test_create_table_client_with_complete_table_url_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_create_table_client_with_complete_table_url_async(self): # Arrange - table_url = self.account_url(tables_cosmos_account_name, "cosmos") + "/foo" - service = TableClient(table_url, table_name='bar', credential=tables_primary_cosmos_account_key) + table_url = self.account_url(self.tables_cosmos_account_name, "cosmos") + "/foo" + service = TableClient(table_url, table_name='bar', credential=self.tables_primary_cosmos_account_key) # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_cosmos_account_name - - @pytest.mark.skip("cosmos differential") + assert service.account_name == self.tables_cosmos_account_name - @CosmosPreparer() - async def test_create_table_client_with_complete_url_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + # @pytest.mark.skip("cosmos differential") + @pytest.mark.asyncio + async def test_create_table_client_with_complete_url_async(self): # Arrange - table_url = "https://{}.table.cosmos.azure.com:443/foo".format(tables_cosmos_account_name) - service = TableClient(table_url, table_name='bar', credential=tables_primary_cosmos_account_key) + table_url = "https://{}.table.cosmos.azure.com:443/foo".format(self.tables_cosmos_account_name) + service = TableClient(table_url, table_name='bar', credential=self.tables_primary_cosmos_account_key) # Assert assert service.scheme == 'https' assert service.table_name == 'bar' - assert service.account_name == tables_cosmos_account_name + assert service.account_name == self.tables_cosmos_account_name - @AzureTestCase.await_prepared_test + @pytest.mark.asyncio async def test_create_table_client_with_invalid_name_async(self): # Arrange table_url = "https://{}.table.cosmos.azure.com:443/foo".format("cosmos_account_name") @@ -484,11 +460,11 @@ async def test_create_table_client_with_invalid_name_async(self): # Assert with pytest.raises(ValueError) as excinfo: - service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="tables_primary_cosmos_account_key") + service = TableClient(account_url=table_url, table_name=invalid_table_name, credential="self.tables_primary_cosmos_account_key") assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str(excinfo) - @AzureTestCase.await_prepared_test + @pytest.mark.asyncio async def test_error_with_malformed_conn_str_async(self): # Arrange @@ -503,26 +479,24 @@ async def test_error_with_malformed_conn_str_async(self): elif conn_str in ("foobar=baz=foo" , "foo=;bar=;", "=", "=;=="): assert str(e.value) == "Connection string missing required connection details." - - @CosmosPreparer() - async def test_closing_pipeline_client_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_closing_pipeline_client_async(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, table_name='table') + self.account_url(self.tables_cosmos_account_name, "cosmos"), credential=self.tables_primary_cosmos_account_key, table_name='table') # Assert async with service: assert hasattr(service, 'close') await service.close() - - @CosmosPreparer() - async def test_closing_pipeline_client_simple_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): + @pytest.mark.asyncio + async def test_closing_pipeline_client_simple_async(self): # Arrange for client, url in SERVICES.items(): # Act service = client( - self.account_url(tables_cosmos_account_name, "cosmos"), credential=tables_primary_cosmos_account_key, table_name='table') + self.account_url(self.tables_cosmos_account_name, "cosmos"), credential=self.tables_primary_cosmos_account_key, table_name='table') await service.close() diff --git a/sdk/tables/azure-data-tables/tests/test_table_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_cosmos.py index f3467cd73e2d..50f929847ca7 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_cosmos.py @@ -38,10 +38,9 @@ AccessPolicy, TableAnalyticsLogging, Metrics, - TableServiceClient + TableServiceClient, + generate_account_sas ) -from azure.data.tables._authentication import SharedKeyCredentialPolicy -from azure.data.tables._table_shared_access_signature import generate_account_sas from _shared.testcase import TableTestCase, SLEEP_DELAY from preparers import CosmosPreparer @@ -175,35 +174,6 @@ def test_query_tables_per_page(self, tables_cosmos_account_name, tables_primary_ if self.is_live: sleep(SLEEP_DELAY) - @CosmosPreparer() - def test_create_table_invalid_name(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Arrange - ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - ts.create_table(table_name=invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - def test_delete_table_invalid_name(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Arrange - ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - ts.create_table(invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - - if self.is_live: - sleep(SLEEP_DELAY) @CosmosPreparer() def test_query_tables(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): @@ -332,20 +302,7 @@ def test_delete_table_with_non_existing_table_fail_not_exist(self, tables_cosmos if self.is_live: sleep(SLEEP_DELAY) - @pytest.mark.skip("Cosmos does not support table access policy") - @CosmosPreparer() - def test_unicode_create_table_unicode_name(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Arrange - url = self.account_url(tables_cosmos_account_name, "cosmos") - ts = TableServiceClient(url, tables_primary_cosmos_account_key) - table_name = u'啊齄丂狛狜' - - # Act - with pytest.raises(HttpResponseError): - ts.create_table(table_name) - if self.is_live: - sleep(SLEEP_DELAY) @pytest.mark.skip("Cosmos does not support table access policy") @CosmosPreparer() @@ -541,3 +498,40 @@ def test_locale(self, tables_cosmos_account_name, tables_primary_cosmos_account_ if self.is_live: sleep(SLEEP_DELAY) + + +class TestTableUnitTest(TableTestCase): + tables_cosmos_account_name = "fake_storage_account" + tables_primary_cosmos_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" + + def test_create_table_invalid_name(self): + # Arrange + ts = TableServiceClient(self.account_url(self.tables_cosmos_account_name, "cosmos"), self.tables_primary_cosmos_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + ts.create_table(table_name=invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + def test_delete_table_invalid_name(self): + # Arrange + ts = TableServiceClient(self.account_url(self.tables_cosmos_account_name, "cosmos"), self.tables_primary_cosmos_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + ts.create_table(invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + def test_unicode_create_table_unicode_name(self): + # Arrange + url = self.account_url(self.tables_cosmos_account_name, "cosmos") + ts = TableServiceClient(url, self.tables_primary_cosmos_account_key) + table_name = u'啊齄丂狛狜' + + # Act + with pytest.raises(ValueError): + ts.create_table(table_name) \ No newline at end of file diff --git a/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py index b5134ff1be49..7aa76da9a29e 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py @@ -120,36 +120,6 @@ async def test_query_tables_per_page(self, tables_cosmos_account_name, tables_pr if self.is_live: sleep(SLEEP_DELAY) - @CosmosPreparer() - async def test_create_table_invalid_name(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Arrange - ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - await ts.create_table(table_name=invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - - if self.is_live: - sleep(SLEEP_DELAY) - - @CosmosPreparer() - async def test_delete_table_invalid_name(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Arrange - ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) - invalid_table_name = "my_table" - - with pytest.raises(ValueError) as excinfo: - await ts.create_table(invalid_table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() async def test_list_tables(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange @@ -280,23 +250,6 @@ async def test_delete_table_with_non_existing_table_fail_not_exist(self, tables_ if self.is_live: sleep(SLEEP_DELAY) - @CosmosPreparer() - async def test_unicode_create_table_unicode_name(self, tables_cosmos_account_name, - tables_primary_cosmos_account_key): - # Arrange - url = self.account_url(tables_cosmos_account_name, "cosmos") - ts = TableServiceClient(url, tables_primary_cosmos_account_key) - table_name = u'啊齄丂狛狜' - - with pytest.raises(ValueError) as excinfo: - await ts.create_table(table_name=table_name) - - assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( - excinfo) - - if self.is_live: - sleep(SLEEP_DELAY) - @pytest.mark.skip("Cosmos does not support table access policy") @CosmosPreparer() async def test_get_table_acl(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): @@ -494,3 +447,45 @@ async def test_locale(self, tables_cosmos_account_name, tables_primary_cosmos_ac if self.is_live: sleep(SLEEP_DELAY) + + +class TestTableUnitTest(AsyncTableTestCase): + tables_cosmos_account_name = "fake_storage_account" + tables_primary_cosmos_account_key = "fakeXMZjnGsZGvd4bVr3Il5SeHA" + + @pytest.mark.asyncio + async def test_unicode_create_table_unicode_name(self): + # Arrange + url = self.account_url(self.tables_cosmos_account_name, "cosmos") + ts = TableServiceClient(url, self.tables_primary_cosmos_account_key) + table_name = u'啊齄丂狛狜' + + with pytest.raises(ValueError) as excinfo: + await ts.create_table(table_name=table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + @pytest.mark.asyncio + async def test_create_table_invalid_name(self): + # Arrange + ts = TableServiceClient(self.account_url(self.tables_cosmos_account_name, "cosmos"), self.tables_primary_cosmos_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + await ts.create_table(table_name=invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) + + @pytest.mark.asyncio + async def test_delete_table_invalid_name(self): + # Arrange + ts = TableServiceClient(self.account_url(self.tables_cosmos_account_name, "cosmos"), self.tables_primary_cosmos_account_key) + invalid_table_name = "my_table" + + with pytest.raises(ValueError) as excinfo: + await ts.create_table(invalid_table_name) + + assert "Table names must be alphanumeric, cannot begin with a number, and must be between 3-63 characters long.""" in str( + excinfo) diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties.py index c5cd1a828f04..e2ad50746381 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties.py @@ -195,13 +195,6 @@ def test_set_cors(self, tables_storage_account_name, tables_primary_storage_acco self._assert_cors_equal(received_props['cors'], cors) # --Test cases for errors --------------------------------------- - @TablesPreparer() - def test_retention_no_days(self, tables_storage_account_name, tables_primary_storage_account_key): - # Assert - pytest.raises(ValueError, - RetentionPolicy, - True, None) - @TablesPreparer() def test_too_many_cors_rules(self, tables_storage_account_name, tables_primary_storage_account_key): # Arrange @@ -225,3 +218,11 @@ def test_retention_too_long(self, tables_storage_account_name, tables_primary_st pytest.raises(HttpResponseError, tsc.set_service_properties, None, None, minute_metrics) + + +class TestTableUnitTest(TableTestCase): + def test_retention_no_days(self): + # Assert + pytest.raises(ValueError, + RetentionPolicy, + True, None) diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py index a25f896a43b4..35093cb8a30f 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py @@ -196,13 +196,6 @@ async def test_set_cors_async(self, tables_storage_account_name, tables_primary_ self._assert_cors_equal(received_props['cors'], cors) # --Test cases for errors --------------------------------------- - @TablesPreparer() - async def test_retention_no_days_async(self, tables_storage_account_name, tables_primary_storage_account_key): - # Assert - pytest.raises(ValueError, - RetentionPolicy, - True, None) - @TablesPreparer() async def test_too_many_cors_rules_async(self, tables_storage_account_name, tables_primary_storage_account_key): # Arrange @@ -225,3 +218,13 @@ async def test_retention_too_long_async(self, tables_storage_account_name, table # Assert with pytest.raises(HttpResponseError): await tsc.set_service_properties(None, None, minute_metrics) + + +class TestTableUnitTest(TableTestCase): + + @pytest.mark.asyncio + async def test_retention_no_days_async(self): + # Assert + pytest.raises(ValueError, + RetentionPolicy, + True, None) \ No newline at end of file diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py index d4076febd771..015723ee7149 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py @@ -97,10 +97,10 @@ def _assert_retention_equal(self, ret1, ret2): # --Test cases per service --------------------------------------- @pytest.mark.skip("Cosmos Tables does not yet support service properties") @CosmosPreparer() - def test_table_service_properties(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_table_service_properties(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange - url = self.account_url(tables_storage_account_name, "cosmos") - tsc = TableServiceClient(url, tables_primary_storage_account_key) + url = self.account_url(tables_cosmos_account_name, "cosmos") + tsc = TableServiceClient(url, tables_primary_cosmos_account_key) # Act resp = tsc.set_service_properties( analytics_logging=TableAnalyticsLogging(), @@ -117,10 +117,10 @@ def test_table_service_properties(self, tables_storage_account_name, tables_prim # --Test cases per feature --------------------------------------- @pytest.mark.skip("Cosmos Tables does not yet support service properties") @CosmosPreparer() - def test_set_logging(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_set_logging(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange - url = self.account_url(tables_storage_account_name, "cosmos") - tsc = TableServiceClient(url, tables_primary_storage_account_key) + url = self.account_url(tables_cosmos_account_name, "cosmos") + tsc = TableServiceClient(url, tables_primary_cosmos_account_key) logging = TableAnalyticsLogging(read=True, write=True, delete=True, retention_policy=RetentionPolicy(enabled=True, days=5)) # Act @@ -134,10 +134,10 @@ def test_set_logging(self, tables_storage_account_name, tables_primary_storage_a @pytest.mark.skip("Cosmos Tables does not yet support service properties") @CosmosPreparer() - def test_set_hour_metrics(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_set_hour_metrics(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange - url = self.account_url(tables_storage_account_name, "cosmos") - tsc = TableServiceClient(url, tables_primary_storage_account_key) + url = self.account_url(tables_cosmos_account_name, "cosmos") + tsc = TableServiceClient(url, tables_primary_cosmos_account_key) hour_metrics = Metrics(enabled=True, include_apis=True, retention_policy=RetentionPolicy(enabled=True, days=5)) # Act @@ -151,10 +151,10 @@ def test_set_hour_metrics(self, tables_storage_account_name, tables_primary_stor @pytest.mark.skip("Cosmos Tables does not yet support service properties") @CosmosPreparer() - def test_set_minute_metrics(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_set_minute_metrics(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange - url = self.account_url(tables_storage_account_name, "cosmos") - tsc = TableServiceClient(url, tables_primary_storage_account_key) + url = self.account_url(tables_cosmos_account_name, "cosmos") + tsc = TableServiceClient(url, tables_primary_cosmos_account_key) minute_metrics = Metrics(enabled=True, include_apis=True, retention_policy=RetentionPolicy(enabled=True, days=5)) @@ -169,10 +169,10 @@ def test_set_minute_metrics(self, tables_storage_account_name, tables_primary_st @pytest.mark.skip("Cosmos Tables does not yet support service properties") @CosmosPreparer() - def test_set_cors(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_set_cors(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange - url = self.account_url(tables_storage_account_name, "cosmos") - tsc = TableServiceClient(url, tables_primary_storage_account_key) + url = self.account_url(tables_cosmos_account_name, "cosmos") + tsc = TableServiceClient(url, tables_primary_cosmos_account_key) cors_rule1 = CorsRule(['www.xyz.com'], ['GET']) allowed_origins = ['www.xyz.com', "www.ab.com", "www.bc.com"] @@ -201,19 +201,9 @@ def test_set_cors(self, tables_storage_account_name, tables_primary_storage_acco # --Test cases for errors --------------------------------------- @pytest.mark.skip("Cosmos Tables does not yet support service properties") @CosmosPreparer() - def test_retention_no_days(self, tables_storage_account_name, tables_primary_storage_account_key): - # Assert - pytest.raises(ValueError, - RetentionPolicy, - True, None) - if self.is_live: - sleep(SLEEP_DELAY) - - @pytest.mark.skip("Cosmos Tables does not yet support service properties") - @CosmosPreparer() - def test_too_many_cors_rules(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_too_many_cors_rules(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange - tsc = TableServiceClient(self.account_url(tables_storage_account_name, "cosmos"), tables_primary_storage_account_key) + tsc = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) cors = [] for i in range(0, 6): cors.append(CorsRule(['www.xyz.com'], ['GET'])) @@ -226,9 +216,9 @@ def test_too_many_cors_rules(self, tables_storage_account_name, tables_primary_s @pytest.mark.skip("Cosmos Tables does not yet support service properties") @CosmosPreparer() - def test_retention_too_long(self, tables_storage_account_name, tables_primary_storage_account_key): + def test_retention_too_long(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange - tsc = TableServiceClient(self.account_url(tables_storage_account_name, "cosmos"), tables_primary_storage_account_key) + tsc = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) minute_metrics = Metrics(enabled=True, include_apis=True, retention_policy=RetentionPolicy(enabled=True, days=366)) @@ -238,3 +228,10 @@ def test_retention_too_long(self, tables_storage_account_name, tables_primary_st None, None, minute_metrics) if self.is_live: sleep(SLEEP_DELAY) + + +class TestTableUnitTest(TableTestCase): + + def test_retention_no_days(self): + # Assert + pytest.raises(ValueError, RetentionPolicy, True, None) diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py index 82face1012d9..550b98c3cd85 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py @@ -198,15 +198,6 @@ async def test_set_cors_async(self, tables_cosmos_account_name, tables_primary_c sleep(SLEEP_DELAY) # --Test cases for errors --------------------------------------- - @CosmosPreparer() - async def test_retention_no_days_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): - # Assert - pytest.raises(ValueError, - RetentionPolicy, - True, None) - if self.is_live: - sleep(SLEEP_DELAY) - @CosmosPreparer() async def test_too_many_cors_rules_async(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): # Arrange @@ -233,3 +224,11 @@ async def test_retention_too_long_async(self, tables_cosmos_account_name, tables await tsc.set_service_properties(None, None, minute_metrics) if self.is_live: sleep(SLEEP_DELAY) + + +class TestTableUnitTest(TableTestCase): + + @pytest.mark.asyncio + async def test_retention_no_days_async(self): + # Assert + pytest.raises(ValueError, RetentionPolicy, True, None) From b5e68d3e9985f60ae0f09fa698e4bbb04494e8f4 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 3 Feb 2021 18:34:30 -0500 Subject: [PATCH 05/13] fixing up imports and using the right base class --- .../tests/_shared/testcase.py | 4 ---- .../azure-data-tables/tests/test_table.py | 5 ++--- .../tests/test_table_async.py | 4 ++-- .../tests/test_table_batch_async.py | 4 ++-- .../tests/test_table_batch_cosmos_async.py | 5 +++-- .../tests/test_table_client.py | 2 +- .../tests/test_table_client_cosmos.py | 2 +- .../tests/test_table_client_cosmos_async.py | 2 +- .../tests/test_table_cosmos_async.py | 9 ++++----- .../tests/test_table_entity_async.py | 20 +++++++++++-------- .../tests/test_table_entity_cosmos_async.py | 5 +++-- .../tests/test_table_service_properties.py | 9 +++++++-- .../test_table_service_properties_async.py | 2 +- .../test_table_service_properties_cosmos.py | 9 +++++++-- ...t_table_service_properties_cosmos_async.py | 9 +++++---- .../tests/test_table_service_stats_async.py | 4 ++-- .../test_table_service_stats_cosmos_async.py | 5 +++-- 17 files changed, 56 insertions(+), 44 deletions(-) diff --git a/sdk/tables/azure-data-tables/tests/_shared/testcase.py b/sdk/tables/azure-data-tables/tests/_shared/testcase.py index 07e860053e5d..953ed0523767 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/testcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/testcase.py @@ -10,7 +10,6 @@ import time from datetime import datetime, timedelta import string -import random import logging import pytest @@ -37,9 +36,6 @@ def get_token(self, *args): class TableTestCase(object): - # def __init__(self, *args, **kwargs): - # super(TableTestCase, self).__init__(*args, **kwargs) - def connection_string(self, account, key): return "DefaultEndpointsProtocol=https;AccountName=" + account + ";AccountKey=" + str(key) + ";EndpointSuffix=core.windows.net" diff --git a/sdk/tables/azure-data-tables/tests/test_table.py b/sdk/tables/azure-data-tables/tests/test_table.py index 876c26e5a2c6..1f6ec3331e82 100644 --- a/sdk/tables/azure-data-tables/tests/test_table.py +++ b/sdk/tables/azure-data-tables/tests/test_table.py @@ -25,10 +25,9 @@ TableAnalyticsLogging, Metrics, TableServiceClient, - TableItem + TableItem, + generate_account_sas ) -from azure.data.tables._authentication import SharedKeyCredentialPolicy -from azure.data.tables._table_shared_access_signature import generate_account_sas from azure.core.pipeline import Pipeline from azure.core.pipeline.policies import ( HeadersPolicy, diff --git a/sdk/tables/azure-data-tables/tests/test_table_async.py b/sdk/tables/azure-data-tables/tests/test_table_async.py index da04970556cb..2e9223b40dcc 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_async.py @@ -13,10 +13,10 @@ TableSasPermissions, ResourceTypes, AccountSasPermissions, - TableItem + TableItem, + generate_account_sas ) from azure.data.tables.aio import TableServiceClient, TableClient -from azure.data.tables._table_shared_access_signature import generate_account_sas from _shared.asynctestcase import AsyncTableTestCase from preparers import TablesPreparer diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_async.py b/sdk/tables/azure-data-tables/tests/test_table_batch_async.py index 65355024a859..85d85112644c 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_async.py @@ -32,14 +32,14 @@ BatchErrorException ) -from _shared.testcase import TableTestCase +from _shared.asynctestcase import AsyncTableTestCase from preparers import TablesPreparer #------------------------------------------------------------------------------ TEST_TABLE_PREFIX = 'table' #------------------------------------------------------------------------------ -class StorageTableBatchTest(AzureTestCase, TableTestCase): +class StorageTableBatchTest(AzureTestCase, AsyncTableTestCase): async def _set_up(self, tables_storage_account_name, tables_primary_storage_account_key): self.ts = TableServiceClient(self.account_url(tables_storage_account_name, "table"), tables_primary_storage_account_key) diff --git a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py index 7e45abc9c66a..839061bd9f01 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_batch_cosmos_async.py @@ -33,14 +33,15 @@ ) from azure.data.tables.aio import TableServiceClient -from _shared.testcase import TableTestCase, SLEEP_DELAY +from _shared.testcase import SLEEP_DELAY +from _shared.asynctestcase import AsyncTableTestCase from preparers import CosmosPreparer #------------------------------------------------------------------------------ TEST_TABLE_PREFIX = 'table' #------------------------------------------------------------------------------ -class StorageTableBatchTest(AzureTestCase, TableTestCase): +class StorageTableBatchTest(AzureTestCase, AsyncTableTestCase): async def _set_up(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): self.ts = TableServiceClient(self.account_url(tables_cosmos_account_name, "cosmos"), tables_primary_cosmos_account_key) diff --git a/sdk/tables/azure-data-tables/tests/test_table_client.py b/sdk/tables/azure-data-tables/tests/test_table_client.py index f4d9dc2ef51b..aaf5a4c00a3b 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client.py @@ -9,7 +9,7 @@ from devtools_testutils import AzureTestCase from azure.data.tables import TableServiceClient, TableClient -from azure.data.tables._version import VERSION +from azure.data.tables import __version__ as VERSION from azure.core.exceptions import HttpResponseError from _shared.testcase import ( diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py index a0c4d057bbc5..3af26364ee7e 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py @@ -11,7 +11,7 @@ from devtools_testutils import AzureTestCase from azure.data.tables import TableServiceClient, TableClient -from azure.data.tables._version import VERSION +from azure.data.tables import __version__ as VERSION from _shared.testcase import ( TableTestCase, diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py index 63d615bf1ad0..4fe6326b433c 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos_async.py @@ -10,7 +10,7 @@ from devtools_testutils import AzureTestCase from azure.data.tables.aio import TableServiceClient, TableClient -from azure.data.tables._version import VERSION +from azure.data.tables import __version__ as VERSION from _shared.asynctestcase import AsyncTableTestCase from _shared.testcase import SLEEP_DELAY diff --git a/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py index 7aa76da9a29e..e0168e2b2ea7 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_cosmos_async.py @@ -9,18 +9,17 @@ from devtools_testutils import AzureTestCase from azure.core.exceptions import ResourceNotFoundError, ResourceExistsError, HttpResponseError -from _shared.asynctestcase import AsyncTableTestCase -from _shared.testcase import SLEEP_DELAY - from azure.data.tables import ( AccessPolicy, TableSasPermissions, ResourceTypes, - AccountSasPermissions + AccountSasPermissions, + generate_account_sas ) from azure.data.tables.aio import TableServiceClient -from azure.data.tables._table_shared_access_signature import generate_account_sas +from _shared.asynctestcase import AsyncTableTestCase +from _shared.testcase import SLEEP_DELAY from preparers import CosmosPreparer TEST_TABLE_PREFIX = 'pytableasync' diff --git a/sdk/tables/azure-data-tables/tests/test_table_entity_async.py b/sdk/tables/azure-data-tables/tests/test_table_entity_async.py index 56250952d724..6bf4f0f21073 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_entity_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_entity_async.py @@ -19,20 +19,24 @@ from azure.core.exceptions import ( HttpResponseError, ResourceNotFoundError, - ResourceExistsError + ResourceExistsError, ) -from azure.data.tables import TableSasPermissions, AccessPolicy, UpdateMode, generate_table_sas -from azure.data.tables._entity import TableEntity, EntityProperty, EdmType +from azure.data.tables import ( + TableSasPermissions, + AccessPolicy, + UpdateMode, + generate_table_sas, + TableEntity, + EntityProperty, + EdmType +) from azure.data.tables.aio import TableServiceClient -from _shared.testcase import TableTestCase +from _shared.asynctestcase import AsyncTableTestCase from preparers import TablesPreparer -# ------------------------------------------------------------------------------ -# TODO: change to `with table_client as client:` to close sessions -# ------------------------------------------------------------------------------ -class StorageTableEntityTest(AzureTestCase, TableTestCase): +class StorageTableEntityTest(AzureTestCase, AsyncTableTestCase): async def _set_up(self, tables_storage_account_name, tables_primary_storage_account_key): account_url = self.account_url(tables_storage_account_name, "table") diff --git a/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py index 0a04b5b15f7c..7b21757e92e3 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_entity_cosmos_async.py @@ -35,13 +35,14 @@ ResourceExistsError, ) -from _shared.testcase import TableTestCase, SLEEP_DELAY +from _shared.asynctestcase import AsyncTableTestCase +from _shared.testcase import SLEEP_DELAY from preparers import CosmosPreparer # ------------------------------------------------------------------------------ # TODO: change to `with table_client as client:` to close sessions # ------------------------------------------------------------------------------ -class StorageTableEntityTest(AzureTestCase, TableTestCase): +class StorageTableEntityTest(AzureTestCase, AsyncTableTestCase): async def _set_up(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): account_url = self.account_url(tables_cosmos_account_name, "cosmos") diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties.py index e2ad50746381..69cf89874978 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties.py @@ -10,8 +10,13 @@ from devtools_testutils import AzureTestCase -from azure.data.tables import TableServiceClient -from azure.data.tables._models import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule +from azure.data.tables import ( + TableServiceClient, + TableAnalyticsLogging, + Metrics, + RetentionPolicy, + CorsRule +) from azure.core.exceptions import HttpResponseError from _shared.testcase import TableTestCase diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py index 35093cb8a30f..6faf66eb1999 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_async.py @@ -12,7 +12,7 @@ from azure.core.exceptions import HttpResponseError -from azure.data.tables._models import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule +from azure.data.tables import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule from azure.data.tables.aio import TableServiceClient from _shared.testcase import TableTestCase diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py index 015723ee7149..139f3c1973a4 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos.py @@ -12,8 +12,13 @@ from azure.core.exceptions import HttpResponseError -from azure.data.tables import TableServiceClient -from azure.data.tables._models import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule +from azure.data.tables import ( + TableServiceClient, + TableAnalyticsLogging, + Metrics, + RetentionPolicy, + CorsRule +) from _shared.testcase import TableTestCase from preparers import CosmosPreparer diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py index 550b98c3cd85..f5efb87e4522 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_properties_cosmos_async.py @@ -10,15 +10,16 @@ from devtools_testutils import AzureTestCase -from azure.data.tables._models import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule +from azure.data.tables import TableAnalyticsLogging, Metrics, RetentionPolicy, CorsRule from azure.data.tables.aio import TableServiceClient from azure.core.exceptions import HttpResponseError -from _shared.testcase import TableTestCase, SLEEP_DELAY +from _shared.testcase import SLEEP_DELAY +from _shared.asynctestcase import AsyncTableTestCase from preparers import CosmosPreparer # ------------------------------------------------------------------------------ -class TableServicePropertiesTest(AzureTestCase, TableTestCase): +class TableServicePropertiesTest(AzureTestCase, AsyncTableTestCase): # --Helpers----------------------------------------------------------------- def _assert_properties_default(self, prop): assert prop is not None @@ -226,7 +227,7 @@ async def test_retention_too_long_async(self, tables_cosmos_account_name, tables sleep(SLEEP_DELAY) -class TestTableUnitTest(TableTestCase): +class TestTableUnitTest(AsyncTableTestCase): @pytest.mark.asyncio async def test_retention_no_days_async(self): diff --git a/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py b/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py index b73dd4645a59..cc2dfd9bdcb5 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py +++ b/sdk/tables/azure-data-tables/tests/test_table_service_stats_async.py @@ -9,7 +9,7 @@ from azure.data.tables.aio import TableServiceClient -from _shared.testcase import TableTestCase +from _shared.asynctestcase import AsyncTableTestCase from preparers import TablesPreparer SERVICE_UNAVAILABLE_RESP_BODY = ' ' # --Test Class ----------------------------------------------------------------- -class TableServiceStatsTest(AzureTestCase, TableTestCase): +class TableServiceStatsTest(AzureTestCase, AsyncTableTestCase): # --Helpers----------------------------------------------------------------- def _assert_stats_default(self, stats): assert stats is not None From 2957e56256397a492f35031279951785bcf110a0 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 3 Feb 2021 18:51:12 -0500 Subject: [PATCH 06/13] removing all is_live code from mixin --- .../tests/_shared/asynctestcase.py | 10 ---------- .../azure-data-tables/tests/_shared/testcase.py | 15 --------------- .../devtools_testutils/azure_testcase.py | 4 ++++ 3 files changed, 4 insertions(+), 25 deletions(-) diff --git a/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py b/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py index 764e859b104f..feabcbe3944b 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py @@ -21,16 +21,6 @@ async def get_token(self, *args): class AsyncTableTestCase(TableTestCase): - @staticmethod - def generate_oauth_token(self): - if self.is_live: - from azure.identity.aio import ClientSecretCredential - return ClientSecretCredential( - self.get_settings_value("TENANT_ID"), - self.get_settings_value("CLIENT_ID"), - self.get_settings_value("CLIENT_SECRET"), - ) - return self.generate_fake_token() def generate_fake_token(self): return AsyncFakeTokenCredential() diff --git a/sdk/tables/azure-data-tables/tests/_shared/testcase.py b/sdk/tables/azure-data-tables/tests/_shared/testcase.py index 953ed0523767..baec5c2ca926 100644 --- a/sdk/tables/azure-data-tables/tests/_shared/testcase.py +++ b/sdk/tables/azure-data-tables/tests/_shared/testcase.py @@ -7,7 +7,6 @@ from __future__ import division from contextlib import contextmanager import os -import time from datetime import datetime, timedelta import string import logging @@ -58,20 +57,6 @@ def account_url(self, account, endpoint_type): if endpoint_type == "cosmos": return "https://{}.table.cosmos.azure.com".format(account) - def sleep(self, seconds): - if self.is_live: - time.sleep(seconds) - - def generate_oauth_token(self): - if self.is_live: - from azure.identity import ClientSecretCredential - return ClientSecretCredential( - self.get_settings_value("TENANT_ID"), - self.get_settings_value("CLIENT_ID"), - self.get_settings_value("CLIENT_SECRET"), - ) - return self.generate_fake_token() - def generate_sas_token(self): fake_key = 'a'*30 + 'b'*30 diff --git a/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py b/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py index 03fbb51132d3..7e3543f53fde 100644 --- a/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py +++ b/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py @@ -343,3 +343,7 @@ def run(test_class_instance, *args, **kwargs): return loop.run_until_complete(test_fn(test_class_instance, **kwargs)) return run + + def sleep(self, seconds): + if self.is_live: + time.sleep(seconds) \ No newline at end of file From 03469d2cb0c73bd6f6c62d7dbbb3bf00aabf0361 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 3 Feb 2021 18:57:00 -0500 Subject: [PATCH 07/13] removing an init dunder --- sdk/tables/azure-data-tables/tests/test_table.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/sdk/tables/azure-data-tables/tests/test_table.py b/sdk/tables/azure-data-tables/tests/test_table.py index 1f6ec3331e82..4ed84978fa91 100644 --- a/sdk/tables/azure-data-tables/tests/test_table.py +++ b/sdk/tables/azure-data-tables/tests/test_table.py @@ -50,9 +50,6 @@ class StorageTableTest(AzureTestCase, TableTestCase): - def __init__(self, *args, **kwargs): - super(StorageTableTest, self).__init__(*args, **kwargs) - # --Helpers----------------------------------------------------------------- def _get_table_reference(self, prefix=TEST_TABLE_PREFIX): table_name = self.get_resource_name(prefix) From eb74ea47bb6099ce033a6da6e96f448a217d80d1 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 4 Feb 2021 08:24:58 -0500 Subject: [PATCH 08/13] forgot an import in azure_testcase --- tools/azure-sdk-tools/devtools_testutils/azure_testcase.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py b/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py index 7e3543f53fde..4b3c7b5f77b8 100644 --- a/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py +++ b/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py @@ -8,6 +8,7 @@ import logging import os.path import sys +import time import zlib try: From 7a83e8cba2e70347fe6fcc61402d2171a836ee3e Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 4 Feb 2021 11:38:24 -0500 Subject: [PATCH 09/13] added conditional to test that is flaky on python2.7 --- sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py index 3af26364ee7e..3ee62a23136d 100644 --- a/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py +++ b/sdk/tables/azure-data-tables/tests/test_table_client_cosmos.py @@ -49,6 +49,7 @@ def callback(response): if self.is_live: sleep(SLEEP_DELAY) + @pytest.mark.skipif(sys.version_info < (3, 0), reason="requires Python3") @CosmosPreparer() def test_user_agent_custom(self, tables_cosmos_account_name, tables_primary_cosmos_account_key): custom_app = "TestApp/v1.0" From 88e5e7d2ee45fe7d36a8916b272b8bc393c43c9c Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 4 Feb 2021 16:20:38 -0500 Subject: [PATCH 10/13] adding mixin section to the tests advanced --- doc/dev/tests-advanced.md | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/doc/dev/tests-advanced.md b/doc/dev/tests-advanced.md index b0607de4a3ba..d6cdaf7a719e 100644 --- a/doc/dev/tests-advanced.md +++ b/doc/dev/tests-advanced.md @@ -1,10 +1,79 @@ # Setup Python Development Environment - Advanced In this document we will provide additional information about the test environments: +- [Test Mixin Classes](#test-mixin-classes) - [Resource Preparers](#preparers) - [Examples with Preparers](#examples-with-preparers) - [mgmt_settings_real.py](#mgmt_settings_real-file) +## Test Mixin Classes +Many of our test suites use a mixin class to reduce re-writing code in multiple test files. For example, in the Tables test suite there is a `_shared` directory containing two of these mixin classes, a [sync one](https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/tables/azure-data-tables/tests/_shared/testcase.py) and an [async version](https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py). These classes will often have ways to create connection strings from an account name and key, formulate the account url, configure logging, or validate service responses. In order for these mixin classes to be used by both the functional and unit tests they should inherit from `object`. For example: + +```python + +class TablesTestMixin(object): + def connection_string(self, account, key): + return "DefaultEndpointsProtocol=https;AccountName=" + account + ";AccountKey=" + str(key) + ";EndpointSuffix=core.windows.net" + + def account_url(self, account, endpoint_type): + """Return an url of storage account. + :param str storage_account: Storage account name + :param str storage_type: The Storage type part of the URL. Should be "table", or "cosmos", etc. + """ + try: + if endpoint_type == "table": + return account.primary_endpoints.table.rstrip("/") + if endpoint_type == "cosmos": + return "https://{}.table.cosmos.azure.com".format(account.name) + else: + raise ValueError("Unknown storage type {}".format(storage_type)) + except AttributeError: # Didn't find "primary_endpoints" + if endpoint_type == "table": + return 'https://{}.{}.core.windows.net'.format(account, endpoint_type) + if endpoint_type == "cosmos": + return "https://{}.table.cosmos.azure.com".format(account) + + def enable_logging(self): + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter(LOGGING_FORMAT)) + self.logger.handlers = [handler] + self.logger.setLevel(logging.INFO) + self.logger.propagate = True + self.logger.disabled = False +``` + +In action this class can be used in functional tests: + +```python +class TestTablesFunctional(AzureTestCase, TablesTestMixin): + ... + def test_with_mixin(self, account, key): + conn_str = self.connection_string(account, key) + client = TableClient.from_connection_string(conn_str) + client.create_table('first') + client.create_table('second') + tables = 0 + for table in client.list_tables(): + tables += 1 + + assert tables == 2 +``` + +Or can be used in a unit test: +```python +class TestTablesUnit(TablesTestMixin): + ... + def test_valid_url(self): + account = "fake_tables_account" + credential = "fake_tables_account_key_0123456789" + + url = self.account_url(account, "tables") + client = TableClient(account_url=url, credential=credential) + + assert client is not None + assert client.account_url == "https://{}.tables.core.windows.net/".format(account) +``` + ## Preparers The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package are the preparers that will be commonly used throughout the repository to test various resources. A preparer is a way to programmatically create fresh resources to run our tests against and then deleting them after running a test suite. These help guarantee standardized behavior by starting each test group from a fresh resource and account. From 2e750a3eed303c776b548cc1f146b2181bebcb3c Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 4 Feb 2021 16:25:43 -0500 Subject: [PATCH 11/13] adding link to azuretestcase --- doc/dev/tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dev/tests.md b/doc/dev/tests.md index 8448f976ce27..2b1006211925 100644 --- a/doc/dev/tests.md +++ b/doc/dev/tests.md @@ -123,7 +123,7 @@ A quick description of the five commands above: * samples: runs all of the samples in the `samples` directory and verifies they are working correctly ## `devtools_testutils` Package -The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package is the `AzureTestCase` object which every test case object should inherit from. This management object takes care of creating and scrubbing recordings to make sure secrets are not added to the recordings files (and subsequently to the git history) and authenticating clients for test methods. +The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package is the [`AzureTestCase`](https://github.com/Azure/azure-sdk-for-python/blob/master/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py#L98-L345) object which every test case object should inherit from. This management object takes care of creating and scrubbing recordings to make sure secrets are not added to the recordings files (and subsequently to the git history) and authenticating clients for test methods. ## Writing New Tests SDK tests are based on the `scenario_tests` subpackage located in [`azure-sdk-for-python/tools/azure-devtools/src/azure_devtools`](https://pypi.org/project/azure-devtools/). `scenario_tests` is a general, mostly abstracted framework which provides several useful features for writing SDK tests, ie: From bb59c4cb7622b389ba59220288f6f1ad111c71ad Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 4 Feb 2021 16:26:44 -0500 Subject: [PATCH 12/13] adding link to azuretestcase --- doc/dev/tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dev/tests.md b/doc/dev/tests.md index 2b1006211925..c15f9d6fb833 100644 --- a/doc/dev/tests.md +++ b/doc/dev/tests.md @@ -123,7 +123,7 @@ A quick description of the five commands above: * samples: runs all of the samples in the `samples` directory and verifies they are working correctly ## `devtools_testutils` Package -The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package is the [`AzureTestCase`](https://github.com/Azure/azure-sdk-for-python/blob/master/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py#L98-L345) object which every test case object should inherit from. This management object takes care of creating and scrubbing recordings to make sure secrets are not added to the recordings files (and subsequently to the git history) and authenticating clients for test methods. +The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package is the [`AzureTestCase`](https://github.com/Azure/azure-sdk-for-python/blob/master/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py#L98) object which every test case object should inherit from. This management object takes care of creating and scrubbing recordings to make sure secrets are not added to the recordings files (and subsequently to the git history) and authenticating clients for test methods. ## Writing New Tests SDK tests are based on the `scenario_tests` subpackage located in [`azure-sdk-for-python/tools/azure-devtools/src/azure_devtools`](https://pypi.org/project/azure-devtools/). `scenario_tests` is a general, mostly abstracted framework which provides several useful features for writing SDK tests, ie: From be3f57dfb4108939ee1af1b9f7e4c4a4f64e11bc Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 4 Feb 2021 16:29:56 -0500 Subject: [PATCH 13/13] undoing changes sent to wrong PR --- doc/dev/tests-advanced.md | 69 --------------------------------------- doc/dev/tests.md | 2 +- 2 files changed, 1 insertion(+), 70 deletions(-) diff --git a/doc/dev/tests-advanced.md b/doc/dev/tests-advanced.md index d6cdaf7a719e..b0607de4a3ba 100644 --- a/doc/dev/tests-advanced.md +++ b/doc/dev/tests-advanced.md @@ -1,79 +1,10 @@ # Setup Python Development Environment - Advanced In this document we will provide additional information about the test environments: -- [Test Mixin Classes](#test-mixin-classes) - [Resource Preparers](#preparers) - [Examples with Preparers](#examples-with-preparers) - [mgmt_settings_real.py](#mgmt_settings_real-file) -## Test Mixin Classes -Many of our test suites use a mixin class to reduce re-writing code in multiple test files. For example, in the Tables test suite there is a `_shared` directory containing two of these mixin classes, a [sync one](https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/tables/azure-data-tables/tests/_shared/testcase.py) and an [async version](https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/tables/azure-data-tables/tests/_shared/asynctestcase.py). These classes will often have ways to create connection strings from an account name and key, formulate the account url, configure logging, or validate service responses. In order for these mixin classes to be used by both the functional and unit tests they should inherit from `object`. For example: - -```python - -class TablesTestMixin(object): - def connection_string(self, account, key): - return "DefaultEndpointsProtocol=https;AccountName=" + account + ";AccountKey=" + str(key) + ";EndpointSuffix=core.windows.net" - - def account_url(self, account, endpoint_type): - """Return an url of storage account. - :param str storage_account: Storage account name - :param str storage_type: The Storage type part of the URL. Should be "table", or "cosmos", etc. - """ - try: - if endpoint_type == "table": - return account.primary_endpoints.table.rstrip("/") - if endpoint_type == "cosmos": - return "https://{}.table.cosmos.azure.com".format(account.name) - else: - raise ValueError("Unknown storage type {}".format(storage_type)) - except AttributeError: # Didn't find "primary_endpoints" - if endpoint_type == "table": - return 'https://{}.{}.core.windows.net'.format(account, endpoint_type) - if endpoint_type == "cosmos": - return "https://{}.table.cosmos.azure.com".format(account) - - def enable_logging(self): - handler = logging.StreamHandler() - handler.setFormatter(logging.Formatter(LOGGING_FORMAT)) - self.logger.handlers = [handler] - self.logger.setLevel(logging.INFO) - self.logger.propagate = True - self.logger.disabled = False -``` - -In action this class can be used in functional tests: - -```python -class TestTablesFunctional(AzureTestCase, TablesTestMixin): - ... - def test_with_mixin(self, account, key): - conn_str = self.connection_string(account, key) - client = TableClient.from_connection_string(conn_str) - client.create_table('first') - client.create_table('second') - tables = 0 - for table in client.list_tables(): - tables += 1 - - assert tables == 2 -``` - -Or can be used in a unit test: -```python -class TestTablesUnit(TablesTestMixin): - ... - def test_valid_url(self): - account = "fake_tables_account" - credential = "fake_tables_account_key_0123456789" - - url = self.account_url(account, "tables") - client = TableClient(account_url=url, credential=credential) - - assert client is not None - assert client.account_url == "https://{}.tables.core.windows.net/".format(account) -``` - ## Preparers The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package are the preparers that will be commonly used throughout the repository to test various resources. A preparer is a way to programmatically create fresh resources to run our tests against and then deleting them after running a test suite. These help guarantee standardized behavior by starting each test group from a fresh resource and account. diff --git a/doc/dev/tests.md b/doc/dev/tests.md index c15f9d6fb833..8448f976ce27 100644 --- a/doc/dev/tests.md +++ b/doc/dev/tests.md @@ -123,7 +123,7 @@ A quick description of the five commands above: * samples: runs all of the samples in the `samples` directory and verifies they are working correctly ## `devtools_testutils` Package -The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package is the [`AzureTestCase`](https://github.com/Azure/azure-sdk-for-python/blob/master/tools/azure-sdk-tools/devtools_testutils/azure_testcase.py#L98) object which every test case object should inherit from. This management object takes care of creating and scrubbing recordings to make sure secrets are not added to the recordings files (and subsequently to the git history) and authenticating clients for test methods. +The Azure SDK team has created some in house tools to help with easier testing. These additional tools are located in the `devtools_testutils` package that was installed with your `dev_requirements.txt`. In this package is the `AzureTestCase` object which every test case object should inherit from. This management object takes care of creating and scrubbing recordings to make sure secrets are not added to the recordings files (and subsequently to the git history) and authenticating clients for test methods. ## Writing New Tests SDK tests are based on the `scenario_tests` subpackage located in [`azure-sdk-for-python/tools/azure-devtools/src/azure_devtools`](https://pypi.org/project/azure-devtools/). `scenario_tests` is a general, mostly abstracted framework which provides several useful features for writing SDK tests, ie: