Fix py34 failure for glance client

Fix somes tests failures for py34, most of them are related
to items order of dict.

Closes-Bug: 1382582

Change-Id: I954b884f03931e4f0ecb654fb38edd0c46a3c379
This commit is contained in:
Fei Long Wang 2014-11-11 15:29:37 +13:00
parent cfe0623520
commit ef0abdc885
9 changed files with 87 additions and 43 deletions

View File

@ -16,6 +16,7 @@
import copy
import json
import six
import six.moves.urllib.parse as urlparse
import testtools
from glanceclient.v2.schemas import Schema
@ -28,11 +29,13 @@ class FakeAPI(object):
def _request(self, method, url, headers=None, data=None,
content_length=None):
call = (method, url, headers or {}, data)
call = build_call_record(method, sort_url_by_query_keys(url),
headers or {}, data)
if content_length is not None:
call = tuple(list(call) + [content_length])
self.calls.append(call)
fixture = self.fixtures[url][method]
fixture = self.fixtures[sort_url_by_query_keys(url)][method]
data = fixture[1]
if isinstance(fixture[1], six.string_types):
@ -165,3 +168,41 @@ class FakeNoTTYStdout(FakeTTYStdout):
def isatty(self):
return False
def sort_url_by_query_keys(url):
"""A helper function which sorts the keys of the query string of a url.
For example, an input of '/v2/tasks?sort_key=id&sort_dir=asc&limit=10'
returns '/v2/tasks?limit=10&sort_dir=asc&sort_key=id'. This is to
prevent non-deterministic ordering of the query string causing
problems with unit tests.
:param url: url which will be ordered by query keys
:returns url: url with ordered query keys
"""
parsed = urlparse.urlparse(url)
queries = urlparse.parse_qsl(parsed.query, True)
sorted_query = sorted(queries, key=lambda x: x[0])
encoded_sorted_query = urlparse.urlencode(sorted_query, True)
url_parts = (parsed.scheme, parsed.netloc, parsed.path,
parsed.params, encoded_sorted_query,
parsed.fragment)
return urlparse.urlunparse(url_parts)
def build_call_record(method, url, headers, data):
"""Key the request body be ordered if it's a dict type.
"""
if isinstance(data, dict):
data = sorted(data.items())
if isinstance(data, six.string_types):
# NOTE(flwang): For image update, the data will be a 'list' which
# contains operation dict, such as: [{"op": "remove", "path": "/a"}]
try:
data = json.loads(data)
except ValueError:
return (method, url, headers or {}, data)
data = [sorted(d.items()) for d in data]
return (method, url, headers or {}, data)

View File

@ -92,7 +92,8 @@ class ImageMemberManagerTest(testtools.TestCase):
def test_create(self):
self.mgr.create(self.image, '1', can_share=True)
expect_body = {'member': {'can_share': True}}
expect = [('PUT', '/v1/images/1/members/1', {}, expect_body)]
expect = [('PUT', '/v1/images/1/members/1', {},
sorted(expect_body.items()))]
self.assertEqual(expect, self.api.calls)
def test_replace(self):
@ -101,7 +102,8 @@ class ImageMemberManagerTest(testtools.TestCase):
{'member_id': '3'},
]
self.mgr.replace(self.image, body)
expect = [('PUT', '/v1/images/1/members', {}, {'memberships': body})]
expect = [('PUT', '/v1/images/1/members', {},
sorted({'memberships': body}.items()))]
self.assertEqual(expect, self.api.calls)
def test_replace_objects(self):
@ -118,5 +120,6 @@ class ImageMemberManagerTest(testtools.TestCase):
{'member_id': '3', 'can_share': True},
],
}
expect = [('PUT', '/v1/images/1/members', {}, expect_body)]
expect = [('PUT', '/v1/images/1/members', {},
sorted(expect_body.items()))]
self.assertEqual(expect, self.api.calls)

View File

@ -158,7 +158,7 @@ fixtures = {
]},
),
},
'/v1/images/detail?marker=a&limit=20': {
'/v1/images/detail?limit=20&marker=a': {
'GET': (
{},
{'images': [
@ -187,7 +187,7 @@ fixtures = {
]},
),
},
'/v1/images/detail?marker=a&limit=1': {
'/v1/images/detail?limit=1&marker=a': {
'GET': (
{},
{'images': [
@ -216,7 +216,7 @@ fixtures = {
]},
),
},
'/v1/images/detail?marker=b&limit=2': {
'/v1/images/detail?limit=2&marker=b': {
'GET': (
{},
{'images': [
@ -245,7 +245,7 @@ fixtures = {
]},
),
},
'/v1/images/detail?property-ping=pong&limit=20':
'/v1/images/detail?limit=20&property-ping=pong':
{
'GET': (
{},
@ -258,7 +258,7 @@ fixtures = {
]},
),
},
'/v1/images/detail?sort_dir=desc&limit=20': {
'/v1/images/detail?limit=20&sort_dir=desc': {
'GET': (
{},
{'images': [
@ -275,7 +275,7 @@ fixtures = {
]},
),
},
'/v1/images/detail?sort_key=name&limit=20': {
'/v1/images/detail?limit=20&sort_key=name': {
'GET': (
{},
{'images': [
@ -441,7 +441,7 @@ class ImageManagerTest(testtools.TestCase):
images = list(self.mgr.list(page_size=2))
expect = [
('GET', '/v1/images/detail?limit=2', {}, None),
('GET', '/v1/images/detail?marker=b&limit=2', {}, None),
('GET', '/v1/images/detail?limit=2&marker=b', {}, None),
]
self.assertEqual(expect, self.api.calls)
self.assertEqual(3, len(images))
@ -459,7 +459,7 @@ class ImageManagerTest(testtools.TestCase):
images = list(self.mgr.list(page_size=1, limit=2))
expect = [
('GET', '/v1/images/detail?limit=1', {}, None),
('GET', '/v1/images/detail?marker=a&limit=1', {}, None),
('GET', '/v1/images/detail?limit=1&marker=a', {}, None),
]
self.assertEqual(2, len(images))
self.assertEqual('a', images[0].id)
@ -468,7 +468,7 @@ class ImageManagerTest(testtools.TestCase):
def test_list_with_marker(self):
list(self.mgr.list(marker='a'))
url = '/v1/images/detail?marker=a&limit=20'
url = '/v1/images/detail?limit=20&marker=a'
expect = [('GET', url, {}, None)]
self.assertEqual(expect, self.api.calls)
@ -480,19 +480,19 @@ class ImageManagerTest(testtools.TestCase):
def test_list_with_property_filters(self):
list(self.mgr.list(filters={'properties': {'ping': 'pong'}}))
url = '/v1/images/detail?property-ping=pong&limit=20'
url = '/v1/images/detail?limit=20&property-ping=pong'
expect = [('GET', url, {}, None)]
self.assertEqual(expect, self.api.calls)
def test_list_with_sort_dir(self):
list(self.mgr.list(sort_dir='desc'))
url = '/v1/images/detail?sort_dir=desc&limit=20'
url = '/v1/images/detail?limit=20&sort_dir=desc'
expect = [('GET', url, {}, None)]
self.assertEqual(expect, self.api.calls)
def test_list_with_sort_key(self):
list(self.mgr.list(sort_key='name'))
url = '/v1/images/detail?sort_key=name&limit=20'
url = '/v1/images/detail?limit=20&sort_key=name'
expect = [('GET', url, {}, None)]
self.assertEqual(expect, self.api.calls)

View File

@ -14,7 +14,6 @@
# under the License.
import errno
import json
import six
import testtools
@ -226,7 +225,7 @@ data_fixtures = {
{'images': []},
),
},
'/v2/images?owner=%s&limit=%d' % (_OWNER_ID, images.DEFAULT_PAGE_SIZE): {
'/v2/images?limit=%d&owner=%s' % (images.DEFAULT_PAGE_SIZE, _OWNER_ID): {
'GET': (
{},
{'images': [
@ -236,14 +235,14 @@ data_fixtures = {
]},
),
},
'/v2/images?owner=%s&limit=%d' % (_BOGUS_ID, images.DEFAULT_PAGE_SIZE): {
'/v2/images?limit=%d&owner=%s' % (images.DEFAULT_PAGE_SIZE, _BOGUS_ID): {
'GET': (
{},
{'images': []},
),
},
'/v2/images?owner=%s&limit=%d&member_status=pending&visibility=shared'
% (_BOGUS_ID, images.DEFAULT_PAGE_SIZE): {
'/v2/images?limit=%d&member_status=pending&owner=%s&visibility=shared'
% (images.DEFAULT_PAGE_SIZE, _BOGUS_ID): {
'GET': (
{},
{'images': [
@ -551,7 +550,7 @@ class TestController(testtools.TestCase):
'image_size': 3}
expect = [('PUT', '/v2/images/%s/file' % image_id,
{'Content-Type': 'application/octet-stream'},
body)]
sorted(body.items()))]
self.assertEqual(expect, self.api.calls)
def test_data_without_checksum(self):
@ -596,7 +595,8 @@ class TestController(testtools.TestCase):
expect_hdrs = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
}
expect_body = '[{"path": "/name", "value": "pong", "op": "replace"}]'
expect_body = [[('op', 'replace'), ('path', '/name'),
('value', 'pong')]]
expect = [
('GET', '/v2/images/%s' % image_id, {}, None),
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
@ -615,7 +615,7 @@ class TestController(testtools.TestCase):
expect_hdrs = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
}
expect_body = '[{"path": "/finn", "value": "human", "op": "add"}]'
expect_body = [[('op', 'add'), ('path', '/finn'), ('value', 'human')]]
expect = [
('GET', '/v2/images/%s' % image_id, {}, None),
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
@ -634,7 +634,7 @@ class TestController(testtools.TestCase):
expect_hdrs = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
}
expect_body = '[{"path": "/barney", "op": "remove"}]'
expect_body = [[('op', 'remove'), ('path', '/barney')]]
expect = [
('GET', '/v2/images/%s' % image_id, {}, None),
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
@ -655,8 +655,8 @@ class TestController(testtools.TestCase):
expect_hdrs = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
}
expect_body = ('[{"path": "/barney", "value": "miller", '
'"op": "replace"}]')
expect_body = ([[('op', 'replace'), ('path', '/barney'),
('value', 'miller')]])
expect = [
('GET', '/v2/images/%s' % image_id, {}, None),
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
@ -677,7 +677,7 @@ class TestController(testtools.TestCase):
expect_hdrs = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
}
expect_body = '[{"path": "/finn", "value": "human", "op": "add"}]'
expect_body = [[('op', 'add'), ('path', '/finn'), ('value', 'human')]]
expect = [
('GET', '/v2/images/%s' % image_id, {}, None),
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
@ -702,7 +702,7 @@ class TestController(testtools.TestCase):
expect_hdrs = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
}
expect_body = '[{"path": "/color", "value": "red", "op": "add"}]'
expect_body = [[('op', 'add'), ('path', '/color'), ('value', 'red')]]
expect = [
('GET', '/v2/images/%s' % image_id, {}, None),
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
@ -718,7 +718,8 @@ class TestController(testtools.TestCase):
expect_hdrs = {
'Content-Type': 'application/openstack-images-v2.1-json-patch',
}
expect_body = '[{"path": "/color", "value": "blue", "op": "replace"}]'
expect_body = [[('op', 'replace'), ('path', '/color'),
('value', 'blue')]]
expect = [
('GET', '/v2/images/%s' % image_id, {}, None),
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
@ -755,10 +756,11 @@ class TestController(testtools.TestCase):
def _patch_req(self, image_id, patch_body):
c_type = 'application/openstack-images-v2.1-json-patch'
data = [sorted(d.items()) for d in patch_body]
return ('PATCH',
'/v2/images/%s' % image_id,
{'Content-Type': c_type},
json.dumps(patch_body))
data)
def test_add_location(self):
image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8'

View File

@ -85,7 +85,7 @@ data_fixtures = {
}
)
},
"/v2/metadefs/namespaces?marker=%s&limit=1" % NAMESPACE7: {
"/v2/metadefs/namespaces?limit=1&marker=%s" % NAMESPACE7: {
"GET": (
{},
{

View File

@ -273,8 +273,8 @@ class TestObjectController(testtools.TestCase):
def test_get_object(self):
obj = self.controller.get(NAMESPACE1, OBJECT1)
self.assertEqual(OBJECT1, obj.name)
self.assertEqual([PROPERTY1, PROPERTY2],
list(six.iterkeys(obj.properties)))
self.assertEqual(sorted([PROPERTY1, PROPERTY2]),
sorted(list(six.iterkeys(obj.properties))))
def test_create_object(self):
properties = {

View File

@ -245,7 +245,7 @@ class TestPropertyController(testtools.TestCase):
properties = list(self.controller.list(NAMESPACE1))
actual = [prop.name for prop in properties]
self.assertEqual([PROPERTY1, PROPERTY2], actual)
self.assertEqual(sorted([PROPERTY1, PROPERTY2]), sorted(actual))
def test_get_property(self):
prop = self.controller.get(NAMESPACE1, PROPERTY1)

View File

@ -170,7 +170,6 @@ class TestSchemaBasedModel(testtools.TestCase):
patch = original.patch
expected = '[{"path": "/color", "op": "remove"}]'
self.assertTrue(compare_json_patches(patch, expected))
self.assertEqual(expected, patch)
def test_patch_should_add_missing_custom_properties(self):
obj = {

View File

@ -112,7 +112,7 @@ fixtures = {
},
),
},
'/v2/tasks?owner=%s&limit=%d' % (_OWNER_ID, tasks.DEFAULT_PAGE_SIZE): {
'/v2/tasks?limit=%d&owner=%s' % (tasks.DEFAULT_PAGE_SIZE, _OWNER_ID): {
'GET': (
{},
{'tasks': [
@ -122,7 +122,7 @@ fixtures = {
]},
),
},
'/v2/tasks?status=processing&limit=%d' % (tasks.DEFAULT_PAGE_SIZE): {
'/v2/tasks?limit=%d&status=processing' % (tasks.DEFAULT_PAGE_SIZE): {
'GET': (
{},
{'tasks': [
@ -132,7 +132,7 @@ fixtures = {
]},
),
},
'/v2/tasks?type=import&limit=%d' % (tasks.DEFAULT_PAGE_SIZE): {
'/v2/tasks?limit=%d&type=import' % (tasks.DEFAULT_PAGE_SIZE): {
'GET': (
{},
{'tasks': [
@ -149,7 +149,7 @@ fixtures = {
]},
),
},
'/v2/tasks?status=fake&limit=%d' % (tasks.DEFAULT_PAGE_SIZE): {
'/v2/tasks?limit=%d&status=fake' % (tasks.DEFAULT_PAGE_SIZE): {
'GET': (
{},
{'tasks': [
@ -166,8 +166,7 @@ fixtures = {
]},
),
},
'/v2/tasks?owner=%s&limit=%d' % (_FAKE_OWNER_ID,
tasks.DEFAULT_PAGE_SIZE):
'/v2/tasks?limit=%d&owner=%s' % (tasks.DEFAULT_PAGE_SIZE, _FAKE_OWNER_ID):
{
'GET': ({},
{'tasks': []},