Merge "Add response schema validation for volume group types"
diff --git a/tempest/lib/api_schema/response/volume/group_types.py b/tempest/lib/api_schema/response/volume/group_types.py
new file mode 100644
index 0000000..bcfa32e
--- /dev/null
+++ b/tempest/lib/api_schema/response/volume/group_types.py
@@ -0,0 +1,122 @@
+# Copyright 2015 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, 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.
+
+group_specs = {
+    'type': 'object',
+    'patternProperties': {
+        '^.+$': {'type': 'string'}
+    }
+}
+
+common_show_group_type = {
+    'type': 'object',
+    'properties': {
+        'id': {'type': 'string'},
+        'is_public': {'type': 'boolean'},
+        'group_specs': group_specs,
+        'description': {'type': ['string', 'null']},
+        'name': {'type': 'string'},
+    },
+    'additionalProperties': False,
+    'required': ['id', 'is_public', 'description', 'name']
+}
+
+create_group_type = {
+    'status_code': [202],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'group_type': common_show_group_type
+        },
+        'additionalProperties': False,
+        'required': ['group_type']
+    }
+}
+
+delete_group_type = {'status_code': [202]}
+
+list_group_types = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'group_types': {
+                'type': 'array',
+                'items': common_show_group_type
+            }
+        },
+        'additionalProperties': False,
+        'required': ['group_types'],
+    }
+}
+
+show_group_type = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'group_type': common_show_group_type
+        },
+        'additionalProperties': False,
+        'required': ['group_type']
+    }
+}
+
+update_group_type = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'group_type': common_show_group_type
+        },
+        'additionalProperties': False,
+        'required': ['group_type']
+    }
+}
+
+create_or_update_group_type_specs = {
+    'status_code': [202],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'group_specs': group_specs,
+        },
+        'additionalProperties': False,
+        'required': ['group_specs']
+    }
+}
+
+list_group_type_specs = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'group_specs': group_specs,
+        },
+        'additionalProperties': False,
+        'required': ['group_specs']
+    }
+}
+
+show_group_type_specs_item = {
+    'status_code': [200],
+    'response_body': group_specs
+}
+
+update_group_type_specs_item = {
+    'status_code': [200],
+    'response_body': group_specs
+}
+
+delete_group_type_specs_item = {'status_code': [202]}
diff --git a/tempest/lib/services/volume/v3/group_types_client.py b/tempest/lib/services/volume/v3/group_types_client.py
index 99833ce..e0bf5e2 100644
--- a/tempest/lib/services/volume/v3/group_types_client.py
+++ b/tempest/lib/services/volume/v3/group_types_client.py
@@ -16,6 +16,7 @@
 from oslo_serialization import jsonutils as json
 from six.moves.urllib import parse as urllib
 
+from tempest.lib.api_schema.response.volume import group_types as schema
 from tempest.lib.common import rest_client
 from tempest.lib.services.volume import base_client
 
@@ -38,13 +39,13 @@
         post_body = json.dumps({'group_type': kwargs})
         resp, body = self.post('group_types', post_body)
         body = json.loads(body)
-        self.expected_success(202, resp.status)
+        self.validate_response(schema.create_group_type, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def delete_group_type(self, group_type_id):
         """Deletes the specified group_type."""
         resp, body = self.delete("group_types/%s" % group_type_id)
-        self.expected_success(202, resp.status)
+        self.validate_response(schema.delete_group_type, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def list_group_types(self, **params):
@@ -60,7 +61,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.expected_success(200, resp.status)
+        self.validate_response(schema.list_group_types, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def show_default_group_type(self):
@@ -84,7 +85,7 @@
         url = "group_types/%s" % group_type_id
         resp, body = self.get(url)
         body = json.loads(body)
-        self.expected_success(200, resp.status)
+        self.validate_response(schema.show_group_type, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def update_group_type(self, group_type_id, **kwargs):
@@ -96,8 +97,8 @@
         """
         post_body = json.dumps({'group_type': kwargs})
         resp, body = self.put('group_types/%s' % group_type_id, post_body)
-        self.expected_success(200, resp.status)
         body = json.loads(body)
+        self.validate_response(schema.update_group_type, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def create_or_update_group_type_specs(self, group_type_id, group_specs):
@@ -111,7 +112,8 @@
         post_body = json.dumps({'group_specs': group_specs})
         resp, body = self.post(url, post_body)
         body = json.loads(body)
-        self.expected_success(202, resp.status)
+        self.validate_response(
+            schema.create_or_update_group_type_specs, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def list_group_type_specs(self, group_type_id):
@@ -119,7 +121,7 @@
         url = 'group_types/%s/group_specs' % group_type_id
         resp, body = self.get(url)
         body = json.loads(body)
-        self.expected_success(200, resp.status)
+        self.validate_response(schema.list_group_type_specs, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def show_group_type_specs_item(self, group_type_id, spec_id):
@@ -127,7 +129,7 @@
         url = "group_types/%s/group_specs/%s" % (group_type_id, spec_id)
         resp, body = self.get(url)
         body = json.loads(body)
-        self.expected_success(200, resp.status)
+        self.validate_response(schema.show_group_type_specs_item, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def update_group_type_specs_item(self, group_type_id, spec_id, spec):
@@ -141,12 +143,12 @@
         put_body = json.dumps(spec)
         resp, body = self.put(url, put_body)
         body = json.loads(body)
-        self.expected_success(200, resp.status)
+        self.validate_response(schema.update_group_type_specs_item, resp, body)
         return rest_client.ResponseBody(resp, body)
 
     def delete_group_type_specs_item(self, group_type_id, spec_id):
         """Deletes specified item of group specs for a given group type."""
         resp, body = self.delete("group_types/%s/group_specs/%s" % (
             group_type_id, spec_id))
-        self.expected_success(202, resp.status)
+        self.validate_response(schema.delete_group_type_specs_item, resp, body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/tests/lib/services/volume/v3/test_group_types_client.py b/tempest/tests/lib/services/volume/v3/test_group_types_client.py
index 8b853d7..33c7737 100644
--- a/tempest/tests/lib/services/volume/v3/test_group_types_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_group_types_client.py
@@ -23,8 +23,8 @@
     FAKE_CREATE_GROUP_TYPE = {
         "group_type": {
             "id": "6685584b-1eac-4da6-b5c3-555430cf68ff",
-            "name": "grp-type-001",
-            "description": "group type 001",
+            "name": "group-type-001",
+            "description": "Test group type 1",
             "is_public": True,
             "group_specs": {
                 "consistent_group_snapshot_enabled": "<is> False"