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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

## Version XX.XX.XX:

### All:
- Fixed a bug where deserialization of service stats throws a TypeError when the service is unavailable.

### Blob:
- create_from_* and and append_blob_from_* methods will return response_properties which contains the etag and last modified time.

Expand Down
3 changes: 2 additions & 1 deletion azure/storage/_deserialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ def _convert_xml_to_service_stats(response):

geo_replication = GeoReplication()
geo_replication.status = geo_replication_element.find('Status').text
geo_replication.last_sync_time = parser.parse(geo_replication_element.find('LastSyncTime').text)
last_sync_time = geo_replication_element.find('LastSyncTime').text
geo_replication.last_sync_time = parser.parse(last_sync_time) if last_sync_time else None

service_stats = ServiceStats()
service_stats.geo_replication = geo_replication
Expand Down
70 changes: 63 additions & 7 deletions tests/test_service_stats.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#-------------------------------------------------------------------------
# -------------------------------------------------------------------------
# Copyright (c) Microsoft. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -11,7 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
# --------------------------------------------------------------------------
import unittest

from azure.storage.blob import BlockBlobService
Expand All @@ -21,20 +21,37 @@
StorageTestCase,
record,
)
from azure.storage.retry import (
LinearRetry
)

#------------------------------------------------------------------------------
SERVICE_UNAVAILABLE_RESP_BODY = '<?xml version="1.0" encoding="utf-8"?><StorageServiceStats><GeoReplication><Status' \
'>unavailable</Status><LastSyncTime></LastSyncTime></GeoReplication' \
'></StorageServiceStats> '

class ServiceStatsTest(StorageTestCase):

#--Helpers-----------------------------------------------------------------
# --Test Class -----------------------------------------------------------------
class ServiceStatsTest(StorageTestCase):
# --Helpers-----------------------------------------------------------------
def _assert_stats_default(self, stats):
self.assertIsNotNone(stats)
self.assertIsNotNone(stats.geo_replication)

self.assertEqual(stats.geo_replication.status, 'live')
self.assertIsNotNone(stats.geo_replication.last_sync_time)

#--Test cases per service ---------------------------------------
def _assert_stats_unavailable(self, stats):
self.assertIsNotNone(stats)
self.assertIsNotNone(stats.geo_replication)

self.assertEqual(stats.geo_replication.status, 'unavailable')
self.assertIsNone(stats.geo_replication.last_sync_time)

@staticmethod
def override_response_body_with_unavailable_status(response):
response.body = SERVICE_UNAVAILABLE_RESP_BODY

# --Test cases per service ---------------------------------------

@record
def test_blob_service_stats(self):
Expand All @@ -47,6 +64,19 @@ def test_blob_service_stats(self):
# Assert
self._assert_stats_default(stats)

@record
def test_blob_service_stats_when_unavailable(self):
# Arrange
bs = self._create_storage_service(BlockBlobService, self.settings)
bs.response_callback = self.override_response_body_with_unavailable_status
bs.retry = LinearRetry(backoff=1).retry

# Act
stats = bs.get_blob_service_stats()

# Assert
self._assert_stats_unavailable(stats)

@record
def test_queue_service_stats(self):
# Arrange
Expand All @@ -58,6 +88,19 @@ def test_queue_service_stats(self):
# Assert
self._assert_stats_default(stats)

@record
def test_queue_service_stats_when_unavailable(self):
# Arrange
qs = self._create_storage_service(QueueService, self.settings)
qs.response_callback = self.override_response_body_with_unavailable_status
qs.retry = LinearRetry(backoff=1).retry

# Act
stats = qs.get_queue_service_stats()

# Assert
self._assert_stats_unavailable(stats)

@record
def test_table_service_stats(self):
# Arrange
Expand All @@ -69,6 +112,19 @@ def test_table_service_stats(self):
# Assert
self._assert_stats_default(stats)

#------------------------------------------------------------------------------
@record
def test_table_service_stats_when_unavailable(self):
# Arrange
ts = self._create_storage_service(TableService, self.settings)
ts.response_callback = self.override_response_body_with_unavailable_status
ts.retry = LinearRetry(backoff=1).retry

# Act
stats = ts.get_table_service_stats()

# Assert
self._assert_stats_unavailable(stats)

# ------------------------------------------------------------------------------
if __name__ == '__main__':
unittest.main()